vscode-json-languageservice 4.1.9 → 4.2.0-next.2
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 +6 -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 +9 -3
- package/lib/esm/services/jsonCompletion.js +1 -1
- package/lib/esm/services/jsonSchemaService.js +170 -52
- package/lib/esm/services/jsonValidation.js +5 -2
- 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 +9 -3
- package/lib/umd/services/jsonCompletion.js +1 -1
- package/lib/umd/services/jsonSchemaService.js +170 -52
- package/lib/umd/services/jsonValidation.js +6 -3
- package/lib/umd/utils/strings.js +15 -3
- package/package.json +1 -4
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.
|
|
@@ -28,7 +28,10 @@ var formats = {
|
|
|
28
28
|
'date-time': { errorMessage: localize('dateTimeFormatWarning', 'String is not a RFC3339 date-time.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)([01][0-9]|2[0-3]):([0-5][0-9]))$/i },
|
|
29
29
|
'date': { errorMessage: localize('dateFormatWarning', 'String is not a RFC3339 date.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/i },
|
|
30
30
|
'time': { errorMessage: localize('timeFormatWarning', 'String is not a RFC3339 time.'), pattern: /^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)([01][0-9]|2[0-3]):([0-5][0-9]))$/i },
|
|
31
|
-
'email': { errorMessage: localize('emailFormatWarning', 'String is not an e-mail address.'), pattern: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-
|
|
31
|
+
'email': { errorMessage: localize('emailFormatWarning', 'String is not an e-mail address.'), pattern: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}))$/ },
|
|
32
|
+
'hostname': { errorMessage: localize('hostnameFormatWarning', 'String is not a hostname.'), pattern: /^(?=.{1,253}\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\.?$/i },
|
|
33
|
+
'ipv4': { errorMessage: localize('ipv4FormatWarning', 'String is not an IPv4 address.'), pattern: /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/ },
|
|
34
|
+
'ipv6': { errorMessage: localize('ipv6FormatWarning', 'String is not an IPv6 address.'), pattern: /^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i },
|
|
32
35
|
};
|
|
33
36
|
var ASTNodeImpl = /** @class */ (function () {
|
|
34
37
|
function ASTNodeImpl(parent, offset, length) {
|
|
@@ -617,7 +620,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
617
620
|
}
|
|
618
621
|
if (isString(schema.pattern)) {
|
|
619
622
|
var regex = extendedRegExp(schema.pattern);
|
|
620
|
-
if (!regex.test(node.value)) {
|
|
623
|
+
if (!(regex === null || regex === void 0 ? void 0 : regex.test(node.value))) {
|
|
621
624
|
validationResult.problems.push({
|
|
622
625
|
location: { offset: node.offset, length: node.length },
|
|
623
626
|
message: schema.patternErrorMessage || schema.errorMessage || localize('patternWarning', 'String does not match the pattern of "{0}".', schema.pattern)
|
|
@@ -655,6 +658,9 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
655
658
|
case 'date':
|
|
656
659
|
case 'time':
|
|
657
660
|
case 'email':
|
|
661
|
+
case 'hostname':
|
|
662
|
+
case 'ipv4':
|
|
663
|
+
case 'ipv6':
|
|
658
664
|
var format = formats[schema.format];
|
|
659
665
|
if (!node.value || !format.pattern.exec(node.value)) {
|
|
660
666
|
validationResult.problems.push({
|
|
@@ -811,7 +817,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
811
817
|
var regex = extendedRegExp(propertyPattern);
|
|
812
818
|
for (var _h = 0, _j = unprocessedProperties.slice(0); _h < _j.length; _h++) {
|
|
813
819
|
var propertyName = _j[_h];
|
|
814
|
-
if (regex.test(propertyName)) {
|
|
820
|
+
if (regex === null || regex === void 0 ? void 0 : regex.test(propertyName)) {
|
|
815
821
|
propertyProcessed(propertyName);
|
|
816
822
|
var child = seenKeys[propertyName];
|
|
817
823
|
if (child) {
|
|
@@ -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,18 @@ 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
|
+
this.anchors = new Map();
|
|
62
63
|
if (unresolvedSchemaContent) {
|
|
63
64
|
this.unresolvedSchema = this.service.promise.resolve(new UnresolvedSchema(unresolvedSchemaContent));
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
SchemaHandle.prototype.getUnresolvedSchema = function () {
|
|
67
68
|
if (!this.unresolvedSchema) {
|
|
68
|
-
this.unresolvedSchema = this.service.loadSchema(this.
|
|
69
|
+
this.unresolvedSchema = this.service.loadSchema(this.uri);
|
|
69
70
|
}
|
|
70
71
|
return this.unresolvedSchema;
|
|
71
72
|
};
|
|
@@ -73,15 +74,18 @@ var SchemaHandle = /** @class */ (function () {
|
|
|
73
74
|
var _this = this;
|
|
74
75
|
if (!this.resolvedSchema) {
|
|
75
76
|
this.resolvedSchema = this.getUnresolvedSchema().then(function (unresolved) {
|
|
76
|
-
return _this.service.resolveSchemaContent(unresolved, _this
|
|
77
|
+
return _this.service.resolveSchemaContent(unresolved, _this);
|
|
77
78
|
});
|
|
78
79
|
}
|
|
79
80
|
return this.resolvedSchema;
|
|
80
81
|
};
|
|
81
82
|
SchemaHandle.prototype.clearSchema = function () {
|
|
83
|
+
var hasChanges = !!this.unresolvedSchema;
|
|
82
84
|
this.resolvedSchema = undefined;
|
|
83
85
|
this.unresolvedSchema = undefined;
|
|
84
|
-
this.dependencies
|
|
86
|
+
this.dependencies.clear();
|
|
87
|
+
this.anchors.clear();
|
|
88
|
+
return hasChanges;
|
|
85
89
|
};
|
|
86
90
|
return SchemaHandle;
|
|
87
91
|
}());
|
|
@@ -119,7 +123,7 @@ var ResolvedSchema = /** @class */ (function () {
|
|
|
119
123
|
for (var _i = 0, _a = Object.keys(schema.patternProperties); _i < _a.length; _i++) {
|
|
120
124
|
var pattern = _a[_i];
|
|
121
125
|
var regex = Strings.extendedRegExp(pattern);
|
|
122
|
-
if (regex.test(next)) {
|
|
126
|
+
if (regex === null || regex === void 0 ? void 0 : regex.test(next)) {
|
|
123
127
|
return this.getSectionRecursive(path, schema.patternProperties[pattern]);
|
|
124
128
|
}
|
|
125
129
|
}
|
|
@@ -185,13 +189,14 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
185
189
|
var curr = toWalk.pop();
|
|
186
190
|
for (var i = 0; i < all.length; i++) {
|
|
187
191
|
var handle = all[i];
|
|
188
|
-
if (handle && (handle.
|
|
189
|
-
if (handle.
|
|
190
|
-
toWalk.push(handle.
|
|
192
|
+
if (handle && (handle.uri === curr || handle.dependencies.has(curr))) {
|
|
193
|
+
if (handle.uri !== curr) {
|
|
194
|
+
toWalk.push(handle.uri);
|
|
195
|
+
}
|
|
196
|
+
if (handle.clearSchema()) {
|
|
197
|
+
hasChanges = true;
|
|
191
198
|
}
|
|
192
|
-
handle.clearSchema();
|
|
193
199
|
all[i] = undefined;
|
|
194
|
-
hasChanges = true;
|
|
195
200
|
}
|
|
196
201
|
}
|
|
197
202
|
}
|
|
@@ -287,7 +292,7 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
287
292
|
return new UnresolvedSchema({}, [localize('json.schema.nocontent', 'Unable to load schema from \'{0}\': {1}.', toDisplayString(url), errorMessage)]);
|
|
288
293
|
});
|
|
289
294
|
};
|
|
290
|
-
JSONSchemaService.prototype.resolveSchemaContent = function (schemaToResolve,
|
|
295
|
+
JSONSchemaService.prototype.resolveSchemaContent = function (schemaToResolve, handle) {
|
|
291
296
|
var _this = this;
|
|
292
297
|
var resolveErrors = schemaToResolve.errors.slice(0);
|
|
293
298
|
var schema = schemaToResolve.schema;
|
|
@@ -299,6 +304,9 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
299
304
|
else if (id === 'https://json-schema.org/draft/2019-09/schema') {
|
|
300
305
|
resolveErrors.push(localize('json.schema.draft201909.notsupported', "Draft 2019-09 schemas are not yet fully supported."));
|
|
301
306
|
}
|
|
307
|
+
else if (id === 'https://json-schema.org/draft/2020-12/schema') {
|
|
308
|
+
resolveErrors.push(localize('json.schema.draft202012.notsupported', "Draft 2020-12 schemas are not yet fully supported."));
|
|
309
|
+
}
|
|
302
310
|
}
|
|
303
311
|
var contextService = this.contextService;
|
|
304
312
|
var findSection = function (schema, path) {
|
|
@@ -316,42 +324,90 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
316
324
|
});
|
|
317
325
|
return current;
|
|
318
326
|
};
|
|
319
|
-
var merge = function (target,
|
|
327
|
+
var merge = function (target, section) {
|
|
328
|
+
for (var key in section) {
|
|
329
|
+
if (section.hasOwnProperty(key) && !target.hasOwnProperty(key)) {
|
|
330
|
+
target[key] = section[key];
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
var mergeByJsonPointer = function (target, sourceRoot, sourceURI, refSegment) {
|
|
320
335
|
var path = refSegment ? decodeURIComponent(refSegment) : undefined;
|
|
321
336
|
var section = findSection(sourceRoot, path);
|
|
322
337
|
if (section) {
|
|
323
|
-
|
|
324
|
-
if (section.hasOwnProperty(key) && !target.hasOwnProperty(key)) {
|
|
325
|
-
target[key] = section[key];
|
|
326
|
-
}
|
|
327
|
-
}
|
|
338
|
+
merge(target, section);
|
|
328
339
|
}
|
|
329
340
|
else {
|
|
330
341
|
resolveErrors.push(localize('json.schema.invalidref', '$ref \'{0}\' in \'{1}\' can not be resolved.', path, sourceURI));
|
|
331
342
|
}
|
|
332
343
|
};
|
|
333
|
-
var
|
|
344
|
+
var isSubSchemaRef = function (refSegment) {
|
|
345
|
+
// Check if the first character is not '/' to determine whether it's a sub schema reference or a JSON Pointer
|
|
346
|
+
return !!refSegment && refSegment.charAt(0) !== '/';
|
|
347
|
+
};
|
|
348
|
+
var reconstructRefURI = function (uri, fragment, separator) {
|
|
349
|
+
if (separator === void 0) { separator = '#'; }
|
|
350
|
+
return normalizeId("" + uri + separator + fragment);
|
|
351
|
+
};
|
|
352
|
+
// To find which $refs point to which $ids we keep two maps:
|
|
353
|
+
// pendingSubSchemas '$id' we expect to encounter (if they exist)
|
|
354
|
+
// handle.anchors for the ones we have encountered
|
|
355
|
+
var pendingSubSchemas = new Map();
|
|
356
|
+
var tryMergeSubSchema = function (target, id, handle) {
|
|
357
|
+
// Get the full URI for the current schema to avoid matching schema1#hello and schema2#hello to the same
|
|
358
|
+
// reference by accident
|
|
359
|
+
var fullId = reconstructRefURI(handle.uri, id);
|
|
360
|
+
var resolved = handle.anchors.get(fullId);
|
|
361
|
+
if (resolved) {
|
|
362
|
+
merge(target, resolved);
|
|
363
|
+
return true; // return success
|
|
364
|
+
}
|
|
365
|
+
// This subschema has not been resolved yet
|
|
366
|
+
// Remember the target to merge later once resolved
|
|
367
|
+
var pending = pendingSubSchemas.get(fullId);
|
|
368
|
+
if (!pending) {
|
|
369
|
+
pending = [];
|
|
370
|
+
pendingSubSchemas.set(fullId, pending);
|
|
371
|
+
}
|
|
372
|
+
pending.push(target);
|
|
373
|
+
return false; // return failure - merge didn't occur
|
|
374
|
+
};
|
|
375
|
+
var resolveExternalLink = function (node, uri, refSegment, parentHandle) {
|
|
334
376
|
if (contextService && !/^[A-Za-z][A-Za-z0-9+\-.+]*:\/\/.*/.test(uri)) {
|
|
335
|
-
uri = contextService.resolveRelativePath(uri,
|
|
377
|
+
uri = contextService.resolveRelativePath(uri, parentHandle.uri);
|
|
336
378
|
}
|
|
337
379
|
uri = normalizeId(uri);
|
|
338
380
|
var referencedHandle = _this.getOrAddSchemaHandle(uri);
|
|
339
381
|
return referencedHandle.getUnresolvedSchema().then(function (unresolvedSchema) {
|
|
340
|
-
|
|
382
|
+
parentHandle.dependencies.add(uri);
|
|
341
383
|
if (unresolvedSchema.errors.length) {
|
|
342
384
|
var loc = refSegment ? uri + '#' + refSegment : uri;
|
|
343
385
|
resolveErrors.push(localize('json.schema.problemloadingref', 'Problems loading reference \'{0}\': {1}', loc, unresolvedSchema.errors[0]));
|
|
344
386
|
}
|
|
345
|
-
|
|
346
|
-
|
|
387
|
+
// A placeholder promise that might execute later a ref resolution for the newly resolved schema
|
|
388
|
+
var externalLinkPromise = Promise.resolve(true);
|
|
389
|
+
if (refSegment === undefined || !isSubSchemaRef(refSegment)) {
|
|
390
|
+
// This is not a sub schema, merge the regular way
|
|
391
|
+
mergeByJsonPointer(node, unresolvedSchema.schema, uri, refSegment);
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
// This is a reference to a subschema
|
|
395
|
+
if (!tryMergeSubSchema(node, refSegment, referencedHandle)) {
|
|
396
|
+
// We weren't able to merge currently so we'll try to resolve this schema first to obtain subschemas
|
|
397
|
+
// that could be missed
|
|
398
|
+
// to improve: it would be enough to find the nodes, no need to resolve the full schema
|
|
399
|
+
externalLinkPromise = resolveRefs(unresolvedSchema.schema, unresolvedSchema.schema, referencedHandle);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return externalLinkPromise.then(function () { return resolveRefs(node, unresolvedSchema.schema, referencedHandle); });
|
|
347
403
|
});
|
|
348
404
|
};
|
|
349
|
-
var resolveRefs = function (node, parentSchema,
|
|
405
|
+
var resolveRefs = function (node, parentSchema, parentHandle) {
|
|
350
406
|
if (!node || typeof node !== 'object') {
|
|
351
407
|
return Promise.resolve(null);
|
|
352
408
|
}
|
|
353
409
|
var toWalk = [node];
|
|
354
|
-
var seen =
|
|
410
|
+
var seen = new Set();
|
|
355
411
|
var openPromises = [];
|
|
356
412
|
var collectEntries = function () {
|
|
357
413
|
var entries = [];
|
|
@@ -401,19 +457,27 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
401
457
|
}
|
|
402
458
|
};
|
|
403
459
|
var handleRef = function (next) {
|
|
404
|
-
var seenRefs =
|
|
460
|
+
var seenRefs = new Set();
|
|
405
461
|
while (next.$ref) {
|
|
406
462
|
var ref = next.$ref;
|
|
407
463
|
var segments = ref.split('#', 2);
|
|
408
464
|
delete next.$ref;
|
|
409
465
|
if (segments[0].length > 0) {
|
|
410
|
-
|
|
466
|
+
// This is a reference to an external schema
|
|
467
|
+
openPromises.push(resolveExternalLink(next, segments[0], segments[1], parentHandle));
|
|
411
468
|
return;
|
|
412
469
|
}
|
|
413
470
|
else {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
471
|
+
// This is a reference inside the current schema
|
|
472
|
+
if (!seenRefs.has(ref)) {
|
|
473
|
+
var id = segments[1];
|
|
474
|
+
if (id !== undefined && isSubSchemaRef(id)) { // A $ref to a sub-schema with an $id (i.e #hello)
|
|
475
|
+
tryMergeSubSchema(next, id, handle);
|
|
476
|
+
}
|
|
477
|
+
else { // A $ref to a JSON Pointer (i.e #/definitions/foo)
|
|
478
|
+
mergeByJsonPointer(next, parentSchema, parentHandle.uri, id); // can set next.$ref again, use seenRefs to avoid circle
|
|
479
|
+
}
|
|
480
|
+
seenRefs.add(ref);
|
|
417
481
|
}
|
|
418
482
|
}
|
|
419
483
|
}
|
|
@@ -421,39 +485,70 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
421
485
|
collectMapEntries(next.definitions, next.properties, next.patternProperties, next.dependencies);
|
|
422
486
|
collectArrayEntries(next.anyOf, next.allOf, next.oneOf, next.items);
|
|
423
487
|
};
|
|
488
|
+
var handleId = function (next) {
|
|
489
|
+
// TODO figure out should loops be preventse
|
|
490
|
+
var id = next.$id || next.id;
|
|
491
|
+
if (typeof id === 'string' && id.charAt(0) === '#') {
|
|
492
|
+
delete next.$id;
|
|
493
|
+
delete next.id;
|
|
494
|
+
// Use a blank separator, as the $id already has the '#'
|
|
495
|
+
var fullId = reconstructRefURI(parentHandle.uri, id, '');
|
|
496
|
+
var resolved = parentHandle.anchors.get(fullId);
|
|
497
|
+
if (!resolved) {
|
|
498
|
+
// it's resolved now
|
|
499
|
+
parentHandle.anchors.set(fullId, next);
|
|
500
|
+
}
|
|
501
|
+
else if (resolved !== next) {
|
|
502
|
+
// Duplicate may occur in recursive $refs, but as long as they are the same object
|
|
503
|
+
// it's ok, otherwise report and error
|
|
504
|
+
resolveErrors.push(localize('json.schema.duplicateid', 'Duplicate id declaration: \'{0}\'', id));
|
|
505
|
+
}
|
|
506
|
+
// Resolve all pending requests and cleanup the queue list
|
|
507
|
+
var pending = pendingSubSchemas.get(fullId);
|
|
508
|
+
if (pending) {
|
|
509
|
+
for (var _i = 0, pending_1 = pending; _i < pending_1.length; _i++) {
|
|
510
|
+
var target = pending_1[_i];
|
|
511
|
+
merge(target, next);
|
|
512
|
+
}
|
|
513
|
+
pendingSubSchemas.delete(fullId);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
};
|
|
424
517
|
while (toWalk.length) {
|
|
425
518
|
var next = toWalk.pop();
|
|
426
|
-
if (seen.
|
|
519
|
+
if (seen.has(next)) {
|
|
427
520
|
continue;
|
|
428
521
|
}
|
|
429
|
-
seen.
|
|
522
|
+
seen.add(next);
|
|
523
|
+
handleId(next);
|
|
430
524
|
handleRef(next);
|
|
431
525
|
}
|
|
432
526
|
return _this.promise.all(openPromises);
|
|
433
527
|
};
|
|
434
|
-
return resolveRefs(schema, schema,
|
|
528
|
+
return resolveRefs(schema, schema, handle).then(function (_) {
|
|
529
|
+
for (var unresolvedSubschemaId in pendingSubSchemas) {
|
|
530
|
+
resolveErrors.push(localize('json.schema.idnotfound', 'Subschema with id \'{0}\' was not found', unresolvedSubschemaId));
|
|
531
|
+
}
|
|
532
|
+
return new ResolvedSchema(schema, resolveErrors);
|
|
533
|
+
});
|
|
435
534
|
};
|
|
436
|
-
JSONSchemaService.prototype.
|
|
437
|
-
|
|
438
|
-
if (
|
|
439
|
-
var
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
schemeId = this.contextService.resolveRelativePath(schemeId, resource);
|
|
446
|
-
}
|
|
447
|
-
if (schemeId) {
|
|
448
|
-
var id = normalizeId(schemeId);
|
|
449
|
-
return this.getOrAddSchemaHandle(id).getResolvedSchema();
|
|
535
|
+
JSONSchemaService.prototype.getSchemaFromProperty = function (resource, document) {
|
|
536
|
+
var _a, _b;
|
|
537
|
+
if (((_a = document.root) === null || _a === void 0 ? void 0 : _a.type) === 'object') {
|
|
538
|
+
for (var _i = 0, _c = document.root.properties; _i < _c.length; _i++) {
|
|
539
|
+
var p = _c[_i];
|
|
540
|
+
if (p.keyNode.value === '$schema' && ((_b = p.valueNode) === null || _b === void 0 ? void 0 : _b.type) === 'string') {
|
|
541
|
+
var schemaId = p.valueNode.value;
|
|
542
|
+
if (this.contextService && !/^\w[\w\d+.-]*:/.test(schemaId)) { // has scheme
|
|
543
|
+
schemaId = this.contextService.resolveRelativePath(schemaId, resource);
|
|
450
544
|
}
|
|
545
|
+
return schemaId;
|
|
451
546
|
}
|
|
452
547
|
}
|
|
453
548
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
549
|
+
return undefined;
|
|
550
|
+
};
|
|
551
|
+
JSONSchemaService.prototype.getAssociatedSchemas = function (resource) {
|
|
457
552
|
var seen = Object.create(null);
|
|
458
553
|
var schemas = [];
|
|
459
554
|
var normalizedResource = normalizeResourceForMatching(resource);
|
|
@@ -469,6 +564,28 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
469
564
|
}
|
|
470
565
|
}
|
|
471
566
|
}
|
|
567
|
+
return schemas;
|
|
568
|
+
};
|
|
569
|
+
JSONSchemaService.prototype.getSchemaURIsForResource = function (resource, document) {
|
|
570
|
+
var schemeId = document && this.getSchemaFromProperty(resource, document);
|
|
571
|
+
if (schemeId) {
|
|
572
|
+
return [schemeId];
|
|
573
|
+
}
|
|
574
|
+
return this.getAssociatedSchemas(resource);
|
|
575
|
+
};
|
|
576
|
+
JSONSchemaService.prototype.getSchemaForResource = function (resource, document) {
|
|
577
|
+
if (document) {
|
|
578
|
+
// first use $schema if present
|
|
579
|
+
var schemeId = this.getSchemaFromProperty(resource, document);
|
|
580
|
+
if (schemeId) {
|
|
581
|
+
var id = normalizeId(schemeId);
|
|
582
|
+
return this.getOrAddSchemaHandle(id).getResolvedSchema();
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (this.cachedSchemaForResource && this.cachedSchemaForResource.resource === resource) {
|
|
586
|
+
return this.cachedSchemaForResource.resolvedSchema;
|
|
587
|
+
}
|
|
588
|
+
var schemas = this.getAssociatedSchemas(resource);
|
|
472
589
|
var resolvedSchema = schemas.length > 0 ? this.createCombinedSchema(resource, schemas).getResolvedSchema() : this.promise.resolve(undefined);
|
|
473
590
|
this.cachedSchemaForResource = { resource: resource, resolvedSchema: resolvedSchema };
|
|
474
591
|
return resolvedSchema;
|
|
@@ -488,7 +605,8 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
488
605
|
JSONSchemaService.prototype.getMatchingSchemas = function (document, jsonDocument, schema) {
|
|
489
606
|
if (schema) {
|
|
490
607
|
var id = schema.id || ('schemaservice://untitled/matchingSchemas/' + idCounter++);
|
|
491
|
-
|
|
608
|
+
var handle = this.addSchemaHandle(id, schema);
|
|
609
|
+
return handle.getResolvedSchema().then(function (resolvedSchema) {
|
|
492
610
|
return jsonDocument.getMatchingSchemas(resolvedSchema.schema).filter(function (s) { return !s.inverted; });
|
|
493
611
|
});
|
|
494
612
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { UnresolvedSchema } from './jsonSchemaService';
|
|
6
5
|
import { ErrorCode, Diagnostic, DiagnosticSeverity, Range } from '../jsonLanguageTypes';
|
|
7
6
|
import * as nls from 'vscode-nls';
|
|
8
7
|
import { isBoolean } from '../utils/objects';
|
|
@@ -86,7 +85,8 @@ var JSONValidation = /** @class */ (function () {
|
|
|
86
85
|
};
|
|
87
86
|
if (schema) {
|
|
88
87
|
var id = schema.id || ('schemaservice://untitled/' + idCounter++);
|
|
89
|
-
|
|
88
|
+
var handle = this.jsonSchemaService.registerExternalSchema(id, [], schema);
|
|
89
|
+
return handle.getResolvedSchema().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, 'u');
|
|
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.
|
|
@@ -40,7 +40,10 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
40
40
|
'date-time': { errorMessage: localize('dateTimeFormatWarning', 'String is not a RFC3339 date-time.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)([01][0-9]|2[0-3]):([0-5][0-9]))$/i },
|
|
41
41
|
'date': { errorMessage: localize('dateFormatWarning', 'String is not a RFC3339 date.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/i },
|
|
42
42
|
'time': { errorMessage: localize('timeFormatWarning', 'String is not a RFC3339 time.'), pattern: /^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)([01][0-9]|2[0-3]):([0-5][0-9]))$/i },
|
|
43
|
-
'email': { errorMessage: localize('emailFormatWarning', 'String is not an e-mail address.'), pattern: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-
|
|
43
|
+
'email': { errorMessage: localize('emailFormatWarning', 'String is not an e-mail address.'), pattern: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}))$/ },
|
|
44
|
+
'hostname': { errorMessage: localize('hostnameFormatWarning', 'String is not a hostname.'), pattern: /^(?=.{1,253}\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\.?$/i },
|
|
45
|
+
'ipv4': { errorMessage: localize('ipv4FormatWarning', 'String is not an IPv4 address.'), pattern: /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/ },
|
|
46
|
+
'ipv6': { errorMessage: localize('ipv6FormatWarning', 'String is not an IPv6 address.'), pattern: /^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i },
|
|
44
47
|
};
|
|
45
48
|
var ASTNodeImpl = /** @class */ (function () {
|
|
46
49
|
function ASTNodeImpl(parent, offset, length) {
|
|
@@ -634,7 +637,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
634
637
|
}
|
|
635
638
|
if (objects_1.isString(schema.pattern)) {
|
|
636
639
|
var regex = strings_1.extendedRegExp(schema.pattern);
|
|
637
|
-
if (!regex.test(node.value)) {
|
|
640
|
+
if (!(regex === null || regex === void 0 ? void 0 : regex.test(node.value))) {
|
|
638
641
|
validationResult.problems.push({
|
|
639
642
|
location: { offset: node.offset, length: node.length },
|
|
640
643
|
message: schema.patternErrorMessage || schema.errorMessage || localize('patternWarning', 'String does not match the pattern of "{0}".', schema.pattern)
|
|
@@ -672,6 +675,9 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
672
675
|
case 'date':
|
|
673
676
|
case 'time':
|
|
674
677
|
case 'email':
|
|
678
|
+
case 'hostname':
|
|
679
|
+
case 'ipv4':
|
|
680
|
+
case 'ipv6':
|
|
675
681
|
var format = formats[schema.format];
|
|
676
682
|
if (!node.value || !format.pattern.exec(node.value)) {
|
|
677
683
|
validationResult.problems.push({
|
|
@@ -828,7 +834,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
828
834
|
var regex = strings_1.extendedRegExp(propertyPattern);
|
|
829
835
|
for (var _h = 0, _j = unprocessedProperties.slice(0); _h < _j.length; _h++) {
|
|
830
836
|
var propertyName = _j[_h];
|
|
831
|
-
if (regex.test(propertyName)) {
|
|
837
|
+
if (regex === null || regex === void 0 ? void 0 : regex.test(propertyName)) {
|
|
832
838
|
propertyProcessed(propertyName);
|
|
833
839
|
var child = seenKeys[propertyName];
|
|
834
840
|
if (child) {
|
|
@@ -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,18 @@
|
|
|
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
|
+
this.anchors = new Map();
|
|
74
75
|
if (unresolvedSchemaContent) {
|
|
75
76
|
this.unresolvedSchema = this.service.promise.resolve(new UnresolvedSchema(unresolvedSchemaContent));
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
79
|
SchemaHandle.prototype.getUnresolvedSchema = function () {
|
|
79
80
|
if (!this.unresolvedSchema) {
|
|
80
|
-
this.unresolvedSchema = this.service.loadSchema(this.
|
|
81
|
+
this.unresolvedSchema = this.service.loadSchema(this.uri);
|
|
81
82
|
}
|
|
82
83
|
return this.unresolvedSchema;
|
|
83
84
|
};
|
|
@@ -85,15 +86,18 @@
|
|
|
85
86
|
var _this = this;
|
|
86
87
|
if (!this.resolvedSchema) {
|
|
87
88
|
this.resolvedSchema = this.getUnresolvedSchema().then(function (unresolved) {
|
|
88
|
-
return _this.service.resolveSchemaContent(unresolved, _this
|
|
89
|
+
return _this.service.resolveSchemaContent(unresolved, _this);
|
|
89
90
|
});
|
|
90
91
|
}
|
|
91
92
|
return this.resolvedSchema;
|
|
92
93
|
};
|
|
93
94
|
SchemaHandle.prototype.clearSchema = function () {
|
|
95
|
+
var hasChanges = !!this.unresolvedSchema;
|
|
94
96
|
this.resolvedSchema = undefined;
|
|
95
97
|
this.unresolvedSchema = undefined;
|
|
96
|
-
this.dependencies
|
|
98
|
+
this.dependencies.clear();
|
|
99
|
+
this.anchors.clear();
|
|
100
|
+
return hasChanges;
|
|
97
101
|
};
|
|
98
102
|
return SchemaHandle;
|
|
99
103
|
}());
|
|
@@ -131,7 +135,7 @@
|
|
|
131
135
|
for (var _i = 0, _a = Object.keys(schema.patternProperties); _i < _a.length; _i++) {
|
|
132
136
|
var pattern = _a[_i];
|
|
133
137
|
var regex = Strings.extendedRegExp(pattern);
|
|
134
|
-
if (regex.test(next)) {
|
|
138
|
+
if (regex === null || regex === void 0 ? void 0 : regex.test(next)) {
|
|
135
139
|
return this.getSectionRecursive(path, schema.patternProperties[pattern]);
|
|
136
140
|
}
|
|
137
141
|
}
|
|
@@ -197,13 +201,14 @@
|
|
|
197
201
|
var curr = toWalk.pop();
|
|
198
202
|
for (var i = 0; i < all.length; i++) {
|
|
199
203
|
var handle = all[i];
|
|
200
|
-
if (handle && (handle.
|
|
201
|
-
if (handle.
|
|
202
|
-
toWalk.push(handle.
|
|
204
|
+
if (handle && (handle.uri === curr || handle.dependencies.has(curr))) {
|
|
205
|
+
if (handle.uri !== curr) {
|
|
206
|
+
toWalk.push(handle.uri);
|
|
207
|
+
}
|
|
208
|
+
if (handle.clearSchema()) {
|
|
209
|
+
hasChanges = true;
|
|
203
210
|
}
|
|
204
|
-
handle.clearSchema();
|
|
205
211
|
all[i] = undefined;
|
|
206
|
-
hasChanges = true;
|
|
207
212
|
}
|
|
208
213
|
}
|
|
209
214
|
}
|
|
@@ -299,7 +304,7 @@
|
|
|
299
304
|
return new UnresolvedSchema({}, [localize('json.schema.nocontent', 'Unable to load schema from \'{0}\': {1}.', toDisplayString(url), errorMessage)]);
|
|
300
305
|
});
|
|
301
306
|
};
|
|
302
|
-
JSONSchemaService.prototype.resolveSchemaContent = function (schemaToResolve,
|
|
307
|
+
JSONSchemaService.prototype.resolveSchemaContent = function (schemaToResolve, handle) {
|
|
303
308
|
var _this = this;
|
|
304
309
|
var resolveErrors = schemaToResolve.errors.slice(0);
|
|
305
310
|
var schema = schemaToResolve.schema;
|
|
@@ -311,6 +316,9 @@
|
|
|
311
316
|
else if (id === 'https://json-schema.org/draft/2019-09/schema') {
|
|
312
317
|
resolveErrors.push(localize('json.schema.draft201909.notsupported', "Draft 2019-09 schemas are not yet fully supported."));
|
|
313
318
|
}
|
|
319
|
+
else if (id === 'https://json-schema.org/draft/2020-12/schema') {
|
|
320
|
+
resolveErrors.push(localize('json.schema.draft202012.notsupported', "Draft 2020-12 schemas are not yet fully supported."));
|
|
321
|
+
}
|
|
314
322
|
}
|
|
315
323
|
var contextService = this.contextService;
|
|
316
324
|
var findSection = function (schema, path) {
|
|
@@ -328,42 +336,90 @@
|
|
|
328
336
|
});
|
|
329
337
|
return current;
|
|
330
338
|
};
|
|
331
|
-
var merge = function (target,
|
|
339
|
+
var merge = function (target, section) {
|
|
340
|
+
for (var key in section) {
|
|
341
|
+
if (section.hasOwnProperty(key) && !target.hasOwnProperty(key)) {
|
|
342
|
+
target[key] = section[key];
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
var mergeByJsonPointer = function (target, sourceRoot, sourceURI, refSegment) {
|
|
332
347
|
var path = refSegment ? decodeURIComponent(refSegment) : undefined;
|
|
333
348
|
var section = findSection(sourceRoot, path);
|
|
334
349
|
if (section) {
|
|
335
|
-
|
|
336
|
-
if (section.hasOwnProperty(key) && !target.hasOwnProperty(key)) {
|
|
337
|
-
target[key] = section[key];
|
|
338
|
-
}
|
|
339
|
-
}
|
|
350
|
+
merge(target, section);
|
|
340
351
|
}
|
|
341
352
|
else {
|
|
342
353
|
resolveErrors.push(localize('json.schema.invalidref', '$ref \'{0}\' in \'{1}\' can not be resolved.', path, sourceURI));
|
|
343
354
|
}
|
|
344
355
|
};
|
|
345
|
-
var
|
|
356
|
+
var isSubSchemaRef = function (refSegment) {
|
|
357
|
+
// Check if the first character is not '/' to determine whether it's a sub schema reference or a JSON Pointer
|
|
358
|
+
return !!refSegment && refSegment.charAt(0) !== '/';
|
|
359
|
+
};
|
|
360
|
+
var reconstructRefURI = function (uri, fragment, separator) {
|
|
361
|
+
if (separator === void 0) { separator = '#'; }
|
|
362
|
+
return normalizeId("" + uri + separator + fragment);
|
|
363
|
+
};
|
|
364
|
+
// To find which $refs point to which $ids we keep two maps:
|
|
365
|
+
// pendingSubSchemas '$id' we expect to encounter (if they exist)
|
|
366
|
+
// handle.anchors for the ones we have encountered
|
|
367
|
+
var pendingSubSchemas = new Map();
|
|
368
|
+
var tryMergeSubSchema = function (target, id, handle) {
|
|
369
|
+
// Get the full URI for the current schema to avoid matching schema1#hello and schema2#hello to the same
|
|
370
|
+
// reference by accident
|
|
371
|
+
var fullId = reconstructRefURI(handle.uri, id);
|
|
372
|
+
var resolved = handle.anchors.get(fullId);
|
|
373
|
+
if (resolved) {
|
|
374
|
+
merge(target, resolved);
|
|
375
|
+
return true; // return success
|
|
376
|
+
}
|
|
377
|
+
// This subschema has not been resolved yet
|
|
378
|
+
// Remember the target to merge later once resolved
|
|
379
|
+
var pending = pendingSubSchemas.get(fullId);
|
|
380
|
+
if (!pending) {
|
|
381
|
+
pending = [];
|
|
382
|
+
pendingSubSchemas.set(fullId, pending);
|
|
383
|
+
}
|
|
384
|
+
pending.push(target);
|
|
385
|
+
return false; // return failure - merge didn't occur
|
|
386
|
+
};
|
|
387
|
+
var resolveExternalLink = function (node, uri, refSegment, parentHandle) {
|
|
346
388
|
if (contextService && !/^[A-Za-z][A-Za-z0-9+\-.+]*:\/\/.*/.test(uri)) {
|
|
347
|
-
uri = contextService.resolveRelativePath(uri,
|
|
389
|
+
uri = contextService.resolveRelativePath(uri, parentHandle.uri);
|
|
348
390
|
}
|
|
349
391
|
uri = normalizeId(uri);
|
|
350
392
|
var referencedHandle = _this.getOrAddSchemaHandle(uri);
|
|
351
393
|
return referencedHandle.getUnresolvedSchema().then(function (unresolvedSchema) {
|
|
352
|
-
|
|
394
|
+
parentHandle.dependencies.add(uri);
|
|
353
395
|
if (unresolvedSchema.errors.length) {
|
|
354
396
|
var loc = refSegment ? uri + '#' + refSegment : uri;
|
|
355
397
|
resolveErrors.push(localize('json.schema.problemloadingref', 'Problems loading reference \'{0}\': {1}', loc, unresolvedSchema.errors[0]));
|
|
356
398
|
}
|
|
357
|
-
|
|
358
|
-
|
|
399
|
+
// A placeholder promise that might execute later a ref resolution for the newly resolved schema
|
|
400
|
+
var externalLinkPromise = Promise.resolve(true);
|
|
401
|
+
if (refSegment === undefined || !isSubSchemaRef(refSegment)) {
|
|
402
|
+
// This is not a sub schema, merge the regular way
|
|
403
|
+
mergeByJsonPointer(node, unresolvedSchema.schema, uri, refSegment);
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
// This is a reference to a subschema
|
|
407
|
+
if (!tryMergeSubSchema(node, refSegment, referencedHandle)) {
|
|
408
|
+
// We weren't able to merge currently so we'll try to resolve this schema first to obtain subschemas
|
|
409
|
+
// that could be missed
|
|
410
|
+
// to improve: it would be enough to find the nodes, no need to resolve the full schema
|
|
411
|
+
externalLinkPromise = resolveRefs(unresolvedSchema.schema, unresolvedSchema.schema, referencedHandle);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return externalLinkPromise.then(function () { return resolveRefs(node, unresolvedSchema.schema, referencedHandle); });
|
|
359
415
|
});
|
|
360
416
|
};
|
|
361
|
-
var resolveRefs = function (node, parentSchema,
|
|
417
|
+
var resolveRefs = function (node, parentSchema, parentHandle) {
|
|
362
418
|
if (!node || typeof node !== 'object') {
|
|
363
419
|
return Promise.resolve(null);
|
|
364
420
|
}
|
|
365
421
|
var toWalk = [node];
|
|
366
|
-
var seen =
|
|
422
|
+
var seen = new Set();
|
|
367
423
|
var openPromises = [];
|
|
368
424
|
var collectEntries = function () {
|
|
369
425
|
var entries = [];
|
|
@@ -413,19 +469,27 @@
|
|
|
413
469
|
}
|
|
414
470
|
};
|
|
415
471
|
var handleRef = function (next) {
|
|
416
|
-
var seenRefs =
|
|
472
|
+
var seenRefs = new Set();
|
|
417
473
|
while (next.$ref) {
|
|
418
474
|
var ref = next.$ref;
|
|
419
475
|
var segments = ref.split('#', 2);
|
|
420
476
|
delete next.$ref;
|
|
421
477
|
if (segments[0].length > 0) {
|
|
422
|
-
|
|
478
|
+
// This is a reference to an external schema
|
|
479
|
+
openPromises.push(resolveExternalLink(next, segments[0], segments[1], parentHandle));
|
|
423
480
|
return;
|
|
424
481
|
}
|
|
425
482
|
else {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
483
|
+
// This is a reference inside the current schema
|
|
484
|
+
if (!seenRefs.has(ref)) {
|
|
485
|
+
var id = segments[1];
|
|
486
|
+
if (id !== undefined && isSubSchemaRef(id)) { // A $ref to a sub-schema with an $id (i.e #hello)
|
|
487
|
+
tryMergeSubSchema(next, id, handle);
|
|
488
|
+
}
|
|
489
|
+
else { // A $ref to a JSON Pointer (i.e #/definitions/foo)
|
|
490
|
+
mergeByJsonPointer(next, parentSchema, parentHandle.uri, id); // can set next.$ref again, use seenRefs to avoid circle
|
|
491
|
+
}
|
|
492
|
+
seenRefs.add(ref);
|
|
429
493
|
}
|
|
430
494
|
}
|
|
431
495
|
}
|
|
@@ -433,39 +497,70 @@
|
|
|
433
497
|
collectMapEntries(next.definitions, next.properties, next.patternProperties, next.dependencies);
|
|
434
498
|
collectArrayEntries(next.anyOf, next.allOf, next.oneOf, next.items);
|
|
435
499
|
};
|
|
500
|
+
var handleId = function (next) {
|
|
501
|
+
// TODO figure out should loops be preventse
|
|
502
|
+
var id = next.$id || next.id;
|
|
503
|
+
if (typeof id === 'string' && id.charAt(0) === '#') {
|
|
504
|
+
delete next.$id;
|
|
505
|
+
delete next.id;
|
|
506
|
+
// Use a blank separator, as the $id already has the '#'
|
|
507
|
+
var fullId = reconstructRefURI(parentHandle.uri, id, '');
|
|
508
|
+
var resolved = parentHandle.anchors.get(fullId);
|
|
509
|
+
if (!resolved) {
|
|
510
|
+
// it's resolved now
|
|
511
|
+
parentHandle.anchors.set(fullId, next);
|
|
512
|
+
}
|
|
513
|
+
else if (resolved !== next) {
|
|
514
|
+
// Duplicate may occur in recursive $refs, but as long as they are the same object
|
|
515
|
+
// it's ok, otherwise report and error
|
|
516
|
+
resolveErrors.push(localize('json.schema.duplicateid', 'Duplicate id declaration: \'{0}\'', id));
|
|
517
|
+
}
|
|
518
|
+
// Resolve all pending requests and cleanup the queue list
|
|
519
|
+
var pending = pendingSubSchemas.get(fullId);
|
|
520
|
+
if (pending) {
|
|
521
|
+
for (var _i = 0, pending_1 = pending; _i < pending_1.length; _i++) {
|
|
522
|
+
var target = pending_1[_i];
|
|
523
|
+
merge(target, next);
|
|
524
|
+
}
|
|
525
|
+
pendingSubSchemas.delete(fullId);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
};
|
|
436
529
|
while (toWalk.length) {
|
|
437
530
|
var next = toWalk.pop();
|
|
438
|
-
if (seen.
|
|
531
|
+
if (seen.has(next)) {
|
|
439
532
|
continue;
|
|
440
533
|
}
|
|
441
|
-
seen.
|
|
534
|
+
seen.add(next);
|
|
535
|
+
handleId(next);
|
|
442
536
|
handleRef(next);
|
|
443
537
|
}
|
|
444
538
|
return _this.promise.all(openPromises);
|
|
445
539
|
};
|
|
446
|
-
return resolveRefs(schema, schema,
|
|
540
|
+
return resolveRefs(schema, schema, handle).then(function (_) {
|
|
541
|
+
for (var unresolvedSubschemaId in pendingSubSchemas) {
|
|
542
|
+
resolveErrors.push(localize('json.schema.idnotfound', 'Subschema with id \'{0}\' was not found', unresolvedSubschemaId));
|
|
543
|
+
}
|
|
544
|
+
return new ResolvedSchema(schema, resolveErrors);
|
|
545
|
+
});
|
|
447
546
|
};
|
|
448
|
-
JSONSchemaService.prototype.
|
|
449
|
-
|
|
450
|
-
if (
|
|
451
|
-
var
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
schemeId = this.contextService.resolveRelativePath(schemeId, resource);
|
|
458
|
-
}
|
|
459
|
-
if (schemeId) {
|
|
460
|
-
var id = normalizeId(schemeId);
|
|
461
|
-
return this.getOrAddSchemaHandle(id).getResolvedSchema();
|
|
547
|
+
JSONSchemaService.prototype.getSchemaFromProperty = function (resource, document) {
|
|
548
|
+
var _a, _b;
|
|
549
|
+
if (((_a = document.root) === null || _a === void 0 ? void 0 : _a.type) === 'object') {
|
|
550
|
+
for (var _i = 0, _c = document.root.properties; _i < _c.length; _i++) {
|
|
551
|
+
var p = _c[_i];
|
|
552
|
+
if (p.keyNode.value === '$schema' && ((_b = p.valueNode) === null || _b === void 0 ? void 0 : _b.type) === 'string') {
|
|
553
|
+
var schemaId = p.valueNode.value;
|
|
554
|
+
if (this.contextService && !/^\w[\w\d+.-]*:/.test(schemaId)) { // has scheme
|
|
555
|
+
schemaId = this.contextService.resolveRelativePath(schemaId, resource);
|
|
462
556
|
}
|
|
557
|
+
return schemaId;
|
|
463
558
|
}
|
|
464
559
|
}
|
|
465
560
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
561
|
+
return undefined;
|
|
562
|
+
};
|
|
563
|
+
JSONSchemaService.prototype.getAssociatedSchemas = function (resource) {
|
|
469
564
|
var seen = Object.create(null);
|
|
470
565
|
var schemas = [];
|
|
471
566
|
var normalizedResource = normalizeResourceForMatching(resource);
|
|
@@ -481,6 +576,28 @@
|
|
|
481
576
|
}
|
|
482
577
|
}
|
|
483
578
|
}
|
|
579
|
+
return schemas;
|
|
580
|
+
};
|
|
581
|
+
JSONSchemaService.prototype.getSchemaURIsForResource = function (resource, document) {
|
|
582
|
+
var schemeId = document && this.getSchemaFromProperty(resource, document);
|
|
583
|
+
if (schemeId) {
|
|
584
|
+
return [schemeId];
|
|
585
|
+
}
|
|
586
|
+
return this.getAssociatedSchemas(resource);
|
|
587
|
+
};
|
|
588
|
+
JSONSchemaService.prototype.getSchemaForResource = function (resource, document) {
|
|
589
|
+
if (document) {
|
|
590
|
+
// first use $schema if present
|
|
591
|
+
var schemeId = this.getSchemaFromProperty(resource, document);
|
|
592
|
+
if (schemeId) {
|
|
593
|
+
var id = normalizeId(schemeId);
|
|
594
|
+
return this.getOrAddSchemaHandle(id).getResolvedSchema();
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (this.cachedSchemaForResource && this.cachedSchemaForResource.resource === resource) {
|
|
598
|
+
return this.cachedSchemaForResource.resolvedSchema;
|
|
599
|
+
}
|
|
600
|
+
var schemas = this.getAssociatedSchemas(resource);
|
|
484
601
|
var resolvedSchema = schemas.length > 0 ? this.createCombinedSchema(resource, schemas).getResolvedSchema() : this.promise.resolve(undefined);
|
|
485
602
|
this.cachedSchemaForResource = { resource: resource, resolvedSchema: resolvedSchema };
|
|
486
603
|
return resolvedSchema;
|
|
@@ -500,7 +617,8 @@
|
|
|
500
617
|
JSONSchemaService.prototype.getMatchingSchemas = function (document, jsonDocument, schema) {
|
|
501
618
|
if (schema) {
|
|
502
619
|
var id = schema.id || ('schemaservice://untitled/matchingSchemas/' + idCounter++);
|
|
503
|
-
|
|
620
|
+
var handle = this.addSchemaHandle(id, schema);
|
|
621
|
+
return handle.getResolvedSchema().then(function (resolvedSchema) {
|
|
504
622
|
return jsonDocument.getMatchingSchemas(resolvedSchema.schema).filter(function (s) { return !s.inverted; });
|
|
505
623
|
});
|
|
506
624
|
}
|
|
@@ -8,13 +8,12 @@
|
|
|
8
8
|
if (v !== undefined) module.exports = v;
|
|
9
9
|
}
|
|
10
10
|
else if (typeof define === "function" && define.amd) {
|
|
11
|
-
define(["require", "exports", "
|
|
11
|
+
define(["require", "exports", "../jsonLanguageTypes", "vscode-nls", "../utils/objects"], factory);
|
|
12
12
|
}
|
|
13
13
|
})(function (require, exports) {
|
|
14
14
|
"use strict";
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.JSONValidation = void 0;
|
|
17
|
-
var jsonSchemaService_1 = require("./jsonSchemaService");
|
|
18
17
|
var jsonLanguageTypes_1 = require("../jsonLanguageTypes");
|
|
19
18
|
var nls = require("vscode-nls");
|
|
20
19
|
var objects_1 = require("../utils/objects");
|
|
@@ -98,7 +97,8 @@
|
|
|
98
97
|
};
|
|
99
98
|
if (schema) {
|
|
100
99
|
var id = schema.id || ('schemaservice://untitled/' + idCounter++);
|
|
101
|
-
|
|
100
|
+
var handle = this.jsonSchemaService.registerExternalSchema(id, [], schema);
|
|
101
|
+
return handle.getResolvedSchema().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, 'u');
|
|
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.2",
|
|
4
4
|
"description": "Language service for JSON",
|
|
5
5
|
"main": "./lib/umd/jsonLanguageService.js",
|
|
6
6
|
"typings": "./lib/umd/jsonLanguageService",
|
|
@@ -14,9 +14,6 @@
|
|
|
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
18
|
"@types/mocha": "^9.0.0",
|
|
22
19
|
"@types/node": "^10.12.21",
|