vscode-json-languageservice 5.1.0 → 5.1.1
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 +5 -0
- package/lib/esm/jsonLanguageTypes.d.ts +12 -0
- package/lib/esm/jsonLanguageTypes.js +9 -0
- package/lib/esm/parser/jsonParser.js +66 -48
- package/lib/esm/services/jsonSchemaService.js +9 -2
- package/lib/esm/services/jsonValidation.js +1 -1
- package/lib/esm/utils/strings.js +15 -0
- package/lib/umd/jsonLanguageTypes.d.ts +12 -0
- package/lib/umd/jsonLanguageTypes.js +10 -1
- package/lib/umd/parser/jsonParser.js +64 -46
- package/lib/umd/services/jsonSchemaService.js +9 -2
- package/lib/umd/services/jsonValidation.js +1 -1
- package/lib/umd/utils/strings.js +17 -1
- package/package.json +11 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
5.2.0 / 2022-08/19
|
|
2
|
+
================
|
|
3
|
+
* new type `SchemaDraft`, representing the offical JSON schema draft versions
|
|
4
|
+
* new property `DocumentLanguageSettings.schemaDraft` to specify the schema version to use, if the schema does not contain a `$schema` property
|
|
5
|
+
|
|
1
6
|
5.1.0 / 2022-07-11
|
|
2
7
|
================
|
|
3
8
|
* new API option `FormattingOptions.keepLines` to indicate the formatter should keep the initial line positions
|
|
@@ -94,6 +94,14 @@ export interface LanguageSettings {
|
|
|
94
94
|
schemas?: SchemaConfiguration[];
|
|
95
95
|
}
|
|
96
96
|
export declare type SeverityLevel = 'error' | 'warning' | 'ignore';
|
|
97
|
+
export declare enum SchemaDraft {
|
|
98
|
+
v3 = 3,
|
|
99
|
+
v4 = 4,
|
|
100
|
+
v6 = 6,
|
|
101
|
+
v7 = 7,
|
|
102
|
+
v2019_09 = 19,
|
|
103
|
+
v2020_12 = 20
|
|
104
|
+
}
|
|
97
105
|
export interface DocumentLanguageSettings {
|
|
98
106
|
/**
|
|
99
107
|
* The severity of reported comments. If not set, 'LanguageSettings.allowComments' defines whether comments are ignored or reported as errors.
|
|
@@ -111,6 +119,10 @@ export interface DocumentLanguageSettings {
|
|
|
111
119
|
* The severity of problems that occurred when resolving and loading schemas. If set to 'ignore', schema resolving problems are not reported. If not set, 'warning' is used.
|
|
112
120
|
*/
|
|
113
121
|
schemaRequest?: SeverityLevel;
|
|
122
|
+
/**
|
|
123
|
+
* The draft version of schema to use if the schema doesn't specify one at $schema
|
|
124
|
+
*/
|
|
125
|
+
schemaDraft?: SchemaDraft;
|
|
114
126
|
}
|
|
115
127
|
export interface SchemaConfiguration {
|
|
116
128
|
/**
|
|
@@ -31,6 +31,15 @@ export var ErrorCode;
|
|
|
31
31
|
ErrorCode[ErrorCode["SchemaResolveError"] = 768] = "SchemaResolveError";
|
|
32
32
|
ErrorCode[ErrorCode["SchemaUnsupportedFeature"] = 769] = "SchemaUnsupportedFeature";
|
|
33
33
|
})(ErrorCode || (ErrorCode = {}));
|
|
34
|
+
export var SchemaDraft;
|
|
35
|
+
(function (SchemaDraft) {
|
|
36
|
+
SchemaDraft[SchemaDraft["v3"] = 3] = "v3";
|
|
37
|
+
SchemaDraft[SchemaDraft["v4"] = 4] = "v4";
|
|
38
|
+
SchemaDraft[SchemaDraft["v6"] = 6] = "v6";
|
|
39
|
+
SchemaDraft[SchemaDraft["v7"] = 7] = "v7";
|
|
40
|
+
SchemaDraft[SchemaDraft["v2019_09"] = 19] = "v2019_09";
|
|
41
|
+
SchemaDraft[SchemaDraft["v2020_12"] = 20] = "v2020_12";
|
|
42
|
+
})(SchemaDraft || (SchemaDraft = {}));
|
|
34
43
|
export var ClientCapabilities;
|
|
35
44
|
(function (ClientCapabilities) {
|
|
36
45
|
ClientCapabilities.LATEST = {
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as Json from 'jsonc-parser';
|
|
6
6
|
import { isNumber, equals, isBoolean, isString, isDefined, isObject } from '../utils/objects';
|
|
7
|
-
import { extendedRegExp } from '../utils/strings';
|
|
8
|
-
import { ErrorCode, Diagnostic, DiagnosticSeverity, Range } from '../jsonLanguageTypes';
|
|
7
|
+
import { extendedRegExp, stringLength } from '../utils/strings';
|
|
8
|
+
import { ErrorCode, Diagnostic, DiagnosticSeverity, Range, SchemaDraft } from '../jsonLanguageTypes';
|
|
9
9
|
import * as nls from 'vscode-nls';
|
|
10
10
|
const localize = nls.loadMessageBundle();
|
|
11
11
|
const formats = {
|
|
@@ -102,6 +102,19 @@ export var EnumMatch;
|
|
|
102
102
|
EnumMatch[EnumMatch["Key"] = 0] = "Key";
|
|
103
103
|
EnumMatch[EnumMatch["Enum"] = 1] = "Enum";
|
|
104
104
|
})(EnumMatch || (EnumMatch = {}));
|
|
105
|
+
const schemaDraftFromId = {
|
|
106
|
+
'http://json-schema.org/draft-03/schema#': SchemaDraft.v3,
|
|
107
|
+
'http://json-schema.org/draft-04/schema#': SchemaDraft.v4,
|
|
108
|
+
'http://json-schema.org/draft-06/schema#': SchemaDraft.v6,
|
|
109
|
+
'http://json-schema.org/draft-07/schema#': SchemaDraft.v7,
|
|
110
|
+
'https://json-schema.org/draft/2019-09/schema': SchemaDraft.v2019_09,
|
|
111
|
+
'https://json-schema.org/draft/2020-12/schema': SchemaDraft.v2020_12
|
|
112
|
+
};
|
|
113
|
+
class EvaluationContext {
|
|
114
|
+
constructor(schemaDraft) {
|
|
115
|
+
this.schemaDraft = schemaDraft;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
105
118
|
class SchemaCollector {
|
|
106
119
|
constructor(focusOffset = -1, exclude) {
|
|
107
120
|
this.focusOffset = focusOffset;
|
|
@@ -124,9 +137,9 @@ class SchemaCollector {
|
|
|
124
137
|
class NoOpSchemaCollector {
|
|
125
138
|
constructor() { }
|
|
126
139
|
get schemas() { return []; }
|
|
127
|
-
add(
|
|
128
|
-
merge(
|
|
129
|
-
include(
|
|
140
|
+
add(_schema) { }
|
|
141
|
+
merge(_other) { }
|
|
142
|
+
include(_node) { return true; }
|
|
130
143
|
newSub() { return this; }
|
|
131
144
|
}
|
|
132
145
|
NoOpSchemaCollector.instance = new NoOpSchemaCollector();
|
|
@@ -143,13 +156,11 @@ export class ValidationResult {
|
|
|
143
156
|
hasProblems() {
|
|
144
157
|
return !!this.problems.length;
|
|
145
158
|
}
|
|
146
|
-
mergeAll(validationResults) {
|
|
147
|
-
for (const validationResult of validationResults) {
|
|
148
|
-
this.merge(validationResult);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
159
|
merge(validationResult) {
|
|
152
160
|
this.problems = this.problems.concat(validationResult.problems);
|
|
161
|
+
this.propertiesMatches += validationResult.propertiesMatches;
|
|
162
|
+
this.propertiesValueMatches += validationResult.propertiesValueMatches;
|
|
163
|
+
this.mergeProcessedProperties(validationResult);
|
|
153
164
|
}
|
|
154
165
|
mergeEnumValues(validationResult) {
|
|
155
166
|
if (!this.enumValueMatch && !validationResult.enumValueMatch && this.enumValues && validationResult.enumValues) {
|
|
@@ -162,7 +173,7 @@ export class ValidationResult {
|
|
|
162
173
|
}
|
|
163
174
|
}
|
|
164
175
|
mergePropertyMatch(propertyValidationResult) {
|
|
165
|
-
this.
|
|
176
|
+
this.problems = this.problems.concat(propertyValidationResult.problems);
|
|
166
177
|
this.propertiesMatches++;
|
|
167
178
|
if (propertyValidationResult.enumValueMatch || !propertyValidationResult.hasProblems() && propertyValidationResult.propertiesMatches) {
|
|
168
179
|
this.propertiesValueMatches++;
|
|
@@ -230,10 +241,10 @@ export class JSONDocument {
|
|
|
230
241
|
doVisit(this.root);
|
|
231
242
|
}
|
|
232
243
|
}
|
|
233
|
-
validate(textDocument, schema, severity = DiagnosticSeverity.Warning) {
|
|
244
|
+
validate(textDocument, schema, severity = DiagnosticSeverity.Warning, schemaDraft) {
|
|
234
245
|
if (this.root && schema) {
|
|
235
246
|
const validationResult = new ValidationResult();
|
|
236
|
-
validate(this.root, schema, validationResult, NoOpSchemaCollector.instance);
|
|
247
|
+
validate(this.root, schema, validationResult, NoOpSchemaCollector.instance, new EvaluationContext(schemaDraft ?? getSchemaDraft(schema)));
|
|
237
248
|
return validationResult.problems.map(p => {
|
|
238
249
|
const range = Range.create(textDocument.positionAt(p.location.offset), textDocument.positionAt(p.location.offset + p.location.length));
|
|
239
250
|
return Diagnostic.create(range, p.message, p.severity ?? severity, p.code);
|
|
@@ -242,19 +253,29 @@ export class JSONDocument {
|
|
|
242
253
|
return undefined;
|
|
243
254
|
}
|
|
244
255
|
getMatchingSchemas(schema, focusOffset = -1, exclude) {
|
|
245
|
-
const matchingSchemas = new SchemaCollector(focusOffset, exclude);
|
|
246
256
|
if (this.root && schema) {
|
|
247
|
-
|
|
257
|
+
const matchingSchemas = new SchemaCollector(focusOffset, exclude);
|
|
258
|
+
const schemaDraft = getSchemaDraft(schema);
|
|
259
|
+
const context = new EvaluationContext(schemaDraft);
|
|
260
|
+
validate(this.root, schema, new ValidationResult(), matchingSchemas, context);
|
|
261
|
+
return matchingSchemas.schemas;
|
|
248
262
|
}
|
|
249
|
-
return
|
|
263
|
+
return [];
|
|
250
264
|
}
|
|
251
265
|
}
|
|
252
|
-
function
|
|
266
|
+
function getSchemaDraft(schema, fallBack = SchemaDraft.v2020_12) {
|
|
267
|
+
let schemaId = schema.$schema;
|
|
268
|
+
if (schemaId) {
|
|
269
|
+
return schemaDraftFromId[schemaId] ?? fallBack;
|
|
270
|
+
}
|
|
271
|
+
return fallBack;
|
|
272
|
+
}
|
|
273
|
+
function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
253
274
|
if (!n || !matchingSchemas.include(n)) {
|
|
254
275
|
return;
|
|
255
276
|
}
|
|
256
277
|
if (n.type === 'property') {
|
|
257
|
-
return validate(n.valueNode, schema, validationResult, matchingSchemas);
|
|
278
|
+
return validate(n.valueNode, schema, validationResult, matchingSchemas, context);
|
|
258
279
|
}
|
|
259
280
|
const node = n;
|
|
260
281
|
_validateNode();
|
|
@@ -295,14 +316,18 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
295
316
|
}
|
|
296
317
|
if (Array.isArray(schema.allOf)) {
|
|
297
318
|
for (const subSchemaRef of schema.allOf) {
|
|
298
|
-
|
|
319
|
+
const subValidationResult = new ValidationResult();
|
|
320
|
+
const subMatchingSchemas = matchingSchemas.newSub();
|
|
321
|
+
validate(node, asSchema(subSchemaRef), subValidationResult, subMatchingSchemas, context);
|
|
322
|
+
validationResult.merge(subValidationResult);
|
|
323
|
+
matchingSchemas.merge(subMatchingSchemas);
|
|
299
324
|
}
|
|
300
325
|
}
|
|
301
326
|
const notSchema = asSchema(schema.not);
|
|
302
327
|
if (notSchema) {
|
|
303
328
|
const subValidationResult = new ValidationResult();
|
|
304
329
|
const subMatchingSchemas = matchingSchemas.newSub();
|
|
305
|
-
validate(node, notSchema, subValidationResult, subMatchingSchemas);
|
|
330
|
+
validate(node, notSchema, subValidationResult, subMatchingSchemas, context);
|
|
306
331
|
if (!subValidationResult.hasProblems()) {
|
|
307
332
|
validationResult.problems.push({
|
|
308
333
|
location: { offset: node.offset, length: node.length },
|
|
@@ -322,7 +347,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
322
347
|
const subSchema = asSchema(subSchemaRef);
|
|
323
348
|
const subValidationResult = new ValidationResult();
|
|
324
349
|
const subMatchingSchemas = matchingSchemas.newSub();
|
|
325
|
-
validate(node, subSchema, subValidationResult, subMatchingSchemas);
|
|
350
|
+
validate(node, subSchema, subValidationResult, subMatchingSchemas, context);
|
|
326
351
|
if (!subValidationResult.hasProblems()) {
|
|
327
352
|
matches.push(subSchema);
|
|
328
353
|
}
|
|
@@ -359,9 +384,6 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
359
384
|
}
|
|
360
385
|
if (bestMatch) {
|
|
361
386
|
validationResult.merge(bestMatch.validationResult);
|
|
362
|
-
validationResult.propertiesMatches += bestMatch.validationResult.propertiesMatches;
|
|
363
|
-
validationResult.propertiesValueMatches += bestMatch.validationResult.propertiesValueMatches;
|
|
364
|
-
validationResult.mergeProcessedProperties(bestMatch.validationResult);
|
|
365
387
|
matchingSchemas.merge(bestMatch.matchingSchemas);
|
|
366
388
|
}
|
|
367
389
|
return matches.length;
|
|
@@ -375,18 +397,15 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
375
397
|
const testBranch = (schema) => {
|
|
376
398
|
const subValidationResult = new ValidationResult();
|
|
377
399
|
const subMatchingSchemas = matchingSchemas.newSub();
|
|
378
|
-
validate(node, asSchema(schema), subValidationResult, subMatchingSchemas);
|
|
400
|
+
validate(node, asSchema(schema), subValidationResult, subMatchingSchemas, context);
|
|
379
401
|
validationResult.merge(subValidationResult);
|
|
380
|
-
validationResult.propertiesMatches += subValidationResult.propertiesMatches;
|
|
381
|
-
validationResult.propertiesValueMatches += subValidationResult.propertiesValueMatches;
|
|
382
|
-
validationResult.mergeProcessedProperties(subValidationResult);
|
|
383
402
|
matchingSchemas.merge(subMatchingSchemas);
|
|
384
403
|
};
|
|
385
404
|
const testCondition = (ifSchema, thenSchema, elseSchema) => {
|
|
386
405
|
const subSchema = asSchema(ifSchema);
|
|
387
406
|
const subValidationResult = new ValidationResult();
|
|
388
407
|
const subMatchingSchemas = matchingSchemas.newSub();
|
|
389
|
-
validate(node, subSchema, subValidationResult, subMatchingSchemas);
|
|
408
|
+
validate(node, subSchema, subValidationResult, subMatchingSchemas, context);
|
|
390
409
|
matchingSchemas.merge(subMatchingSchemas);
|
|
391
410
|
validationResult.mergeProcessedProperties(subValidationResult);
|
|
392
411
|
if (!subValidationResult.hasProblems()) {
|
|
@@ -528,13 +547,13 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
528
547
|
}
|
|
529
548
|
}
|
|
530
549
|
function _validateStringNode(node) {
|
|
531
|
-
if (isNumber(schema.minLength) && node.value
|
|
550
|
+
if (isNumber(schema.minLength) && stringLength(node.value) < schema.minLength) {
|
|
532
551
|
validationResult.problems.push({
|
|
533
552
|
location: { offset: node.offset, length: node.length },
|
|
534
553
|
message: localize('minLengthWarning', 'String is shorter than the minimum length of {0}.', schema.minLength)
|
|
535
554
|
});
|
|
536
555
|
}
|
|
537
|
-
if (isNumber(schema.maxLength) && node.value
|
|
556
|
+
if (isNumber(schema.maxLength) && stringLength(node.value) > schema.maxLength) {
|
|
538
557
|
validationResult.problems.push({
|
|
539
558
|
location: { offset: node.offset, length: node.length },
|
|
540
559
|
message: localize('maxLengthWarning', 'String is longer than the maximum length of {0}.', schema.maxLength)
|
|
@@ -597,8 +616,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
597
616
|
function _validateArrayNode(node) {
|
|
598
617
|
let prefixItemsSchemas;
|
|
599
618
|
let additionalItemSchema;
|
|
600
|
-
|
|
601
|
-
if (isSchema_2020_12) {
|
|
619
|
+
if (context.schemaDraft >= SchemaDraft.v2020_12) {
|
|
602
620
|
prefixItemsSchemas = schema.prefixItems;
|
|
603
621
|
additionalItemSchema = !Array.isArray(schema.items) ? schema.items : undefined;
|
|
604
622
|
}
|
|
@@ -615,7 +633,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
615
633
|
const itemValidationResult = new ValidationResult();
|
|
616
634
|
const item = node.items[index];
|
|
617
635
|
if (item) {
|
|
618
|
-
validate(item, subSchema, itemValidationResult, matchingSchemas);
|
|
636
|
+
validate(item, subSchema, itemValidationResult, matchingSchemas, context);
|
|
619
637
|
validationResult.mergePropertyMatch(itemValidationResult);
|
|
620
638
|
}
|
|
621
639
|
validationResult.processedProperties.add(String(index));
|
|
@@ -637,7 +655,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
637
655
|
else {
|
|
638
656
|
for (; index < node.items.length; index++) {
|
|
639
657
|
const itemValidationResult = new ValidationResult();
|
|
640
|
-
validate(node.items[index], additionalItemSchema, itemValidationResult, matchingSchemas);
|
|
658
|
+
validate(node.items[index], additionalItemSchema, itemValidationResult, matchingSchemas, context);
|
|
641
659
|
validationResult.mergePropertyMatch(itemValidationResult);
|
|
642
660
|
validationResult.processedProperties.add(String(index));
|
|
643
661
|
}
|
|
@@ -649,10 +667,10 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
649
667
|
for (let index = 0; index < node.items.length; index++) {
|
|
650
668
|
const item = node.items[index];
|
|
651
669
|
const itemValidationResult = new ValidationResult();
|
|
652
|
-
validate(item, containsSchema, itemValidationResult, NoOpSchemaCollector.instance);
|
|
670
|
+
validate(item, containsSchema, itemValidationResult, NoOpSchemaCollector.instance, context);
|
|
653
671
|
if (!itemValidationResult.hasProblems()) {
|
|
654
672
|
containsCount++;
|
|
655
|
-
if (
|
|
673
|
+
if (context.schemaDraft >= SchemaDraft.v2020_12) {
|
|
656
674
|
validationResult.processedProperties.add(String(index));
|
|
657
675
|
}
|
|
658
676
|
}
|
|
@@ -688,7 +706,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
688
706
|
}
|
|
689
707
|
else {
|
|
690
708
|
const itemValidationResult = new ValidationResult();
|
|
691
|
-
validate(node.items[i], schema.
|
|
709
|
+
validate(node.items[i], schema.unevaluatedItems, itemValidationResult, matchingSchemas, context);
|
|
692
710
|
validationResult.mergePropertyMatch(itemValidationResult);
|
|
693
711
|
}
|
|
694
712
|
}
|
|
@@ -766,7 +784,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
766
784
|
}
|
|
767
785
|
else {
|
|
768
786
|
const propertyValidationResult = new ValidationResult();
|
|
769
|
-
validate(child, propertySchema, propertyValidationResult, matchingSchemas);
|
|
787
|
+
validate(child, propertySchema, propertyValidationResult, matchingSchemas, context);
|
|
770
788
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
771
789
|
}
|
|
772
790
|
}
|
|
@@ -798,7 +816,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
798
816
|
}
|
|
799
817
|
else {
|
|
800
818
|
const propertyValidationResult = new ValidationResult();
|
|
801
|
-
validate(child, propertySchema, propertyValidationResult, matchingSchemas);
|
|
819
|
+
validate(child, propertySchema, propertyValidationResult, matchingSchemas, context);
|
|
802
820
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
803
821
|
}
|
|
804
822
|
}
|
|
@@ -809,7 +827,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
809
827
|
}
|
|
810
828
|
}
|
|
811
829
|
const additionalProperties = schema.additionalProperties;
|
|
812
|
-
if (additionalProperties !== undefined
|
|
830
|
+
if (additionalProperties !== undefined) {
|
|
813
831
|
for (const propertyName of unprocessedProperties) {
|
|
814
832
|
propertyProcessed(propertyName);
|
|
815
833
|
const child = seenKeys[propertyName];
|
|
@@ -821,16 +839,16 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
821
839
|
message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
|
|
822
840
|
});
|
|
823
841
|
}
|
|
824
|
-
else {
|
|
842
|
+
else if (additionalProperties !== true) {
|
|
825
843
|
const propertyValidationResult = new ValidationResult();
|
|
826
|
-
validate(child, additionalProperties, propertyValidationResult, matchingSchemas);
|
|
844
|
+
validate(child, additionalProperties, propertyValidationResult, matchingSchemas, context);
|
|
827
845
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
828
846
|
}
|
|
829
847
|
}
|
|
830
848
|
}
|
|
831
849
|
}
|
|
832
850
|
const unevaluatedProperties = schema.unevaluatedProperties;
|
|
833
|
-
if (unevaluatedProperties !== undefined
|
|
851
|
+
if (unevaluatedProperties !== undefined) {
|
|
834
852
|
const processed = [];
|
|
835
853
|
for (const propertyName of unprocessedProperties) {
|
|
836
854
|
if (!validationResult.processedProperties.has(propertyName)) {
|
|
@@ -844,9 +862,9 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
844
862
|
message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
|
|
845
863
|
});
|
|
846
864
|
}
|
|
847
|
-
else {
|
|
865
|
+
else if (unevaluatedProperties !== true) {
|
|
848
866
|
const propertyValidationResult = new ValidationResult();
|
|
849
|
-
validate(child, unevaluatedProperties, propertyValidationResult, matchingSchemas);
|
|
867
|
+
validate(child, unevaluatedProperties, propertyValidationResult, matchingSchemas, context);
|
|
850
868
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
851
869
|
}
|
|
852
870
|
}
|
|
@@ -901,7 +919,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
901
919
|
for (const f of node.properties) {
|
|
902
920
|
const key = f.keyNode;
|
|
903
921
|
if (key) {
|
|
904
|
-
validate(key, propertyNames, validationResult, NoOpSchemaCollector.instance);
|
|
922
|
+
validate(key, propertyNames, validationResult, NoOpSchemaCollector.instance, context);
|
|
905
923
|
}
|
|
906
924
|
}
|
|
907
925
|
}
|
|
@@ -923,7 +941,7 @@ function validate(n, schema, validationResult, matchingSchemas) {
|
|
|
923
941
|
const propertySchema = asSchema(propertyDep);
|
|
924
942
|
if (propertySchema) {
|
|
925
943
|
const propertyValidationResult = new ValidationResult();
|
|
926
|
-
validate(node, propertySchema, propertyValidationResult, matchingSchemas);
|
|
944
|
+
validate(node, propertySchema, propertyValidationResult, matchingSchemas, context);
|
|
927
945
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
928
946
|
}
|
|
929
947
|
}
|
|
@@ -258,10 +258,17 @@ export class JSONSchemaService {
|
|
|
258
258
|
const errorMessage = localize('json.schema.nocontent', 'Unable to load schema from \'{0}\': No content.', toDisplayString(url));
|
|
259
259
|
return new UnresolvedSchema({}, [errorMessage]);
|
|
260
260
|
}
|
|
261
|
+
const errors = [];
|
|
262
|
+
if (content.charCodeAt(0) === 65279) {
|
|
263
|
+
errors.push(localize('json.schema.encodingWithBOM', 'Problem reading content from \'{0}\': UTF-8 with BOM detected, only UTF 8 is allowed.', toDisplayString(url)));
|
|
264
|
+
content = content.trimStart();
|
|
265
|
+
}
|
|
261
266
|
let schemaContent = {};
|
|
262
267
|
const jsonErrors = [];
|
|
263
268
|
schemaContent = Json.parse(content, jsonErrors);
|
|
264
|
-
|
|
269
|
+
if (jsonErrors.length) {
|
|
270
|
+
errors.push(localize('json.schema.invalidFormat', 'Unable to parse content from \'{0}\': Parse error at offset {1}.', toDisplayString(url), jsonErrors[0].offset));
|
|
271
|
+
}
|
|
265
272
|
return new UnresolvedSchema(schemaContent, errors);
|
|
266
273
|
}, (error) => {
|
|
267
274
|
let errorMessage = error.toString();
|
|
@@ -306,7 +313,7 @@ export class JSONSchemaService {
|
|
|
306
313
|
};
|
|
307
314
|
const merge = (target, section) => {
|
|
308
315
|
for (const key in section) {
|
|
309
|
-
if (section.hasOwnProperty(key) &&
|
|
316
|
+
if (section.hasOwnProperty(key) && key !== 'id' && key !== '$id') {
|
|
310
317
|
target[key] = section[key];
|
|
311
318
|
}
|
|
312
319
|
}
|
|
@@ -60,7 +60,7 @@ export class JSONValidation {
|
|
|
60
60
|
for (const warning of schema.warnings) {
|
|
61
61
|
addSchemaProblem(warning, ErrorCode.SchemaUnsupportedFeature);
|
|
62
62
|
}
|
|
63
|
-
const semanticErrors = jsonDocument.validate(textDocument, schema.schema, schemaValidation);
|
|
63
|
+
const semanticErrors = jsonDocument.validate(textDocument, schema.schema, schemaValidation, documentSettings?.schemaDraft);
|
|
64
64
|
if (semanticErrors) {
|
|
65
65
|
semanticErrors.forEach(addProblem);
|
|
66
66
|
}
|
package/lib/esm/utils/strings.js
CHANGED
|
@@ -62,3 +62,18 @@ export function extendedRegExp(pattern) {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
// from https://tanishiking.github.io/posts/count-unicode-codepoint/#work-hard-with-for-statements
|
|
66
|
+
export function stringLength(str) {
|
|
67
|
+
let count = 0;
|
|
68
|
+
for (let i = 0; i < str.length; i++) {
|
|
69
|
+
count++;
|
|
70
|
+
// obtain the i-th 16-bit
|
|
71
|
+
const code = str.charCodeAt(i);
|
|
72
|
+
if (0xD800 <= code && code <= 0xDBFF) {
|
|
73
|
+
// if the i-th 16bit is an upper surrogate
|
|
74
|
+
// skip the next 16 bits (lower surrogate)
|
|
75
|
+
i++;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return count;
|
|
79
|
+
}
|
|
@@ -94,6 +94,14 @@ export interface LanguageSettings {
|
|
|
94
94
|
schemas?: SchemaConfiguration[];
|
|
95
95
|
}
|
|
96
96
|
export declare type SeverityLevel = 'error' | 'warning' | 'ignore';
|
|
97
|
+
export declare enum SchemaDraft {
|
|
98
|
+
v3 = 3,
|
|
99
|
+
v4 = 4,
|
|
100
|
+
v6 = 6,
|
|
101
|
+
v7 = 7,
|
|
102
|
+
v2019_09 = 19,
|
|
103
|
+
v2020_12 = 20
|
|
104
|
+
}
|
|
97
105
|
export interface DocumentLanguageSettings {
|
|
98
106
|
/**
|
|
99
107
|
* The severity of reported comments. If not set, 'LanguageSettings.allowComments' defines whether comments are ignored or reported as errors.
|
|
@@ -111,6 +119,10 @@ export interface DocumentLanguageSettings {
|
|
|
111
119
|
* The severity of problems that occurred when resolving and loading schemas. If set to 'ignore', schema resolving problems are not reported. If not set, 'warning' is used.
|
|
112
120
|
*/
|
|
113
121
|
schemaRequest?: SeverityLevel;
|
|
122
|
+
/**
|
|
123
|
+
* The draft version of schema to use if the schema doesn't specify one at $schema
|
|
124
|
+
*/
|
|
125
|
+
schemaDraft?: SchemaDraft;
|
|
114
126
|
}
|
|
115
127
|
export interface SchemaConfiguration {
|
|
116
128
|
/**
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
})(function (require, exports) {
|
|
14
14
|
"use strict";
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.ClientCapabilities = 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;
|
|
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
17
|
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
|
18
18
|
Object.defineProperty(exports, "Range", { enumerable: true, get: function () { return vscode_languageserver_types_1.Range; } });
|
|
19
19
|
Object.defineProperty(exports, "Position", { enumerable: true, get: function () { return vscode_languageserver_types_1.Position; } });
|
|
@@ -78,6 +78,15 @@
|
|
|
78
78
|
ErrorCode[ErrorCode["SchemaResolveError"] = 768] = "SchemaResolveError";
|
|
79
79
|
ErrorCode[ErrorCode["SchemaUnsupportedFeature"] = 769] = "SchemaUnsupportedFeature";
|
|
80
80
|
})(ErrorCode = exports.ErrorCode || (exports.ErrorCode = {}));
|
|
81
|
+
var SchemaDraft;
|
|
82
|
+
(function (SchemaDraft) {
|
|
83
|
+
SchemaDraft[SchemaDraft["v3"] = 3] = "v3";
|
|
84
|
+
SchemaDraft[SchemaDraft["v4"] = 4] = "v4";
|
|
85
|
+
SchemaDraft[SchemaDraft["v6"] = 6] = "v6";
|
|
86
|
+
SchemaDraft[SchemaDraft["v7"] = 7] = "v7";
|
|
87
|
+
SchemaDraft[SchemaDraft["v2019_09"] = 19] = "v2019_09";
|
|
88
|
+
SchemaDraft[SchemaDraft["v2020_12"] = 20] = "v2020_12";
|
|
89
|
+
})(SchemaDraft = exports.SchemaDraft || (exports.SchemaDraft = {}));
|
|
81
90
|
var ClientCapabilities;
|
|
82
91
|
(function (ClientCapabilities) {
|
|
83
92
|
ClientCapabilities.LATEST = {
|
|
@@ -123,6 +123,19 @@
|
|
|
123
123
|
EnumMatch[EnumMatch["Key"] = 0] = "Key";
|
|
124
124
|
EnumMatch[EnumMatch["Enum"] = 1] = "Enum";
|
|
125
125
|
})(EnumMatch = exports.EnumMatch || (exports.EnumMatch = {}));
|
|
126
|
+
const schemaDraftFromId = {
|
|
127
|
+
'http://json-schema.org/draft-03/schema#': jsonLanguageTypes_1.SchemaDraft.v3,
|
|
128
|
+
'http://json-schema.org/draft-04/schema#': jsonLanguageTypes_1.SchemaDraft.v4,
|
|
129
|
+
'http://json-schema.org/draft-06/schema#': jsonLanguageTypes_1.SchemaDraft.v6,
|
|
130
|
+
'http://json-schema.org/draft-07/schema#': jsonLanguageTypes_1.SchemaDraft.v7,
|
|
131
|
+
'https://json-schema.org/draft/2019-09/schema': jsonLanguageTypes_1.SchemaDraft.v2019_09,
|
|
132
|
+
'https://json-schema.org/draft/2020-12/schema': jsonLanguageTypes_1.SchemaDraft.v2020_12
|
|
133
|
+
};
|
|
134
|
+
class EvaluationContext {
|
|
135
|
+
constructor(schemaDraft) {
|
|
136
|
+
this.schemaDraft = schemaDraft;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
126
139
|
class SchemaCollector {
|
|
127
140
|
constructor(focusOffset = -1, exclude) {
|
|
128
141
|
this.focusOffset = focusOffset;
|
|
@@ -145,9 +158,9 @@
|
|
|
145
158
|
class NoOpSchemaCollector {
|
|
146
159
|
constructor() { }
|
|
147
160
|
get schemas() { return []; }
|
|
148
|
-
add(
|
|
149
|
-
merge(
|
|
150
|
-
include(
|
|
161
|
+
add(_schema) { }
|
|
162
|
+
merge(_other) { }
|
|
163
|
+
include(_node) { return true; }
|
|
151
164
|
newSub() { return this; }
|
|
152
165
|
}
|
|
153
166
|
NoOpSchemaCollector.instance = new NoOpSchemaCollector();
|
|
@@ -164,13 +177,11 @@
|
|
|
164
177
|
hasProblems() {
|
|
165
178
|
return !!this.problems.length;
|
|
166
179
|
}
|
|
167
|
-
mergeAll(validationResults) {
|
|
168
|
-
for (const validationResult of validationResults) {
|
|
169
|
-
this.merge(validationResult);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
180
|
merge(validationResult) {
|
|
173
181
|
this.problems = this.problems.concat(validationResult.problems);
|
|
182
|
+
this.propertiesMatches += validationResult.propertiesMatches;
|
|
183
|
+
this.propertiesValueMatches += validationResult.propertiesValueMatches;
|
|
184
|
+
this.mergeProcessedProperties(validationResult);
|
|
174
185
|
}
|
|
175
186
|
mergeEnumValues(validationResult) {
|
|
176
187
|
if (!this.enumValueMatch && !validationResult.enumValueMatch && this.enumValues && validationResult.enumValues) {
|
|
@@ -183,7 +194,7 @@
|
|
|
183
194
|
}
|
|
184
195
|
}
|
|
185
196
|
mergePropertyMatch(propertyValidationResult) {
|
|
186
|
-
this.
|
|
197
|
+
this.problems = this.problems.concat(propertyValidationResult.problems);
|
|
187
198
|
this.propertiesMatches++;
|
|
188
199
|
if (propertyValidationResult.enumValueMatch || !propertyValidationResult.hasProblems() && propertyValidationResult.propertiesMatches) {
|
|
189
200
|
this.propertiesValueMatches++;
|
|
@@ -256,10 +267,10 @@
|
|
|
256
267
|
doVisit(this.root);
|
|
257
268
|
}
|
|
258
269
|
}
|
|
259
|
-
validate(textDocument, schema, severity = jsonLanguageTypes_1.DiagnosticSeverity.Warning) {
|
|
270
|
+
validate(textDocument, schema, severity = jsonLanguageTypes_1.DiagnosticSeverity.Warning, schemaDraft) {
|
|
260
271
|
if (this.root && schema) {
|
|
261
272
|
const validationResult = new ValidationResult();
|
|
262
|
-
validate(this.root, schema, validationResult, NoOpSchemaCollector.instance);
|
|
273
|
+
validate(this.root, schema, validationResult, NoOpSchemaCollector.instance, new EvaluationContext(schemaDraft ?? getSchemaDraft(schema)));
|
|
263
274
|
return validationResult.problems.map(p => {
|
|
264
275
|
const range = jsonLanguageTypes_1.Range.create(textDocument.positionAt(p.location.offset), textDocument.positionAt(p.location.offset + p.location.length));
|
|
265
276
|
return jsonLanguageTypes_1.Diagnostic.create(range, p.message, p.severity ?? severity, p.code);
|
|
@@ -268,20 +279,30 @@
|
|
|
268
279
|
return undefined;
|
|
269
280
|
}
|
|
270
281
|
getMatchingSchemas(schema, focusOffset = -1, exclude) {
|
|
271
|
-
const matchingSchemas = new SchemaCollector(focusOffset, exclude);
|
|
272
282
|
if (this.root && schema) {
|
|
273
|
-
|
|
283
|
+
const matchingSchemas = new SchemaCollector(focusOffset, exclude);
|
|
284
|
+
const schemaDraft = getSchemaDraft(schema);
|
|
285
|
+
const context = new EvaluationContext(schemaDraft);
|
|
286
|
+
validate(this.root, schema, new ValidationResult(), matchingSchemas, context);
|
|
287
|
+
return matchingSchemas.schemas;
|
|
274
288
|
}
|
|
275
|
-
return
|
|
289
|
+
return [];
|
|
276
290
|
}
|
|
277
291
|
}
|
|
278
292
|
exports.JSONDocument = JSONDocument;
|
|
279
|
-
function
|
|
293
|
+
function getSchemaDraft(schema, fallBack = jsonLanguageTypes_1.SchemaDraft.v2020_12) {
|
|
294
|
+
let schemaId = schema.$schema;
|
|
295
|
+
if (schemaId) {
|
|
296
|
+
return schemaDraftFromId[schemaId] ?? fallBack;
|
|
297
|
+
}
|
|
298
|
+
return fallBack;
|
|
299
|
+
}
|
|
300
|
+
function validate(n, schema, validationResult, matchingSchemas, context) {
|
|
280
301
|
if (!n || !matchingSchemas.include(n)) {
|
|
281
302
|
return;
|
|
282
303
|
}
|
|
283
304
|
if (n.type === 'property') {
|
|
284
|
-
return validate(n.valueNode, schema, validationResult, matchingSchemas);
|
|
305
|
+
return validate(n.valueNode, schema, validationResult, matchingSchemas, context);
|
|
285
306
|
}
|
|
286
307
|
const node = n;
|
|
287
308
|
_validateNode();
|
|
@@ -322,14 +343,18 @@
|
|
|
322
343
|
}
|
|
323
344
|
if (Array.isArray(schema.allOf)) {
|
|
324
345
|
for (const subSchemaRef of schema.allOf) {
|
|
325
|
-
|
|
346
|
+
const subValidationResult = new ValidationResult();
|
|
347
|
+
const subMatchingSchemas = matchingSchemas.newSub();
|
|
348
|
+
validate(node, asSchema(subSchemaRef), subValidationResult, subMatchingSchemas, context);
|
|
349
|
+
validationResult.merge(subValidationResult);
|
|
350
|
+
matchingSchemas.merge(subMatchingSchemas);
|
|
326
351
|
}
|
|
327
352
|
}
|
|
328
353
|
const notSchema = asSchema(schema.not);
|
|
329
354
|
if (notSchema) {
|
|
330
355
|
const subValidationResult = new ValidationResult();
|
|
331
356
|
const subMatchingSchemas = matchingSchemas.newSub();
|
|
332
|
-
validate(node, notSchema, subValidationResult, subMatchingSchemas);
|
|
357
|
+
validate(node, notSchema, subValidationResult, subMatchingSchemas, context);
|
|
333
358
|
if (!subValidationResult.hasProblems()) {
|
|
334
359
|
validationResult.problems.push({
|
|
335
360
|
location: { offset: node.offset, length: node.length },
|
|
@@ -349,7 +374,7 @@
|
|
|
349
374
|
const subSchema = asSchema(subSchemaRef);
|
|
350
375
|
const subValidationResult = new ValidationResult();
|
|
351
376
|
const subMatchingSchemas = matchingSchemas.newSub();
|
|
352
|
-
validate(node, subSchema, subValidationResult, subMatchingSchemas);
|
|
377
|
+
validate(node, subSchema, subValidationResult, subMatchingSchemas, context);
|
|
353
378
|
if (!subValidationResult.hasProblems()) {
|
|
354
379
|
matches.push(subSchema);
|
|
355
380
|
}
|
|
@@ -386,9 +411,6 @@
|
|
|
386
411
|
}
|
|
387
412
|
if (bestMatch) {
|
|
388
413
|
validationResult.merge(bestMatch.validationResult);
|
|
389
|
-
validationResult.propertiesMatches += bestMatch.validationResult.propertiesMatches;
|
|
390
|
-
validationResult.propertiesValueMatches += bestMatch.validationResult.propertiesValueMatches;
|
|
391
|
-
validationResult.mergeProcessedProperties(bestMatch.validationResult);
|
|
392
414
|
matchingSchemas.merge(bestMatch.matchingSchemas);
|
|
393
415
|
}
|
|
394
416
|
return matches.length;
|
|
@@ -402,18 +424,15 @@
|
|
|
402
424
|
const testBranch = (schema) => {
|
|
403
425
|
const subValidationResult = new ValidationResult();
|
|
404
426
|
const subMatchingSchemas = matchingSchemas.newSub();
|
|
405
|
-
validate(node, asSchema(schema), subValidationResult, subMatchingSchemas);
|
|
427
|
+
validate(node, asSchema(schema), subValidationResult, subMatchingSchemas, context);
|
|
406
428
|
validationResult.merge(subValidationResult);
|
|
407
|
-
validationResult.propertiesMatches += subValidationResult.propertiesMatches;
|
|
408
|
-
validationResult.propertiesValueMatches += subValidationResult.propertiesValueMatches;
|
|
409
|
-
validationResult.mergeProcessedProperties(subValidationResult);
|
|
410
429
|
matchingSchemas.merge(subMatchingSchemas);
|
|
411
430
|
};
|
|
412
431
|
const testCondition = (ifSchema, thenSchema, elseSchema) => {
|
|
413
432
|
const subSchema = asSchema(ifSchema);
|
|
414
433
|
const subValidationResult = new ValidationResult();
|
|
415
434
|
const subMatchingSchemas = matchingSchemas.newSub();
|
|
416
|
-
validate(node, subSchema, subValidationResult, subMatchingSchemas);
|
|
435
|
+
validate(node, subSchema, subValidationResult, subMatchingSchemas, context);
|
|
417
436
|
matchingSchemas.merge(subMatchingSchemas);
|
|
418
437
|
validationResult.mergeProcessedProperties(subValidationResult);
|
|
419
438
|
if (!subValidationResult.hasProblems()) {
|
|
@@ -555,13 +574,13 @@
|
|
|
555
574
|
}
|
|
556
575
|
}
|
|
557
576
|
function _validateStringNode(node) {
|
|
558
|
-
if ((0, objects_1.isNumber)(schema.minLength) && node.value
|
|
577
|
+
if ((0, objects_1.isNumber)(schema.minLength) && (0, strings_1.stringLength)(node.value) < schema.minLength) {
|
|
559
578
|
validationResult.problems.push({
|
|
560
579
|
location: { offset: node.offset, length: node.length },
|
|
561
580
|
message: localize('minLengthWarning', 'String is shorter than the minimum length of {0}.', schema.minLength)
|
|
562
581
|
});
|
|
563
582
|
}
|
|
564
|
-
if ((0, objects_1.isNumber)(schema.maxLength) && node.value
|
|
583
|
+
if ((0, objects_1.isNumber)(schema.maxLength) && (0, strings_1.stringLength)(node.value) > schema.maxLength) {
|
|
565
584
|
validationResult.problems.push({
|
|
566
585
|
location: { offset: node.offset, length: node.length },
|
|
567
586
|
message: localize('maxLengthWarning', 'String is longer than the maximum length of {0}.', schema.maxLength)
|
|
@@ -624,8 +643,7 @@
|
|
|
624
643
|
function _validateArrayNode(node) {
|
|
625
644
|
let prefixItemsSchemas;
|
|
626
645
|
let additionalItemSchema;
|
|
627
|
-
|
|
628
|
-
if (isSchema_2020_12) {
|
|
646
|
+
if (context.schemaDraft >= jsonLanguageTypes_1.SchemaDraft.v2020_12) {
|
|
629
647
|
prefixItemsSchemas = schema.prefixItems;
|
|
630
648
|
additionalItemSchema = !Array.isArray(schema.items) ? schema.items : undefined;
|
|
631
649
|
}
|
|
@@ -642,7 +660,7 @@
|
|
|
642
660
|
const itemValidationResult = new ValidationResult();
|
|
643
661
|
const item = node.items[index];
|
|
644
662
|
if (item) {
|
|
645
|
-
validate(item, subSchema, itemValidationResult, matchingSchemas);
|
|
663
|
+
validate(item, subSchema, itemValidationResult, matchingSchemas, context);
|
|
646
664
|
validationResult.mergePropertyMatch(itemValidationResult);
|
|
647
665
|
}
|
|
648
666
|
validationResult.processedProperties.add(String(index));
|
|
@@ -664,7 +682,7 @@
|
|
|
664
682
|
else {
|
|
665
683
|
for (; index < node.items.length; index++) {
|
|
666
684
|
const itemValidationResult = new ValidationResult();
|
|
667
|
-
validate(node.items[index], additionalItemSchema, itemValidationResult, matchingSchemas);
|
|
685
|
+
validate(node.items[index], additionalItemSchema, itemValidationResult, matchingSchemas, context);
|
|
668
686
|
validationResult.mergePropertyMatch(itemValidationResult);
|
|
669
687
|
validationResult.processedProperties.add(String(index));
|
|
670
688
|
}
|
|
@@ -676,10 +694,10 @@
|
|
|
676
694
|
for (let index = 0; index < node.items.length; index++) {
|
|
677
695
|
const item = node.items[index];
|
|
678
696
|
const itemValidationResult = new ValidationResult();
|
|
679
|
-
validate(item, containsSchema, itemValidationResult, NoOpSchemaCollector.instance);
|
|
697
|
+
validate(item, containsSchema, itemValidationResult, NoOpSchemaCollector.instance, context);
|
|
680
698
|
if (!itemValidationResult.hasProblems()) {
|
|
681
699
|
containsCount++;
|
|
682
|
-
if (
|
|
700
|
+
if (context.schemaDraft >= jsonLanguageTypes_1.SchemaDraft.v2020_12) {
|
|
683
701
|
validationResult.processedProperties.add(String(index));
|
|
684
702
|
}
|
|
685
703
|
}
|
|
@@ -715,7 +733,7 @@
|
|
|
715
733
|
}
|
|
716
734
|
else {
|
|
717
735
|
const itemValidationResult = new ValidationResult();
|
|
718
|
-
validate(node.items[i], schema.
|
|
736
|
+
validate(node.items[i], schema.unevaluatedItems, itemValidationResult, matchingSchemas, context);
|
|
719
737
|
validationResult.mergePropertyMatch(itemValidationResult);
|
|
720
738
|
}
|
|
721
739
|
}
|
|
@@ -793,7 +811,7 @@
|
|
|
793
811
|
}
|
|
794
812
|
else {
|
|
795
813
|
const propertyValidationResult = new ValidationResult();
|
|
796
|
-
validate(child, propertySchema, propertyValidationResult, matchingSchemas);
|
|
814
|
+
validate(child, propertySchema, propertyValidationResult, matchingSchemas, context);
|
|
797
815
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
798
816
|
}
|
|
799
817
|
}
|
|
@@ -825,7 +843,7 @@
|
|
|
825
843
|
}
|
|
826
844
|
else {
|
|
827
845
|
const propertyValidationResult = new ValidationResult();
|
|
828
|
-
validate(child, propertySchema, propertyValidationResult, matchingSchemas);
|
|
846
|
+
validate(child, propertySchema, propertyValidationResult, matchingSchemas, context);
|
|
829
847
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
830
848
|
}
|
|
831
849
|
}
|
|
@@ -836,7 +854,7 @@
|
|
|
836
854
|
}
|
|
837
855
|
}
|
|
838
856
|
const additionalProperties = schema.additionalProperties;
|
|
839
|
-
if (additionalProperties !== undefined
|
|
857
|
+
if (additionalProperties !== undefined) {
|
|
840
858
|
for (const propertyName of unprocessedProperties) {
|
|
841
859
|
propertyProcessed(propertyName);
|
|
842
860
|
const child = seenKeys[propertyName];
|
|
@@ -848,16 +866,16 @@
|
|
|
848
866
|
message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
|
|
849
867
|
});
|
|
850
868
|
}
|
|
851
|
-
else {
|
|
869
|
+
else if (additionalProperties !== true) {
|
|
852
870
|
const propertyValidationResult = new ValidationResult();
|
|
853
|
-
validate(child, additionalProperties, propertyValidationResult, matchingSchemas);
|
|
871
|
+
validate(child, additionalProperties, propertyValidationResult, matchingSchemas, context);
|
|
854
872
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
855
873
|
}
|
|
856
874
|
}
|
|
857
875
|
}
|
|
858
876
|
}
|
|
859
877
|
const unevaluatedProperties = schema.unevaluatedProperties;
|
|
860
|
-
if (unevaluatedProperties !== undefined
|
|
878
|
+
if (unevaluatedProperties !== undefined) {
|
|
861
879
|
const processed = [];
|
|
862
880
|
for (const propertyName of unprocessedProperties) {
|
|
863
881
|
if (!validationResult.processedProperties.has(propertyName)) {
|
|
@@ -871,9 +889,9 @@
|
|
|
871
889
|
message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
|
|
872
890
|
});
|
|
873
891
|
}
|
|
874
|
-
else {
|
|
892
|
+
else if (unevaluatedProperties !== true) {
|
|
875
893
|
const propertyValidationResult = new ValidationResult();
|
|
876
|
-
validate(child, unevaluatedProperties, propertyValidationResult, matchingSchemas);
|
|
894
|
+
validate(child, unevaluatedProperties, propertyValidationResult, matchingSchemas, context);
|
|
877
895
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
878
896
|
}
|
|
879
897
|
}
|
|
@@ -928,7 +946,7 @@
|
|
|
928
946
|
for (const f of node.properties) {
|
|
929
947
|
const key = f.keyNode;
|
|
930
948
|
if (key) {
|
|
931
|
-
validate(key, propertyNames, validationResult, NoOpSchemaCollector.instance);
|
|
949
|
+
validate(key, propertyNames, validationResult, NoOpSchemaCollector.instance, context);
|
|
932
950
|
}
|
|
933
951
|
}
|
|
934
952
|
}
|
|
@@ -950,7 +968,7 @@
|
|
|
950
968
|
const propertySchema = asSchema(propertyDep);
|
|
951
969
|
if (propertySchema) {
|
|
952
970
|
const propertyValidationResult = new ValidationResult();
|
|
953
|
-
validate(node, propertySchema, propertyValidationResult, matchingSchemas);
|
|
971
|
+
validate(node, propertySchema, propertyValidationResult, matchingSchemas, context);
|
|
954
972
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
955
973
|
}
|
|
956
974
|
}
|
|
@@ -272,10 +272,17 @@
|
|
|
272
272
|
const errorMessage = localize('json.schema.nocontent', 'Unable to load schema from \'{0}\': No content.', toDisplayString(url));
|
|
273
273
|
return new UnresolvedSchema({}, [errorMessage]);
|
|
274
274
|
}
|
|
275
|
+
const errors = [];
|
|
276
|
+
if (content.charCodeAt(0) === 65279) {
|
|
277
|
+
errors.push(localize('json.schema.encodingWithBOM', 'Problem reading content from \'{0}\': UTF-8 with BOM detected, only UTF 8 is allowed.', toDisplayString(url)));
|
|
278
|
+
content = content.trimStart();
|
|
279
|
+
}
|
|
275
280
|
let schemaContent = {};
|
|
276
281
|
const jsonErrors = [];
|
|
277
282
|
schemaContent = Json.parse(content, jsonErrors);
|
|
278
|
-
|
|
283
|
+
if (jsonErrors.length) {
|
|
284
|
+
errors.push(localize('json.schema.invalidFormat', 'Unable to parse content from \'{0}\': Parse error at offset {1}.', toDisplayString(url), jsonErrors[0].offset));
|
|
285
|
+
}
|
|
279
286
|
return new UnresolvedSchema(schemaContent, errors);
|
|
280
287
|
}, (error) => {
|
|
281
288
|
let errorMessage = error.toString();
|
|
@@ -320,7 +327,7 @@
|
|
|
320
327
|
};
|
|
321
328
|
const merge = (target, section) => {
|
|
322
329
|
for (const key in section) {
|
|
323
|
-
if (section.hasOwnProperty(key) &&
|
|
330
|
+
if (section.hasOwnProperty(key) && key !== 'id' && key !== '$id') {
|
|
324
331
|
target[key] = section[key];
|
|
325
332
|
}
|
|
326
333
|
}
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
for (const warning of schema.warnings) {
|
|
73
73
|
addSchemaProblem(warning, jsonLanguageTypes_1.ErrorCode.SchemaUnsupportedFeature);
|
|
74
74
|
}
|
|
75
|
-
const semanticErrors = jsonDocument.validate(textDocument, schema.schema, schemaValidation);
|
|
75
|
+
const semanticErrors = jsonDocument.validate(textDocument, schema.schema, schemaValidation, documentSettings?.schemaDraft);
|
|
76
76
|
if (semanticErrors) {
|
|
77
77
|
semanticErrors.forEach(addProblem);
|
|
78
78
|
}
|
package/lib/umd/utils/strings.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
})(function (require, exports) {
|
|
14
14
|
"use strict";
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.extendedRegExp = exports.repeat = exports.convertSimple2RegExpPattern = exports.endsWith = exports.startsWith = void 0;
|
|
16
|
+
exports.stringLength = exports.extendedRegExp = exports.repeat = exports.convertSimple2RegExpPattern = exports.endsWith = exports.startsWith = void 0;
|
|
17
17
|
function startsWith(haystack, needle) {
|
|
18
18
|
if (haystack.length < needle.length) {
|
|
19
19
|
return false;
|
|
@@ -79,4 +79,20 @@
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
exports.extendedRegExp = extendedRegExp;
|
|
82
|
+
// from https://tanishiking.github.io/posts/count-unicode-codepoint/#work-hard-with-for-statements
|
|
83
|
+
function stringLength(str) {
|
|
84
|
+
let count = 0;
|
|
85
|
+
for (let i = 0; i < str.length; i++) {
|
|
86
|
+
count++;
|
|
87
|
+
// obtain the i-th 16-bit
|
|
88
|
+
const code = str.charCodeAt(i);
|
|
89
|
+
if (0xD800 <= code && code <= 0xDBFF) {
|
|
90
|
+
// if the i-th 16bit is an upper surrogate
|
|
91
|
+
// skip the next 16 bits (lower surrogate)
|
|
92
|
+
i++;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return count;
|
|
96
|
+
}
|
|
97
|
+
exports.stringLength = stringLength;
|
|
82
98
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vscode-json-languageservice",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.1",
|
|
4
4
|
"description": "Language service for JSON",
|
|
5
5
|
"main": "./lib/umd/jsonLanguageService.js",
|
|
6
6
|
"typings": "./lib/umd/jsonLanguageService",
|
|
@@ -17,19 +17,20 @@
|
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/mocha": "^9.1.1",
|
|
19
19
|
"@types/node": "16.x",
|
|
20
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
21
|
-
"@typescript-eslint/parser": "^5.
|
|
22
|
-
"eslint": "^8.
|
|
20
|
+
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
|
21
|
+
"@typescript-eslint/parser": "^5.38.1",
|
|
22
|
+
"eslint": "^8.24.0",
|
|
23
23
|
"mocha": "^10.0.0",
|
|
24
24
|
"rimraf": "^3.0.2",
|
|
25
|
-
"typescript": "^4.
|
|
25
|
+
"typescript": "^4.8.3",
|
|
26
|
+
"json-schema-test-suite": "https://github.com/json-schema-org/JSON-Schema-Test-Suite.git#69acf52990b004240839ae19b4bec8fb01d50876"
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"jsonc-parser": "^3.
|
|
29
|
-
"vscode-languageserver-textdocument": "^1.0.
|
|
30
|
-
"vscode-languageserver-types": "^3.17.
|
|
31
|
-
"vscode-nls": "^5.0
|
|
32
|
-
"vscode-uri": "^3.0.
|
|
29
|
+
"jsonc-parser": "^3.2.0",
|
|
30
|
+
"vscode-languageserver-textdocument": "^1.0.7",
|
|
31
|
+
"vscode-languageserver-types": "^3.17.2",
|
|
32
|
+
"vscode-nls": "^5.2.0",
|
|
33
|
+
"vscode-uri": "^3.0.6"
|
|
33
34
|
},
|
|
34
35
|
"scripts": {
|
|
35
36
|
"prepublishOnly": "npm run clean && npm run compile-esm && npm run test && npm run remove-sourcemap-refs",
|