diff --git a/src/languageservice/services/yamlSchemaService.ts b/src/languageservice/services/yamlSchemaService.ts index 872b512da..04a7aec8d 100644 --- a/src/languageservice/services/yamlSchemaService.ts +++ b/src/languageservice/services/yamlSchemaService.ts @@ -328,12 +328,24 @@ export class YAMLSchemaService extends JSONSchemaService { let schemaFromModeline = getSchemaFromModeline(doc); if (schemaFromModeline !== undefined) { if (!schemaFromModeline.startsWith('file:') && !schemaFromModeline.startsWith('http')) { + // If path contains a fragment and it is left intact, "#" will be + // considered part of the filename and converted to "%23" by + // path.resolve() -> take it out and add back after path.resolve + let appendix = ''; + if (schemaFromModeline.indexOf('#') > 0) { + const segments = schemaFromModeline.split('#', 2); + schemaFromModeline = segments[0]; + appendix = segments[1]; + } if (!path.isAbsolute(schemaFromModeline)) { const resUri = URI.parse(resource); schemaFromModeline = URI.file(path.resolve(path.parse(resUri.fsPath).dir, schemaFromModeline)).toString(); } else { schemaFromModeline = URI.file(schemaFromModeline).toString(); } + if (appendix.length > 0) { + schemaFromModeline += '#' + appendix; + } } this.addSchemaPriority(schemaFromModeline, SchemaPriority.Modeline); schemas.push(schemaFromModeline); diff --git a/test/yamlSchemaService.test.ts b/test/yamlSchemaService.test.ts index f76b03369..8563adc72 100644 --- a/test/yamlSchemaService.test.ts +++ b/test/yamlSchemaService.test.ts @@ -92,6 +92,31 @@ describe('YAML Schema Service', () => { expect(schema.schema.definitions.bar.type).eqls('string'); }); + it('should handle file path with fragments', async () => { + const content = `# yaml-language-server: $schema=schema.json#/definitions/schemaArray\nfoo: bar`; + const yamlDock = parse(content); + + requestServiceMock = sandbox.fake.resolves(`{"definitions": {"schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }}, "properties": {}}`); + + const service = new SchemaService.YAMLSchemaService(requestServiceMock); + const schema = await service.getSchemaForResource('', yamlDock.documents[0]); + + expect(requestServiceMock).calledTwice; + if (process.platform === 'win32') { + expect(requestServiceMock).calledWithExactly('file:///d%3A/schema.json'); + expect(requestServiceMock).calledWithExactly('file:///d%3A/schema.json#/definitions/schemaArray'); + } else { + expect(requestServiceMock).calledWithExactly('file:///schema.json'); + expect(requestServiceMock).calledWithExactly('file:///schema.json#/definitions/schemaArray'); + } + + expect(schema.schema.type).eqls('array'); + }); + it('should handle modeline schema comment in the middle of file', () => { const documentContent = `foo:\n bar\n# yaml-language-server: $schema=https://json-schema.org/draft-07/schema#\naa:bbb\n`; const content = `${documentContent}`;