Skip to content

Commit 1dc5125

Browse files
committed
support specifying schema via $schema key
1 parent 2bae915 commit 1dc5125

File tree

3 files changed

+40
-8
lines changed

3 files changed

+40
-8
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@ yaml.schemas: {
179179

180180
`yaml.schemas` allows you to specify json schemas that you want to validate against the yaml that you write. Kubernetes is an optional field. It does not require a url as the language server will provide that. You just need the keyword kubernetes and a glob pattern.
181181

182+
### Using `$schema` key to specify schema
183+
184+
Like [VSCode](https://code.visualstudio.com/Docs/languages/json#_mapping-in-the-json), specifying schema via `$schema` key at root is supported.
185+
186+
```
187+
$schema: <urlToTheSchema>
188+
```
189+
182190
### Using inlined schema
183191

184192
It is possible to specify a yaml schema using a modeline.

src/languageservice/services/yamlSchemaService.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { URI } from 'vscode-uri';
2121
import * as nls from 'vscode-nls';
2222
import { convertSimple2RegExpPattern } from '../utils/strings';
2323
import { SingleYAMLDocument } from '../parser/yamlParser07';
24+
import { ObjectASTNode, StringASTNode } from '../jsonASTTypes';
2425
import { JSONDocument } from '../parser/jsonParser07';
2526
import * as yaml from 'js-yaml';
2627

@@ -268,10 +269,10 @@ export class YAMLSchemaService extends JSONSchemaService {
268269
const seen: { [schemaId: string]: boolean } = Object.create(null);
269270
const schemas: string[] = [];
270271

271-
const schemaFromModeline = this.getSchemaFromModeline(doc);
272-
if (schemaFromModeline !== undefined) {
273-
schemas.push(schemaFromModeline);
274-
seen[schemaFromModeline] = true;
272+
const schemaFromFileContent = this.getSchemaFromFileContent(doc);
273+
if (schemaFromFileContent !== undefined) {
274+
schemas.push(schemaFromFileContent);
275+
seen[schemaFromFileContent] = true;
275276
}
276277

277278
for (const entry of this.filePatternAssociations) {
@@ -368,8 +369,19 @@ export class YAMLSchemaService extends JSONSchemaService {
368369
* Public for testing purpose, not part of the API.
369370
* @param doc
370371
*/
371-
public getSchemaFromModeline(doc: SingleYAMLDocument | JSONDocument): string {
372+
public getSchemaFromFileContent(doc: SingleYAMLDocument | JSONDocument): string {
373+
let schema = undefined;
372374
if (doc instanceof SingleYAMLDocument) {
375+
const properties = (doc.root as ObjectASTNode).properties;
376+
for (const prop of properties) {
377+
if (prop.keyNode.value == '$schema') {
378+
schema = (prop.valueNode as StringASTNode).value;
379+
}
380+
}
381+
if (schema !== undefined) {
382+
return schema;
383+
}
384+
373385
const yamlLanguageServerModeline = doc.lineComments.find((lineComment) => {
374386
const matchModeline = lineComment.match(/^#\s+yaml-language-server\s*:/g);
375387
return matchModeline !== null && matchModeline.length === 1;
@@ -382,11 +394,11 @@ export class YAMLSchemaService extends JSONSchemaService {
382394
'Several $schema attributes have been found on the yaml-language-server modeline. The first one will be picked.'
383395
);
384396
}
385-
return schemaMatchs[0].substring('$schema='.length);
397+
schema = schemaMatchs[0].substring('$schema='.length);
386398
}
387399
}
388400
}
389-
return undefined;
401+
return schema;
390402
}
391403

392404
private async resolveCustomSchema(schemaUri, doc): ResolvedSchema {

test/schema.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ suite('JSON Schema', () => {
538538
assert.equal(hello_world_schema, null);
539539
});
540540

541-
describe('Test getSchemaFromModeline', function () {
541+
describe('Test getSchemaFromFileContent', function () {
542542
test('simple case', async () => {
543543
checkReturnSchemaUrl('# yaml-language-server: $schema=expectedUrl', 'expectedUrl');
544544
});
@@ -586,6 +586,18 @@ suite('JSON Schema', () => {
586586
checkReturnSchemaUrl('# yaml-language-server: $notschema=url1', undefined);
587587
});
588588

589+
test('schema key', async () => {
590+
checkReturnSchemaUrl('$schema: expectedUrl', 'expectedUrl');
591+
});
592+
593+
test('schema key and simple case', async () => {
594+
checkReturnSchemaUrl('# yaml-language-server: $schema=expectedUrl1\n$schema: expectedUrl2', 'expectedUrl2');
595+
});
596+
597+
test('schema key with wrong type', async () => {
598+
checkReturnSchemaUrl('# yaml-language-server: $schema=expectedUrl1\n$schema: [expectedUrl2,expectedUrl3]', 'expectedUrl1');
599+
});
600+
589601
function checkReturnSchemaUrl(modeline: string, expectedResult: string): void {
590602
const service = new SchemaService.YAMLSchemaService(schemaRequestServiceForURL, workspaceContext);
591603
const yamlDoc = new parser.SingleYAMLDocument([]);

0 commit comments

Comments
 (0)