vscode-json-languageservice 4.1.10 → 4.2.0-next.3
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 +7 -1
- package/lib/esm/services/configuration.js +1 -1
- package/lib/esm/services/jsonCompletion.js +2 -2
- package/lib/esm/services/jsonDocumentSymbols.js +3 -3
- package/lib/esm/services/jsonHover.js +1 -1
- package/lib/esm/services/jsonLinks.js +1 -1
- package/lib/esm/services/jsonSchemaService.js +189 -119
- package/lib/esm/services/jsonValidation.js +5 -2
- package/lib/umd/jsonLanguageService.d.ts +2 -1
- package/lib/umd/jsonLanguageService.js +4 -3
- package/lib/umd/jsonLanguageTypes.d.ts +3 -0
- package/lib/umd/parser/jsonParser.js +31 -25
- package/lib/umd/services/configuration.js +1 -1
- package/lib/umd/services/jsonCompletion.js +12 -12
- package/lib/umd/services/jsonDocumentSymbols.js +4 -4
- package/lib/umd/services/jsonFolding.js +1 -1
- package/lib/umd/services/jsonHover.js +1 -1
- package/lib/umd/services/jsonLinks.js +1 -1
- package/lib/umd/services/jsonSchemaService.js +190 -120
- package/lib/umd/services/jsonSelectionRanges.js +1 -1
- package/lib/umd/services/jsonValidation.js +11 -8
- package/package.json +9 -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.
|
|
@@ -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) {
|
|
@@ -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({
|
|
@@ -522,7 +522,7 @@ for (var schemaName in schemaContributions.schemas) {
|
|
|
522
522
|
propertyObject['description'] = description;
|
|
523
523
|
}
|
|
524
524
|
else {
|
|
525
|
-
console.log(property
|
|
525
|
+
console.log("".concat(property, ": localize('schema.json.").concat(property, "', \"\")"));
|
|
526
526
|
}
|
|
527
527
|
}
|
|
528
528
|
}
|
|
@@ -218,7 +218,7 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
218
218
|
if (propertySchema.suggestSortText !== undefined) {
|
|
219
219
|
proposal.sortText = propertySchema.suggestSortText;
|
|
220
220
|
}
|
|
221
|
-
if (proposal.insertText && endsWith(proposal.insertText, "$1"
|
|
221
|
+
if (proposal.insertText && endsWith(proposal.insertText, "$1".concat(separatorAfter))) {
|
|
222
222
|
proposal.command = {
|
|
223
223
|
title: 'Suggest',
|
|
224
224
|
command: 'editor.action.triggerSuggest'
|
|
@@ -243,7 +243,7 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
243
243
|
if (schemaPropertyNames_1.suggestSortText !== undefined) {
|
|
244
244
|
proposal.sortText = schemaPropertyNames_1.suggestSortText;
|
|
245
245
|
}
|
|
246
|
-
if (proposal.insertText && endsWith(proposal.insertText, "$1"
|
|
246
|
+
if (proposal.insertText && endsWith(proposal.insertText, "$1".concat(separatorAfter))) {
|
|
247
247
|
proposal.command = {
|
|
248
248
|
title: 'Suggest',
|
|
249
249
|
command: 'editor.action.triggerSuggest'
|
|
@@ -202,7 +202,7 @@ var JSONDocumentSymbols = /** @class */ (function () {
|
|
|
202
202
|
if (name && name.trim()) {
|
|
203
203
|
return name;
|
|
204
204
|
}
|
|
205
|
-
return "\""
|
|
205
|
+
return "\"".concat(name, "\"");
|
|
206
206
|
};
|
|
207
207
|
JSONDocumentSymbols.prototype.getDetail = function (node) {
|
|
208
208
|
if (!node) {
|
|
@@ -262,10 +262,10 @@ var JSONDocumentSymbols = /** @class */ (function () {
|
|
|
262
262
|
}
|
|
263
263
|
var label;
|
|
264
264
|
if (color.alpha === 1) {
|
|
265
|
-
label = "#"
|
|
265
|
+
label = "#".concat(toTwoDigitHex(red256)).concat(toTwoDigitHex(green256)).concat(toTwoDigitHex(blue256));
|
|
266
266
|
}
|
|
267
267
|
else {
|
|
268
|
-
label = "#"
|
|
268
|
+
label = "#".concat(toTwoDigitHex(red256)).concat(toTwoDigitHex(green256)).concat(toTwoDigitHex(blue256)).concat(toTwoDigitHex(Math.round(color.alpha * 255)));
|
|
269
269
|
}
|
|
270
270
|
result.push({ label: label, textEdit: TextEdit.replace(range, JSON.stringify(label)) });
|
|
271
271
|
return result;
|
|
@@ -86,7 +86,7 @@ var JSONHover = /** @class */ (function () {
|
|
|
86
86
|
if (result.length > 0) {
|
|
87
87
|
result += "\n\n";
|
|
88
88
|
}
|
|
89
|
-
result += "`"
|
|
89
|
+
result += "`".concat(toMarkdownCodeBlock(enumValue_1), "`: ").concat(markdownEnumValueDescription_1);
|
|
90
90
|
}
|
|
91
91
|
return createHover([result]);
|
|
92
92
|
}
|
|
@@ -13,7 +13,7 @@ export function findLinks(document, doc) {
|
|
|
13
13
|
if (targetNode) {
|
|
14
14
|
var targetPos = document.positionAt(targetNode.offset);
|
|
15
15
|
links.push({
|
|
16
|
-
target: document.uri
|
|
16
|
+
target: "".concat(document.uri, "#").concat(targetPos.line + 1, ",").concat(targetPos.character + 1),
|
|
17
17
|
range: createRange(document, node.valueNode)
|
|
18
18
|
});
|
|
19
19
|
}
|
|
@@ -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 = undefined;
|
|
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 = undefined;
|
|
88
|
+
return hasChanges;
|
|
85
89
|
};
|
|
86
90
|
return SchemaHandle;
|
|
87
91
|
}());
|
|
@@ -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,15 +304,16 @@ 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
|
-
var
|
|
305
|
-
|
|
306
|
-
return schema;
|
|
307
|
-
}
|
|
312
|
+
var findSectionByJSONPointer = function (schema, path) {
|
|
313
|
+
path = decodeURIComponent(path);
|
|
308
314
|
var current = schema;
|
|
309
315
|
if (path[0] === '/') {
|
|
310
|
-
path = path.
|
|
316
|
+
path = path.substring(1);
|
|
311
317
|
}
|
|
312
318
|
path.split('/').some(function (part) {
|
|
313
319
|
part = part.replace(/~1/g, '/').replace(/~0/g, '~');
|
|
@@ -316,144 +322,185 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
316
322
|
});
|
|
317
323
|
return current;
|
|
318
324
|
};
|
|
319
|
-
var
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
325
|
+
var findSchemaById = function (schema, handle, id) {
|
|
326
|
+
if (!handle.anchors) {
|
|
327
|
+
handle.anchors = collectAnchors(schema);
|
|
328
|
+
}
|
|
329
|
+
return handle.anchors.get(id);
|
|
330
|
+
};
|
|
331
|
+
var merge = function (target, section) {
|
|
332
|
+
for (var key in section) {
|
|
333
|
+
if (section.hasOwnProperty(key) && !target.hasOwnProperty(key) && key !== 'id' && key !== '$id') {
|
|
334
|
+
target[key] = section[key];
|
|
327
335
|
}
|
|
328
336
|
}
|
|
337
|
+
};
|
|
338
|
+
var mergeRef = function (target, sourceRoot, sourceHandle, refSegment) {
|
|
339
|
+
var section;
|
|
340
|
+
if (refSegment === undefined) {
|
|
341
|
+
section = sourceRoot;
|
|
342
|
+
}
|
|
343
|
+
else if (refSegment.charAt(0) === '/') {
|
|
344
|
+
// A $ref to a JSON Pointer (i.e #/definitions/foo)
|
|
345
|
+
section = findSectionByJSONPointer(sourceRoot, refSegment);
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
// A $ref to a sub-schema with an $id (i.e #hello)
|
|
349
|
+
section = findSchemaById(sourceRoot, sourceHandle, refSegment);
|
|
350
|
+
}
|
|
351
|
+
if (section) {
|
|
352
|
+
merge(target, section);
|
|
353
|
+
}
|
|
329
354
|
else {
|
|
330
|
-
resolveErrors.push(localize('json.schema.
|
|
355
|
+
resolveErrors.push(localize('json.schema.invalidid', '$ref \'{0}\' in \'{1}\' can not be resolved.', refSegment, sourceHandle.uri));
|
|
331
356
|
}
|
|
332
357
|
};
|
|
333
|
-
var resolveExternalLink = function (node, uri, refSegment,
|
|
358
|
+
var resolveExternalLink = function (node, uri, refSegment, parentHandle) {
|
|
334
359
|
if (contextService && !/^[A-Za-z][A-Za-z0-9+\-.+]*:\/\/.*/.test(uri)) {
|
|
335
|
-
uri = contextService.resolveRelativePath(uri,
|
|
360
|
+
uri = contextService.resolveRelativePath(uri, parentHandle.uri);
|
|
336
361
|
}
|
|
337
362
|
uri = normalizeId(uri);
|
|
338
363
|
var referencedHandle = _this.getOrAddSchemaHandle(uri);
|
|
339
364
|
return referencedHandle.getUnresolvedSchema().then(function (unresolvedSchema) {
|
|
340
|
-
|
|
365
|
+
parentHandle.dependencies.add(uri);
|
|
341
366
|
if (unresolvedSchema.errors.length) {
|
|
342
367
|
var loc = refSegment ? uri + '#' + refSegment : uri;
|
|
343
368
|
resolveErrors.push(localize('json.schema.problemloadingref', 'Problems loading reference \'{0}\': {1}', loc, unresolvedSchema.errors[0]));
|
|
344
369
|
}
|
|
345
|
-
|
|
346
|
-
return resolveRefs(node, unresolvedSchema.schema,
|
|
370
|
+
mergeRef(node, unresolvedSchema.schema, referencedHandle, refSegment);
|
|
371
|
+
return resolveRefs(node, unresolvedSchema.schema, referencedHandle);
|
|
347
372
|
});
|
|
348
373
|
};
|
|
349
|
-
var resolveRefs = function (node, parentSchema,
|
|
350
|
-
if (!node || typeof node !== 'object') {
|
|
351
|
-
return Promise.resolve(null);
|
|
352
|
-
}
|
|
353
|
-
var toWalk = [node];
|
|
354
|
-
var seen = [];
|
|
374
|
+
var resolveRefs = function (node, parentSchema, parentHandle) {
|
|
355
375
|
var openPromises = [];
|
|
356
|
-
|
|
357
|
-
var
|
|
358
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
359
|
-
entries[_i] = arguments[_i];
|
|
360
|
-
}
|
|
361
|
-
for (var _a = 0, entries_1 = entries; _a < entries_1.length; _a++) {
|
|
362
|
-
var entry = entries_1[_a];
|
|
363
|
-
if (typeof entry === 'object') {
|
|
364
|
-
toWalk.push(entry);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
};
|
|
368
|
-
var collectMapEntries = function () {
|
|
369
|
-
var maps = [];
|
|
370
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
371
|
-
maps[_i] = arguments[_i];
|
|
372
|
-
}
|
|
373
|
-
for (var _a = 0, maps_1 = maps; _a < maps_1.length; _a++) {
|
|
374
|
-
var map = maps_1[_a];
|
|
375
|
-
if (typeof map === 'object') {
|
|
376
|
-
for (var k in map) {
|
|
377
|
-
var key = k;
|
|
378
|
-
var entry = map[key];
|
|
379
|
-
if (typeof entry === 'object') {
|
|
380
|
-
toWalk.push(entry);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
};
|
|
386
|
-
var collectArrayEntries = function () {
|
|
387
|
-
var arrays = [];
|
|
388
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
389
|
-
arrays[_i] = arguments[_i];
|
|
390
|
-
}
|
|
391
|
-
for (var _a = 0, arrays_1 = arrays; _a < arrays_1.length; _a++) {
|
|
392
|
-
var array = arrays_1[_a];
|
|
393
|
-
if (Array.isArray(array)) {
|
|
394
|
-
for (var _b = 0, array_1 = array; _b < array_1.length; _b++) {
|
|
395
|
-
var entry = array_1[_b];
|
|
396
|
-
if (typeof entry === 'object') {
|
|
397
|
-
toWalk.push(entry);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
};
|
|
403
|
-
var handleRef = function (next) {
|
|
404
|
-
var seenRefs = [];
|
|
376
|
+
_this.traverseNodes(node, function (next) {
|
|
377
|
+
var seenRefs = new Set();
|
|
405
378
|
while (next.$ref) {
|
|
406
379
|
var ref = next.$ref;
|
|
407
380
|
var segments = ref.split('#', 2);
|
|
408
381
|
delete next.$ref;
|
|
409
382
|
if (segments[0].length > 0) {
|
|
410
|
-
|
|
383
|
+
// This is a reference to an external schema
|
|
384
|
+
openPromises.push(resolveExternalLink(next, segments[0], segments[1], parentHandle));
|
|
411
385
|
return;
|
|
412
386
|
}
|
|
413
387
|
else {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
388
|
+
// This is a reference inside the current schema
|
|
389
|
+
if (!seenRefs.has(ref)) {
|
|
390
|
+
var id = segments[1];
|
|
391
|
+
mergeRef(next, parentSchema, parentHandle, id);
|
|
392
|
+
seenRefs.add(ref);
|
|
417
393
|
}
|
|
418
394
|
}
|
|
419
395
|
}
|
|
420
|
-
|
|
421
|
-
collectMapEntries(next.definitions, next.properties, next.patternProperties, next.dependencies);
|
|
422
|
-
collectArrayEntries(next.anyOf, next.allOf, next.oneOf, next.items);
|
|
423
|
-
};
|
|
424
|
-
while (toWalk.length) {
|
|
425
|
-
var next = toWalk.pop();
|
|
426
|
-
if (seen.indexOf(next) >= 0) {
|
|
427
|
-
continue;
|
|
428
|
-
}
|
|
429
|
-
seen.push(next);
|
|
430
|
-
handleRef(next);
|
|
431
|
-
}
|
|
396
|
+
});
|
|
432
397
|
return _this.promise.all(openPromises);
|
|
433
398
|
};
|
|
434
|
-
|
|
399
|
+
var collectAnchors = function (root) {
|
|
400
|
+
var result = new Map();
|
|
401
|
+
_this.traverseNodes(root, function (next) {
|
|
402
|
+
var id = next.$id || next.id;
|
|
403
|
+
if (typeof id === 'string' && id.charAt(0) === '#') {
|
|
404
|
+
// delete next.$id;
|
|
405
|
+
// delete next.id;
|
|
406
|
+
var anchor = id.substring(1);
|
|
407
|
+
if (result.has(anchor)) {
|
|
408
|
+
resolveErrors.push(localize('json.schema.duplicateid', 'Duplicate id declaration: \'{0}\'', id));
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
result.set(anchor, next);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
return result;
|
|
416
|
+
};
|
|
417
|
+
return resolveRefs(schema, schema, handle).then(function (_) {
|
|
418
|
+
return new ResolvedSchema(schema, resolveErrors);
|
|
419
|
+
});
|
|
435
420
|
};
|
|
436
|
-
JSONSchemaService.prototype.
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
421
|
+
JSONSchemaService.prototype.traverseNodes = function (root, handle) {
|
|
422
|
+
if (!root || typeof root !== 'object') {
|
|
423
|
+
return Promise.resolve(null);
|
|
424
|
+
}
|
|
425
|
+
var seen = new Set();
|
|
426
|
+
var collectEntries = function () {
|
|
427
|
+
var entries = [];
|
|
428
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
429
|
+
entries[_i] = arguments[_i];
|
|
430
|
+
}
|
|
431
|
+
for (var _a = 0, entries_1 = entries; _a < entries_1.length; _a++) {
|
|
432
|
+
var entry = entries_1[_a];
|
|
433
|
+
if (typeof entry === 'object') {
|
|
434
|
+
toWalk.push(entry);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
var collectMapEntries = function () {
|
|
439
|
+
var maps = [];
|
|
440
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
441
|
+
maps[_i] = arguments[_i];
|
|
442
|
+
}
|
|
443
|
+
for (var _a = 0, maps_1 = maps; _a < maps_1.length; _a++) {
|
|
444
|
+
var map = maps_1[_a];
|
|
445
|
+
if (typeof map === 'object') {
|
|
446
|
+
for (var k in map) {
|
|
447
|
+
var key = k;
|
|
448
|
+
var entry = map[key];
|
|
449
|
+
if (typeof entry === 'object') {
|
|
450
|
+
toWalk.push(entry);
|
|
451
|
+
}
|
|
446
452
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
var collectArrayEntries = function () {
|
|
457
|
+
var arrays = [];
|
|
458
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
459
|
+
arrays[_i] = arguments[_i];
|
|
460
|
+
}
|
|
461
|
+
for (var _a = 0, arrays_1 = arrays; _a < arrays_1.length; _a++) {
|
|
462
|
+
var array = arrays_1[_a];
|
|
463
|
+
if (Array.isArray(array)) {
|
|
464
|
+
for (var _b = 0, array_1 = array; _b < array_1.length; _b++) {
|
|
465
|
+
var entry = array_1[_b];
|
|
466
|
+
if (typeof entry === 'object') {
|
|
467
|
+
toWalk.push(entry);
|
|
468
|
+
}
|
|
450
469
|
}
|
|
451
470
|
}
|
|
452
471
|
}
|
|
472
|
+
};
|
|
473
|
+
var toWalk = [root];
|
|
474
|
+
var next = toWalk.pop();
|
|
475
|
+
while (next) {
|
|
476
|
+
if (!seen.has(next)) {
|
|
477
|
+
seen.add(next);
|
|
478
|
+
handle(next);
|
|
479
|
+
collectEntries(next.items, next.additionalItems, next.additionalProperties, next.not, next.contains, next.propertyNames, next.if, next.then, next.else);
|
|
480
|
+
collectMapEntries(next.definitions, next.properties, next.patternProperties, next.dependencies);
|
|
481
|
+
collectArrayEntries(next.anyOf, next.allOf, next.oneOf, next.items);
|
|
482
|
+
}
|
|
483
|
+
next = toWalk.pop();
|
|
453
484
|
}
|
|
454
|
-
|
|
455
|
-
|
|
485
|
+
};
|
|
486
|
+
;
|
|
487
|
+
JSONSchemaService.prototype.getSchemaFromProperty = function (resource, document) {
|
|
488
|
+
var _a, _b;
|
|
489
|
+
if (((_a = document.root) === null || _a === void 0 ? void 0 : _a.type) === 'object') {
|
|
490
|
+
for (var _i = 0, _c = document.root.properties; _i < _c.length; _i++) {
|
|
491
|
+
var p = _c[_i];
|
|
492
|
+
if (p.keyNode.value === '$schema' && ((_b = p.valueNode) === null || _b === void 0 ? void 0 : _b.type) === 'string') {
|
|
493
|
+
var schemaId = p.valueNode.value;
|
|
494
|
+
if (this.contextService && !/^\w[\w\d+.-]*:/.test(schemaId)) { // has scheme
|
|
495
|
+
schemaId = this.contextService.resolveRelativePath(schemaId, resource);
|
|
496
|
+
}
|
|
497
|
+
return schemaId;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
456
500
|
}
|
|
501
|
+
return undefined;
|
|
502
|
+
};
|
|
503
|
+
JSONSchemaService.prototype.getAssociatedSchemas = function (resource) {
|
|
457
504
|
var seen = Object.create(null);
|
|
458
505
|
var schemas = [];
|
|
459
506
|
var normalizedResource = normalizeResourceForMatching(resource);
|
|
@@ -469,6 +516,28 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
469
516
|
}
|
|
470
517
|
}
|
|
471
518
|
}
|
|
519
|
+
return schemas;
|
|
520
|
+
};
|
|
521
|
+
JSONSchemaService.prototype.getSchemaURIsForResource = function (resource, document) {
|
|
522
|
+
var schemeId = document && this.getSchemaFromProperty(resource, document);
|
|
523
|
+
if (schemeId) {
|
|
524
|
+
return [schemeId];
|
|
525
|
+
}
|
|
526
|
+
return this.getAssociatedSchemas(resource);
|
|
527
|
+
};
|
|
528
|
+
JSONSchemaService.prototype.getSchemaForResource = function (resource, document) {
|
|
529
|
+
if (document) {
|
|
530
|
+
// first use $schema if present
|
|
531
|
+
var schemeId = this.getSchemaFromProperty(resource, document);
|
|
532
|
+
if (schemeId) {
|
|
533
|
+
var id = normalizeId(schemeId);
|
|
534
|
+
return this.getOrAddSchemaHandle(id).getResolvedSchema();
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
if (this.cachedSchemaForResource && this.cachedSchemaForResource.resource === resource) {
|
|
538
|
+
return this.cachedSchemaForResource.resolvedSchema;
|
|
539
|
+
}
|
|
540
|
+
var schemas = this.getAssociatedSchemas(resource);
|
|
472
541
|
var resolvedSchema = schemas.length > 0 ? this.createCombinedSchema(resource, schemas).getResolvedSchema() : this.promise.resolve(undefined);
|
|
473
542
|
this.cachedSchemaForResource = { resource: resource, resolvedSchema: resolvedSchema };
|
|
474
543
|
return resolvedSchema;
|
|
@@ -488,7 +557,8 @@ var JSONSchemaService = /** @class */ (function () {
|
|
|
488
557
|
JSONSchemaService.prototype.getMatchingSchemas = function (document, jsonDocument, schema) {
|
|
489
558
|
if (schema) {
|
|
490
559
|
var id = schema.id || ('schemaservice://untitled/matchingSchemas/' + idCounter++);
|
|
491
|
-
|
|
560
|
+
var handle = this.addSchemaHandle(id, schema);
|
|
561
|
+
return handle.getResolvedSchema().then(function (resolvedSchema) {
|
|
492
562
|
return jsonDocument.getMatchingSchemas(resolvedSchema.schema).filter(function (s) { return !s.inverted; });
|
|
493
563
|
});
|
|
494
564
|
}
|
|
@@ -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 };
|
|
@@ -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,8 +57,9 @@ 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
|
-
|
|
61
|
-
|
|
60
|
+
getLanguageStatus: jsonValidation.getLanguageStatus.bind(jsonValidation),
|
|
61
|
+
parseJSONDocument: function (document) { return (0, jsonParser_1.parse)(document, { collectComments: true }); },
|
|
62
|
+
newJSONDocument: function (root, diagnostics) { return (0, jsonParser_1.newJSONDocument)(root, diagnostics); },
|
|
62
63
|
getMatchingSchemas: jsonSchemaService.getMatchingSchemas.bind(jsonSchemaService),
|
|
63
64
|
doResolve: jsonCompletion.doResolve.bind(jsonCompletion),
|
|
64
65
|
doComplete: jsonCompletion.doComplete.bind(jsonCompletion),
|
|
@@ -79,7 +80,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
79
80
|
range = { offset: offset, length: length };
|
|
80
81
|
}
|
|
81
82
|
var options = { tabSize: o ? o.tabSize : 4, insertSpaces: (o === null || o === void 0 ? void 0 : o.insertSpaces) === true, insertFinalNewline: (o === null || o === void 0 ? void 0 : o.insertFinalNewline) === true, eol: '\n' };
|
|
82
|
-
return jsonc_parser_1.format(d.getText(), range, options).map(function (e) {
|
|
83
|
+
return (0, jsonc_parser_1.format)(d.getText(), range, options).map(function (e) {
|
|
83
84
|
return jsonLanguageTypes_1.TextEdit.replace(jsonLanguageTypes_1.Range.create(d.positionAt(e.offset), d.positionAt(e.offset + e.length)), e.content);
|
|
84
85
|
});
|
|
85
86
|
}
|
|
@@ -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.
|