vscode-json-languageservice 4.1.7 → 4.2.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/lib/esm/jsonLanguageService.d.ts +2 -1
- package/lib/esm/jsonLanguageService.js +1 -0
- package/lib/esm/jsonLanguageTypes.d.ts +3 -0
- package/lib/esm/parser/jsonParser.js +2 -2
- package/lib/esm/services/configuration.js +0 -2
- package/lib/esm/services/jsonCompletion.js +1 -1
- package/lib/esm/services/jsonSchemaService.js +64 -39
- package/lib/esm/services/jsonValidation.js +4 -1
- package/lib/esm/utils/strings.js +15 -3
- package/lib/umd/jsonLanguageService.d.ts +2 -1
- package/lib/umd/jsonLanguageService.js +1 -0
- package/lib/umd/jsonLanguageTypes.d.ts +3 -0
- package/lib/umd/parser/jsonParser.js +2 -2
- package/lib/umd/services/configuration.js +0 -2
- package/lib/umd/services/jsonCompletion.js +1 -1
- package/lib/umd/services/jsonSchemaService.js +64 -39
- package/lib/umd/services/jsonValidation.js +4 -1
- package/lib/umd/utils/strings.js +15 -3
- package/package.json +6 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Thenable, ASTNode, Color, ColorInformation, ColorPresentation, LanguageServiceParams, LanguageSettings, DocumentLanguageSettings, FoldingRange, JSONSchema, SelectionRange, FoldingRangesContext, DocumentSymbolsContext, ColorInformationContext as DocumentColorsContext, TextDocument, Position, CompletionItem, CompletionList, Hover, Range, SymbolInformation, Diagnostic, TextEdit, FormattingOptions, DocumentSymbol, DefinitionLink, MatchingSchema } from './jsonLanguageTypes';
|
|
1
|
+
import { Thenable, ASTNode, Color, ColorInformation, ColorPresentation, LanguageServiceParams, LanguageSettings, DocumentLanguageSettings, FoldingRange, JSONSchema, SelectionRange, FoldingRangesContext, DocumentSymbolsContext, ColorInformationContext as DocumentColorsContext, TextDocument, Position, CompletionItem, CompletionList, Hover, Range, SymbolInformation, Diagnostic, TextEdit, FormattingOptions, DocumentSymbol, DefinitionLink, MatchingSchema, JSONLanguageStatus } from './jsonLanguageTypes';
|
|
2
2
|
import { DocumentLink } from 'vscode-languageserver-types';
|
|
3
3
|
export declare type JSONDocument = {
|
|
4
4
|
root: ASTNode | undefined;
|
|
@@ -12,6 +12,7 @@ export interface LanguageService {
|
|
|
12
12
|
newJSONDocument(rootNode: ASTNode, syntaxDiagnostics?: Diagnostic[]): JSONDocument;
|
|
13
13
|
resetSchema(uri: string): boolean;
|
|
14
14
|
getMatchingSchemas(document: TextDocument, jsonDocument: JSONDocument, schema?: JSONSchema): Thenable<MatchingSchema[]>;
|
|
15
|
+
getLanguageStatus(document: TextDocument, jsonDocument: JSONDocument): JSONLanguageStatus;
|
|
15
16
|
doResolve(item: CompletionItem): Thenable<CompletionItem>;
|
|
16
17
|
doComplete(document: TextDocument, position: Position, doc: JSONDocument): Thenable<CompletionList | null>;
|
|
17
18
|
findDocumentSymbols(document: TextDocument, doc: JSONDocument, context?: DocumentSymbolsContext): SymbolInformation[];
|
|
@@ -35,6 +35,7 @@ export function getLanguageService(params) {
|
|
|
35
35
|
},
|
|
36
36
|
resetSchema: function (uri) { return jsonSchemaService.onResourceChange(uri); },
|
|
37
37
|
doValidation: jsonValidation.doValidation.bind(jsonValidation),
|
|
38
|
+
getLanguageStatus: jsonValidation.getLanguageStatus.bind(jsonValidation),
|
|
38
39
|
parseJSONDocument: function (document) { return parseJSON(document, { collectComments: true }); },
|
|
39
40
|
newJSONDocument: function (root, diagnostics) { return newJSONDocument(root, diagnostics); },
|
|
40
41
|
getMatchingSchemas: jsonSchemaService.getMatchingSchemas.bind(jsonSchemaService),
|
|
@@ -74,6 +74,9 @@ export interface MatchingSchema {
|
|
|
74
74
|
node: ASTNode;
|
|
75
75
|
schema: JSONSchema;
|
|
76
76
|
}
|
|
77
|
+
export interface JSONLanguageStatus {
|
|
78
|
+
schemas: string[];
|
|
79
|
+
}
|
|
77
80
|
export interface LanguageSettings {
|
|
78
81
|
/**
|
|
79
82
|
* If set, the validator will return syntax and semantic errors.
|
|
@@ -617,7 +617,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
617
617
|
}
|
|
618
618
|
if (isString(schema.pattern)) {
|
|
619
619
|
var regex = extendedRegExp(schema.pattern);
|
|
620
|
-
if (!regex.test(node.value)) {
|
|
620
|
+
if (!(regex === null || regex === void 0 ? void 0 : regex.test(node.value))) {
|
|
621
621
|
validationResult.problems.push({
|
|
622
622
|
location: { offset: node.offset, length: node.length },
|
|
623
623
|
message: schema.patternErrorMessage || schema.errorMessage || localize('patternWarning', 'String does not match the pattern of "{0}".', schema.pattern)
|
|
@@ -811,7 +811,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
811
811
|
var regex = extendedRegExp(propertyPattern);
|
|
812
812
|
for (var _h = 0, _j = unprocessedProperties.slice(0); _h < _j.length; _h++) {
|
|
813
813
|
var propertyName = _j[_h];
|
|
814
|
-
if (regex.test(propertyName)) {
|
|
814
|
+
if (regex === null || regex === void 0 ? void 0 : regex.test(propertyName)) {
|
|
815
815
|
propertyProcessed(propertyName);
|
|
816
816
|
var child = seenKeys[propertyName];
|
|
817
817
|
if (child) {
|
|
@@ -13,7 +13,6 @@ export var schemaContributions = {
|
|
|
13
13
|
},
|
|
14
14
|
// bundle the schema-schema to include (localized) descriptions
|
|
15
15
|
'http://json-schema.org/draft-04/schema#': {
|
|
16
|
-
'title': localize('schema.json', 'Describes a JSON file using a schema. See json-schema.org for more info.'),
|
|
17
16
|
'$schema': 'http://json-schema.org/draft-04/schema#',
|
|
18
17
|
'definitions': {
|
|
19
18
|
'schemaArray': {
|
|
@@ -297,7 +296,6 @@ export var schemaContributions = {
|
|
|
297
296
|
'default': {}
|
|
298
297
|
},
|
|
299
298
|
'http://json-schema.org/draft-07/schema#': {
|
|
300
|
-
'title': localize('schema.json', 'Describes a JSON file using a schema. See json-schema.org for more info.'),
|
|
301
299
|
'definitions': {
|
|
302
300
|
'schemaArray': {
|
|
303
301
|
'type': 'array',
|
|
@@ -440,7 +440,7 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
440
440
|
for (var _a = 0, _b = Object.keys(s.schema.patternProperties); _a < _b.length; _a++) {
|
|
441
441
|
var pattern = _b[_a];
|
|
442
442
|
var regex = extendedRegExp(pattern);
|
|
443
|
-
if (regex.test(parentKey)) {
|
|
443
|
+
if (regex === null || regex === void 0 ? void 0 : regex.test(parentKey)) {
|
|
444
444
|
propertyMatched = true;
|
|
445
445
|
var propertySchema = s.schema.patternProperties[pattern];
|
|
446
446
|
this.addSchemaValueCompletions(propertySchema, separatorAfter, collector, types);
|
|
@@ -55,17 +55,17 @@ var FilePatternAssociation = /** @class */ (function () {
|
|
|
55
55
|
return FilePatternAssociation;
|
|
56
56
|
}());
|
|
57
57
|
var SchemaHandle = /** @class */ (function () {
|
|
58
|
-
function SchemaHandle(service,
|
|
58
|
+
function SchemaHandle(service, uri, unresolvedSchemaContent) {
|
|
59
59
|
this.service = service;
|
|
60
|
-
this.
|
|
61
|
-
this.dependencies =
|
|
60
|
+
this.uri = uri;
|
|
61
|
+
this.dependencies = new Set();
|
|
62
62
|
if (unresolvedSchemaContent) {
|
|
63
63
|
this.unresolvedSchema = this.service.promise.resolve(new UnresolvedSchema(unresolvedSchemaContent));
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
SchemaHandle.prototype.getUnresolvedSchema = function () {
|
|
67
67
|
if (!this.unresolvedSchema) {
|
|
68
|
-
this.unresolvedSchema = this.service.loadSchema(this.
|
|
68
|
+
this.unresolvedSchema = this.service.loadSchema(this.uri);
|
|
69
69
|
}
|
|
70
70
|
return this.unresolvedSchema;
|
|
71
71
|
};
|
|
@@ -73,15 +73,17 @@ var SchemaHandle = /** @class */ (function () {
|
|
|
73
73
|
var _this = this;
|
|
74
74
|
if (!this.resolvedSchema) {
|
|
75
75
|
this.resolvedSchema = this.getUnresolvedSchema().then(function (unresolved) {
|
|
76
|
-
return _this.service.resolveSchemaContent(unresolved, _this.
|
|
76
|
+
return _this.service.resolveSchemaContent(unresolved, _this.uri, _this.dependencies);
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
return this.resolvedSchema;
|
|
80
80
|
};
|
|
81
81
|
SchemaHandle.prototype.clearSchema = function () {
|
|
82
|
+
var hasChanges = !!this.unresolvedSchema;
|
|
82
83
|
this.resolvedSchema = undefined;
|
|
83
84
|
this.unresolvedSchema = undefined;
|
|
84
|
-
this.dependencies
|
|
85
|
+
this.dependencies.clear();
|
|
86
|
+
return hasChanges;
|
|
85
87
|
};
|
|
86
88
|
return SchemaHandle;
|
|
87
89
|
}());
|
|
@@ -119,7 +121,7 @@ var ResolvedSchema = /** @class */ (function () {
|
|
|
119
121
|
for (var _i = 0, _a = Object.keys(schema.patternProperties); _i < _a.length; _i++) {
|
|
120
122
|
var pattern = _a[_i];
|
|
121
123
|
var regex = Strings.extendedRegExp(pattern);
|
|
122
|
-
if (regex.test(next)) {
|
|
124
|
+
if (regex === null || regex === void 0 ? void 0 : regex.test(next)) {
|
|
123
125
|
return this.getSectionRecursive(path, schema.patternProperties[pattern]);
|
|
124
126
|
}
|
|
125
127
|
}
|
|
@@ -175,6 +177,8 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
175
177
|
};
|
|
176
178
|
JSONSchemaService.prototype.onResourceChange = function (uri) {
|
|
177
179
|
var _this = this;
|
|
180
|
+
// always clear this local cache when a resource changes
|
|
181
|
+
this.cachedSchemaForResource = undefined;
|
|
178
182
|
var hasChanges = false;
|
|
179
183
|
uri = normalizeId(uri);
|
|
180
184
|
var toWalk = [uri];
|
|
@@ -183,13 +187,14 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
183
187
|
var curr = toWalk.pop();
|
|
184
188
|
for (var i = 0; i < all.length; i++) {
|
|
185
189
|
var handle = all[i];
|
|
186
|
-
if (handle && (handle.
|
|
187
|
-
if (handle.
|
|
188
|
-
toWalk.push(handle.
|
|
190
|
+
if (handle && (handle.uri === curr || handle.dependencies.has(curr))) {
|
|
191
|
+
if (handle.uri !== curr) {
|
|
192
|
+
toWalk.push(handle.uri);
|
|
193
|
+
}
|
|
194
|
+
if (handle.clearSchema()) {
|
|
195
|
+
hasChanges = true;
|
|
189
196
|
}
|
|
190
|
-
handle.clearSchema();
|
|
191
197
|
all[i] = undefined;
|
|
192
|
-
hasChanges = true;
|
|
193
198
|
}
|
|
194
199
|
}
|
|
195
200
|
}
|
|
@@ -231,7 +236,7 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
231
236
|
this.registeredSchemasIds[id] = true;
|
|
232
237
|
this.cachedSchemaForResource = undefined;
|
|
233
238
|
if (filePatterns) {
|
|
234
|
-
this.addFilePatternAssociation(filePatterns, [
|
|
239
|
+
this.addFilePatternAssociation(filePatterns, [id]);
|
|
235
240
|
}
|
|
236
241
|
return unresolvedSchemaContent ? this.addSchemaHandle(id, unresolvedSchemaContent) : this.getOrAddSchemaHandle(id);
|
|
237
242
|
};
|
|
@@ -297,6 +302,9 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
297
302
|
else if (id === 'https://json-schema.org/draft/2019-09/schema') {
|
|
298
303
|
resolveErrors.push(localize('json.schema.draft201909.notsupported', "Draft 2019-09 schemas are not yet fully supported."));
|
|
299
304
|
}
|
|
305
|
+
else if (id === 'https://json-schema.org/draft/2020-12/schema') {
|
|
306
|
+
resolveErrors.push(localize('json.schema.draft202012.notsupported', "Draft 2020-12 schemas are not yet fully supported."));
|
|
307
|
+
}
|
|
300
308
|
}
|
|
301
309
|
var contextService = this.contextService;
|
|
302
310
|
var findSection = function (schema, path) {
|
|
@@ -335,7 +343,7 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
335
343
|
uri = normalizeId(uri);
|
|
336
344
|
var referencedHandle = _this.getOrAddSchemaHandle(uri);
|
|
337
345
|
return referencedHandle.getUnresolvedSchema().then(function (unresolvedSchema) {
|
|
338
|
-
parentSchemaDependencies
|
|
346
|
+
parentSchemaDependencies.add(uri);
|
|
339
347
|
if (unresolvedSchema.errors.length) {
|
|
340
348
|
var loc = refSegment ? uri + '#' + refSegment : uri;
|
|
341
349
|
resolveErrors.push(localize('json.schema.problemloadingref', 'Problems loading reference \'{0}\': {1}', loc, unresolvedSchema.errors[0]));
|
|
@@ -349,7 +357,7 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
349
357
|
return Promise.resolve(null);
|
|
350
358
|
}
|
|
351
359
|
var toWalk = [node];
|
|
352
|
-
var seen =
|
|
360
|
+
var seen = new Set();
|
|
353
361
|
var openPromises = [];
|
|
354
362
|
var collectEntries = function () {
|
|
355
363
|
var entries = [];
|
|
@@ -399,7 +407,7 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
399
407
|
}
|
|
400
408
|
};
|
|
401
409
|
var handleRef = function (next) {
|
|
402
|
-
var seenRefs =
|
|
410
|
+
var seenRefs = new Set();
|
|
403
411
|
while (next.$ref) {
|
|
404
412
|
var ref = next.$ref;
|
|
405
413
|
var segments = ref.split('#', 2);
|
|
@@ -409,9 +417,9 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
409
417
|
return;
|
|
410
418
|
}
|
|
411
419
|
else {
|
|
412
|
-
if (seenRefs.
|
|
420
|
+
if (!seenRefs.has(ref)) {
|
|
413
421
|
merge(next, parentSchema, parentSchemaURL, segments[1]); // can set next.$ref again, use seenRefs to avoid circle
|
|
414
|
-
seenRefs.
|
|
422
|
+
seenRefs.add(ref);
|
|
415
423
|
}
|
|
416
424
|
}
|
|
417
425
|
}
|
|
@@ -421,37 +429,29 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
421
429
|
};
|
|
422
430
|
while (toWalk.length) {
|
|
423
431
|
var next = toWalk.pop();
|
|
424
|
-
if (seen.
|
|
432
|
+
if (seen.has(next)) {
|
|
425
433
|
continue;
|
|
426
434
|
}
|
|
427
|
-
seen.
|
|
435
|
+
seen.add(next);
|
|
428
436
|
handleRef(next);
|
|
429
437
|
}
|
|
430
438
|
return _this.promise.all(openPromises);
|
|
431
439
|
};
|
|
432
440
|
return resolveRefs(schema, schema, schemaURL, dependencies).then(function (_) { return new ResolvedSchema(schema, resolveErrors); });
|
|
433
441
|
};
|
|
434
|
-
JSONSchemaService.prototype.
|
|
435
|
-
|
|
436
|
-
if (
|
|
437
|
-
var
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
var schemeId = Parser.getNodeValue(valueNode);
|
|
442
|
-
if (schemeId && Strings.startsWith(schemeId, '.') && this.contextService) {
|
|
443
|
-
schemeId = this.contextService.resolveRelativePath(schemeId, resource);
|
|
444
|
-
}
|
|
445
|
-
if (schemeId) {
|
|
446
|
-
var id = normalizeId(schemeId);
|
|
447
|
-
return this.getOrAddSchemaHandle(id).getResolvedSchema();
|
|
448
|
-
}
|
|
442
|
+
JSONSchemaService.prototype.getSchemaProperty = function (document) {
|
|
443
|
+
var _a, _b;
|
|
444
|
+
if (((_a = document.root) === null || _a === void 0 ? void 0 : _a.type) === 'object') {
|
|
445
|
+
for (var _i = 0, _c = document.root.properties; _i < _c.length; _i++) {
|
|
446
|
+
var p = _c[_i];
|
|
447
|
+
if (p.keyNode.value === '$schema' && ((_b = p.valueNode) === null || _b === void 0 ? void 0 : _b.type) === 'string') {
|
|
448
|
+
return p.valueNode.value;
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
451
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
452
|
+
return undefined;
|
|
453
|
+
};
|
|
454
|
+
JSONSchemaService.prototype.getAssociatedSchemas = function (resource) {
|
|
455
455
|
var seen = Object.create(null);
|
|
456
456
|
var schemas = [];
|
|
457
457
|
var normalizedResource = normalizeResourceForMatching(resource);
|
|
@@ -467,6 +467,31 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
467
467
|
}
|
|
468
468
|
}
|
|
469
469
|
}
|
|
470
|
+
return schemas;
|
|
471
|
+
};
|
|
472
|
+
JSONSchemaService.prototype.getSchemaURIsForResource = function (resource, document) {
|
|
473
|
+
var schemeId = document && this.getSchemaProperty(document);
|
|
474
|
+
if (schemeId) {
|
|
475
|
+
return [schemeId];
|
|
476
|
+
}
|
|
477
|
+
return this.getAssociatedSchemas(resource);
|
|
478
|
+
};
|
|
479
|
+
JSONSchemaService.prototype.getSchemaForResource = function (resource, document) {
|
|
480
|
+
if (document) {
|
|
481
|
+
// first use $schema if present
|
|
482
|
+
var schemeId = this.getSchemaProperty(document);
|
|
483
|
+
if (schemeId && Strings.startsWith(schemeId, '.') && this.contextService) {
|
|
484
|
+
schemeId = this.contextService.resolveRelativePath(schemeId, resource);
|
|
485
|
+
}
|
|
486
|
+
if (schemeId) {
|
|
487
|
+
var id = normalizeId(schemeId);
|
|
488
|
+
return this.getOrAddSchemaHandle(id).getResolvedSchema();
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (this.cachedSchemaForResource && this.cachedSchemaForResource.resource === resource) {
|
|
492
|
+
return this.cachedSchemaForResource.resolvedSchema;
|
|
493
|
+
}
|
|
494
|
+
var schemas = this.getAssociatedSchemas(resource);
|
|
470
495
|
var resolvedSchema = schemas.length > 0 ? this.createCombinedSchema(resource, schemas).getResolvedSchema() : this.promise.resolve(undefined);
|
|
471
496
|
this.cachedSchemaForResource = { resource: resource, resolvedSchema: resolvedSchema };
|
|
472
497
|
return resolvedSchema;
|
|
@@ -486,7 +511,7 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
486
511
|
JSONSchemaService.prototype.getMatchingSchemas = function (document, jsonDocument, schema) {
|
|
487
512
|
if (schema) {
|
|
488
513
|
var id = schema.id || ('schemaservice://untitled/matchingSchemas/' + idCounter++);
|
|
489
|
-
return this.resolveSchemaContent(new UnresolvedSchema(schema), id,
|
|
514
|
+
return this.resolveSchemaContent(new UnresolvedSchema(schema), id, new Set()).then(function (resolvedSchema) {
|
|
490
515
|
return jsonDocument.getMatchingSchemas(resolvedSchema.schema).filter(function (s) { return !s.inverted; });
|
|
491
516
|
});
|
|
492
517
|
}
|
|
@@ -86,7 +86,7 @@ var JSONValidation = /** @class */ (function () {
|
|
|
86
86
|
};
|
|
87
87
|
if (schema) {
|
|
88
88
|
var id = schema.id || ('schemaservice://untitled/' + idCounter++);
|
|
89
|
-
return this.jsonSchemaService.resolveSchemaContent(new UnresolvedSchema(schema), id,
|
|
89
|
+
return this.jsonSchemaService.resolveSchemaContent(new UnresolvedSchema(schema), id, new Set()).then(function (resolvedSchema) {
|
|
90
90
|
return getDiagnostics(resolvedSchema);
|
|
91
91
|
});
|
|
92
92
|
}
|
|
@@ -94,6 +94,9 @@ var JSONValidation = /** @class */ (function () {
|
|
|
94
94
|
return getDiagnostics(schema);
|
|
95
95
|
});
|
|
96
96
|
};
|
|
97
|
+
JSONValidation.prototype.getLanguageStatus = function (textDocument, jsonDocument) {
|
|
98
|
+
return { schemas: this.jsonSchemaService.getSchemaURIsForResource(textDocument.uri, jsonDocument) };
|
|
99
|
+
};
|
|
97
100
|
return JSONValidation;
|
|
98
101
|
}());
|
|
99
102
|
export { JSONValidation };
|
package/lib/esm/utils/strings.js
CHANGED
|
@@ -43,10 +43,22 @@ export function repeat(value, count) {
|
|
|
43
43
|
return s;
|
|
44
44
|
}
|
|
45
45
|
export function extendedRegExp(pattern) {
|
|
46
|
+
var flags = '';
|
|
46
47
|
if (startsWith(pattern, '(?i)')) {
|
|
47
|
-
|
|
48
|
+
pattern = pattern.substring(4);
|
|
49
|
+
flags = 'i';
|
|
48
50
|
}
|
|
49
|
-
|
|
50
|
-
return new RegExp(pattern);
|
|
51
|
+
try {
|
|
52
|
+
return new RegExp(pattern, flags + 'u');
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
// could be an exception due to the 'u ' flag
|
|
56
|
+
try {
|
|
57
|
+
return new RegExp(pattern, flags);
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
// invalid pattern
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
51
63
|
}
|
|
52
64
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Thenable, ASTNode, Color, ColorInformation, ColorPresentation, LanguageServiceParams, LanguageSettings, DocumentLanguageSettings, FoldingRange, JSONSchema, SelectionRange, FoldingRangesContext, DocumentSymbolsContext, ColorInformationContext as DocumentColorsContext, TextDocument, Position, CompletionItem, CompletionList, Hover, Range, SymbolInformation, Diagnostic, TextEdit, FormattingOptions, DocumentSymbol, DefinitionLink, MatchingSchema } from './jsonLanguageTypes';
|
|
1
|
+
import { Thenable, ASTNode, Color, ColorInformation, ColorPresentation, LanguageServiceParams, LanguageSettings, DocumentLanguageSettings, FoldingRange, JSONSchema, SelectionRange, FoldingRangesContext, DocumentSymbolsContext, ColorInformationContext as DocumentColorsContext, TextDocument, Position, CompletionItem, CompletionList, Hover, Range, SymbolInformation, Diagnostic, TextEdit, FormattingOptions, DocumentSymbol, DefinitionLink, MatchingSchema, JSONLanguageStatus } from './jsonLanguageTypes';
|
|
2
2
|
import { DocumentLink } from 'vscode-languageserver-types';
|
|
3
3
|
export declare type JSONDocument = {
|
|
4
4
|
root: ASTNode | undefined;
|
|
@@ -12,6 +12,7 @@ export interface LanguageService {
|
|
|
12
12
|
newJSONDocument(rootNode: ASTNode, syntaxDiagnostics?: Diagnostic[]): JSONDocument;
|
|
13
13
|
resetSchema(uri: string): boolean;
|
|
14
14
|
getMatchingSchemas(document: TextDocument, jsonDocument: JSONDocument, schema?: JSONSchema): Thenable<MatchingSchema[]>;
|
|
15
|
+
getLanguageStatus(document: TextDocument, jsonDocument: JSONDocument): JSONLanguageStatus;
|
|
15
16
|
doResolve(item: CompletionItem): Thenable<CompletionItem>;
|
|
16
17
|
doComplete(document: TextDocument, position: Position, doc: JSONDocument): Thenable<CompletionList | null>;
|
|
17
18
|
findDocumentSymbols(document: TextDocument, doc: JSONDocument, context?: DocumentSymbolsContext): SymbolInformation[];
|
|
@@ -57,6 +57,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
57
57
|
},
|
|
58
58
|
resetSchema: function (uri) { return jsonSchemaService.onResourceChange(uri); },
|
|
59
59
|
doValidation: jsonValidation.doValidation.bind(jsonValidation),
|
|
60
|
+
getLanguageStatus: jsonValidation.getLanguageStatus.bind(jsonValidation),
|
|
60
61
|
parseJSONDocument: function (document) { return jsonParser_1.parse(document, { collectComments: true }); },
|
|
61
62
|
newJSONDocument: function (root, diagnostics) { return jsonParser_1.newJSONDocument(root, diagnostics); },
|
|
62
63
|
getMatchingSchemas: jsonSchemaService.getMatchingSchemas.bind(jsonSchemaService),
|
|
@@ -74,6 +74,9 @@ export interface MatchingSchema {
|
|
|
74
74
|
node: ASTNode;
|
|
75
75
|
schema: JSONSchema;
|
|
76
76
|
}
|
|
77
|
+
export interface JSONLanguageStatus {
|
|
78
|
+
schemas: string[];
|
|
79
|
+
}
|
|
77
80
|
export interface LanguageSettings {
|
|
78
81
|
/**
|
|
79
82
|
* If set, the validator will return syntax and semantic errors.
|
|
@@ -634,7 +634,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
634
634
|
}
|
|
635
635
|
if (objects_1.isString(schema.pattern)) {
|
|
636
636
|
var regex = strings_1.extendedRegExp(schema.pattern);
|
|
637
|
-
if (!regex.test(node.value)) {
|
|
637
|
+
if (!(regex === null || regex === void 0 ? void 0 : regex.test(node.value))) {
|
|
638
638
|
validationResult.problems.push({
|
|
639
639
|
location: { offset: node.offset, length: node.length },
|
|
640
640
|
message: schema.patternErrorMessage || schema.errorMessage || localize('patternWarning', 'String does not match the pattern of "{0}".', schema.pattern)
|
|
@@ -828,7 +828,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
828
828
|
var regex = strings_1.extendedRegExp(propertyPattern);
|
|
829
829
|
for (var _h = 0, _j = unprocessedProperties.slice(0); _h < _j.length; _h++) {
|
|
830
830
|
var propertyName = _j[_h];
|
|
831
|
-
if (regex.test(propertyName)) {
|
|
831
|
+
if (regex === null || regex === void 0 ? void 0 : regex.test(propertyName)) {
|
|
832
832
|
propertyProcessed(propertyName);
|
|
833
833
|
var child = seenKeys[propertyName];
|
|
834
834
|
if (child) {
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
},
|
|
26
26
|
// bundle the schema-schema to include (localized) descriptions
|
|
27
27
|
'http://json-schema.org/draft-04/schema#': {
|
|
28
|
-
'title': localize('schema.json', 'Describes a JSON file using a schema. See json-schema.org for more info.'),
|
|
29
28
|
'$schema': 'http://json-schema.org/draft-04/schema#',
|
|
30
29
|
'definitions': {
|
|
31
30
|
'schemaArray': {
|
|
@@ -309,7 +308,6 @@
|
|
|
309
308
|
'default': {}
|
|
310
309
|
},
|
|
311
310
|
'http://json-schema.org/draft-07/schema#': {
|
|
312
|
-
'title': localize('schema.json', 'Describes a JSON file using a schema. See json-schema.org for more info.'),
|
|
313
311
|
'definitions': {
|
|
314
312
|
'schemaArray': {
|
|
315
313
|
'type': 'array',
|
|
@@ -452,7 +452,7 @@
|
|
|
452
452
|
for (var _a = 0, _b = Object.keys(s.schema.patternProperties); _a < _b.length; _a++) {
|
|
453
453
|
var pattern = _b[_a];
|
|
454
454
|
var regex = strings_1.extendedRegExp(pattern);
|
|
455
|
-
if (regex.test(parentKey)) {
|
|
455
|
+
if (regex === null || regex === void 0 ? void 0 : regex.test(parentKey)) {
|
|
456
456
|
propertyMatched = true;
|
|
457
457
|
var propertySchema = s.schema.patternProperties[pattern];
|
|
458
458
|
this.addSchemaValueCompletions(propertySchema, separatorAfter, collector, types);
|
|
@@ -67,17 +67,17 @@
|
|
|
67
67
|
return FilePatternAssociation;
|
|
68
68
|
}());
|
|
69
69
|
var SchemaHandle = /** @class */ (function () {
|
|
70
|
-
function SchemaHandle(service,
|
|
70
|
+
function SchemaHandle(service, uri, unresolvedSchemaContent) {
|
|
71
71
|
this.service = service;
|
|
72
|
-
this.
|
|
73
|
-
this.dependencies =
|
|
72
|
+
this.uri = uri;
|
|
73
|
+
this.dependencies = new Set();
|
|
74
74
|
if (unresolvedSchemaContent) {
|
|
75
75
|
this.unresolvedSchema = this.service.promise.resolve(new UnresolvedSchema(unresolvedSchemaContent));
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
SchemaHandle.prototype.getUnresolvedSchema = function () {
|
|
79
79
|
if (!this.unresolvedSchema) {
|
|
80
|
-
this.unresolvedSchema = this.service.loadSchema(this.
|
|
80
|
+
this.unresolvedSchema = this.service.loadSchema(this.uri);
|
|
81
81
|
}
|
|
82
82
|
return this.unresolvedSchema;
|
|
83
83
|
};
|
|
@@ -85,15 +85,17 @@
|
|
|
85
85
|
var _this = this;
|
|
86
86
|
if (!this.resolvedSchema) {
|
|
87
87
|
this.resolvedSchema = this.getUnresolvedSchema().then(function (unresolved) {
|
|
88
|
-
return _this.service.resolveSchemaContent(unresolved, _this.
|
|
88
|
+
return _this.service.resolveSchemaContent(unresolved, _this.uri, _this.dependencies);
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
91
|
return this.resolvedSchema;
|
|
92
92
|
};
|
|
93
93
|
SchemaHandle.prototype.clearSchema = function () {
|
|
94
|
+
var hasChanges = !!this.unresolvedSchema;
|
|
94
95
|
this.resolvedSchema = undefined;
|
|
95
96
|
this.unresolvedSchema = undefined;
|
|
96
|
-
this.dependencies
|
|
97
|
+
this.dependencies.clear();
|
|
98
|
+
return hasChanges;
|
|
97
99
|
};
|
|
98
100
|
return SchemaHandle;
|
|
99
101
|
}());
|
|
@@ -131,7 +133,7 @@
|
|
|
131
133
|
for (var _i = 0, _a = Object.keys(schema.patternProperties); _i < _a.length; _i++) {
|
|
132
134
|
var pattern = _a[_i];
|
|
133
135
|
var regex = Strings.extendedRegExp(pattern);
|
|
134
|
-
if (regex.test(next)) {
|
|
136
|
+
if (regex === null || regex === void 0 ? void 0 : regex.test(next)) {
|
|
135
137
|
return this.getSectionRecursive(path, schema.patternProperties[pattern]);
|
|
136
138
|
}
|
|
137
139
|
}
|
|
@@ -187,6 +189,8 @@
|
|
|
187
189
|
};
|
|
188
190
|
JSONSchemaService.prototype.onResourceChange = function (uri) {
|
|
189
191
|
var _this = this;
|
|
192
|
+
// always clear this local cache when a resource changes
|
|
193
|
+
this.cachedSchemaForResource = undefined;
|
|
190
194
|
var hasChanges = false;
|
|
191
195
|
uri = normalizeId(uri);
|
|
192
196
|
var toWalk = [uri];
|
|
@@ -195,13 +199,14 @@
|
|
|
195
199
|
var curr = toWalk.pop();
|
|
196
200
|
for (var i = 0; i < all.length; i++) {
|
|
197
201
|
var handle = all[i];
|
|
198
|
-
if (handle && (handle.
|
|
199
|
-
if (handle.
|
|
200
|
-
toWalk.push(handle.
|
|
202
|
+
if (handle && (handle.uri === curr || handle.dependencies.has(curr))) {
|
|
203
|
+
if (handle.uri !== curr) {
|
|
204
|
+
toWalk.push(handle.uri);
|
|
205
|
+
}
|
|
206
|
+
if (handle.clearSchema()) {
|
|
207
|
+
hasChanges = true;
|
|
201
208
|
}
|
|
202
|
-
handle.clearSchema();
|
|
203
209
|
all[i] = undefined;
|
|
204
|
-
hasChanges = true;
|
|
205
210
|
}
|
|
206
211
|
}
|
|
207
212
|
}
|
|
@@ -243,7 +248,7 @@
|
|
|
243
248
|
this.registeredSchemasIds[id] = true;
|
|
244
249
|
this.cachedSchemaForResource = undefined;
|
|
245
250
|
if (filePatterns) {
|
|
246
|
-
this.addFilePatternAssociation(filePatterns, [
|
|
251
|
+
this.addFilePatternAssociation(filePatterns, [id]);
|
|
247
252
|
}
|
|
248
253
|
return unresolvedSchemaContent ? this.addSchemaHandle(id, unresolvedSchemaContent) : this.getOrAddSchemaHandle(id);
|
|
249
254
|
};
|
|
@@ -309,6 +314,9 @@
|
|
|
309
314
|
else if (id === 'https://json-schema.org/draft/2019-09/schema') {
|
|
310
315
|
resolveErrors.push(localize('json.schema.draft201909.notsupported', "Draft 2019-09 schemas are not yet fully supported."));
|
|
311
316
|
}
|
|
317
|
+
else if (id === 'https://json-schema.org/draft/2020-12/schema') {
|
|
318
|
+
resolveErrors.push(localize('json.schema.draft202012.notsupported', "Draft 2020-12 schemas are not yet fully supported."));
|
|
319
|
+
}
|
|
312
320
|
}
|
|
313
321
|
var contextService = this.contextService;
|
|
314
322
|
var findSection = function (schema, path) {
|
|
@@ -347,7 +355,7 @@
|
|
|
347
355
|
uri = normalizeId(uri);
|
|
348
356
|
var referencedHandle = _this.getOrAddSchemaHandle(uri);
|
|
349
357
|
return referencedHandle.getUnresolvedSchema().then(function (unresolvedSchema) {
|
|
350
|
-
parentSchemaDependencies
|
|
358
|
+
parentSchemaDependencies.add(uri);
|
|
351
359
|
if (unresolvedSchema.errors.length) {
|
|
352
360
|
var loc = refSegment ? uri + '#' + refSegment : uri;
|
|
353
361
|
resolveErrors.push(localize('json.schema.problemloadingref', 'Problems loading reference \'{0}\': {1}', loc, unresolvedSchema.errors[0]));
|
|
@@ -361,7 +369,7 @@
|
|
|
361
369
|
return Promise.resolve(null);
|
|
362
370
|
}
|
|
363
371
|
var toWalk = [node];
|
|
364
|
-
var seen =
|
|
372
|
+
var seen = new Set();
|
|
365
373
|
var openPromises = [];
|
|
366
374
|
var collectEntries = function () {
|
|
367
375
|
var entries = [];
|
|
@@ -411,7 +419,7 @@
|
|
|
411
419
|
}
|
|
412
420
|
};
|
|
413
421
|
var handleRef = function (next) {
|
|
414
|
-
var seenRefs =
|
|
422
|
+
var seenRefs = new Set();
|
|
415
423
|
while (next.$ref) {
|
|
416
424
|
var ref = next.$ref;
|
|
417
425
|
var segments = ref.split('#', 2);
|
|
@@ -421,9 +429,9 @@
|
|
|
421
429
|
return;
|
|
422
430
|
}
|
|
423
431
|
else {
|
|
424
|
-
if (seenRefs.
|
|
432
|
+
if (!seenRefs.has(ref)) {
|
|
425
433
|
merge(next, parentSchema, parentSchemaURL, segments[1]); // can set next.$ref again, use seenRefs to avoid circle
|
|
426
|
-
seenRefs.
|
|
434
|
+
seenRefs.add(ref);
|
|
427
435
|
}
|
|
428
436
|
}
|
|
429
437
|
}
|
|
@@ -433,37 +441,29 @@
|
|
|
433
441
|
};
|
|
434
442
|
while (toWalk.length) {
|
|
435
443
|
var next = toWalk.pop();
|
|
436
|
-
if (seen.
|
|
444
|
+
if (seen.has(next)) {
|
|
437
445
|
continue;
|
|
438
446
|
}
|
|
439
|
-
seen.
|
|
447
|
+
seen.add(next);
|
|
440
448
|
handleRef(next);
|
|
441
449
|
}
|
|
442
450
|
return _this.promise.all(openPromises);
|
|
443
451
|
};
|
|
444
452
|
return resolveRefs(schema, schema, schemaURL, dependencies).then(function (_) { return new ResolvedSchema(schema, resolveErrors); });
|
|
445
453
|
};
|
|
446
|
-
JSONSchemaService.prototype.
|
|
447
|
-
|
|
448
|
-
if (
|
|
449
|
-
var
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
var schemeId = Parser.getNodeValue(valueNode);
|
|
454
|
-
if (schemeId && Strings.startsWith(schemeId, '.') && this.contextService) {
|
|
455
|
-
schemeId = this.contextService.resolveRelativePath(schemeId, resource);
|
|
456
|
-
}
|
|
457
|
-
if (schemeId) {
|
|
458
|
-
var id = normalizeId(schemeId);
|
|
459
|
-
return this.getOrAddSchemaHandle(id).getResolvedSchema();
|
|
460
|
-
}
|
|
454
|
+
JSONSchemaService.prototype.getSchemaProperty = function (document) {
|
|
455
|
+
var _a, _b;
|
|
456
|
+
if (((_a = document.root) === null || _a === void 0 ? void 0 : _a.type) === 'object') {
|
|
457
|
+
for (var _i = 0, _c = document.root.properties; _i < _c.length; _i++) {
|
|
458
|
+
var p = _c[_i];
|
|
459
|
+
if (p.keyNode.value === '$schema' && ((_b = p.valueNode) === null || _b === void 0 ? void 0 : _b.type) === 'string') {
|
|
460
|
+
return p.valueNode.value;
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
463
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
464
|
+
return undefined;
|
|
465
|
+
};
|
|
466
|
+
JSONSchemaService.prototype.getAssociatedSchemas = function (resource) {
|
|
467
467
|
var seen = Object.create(null);
|
|
468
468
|
var schemas = [];
|
|
469
469
|
var normalizedResource = normalizeResourceForMatching(resource);
|
|
@@ -479,6 +479,31 @@
|
|
|
479
479
|
}
|
|
480
480
|
}
|
|
481
481
|
}
|
|
482
|
+
return schemas;
|
|
483
|
+
};
|
|
484
|
+
JSONSchemaService.prototype.getSchemaURIsForResource = function (resource, document) {
|
|
485
|
+
var schemeId = document && this.getSchemaProperty(document);
|
|
486
|
+
if (schemeId) {
|
|
487
|
+
return [schemeId];
|
|
488
|
+
}
|
|
489
|
+
return this.getAssociatedSchemas(resource);
|
|
490
|
+
};
|
|
491
|
+
JSONSchemaService.prototype.getSchemaForResource = function (resource, document) {
|
|
492
|
+
if (document) {
|
|
493
|
+
// first use $schema if present
|
|
494
|
+
var schemeId = this.getSchemaProperty(document);
|
|
495
|
+
if (schemeId && Strings.startsWith(schemeId, '.') && this.contextService) {
|
|
496
|
+
schemeId = this.contextService.resolveRelativePath(schemeId, resource);
|
|
497
|
+
}
|
|
498
|
+
if (schemeId) {
|
|
499
|
+
var id = normalizeId(schemeId);
|
|
500
|
+
return this.getOrAddSchemaHandle(id).getResolvedSchema();
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (this.cachedSchemaForResource && this.cachedSchemaForResource.resource === resource) {
|
|
504
|
+
return this.cachedSchemaForResource.resolvedSchema;
|
|
505
|
+
}
|
|
506
|
+
var schemas = this.getAssociatedSchemas(resource);
|
|
482
507
|
var resolvedSchema = schemas.length > 0 ? this.createCombinedSchema(resource, schemas).getResolvedSchema() : this.promise.resolve(undefined);
|
|
483
508
|
this.cachedSchemaForResource = { resource: resource, resolvedSchema: resolvedSchema };
|
|
484
509
|
return resolvedSchema;
|
|
@@ -498,7 +523,7 @@
|
|
|
498
523
|
JSONSchemaService.prototype.getMatchingSchemas = function (document, jsonDocument, schema) {
|
|
499
524
|
if (schema) {
|
|
500
525
|
var id = schema.id || ('schemaservice://untitled/matchingSchemas/' + idCounter++);
|
|
501
|
-
return this.resolveSchemaContent(new UnresolvedSchema(schema), id,
|
|
526
|
+
return this.resolveSchemaContent(new UnresolvedSchema(schema), id, new Set()).then(function (resolvedSchema) {
|
|
502
527
|
return jsonDocument.getMatchingSchemas(resolvedSchema.schema).filter(function (s) { return !s.inverted; });
|
|
503
528
|
});
|
|
504
529
|
}
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
};
|
|
99
99
|
if (schema) {
|
|
100
100
|
var id = schema.id || ('schemaservice://untitled/' + idCounter++);
|
|
101
|
-
return this.jsonSchemaService.resolveSchemaContent(new jsonSchemaService_1.UnresolvedSchema(schema), id,
|
|
101
|
+
return this.jsonSchemaService.resolveSchemaContent(new jsonSchemaService_1.UnresolvedSchema(schema), id, new Set()).then(function (resolvedSchema) {
|
|
102
102
|
return getDiagnostics(resolvedSchema);
|
|
103
103
|
});
|
|
104
104
|
}
|
|
@@ -106,6 +106,9 @@
|
|
|
106
106
|
return getDiagnostics(schema);
|
|
107
107
|
});
|
|
108
108
|
};
|
|
109
|
+
JSONValidation.prototype.getLanguageStatus = function (textDocument, jsonDocument) {
|
|
110
|
+
return { schemas: this.jsonSchemaService.getSchemaURIsForResource(textDocument.uri, jsonDocument) };
|
|
111
|
+
};
|
|
109
112
|
return JSONValidation;
|
|
110
113
|
}());
|
|
111
114
|
exports.JSONValidation = JSONValidation;
|
package/lib/umd/utils/strings.js
CHANGED
|
@@ -59,11 +59,23 @@
|
|
|
59
59
|
}
|
|
60
60
|
exports.repeat = repeat;
|
|
61
61
|
function extendedRegExp(pattern) {
|
|
62
|
+
var flags = '';
|
|
62
63
|
if (startsWith(pattern, '(?i)')) {
|
|
63
|
-
|
|
64
|
+
pattern = pattern.substring(4);
|
|
65
|
+
flags = 'i';
|
|
64
66
|
}
|
|
65
|
-
|
|
66
|
-
return new RegExp(pattern);
|
|
67
|
+
try {
|
|
68
|
+
return new RegExp(pattern, flags + 'u');
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
// could be an exception due to the 'u ' flag
|
|
72
|
+
try {
|
|
73
|
+
return new RegExp(pattern, flags);
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
// invalid pattern
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
67
79
|
}
|
|
68
80
|
}
|
|
69
81
|
exports.extendedRegExp = extendedRegExp;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vscode-json-languageservice",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0-next.0",
|
|
4
4
|
"description": "Language service for JSON",
|
|
5
5
|
"main": "./lib/umd/jsonLanguageService.js",
|
|
6
6
|
"typings": "./lib/umd/jsonLanguageService",
|
|
@@ -14,16 +14,13 @@
|
|
|
14
14
|
"bugs": {
|
|
15
15
|
"url": "https://github.com/Microsoft/vscode-json-languageservice"
|
|
16
16
|
},
|
|
17
|
-
"engines": {
|
|
18
|
-
"npm": ">=7.0.0"
|
|
19
|
-
},
|
|
20
17
|
"devDependencies": {
|
|
21
|
-
"@types/mocha": "^
|
|
18
|
+
"@types/mocha": "^9.0.0",
|
|
22
19
|
"@types/node": "^10.12.21",
|
|
23
|
-
"@typescript-eslint/eslint-plugin": "^4.
|
|
24
|
-
"@typescript-eslint/parser": "^4.
|
|
25
|
-
"eslint": "^7.
|
|
26
|
-
"mocha": "^
|
|
20
|
+
"@typescript-eslint/eslint-plugin": "^4.32.0",
|
|
21
|
+
"@typescript-eslint/parser": "^4.32.0",
|
|
22
|
+
"eslint": "^7.32.0",
|
|
23
|
+
"mocha": "^9.1.2",
|
|
27
24
|
"rimraf": "^3.0.2",
|
|
28
25
|
"typescript": "^4.1.3"
|
|
29
26
|
},
|