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 CHANGED
@@ -1,4 +1,10 @@
1
1
 
2
+
3
+ 4.2.0 /
4
+ ================
5
+ * new API `LanguageService.getLanguageStatus`
6
+ * support for $ref with $id
7
+
2
8
  4.1.6 / 2021-07-16
3
9
  ================
4
10
  * Replace minimatch with glob-to-regexp
@@ -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-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ }
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 + ": localize('schema.json." + 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" + separatorAfter)) {
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" + separatorAfter)) {
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 "\"" + name + "\"";
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 = "#" + toTwoDigitHex(red256) + toTwoDigitHex(green256) + toTwoDigitHex(blue256);
265
+ label = "#".concat(toTwoDigitHex(red256)).concat(toTwoDigitHex(green256)).concat(toTwoDigitHex(blue256));
266
266
  }
267
267
  else {
268
- label = "#" + toTwoDigitHex(red256) + toTwoDigitHex(green256) + toTwoDigitHex(blue256) + toTwoDigitHex(Math.round(color.alpha * 255));
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 += "`" + toMarkdownCodeBlock(enumValue_1) + "`: " + markdownEnumValueDescription_1;
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 + "#" + (targetPos.line + 1) + "," + (targetPos.character + 1),
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, url, unresolvedSchemaContent) {
58
+ function SchemaHandle(service, uri, unresolvedSchemaContent) {
59
59
  this.service = service;
60
- this.url = url;
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.url);
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.url, _this.dependencies);
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.url === curr || handle.dependencies[curr])) {
189
- if (handle.url !== curr) {
190
- toWalk.push(handle.url);
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, schemaURL, dependencies) {
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 findSection = function (schema, path) {
305
- if (!path) {
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.substr(1);
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 merge = function (target, sourceRoot, sourceURI, refSegment) {
320
- var path = refSegment ? decodeURIComponent(refSegment) : undefined;
321
- var section = findSection(sourceRoot, path);
322
- if (section) {
323
- for (var key in section) {
324
- if (section.hasOwnProperty(key) && !target.hasOwnProperty(key)) {
325
- target[key] = section[key];
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.invalidref', '$ref \'{0}\' in \'{1}\' can not be resolved.', path, sourceURI));
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, parentSchemaURL, parentSchemaDependencies) {
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, parentSchemaURL);
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
- parentSchemaDependencies[uri] = true;
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
- merge(node, unresolvedSchema.schema, uri, refSegment);
346
- return resolveRefs(node, unresolvedSchema.schema, uri, referencedHandle.dependencies);
370
+ mergeRef(node, unresolvedSchema.schema, referencedHandle, refSegment);
371
+ return resolveRefs(node, unresolvedSchema.schema, referencedHandle);
347
372
  });
348
373
  };
349
- var resolveRefs = function (node, parentSchema, parentSchemaURL, parentSchemaDependencies) {
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
- var collectEntries = function () {
357
- var entries = [];
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
- openPromises.push(resolveExternalLink(next, segments[0], segments[1], parentSchemaURL, parentSchemaDependencies));
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
- if (seenRefs.indexOf(ref) === -1) {
415
- merge(next, parentSchema, parentSchemaURL, segments[1]); // can set next.$ref again, use seenRefs to avoid circle
416
- seenRefs.push(ref);
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
- collectEntries(next.items, next.additionalItems, next.additionalProperties, next.not, next.contains, next.propertyNames, next.if, next.then, next.else);
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
- return resolveRefs(schema, schema, schemaURL, dependencies).then(function (_) { return new ResolvedSchema(schema, resolveErrors); });
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.getSchemaForResource = function (resource, document) {
437
- // first use $schema if present
438
- if (document && document.root && document.root.type === 'object') {
439
- var schemaProperties = document.root.properties.filter(function (p) { return (p.keyNode.value === '$schema') && p.valueNode && p.valueNode.type === 'string'; });
440
- if (schemaProperties.length > 0) {
441
- var valueNode = schemaProperties[0].valueNode;
442
- if (valueNode && valueNode.type === 'string') {
443
- var schemeId = Parser.getNodeValue(valueNode);
444
- if (schemeId && Strings.startsWith(schemeId, '.') && this.contextService) {
445
- schemeId = this.contextService.resolveRelativePath(schemeId, resource);
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
- if (schemeId) {
448
- var id = normalizeId(schemeId);
449
- return this.getOrAddSchemaHandle(id).getResolvedSchema();
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
- if (this.cachedSchemaForResource && this.cachedSchemaForResource.resource === resource) {
455
- return this.cachedSchemaForResource.resolvedSchema;
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
- return this.resolveSchemaContent(new UnresolvedSchema(schema), id, {}).then(function (resolvedSchema) {
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
- return this.jsonSchemaService.resolveSchemaContent(new UnresolvedSchema(schema), id, {}).then(function (resolvedSchema) {
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
- parseJSONDocument: function (document) { return jsonParser_1.parse(document, { collectComments: true }); },
61
- newJSONDocument: function (root, diagnostics) { return jsonParser_1.newJSONDocument(root, diagnostics); },
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.