vscode-json-languageservice 4.2.0 → 5.1.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 +10 -1
- package/SECURITY.md +41 -0
- package/lib/esm/jsonLanguageService.js +22 -22
- package/lib/esm/jsonLanguageTypes.d.ts +3 -1
- package/lib/esm/jsonLanguageTypes.js +3 -2
- package/lib/esm/jsonSchema.d.ts +21 -2
- package/lib/esm/parser/jsonParser.js +488 -488
- package/lib/esm/services/configuration.js +9 -9
- package/lib/esm/services/jsonCompletion.js +280 -290
- package/lib/esm/services/jsonDocumentSymbols.js +88 -99
- package/lib/esm/services/jsonFolding.js +38 -39
- package/lib/esm/services/jsonHover.js +40 -43
- package/lib/esm/services/jsonLinks.js +12 -13
- package/lib/esm/services/jsonSchemaService.js +234 -253
- package/lib/esm/services/jsonSelectionRanges.js +9 -9
- package/lib/esm/services/jsonValidation.js +53 -51
- package/lib/esm/utils/colors.js +7 -8
- package/lib/esm/utils/glob.js +12 -12
- package/lib/esm/utils/json.js +7 -7
- package/lib/esm/utils/objects.js +3 -0
- package/lib/esm/utils/strings.js +3 -3
- package/lib/umd/jsonLanguageService.js +36 -32
- package/lib/umd/jsonLanguageTypes.d.ts +3 -1
- package/lib/umd/jsonLanguageTypes.js +5 -3
- package/lib/umd/jsonSchema.d.ts +21 -2
- package/lib/umd/parser/jsonParser.js +492 -482
- package/lib/umd/services/configuration.js +9 -9
- package/lib/umd/services/jsonCompletion.js +287 -296
- package/lib/umd/services/jsonDocumentSymbols.js +92 -102
- package/lib/umd/services/jsonFolding.js +40 -41
- package/lib/umd/services/jsonHover.js +42 -44
- package/lib/umd/services/jsonLinks.js +13 -14
- package/lib/umd/services/jsonSchemaService.js +241 -257
- package/lib/umd/services/jsonSelectionRanges.js +11 -11
- package/lib/umd/services/jsonValidation.js +56 -53
- package/lib/umd/utils/colors.js +7 -8
- package/lib/umd/utils/glob.js +12 -12
- package/lib/umd/utils/json.js +7 -7
- package/lib/umd/utils/objects.js +5 -1
- package/lib/umd/utils/strings.js +3 -3
- package/package.json +12 -12
|
@@ -2,21 +2,6 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
var __extends = (this && this.__extends) || (function () {
|
|
6
|
-
var extendStatics = function (d, b) {
|
|
7
|
-
extendStatics = Object.setPrototypeOf ||
|
|
8
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
9
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
10
|
-
return extendStatics(d, b);
|
|
11
|
-
};
|
|
12
|
-
return function (d, b) {
|
|
13
|
-
if (typeof b !== "function" && b !== null)
|
|
14
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
15
|
-
extendStatics(d, b);
|
|
16
|
-
function __() { this.constructor = d; }
|
|
17
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
18
|
-
};
|
|
19
|
-
})();
|
|
20
5
|
(function (factory) {
|
|
21
6
|
if (typeof module === "object" && typeof module.exports === "object") {
|
|
22
7
|
var v = factory(require, exports);
|
|
@@ -29,13 +14,13 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
29
14
|
"use strict";
|
|
30
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
16
|
exports.parse = exports.JSONDocument = exports.contains = exports.getNodePath = exports.getNodeValue = exports.newJSONDocument = exports.ValidationResult = exports.EnumMatch = exports.asSchema = exports.ObjectASTNodeImpl = exports.PropertyASTNodeImpl = exports.StringASTNodeImpl = exports.NumberASTNodeImpl = exports.ArrayASTNodeImpl = exports.BooleanASTNodeImpl = exports.NullASTNodeImpl = exports.ASTNodeImpl = void 0;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
17
|
+
const Json = require("jsonc-parser");
|
|
18
|
+
const objects_1 = require("../utils/objects");
|
|
19
|
+
const strings_1 = require("../utils/strings");
|
|
20
|
+
const jsonLanguageTypes_1 = require("../jsonLanguageTypes");
|
|
21
|
+
const nls = require("vscode-nls");
|
|
22
|
+
const localize = nls.loadMessageBundle();
|
|
23
|
+
const formats = {
|
|
39
24
|
'color-hex': { errorMessage: localize('colorHexFormatWarning', 'Invalid color format. Use #RGB, #RGBA, #RRGGBB or #RRGGBBAA.'), pattern: /^#([0-9A-Fa-f]{3,4}|([0-9A-Fa-f]{2}){3,4})$/ },
|
|
40
25
|
'date-time': { errorMessage: localize('dateTimeFormatWarning', 'String is not a RFC3339 date-time.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)([01][0-9]|2[0-3]):([0-5][0-9]))$/i },
|
|
41
26
|
'date': { errorMessage: localize('dateFormatWarning', 'String is not a RFC3339 date.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/i },
|
|
@@ -45,125 +30,86 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
45
30
|
'ipv4': { errorMessage: localize('ipv4FormatWarning', 'String is not an IPv4 address.'), pattern: /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/ },
|
|
46
31
|
'ipv6': { errorMessage: localize('ipv6FormatWarning', 'String is not an IPv6 address.'), pattern: /^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i },
|
|
47
32
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (length === void 0) { length = 0; }
|
|
33
|
+
class ASTNodeImpl {
|
|
34
|
+
constructor(parent, offset, length = 0) {
|
|
51
35
|
this.offset = offset;
|
|
52
36
|
this.length = length;
|
|
53
37
|
this.parent = parent;
|
|
54
38
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
enumerable: false,
|
|
60
|
-
configurable: true
|
|
61
|
-
});
|
|
62
|
-
ASTNodeImpl.prototype.toString = function () {
|
|
39
|
+
get children() {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
toString() {
|
|
63
43
|
return 'type: ' + this.type + ' (' + this.offset + '/' + this.length + ')' + (this.parent ? ' parent: {' + this.parent.toString() + '}' : '');
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
}());
|
|
44
|
+
}
|
|
45
|
+
}
|
|
67
46
|
exports.ASTNodeImpl = ASTNodeImpl;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
_this.value = null;
|
|
74
|
-
return _this;
|
|
47
|
+
class NullASTNodeImpl extends ASTNodeImpl {
|
|
48
|
+
constructor(parent, offset) {
|
|
49
|
+
super(parent, offset);
|
|
50
|
+
this.type = 'null';
|
|
51
|
+
this.value = null;
|
|
75
52
|
}
|
|
76
|
-
|
|
77
|
-
}(ASTNodeImpl));
|
|
53
|
+
}
|
|
78
54
|
exports.NullASTNodeImpl = NullASTNodeImpl;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
_this.value = boolValue;
|
|
85
|
-
return _this;
|
|
55
|
+
class BooleanASTNodeImpl extends ASTNodeImpl {
|
|
56
|
+
constructor(parent, boolValue, offset) {
|
|
57
|
+
super(parent, offset);
|
|
58
|
+
this.type = 'boolean';
|
|
59
|
+
this.value = boolValue;
|
|
86
60
|
}
|
|
87
|
-
|
|
88
|
-
}(ASTNodeImpl));
|
|
61
|
+
}
|
|
89
62
|
exports.BooleanASTNodeImpl = BooleanASTNodeImpl;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
_this.items = [];
|
|
96
|
-
return _this;
|
|
63
|
+
class ArrayASTNodeImpl extends ASTNodeImpl {
|
|
64
|
+
constructor(parent, offset) {
|
|
65
|
+
super(parent, offset);
|
|
66
|
+
this.type = 'array';
|
|
67
|
+
this.items = [];
|
|
97
68
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
enumerable: false,
|
|
103
|
-
configurable: true
|
|
104
|
-
});
|
|
105
|
-
return ArrayASTNodeImpl;
|
|
106
|
-
}(ASTNodeImpl));
|
|
69
|
+
get children() {
|
|
70
|
+
return this.items;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
107
73
|
exports.ArrayASTNodeImpl = ArrayASTNodeImpl;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
_this.value = Number.NaN;
|
|
115
|
-
return _this;
|
|
74
|
+
class NumberASTNodeImpl extends ASTNodeImpl {
|
|
75
|
+
constructor(parent, offset) {
|
|
76
|
+
super(parent, offset);
|
|
77
|
+
this.type = 'number';
|
|
78
|
+
this.isInteger = true;
|
|
79
|
+
this.value = Number.NaN;
|
|
116
80
|
}
|
|
117
|
-
|
|
118
|
-
}(ASTNodeImpl));
|
|
81
|
+
}
|
|
119
82
|
exports.NumberASTNodeImpl = NumberASTNodeImpl;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
_this.value = '';
|
|
126
|
-
return _this;
|
|
83
|
+
class StringASTNodeImpl extends ASTNodeImpl {
|
|
84
|
+
constructor(parent, offset, length) {
|
|
85
|
+
super(parent, offset, length);
|
|
86
|
+
this.type = 'string';
|
|
87
|
+
this.value = '';
|
|
127
88
|
}
|
|
128
|
-
|
|
129
|
-
}(ASTNodeImpl));
|
|
89
|
+
}
|
|
130
90
|
exports.StringASTNodeImpl = StringASTNodeImpl;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
_this.keyNode = keyNode;
|
|
138
|
-
return _this;
|
|
91
|
+
class PropertyASTNodeImpl extends ASTNodeImpl {
|
|
92
|
+
constructor(parent, offset, keyNode) {
|
|
93
|
+
super(parent, offset);
|
|
94
|
+
this.type = 'property';
|
|
95
|
+
this.colonOffset = -1;
|
|
96
|
+
this.keyNode = keyNode;
|
|
139
97
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
enumerable: false,
|
|
145
|
-
configurable: true
|
|
146
|
-
});
|
|
147
|
-
return PropertyASTNodeImpl;
|
|
148
|
-
}(ASTNodeImpl));
|
|
98
|
+
get children() {
|
|
99
|
+
return this.valueNode ? [this.keyNode, this.valueNode] : [this.keyNode];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
149
102
|
exports.PropertyASTNodeImpl = PropertyASTNodeImpl;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
_this.properties = [];
|
|
156
|
-
return _this;
|
|
103
|
+
class ObjectASTNodeImpl extends ASTNodeImpl {
|
|
104
|
+
constructor(parent, offset) {
|
|
105
|
+
super(parent, offset);
|
|
106
|
+
this.type = 'object';
|
|
107
|
+
this.properties = [];
|
|
157
108
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
enumerable: false,
|
|
163
|
-
configurable: true
|
|
164
|
-
});
|
|
165
|
-
return ObjectASTNodeImpl;
|
|
166
|
-
}(ASTNodeImpl));
|
|
109
|
+
get children() {
|
|
110
|
+
return this.properties;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
167
113
|
exports.ObjectASTNodeImpl = ObjectASTNodeImpl;
|
|
168
114
|
function asSchema(schema) {
|
|
169
115
|
if ((0, objects_1.isBoolean)(schema)) {
|
|
@@ -177,75 +123,66 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
177
123
|
EnumMatch[EnumMatch["Key"] = 0] = "Key";
|
|
178
124
|
EnumMatch[EnumMatch["Enum"] = 1] = "Enum";
|
|
179
125
|
})(EnumMatch = exports.EnumMatch || (exports.EnumMatch = {}));
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (focusOffset === void 0) { focusOffset = -1; }
|
|
126
|
+
class SchemaCollector {
|
|
127
|
+
constructor(focusOffset = -1, exclude) {
|
|
183
128
|
this.focusOffset = focusOffset;
|
|
184
129
|
this.exclude = exclude;
|
|
185
130
|
this.schemas = [];
|
|
186
131
|
}
|
|
187
|
-
|
|
132
|
+
add(schema) {
|
|
188
133
|
this.schemas.push(schema);
|
|
189
|
-
}
|
|
190
|
-
|
|
134
|
+
}
|
|
135
|
+
merge(other) {
|
|
191
136
|
Array.prototype.push.apply(this.schemas, other.schemas);
|
|
192
|
-
}
|
|
193
|
-
|
|
137
|
+
}
|
|
138
|
+
include(node) {
|
|
194
139
|
return (this.focusOffset === -1 || contains(node, this.focusOffset)) && (node !== this.exclude);
|
|
195
|
-
}
|
|
196
|
-
|
|
140
|
+
}
|
|
141
|
+
newSub() {
|
|
197
142
|
return new SchemaCollector(-1, this.exclude);
|
|
198
|
-
};
|
|
199
|
-
return SchemaCollector;
|
|
200
|
-
}());
|
|
201
|
-
var NoOpSchemaCollector = /** @class */ (function () {
|
|
202
|
-
function NoOpSchemaCollector() {
|
|
203
143
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
var ValidationResult = /** @class */ (function () {
|
|
217
|
-
function ValidationResult() {
|
|
144
|
+
}
|
|
145
|
+
class NoOpSchemaCollector {
|
|
146
|
+
constructor() { }
|
|
147
|
+
get schemas() { return []; }
|
|
148
|
+
add(schema) { }
|
|
149
|
+
merge(other) { }
|
|
150
|
+
include(node) { return true; }
|
|
151
|
+
newSub() { return this; }
|
|
152
|
+
}
|
|
153
|
+
NoOpSchemaCollector.instance = new NoOpSchemaCollector();
|
|
154
|
+
class ValidationResult {
|
|
155
|
+
constructor() {
|
|
218
156
|
this.problems = [];
|
|
219
157
|
this.propertiesMatches = 0;
|
|
158
|
+
this.processedProperties = new Set();
|
|
220
159
|
this.propertiesValueMatches = 0;
|
|
221
160
|
this.primaryValueMatches = 0;
|
|
222
161
|
this.enumValueMatch = false;
|
|
223
162
|
this.enumValues = undefined;
|
|
224
163
|
}
|
|
225
|
-
|
|
164
|
+
hasProblems() {
|
|
226
165
|
return !!this.problems.length;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
for (
|
|
230
|
-
var validationResult = validationResults_1[_i];
|
|
166
|
+
}
|
|
167
|
+
mergeAll(validationResults) {
|
|
168
|
+
for (const validationResult of validationResults) {
|
|
231
169
|
this.merge(validationResult);
|
|
232
170
|
}
|
|
233
|
-
}
|
|
234
|
-
|
|
171
|
+
}
|
|
172
|
+
merge(validationResult) {
|
|
235
173
|
this.problems = this.problems.concat(validationResult.problems);
|
|
236
|
-
}
|
|
237
|
-
|
|
174
|
+
}
|
|
175
|
+
mergeEnumValues(validationResult) {
|
|
238
176
|
if (!this.enumValueMatch && !validationResult.enumValueMatch && this.enumValues && validationResult.enumValues) {
|
|
239
177
|
this.enumValues = this.enumValues.concat(validationResult.enumValues);
|
|
240
|
-
for (
|
|
241
|
-
var error = _a[_i];
|
|
178
|
+
for (const error of this.problems) {
|
|
242
179
|
if (error.code === jsonLanguageTypes_1.ErrorCode.EnumValueMismatch) {
|
|
243
|
-
error.message = localize('enumWarning', 'Value is not accepted. Valid values: {0}.', this.enumValues.map(
|
|
180
|
+
error.message = localize('enumWarning', 'Value is not accepted. Valid values: {0}.', this.enumValues.map(v => JSON.stringify(v)).join(', '));
|
|
244
181
|
}
|
|
245
182
|
}
|
|
246
183
|
}
|
|
247
|
-
}
|
|
248
|
-
|
|
184
|
+
}
|
|
185
|
+
mergePropertyMatch(propertyValidationResult) {
|
|
249
186
|
this.merge(propertyValidationResult);
|
|
250
187
|
this.propertiesMatches++;
|
|
251
188
|
if (propertyValidationResult.enumValueMatch || !propertyValidationResult.hasProblems() && propertyValidationResult.propertiesMatches) {
|
|
@@ -254,9 +191,12 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
254
191
|
if (propertyValidationResult.enumValueMatch && propertyValidationResult.enumValues && propertyValidationResult.enumValues.length === 1) {
|
|
255
192
|
this.primaryValueMatches++;
|
|
256
193
|
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
194
|
+
}
|
|
195
|
+
mergeProcessedProperties(validationResult) {
|
|
196
|
+
validationResult.processedProperties.forEach(p => this.processedProperties.add(p));
|
|
197
|
+
}
|
|
198
|
+
compare(other) {
|
|
199
|
+
const hasProblems = this.hasProblems();
|
|
260
200
|
if (hasProblems !== other.hasProblems()) {
|
|
261
201
|
return hasProblems ? -1 : 1;
|
|
262
202
|
}
|
|
@@ -270,12 +210,10 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
270
210
|
return this.propertiesValueMatches - other.propertiesValueMatches;
|
|
271
211
|
}
|
|
272
212
|
return this.propertiesMatches - other.propertiesMatches;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
}());
|
|
213
|
+
}
|
|
214
|
+
}
|
|
276
215
|
exports.ValidationResult = ValidationResult;
|
|
277
|
-
function newJSONDocument(root, diagnostics) {
|
|
278
|
-
if (diagnostics === void 0) { diagnostics = []; }
|
|
216
|
+
function newJSONDocument(root, diagnostics = []) {
|
|
279
217
|
return new JSONDocument(root, diagnostics, []);
|
|
280
218
|
}
|
|
281
219
|
exports.newJSONDocument = newJSONDocument;
|
|
@@ -287,87 +225,80 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
287
225
|
return Json.getNodePath(node);
|
|
288
226
|
}
|
|
289
227
|
exports.getNodePath = getNodePath;
|
|
290
|
-
function contains(node, offset, includeRightBound) {
|
|
291
|
-
if (includeRightBound === void 0) { includeRightBound = false; }
|
|
228
|
+
function contains(node, offset, includeRightBound = false) {
|
|
292
229
|
return offset >= node.offset && offset < (node.offset + node.length) || includeRightBound && offset === (node.offset + node.length);
|
|
293
230
|
}
|
|
294
231
|
exports.contains = contains;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (syntaxErrors === void 0) { syntaxErrors = []; }
|
|
298
|
-
if (comments === void 0) { comments = []; }
|
|
232
|
+
class JSONDocument {
|
|
233
|
+
constructor(root, syntaxErrors = [], comments = []) {
|
|
299
234
|
this.root = root;
|
|
300
235
|
this.syntaxErrors = syntaxErrors;
|
|
301
236
|
this.comments = comments;
|
|
302
237
|
}
|
|
303
|
-
|
|
304
|
-
if (includeRightBound === void 0) { includeRightBound = false; }
|
|
238
|
+
getNodeFromOffset(offset, includeRightBound = false) {
|
|
305
239
|
if (this.root) {
|
|
306
240
|
return Json.findNodeAtOffset(this.root, offset, includeRightBound);
|
|
307
241
|
}
|
|
308
242
|
return undefined;
|
|
309
|
-
}
|
|
310
|
-
|
|
243
|
+
}
|
|
244
|
+
visit(visitor) {
|
|
311
245
|
if (this.root) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
246
|
+
const doVisit = (node) => {
|
|
247
|
+
let ctn = visitor(node);
|
|
248
|
+
const children = node.children;
|
|
315
249
|
if (Array.isArray(children)) {
|
|
316
|
-
for (
|
|
317
|
-
ctn =
|
|
250
|
+
for (let i = 0; i < children.length && ctn; i++) {
|
|
251
|
+
ctn = doVisit(children[i]);
|
|
318
252
|
}
|
|
319
253
|
}
|
|
320
254
|
return ctn;
|
|
321
255
|
};
|
|
322
|
-
|
|
256
|
+
doVisit(this.root);
|
|
323
257
|
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
if (severity === void 0) { severity = jsonLanguageTypes_1.DiagnosticSeverity.Warning; }
|
|
258
|
+
}
|
|
259
|
+
validate(textDocument, schema, severity = jsonLanguageTypes_1.DiagnosticSeverity.Warning) {
|
|
327
260
|
if (this.root && schema) {
|
|
328
|
-
|
|
261
|
+
const validationResult = new ValidationResult();
|
|
329
262
|
validate(this.root, schema, validationResult, NoOpSchemaCollector.instance);
|
|
330
|
-
return validationResult.problems.map(
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
return jsonLanguageTypes_1.Diagnostic.create(range, p.message, (_a = p.severity) !== null && _a !== void 0 ? _a : severity, p.code);
|
|
263
|
+
return validationResult.problems.map(p => {
|
|
264
|
+
const range = jsonLanguageTypes_1.Range.create(textDocument.positionAt(p.location.offset), textDocument.positionAt(p.location.offset + p.location.length));
|
|
265
|
+
return jsonLanguageTypes_1.Diagnostic.create(range, p.message, p.severity ?? severity, p.code);
|
|
334
266
|
});
|
|
335
267
|
}
|
|
336
268
|
return undefined;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
var matchingSchemas = new SchemaCollector(focusOffset, exclude);
|
|
269
|
+
}
|
|
270
|
+
getMatchingSchemas(schema, focusOffset = -1, exclude) {
|
|
271
|
+
const matchingSchemas = new SchemaCollector(focusOffset, exclude);
|
|
341
272
|
if (this.root && schema) {
|
|
342
273
|
validate(this.root, schema, new ValidationResult(), matchingSchemas);
|
|
343
274
|
}
|
|
344
275
|
return matchingSchemas.schemas;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
}());
|
|
276
|
+
}
|
|
277
|
+
}
|
|
348
278
|
exports.JSONDocument = JSONDocument;
|
|
349
279
|
function validate(n, schema, validationResult, matchingSchemas) {
|
|
350
280
|
if (!n || !matchingSchemas.include(n)) {
|
|
351
281
|
return;
|
|
352
282
|
}
|
|
353
|
-
|
|
283
|
+
if (n.type === 'property') {
|
|
284
|
+
return validate(n.valueNode, schema, validationResult, matchingSchemas);
|
|
285
|
+
}
|
|
286
|
+
const node = n;
|
|
287
|
+
_validateNode();
|
|
354
288
|
switch (node.type) {
|
|
355
289
|
case 'object':
|
|
356
|
-
_validateObjectNode(node
|
|
290
|
+
_validateObjectNode(node);
|
|
357
291
|
break;
|
|
358
292
|
case 'array':
|
|
359
|
-
_validateArrayNode(node
|
|
293
|
+
_validateArrayNode(node);
|
|
360
294
|
break;
|
|
361
295
|
case 'string':
|
|
362
|
-
_validateStringNode(node
|
|
296
|
+
_validateStringNode(node);
|
|
363
297
|
break;
|
|
364
298
|
case 'number':
|
|
365
|
-
_validateNumberNode(node
|
|
299
|
+
_validateNumberNode(node);
|
|
366
300
|
break;
|
|
367
|
-
case 'property':
|
|
368
|
-
return validate(node.valueNode, schema, validationResult, matchingSchemas);
|
|
369
301
|
}
|
|
370
|
-
_validateNode();
|
|
371
302
|
matchingSchemas.add({ node: node, schema: schema });
|
|
372
303
|
function _validateNode() {
|
|
373
304
|
function matchesType(type) {
|
|
@@ -390,15 +321,14 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
390
321
|
}
|
|
391
322
|
}
|
|
392
323
|
if (Array.isArray(schema.allOf)) {
|
|
393
|
-
for (
|
|
394
|
-
var subSchemaRef = _a[_i];
|
|
324
|
+
for (const subSchemaRef of schema.allOf) {
|
|
395
325
|
validate(node, asSchema(subSchemaRef), validationResult, matchingSchemas);
|
|
396
326
|
}
|
|
397
327
|
}
|
|
398
|
-
|
|
328
|
+
const notSchema = asSchema(schema.not);
|
|
399
329
|
if (notSchema) {
|
|
400
|
-
|
|
401
|
-
|
|
330
|
+
const subValidationResult = new ValidationResult();
|
|
331
|
+
const subMatchingSchemas = matchingSchemas.newSub();
|
|
402
332
|
validate(node, notSchema, subValidationResult, subMatchingSchemas);
|
|
403
333
|
if (!subValidationResult.hasProblems()) {
|
|
404
334
|
validationResult.problems.push({
|
|
@@ -406,21 +336,19 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
406
336
|
message: localize('notSchemaWarning', "Matches a schema that is not allowed.")
|
|
407
337
|
});
|
|
408
338
|
}
|
|
409
|
-
for (
|
|
410
|
-
var ms = _c[_b];
|
|
339
|
+
for (const ms of subMatchingSchemas.schemas) {
|
|
411
340
|
ms.inverted = !ms.inverted;
|
|
412
341
|
matchingSchemas.add(ms);
|
|
413
342
|
}
|
|
414
343
|
}
|
|
415
|
-
|
|
416
|
-
|
|
344
|
+
const testAlternatives = (alternatives, maxOneMatch) => {
|
|
345
|
+
const matches = [];
|
|
417
346
|
// remember the best match that is used for error messages
|
|
418
|
-
|
|
419
|
-
for (
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
var subMatchingSchemas = matchingSchemas.newSub();
|
|
347
|
+
let bestMatch = undefined;
|
|
348
|
+
for (const subSchemaRef of alternatives) {
|
|
349
|
+
const subSchema = asSchema(subSchemaRef);
|
|
350
|
+
const subValidationResult = new ValidationResult();
|
|
351
|
+
const subMatchingSchemas = matchingSchemas.newSub();
|
|
424
352
|
validate(node, subSchema, subValidationResult, subMatchingSchemas);
|
|
425
353
|
if (!subValidationResult.hasProblems()) {
|
|
426
354
|
matches.push(subSchema);
|
|
@@ -434,9 +362,10 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
434
362
|
bestMatch.matchingSchemas.merge(subMatchingSchemas);
|
|
435
363
|
bestMatch.validationResult.propertiesMatches += subValidationResult.propertiesMatches;
|
|
436
364
|
bestMatch.validationResult.propertiesValueMatches += subValidationResult.propertiesValueMatches;
|
|
365
|
+
bestMatch.validationResult.mergeProcessedProperties(subValidationResult);
|
|
437
366
|
}
|
|
438
367
|
else {
|
|
439
|
-
|
|
368
|
+
const compareResult = subValidationResult.compare(bestMatch.validationResult);
|
|
440
369
|
if (compareResult > 0) {
|
|
441
370
|
// our node is the best matching so far
|
|
442
371
|
bestMatch = { schema: subSchema, validationResult: subValidationResult, matchingSchemas: subMatchingSchemas };
|
|
@@ -459,6 +388,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
459
388
|
validationResult.merge(bestMatch.validationResult);
|
|
460
389
|
validationResult.propertiesMatches += bestMatch.validationResult.propertiesMatches;
|
|
461
390
|
validationResult.propertiesValueMatches += bestMatch.validationResult.propertiesValueMatches;
|
|
391
|
+
validationResult.mergeProcessedProperties(bestMatch.validationResult);
|
|
462
392
|
matchingSchemas.merge(bestMatch.matchingSchemas);
|
|
463
393
|
}
|
|
464
394
|
return matches.length;
|
|
@@ -469,21 +399,23 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
469
399
|
if (Array.isArray(schema.oneOf)) {
|
|
470
400
|
testAlternatives(schema.oneOf, true);
|
|
471
401
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
402
|
+
const testBranch = (schema) => {
|
|
403
|
+
const subValidationResult = new ValidationResult();
|
|
404
|
+
const subMatchingSchemas = matchingSchemas.newSub();
|
|
475
405
|
validate(node, asSchema(schema), subValidationResult, subMatchingSchemas);
|
|
476
406
|
validationResult.merge(subValidationResult);
|
|
477
407
|
validationResult.propertiesMatches += subValidationResult.propertiesMatches;
|
|
478
408
|
validationResult.propertiesValueMatches += subValidationResult.propertiesValueMatches;
|
|
409
|
+
validationResult.mergeProcessedProperties(subValidationResult);
|
|
479
410
|
matchingSchemas.merge(subMatchingSchemas);
|
|
480
411
|
};
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
412
|
+
const testCondition = (ifSchema, thenSchema, elseSchema) => {
|
|
413
|
+
const subSchema = asSchema(ifSchema);
|
|
414
|
+
const subValidationResult = new ValidationResult();
|
|
415
|
+
const subMatchingSchemas = matchingSchemas.newSub();
|
|
485
416
|
validate(node, subSchema, subValidationResult, subMatchingSchemas);
|
|
486
417
|
matchingSchemas.merge(subMatchingSchemas);
|
|
418
|
+
validationResult.mergeProcessedProperties(subValidationResult);
|
|
487
419
|
if (!subValidationResult.hasProblems()) {
|
|
488
420
|
if (thenSchema) {
|
|
489
421
|
testBranch(thenSchema);
|
|
@@ -493,15 +425,14 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
493
425
|
testBranch(elseSchema);
|
|
494
426
|
}
|
|
495
427
|
};
|
|
496
|
-
|
|
428
|
+
const ifSchema = asSchema(schema.if);
|
|
497
429
|
if (ifSchema) {
|
|
498
430
|
testCondition(ifSchema, asSchema(schema.then), asSchema(schema.else));
|
|
499
431
|
}
|
|
500
432
|
if (Array.isArray(schema.enum)) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
for (
|
|
504
|
-
var e = _e[_d];
|
|
433
|
+
const val = getNodeValue(node);
|
|
434
|
+
let enumValueMatch = false;
|
|
435
|
+
for (const e of schema.enum) {
|
|
505
436
|
if ((0, objects_1.equals)(val, e)) {
|
|
506
437
|
enumValueMatch = true;
|
|
507
438
|
break;
|
|
@@ -513,12 +444,12 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
513
444
|
validationResult.problems.push({
|
|
514
445
|
location: { offset: node.offset, length: node.length },
|
|
515
446
|
code: jsonLanguageTypes_1.ErrorCode.EnumValueMismatch,
|
|
516
|
-
message: schema.errorMessage || localize('enumWarning', 'Value is not accepted. Valid values: {0}.', schema.enum.map(
|
|
447
|
+
message: schema.errorMessage || localize('enumWarning', 'Value is not accepted. Valid values: {0}.', schema.enum.map(v => JSON.stringify(v)).join(', '))
|
|
517
448
|
});
|
|
518
449
|
}
|
|
519
450
|
}
|
|
520
451
|
if ((0, objects_1.isDefined)(schema.const)) {
|
|
521
|
-
|
|
452
|
+
const val = getNodeValue(node);
|
|
522
453
|
if (!(0, objects_1.equals)(val, schema.const)) {
|
|
523
454
|
validationResult.problems.push({
|
|
524
455
|
location: { offset: node.offset, length: node.length },
|
|
@@ -532,36 +463,37 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
532
463
|
}
|
|
533
464
|
validationResult.enumValues = [schema.const];
|
|
534
465
|
}
|
|
535
|
-
|
|
466
|
+
let deprecationMessage = schema.deprecationMessage;
|
|
467
|
+
if ((deprecationMessage || schema.deprecated) && node.parent) {
|
|
468
|
+
deprecationMessage = deprecationMessage || localize('deprecated', 'Value is deprecated');
|
|
536
469
|
validationResult.problems.push({
|
|
537
470
|
location: { offset: node.parent.offset, length: node.parent.length },
|
|
538
471
|
severity: jsonLanguageTypes_1.DiagnosticSeverity.Warning,
|
|
539
|
-
message:
|
|
472
|
+
message: deprecationMessage,
|
|
540
473
|
code: jsonLanguageTypes_1.ErrorCode.Deprecated
|
|
541
474
|
});
|
|
542
475
|
}
|
|
543
476
|
}
|
|
544
|
-
function _validateNumberNode(node
|
|
545
|
-
|
|
477
|
+
function _validateNumberNode(node) {
|
|
478
|
+
const val = node.value;
|
|
546
479
|
function normalizeFloats(float) {
|
|
547
|
-
|
|
548
|
-
var parts = /^(-?\d+)(?:\.(\d+))?(?:e([-+]\d+))?$/.exec(float.toString());
|
|
480
|
+
const parts = /^(-?\d+)(?:\.(\d+))?(?:e([-+]\d+))?$/.exec(float.toString());
|
|
549
481
|
return parts && {
|
|
550
482
|
value: Number(parts[1] + (parts[2] || '')),
|
|
551
|
-
multiplier: (
|
|
483
|
+
multiplier: (parts[2]?.length || 0) - (parseInt(parts[3]) || 0)
|
|
552
484
|
};
|
|
553
485
|
}
|
|
554
486
|
;
|
|
555
487
|
if ((0, objects_1.isNumber)(schema.multipleOf)) {
|
|
556
|
-
|
|
488
|
+
let remainder = -1;
|
|
557
489
|
if (Number.isInteger(schema.multipleOf)) {
|
|
558
490
|
remainder = val % schema.multipleOf;
|
|
559
491
|
}
|
|
560
492
|
else {
|
|
561
|
-
|
|
562
|
-
|
|
493
|
+
let normMultipleOf = normalizeFloats(schema.multipleOf);
|
|
494
|
+
let normValue = normalizeFloats(val);
|
|
563
495
|
if (normMultipleOf && normValue) {
|
|
564
|
-
|
|
496
|
+
const multiplier = 10 ** Math.abs(normValue.multiplier - normMultipleOf.multiplier);
|
|
565
497
|
if (normValue.multiplier < normMultipleOf.multiplier) {
|
|
566
498
|
normValue.value *= multiplier;
|
|
567
499
|
}
|
|
@@ -593,28 +525,28 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
593
525
|
}
|
|
594
526
|
return undefined;
|
|
595
527
|
}
|
|
596
|
-
|
|
528
|
+
const exclusiveMinimum = getExclusiveLimit(schema.minimum, schema.exclusiveMinimum);
|
|
597
529
|
if ((0, objects_1.isNumber)(exclusiveMinimum) && val <= exclusiveMinimum) {
|
|
598
530
|
validationResult.problems.push({
|
|
599
531
|
location: { offset: node.offset, length: node.length },
|
|
600
532
|
message: localize('exclusiveMinimumWarning', 'Value is below the exclusive minimum of {0}.', exclusiveMinimum)
|
|
601
533
|
});
|
|
602
534
|
}
|
|
603
|
-
|
|
535
|
+
const exclusiveMaximum = getExclusiveLimit(schema.maximum, schema.exclusiveMaximum);
|
|
604
536
|
if ((0, objects_1.isNumber)(exclusiveMaximum) && val >= exclusiveMaximum) {
|
|
605
537
|
validationResult.problems.push({
|
|
606
538
|
location: { offset: node.offset, length: node.length },
|
|
607
539
|
message: localize('exclusiveMaximumWarning', 'Value is above the exclusive maximum of {0}.', exclusiveMaximum)
|
|
608
540
|
});
|
|
609
541
|
}
|
|
610
|
-
|
|
542
|
+
const minimum = getLimit(schema.minimum, schema.exclusiveMinimum);
|
|
611
543
|
if ((0, objects_1.isNumber)(minimum) && val < minimum) {
|
|
612
544
|
validationResult.problems.push({
|
|
613
545
|
location: { offset: node.offset, length: node.length },
|
|
614
546
|
message: localize('minimumWarning', 'Value is below the minimum of {0}.', minimum)
|
|
615
547
|
});
|
|
616
548
|
}
|
|
617
|
-
|
|
549
|
+
const maximum = getLimit(schema.maximum, schema.exclusiveMaximum);
|
|
618
550
|
if ((0, objects_1.isNumber)(maximum) && val > maximum) {
|
|
619
551
|
validationResult.problems.push({
|
|
620
552
|
location: { offset: node.offset, length: node.length },
|
|
@@ -622,7 +554,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
622
554
|
});
|
|
623
555
|
}
|
|
624
556
|
}
|
|
625
|
-
function _validateStringNode(node
|
|
557
|
+
function _validateStringNode(node) {
|
|
626
558
|
if ((0, objects_1.isNumber)(schema.minLength) && node.value.length < schema.minLength) {
|
|
627
559
|
validationResult.problems.push({
|
|
628
560
|
location: { offset: node.offset, length: node.length },
|
|
@@ -636,8 +568,8 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
636
568
|
});
|
|
637
569
|
}
|
|
638
570
|
if ((0, objects_1.isString)(schema.pattern)) {
|
|
639
|
-
|
|
640
|
-
if (!(regex
|
|
571
|
+
const regex = (0, strings_1.extendedRegExp)(schema.pattern);
|
|
572
|
+
if (!(regex?.test(node.value))) {
|
|
641
573
|
validationResult.problems.push({
|
|
642
574
|
location: { offset: node.offset, length: node.length },
|
|
643
575
|
message: schema.patternErrorMessage || schema.errorMessage || localize('patternWarning', 'String does not match the pattern of "{0}".', schema.pattern)
|
|
@@ -649,12 +581,12 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
649
581
|
case 'uri':
|
|
650
582
|
case 'uri-reference':
|
|
651
583
|
{
|
|
652
|
-
|
|
584
|
+
let errorMessage;
|
|
653
585
|
if (!node.value) {
|
|
654
586
|
errorMessage = localize('uriEmpty', 'URI expected.');
|
|
655
587
|
}
|
|
656
588
|
else {
|
|
657
|
-
|
|
589
|
+
const match = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(node.value);
|
|
658
590
|
if (!match) {
|
|
659
591
|
errorMessage = localize('uriMissing', 'URI is expected.');
|
|
660
592
|
}
|
|
@@ -678,7 +610,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
678
610
|
case 'hostname':
|
|
679
611
|
case 'ipv4':
|
|
680
612
|
case 'ipv6':
|
|
681
|
-
|
|
613
|
+
const format = formats[schema.format];
|
|
682
614
|
if (!node.value || !format.pattern.exec(node.value)) {
|
|
683
615
|
validationResult.problems.push({
|
|
684
616
|
location: { offset: node.offset, length: node.length },
|
|
@@ -689,62 +621,107 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
689
621
|
}
|
|
690
622
|
}
|
|
691
623
|
}
|
|
692
|
-
function _validateArrayNode(node
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
624
|
+
function _validateArrayNode(node) {
|
|
625
|
+
let prefixItemsSchemas;
|
|
626
|
+
let additionalItemSchema;
|
|
627
|
+
let isSchema_2020_12 = Array.isArray(schema.prefixItems) || (schema.items !== undefined && !Array.isArray(schema.items) && schema.additionalItems === undefined);
|
|
628
|
+
if (isSchema_2020_12) {
|
|
629
|
+
prefixItemsSchemas = schema.prefixItems;
|
|
630
|
+
additionalItemSchema = !Array.isArray(schema.items) ? schema.items : undefined;
|
|
631
|
+
}
|
|
632
|
+
else {
|
|
633
|
+
prefixItemsSchemas = Array.isArray(schema.items) ? schema.items : undefined;
|
|
634
|
+
additionalItemSchema = !Array.isArray(schema.items) ? schema.items : schema.additionalItems;
|
|
635
|
+
}
|
|
636
|
+
let index = 0;
|
|
637
|
+
if (prefixItemsSchemas !== undefined) {
|
|
638
|
+
const max = Math.min(prefixItemsSchemas.length, node.items.length);
|
|
639
|
+
for (; index < max; index++) {
|
|
640
|
+
const subSchemaRef = prefixItemsSchemas[index];
|
|
641
|
+
const subSchema = asSchema(subSchemaRef);
|
|
642
|
+
const itemValidationResult = new ValidationResult();
|
|
643
|
+
const item = node.items[index];
|
|
700
644
|
if (item) {
|
|
701
645
|
validate(item, subSchema, itemValidationResult, matchingSchemas);
|
|
702
646
|
validationResult.mergePropertyMatch(itemValidationResult);
|
|
703
647
|
}
|
|
704
|
-
|
|
705
|
-
validationResult.propertiesValueMatches++;
|
|
706
|
-
}
|
|
648
|
+
validationResult.processedProperties.add(String(index));
|
|
707
649
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
validate(node.items[i], schema.additionalItems, itemValidationResult, matchingSchemas);
|
|
713
|
-
validationResult.mergePropertyMatch(itemValidationResult);
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
else if (schema.additionalItems === false) {
|
|
650
|
+
}
|
|
651
|
+
if (additionalItemSchema !== undefined && index < node.items.length) {
|
|
652
|
+
if (typeof additionalItemSchema === 'boolean') {
|
|
653
|
+
if (additionalItemSchema === false) {
|
|
717
654
|
validationResult.problems.push({
|
|
718
655
|
location: { offset: node.offset, length: node.length },
|
|
719
|
-
message: localize('additionalItemsWarning', 'Array has too many items according to schema. Expected {0} or fewer.',
|
|
656
|
+
message: localize('additionalItemsWarning', 'Array has too many items according to schema. Expected {0} or fewer.', index)
|
|
720
657
|
});
|
|
721
658
|
}
|
|
659
|
+
for (; index < node.items.length; index++) {
|
|
660
|
+
validationResult.processedProperties.add(String(index));
|
|
661
|
+
validationResult.propertiesValueMatches++;
|
|
662
|
+
}
|
|
722
663
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
for (var _i = 0, _a = node.items; _i < _a.length; _i++) {
|
|
728
|
-
var item = _a[_i];
|
|
729
|
-
var itemValidationResult = new ValidationResult();
|
|
730
|
-
validate(item, itemSchema, itemValidationResult, matchingSchemas);
|
|
664
|
+
else {
|
|
665
|
+
for (; index < node.items.length; index++) {
|
|
666
|
+
const itemValidationResult = new ValidationResult();
|
|
667
|
+
validate(node.items[index], additionalItemSchema, itemValidationResult, matchingSchemas);
|
|
731
668
|
validationResult.mergePropertyMatch(itemValidationResult);
|
|
669
|
+
validationResult.processedProperties.add(String(index));
|
|
732
670
|
}
|
|
733
671
|
}
|
|
734
672
|
}
|
|
735
|
-
|
|
673
|
+
const containsSchema = asSchema(schema.contains);
|
|
736
674
|
if (containsSchema) {
|
|
737
|
-
|
|
738
|
-
|
|
675
|
+
let containsCount = 0;
|
|
676
|
+
for (let index = 0; index < node.items.length; index++) {
|
|
677
|
+
const item = node.items[index];
|
|
678
|
+
const itemValidationResult = new ValidationResult();
|
|
739
679
|
validate(item, containsSchema, itemValidationResult, NoOpSchemaCollector.instance);
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
680
|
+
if (!itemValidationResult.hasProblems()) {
|
|
681
|
+
containsCount++;
|
|
682
|
+
if (isSchema_2020_12) {
|
|
683
|
+
validationResult.processedProperties.add(String(index));
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
if (containsCount === 0 && !(0, objects_1.isNumber)(schema.minContains)) {
|
|
743
688
|
validationResult.problems.push({
|
|
744
689
|
location: { offset: node.offset, length: node.length },
|
|
745
690
|
message: schema.errorMessage || localize('requiredItemMissingWarning', 'Array does not contain required item.')
|
|
746
691
|
});
|
|
747
692
|
}
|
|
693
|
+
if ((0, objects_1.isNumber)(schema.minContains) && containsCount < schema.minContains) {
|
|
694
|
+
validationResult.problems.push({
|
|
695
|
+
location: { offset: node.offset, length: node.length },
|
|
696
|
+
message: localize('minContainsWarning', 'Array has too few items that match the contains contraint. Expected {0} or more.', schema.minContains)
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
if ((0, objects_1.isNumber)(schema.maxContains) && containsCount > schema.maxContains) {
|
|
700
|
+
validationResult.problems.push({
|
|
701
|
+
location: { offset: node.offset, length: node.length },
|
|
702
|
+
message: localize('maxContainsWarning', 'Array has too many items that match the contains contraint. Expected {0} or less.', schema.maxContains)
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
const unevaluatedItems = schema.unevaluatedItems;
|
|
707
|
+
if (unevaluatedItems !== undefined) {
|
|
708
|
+
for (let i = 0; i < node.items.length; i++) {
|
|
709
|
+
if (!validationResult.processedProperties.has(String(i))) {
|
|
710
|
+
if (unevaluatedItems === false) {
|
|
711
|
+
validationResult.problems.push({
|
|
712
|
+
location: { offset: node.offset, length: node.length },
|
|
713
|
+
message: localize('unevaluatedItemsWarning', 'Item does not match any validation rule from the array.')
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
const itemValidationResult = new ValidationResult();
|
|
718
|
+
validate(node.items[i], schema.additionalItems, itemValidationResult, matchingSchemas);
|
|
719
|
+
validationResult.mergePropertyMatch(itemValidationResult);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
validationResult.processedProperties.add(String(i));
|
|
723
|
+
validationResult.propertiesValueMatches++;
|
|
724
|
+
}
|
|
748
725
|
}
|
|
749
726
|
if ((0, objects_1.isNumber)(schema.minItems) && node.items.length < schema.minItems) {
|
|
750
727
|
validationResult.problems.push({
|
|
@@ -759,9 +736,9 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
759
736
|
});
|
|
760
737
|
}
|
|
761
738
|
if (schema.uniqueItems === true) {
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
return index !==
|
|
739
|
+
const values = getNodeValue(node);
|
|
740
|
+
const duplicates = values.some((value, index) => {
|
|
741
|
+
return index !== values.lastIndexOf(value);
|
|
765
742
|
});
|
|
766
743
|
if (duplicates) {
|
|
767
744
|
validationResult.problems.push({
|
|
@@ -771,21 +748,19 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
771
748
|
}
|
|
772
749
|
}
|
|
773
750
|
}
|
|
774
|
-
function _validateObjectNode(node
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
for (
|
|
778
|
-
|
|
779
|
-
var key = propertyNode.keyNode.value;
|
|
751
|
+
function _validateObjectNode(node) {
|
|
752
|
+
const seenKeys = Object.create(null);
|
|
753
|
+
const unprocessedProperties = new Set();
|
|
754
|
+
for (const propertyNode of node.properties) {
|
|
755
|
+
const key = propertyNode.keyNode.value;
|
|
780
756
|
seenKeys[key] = propertyNode.valueNode;
|
|
781
|
-
unprocessedProperties.
|
|
757
|
+
unprocessedProperties.add(key);
|
|
782
758
|
}
|
|
783
759
|
if (Array.isArray(schema.required)) {
|
|
784
|
-
for (
|
|
785
|
-
var propertyName = _c[_b];
|
|
760
|
+
for (const propertyName of schema.required) {
|
|
786
761
|
if (!seenKeys[propertyName]) {
|
|
787
|
-
|
|
788
|
-
|
|
762
|
+
const keyNode = node.parent && node.parent.type === 'property' && node.parent.keyNode;
|
|
763
|
+
const location = keyNode ? { offset: keyNode.offset, length: keyNode.length } : { offset: node.offset, length: 1 };
|
|
789
764
|
validationResult.problems.push({
|
|
790
765
|
location: location,
|
|
791
766
|
message: localize('MissingRequiredPropWarning', 'Missing property "{0}".', propertyName)
|
|
@@ -793,23 +768,19 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
793
768
|
}
|
|
794
769
|
}
|
|
795
770
|
}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
unprocessedProperties.splice(index, 1);
|
|
800
|
-
index = unprocessedProperties.indexOf(prop);
|
|
801
|
-
}
|
|
771
|
+
const propertyProcessed = (prop) => {
|
|
772
|
+
unprocessedProperties.delete(prop);
|
|
773
|
+
validationResult.processedProperties.add(prop);
|
|
802
774
|
};
|
|
803
775
|
if (schema.properties) {
|
|
804
|
-
for (
|
|
805
|
-
var propertyName = _e[_d];
|
|
776
|
+
for (const propertyName of Object.keys(schema.properties)) {
|
|
806
777
|
propertyProcessed(propertyName);
|
|
807
|
-
|
|
808
|
-
|
|
778
|
+
const propertySchema = schema.properties[propertyName];
|
|
779
|
+
const child = seenKeys[propertyName];
|
|
809
780
|
if (child) {
|
|
810
781
|
if ((0, objects_1.isBoolean)(propertySchema)) {
|
|
811
782
|
if (!propertySchema) {
|
|
812
|
-
|
|
783
|
+
const propertyNode = child.parent;
|
|
813
784
|
validationResult.problems.push({
|
|
814
785
|
location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
|
|
815
786
|
message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
|
|
@@ -821,7 +792,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
821
792
|
}
|
|
822
793
|
}
|
|
823
794
|
else {
|
|
824
|
-
|
|
795
|
+
const propertyValidationResult = new ValidationResult();
|
|
825
796
|
validate(child, propertySchema, propertyValidationResult, matchingSchemas);
|
|
826
797
|
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
827
798
|
}
|
|
@@ -829,64 +800,86 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
829
800
|
}
|
|
830
801
|
}
|
|
831
802
|
if (schema.patternProperties) {
|
|
832
|
-
for (
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
803
|
+
for (const propertyPattern of Object.keys(schema.patternProperties)) {
|
|
804
|
+
const regex = (0, strings_1.extendedRegExp)(propertyPattern);
|
|
805
|
+
if (regex) {
|
|
806
|
+
const processed = [];
|
|
807
|
+
for (const propertyName of unprocessedProperties) {
|
|
808
|
+
if (regex.test(propertyName)) {
|
|
809
|
+
processed.push(propertyName);
|
|
810
|
+
const child = seenKeys[propertyName];
|
|
811
|
+
if (child) {
|
|
812
|
+
const propertySchema = schema.patternProperties[propertyPattern];
|
|
813
|
+
if ((0, objects_1.isBoolean)(propertySchema)) {
|
|
814
|
+
if (!propertySchema) {
|
|
815
|
+
const propertyNode = child.parent;
|
|
816
|
+
validationResult.problems.push({
|
|
817
|
+
location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
|
|
818
|
+
message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
else {
|
|
822
|
+
validationResult.propertiesMatches++;
|
|
823
|
+
validationResult.propertiesValueMatches++;
|
|
824
|
+
}
|
|
849
825
|
}
|
|
850
826
|
else {
|
|
851
|
-
|
|
852
|
-
|
|
827
|
+
const propertyValidationResult = new ValidationResult();
|
|
828
|
+
validate(child, propertySchema, propertyValidationResult, matchingSchemas);
|
|
829
|
+
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
853
830
|
}
|
|
854
831
|
}
|
|
855
|
-
else {
|
|
856
|
-
var propertyValidationResult = new ValidationResult();
|
|
857
|
-
validate(child, propertySchema, propertyValidationResult, matchingSchemas);
|
|
858
|
-
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
859
|
-
}
|
|
860
832
|
}
|
|
861
833
|
}
|
|
834
|
+
processed.forEach(propertyProcessed);
|
|
862
835
|
}
|
|
863
836
|
}
|
|
864
837
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
838
|
+
const additionalProperties = schema.additionalProperties;
|
|
839
|
+
if (additionalProperties !== undefined && additionalProperties !== true) {
|
|
840
|
+
for (const propertyName of unprocessedProperties) {
|
|
841
|
+
propertyProcessed(propertyName);
|
|
842
|
+
const child = seenKeys[propertyName];
|
|
869
843
|
if (child) {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
else if (schema.additionalProperties === false) {
|
|
877
|
-
if (unprocessedProperties.length > 0) {
|
|
878
|
-
for (var _l = 0, unprocessedProperties_2 = unprocessedProperties; _l < unprocessedProperties_2.length; _l++) {
|
|
879
|
-
var propertyName = unprocessedProperties_2[_l];
|
|
880
|
-
var child = seenKeys[propertyName];
|
|
881
|
-
if (child) {
|
|
882
|
-
var propertyNode = child.parent;
|
|
844
|
+
if (additionalProperties === false) {
|
|
845
|
+
const propertyNode = child.parent;
|
|
883
846
|
validationResult.problems.push({
|
|
884
847
|
location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
|
|
885
848
|
message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
|
|
886
849
|
});
|
|
887
850
|
}
|
|
851
|
+
else {
|
|
852
|
+
const propertyValidationResult = new ValidationResult();
|
|
853
|
+
validate(child, additionalProperties, propertyValidationResult, matchingSchemas);
|
|
854
|
+
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
const unevaluatedProperties = schema.unevaluatedProperties;
|
|
860
|
+
if (unevaluatedProperties !== undefined && unevaluatedProperties !== true) {
|
|
861
|
+
const processed = [];
|
|
862
|
+
for (const propertyName of unprocessedProperties) {
|
|
863
|
+
if (!validationResult.processedProperties.has(propertyName)) {
|
|
864
|
+
processed.push(propertyName);
|
|
865
|
+
const child = seenKeys[propertyName];
|
|
866
|
+
if (child) {
|
|
867
|
+
if (unevaluatedProperties === false) {
|
|
868
|
+
const propertyNode = child.parent;
|
|
869
|
+
validationResult.problems.push({
|
|
870
|
+
location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
|
|
871
|
+
message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
else {
|
|
875
|
+
const propertyValidationResult = new ValidationResult();
|
|
876
|
+
validate(child, unevaluatedProperties, propertyValidationResult, matchingSchemas);
|
|
877
|
+
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
888
880
|
}
|
|
889
881
|
}
|
|
882
|
+
processed.forEach(propertyProcessed);
|
|
890
883
|
}
|
|
891
884
|
if ((0, objects_1.isNumber)(schema.maxProperties)) {
|
|
892
885
|
if (node.properties.length > schema.maxProperties) {
|
|
@@ -904,71 +897,88 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
904
897
|
});
|
|
905
898
|
}
|
|
906
899
|
}
|
|
900
|
+
if (schema.dependentRequired) {
|
|
901
|
+
for (const key in schema.dependentRequired) {
|
|
902
|
+
const prop = seenKeys[key];
|
|
903
|
+
const propertyDeps = schema.dependentRequired[key];
|
|
904
|
+
if (prop && Array.isArray(propertyDeps)) {
|
|
905
|
+
_validatePropertyDependencies(key, propertyDeps);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
if (schema.dependentSchemas) {
|
|
910
|
+
for (const key in schema.dependentSchemas) {
|
|
911
|
+
const prop = seenKeys[key];
|
|
912
|
+
const propertyDeps = schema.dependentSchemas[key];
|
|
913
|
+
if (prop && (0, objects_1.isObject)(propertyDeps)) {
|
|
914
|
+
_validatePropertyDependencies(key, propertyDeps);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
907
918
|
if (schema.dependencies) {
|
|
908
|
-
for (
|
|
909
|
-
|
|
910
|
-
var prop = seenKeys[key];
|
|
919
|
+
for (const key in schema.dependencies) {
|
|
920
|
+
const prop = seenKeys[key];
|
|
911
921
|
if (prop) {
|
|
912
|
-
|
|
913
|
-
if (Array.isArray(propertyDep)) {
|
|
914
|
-
for (var _p = 0, propertyDep_1 = propertyDep; _p < propertyDep_1.length; _p++) {
|
|
915
|
-
var requiredProp = propertyDep_1[_p];
|
|
916
|
-
if (!seenKeys[requiredProp]) {
|
|
917
|
-
validationResult.problems.push({
|
|
918
|
-
location: { offset: node.offset, length: node.length },
|
|
919
|
-
message: localize('RequiredDependentPropWarning', 'Object is missing property {0} required by property {1}.', requiredProp, key)
|
|
920
|
-
});
|
|
921
|
-
}
|
|
922
|
-
else {
|
|
923
|
-
validationResult.propertiesValueMatches++;
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
else {
|
|
928
|
-
var propertySchema = asSchema(propertyDep);
|
|
929
|
-
if (propertySchema) {
|
|
930
|
-
var propertyValidationResult = new ValidationResult();
|
|
931
|
-
validate(node, propertySchema, propertyValidationResult, matchingSchemas);
|
|
932
|
-
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
933
|
-
}
|
|
934
|
-
}
|
|
922
|
+
_validatePropertyDependencies(key, schema.dependencies[key]);
|
|
935
923
|
}
|
|
936
924
|
}
|
|
937
925
|
}
|
|
938
|
-
|
|
926
|
+
const propertyNames = asSchema(schema.propertyNames);
|
|
939
927
|
if (propertyNames) {
|
|
940
|
-
for (
|
|
941
|
-
|
|
942
|
-
var key = f.keyNode;
|
|
928
|
+
for (const f of node.properties) {
|
|
929
|
+
const key = f.keyNode;
|
|
943
930
|
if (key) {
|
|
944
931
|
validate(key, propertyNames, validationResult, NoOpSchemaCollector.instance);
|
|
945
932
|
}
|
|
946
933
|
}
|
|
947
934
|
}
|
|
935
|
+
function _validatePropertyDependencies(key, propertyDep) {
|
|
936
|
+
if (Array.isArray(propertyDep)) {
|
|
937
|
+
for (const requiredProp of propertyDep) {
|
|
938
|
+
if (!seenKeys[requiredProp]) {
|
|
939
|
+
validationResult.problems.push({
|
|
940
|
+
location: { offset: node.offset, length: node.length },
|
|
941
|
+
message: localize('RequiredDependentPropWarning', 'Object is missing property {0} required by property {1}.', requiredProp, key)
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
else {
|
|
945
|
+
validationResult.propertiesValueMatches++;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
else {
|
|
950
|
+
const propertySchema = asSchema(propertyDep);
|
|
951
|
+
if (propertySchema) {
|
|
952
|
+
const propertyValidationResult = new ValidationResult();
|
|
953
|
+
validate(node, propertySchema, propertyValidationResult, matchingSchemas);
|
|
954
|
+
validationResult.mergePropertyMatch(propertyValidationResult);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
}
|
|
948
958
|
}
|
|
949
959
|
}
|
|
950
960
|
function parse(textDocument, config) {
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
961
|
+
const problems = [];
|
|
962
|
+
let lastProblemOffset = -1;
|
|
963
|
+
const text = textDocument.getText();
|
|
964
|
+
const scanner = Json.createScanner(text, false);
|
|
965
|
+
const commentRanges = config && config.collectComments ? [] : undefined;
|
|
956
966
|
function _scanNext() {
|
|
957
967
|
while (true) {
|
|
958
|
-
|
|
968
|
+
const token = scanner.scan();
|
|
959
969
|
_checkScanError();
|
|
960
|
-
switch (
|
|
961
|
-
case 12 /* LineCommentTrivia */:
|
|
962
|
-
case 13 /* BlockCommentTrivia */:
|
|
970
|
+
switch (token) {
|
|
971
|
+
case 12 /* Json.SyntaxKind.LineCommentTrivia */:
|
|
972
|
+
case 13 /* Json.SyntaxKind.BlockCommentTrivia */:
|
|
963
973
|
if (Array.isArray(commentRanges)) {
|
|
964
974
|
commentRanges.push(jsonLanguageTypes_1.Range.create(textDocument.positionAt(scanner.getTokenOffset()), textDocument.positionAt(scanner.getTokenOffset() + scanner.getTokenLength())));
|
|
965
975
|
}
|
|
966
976
|
break;
|
|
967
|
-
case 15 /* Trivia */:
|
|
968
|
-
case 14 /* LineBreakTrivia */:
|
|
977
|
+
case 15 /* Json.SyntaxKind.Trivia */:
|
|
978
|
+
case 14 /* Json.SyntaxKind.LineBreakTrivia */:
|
|
969
979
|
break;
|
|
970
980
|
default:
|
|
971
|
-
return
|
|
981
|
+
return token;
|
|
972
982
|
}
|
|
973
983
|
}
|
|
974
984
|
}
|
|
@@ -979,20 +989,16 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
979
989
|
}
|
|
980
990
|
return false;
|
|
981
991
|
}
|
|
982
|
-
function _errorAtRange(message, code, startOffset, endOffset, severity) {
|
|
983
|
-
if (severity === void 0) { severity = jsonLanguageTypes_1.DiagnosticSeverity.Error; }
|
|
992
|
+
function _errorAtRange(message, code, startOffset, endOffset, severity = jsonLanguageTypes_1.DiagnosticSeverity.Error) {
|
|
984
993
|
if (problems.length === 0 || startOffset !== lastProblemOffset) {
|
|
985
|
-
|
|
994
|
+
const range = jsonLanguageTypes_1.Range.create(textDocument.positionAt(startOffset), textDocument.positionAt(endOffset));
|
|
986
995
|
problems.push(jsonLanguageTypes_1.Diagnostic.create(range, message, severity, code, textDocument.languageId));
|
|
987
996
|
lastProblemOffset = startOffset;
|
|
988
997
|
}
|
|
989
998
|
}
|
|
990
|
-
function _error(message, code, node, skipUntilAfter, skipUntil) {
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
if (skipUntil === void 0) { skipUntil = []; }
|
|
994
|
-
var start = scanner.getTokenOffset();
|
|
995
|
-
var end = scanner.getTokenOffset() + scanner.getTokenLength();
|
|
999
|
+
function _error(message, code, node = undefined, skipUntilAfter = [], skipUntil = []) {
|
|
1000
|
+
let start = scanner.getTokenOffset();
|
|
1001
|
+
let end = scanner.getTokenOffset() + scanner.getTokenLength();
|
|
996
1002
|
if (start === end && start > 0) {
|
|
997
1003
|
start--;
|
|
998
1004
|
while (start > 0 && /\s/.test(text.charAt(start))) {
|
|
@@ -1005,38 +1011,38 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
1005
1011
|
_finalize(node, false);
|
|
1006
1012
|
}
|
|
1007
1013
|
if (skipUntilAfter.length + skipUntil.length > 0) {
|
|
1008
|
-
|
|
1009
|
-
while (
|
|
1010
|
-
if (skipUntilAfter.indexOf(
|
|
1014
|
+
let token = scanner.getToken();
|
|
1015
|
+
while (token !== 17 /* Json.SyntaxKind.EOF */) {
|
|
1016
|
+
if (skipUntilAfter.indexOf(token) !== -1) {
|
|
1011
1017
|
_scanNext();
|
|
1012
1018
|
break;
|
|
1013
1019
|
}
|
|
1014
|
-
else if (skipUntil.indexOf(
|
|
1020
|
+
else if (skipUntil.indexOf(token) !== -1) {
|
|
1015
1021
|
break;
|
|
1016
1022
|
}
|
|
1017
|
-
|
|
1023
|
+
token = _scanNext();
|
|
1018
1024
|
}
|
|
1019
1025
|
}
|
|
1020
1026
|
return node;
|
|
1021
1027
|
}
|
|
1022
1028
|
function _checkScanError() {
|
|
1023
1029
|
switch (scanner.getTokenError()) {
|
|
1024
|
-
case 4 /* InvalidUnicode */:
|
|
1030
|
+
case 4 /* Json.ScanError.InvalidUnicode */:
|
|
1025
1031
|
_error(localize('InvalidUnicode', 'Invalid unicode sequence in string.'), jsonLanguageTypes_1.ErrorCode.InvalidUnicode);
|
|
1026
1032
|
return true;
|
|
1027
|
-
case 5 /* InvalidEscapeCharacter */:
|
|
1033
|
+
case 5 /* Json.ScanError.InvalidEscapeCharacter */:
|
|
1028
1034
|
_error(localize('InvalidEscapeCharacter', 'Invalid escape character in string.'), jsonLanguageTypes_1.ErrorCode.InvalidEscapeCharacter);
|
|
1029
1035
|
return true;
|
|
1030
|
-
case 3 /* UnexpectedEndOfNumber */:
|
|
1036
|
+
case 3 /* Json.ScanError.UnexpectedEndOfNumber */:
|
|
1031
1037
|
_error(localize('UnexpectedEndOfNumber', 'Unexpected end of number.'), jsonLanguageTypes_1.ErrorCode.UnexpectedEndOfNumber);
|
|
1032
1038
|
return true;
|
|
1033
|
-
case 1 /* UnexpectedEndOfComment */:
|
|
1039
|
+
case 1 /* Json.ScanError.UnexpectedEndOfComment */:
|
|
1034
1040
|
_error(localize('UnexpectedEndOfComment', 'Unexpected end of comment.'), jsonLanguageTypes_1.ErrorCode.UnexpectedEndOfComment);
|
|
1035
1041
|
return true;
|
|
1036
|
-
case 2 /* UnexpectedEndOfString */:
|
|
1042
|
+
case 2 /* Json.ScanError.UnexpectedEndOfString */:
|
|
1037
1043
|
_error(localize('UnexpectedEndOfString', 'Unexpected end of string.'), jsonLanguageTypes_1.ErrorCode.UnexpectedEndOfString);
|
|
1038
1044
|
return true;
|
|
1039
|
-
case 6 /* InvalidCharacter */:
|
|
1045
|
+
case 6 /* Json.ScanError.InvalidCharacter */:
|
|
1040
1046
|
_error(localize('InvalidCharacter', 'Invalid characters in string. Control characters must be escaped.'), jsonLanguageTypes_1.ErrorCode.InvalidCharacter);
|
|
1041
1047
|
return true;
|
|
1042
1048
|
}
|
|
@@ -1050,21 +1056,21 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
1050
1056
|
return node;
|
|
1051
1057
|
}
|
|
1052
1058
|
function _parseArray(parent) {
|
|
1053
|
-
if (scanner.getToken() !== 3 /* OpenBracketToken */) {
|
|
1059
|
+
if (scanner.getToken() !== 3 /* Json.SyntaxKind.OpenBracketToken */) {
|
|
1054
1060
|
return undefined;
|
|
1055
1061
|
}
|
|
1056
|
-
|
|
1062
|
+
const node = new ArrayASTNodeImpl(parent, scanner.getTokenOffset());
|
|
1057
1063
|
_scanNext(); // consume OpenBracketToken
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
while (scanner.getToken() !== 4 /* CloseBracketToken */ && scanner.getToken() !== 17 /* EOF */) {
|
|
1061
|
-
if (scanner.getToken() === 5 /* CommaToken */) {
|
|
1064
|
+
const count = 0;
|
|
1065
|
+
let needsComma = false;
|
|
1066
|
+
while (scanner.getToken() !== 4 /* Json.SyntaxKind.CloseBracketToken */ && scanner.getToken() !== 17 /* Json.SyntaxKind.EOF */) {
|
|
1067
|
+
if (scanner.getToken() === 5 /* Json.SyntaxKind.CommaToken */) {
|
|
1062
1068
|
if (!needsComma) {
|
|
1063
1069
|
_error(localize('ValueExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected);
|
|
1064
1070
|
}
|
|
1065
|
-
|
|
1071
|
+
const commaOffset = scanner.getTokenOffset();
|
|
1066
1072
|
_scanNext(); // consume comma
|
|
1067
|
-
if (scanner.getToken() === 4 /* CloseBracketToken */) {
|
|
1073
|
+
if (scanner.getToken() === 4 /* Json.SyntaxKind.CloseBracketToken */) {
|
|
1068
1074
|
if (needsComma) {
|
|
1069
1075
|
_errorAtRange(localize('TrailingComma', 'Trailing comma'), jsonLanguageTypes_1.ErrorCode.TrailingComma, commaOffset, commaOffset + 1);
|
|
1070
1076
|
}
|
|
@@ -1074,29 +1080,29 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
1074
1080
|
else if (needsComma) {
|
|
1075
1081
|
_error(localize('ExpectedComma', 'Expected comma'), jsonLanguageTypes_1.ErrorCode.CommaExpected);
|
|
1076
1082
|
}
|
|
1077
|
-
|
|
1083
|
+
const item = _parseValue(node);
|
|
1078
1084
|
if (!item) {
|
|
1079
|
-
_error(localize('PropertyExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected, undefined, [], [4 /* CloseBracketToken */, 5 /* CommaToken */]);
|
|
1085
|
+
_error(localize('PropertyExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected, undefined, [], [4 /* Json.SyntaxKind.CloseBracketToken */, 5 /* Json.SyntaxKind.CommaToken */]);
|
|
1080
1086
|
}
|
|
1081
1087
|
else {
|
|
1082
1088
|
node.items.push(item);
|
|
1083
1089
|
}
|
|
1084
1090
|
needsComma = true;
|
|
1085
1091
|
}
|
|
1086
|
-
if (scanner.getToken() !== 4 /* CloseBracketToken */) {
|
|
1092
|
+
if (scanner.getToken() !== 4 /* Json.SyntaxKind.CloseBracketToken */) {
|
|
1087
1093
|
return _error(localize('ExpectedCloseBracket', 'Expected comma or closing bracket'), jsonLanguageTypes_1.ErrorCode.CommaOrCloseBacketExpected, node);
|
|
1088
1094
|
}
|
|
1089
1095
|
return _finalize(node, true);
|
|
1090
1096
|
}
|
|
1091
|
-
|
|
1097
|
+
const keyPlaceholder = new StringASTNodeImpl(undefined, 0, 0);
|
|
1092
1098
|
function _parseProperty(parent, keysSeen) {
|
|
1093
|
-
|
|
1094
|
-
|
|
1099
|
+
const node = new PropertyASTNodeImpl(parent, scanner.getTokenOffset(), keyPlaceholder);
|
|
1100
|
+
let key = _parseString(node);
|
|
1095
1101
|
if (!key) {
|
|
1096
|
-
if (scanner.getToken() === 16 /* Unknown */) {
|
|
1102
|
+
if (scanner.getToken() === 16 /* Json.SyntaxKind.Unknown */) {
|
|
1097
1103
|
// give a more helpful error message
|
|
1098
1104
|
_error(localize('DoubleQuotesExpected', 'Property keys must be doublequoted'), jsonLanguageTypes_1.ErrorCode.Undefined);
|
|
1099
|
-
|
|
1105
|
+
const keyNode = new StringASTNodeImpl(node, scanner.getTokenOffset(), scanner.getTokenLength());
|
|
1100
1106
|
keyNode.value = scanner.getTokenValue();
|
|
1101
1107
|
key = keyNode;
|
|
1102
1108
|
_scanNext(); // consume Unknown
|
|
@@ -1106,52 +1112,56 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
1106
1112
|
}
|
|
1107
1113
|
}
|
|
1108
1114
|
node.keyNode = key;
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1115
|
+
// For JSON files that forbid code comments, there is a convention to use the key name "//" to add comments.
|
|
1116
|
+
// Multiple instances of "//" are okay.
|
|
1117
|
+
if (key.value !== "//") {
|
|
1118
|
+
const seen = keysSeen[key.value];
|
|
1119
|
+
if (seen) {
|
|
1120
|
+
_errorAtRange(localize('DuplicateKeyWarning', "Duplicate object key"), jsonLanguageTypes_1.ErrorCode.DuplicateKey, node.keyNode.offset, node.keyNode.offset + node.keyNode.length, jsonLanguageTypes_1.DiagnosticSeverity.Warning);
|
|
1121
|
+
if ((0, objects_1.isObject)(seen)) {
|
|
1122
|
+
_errorAtRange(localize('DuplicateKeyWarning', "Duplicate object key"), jsonLanguageTypes_1.ErrorCode.DuplicateKey, seen.keyNode.offset, seen.keyNode.offset + seen.keyNode.length, jsonLanguageTypes_1.DiagnosticSeverity.Warning);
|
|
1123
|
+
}
|
|
1124
|
+
keysSeen[key.value] = true; // if the same key is duplicate again, avoid duplicate error reporting
|
|
1125
|
+
}
|
|
1126
|
+
else {
|
|
1127
|
+
keysSeen[key.value] = node;
|
|
1114
1128
|
}
|
|
1115
|
-
keysSeen[key.value] = true; // if the same key is duplicate again, avoid duplicate error reporting
|
|
1116
|
-
}
|
|
1117
|
-
else {
|
|
1118
|
-
keysSeen[key.value] = node;
|
|
1119
1129
|
}
|
|
1120
|
-
if (scanner.getToken() === 6 /* ColonToken */) {
|
|
1130
|
+
if (scanner.getToken() === 6 /* Json.SyntaxKind.ColonToken */) {
|
|
1121
1131
|
node.colonOffset = scanner.getTokenOffset();
|
|
1122
1132
|
_scanNext(); // consume ColonToken
|
|
1123
1133
|
}
|
|
1124
1134
|
else {
|
|
1125
1135
|
_error(localize('ColonExpected', 'Colon expected'), jsonLanguageTypes_1.ErrorCode.ColonExpected);
|
|
1126
|
-
if (scanner.getToken() === 10 /* StringLiteral */ && textDocument.positionAt(key.offset + key.length).line < textDocument.positionAt(scanner.getTokenOffset()).line) {
|
|
1136
|
+
if (scanner.getToken() === 10 /* Json.SyntaxKind.StringLiteral */ && textDocument.positionAt(key.offset + key.length).line < textDocument.positionAt(scanner.getTokenOffset()).line) {
|
|
1127
1137
|
node.length = key.length;
|
|
1128
1138
|
return node;
|
|
1129
1139
|
}
|
|
1130
1140
|
}
|
|
1131
|
-
|
|
1141
|
+
const value = _parseValue(node);
|
|
1132
1142
|
if (!value) {
|
|
1133
|
-
return _error(localize('ValueExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected, node, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
|
|
1143
|
+
return _error(localize('ValueExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected, node, [], [2 /* Json.SyntaxKind.CloseBraceToken */, 5 /* Json.SyntaxKind.CommaToken */]);
|
|
1134
1144
|
}
|
|
1135
1145
|
node.valueNode = value;
|
|
1136
1146
|
node.length = value.offset + value.length - node.offset;
|
|
1137
1147
|
return node;
|
|
1138
1148
|
}
|
|
1139
1149
|
function _parseObject(parent) {
|
|
1140
|
-
if (scanner.getToken() !== 1 /* OpenBraceToken */) {
|
|
1150
|
+
if (scanner.getToken() !== 1 /* Json.SyntaxKind.OpenBraceToken */) {
|
|
1141
1151
|
return undefined;
|
|
1142
1152
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1153
|
+
const node = new ObjectASTNodeImpl(parent, scanner.getTokenOffset());
|
|
1154
|
+
const keysSeen = Object.create(null);
|
|
1145
1155
|
_scanNext(); // consume OpenBraceToken
|
|
1146
|
-
|
|
1147
|
-
while (scanner.getToken() !== 2 /* CloseBraceToken */ && scanner.getToken() !== 17 /* EOF */) {
|
|
1148
|
-
if (scanner.getToken() === 5 /* CommaToken */) {
|
|
1156
|
+
let needsComma = false;
|
|
1157
|
+
while (scanner.getToken() !== 2 /* Json.SyntaxKind.CloseBraceToken */ && scanner.getToken() !== 17 /* Json.SyntaxKind.EOF */) {
|
|
1158
|
+
if (scanner.getToken() === 5 /* Json.SyntaxKind.CommaToken */) {
|
|
1149
1159
|
if (!needsComma) {
|
|
1150
1160
|
_error(localize('PropertyExpected', 'Property expected'), jsonLanguageTypes_1.ErrorCode.PropertyExpected);
|
|
1151
1161
|
}
|
|
1152
|
-
|
|
1162
|
+
const commaOffset = scanner.getTokenOffset();
|
|
1153
1163
|
_scanNext(); // consume comma
|
|
1154
|
-
if (scanner.getToken() === 2 /* CloseBraceToken */) {
|
|
1164
|
+
if (scanner.getToken() === 2 /* Json.SyntaxKind.CloseBraceToken */) {
|
|
1155
1165
|
if (needsComma) {
|
|
1156
1166
|
_errorAtRange(localize('TrailingComma', 'Trailing comma'), jsonLanguageTypes_1.ErrorCode.TrailingComma, commaOffset, commaOffset + 1);
|
|
1157
1167
|
}
|
|
@@ -1161,37 +1171,37 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
1161
1171
|
else if (needsComma) {
|
|
1162
1172
|
_error(localize('ExpectedComma', 'Expected comma'), jsonLanguageTypes_1.ErrorCode.CommaExpected);
|
|
1163
1173
|
}
|
|
1164
|
-
|
|
1174
|
+
const property = _parseProperty(node, keysSeen);
|
|
1165
1175
|
if (!property) {
|
|
1166
|
-
_error(localize('PropertyExpected', 'Property expected'), jsonLanguageTypes_1.ErrorCode.PropertyExpected, undefined, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
|
|
1176
|
+
_error(localize('PropertyExpected', 'Property expected'), jsonLanguageTypes_1.ErrorCode.PropertyExpected, undefined, [], [2 /* Json.SyntaxKind.CloseBraceToken */, 5 /* Json.SyntaxKind.CommaToken */]);
|
|
1167
1177
|
}
|
|
1168
1178
|
else {
|
|
1169
1179
|
node.properties.push(property);
|
|
1170
1180
|
}
|
|
1171
1181
|
needsComma = true;
|
|
1172
1182
|
}
|
|
1173
|
-
if (scanner.getToken() !== 2 /* CloseBraceToken */) {
|
|
1183
|
+
if (scanner.getToken() !== 2 /* Json.SyntaxKind.CloseBraceToken */) {
|
|
1174
1184
|
return _error(localize('ExpectedCloseBrace', 'Expected comma or closing brace'), jsonLanguageTypes_1.ErrorCode.CommaOrCloseBraceExpected, node);
|
|
1175
1185
|
}
|
|
1176
1186
|
return _finalize(node, true);
|
|
1177
1187
|
}
|
|
1178
1188
|
function _parseString(parent) {
|
|
1179
|
-
if (scanner.getToken() !== 10 /* StringLiteral */) {
|
|
1189
|
+
if (scanner.getToken() !== 10 /* Json.SyntaxKind.StringLiteral */) {
|
|
1180
1190
|
return undefined;
|
|
1181
1191
|
}
|
|
1182
|
-
|
|
1192
|
+
const node = new StringASTNodeImpl(parent, scanner.getTokenOffset());
|
|
1183
1193
|
node.value = scanner.getTokenValue();
|
|
1184
1194
|
return _finalize(node, true);
|
|
1185
1195
|
}
|
|
1186
1196
|
function _parseNumber(parent) {
|
|
1187
|
-
if (scanner.getToken() !== 11 /* NumericLiteral */) {
|
|
1197
|
+
if (scanner.getToken() !== 11 /* Json.SyntaxKind.NumericLiteral */) {
|
|
1188
1198
|
return undefined;
|
|
1189
1199
|
}
|
|
1190
|
-
|
|
1191
|
-
if (scanner.getTokenError() === 0 /* None */) {
|
|
1192
|
-
|
|
1200
|
+
const node = new NumberASTNodeImpl(parent, scanner.getTokenOffset());
|
|
1201
|
+
if (scanner.getTokenError() === 0 /* Json.ScanError.None */) {
|
|
1202
|
+
const tokenValue = scanner.getTokenValue();
|
|
1193
1203
|
try {
|
|
1194
|
-
|
|
1204
|
+
const numberValue = JSON.parse(tokenValue);
|
|
1195
1205
|
if (!(0, objects_1.isNumber)(numberValue)) {
|
|
1196
1206
|
return _error(localize('InvalidNumberFormat', 'Invalid number format.'), jsonLanguageTypes_1.ErrorCode.Undefined, node);
|
|
1197
1207
|
}
|
|
@@ -1205,13 +1215,13 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
1205
1215
|
return _finalize(node, true);
|
|
1206
1216
|
}
|
|
1207
1217
|
function _parseLiteral(parent) {
|
|
1208
|
-
|
|
1218
|
+
let node;
|
|
1209
1219
|
switch (scanner.getToken()) {
|
|
1210
|
-
case 7 /* NullKeyword */:
|
|
1220
|
+
case 7 /* Json.SyntaxKind.NullKeyword */:
|
|
1211
1221
|
return _finalize(new NullASTNodeImpl(parent, scanner.getTokenOffset()), true);
|
|
1212
|
-
case 8 /* TrueKeyword */:
|
|
1222
|
+
case 8 /* Json.SyntaxKind.TrueKeyword */:
|
|
1213
1223
|
return _finalize(new BooleanASTNodeImpl(parent, true, scanner.getTokenOffset()), true);
|
|
1214
|
-
case 9 /* FalseKeyword */:
|
|
1224
|
+
case 9 /* Json.SyntaxKind.FalseKeyword */:
|
|
1215
1225
|
return _finalize(new BooleanASTNodeImpl(parent, false, scanner.getTokenOffset()), true);
|
|
1216
1226
|
default:
|
|
1217
1227
|
return undefined;
|
|
@@ -1220,14 +1230,14 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
1220
1230
|
function _parseValue(parent) {
|
|
1221
1231
|
return _parseArray(parent) || _parseObject(parent) || _parseString(parent) || _parseNumber(parent) || _parseLiteral(parent);
|
|
1222
1232
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
if (token !== 17 /* EOF */) {
|
|
1233
|
+
let _root = undefined;
|
|
1234
|
+
const token = _scanNext();
|
|
1235
|
+
if (token !== 17 /* Json.SyntaxKind.EOF */) {
|
|
1226
1236
|
_root = _parseValue(_root);
|
|
1227
1237
|
if (!_root) {
|
|
1228
1238
|
_error(localize('Invalid symbol', 'Expected a JSON object, array or literal.'), jsonLanguageTypes_1.ErrorCode.Undefined);
|
|
1229
1239
|
}
|
|
1230
|
-
else if (scanner.getToken() !== 17 /* EOF */) {
|
|
1240
|
+
else if (scanner.getToken() !== 17 /* Json.SyntaxKind.EOF */) {
|
|
1231
1241
|
_error(localize('End of file expected', 'End of file expected.'), jsonLanguageTypes_1.ErrorCode.Undefined);
|
|
1232
1242
|
}
|
|
1233
1243
|
}
|