Skip to content

Commit 414d72c

Browse files
committed
Fix schema url fragments support
Signed-off-by: Yevhen Vydolob <[email protected]>
1 parent 4f03d4a commit 414d72c

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

src/languageservice/services/yamlSchemaService.ts

+18-10
Original file line numberDiff line numberDiff line change
@@ -109,17 +109,16 @@ export class YAMLSchemaService extends JSONSchemaService {
109109
this.customSchemaProvider = customSchemaProvider;
110110
}
111111

112-
public resolveSchemaContent(
112+
async resolveSchemaContent(
113113
schemaToResolve: UnresolvedSchema,
114114
schemaURL: string,
115115
dependencies: SchemaDependencies
116116
): Promise<ResolvedSchema> {
117117
const resolveErrors: string[] = schemaToResolve.errors.slice(0);
118-
const schema = schemaToResolve.schema;
118+
let schema = schemaToResolve.schema;
119119
const contextService = this.contextService;
120120

121-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
122-
const findSection = (schema: JSONSchema, path: string): any => {
121+
const findSection = (schema: JSONSchema, path: string): JSONSchema => {
123122
if (!path) {
124123
return schema;
125124
}
@@ -176,15 +175,15 @@ export class YAMLSchemaService extends JSONSchemaService {
176175
});
177176
};
178177

179-
const resolveRefs = (
178+
const resolveRefs = async (
180179
node: JSONSchema,
181180
parentSchema: JSONSchema,
182181
parentSchemaURL: string,
183182
parentSchemaDependencies: SchemaDependencies
184183
// eslint-disable-next-line @typescript-eslint/no-explicit-any
185184
): Promise<any> => {
186185
if (!node || typeof node !== 'object') {
187-
return Promise.resolve(null);
186+
return null;
188187
}
189188

190189
const toWalk: JSONSchema[] = [node];
@@ -260,7 +259,17 @@ export class YAMLSchemaService extends JSONSchemaService {
260259
if (parentSchemaURL.indexOf('#') > 0) {
261260
const segments = parentSchemaURL.split('#', 2);
262261
if (segments[0].length > 0 && segments[1].length > 0) {
263-
openPromises.push(resolveExternalLink(node, segments[0], segments[1], parentSchemaURL, parentSchemaDependencies));
262+
const newSchema = {};
263+
await resolveExternalLink(newSchema, segments[0], segments[1], parentSchemaURL, parentSchemaDependencies);
264+
for (const key in schema) {
265+
if (key === 'required') {
266+
continue;
267+
}
268+
if (Object.prototype.hasOwnProperty.call(schema, key) && !Object.prototype.hasOwnProperty.call(newSchema, key)) {
269+
newSchema[key] = schema[key];
270+
}
271+
}
272+
schema = newSchema;
264273
}
265274
}
266275

@@ -275,9 +284,8 @@ export class YAMLSchemaService extends JSONSchemaService {
275284
return Promise.all(openPromises);
276285
};
277286

278-
return resolveRefs(schema, schema, schemaURL, dependencies).then(() => {
279-
return new ResolvedSchema(schema, resolveErrors);
280-
});
287+
await resolveRefs(schema, schema, schemaURL, dependencies);
288+
return new ResolvedSchema(schema, resolveErrors);
281289
}
282290

283291
public getSchemaForResource(resource: string, doc: JSONDocument): Promise<ResolvedSchema> {

test/yamlSchemaService.test.ts

+26
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,31 @@ describe('YAML Schema Service', () => {
6565

6666
expect(schema.schema.type).eqls('array');
6767
});
68+
69+
it('should handle url with fragments when root object is schema', async () => {
70+
const content = `# yaml-language-server: $schema=https://json-schema.org/draft-07/schema#/definitions/schemaArray`;
71+
const yamlDock = parse(content);
72+
73+
requestServiceMock = sandbox.fake.resolves(`{"definitions": {"schemaArray": {
74+
"type": "array",
75+
"minItems": 1,
76+
"items": { "$ref": "#" }
77+
},
78+
"bar": {
79+
"type": "string"
80+
}
81+
}, "properties": {"foo": {"type": "boolean"}}, "required": ["foo"]}`);
82+
83+
const service = new SchemaService.YAMLSchemaService(requestServiceMock);
84+
const schema = await service.getSchemaForResource('', yamlDock.documents[0]);
85+
86+
expect(requestServiceMock).calledTwice;
87+
expect(requestServiceMock).calledWithExactly('https://json-schema.org/draft-07/schema');
88+
expect(requestServiceMock).calledWithExactly('https://json-schema.org/draft-07/schema#/definitions/schemaArray');
89+
90+
expect(schema.schema.type).eqls('array');
91+
expect(schema.schema.required).is.undefined;
92+
expect(schema.schema.definitions.bar.type).eqls('string');
93+
});
6894
});
6995
});

0 commit comments

Comments
 (0)