From b518eece4e883bfbc03d3344042f10205873992c Mon Sep 17 00:00:00 2001 From: Morgan Chang Date: Fri, 31 Jul 2026 14:51:30 -0400 Subject: [PATCH] fix schema priority lookup for normalized file URIs Signed-off-by: Morgan Chang --- .../services/yamlSchemaService.ts | 9 ++++--- test/schema.test.ts | 26 +++++++++++++++++++ test/yamlSchemaService.test.ts | 25 ++++++++++++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/languageservice/services/yamlSchemaService.ts b/src/languageservice/services/yamlSchemaService.ts index 4d92c7d2e..82883dfe0 100644 --- a/src/languageservice/services/yamlSchemaService.ts +++ b/src/languageservice/services/yamlSchemaService.ts @@ -1483,12 +1483,13 @@ export class YAMLSchemaService implements IJSONSchemaService { // Set the priority of a schema in the schema service public addSchemaPriority(uri: string, priority: number): void { - let currSchemaArray = this.schemaPriorityMapping.get(uri); + const id = normalizeId(uri); + const currSchemaArray = this.schemaPriorityMapping.get(id); if (currSchemaArray) { - currSchemaArray = currSchemaArray.add(priority); - this.schemaPriorityMapping.set(uri, currSchemaArray); + currSchemaArray.add(priority); + this.schemaPriorityMapping.set(id, currSchemaArray); } else { - this.schemaPriorityMapping.set(uri, new Set().add(priority)); + this.schemaPriorityMapping.set(id, new Set().add(priority)); } } diff --git a/test/schema.test.ts b/test/schema.test.ts index b9a803ff8..746a9f815 100644 --- a/test/schema.test.ts +++ b/test/schema.test.ts @@ -870,6 +870,32 @@ address: languageSettingsSetup = new ServiceSetup().withCompletion(); }); + for (const { description, uri } of [ + { description: 'encoded Windows drive colon', uri: 'file:///c%3A/Users/user1/schema.json' }, + { description: 'unencoded Windows drive colon', uri: 'file:///c:/Users/user1/schema.json' }, + ]) { + it(`Preserves settings priority for ${description}`, async () => { + languageSettingsSetup + .withSchemaFileMatch({ + fileMatch: ['test.yaml'], + uri: 'https://example.test/schema-store.json', + priority: SchemaPriority.SchemaStore, + schema: schemaStoreSample, + }) + .withSchemaFileMatch({ + fileMatch: ['test.yaml'], + uri, + priority: SchemaPriority.Settings, + schema: schemaSettingsSample, + }); + languageService.configure(languageSettingsSetup.languageSettings); + const document = setupTextDocument(''); + const result = await languageService.doComplete(document, Position.create(0, 0), false); + assert.strictEqual(result.items.length, 1); + assert.strictEqual(result.items[0].label, 'settings'); + }); + } + it('Modeline Schema takes precendence over all other schema APIs', async () => { languageSettingsSetup .withSchemaFileMatch({ diff --git a/test/yamlSchemaService.test.ts b/test/yamlSchemaService.test.ts index b3ffb728e..493ad9fcc 100644 --- a/test/yamlSchemaService.test.ts +++ b/test/yamlSchemaService.test.ts @@ -135,6 +135,31 @@ describe('YAML Schema Service', () => { expect(schema.schema.type).eqls('array'); }); + for (const { description, uri } of [ + { description: 'encoded Windows drive colon', uri: 'file:///c%3A/Users/user1/schema.json' }, + { description: 'unencoded Windows drive colon', uri: 'file:///c:/Users/user1/schema.json' }, + ]) { + it(`should resolve a schema URI with an ${description}`, async () => { + const yamlDock = parse('foo: bar'); + const normalizedUri = 'file:///c:/Users/user1/schema.json'; + requestServiceMock = sandbox.fake.resolves( + JSON.stringify({ + type: 'object', + properties: { + foo: { type: 'string' }, + }, + }) + ); + + const service = new SchemaService.YAMLSchemaService(requestServiceMock); + service.registerExternalSchema(uri, ['test.yaml']); + const schema = await service.getSchemaForResource('test.yaml', yamlDock.documents[0]); + + expect(requestServiceMock).calledOnceWithExactly(normalizedUri); + expect(schema.schema.properties.foo).to.include({ type: 'string' }); + }); + } + it('should use local sibling schema path before remote $id ref', async () => { const content = `# yaml-language-server: $schema=file:///schemas/primary.json\nmode: stage`; const yamlDock = parse(content);