vscode-json-languageservice 5.6.3 → 5.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ 5.7.0 / 2026-01-12
2
+ ================
3
+ * the error code for `SchemaResolveError` is now 0x10000 plus the error code returned by the request service.
4
+
1
5
  5.6.0 / 2025-05-28
2
6
  ================
3
7
  * added `Schema.enumSortTexts` and `Schema.enumDetails` to control the sort order and presentation of suggestions for enums
@@ -26,9 +26,10 @@ export declare enum ErrorCode {
26
26
  DuplicateKey = 520,
27
27
  CommentNotPermitted = 521,
28
28
  PropertyKeysMustBeDoublequoted = 528,
29
- SchemaResolveError = 768,
30
- SchemaUnsupportedFeature = 769
29
+ SchemaUnsupportedFeature = 769,
30
+ SchemaResolveError = 65536
31
31
  }
32
+ export declare function isSchemaResolveError(code: number): boolean;
32
33
  export type ASTNode = ObjectASTNode | PropertyASTNode | ArrayASTNode | StringASTNode | NumberASTNode | BooleanASTNode | NullASTNode;
33
34
  export interface BaseASTNode {
34
35
  readonly type: 'object' | 'array' | 'property' | 'string' | 'number' | 'boolean' | 'null';
@@ -153,7 +154,8 @@ export interface WorkspaceContextService {
153
154
  }
154
155
  /**
155
156
  * The schema request service is used to fetch schemas. If successful, returns a resolved promise with the content of the schema.
156
- * In case of an error, returns a rejected promise with a displayable error string.
157
+ * In case of an error, returns a rejected promise with an Error object. If the type is of form { message: string, code: number }, the
158
+ * error code will be used for diagnostics.
157
159
  */
158
160
  export interface SchemaRequestService {
159
161
  (uri: string): PromiseLike<string>;
@@ -29,9 +29,12 @@ export var ErrorCode;
29
29
  ErrorCode[ErrorCode["DuplicateKey"] = 520] = "DuplicateKey";
30
30
  ErrorCode[ErrorCode["CommentNotPermitted"] = 521] = "CommentNotPermitted";
31
31
  ErrorCode[ErrorCode["PropertyKeysMustBeDoublequoted"] = 528] = "PropertyKeysMustBeDoublequoted";
32
- ErrorCode[ErrorCode["SchemaResolveError"] = 768] = "SchemaResolveError";
33
32
  ErrorCode[ErrorCode["SchemaUnsupportedFeature"] = 769] = "SchemaUnsupportedFeature";
33
+ ErrorCode[ErrorCode["SchemaResolveError"] = 65536] = "SchemaResolveError";
34
34
  })(ErrorCode || (ErrorCode = {}));
35
+ export function isSchemaResolveError(code) {
36
+ return code >= ErrorCode.SchemaResolveError;
37
+ }
35
38
  export var SchemaDraft;
36
39
  (function (SchemaDraft) {
37
40
  SchemaDraft[SchemaDraft["v3"] = 3] = "v3";
@@ -364,9 +364,10 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
364
364
  }
365
365
  const testAlternatives = (alternatives, maxOneMatch) => {
366
366
  const matches = [];
367
+ const alternativesToTest = _tryDiscriminatorOptimization(alternatives) ?? alternatives;
367
368
  // remember the best match that is used for error messages
368
369
  let bestMatch = undefined;
369
- for (const subSchemaRef of alternatives) {
370
+ for (const subSchemaRef of alternativesToTest) {
370
371
  const subSchema = asSchema(subSchemaRef);
371
372
  const subValidationResult = new ValidationResult();
372
373
  const subMatchingSchemas = matchingSchemas.newSub();
@@ -491,6 +492,70 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
491
492
  });
492
493
  }
493
494
  }
495
+ function _tryDiscriminatorOptimization(alternatives) {
496
+ if (alternatives.length < 2) {
497
+ return undefined;
498
+ }
499
+ const buildConstMap = (getSchemas) => {
500
+ const constMap = new Map();
501
+ for (let i = 0; i < alternatives.length; i++) {
502
+ const schemas = getSchemas(asSchema(alternatives[i]), i);
503
+ if (!schemas) {
504
+ return undefined; // Early exit if any alternative can't be processed
505
+ }
506
+ schemas.forEach(([key, schema]) => {
507
+ if (schema.const !== undefined) {
508
+ if (!constMap.has(key)) {
509
+ constMap.set(key, new Map());
510
+ }
511
+ const valueMap = constMap.get(key);
512
+ if (!valueMap.has(schema.const)) {
513
+ valueMap.set(schema.const, []);
514
+ }
515
+ valueMap.get(schema.const).push(i);
516
+ }
517
+ });
518
+ }
519
+ return constMap;
520
+ };
521
+ const findDiscriminator = (constMap, getValue) => {
522
+ for (const [key, valueMap] of constMap) {
523
+ const coveredAlts = new Set();
524
+ valueMap.forEach(indices => indices.forEach(idx => coveredAlts.add(idx)));
525
+ if (coveredAlts.size === alternatives.length) {
526
+ const discriminatorValue = getValue(key);
527
+ const matchingIndices = valueMap.get(discriminatorValue);
528
+ if (matchingIndices?.length) {
529
+ return matchingIndices.map(idx => alternatives[idx]);
530
+ }
531
+ break; // Found valid discriminator but no match
532
+ }
533
+ }
534
+ return undefined;
535
+ };
536
+ if (node.type === 'object' && node.properties?.length) {
537
+ const constMap = buildConstMap((schema) => schema.properties ? Object.entries(schema.properties).map(([k, v]) => [k, asSchema(v)]) : undefined);
538
+ if (constMap) {
539
+ return findDiscriminator(constMap, (propName) => {
540
+ const prop = node.properties.find(p => p.keyNode.value === propName);
541
+ return prop?.valueNode?.type === 'string' ? prop.valueNode.value : undefined;
542
+ });
543
+ }
544
+ }
545
+ else if (node.type === 'array' && node.items?.length) {
546
+ const constMap = buildConstMap((schema) => {
547
+ const itemSchemas = schema.prefixItems || (Array.isArray(schema.items) ? schema.items : undefined);
548
+ return itemSchemas ? itemSchemas.map((item, idx) => [idx, asSchema(item)]) : undefined;
549
+ });
550
+ if (constMap) {
551
+ return findDiscriminator(constMap, (itemIndex) => {
552
+ const item = node.items[itemIndex];
553
+ return item?.type === 'string' ? item.value : undefined;
554
+ });
555
+ }
556
+ }
557
+ return undefined;
558
+ }
494
559
  function _validateNumberNode(node) {
495
560
  const val = node.value;
496
561
  function normalizeFloats(float) {
@@ -952,7 +1017,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
952
1017
  for (const f of node.properties) {
953
1018
  const key = f.keyNode;
954
1019
  if (key) {
955
- validate(key, propertyNames, validationResult, NoOpSchemaCollector.instance, context);
1020
+ validate(key, propertyNames, validationResult, matchingSchemas, context);
956
1021
  }
957
1022
  }
958
1023
  }
@@ -6,7 +6,7 @@ import * as Json from 'jsonc-parser';
6
6
  import { URI } from 'vscode-uri';
7
7
  import * as Strings from '../utils/strings';
8
8
  import { asSchema, getSchemaDraftFromId, normalizeId } from '../parser/jsonParser';
9
- import { SchemaDraft } from '../jsonLanguageTypes';
9
+ import { SchemaDraft, ErrorCode } from '../jsonLanguageTypes';
10
10
  import * as l10n from '@vscode/l10n';
11
11
  import { createRegex } from '../utils/glob';
12
12
  import { isObject, isString } from '../utils/objects';
@@ -102,6 +102,9 @@ export class UnresolvedSchema {
102
102
  this.errors = errors;
103
103
  }
104
104
  }
105
+ function toDiagnostic(message, code) {
106
+ return { message, code };
107
+ }
105
108
  export class ResolvedSchema {
106
109
  constructor(schema, errors = [], warnings = [], schemaDraft) {
107
110
  this.schema = schema;
@@ -262,36 +265,45 @@ export class JSONSchemaService {
262
265
  loadSchema(url) {
263
266
  if (!this.requestService) {
264
267
  const errorMessage = l10n.t('Unable to load schema from \'{0}\'. No schema request service available', toDisplayString(url));
265
- return this.promise.resolve(new UnresolvedSchema({}, [errorMessage]));
268
+ return this.promise.resolve(new UnresolvedSchema({}, [toDiagnostic(errorMessage, ErrorCode.SchemaResolveError)]));
266
269
  }
267
270
  return this.requestService(url).then(content => {
268
271
  if (!content) {
269
272
  const errorMessage = l10n.t('Unable to load schema from \'{0}\': No content.', toDisplayString(url));
270
- return new UnresolvedSchema({}, [errorMessage]);
273
+ return new UnresolvedSchema({}, [toDiagnostic(errorMessage, ErrorCode.SchemaResolveError)]);
271
274
  }
272
275
  const errors = [];
273
276
  if (content.charCodeAt(0) === 65279) {
274
- errors.push(l10n.t('Problem reading content from \'{0}\': UTF-8 with BOM detected, only UTF 8 is allowed.', toDisplayString(url)));
277
+ errors.push(toDiagnostic(l10n.t('Problem reading content from \'{0}\': UTF-8 with BOM detected, only UTF 8 is allowed.', toDisplayString(url)), ErrorCode.SchemaResolveError));
275
278
  content = content.trimStart();
276
279
  }
277
280
  let schemaContent = {};
278
281
  const jsonErrors = [];
279
282
  schemaContent = Json.parse(content, jsonErrors);
280
283
  if (jsonErrors.length) {
281
- errors.push(l10n.t('Unable to parse content from \'{0}\': Parse error at offset {1}.', toDisplayString(url), jsonErrors[0].offset));
284
+ errors.push(toDiagnostic(l10n.t('Unable to parse content from \'{0}\': Parse error at offset {1}.', toDisplayString(url), jsonErrors[0].offset), ErrorCode.SchemaResolveError));
282
285
  }
283
286
  return new UnresolvedSchema(schemaContent, errors);
284
287
  }, (error) => {
285
- let errorMessage = error.toString();
286
- const errorSplit = error.toString().split('Error: ');
287
- if (errorSplit.length > 1) {
288
- // more concise error message, URL and context are attached by caller anyways
289
- errorMessage = errorSplit[1];
288
+ let { message, code } = error;
289
+ if (typeof message !== 'string') {
290
+ let errorMessage = error.toString();
291
+ const errorSplit = error.toString().split('Error: ');
292
+ if (errorSplit.length > 1) {
293
+ // more concise error message, URL and context are attached by caller anyways
294
+ errorMessage = errorSplit[1];
295
+ }
296
+ if (Strings.endsWith(errorMessage, '.')) {
297
+ errorMessage = errorMessage.substr(0, errorMessage.length - 1);
298
+ }
299
+ message = errorMessage;
290
300
  }
291
- if (Strings.endsWith(errorMessage, '.')) {
292
- errorMessage = errorMessage.substr(0, errorMessage.length - 1);
301
+ let errorCode = ErrorCode.SchemaResolveError;
302
+ if (typeof code === 'number' && code < 0x10000) {
303
+ errorCode += code;
293
304
  }
294
- return new UnresolvedSchema({}, [l10n.t('Unable to load schema from \'{0}\': {1}.', toDisplayString(url), errorMessage)]);
305
+ const errorMessage = l10n.t('Unable to load schema from \'{0}\': {1}.', toDisplayString(url), message);
306
+ return new UnresolvedSchema({}, [toDiagnostic(errorMessage, errorCode)]);
295
307
  });
296
308
  }
297
309
  resolveSchemaContent(schemaToResolve, handle) {
@@ -299,7 +311,7 @@ export class JSONSchemaService {
299
311
  const schema = schemaToResolve.schema;
300
312
  const schemaDraft = schema.$schema ? getSchemaDraftFromId(schema.$schema) : undefined;
301
313
  if (schemaDraft === SchemaDraft.v3) {
302
- return this.promise.resolve(new ResolvedSchema({}, [l10n.t("Draft-03 schemas are not supported.")], [], schemaDraft));
314
+ return this.promise.resolve(new ResolvedSchema({}, [toDiagnostic(l10n.t("Draft-03 schemas are not supported."), ErrorCode.SchemaUnsupportedFeature)], [], schemaDraft));
303
315
  }
304
316
  let usesUnsupportedFeatures = new Set();
305
317
  const contextService = this.contextService;
@@ -346,7 +358,8 @@ export class JSONSchemaService {
346
358
  merge(target, section);
347
359
  }
348
360
  else {
349
- resolveErrors.push(l10n.t('$ref \'{0}\' in \'{1}\' can not be resolved.', refSegment || '', sourceHandle.uri));
361
+ const message = l10n.t('$ref \'{0}\' in \'{1}\' can not be resolved.', refSegment || '', sourceHandle.uri);
362
+ resolveErrors.push(toDiagnostic(message, ErrorCode.SchemaResolveError));
350
363
  }
351
364
  };
352
365
  const resolveExternalLink = (node, uri, refSegment, parentHandle) => {
@@ -359,7 +372,8 @@ export class JSONSchemaService {
359
372
  parentHandle.dependencies.add(uri);
360
373
  if (unresolvedSchema.errors.length) {
361
374
  const loc = refSegment ? uri + '#' + refSegment : uri;
362
- resolveErrors.push(l10n.t('Problems loading reference \'{0}\': {1}', loc, unresolvedSchema.errors[0]));
375
+ const errorMessage = l10n.t('Problems loading reference \'{0}\': {1}', loc, unresolvedSchema.errors[0].message);
376
+ resolveErrors.push(toDiagnostic(errorMessage, unresolvedSchema.errors[0].code));
363
377
  }
364
378
  mergeRef(node, unresolvedSchema.schema, referencedHandle, refSegment);
365
379
  return resolveRefs(node, unresolvedSchema.schema, referencedHandle);
@@ -403,7 +417,7 @@ export class JSONSchemaService {
403
417
  const anchor = isString(id) && id.charAt(0) === '#' ? id.substring(1) : next.$anchor;
404
418
  if (anchor) {
405
419
  if (result.has(anchor)) {
406
- resolveErrors.push(l10n.t('Duplicate anchor declaration: \'{0}\'', anchor));
420
+ resolveErrors.push(toDiagnostic(l10n.t('Duplicate anchor declaration: \'{0}\'', anchor), ErrorCode.SchemaResolveError));
407
421
  }
408
422
  else {
409
423
  result.set(anchor, next);
@@ -421,7 +435,7 @@ export class JSONSchemaService {
421
435
  return resolveRefs(schema, schema, handle).then(_ => {
422
436
  let resolveWarnings = [];
423
437
  if (usesUnsupportedFeatures.size) {
424
- resolveWarnings.push(l10n.t('The schema uses meta-schema features ({0}) that are not yet supported by the validator.', Array.from(usesUnsupportedFeatures.keys()).join(', ')));
438
+ resolveWarnings.push(toDiagnostic(l10n.t('The schema uses meta-schema features ({0}) that are not yet supported by the validator.', Array.from(usesUnsupportedFeatures.keys()).join(', ')), ErrorCode.SchemaUnsupportedFeature));
425
439
  }
426
440
  return new ResolvedSchema(schema, resolveErrors, resolveWarnings, schemaDraft);
427
441
  });
@@ -53,11 +53,11 @@ export class JSONValidation {
53
53
  }
54
54
  };
55
55
  if (schema.errors.length) {
56
- addSchemaProblem(schema.errors[0], ErrorCode.SchemaResolveError);
56
+ addSchemaProblem(schema.errors[0].message, schema.errors[0].code);
57
57
  }
58
58
  else if (schemaValidation) {
59
59
  for (const warning of schema.warnings) {
60
- addSchemaProblem(warning, ErrorCode.SchemaUnsupportedFeature);
60
+ addSchemaProblem(warning.message, warning.code);
61
61
  }
62
62
  const semanticErrors = jsonDocument.validate(textDocument, schema.schema, schemaValidation, documentSettings?.schemaDraft);
63
63
  if (semanticErrors) {
@@ -26,9 +26,10 @@ export declare enum ErrorCode {
26
26
  DuplicateKey = 520,
27
27
  CommentNotPermitted = 521,
28
28
  PropertyKeysMustBeDoublequoted = 528,
29
- SchemaResolveError = 768,
30
- SchemaUnsupportedFeature = 769
29
+ SchemaUnsupportedFeature = 769,
30
+ SchemaResolveError = 65536
31
31
  }
32
+ export declare function isSchemaResolveError(code: number): boolean;
32
33
  export type ASTNode = ObjectASTNode | PropertyASTNode | ArrayASTNode | StringASTNode | NumberASTNode | BooleanASTNode | NullASTNode;
33
34
  export interface BaseASTNode {
34
35
  readonly type: 'object' | 'array' | 'property' | 'string' | 'number' | 'boolean' | 'null';
@@ -153,7 +154,8 @@ export interface WorkspaceContextService {
153
154
  }
154
155
  /**
155
156
  * The schema request service is used to fetch schemas. If successful, returns a resolved promise with the content of the schema.
156
- * In case of an error, returns a rejected promise with a displayable error string.
157
+ * In case of an error, returns a rejected promise with an Error object. If the type is of form { message: string, code: number }, the
158
+ * error code will be used for diagnostics.
157
159
  */
158
160
  export interface SchemaRequestService {
159
161
  (uri: string): PromiseLike<string>;
@@ -14,6 +14,7 @@
14
14
  "use strict";
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.ClientCapabilities = exports.SchemaDraft = exports.ErrorCode = exports.DocumentHighlightKind = exports.VersionedTextDocumentIdentifier = exports.TextDocumentEdit = exports.CodeActionKind = exports.TextEdit = exports.WorkspaceEdit = exports.DocumentLink = exports.DocumentHighlight = exports.CodeAction = exports.Command = exports.CodeActionContext = exports.MarkedString = exports.Hover = exports.Location = exports.DocumentSymbol = exports.SymbolKind = exports.SymbolInformation = exports.InsertTextFormat = exports.CompletionItemTag = exports.CompletionList = exports.CompletionItemKind = exports.CompletionItem = exports.DiagnosticSeverity = exports.Diagnostic = exports.SelectionRange = exports.FoldingRangeKind = exports.FoldingRange = exports.ColorPresentation = exports.ColorInformation = exports.Color = exports.MarkupKind = exports.MarkupContent = exports.DocumentUri = exports.Position = exports.Range = exports.TextDocument = void 0;
17
+ exports.isSchemaResolveError = isSchemaResolveError;
17
18
  const vscode_languageserver_types_1 = require("vscode-languageserver-types");
18
19
  Object.defineProperty(exports, "Range", { enumerable: true, get: function () { return vscode_languageserver_types_1.Range; } });
19
20
  Object.defineProperty(exports, "Position", { enumerable: true, get: function () { return vscode_languageserver_types_1.Position; } });
@@ -76,9 +77,12 @@
76
77
  ErrorCode[ErrorCode["DuplicateKey"] = 520] = "DuplicateKey";
77
78
  ErrorCode[ErrorCode["CommentNotPermitted"] = 521] = "CommentNotPermitted";
78
79
  ErrorCode[ErrorCode["PropertyKeysMustBeDoublequoted"] = 528] = "PropertyKeysMustBeDoublequoted";
79
- ErrorCode[ErrorCode["SchemaResolveError"] = 768] = "SchemaResolveError";
80
80
  ErrorCode[ErrorCode["SchemaUnsupportedFeature"] = 769] = "SchemaUnsupportedFeature";
81
+ ErrorCode[ErrorCode["SchemaResolveError"] = 65536] = "SchemaResolveError";
81
82
  })(ErrorCode || (exports.ErrorCode = ErrorCode = {}));
83
+ function isSchemaResolveError(code) {
84
+ return code >= ErrorCode.SchemaResolveError;
85
+ }
82
86
  var SchemaDraft;
83
87
  (function (SchemaDraft) {
84
88
  SchemaDraft[SchemaDraft["v3"] = 3] = "v3";
@@ -394,9 +394,10 @@
394
394
  }
395
395
  const testAlternatives = (alternatives, maxOneMatch) => {
396
396
  const matches = [];
397
+ const alternativesToTest = _tryDiscriminatorOptimization(alternatives) ?? alternatives;
397
398
  // remember the best match that is used for error messages
398
399
  let bestMatch = undefined;
399
- for (const subSchemaRef of alternatives) {
400
+ for (const subSchemaRef of alternativesToTest) {
400
401
  const subSchema = asSchema(subSchemaRef);
401
402
  const subValidationResult = new ValidationResult();
402
403
  const subMatchingSchemas = matchingSchemas.newSub();
@@ -521,6 +522,70 @@
521
522
  });
522
523
  }
523
524
  }
525
+ function _tryDiscriminatorOptimization(alternatives) {
526
+ if (alternatives.length < 2) {
527
+ return undefined;
528
+ }
529
+ const buildConstMap = (getSchemas) => {
530
+ const constMap = new Map();
531
+ for (let i = 0; i < alternatives.length; i++) {
532
+ const schemas = getSchemas(asSchema(alternatives[i]), i);
533
+ if (!schemas) {
534
+ return undefined; // Early exit if any alternative can't be processed
535
+ }
536
+ schemas.forEach(([key, schema]) => {
537
+ if (schema.const !== undefined) {
538
+ if (!constMap.has(key)) {
539
+ constMap.set(key, new Map());
540
+ }
541
+ const valueMap = constMap.get(key);
542
+ if (!valueMap.has(schema.const)) {
543
+ valueMap.set(schema.const, []);
544
+ }
545
+ valueMap.get(schema.const).push(i);
546
+ }
547
+ });
548
+ }
549
+ return constMap;
550
+ };
551
+ const findDiscriminator = (constMap, getValue) => {
552
+ for (const [key, valueMap] of constMap) {
553
+ const coveredAlts = new Set();
554
+ valueMap.forEach(indices => indices.forEach(idx => coveredAlts.add(idx)));
555
+ if (coveredAlts.size === alternatives.length) {
556
+ const discriminatorValue = getValue(key);
557
+ const matchingIndices = valueMap.get(discriminatorValue);
558
+ if (matchingIndices?.length) {
559
+ return matchingIndices.map(idx => alternatives[idx]);
560
+ }
561
+ break; // Found valid discriminator but no match
562
+ }
563
+ }
564
+ return undefined;
565
+ };
566
+ if (node.type === 'object' && node.properties?.length) {
567
+ const constMap = buildConstMap((schema) => schema.properties ? Object.entries(schema.properties).map(([k, v]) => [k, asSchema(v)]) : undefined);
568
+ if (constMap) {
569
+ return findDiscriminator(constMap, (propName) => {
570
+ const prop = node.properties.find(p => p.keyNode.value === propName);
571
+ return prop?.valueNode?.type === 'string' ? prop.valueNode.value : undefined;
572
+ });
573
+ }
574
+ }
575
+ else if (node.type === 'array' && node.items?.length) {
576
+ const constMap = buildConstMap((schema) => {
577
+ const itemSchemas = schema.prefixItems || (Array.isArray(schema.items) ? schema.items : undefined);
578
+ return itemSchemas ? itemSchemas.map((item, idx) => [idx, asSchema(item)]) : undefined;
579
+ });
580
+ if (constMap) {
581
+ return findDiscriminator(constMap, (itemIndex) => {
582
+ const item = node.items[itemIndex];
583
+ return item?.type === 'string' ? item.value : undefined;
584
+ });
585
+ }
586
+ }
587
+ return undefined;
588
+ }
524
589
  function _validateNumberNode(node) {
525
590
  const val = node.value;
526
591
  function normalizeFloats(float) {
@@ -982,7 +1047,7 @@
982
1047
  for (const f of node.properties) {
983
1048
  const key = f.keyNode;
984
1049
  if (key) {
985
- validate(key, propertyNames, validationResult, NoOpSchemaCollector.instance, context);
1050
+ validate(key, propertyNames, validationResult, matchingSchemas, context);
986
1051
  }
987
1052
  }
988
1053
  }
@@ -115,6 +115,9 @@
115
115
  }
116
116
  }
117
117
  exports.UnresolvedSchema = UnresolvedSchema;
118
+ function toDiagnostic(message, code) {
119
+ return { message, code };
120
+ }
118
121
  class ResolvedSchema {
119
122
  constructor(schema, errors = [], warnings = [], schemaDraft) {
120
123
  this.schema = schema;
@@ -276,36 +279,45 @@
276
279
  loadSchema(url) {
277
280
  if (!this.requestService) {
278
281
  const errorMessage = l10n.t('Unable to load schema from \'{0}\'. No schema request service available', toDisplayString(url));
279
- return this.promise.resolve(new UnresolvedSchema({}, [errorMessage]));
282
+ return this.promise.resolve(new UnresolvedSchema({}, [toDiagnostic(errorMessage, jsonLanguageTypes_1.ErrorCode.SchemaResolveError)]));
280
283
  }
281
284
  return this.requestService(url).then(content => {
282
285
  if (!content) {
283
286
  const errorMessage = l10n.t('Unable to load schema from \'{0}\': No content.', toDisplayString(url));
284
- return new UnresolvedSchema({}, [errorMessage]);
287
+ return new UnresolvedSchema({}, [toDiagnostic(errorMessage, jsonLanguageTypes_1.ErrorCode.SchemaResolveError)]);
285
288
  }
286
289
  const errors = [];
287
290
  if (content.charCodeAt(0) === 65279) {
288
- errors.push(l10n.t('Problem reading content from \'{0}\': UTF-8 with BOM detected, only UTF 8 is allowed.', toDisplayString(url)));
291
+ errors.push(toDiagnostic(l10n.t('Problem reading content from \'{0}\': UTF-8 with BOM detected, only UTF 8 is allowed.', toDisplayString(url)), jsonLanguageTypes_1.ErrorCode.SchemaResolveError));
289
292
  content = content.trimStart();
290
293
  }
291
294
  let schemaContent = {};
292
295
  const jsonErrors = [];
293
296
  schemaContent = Json.parse(content, jsonErrors);
294
297
  if (jsonErrors.length) {
295
- errors.push(l10n.t('Unable to parse content from \'{0}\': Parse error at offset {1}.', toDisplayString(url), jsonErrors[0].offset));
298
+ errors.push(toDiagnostic(l10n.t('Unable to parse content from \'{0}\': Parse error at offset {1}.', toDisplayString(url), jsonErrors[0].offset), jsonLanguageTypes_1.ErrorCode.SchemaResolveError));
296
299
  }
297
300
  return new UnresolvedSchema(schemaContent, errors);
298
301
  }, (error) => {
299
- let errorMessage = error.toString();
300
- const errorSplit = error.toString().split('Error: ');
301
- if (errorSplit.length > 1) {
302
- // more concise error message, URL and context are attached by caller anyways
303
- errorMessage = errorSplit[1];
302
+ let { message, code } = error;
303
+ if (typeof message !== 'string') {
304
+ let errorMessage = error.toString();
305
+ const errorSplit = error.toString().split('Error: ');
306
+ if (errorSplit.length > 1) {
307
+ // more concise error message, URL and context are attached by caller anyways
308
+ errorMessage = errorSplit[1];
309
+ }
310
+ if (Strings.endsWith(errorMessage, '.')) {
311
+ errorMessage = errorMessage.substr(0, errorMessage.length - 1);
312
+ }
313
+ message = errorMessage;
304
314
  }
305
- if (Strings.endsWith(errorMessage, '.')) {
306
- errorMessage = errorMessage.substr(0, errorMessage.length - 1);
315
+ let errorCode = jsonLanguageTypes_1.ErrorCode.SchemaResolveError;
316
+ if (typeof code === 'number' && code < 0x10000) {
317
+ errorCode += code;
307
318
  }
308
- return new UnresolvedSchema({}, [l10n.t('Unable to load schema from \'{0}\': {1}.', toDisplayString(url), errorMessage)]);
319
+ const errorMessage = l10n.t('Unable to load schema from \'{0}\': {1}.', toDisplayString(url), message);
320
+ return new UnresolvedSchema({}, [toDiagnostic(errorMessage, errorCode)]);
309
321
  });
310
322
  }
311
323
  resolveSchemaContent(schemaToResolve, handle) {
@@ -313,7 +325,7 @@
313
325
  const schema = schemaToResolve.schema;
314
326
  const schemaDraft = schema.$schema ? (0, jsonParser_1.getSchemaDraftFromId)(schema.$schema) : undefined;
315
327
  if (schemaDraft === jsonLanguageTypes_1.SchemaDraft.v3) {
316
- return this.promise.resolve(new ResolvedSchema({}, [l10n.t("Draft-03 schemas are not supported.")], [], schemaDraft));
328
+ return this.promise.resolve(new ResolvedSchema({}, [toDiagnostic(l10n.t("Draft-03 schemas are not supported."), jsonLanguageTypes_1.ErrorCode.SchemaUnsupportedFeature)], [], schemaDraft));
317
329
  }
318
330
  let usesUnsupportedFeatures = new Set();
319
331
  const contextService = this.contextService;
@@ -360,7 +372,8 @@
360
372
  merge(target, section);
361
373
  }
362
374
  else {
363
- resolveErrors.push(l10n.t('$ref \'{0}\' in \'{1}\' can not be resolved.', refSegment || '', sourceHandle.uri));
375
+ const message = l10n.t('$ref \'{0}\' in \'{1}\' can not be resolved.', refSegment || '', sourceHandle.uri);
376
+ resolveErrors.push(toDiagnostic(message, jsonLanguageTypes_1.ErrorCode.SchemaResolveError));
364
377
  }
365
378
  };
366
379
  const resolveExternalLink = (node, uri, refSegment, parentHandle) => {
@@ -373,7 +386,8 @@
373
386
  parentHandle.dependencies.add(uri);
374
387
  if (unresolvedSchema.errors.length) {
375
388
  const loc = refSegment ? uri + '#' + refSegment : uri;
376
- resolveErrors.push(l10n.t('Problems loading reference \'{0}\': {1}', loc, unresolvedSchema.errors[0]));
389
+ const errorMessage = l10n.t('Problems loading reference \'{0}\': {1}', loc, unresolvedSchema.errors[0].message);
390
+ resolveErrors.push(toDiagnostic(errorMessage, unresolvedSchema.errors[0].code));
377
391
  }
378
392
  mergeRef(node, unresolvedSchema.schema, referencedHandle, refSegment);
379
393
  return resolveRefs(node, unresolvedSchema.schema, referencedHandle);
@@ -417,7 +431,7 @@
417
431
  const anchor = (0, objects_1.isString)(id) && id.charAt(0) === '#' ? id.substring(1) : next.$anchor;
418
432
  if (anchor) {
419
433
  if (result.has(anchor)) {
420
- resolveErrors.push(l10n.t('Duplicate anchor declaration: \'{0}\'', anchor));
434
+ resolveErrors.push(toDiagnostic(l10n.t('Duplicate anchor declaration: \'{0}\'', anchor), jsonLanguageTypes_1.ErrorCode.SchemaResolveError));
421
435
  }
422
436
  else {
423
437
  result.set(anchor, next);
@@ -435,7 +449,7 @@
435
449
  return resolveRefs(schema, schema, handle).then(_ => {
436
450
  let resolveWarnings = [];
437
451
  if (usesUnsupportedFeatures.size) {
438
- resolveWarnings.push(l10n.t('The schema uses meta-schema features ({0}) that are not yet supported by the validator.', Array.from(usesUnsupportedFeatures.keys()).join(', ')));
452
+ resolveWarnings.push(toDiagnostic(l10n.t('The schema uses meta-schema features ({0}) that are not yet supported by the validator.', Array.from(usesUnsupportedFeatures.keys()).join(', ')), jsonLanguageTypes_1.ErrorCode.SchemaUnsupportedFeature));
439
453
  }
440
454
  return new ResolvedSchema(schema, resolveErrors, resolveWarnings, schemaDraft);
441
455
  });
@@ -65,11 +65,11 @@
65
65
  }
66
66
  };
67
67
  if (schema.errors.length) {
68
- addSchemaProblem(schema.errors[0], jsonLanguageTypes_1.ErrorCode.SchemaResolveError);
68
+ addSchemaProblem(schema.errors[0].message, schema.errors[0].code);
69
69
  }
70
70
  else if (schemaValidation) {
71
71
  for (const warning of schema.warnings) {
72
- addSchemaProblem(warning, jsonLanguageTypes_1.ErrorCode.SchemaUnsupportedFeature);
72
+ addSchemaProblem(warning.message, warning.code);
73
73
  }
74
74
  const semanticErrors = jsonDocument.validate(textDocument, schema.schema, schemaValidation, documentSettings?.schemaDraft);
75
75
  if (semanticErrors) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vscode-json-languageservice",
3
- "version": "5.6.3",
3
+ "version": "5.7.0",
4
4
  "description": "Language service for JSON",
5
5
  "main": "./lib/umd/jsonLanguageService.js",
6
6
  "typings": "./lib/umd/jsonLanguageService",
@@ -17,12 +17,12 @@
17
17
  "devDependencies": {
18
18
  "@types/mocha": "^10.0.10",
19
19
  "@types/node": "22.x",
20
- "@typescript-eslint/eslint-plugin": "^8.46.3",
21
- "@typescript-eslint/parser": "^8.46.3",
22
- "eslint": "^9.39.0",
20
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
21
+ "@typescript-eslint/parser": "^8.53.0",
22
+ "eslint": "^9.39.2",
23
23
  "json-schema-test-suite": "https://github.com/json-schema-org/JSON-Schema-Test-Suite.git#69acf52990b004240839ae19b4bec8fb01d50876",
24
- "mocha": "^11.7.4",
25
- "rimraf": "^6.1.0",
24
+ "mocha": "^11.7.5",
25
+ "rimraf": "^6.1.2",
26
26
  "typescript": "^5.9.3"
27
27
  },
28
28
  "dependencies": {