vscode-json-languageservice 5.1.1 → 5.1.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/README.md +1 -1
- package/lib/esm/jsonContributions.d.ts +2 -3
- package/lib/esm/jsonLanguageService.d.ts +1 -1
- package/lib/esm/jsonLanguageTypes.d.ts +2 -2
- package/lib/esm/jsonSchema.d.ts +1 -1
- package/lib/esm/parser/jsonParser.js +70 -71
- package/lib/esm/services/configuration.js +47 -51
- package/lib/esm/services/jsonCompletion.js +9 -13
- package/lib/esm/services/jsonSchemaService.js +11 -12
- package/lib/esm/services/jsonValidation.js +2 -3
- package/lib/umd/jsonContributions.d.ts +2 -3
- package/lib/umd/jsonLanguageService.d.ts +1 -1
- package/lib/umd/jsonLanguageTypes.d.ts +2 -2
- package/lib/umd/jsonSchema.d.ts +1 -1
- package/lib/umd/parser/jsonParser.js +71 -72
- package/lib/umd/services/configuration.js +48 -52
- package/lib/umd/services/jsonCompletion.js +10 -14
- package/lib/umd/services/jsonSchemaService.js +12 -13
- package/lib/umd/services/jsonValidation.js +3 -4
- package/package.json +11 -14
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ JSON language service extracted from VSCode to be reused, e.g in the Monaco edit
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.org/package/vscode-json-languageservice)
|
|
6
6
|
[](https://npmjs.org/package/vscode-json-languageservice)
|
|
7
|
-
[](https://github.com/microsoft/vscode-json-languageservice/actions)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
|
|
10
10
|
## Why?
|
|
@@ -6,12 +6,11 @@ export interface JSONWorkerContribution {
|
|
|
6
6
|
collectDefaultCompletions(uri: string, result: CompletionsCollector): Thenable<any>;
|
|
7
7
|
resolveCompletion?(item: CompletionItem): Thenable<CompletionItem>;
|
|
8
8
|
}
|
|
9
|
-
export
|
|
10
|
-
export
|
|
9
|
+
export type Segment = string | number;
|
|
10
|
+
export type JSONPath = Segment[];
|
|
11
11
|
export interface CompletionsCollector {
|
|
12
12
|
add(suggestion: CompletionItem): void;
|
|
13
13
|
error(message: string): void;
|
|
14
|
-
log(message: string): void;
|
|
15
14
|
setAsIncomplete(): void;
|
|
16
15
|
getNumberOfProposals(): number;
|
|
17
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
export
|
|
3
|
+
export type JSONDocument = {
|
|
4
4
|
root: ASTNode | undefined;
|
|
5
5
|
getNodeFromOffset(offset: number, includeRightBound?: boolean): ASTNode | undefined;
|
|
6
6
|
};
|
|
@@ -28,7 +28,7 @@ export declare enum ErrorCode {
|
|
|
28
28
|
SchemaResolveError = 768,
|
|
29
29
|
SchemaUnsupportedFeature = 769
|
|
30
30
|
}
|
|
31
|
-
export
|
|
31
|
+
export type ASTNode = ObjectASTNode | PropertyASTNode | ArrayASTNode | StringASTNode | NumberASTNode | BooleanASTNode | NullASTNode;
|
|
32
32
|
export interface BaseASTNode {
|
|
33
33
|
readonly type: 'object' | 'array' | 'property' | 'string' | 'number' | 'boolean' | 'null';
|
|
34
34
|
readonly parent?: ASTNode;
|
|
@@ -93,7 +93,7 @@ export interface LanguageSettings {
|
|
|
93
93
|
*/
|
|
94
94
|
schemas?: SchemaConfiguration[];
|
|
95
95
|
}
|
|
96
|
-
export
|
|
96
|
+
export type SeverityLevel = 'error' | 'warning' | 'ignore';
|
|
97
97
|
export declare enum SchemaDraft {
|
|
98
98
|
v3 = 3,
|
|
99
99
|
v4 = 4,
|
package/lib/esm/jsonSchema.d.ts
CHANGED
|
@@ -6,17 +6,16 @@ import * as Json from 'jsonc-parser';
|
|
|
6
6
|
import { isNumber, equals, isBoolean, isString, isDefined, isObject } from '../utils/objects';
|
|
7
7
|
import { extendedRegExp, stringLength } from '../utils/strings';
|
|
8
8
|
import { ErrorCode, Diagnostic, DiagnosticSeverity, Range, SchemaDraft } from '../jsonLanguageTypes';
|
|
9
|
-
import * as
|
|
10
|
-
const localize = nls.loadMessageBundle();
|
|
9
|
+
import * as l10n from '@vscode/l10n';
|
|
11
10
|
const formats = {
|
|
12
|
-
'color-hex': { errorMessage:
|
|
13
|
-
'date-time': { errorMessage:
|
|
14
|
-
'date': { errorMessage:
|
|
15
|
-
'time': { errorMessage:
|
|
16
|
-
'email': { errorMessage:
|
|
17
|
-
'hostname': { errorMessage:
|
|
18
|
-
'ipv4': { errorMessage:
|
|
19
|
-
'ipv6': { errorMessage:
|
|
11
|
+
'color-hex': { errorMessage: l10n.t('Invalid color format. Use #RGB, #RGBA, #RRGGBB or #RRGGBBAA.'), pattern: /^#([0-9A-Fa-f]{3,4}|([0-9A-Fa-f]{2}){3,4})$/ },
|
|
12
|
+
'date-time': { errorMessage: l10n.t('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 },
|
|
13
|
+
'date': { errorMessage: l10n.t('String is not a RFC3339 date.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/i },
|
|
14
|
+
'time': { errorMessage: l10n.t('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 },
|
|
15
|
+
'email': { errorMessage: l10n.t('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,}))$/ },
|
|
16
|
+
'hostname': { errorMessage: l10n.t('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 },
|
|
17
|
+
'ipv4': { errorMessage: l10n.t('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)$/ },
|
|
18
|
+
'ipv6': { errorMessage: l10n.t('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 },
|
|
20
19
|
};
|
|
21
20
|
export class ASTNodeImpl {
|
|
22
21
|
constructor(parent, offset, length = 0) {
|
|
@@ -167,7 +166,7 @@ export class ValidationResult {
|
|
|
167
166
|
this.enumValues = this.enumValues.concat(validationResult.enumValues);
|
|
168
167
|
for (const error of this.problems) {
|
|
169
168
|
if (error.code === ErrorCode.EnumValueMismatch) {
|
|
170
|
-
error.message =
|
|
169
|
+
error.message = l10n.t('Value is not accepted. Valid values: {0}.', this.enumValues.map(v => JSON.stringify(v)).join(', '));
|
|
171
170
|
}
|
|
172
171
|
}
|
|
173
172
|
}
|
|
@@ -302,7 +301,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
302
301
|
if (!schema.type.some(matchesType)) {
|
|
303
302
|
validationResult.problems.push({
|
|
304
303
|
location: { offset: node.offset, length: node.length },
|
|
305
|
-
message: schema.errorMessage ||
|
|
304
|
+
message: schema.errorMessage || l10n.t('Incorrect type. Expected one of {0}.', schema.type.join(', '))
|
|
306
305
|
});
|
|
307
306
|
}
|
|
308
307
|
}
|
|
@@ -310,7 +309,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
310
309
|
if (!matchesType(schema.type)) {
|
|
311
310
|
validationResult.problems.push({
|
|
312
311
|
location: { offset: node.offset, length: node.length },
|
|
313
|
-
message: schema.errorMessage ||
|
|
312
|
+
message: schema.errorMessage || l10n.t('Incorrect type. Expected "{0}".', schema.type)
|
|
314
313
|
});
|
|
315
314
|
}
|
|
316
315
|
}
|
|
@@ -331,7 +330,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
331
330
|
if (!subValidationResult.hasProblems()) {
|
|
332
331
|
validationResult.problems.push({
|
|
333
332
|
location: { offset: node.offset, length: node.length },
|
|
334
|
-
message:
|
|
333
|
+
message: l10n.t("Matches a schema that is not allowed.")
|
|
335
334
|
});
|
|
336
335
|
}
|
|
337
336
|
for (const ms of subMatchingSchemas.schemas) {
|
|
@@ -379,7 +378,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
379
378
|
if (matches.length > 1 && maxOneMatch) {
|
|
380
379
|
validationResult.problems.push({
|
|
381
380
|
location: { offset: node.offset, length: 1 },
|
|
382
|
-
message:
|
|
381
|
+
message: l10n.t("Matches multiple schemas when only one must validate.")
|
|
383
382
|
});
|
|
384
383
|
}
|
|
385
384
|
if (bestMatch) {
|
|
@@ -436,7 +435,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
436
435
|
validationResult.problems.push({
|
|
437
436
|
location: { offset: node.offset, length: node.length },
|
|
438
437
|
code: ErrorCode.EnumValueMismatch,
|
|
439
|
-
message: schema.errorMessage ||
|
|
438
|
+
message: schema.errorMessage || l10n.t('Value is not accepted. Valid values: {0}.', schema.enum.map(v => JSON.stringify(v)).join(', '))
|
|
440
439
|
});
|
|
441
440
|
}
|
|
442
441
|
}
|
|
@@ -446,7 +445,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
446
445
|
validationResult.problems.push({
|
|
447
446
|
location: { offset: node.offset, length: node.length },
|
|
448
447
|
code: ErrorCode.EnumValueMismatch,
|
|
449
|
-
message: schema.errorMessage ||
|
|
448
|
+
message: schema.errorMessage || l10n.t('Value must be {0}.', JSON.stringify(schema.const))
|
|
450
449
|
});
|
|
451
450
|
validationResult.enumValueMatch = false;
|
|
452
451
|
}
|
|
@@ -457,7 +456,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
457
456
|
}
|
|
458
457
|
let deprecationMessage = schema.deprecationMessage;
|
|
459
458
|
if ((deprecationMessage || schema.deprecated) && node.parent) {
|
|
460
|
-
deprecationMessage = deprecationMessage ||
|
|
459
|
+
deprecationMessage = deprecationMessage || l10n.t('Value is deprecated');
|
|
461
460
|
validationResult.problems.push({
|
|
462
461
|
location: { offset: node.parent.offset, length: node.parent.length },
|
|
463
462
|
severity: DiagnosticSeverity.Warning,
|
|
@@ -498,7 +497,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
498
497
|
if (remainder !== 0) {
|
|
499
498
|
validationResult.problems.push({
|
|
500
499
|
location: { offset: node.offset, length: node.length },
|
|
501
|
-
message:
|
|
500
|
+
message: l10n.t('Value is not divisible by {0}.', schema.multipleOf)
|
|
502
501
|
});
|
|
503
502
|
}
|
|
504
503
|
}
|
|
@@ -521,28 +520,28 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
521
520
|
if (isNumber(exclusiveMinimum) && val <= exclusiveMinimum) {
|
|
522
521
|
validationResult.problems.push({
|
|
523
522
|
location: { offset: node.offset, length: node.length },
|
|
524
|
-
message:
|
|
523
|
+
message: l10n.t('Value is below the exclusive minimum of {0}.', exclusiveMinimum)
|
|
525
524
|
});
|
|
526
525
|
}
|
|
527
526
|
const exclusiveMaximum = getExclusiveLimit(schema.maximum, schema.exclusiveMaximum);
|
|
528
527
|
if (isNumber(exclusiveMaximum) && val >= exclusiveMaximum) {
|
|
529
528
|
validationResult.problems.push({
|
|
530
529
|
location: { offset: node.offset, length: node.length },
|
|
531
|
-
message:
|
|
530
|
+
message: l10n.t('Value is above the exclusive maximum of {0}.', exclusiveMaximum)
|
|
532
531
|
});
|
|
533
532
|
}
|
|
534
533
|
const minimum = getLimit(schema.minimum, schema.exclusiveMinimum);
|
|
535
534
|
if (isNumber(minimum) && val < minimum) {
|
|
536
535
|
validationResult.problems.push({
|
|
537
536
|
location: { offset: node.offset, length: node.length },
|
|
538
|
-
message:
|
|
537
|
+
message: l10n.t('Value is below the minimum of {0}.', minimum)
|
|
539
538
|
});
|
|
540
539
|
}
|
|
541
540
|
const maximum = getLimit(schema.maximum, schema.exclusiveMaximum);
|
|
542
541
|
if (isNumber(maximum) && val > maximum) {
|
|
543
542
|
validationResult.problems.push({
|
|
544
543
|
location: { offset: node.offset, length: node.length },
|
|
545
|
-
message:
|
|
544
|
+
message: l10n.t('Value is above the maximum of {0}.', maximum)
|
|
546
545
|
});
|
|
547
546
|
}
|
|
548
547
|
}
|
|
@@ -550,13 +549,13 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
550
549
|
if (isNumber(schema.minLength) && stringLength(node.value) < schema.minLength) {
|
|
551
550
|
validationResult.problems.push({
|
|
552
551
|
location: { offset: node.offset, length: node.length },
|
|
553
|
-
message:
|
|
552
|
+
message: l10n.t('String is shorter than the minimum length of {0}.', schema.minLength)
|
|
554
553
|
});
|
|
555
554
|
}
|
|
556
555
|
if (isNumber(schema.maxLength) && stringLength(node.value) > schema.maxLength) {
|
|
557
556
|
validationResult.problems.push({
|
|
558
557
|
location: { offset: node.offset, length: node.length },
|
|
559
|
-
message:
|
|
558
|
+
message: l10n.t('String is longer than the maximum length of {0}.', schema.maxLength)
|
|
560
559
|
});
|
|
561
560
|
}
|
|
562
561
|
if (isString(schema.pattern)) {
|
|
@@ -564,7 +563,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
564
563
|
if (!(regex?.test(node.value))) {
|
|
565
564
|
validationResult.problems.push({
|
|
566
565
|
location: { offset: node.offset, length: node.length },
|
|
567
|
-
message: schema.patternErrorMessage || schema.errorMessage ||
|
|
566
|
+
message: schema.patternErrorMessage || schema.errorMessage || l10n.t('String does not match the pattern of "{0}".', schema.pattern)
|
|
568
567
|
});
|
|
569
568
|
}
|
|
570
569
|
}
|
|
@@ -575,21 +574,21 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
575
574
|
{
|
|
576
575
|
let errorMessage;
|
|
577
576
|
if (!node.value) {
|
|
578
|
-
errorMessage =
|
|
577
|
+
errorMessage = l10n.t('URI expected.');
|
|
579
578
|
}
|
|
580
579
|
else {
|
|
581
580
|
const match = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(node.value);
|
|
582
581
|
if (!match) {
|
|
583
|
-
errorMessage =
|
|
582
|
+
errorMessage = l10n.t('URI is expected.');
|
|
584
583
|
}
|
|
585
584
|
else if (!match[2] && schema.format === 'uri') {
|
|
586
|
-
errorMessage =
|
|
585
|
+
errorMessage = l10n.t('URI with a scheme is expected.');
|
|
587
586
|
}
|
|
588
587
|
}
|
|
589
588
|
if (errorMessage) {
|
|
590
589
|
validationResult.problems.push({
|
|
591
590
|
location: { offset: node.offset, length: node.length },
|
|
592
|
-
message: schema.patternErrorMessage || schema.errorMessage ||
|
|
591
|
+
message: schema.patternErrorMessage || schema.errorMessage || l10n.t('String is not a URI: {0}', errorMessage)
|
|
593
592
|
});
|
|
594
593
|
}
|
|
595
594
|
}
|
|
@@ -644,7 +643,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
644
643
|
if (additionalItemSchema === false) {
|
|
645
644
|
validationResult.problems.push({
|
|
646
645
|
location: { offset: node.offset, length: node.length },
|
|
647
|
-
message:
|
|
646
|
+
message: l10n.t('Array has too many items according to schema. Expected {0} or fewer.', index)
|
|
648
647
|
});
|
|
649
648
|
}
|
|
650
649
|
for (; index < node.items.length; index++) {
|
|
@@ -678,19 +677,19 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
678
677
|
if (containsCount === 0 && !isNumber(schema.minContains)) {
|
|
679
678
|
validationResult.problems.push({
|
|
680
679
|
location: { offset: node.offset, length: node.length },
|
|
681
|
-
message: schema.errorMessage ||
|
|
680
|
+
message: schema.errorMessage || l10n.t('Array does not contain required item.')
|
|
682
681
|
});
|
|
683
682
|
}
|
|
684
683
|
if (isNumber(schema.minContains) && containsCount < schema.minContains) {
|
|
685
684
|
validationResult.problems.push({
|
|
686
685
|
location: { offset: node.offset, length: node.length },
|
|
687
|
-
message:
|
|
686
|
+
message: l10n.t('Array has too few items that match the contains contraint. Expected {0} or more.', schema.minContains)
|
|
688
687
|
});
|
|
689
688
|
}
|
|
690
689
|
if (isNumber(schema.maxContains) && containsCount > schema.maxContains) {
|
|
691
690
|
validationResult.problems.push({
|
|
692
691
|
location: { offset: node.offset, length: node.length },
|
|
693
|
-
message:
|
|
692
|
+
message: l10n.t('Array has too many items that match the contains contraint. Expected {0} or less.', schema.maxContains)
|
|
694
693
|
});
|
|
695
694
|
}
|
|
696
695
|
}
|
|
@@ -701,7 +700,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
701
700
|
if (unevaluatedItems === false) {
|
|
702
701
|
validationResult.problems.push({
|
|
703
702
|
location: { offset: node.offset, length: node.length },
|
|
704
|
-
message:
|
|
703
|
+
message: l10n.t('Item does not match any validation rule from the array.')
|
|
705
704
|
});
|
|
706
705
|
}
|
|
707
706
|
else {
|
|
@@ -717,13 +716,13 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
717
716
|
if (isNumber(schema.minItems) && node.items.length < schema.minItems) {
|
|
718
717
|
validationResult.problems.push({
|
|
719
718
|
location: { offset: node.offset, length: node.length },
|
|
720
|
-
message:
|
|
719
|
+
message: l10n.t('Array has too few items. Expected {0} or more.', schema.minItems)
|
|
721
720
|
});
|
|
722
721
|
}
|
|
723
722
|
if (isNumber(schema.maxItems) && node.items.length > schema.maxItems) {
|
|
724
723
|
validationResult.problems.push({
|
|
725
724
|
location: { offset: node.offset, length: node.length },
|
|
726
|
-
message:
|
|
725
|
+
message: l10n.t('Array has too many items. Expected {0} or fewer.', schema.maxItems)
|
|
727
726
|
});
|
|
728
727
|
}
|
|
729
728
|
if (schema.uniqueItems === true) {
|
|
@@ -734,7 +733,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
734
733
|
if (duplicates) {
|
|
735
734
|
validationResult.problems.push({
|
|
736
735
|
location: { offset: node.offset, length: node.length },
|
|
737
|
-
message:
|
|
736
|
+
message: l10n.t('Array has duplicate items.')
|
|
738
737
|
});
|
|
739
738
|
}
|
|
740
739
|
}
|
|
@@ -754,7 +753,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
754
753
|
const location = keyNode ? { offset: keyNode.offset, length: keyNode.length } : { offset: node.offset, length: 1 };
|
|
755
754
|
validationResult.problems.push({
|
|
756
755
|
location: location,
|
|
757
|
-
message:
|
|
756
|
+
message: l10n.t('Missing property "{0}".', propertyName)
|
|
758
757
|
});
|
|
759
758
|
}
|
|
760
759
|
}
|
|
@@ -774,7 +773,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
774
773
|
const propertyNode = child.parent;
|
|
775
774
|
validationResult.problems.push({
|
|
776
775
|
location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
|
|
777
|
-
message: schema.errorMessage ||
|
|
776
|
+
message: schema.errorMessage || l10n.t('Property {0} is not allowed.', propertyName)
|
|
778
777
|
});
|
|
779
778
|
}
|
|
780
779
|
else {
|
|
@@ -806,7 +805,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
806
805
|
const propertyNode = child.parent;
|
|
807
806
|
validationResult.problems.push({
|
|
808
807
|
location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
|
|
809
|
-
message: schema.errorMessage ||
|
|
808
|
+
message: schema.errorMessage || l10n.t('Property {0} is not allowed.', propertyName)
|
|
810
809
|
});
|
|
811
810
|
}
|
|
812
811
|
else {
|
|
@@ -836,7 +835,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
836
835
|
const propertyNode = child.parent;
|
|
837
836
|
validationResult.problems.push({
|
|
838
837
|
location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
|
|
839
|
-
message: schema.errorMessage ||
|
|
838
|
+
message: schema.errorMessage || l10n.t('Property {0} is not allowed.', propertyName)
|
|
840
839
|
});
|
|
841
840
|
}
|
|
842
841
|
else if (additionalProperties !== true) {
|
|
@@ -859,7 +858,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
859
858
|
const propertyNode = child.parent;
|
|
860
859
|
validationResult.problems.push({
|
|
861
860
|
location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
|
|
862
|
-
message: schema.errorMessage ||
|
|
861
|
+
message: schema.errorMessage || l10n.t('Property {0} is not allowed.', propertyName)
|
|
863
862
|
});
|
|
864
863
|
}
|
|
865
864
|
else if (unevaluatedProperties !== true) {
|
|
@@ -876,7 +875,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
876
875
|
if (node.properties.length > schema.maxProperties) {
|
|
877
876
|
validationResult.problems.push({
|
|
878
877
|
location: { offset: node.offset, length: node.length },
|
|
879
|
-
message:
|
|
878
|
+
message: l10n.t('Object has more properties than limit of {0}.', schema.maxProperties)
|
|
880
879
|
});
|
|
881
880
|
}
|
|
882
881
|
}
|
|
@@ -884,7 +883,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
884
883
|
if (node.properties.length < schema.minProperties) {
|
|
885
884
|
validationResult.problems.push({
|
|
886
885
|
location: { offset: node.offset, length: node.length },
|
|
887
|
-
message:
|
|
886
|
+
message: l10n.t('Object has fewer properties than the required number of {0}', schema.minProperties)
|
|
888
887
|
});
|
|
889
888
|
}
|
|
890
889
|
}
|
|
@@ -929,7 +928,7 @@ function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
|
929
928
|
if (!seenKeys[requiredProp]) {
|
|
930
929
|
validationResult.problems.push({
|
|
931
930
|
location: { offset: node.offset, length: node.length },
|
|
932
|
-
message:
|
|
931
|
+
message: l10n.t('Object is missing property {0} required by property {1}.', requiredProp, key)
|
|
933
932
|
});
|
|
934
933
|
}
|
|
935
934
|
else {
|
|
@@ -1019,22 +1018,22 @@ export function parse(textDocument, config) {
|
|
|
1019
1018
|
function _checkScanError() {
|
|
1020
1019
|
switch (scanner.getTokenError()) {
|
|
1021
1020
|
case 4 /* Json.ScanError.InvalidUnicode */:
|
|
1022
|
-
_error(
|
|
1021
|
+
_error(l10n.t('Invalid unicode sequence in string.'), ErrorCode.InvalidUnicode);
|
|
1023
1022
|
return true;
|
|
1024
1023
|
case 5 /* Json.ScanError.InvalidEscapeCharacter */:
|
|
1025
|
-
_error(
|
|
1024
|
+
_error(l10n.t('Invalid escape character in string.'), ErrorCode.InvalidEscapeCharacter);
|
|
1026
1025
|
return true;
|
|
1027
1026
|
case 3 /* Json.ScanError.UnexpectedEndOfNumber */:
|
|
1028
|
-
_error(
|
|
1027
|
+
_error(l10n.t('Unexpected end of number.'), ErrorCode.UnexpectedEndOfNumber);
|
|
1029
1028
|
return true;
|
|
1030
1029
|
case 1 /* Json.ScanError.UnexpectedEndOfComment */:
|
|
1031
|
-
_error(
|
|
1030
|
+
_error(l10n.t('Unexpected end of comment.'), ErrorCode.UnexpectedEndOfComment);
|
|
1032
1031
|
return true;
|
|
1033
1032
|
case 2 /* Json.ScanError.UnexpectedEndOfString */:
|
|
1034
|
-
_error(
|
|
1033
|
+
_error(l10n.t('Unexpected end of string.'), ErrorCode.UnexpectedEndOfString);
|
|
1035
1034
|
return true;
|
|
1036
1035
|
case 6 /* Json.ScanError.InvalidCharacter */:
|
|
1037
|
-
_error(
|
|
1036
|
+
_error(l10n.t('Invalid characters in string. Control characters must be escaped.'), ErrorCode.InvalidCharacter);
|
|
1038
1037
|
return true;
|
|
1039
1038
|
}
|
|
1040
1039
|
return false;
|
|
@@ -1057,23 +1056,23 @@ export function parse(textDocument, config) {
|
|
|
1057
1056
|
while (scanner.getToken() !== 4 /* Json.SyntaxKind.CloseBracketToken */ && scanner.getToken() !== 17 /* Json.SyntaxKind.EOF */) {
|
|
1058
1057
|
if (scanner.getToken() === 5 /* Json.SyntaxKind.CommaToken */) {
|
|
1059
1058
|
if (!needsComma) {
|
|
1060
|
-
_error(
|
|
1059
|
+
_error(l10n.t('Value expected'), ErrorCode.ValueExpected);
|
|
1061
1060
|
}
|
|
1062
1061
|
const commaOffset = scanner.getTokenOffset();
|
|
1063
1062
|
_scanNext(); // consume comma
|
|
1064
1063
|
if (scanner.getToken() === 4 /* Json.SyntaxKind.CloseBracketToken */) {
|
|
1065
1064
|
if (needsComma) {
|
|
1066
|
-
_errorAtRange(
|
|
1065
|
+
_errorAtRange(l10n.t('Trailing comma'), ErrorCode.TrailingComma, commaOffset, commaOffset + 1);
|
|
1067
1066
|
}
|
|
1068
1067
|
continue;
|
|
1069
1068
|
}
|
|
1070
1069
|
}
|
|
1071
1070
|
else if (needsComma) {
|
|
1072
|
-
_error(
|
|
1071
|
+
_error(l10n.t('Expected comma'), ErrorCode.CommaExpected);
|
|
1073
1072
|
}
|
|
1074
1073
|
const item = _parseValue(node);
|
|
1075
1074
|
if (!item) {
|
|
1076
|
-
_error(
|
|
1075
|
+
_error(l10n.t('Value expected'), ErrorCode.ValueExpected, undefined, [], [4 /* Json.SyntaxKind.CloseBracketToken */, 5 /* Json.SyntaxKind.CommaToken */]);
|
|
1077
1076
|
}
|
|
1078
1077
|
else {
|
|
1079
1078
|
node.items.push(item);
|
|
@@ -1081,7 +1080,7 @@ export function parse(textDocument, config) {
|
|
|
1081
1080
|
needsComma = true;
|
|
1082
1081
|
}
|
|
1083
1082
|
if (scanner.getToken() !== 4 /* Json.SyntaxKind.CloseBracketToken */) {
|
|
1084
|
-
return _error(
|
|
1083
|
+
return _error(l10n.t('Expected comma or closing bracket'), ErrorCode.CommaOrCloseBacketExpected, node);
|
|
1085
1084
|
}
|
|
1086
1085
|
return _finalize(node, true);
|
|
1087
1086
|
}
|
|
@@ -1092,7 +1091,7 @@ export function parse(textDocument, config) {
|
|
|
1092
1091
|
if (!key) {
|
|
1093
1092
|
if (scanner.getToken() === 16 /* Json.SyntaxKind.Unknown */) {
|
|
1094
1093
|
// give a more helpful error message
|
|
1095
|
-
_error(
|
|
1094
|
+
_error(l10n.t('Property keys must be doublequoted'), ErrorCode.Undefined);
|
|
1096
1095
|
const keyNode = new StringASTNodeImpl(node, scanner.getTokenOffset(), scanner.getTokenLength());
|
|
1097
1096
|
keyNode.value = scanner.getTokenValue();
|
|
1098
1097
|
key = keyNode;
|
|
@@ -1108,9 +1107,9 @@ export function parse(textDocument, config) {
|
|
|
1108
1107
|
if (key.value !== "//") {
|
|
1109
1108
|
const seen = keysSeen[key.value];
|
|
1110
1109
|
if (seen) {
|
|
1111
|
-
_errorAtRange(
|
|
1110
|
+
_errorAtRange(l10n.t("Duplicate object key"), ErrorCode.DuplicateKey, node.keyNode.offset, node.keyNode.offset + node.keyNode.length, DiagnosticSeverity.Warning);
|
|
1112
1111
|
if (isObject(seen)) {
|
|
1113
|
-
_errorAtRange(
|
|
1112
|
+
_errorAtRange(l10n.t("Duplicate object key"), ErrorCode.DuplicateKey, seen.keyNode.offset, seen.keyNode.offset + seen.keyNode.length, DiagnosticSeverity.Warning);
|
|
1114
1113
|
}
|
|
1115
1114
|
keysSeen[key.value] = true; // if the same key is duplicate again, avoid duplicate error reporting
|
|
1116
1115
|
}
|
|
@@ -1123,7 +1122,7 @@ export function parse(textDocument, config) {
|
|
|
1123
1122
|
_scanNext(); // consume ColonToken
|
|
1124
1123
|
}
|
|
1125
1124
|
else {
|
|
1126
|
-
_error(
|
|
1125
|
+
_error(l10n.t('Colon expected'), ErrorCode.ColonExpected);
|
|
1127
1126
|
if (scanner.getToken() === 10 /* Json.SyntaxKind.StringLiteral */ && textDocument.positionAt(key.offset + key.length).line < textDocument.positionAt(scanner.getTokenOffset()).line) {
|
|
1128
1127
|
node.length = key.length;
|
|
1129
1128
|
return node;
|
|
@@ -1131,7 +1130,7 @@ export function parse(textDocument, config) {
|
|
|
1131
1130
|
}
|
|
1132
1131
|
const value = _parseValue(node);
|
|
1133
1132
|
if (!value) {
|
|
1134
|
-
return _error(
|
|
1133
|
+
return _error(l10n.t('Value expected'), ErrorCode.ValueExpected, node, [], [2 /* Json.SyntaxKind.CloseBraceToken */, 5 /* Json.SyntaxKind.CommaToken */]);
|
|
1135
1134
|
}
|
|
1136
1135
|
node.valueNode = value;
|
|
1137
1136
|
node.length = value.offset + value.length - node.offset;
|
|
@@ -1148,23 +1147,23 @@ export function parse(textDocument, config) {
|
|
|
1148
1147
|
while (scanner.getToken() !== 2 /* Json.SyntaxKind.CloseBraceToken */ && scanner.getToken() !== 17 /* Json.SyntaxKind.EOF */) {
|
|
1149
1148
|
if (scanner.getToken() === 5 /* Json.SyntaxKind.CommaToken */) {
|
|
1150
1149
|
if (!needsComma) {
|
|
1151
|
-
_error(
|
|
1150
|
+
_error(l10n.t('Property expected'), ErrorCode.PropertyExpected);
|
|
1152
1151
|
}
|
|
1153
1152
|
const commaOffset = scanner.getTokenOffset();
|
|
1154
1153
|
_scanNext(); // consume comma
|
|
1155
1154
|
if (scanner.getToken() === 2 /* Json.SyntaxKind.CloseBraceToken */) {
|
|
1156
1155
|
if (needsComma) {
|
|
1157
|
-
_errorAtRange(
|
|
1156
|
+
_errorAtRange(l10n.t('Trailing comma'), ErrorCode.TrailingComma, commaOffset, commaOffset + 1);
|
|
1158
1157
|
}
|
|
1159
1158
|
continue;
|
|
1160
1159
|
}
|
|
1161
1160
|
}
|
|
1162
1161
|
else if (needsComma) {
|
|
1163
|
-
_error(
|
|
1162
|
+
_error(l10n.t('Expected comma'), ErrorCode.CommaExpected);
|
|
1164
1163
|
}
|
|
1165
1164
|
const property = _parseProperty(node, keysSeen);
|
|
1166
1165
|
if (!property) {
|
|
1167
|
-
_error(
|
|
1166
|
+
_error(l10n.t('Property expected'), ErrorCode.PropertyExpected, undefined, [], [2 /* Json.SyntaxKind.CloseBraceToken */, 5 /* Json.SyntaxKind.CommaToken */]);
|
|
1168
1167
|
}
|
|
1169
1168
|
else {
|
|
1170
1169
|
node.properties.push(property);
|
|
@@ -1172,7 +1171,7 @@ export function parse(textDocument, config) {
|
|
|
1172
1171
|
needsComma = true;
|
|
1173
1172
|
}
|
|
1174
1173
|
if (scanner.getToken() !== 2 /* Json.SyntaxKind.CloseBraceToken */) {
|
|
1175
|
-
return _error(
|
|
1174
|
+
return _error(l10n.t('Expected comma or closing brace'), ErrorCode.CommaOrCloseBraceExpected, node);
|
|
1176
1175
|
}
|
|
1177
1176
|
return _finalize(node, true);
|
|
1178
1177
|
}
|
|
@@ -1194,12 +1193,12 @@ export function parse(textDocument, config) {
|
|
|
1194
1193
|
try {
|
|
1195
1194
|
const numberValue = JSON.parse(tokenValue);
|
|
1196
1195
|
if (!isNumber(numberValue)) {
|
|
1197
|
-
return _error(
|
|
1196
|
+
return _error(l10n.t('Invalid number format.'), ErrorCode.Undefined, node);
|
|
1198
1197
|
}
|
|
1199
1198
|
node.value = numberValue;
|
|
1200
1199
|
}
|
|
1201
1200
|
catch (e) {
|
|
1202
|
-
return _error(
|
|
1201
|
+
return _error(l10n.t('Invalid number format.'), ErrorCode.Undefined, node);
|
|
1203
1202
|
}
|
|
1204
1203
|
node.isInteger = tokenValue.indexOf('.') === -1;
|
|
1205
1204
|
}
|
|
@@ -1226,10 +1225,10 @@ export function parse(textDocument, config) {
|
|
|
1226
1225
|
if (token !== 17 /* Json.SyntaxKind.EOF */) {
|
|
1227
1226
|
_root = _parseValue(_root);
|
|
1228
1227
|
if (!_root) {
|
|
1229
|
-
_error(
|
|
1228
|
+
_error(l10n.t('Expected a JSON object, array or literal.'), ErrorCode.Undefined);
|
|
1230
1229
|
}
|
|
1231
1230
|
else if (scanner.getToken() !== 17 /* Json.SyntaxKind.EOF */) {
|
|
1232
|
-
_error(
|
|
1231
|
+
_error(l10n.t('End of file expected.'), ErrorCode.Undefined);
|
|
1233
1232
|
}
|
|
1234
1233
|
}
|
|
1235
1234
|
return new JSONDocument(_root, problems, commentRanges);
|