Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"lodash": "4.17.21",
"prettier": "^3.5.0",
"request-light": "^0.5.7",
"vscode-json-languageservice": "4.1.8",
"vscode-json-languageservice": "4.2.0",
"vscode-languageserver": "^9.0.0",
"vscode-languageserver-textdocument": "^1.0.1",
"vscode-languageserver-types": "^3.16.0",
Expand Down Expand Up @@ -99,4 +99,4 @@
],
"all": true
}
}
}
39 changes: 18 additions & 21 deletions src/languageservice/services/yamlSchemaService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,7 @@ export class YAMLSchemaService extends JSONSchemaService {
return result;
}

async resolveSchemaContent(
schemaToResolve: UnresolvedSchema,
schemaURL: string,
dependencies: SchemaDependencies
): Promise<ResolvedSchema> {
async resolveSchemaContent(schemaToResolve: UnresolvedSchema, schemaHandle: SchemaHandle): Promise<ResolvedSchema> {
const resolveErrors: string[] = schemaToResolve.errors.slice(0);
let schema: JSONSchema = schemaToResolve.schema;
const contextService = this.contextService;
Expand All @@ -180,7 +176,9 @@ export class YAMLSchemaService extends JSONSchemaService {
for (const err of validator.errors as DefinedError[]) {
errs.push(`${err.instancePath} : ${err.message}`);
}
resolveErrors.push(`Schema '${getSchemaTitle(schemaToResolve.schema, schemaURL)}' is not valid:\n${errs.join('\n')}`);
resolveErrors.push(
`Schema '${getSchemaTitle(schemaToResolve.schema, schemaHandle.uri)}' is not valid:\n${errs.join('\n')}`
);
}

const findSection = (schema: JSONSchema, path: string): JSONSchema => {
Expand Down Expand Up @@ -216,17 +214,16 @@ export class YAMLSchemaService extends JSONSchemaService {
node: JSONSchema,
uri: string,
linkPath: string,
parentSchemaURL: string,
parentSchemaDependencies: SchemaDependencies
parentSchemaHandle: SchemaHandle
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promise<any> => {
if (contextService && !/^\w+:\/\/.*/.test(uri)) {
uri = contextService.resolveRelativePath(uri, parentSchemaURL);
uri = contextService.resolveRelativePath(uri, parentSchemaHandle.uri);
}
uri = this.normalizeId(uri);
const referencedHandle = this.getOrAddSchemaHandle(uri);
return referencedHandle.getUnresolvedSchema().then((unresolvedSchema) => {
parentSchemaDependencies[uri] = true;
parentSchemaHandle.dependencies[uri] = true;
if (unresolvedSchema.errors.length) {
const loc = linkPath ? uri + '#' + linkPath : uri;
resolveErrors.push(
Expand All @@ -236,15 +233,14 @@ export class YAMLSchemaService extends JSONSchemaService {
merge(node, unresolvedSchema.schema, uri, linkPath);
node.url = uri;
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return resolveRefs(node, unresolvedSchema.schema, uri, referencedHandle.dependencies);
return resolveRefs(node, unresolvedSchema.schema, referencedHandle);
});
};

const resolveRefs = async (
node: JSONSchema,
parentSchema: JSONSchema,
parentSchemaURL: string,
parentSchemaDependencies: SchemaDependencies
parentSchemaHandle: SchemaHandle
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promise<any> => {
if (!node || typeof node !== 'object') {
Expand Down Expand Up @@ -296,11 +292,11 @@ export class YAMLSchemaService extends JSONSchemaService {
next._$ref = next.$ref;
delete next.$ref;
if (segments[0].length > 0) {
openPromises.push(resolveExternalLink(next, segments[0], segments[1], parentSchemaURL, parentSchemaDependencies));
openPromises.push(resolveExternalLink(next, segments[0], segments[1], parentSchemaHandle));
return;
} else {
if (!seenRefs.has(ref)) {
merge(next, parentSchema, parentSchemaURL, segments[1]); // can set next.$ref again, use seenRefs to avoid circle
merge(next, parentSchema, parentSchemaHandle.uri, segments[1]); // can set next.$ref again, use seenRefs to avoid circle
seenRefs.add(ref);
}
}
Expand All @@ -321,11 +317,11 @@ export class YAMLSchemaService extends JSONSchemaService {
collectArrayEntries(next.anyOf, next.allOf, next.oneOf, <JSONSchema[]>next.items, next.schemaSequence);
};

if (parentSchemaURL.indexOf('#') > 0) {
const segments = parentSchemaURL.split('#', 2);
if (parentSchemaHandle.uri.indexOf('#') > 0) {
const segments = parentSchemaHandle.uri.split('#', 2);
if (segments[0].length > 0 && segments[1].length > 0) {
const newSchema = {};
await resolveExternalLink(newSchema, segments[0], segments[1], parentSchemaURL, parentSchemaDependencies);
await resolveExternalLink(newSchema, segments[0], segments[1], parentSchemaHandle);
for (const key in schema) {
if (key === 'required') {
continue;
Expand All @@ -349,7 +345,7 @@ export class YAMLSchemaService extends JSONSchemaService {
return Promise.all(openPromises);
};

await resolveRefs(schema, schema, schemaURL, dependencies);
await resolveRefs(schema, schema, schemaHandle);
return new ResolvedSchema(schema, resolveErrors);
}

Expand Down Expand Up @@ -512,9 +508,10 @@ export class YAMLSchemaService extends JSONSchemaService {
return priorityMapping.get(highestPrio) || [];
}

private async resolveCustomSchema(schemaUri, doc): ResolvedSchema {
private async resolveCustomSchema(schemaUri: string, doc): ResolvedSchema {
const unresolvedSchema = await this.loadSchema(schemaUri);
const schema = await this.resolveSchemaContent(unresolvedSchema, schemaUri, []);
const schemaHandle = this.getOrAddSchemaHandle(schemaUri);
const schema = await this.resolveSchemaContent(unresolvedSchema, schemaHandle);
if (schema.schema && typeof schema.schema === 'object') {
schema.schema.url = schemaUri;
}
Expand Down
31 changes: 31 additions & 0 deletions test/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,37 @@ describe('JSON Schema', () => {
);
});

it('Resolving $refs 4', function (testDone) {
const service = new SchemaService.YAMLSchemaService(requestServiceMock, workspaceContext);
service.setSchemaContributions({
schemas: {
'https://myschemastore/refs': {
id: 'https://myschemastore/refs',
type: 'object',
properties: {
A: { $id: '#A', type: 'string' },
B: { $ref: '#A' },
},
},
},
});

service
.getResolvedSchema('https://myschemastore/refs')
.then((fs) => {
assert.deepEqual(fs.schema.properties['A'], { $id: '#A', type: 'string' });
assert.deepEqual(fs.schema.properties['B'], { $id: '#A', type: 'string' });
})
.then(
() => {
return testDone();
},
(error) => {
testDone(error);
}
);
});

it('FileSchema', function (testDone) {
const service = new SchemaService.YAMLSchemaService(requestServiceMock, workspaceContext);

Expand Down
22 changes: 16 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3218,16 +3218,16 @@ [email protected]:
core-util-is "1.0.2"
extsprintf "^1.2.0"

vscode-json-languageservice@4.1.8:
version "4.1.8"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.1.8.tgz#397a39238d496e3e08a544a8b93df2cd13347d0c"
integrity sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==
vscode-json-languageservice@4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.2.0.tgz#df0693b69ba2fbf0a6add896087b6f1c9c38f06a"
integrity sha512-XNawv0Vdy/sUK0S+hGf7cq/qsVAbIniGJr89TvZOqMCNJmpgKTy1e8PL1aWW0uy6BfWMG7vxa5lZb3ypuFtuGQ==
dependencies:
jsonc-parser "^3.0.0"
vscode-languageserver-textdocument "^1.0.1"
vscode-languageserver-textdocument "^1.0.3"
vscode-languageserver-types "^3.16.0"
vscode-nls "^5.0.0"
vscode-uri "^3.0.2"
vscode-uri "^3.0.3"

[email protected]:
version "8.2.0"
Expand All @@ -3247,6 +3247,11 @@ vscode-languageserver-textdocument@^1.0.1:
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz#0822a000e7d4dc083312580d7575fe9e3ba2e2bf"
integrity sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==

vscode-languageserver-textdocument@^1.0.3:
version "1.0.12"
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz#457ee04271ab38998a093c68c2342f53f6e4a631"
integrity sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==

[email protected], vscode-languageserver-types@^3.16.0:
version "3.17.5"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a"
Expand All @@ -3269,6 +3274,11 @@ vscode-uri@^3.0.2:
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f"
integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==

vscode-uri@^3.0.3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c"
integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==

which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz"
Expand Down