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
|
@@ -9,72 +9,68 @@ import { endsWith, extendedRegExp } from '../utils/strings';
|
|
|
9
9
|
import { isDefined } from '../utils/objects';
|
|
10
10
|
import { CompletionItem, CompletionItemKind, Range, TextEdit, InsertTextFormat, MarkupKind } from '../jsonLanguageTypes';
|
|
11
11
|
import * as nls from 'vscode-nls';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (contributions === void 0) { contributions = []; }
|
|
18
|
-
if (promiseConstructor === void 0) { promiseConstructor = Promise; }
|
|
19
|
-
if (clientCapabilities === void 0) { clientCapabilities = {}; }
|
|
12
|
+
const localize = nls.loadMessageBundle();
|
|
13
|
+
const valueCommitCharacters = [',', '}', ']'];
|
|
14
|
+
const propertyCommitCharacters = [':'];
|
|
15
|
+
export class JSONCompletion {
|
|
16
|
+
constructor(schemaService, contributions = [], promiseConstructor = Promise, clientCapabilities = {}) {
|
|
20
17
|
this.schemaService = schemaService;
|
|
21
18
|
this.contributions = contributions;
|
|
22
19
|
this.promiseConstructor = promiseConstructor;
|
|
23
20
|
this.clientCapabilities = clientCapabilities;
|
|
24
21
|
}
|
|
25
|
-
|
|
26
|
-
for (
|
|
27
|
-
|
|
22
|
+
doResolve(item) {
|
|
23
|
+
for (let i = this.contributions.length - 1; i >= 0; i--) {
|
|
24
|
+
const resolveCompletion = this.contributions[i].resolveCompletion;
|
|
28
25
|
if (resolveCompletion) {
|
|
29
|
-
|
|
26
|
+
const resolver = resolveCompletion(item);
|
|
30
27
|
if (resolver) {
|
|
31
28
|
return resolver;
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
}
|
|
35
32
|
return this.promiseConstructor.resolve(item);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
var result = {
|
|
33
|
+
}
|
|
34
|
+
doComplete(document, position, doc) {
|
|
35
|
+
const result = {
|
|
40
36
|
items: [],
|
|
41
37
|
isIncomplete: false
|
|
42
38
|
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
const text = document.getText();
|
|
40
|
+
const offset = document.offsetAt(position);
|
|
41
|
+
let node = doc.getNodeFromOffset(offset, true);
|
|
46
42
|
if (this.isInComment(document, node ? node.offset : 0, offset)) {
|
|
47
43
|
return Promise.resolve(result);
|
|
48
44
|
}
|
|
49
45
|
if (node && (offset === node.offset + node.length) && offset > 0) {
|
|
50
|
-
|
|
46
|
+
const ch = text[offset - 1];
|
|
51
47
|
if (node.type === 'object' && ch === '}' || node.type === 'array' && ch === ']') {
|
|
52
48
|
// after ] or }
|
|
53
49
|
node = node.parent;
|
|
54
50
|
}
|
|
55
51
|
}
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
const currentWord = this.getCurrentWord(document, offset);
|
|
53
|
+
let overwriteRange;
|
|
58
54
|
if (node && (node.type === 'string' || node.type === 'number' || node.type === 'boolean' || node.type === 'null')) {
|
|
59
55
|
overwriteRange = Range.create(document.positionAt(node.offset), document.positionAt(node.offset + node.length));
|
|
60
56
|
}
|
|
61
57
|
else {
|
|
62
|
-
|
|
58
|
+
let overwriteStart = offset - currentWord.length;
|
|
63
59
|
if (overwriteStart > 0 && text[overwriteStart - 1] === '"') {
|
|
64
60
|
overwriteStart--;
|
|
65
61
|
}
|
|
66
62
|
overwriteRange = Range.create(document.positionAt(overwriteStart), position);
|
|
67
63
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
add:
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
const supportsCommitCharacters = false; //this.doesSupportsCommitCharacters(); disabled for now, waiting for new API: https://github.com/microsoft/vscode/issues/42544
|
|
65
|
+
const proposed = {};
|
|
66
|
+
const collector = {
|
|
67
|
+
add: (suggestion) => {
|
|
68
|
+
let label = suggestion.label;
|
|
69
|
+
const existing = proposed[label];
|
|
74
70
|
if (!existing) {
|
|
75
71
|
label = label.replace(/[\n]/g, '↵');
|
|
76
72
|
if (label.length > 60) {
|
|
77
|
-
|
|
73
|
+
const shortendedLabel = label.substr(0, 57).trim() + '...';
|
|
78
74
|
if (!proposed[shortendedLabel]) {
|
|
79
75
|
label = shortendedLabel;
|
|
80
76
|
}
|
|
@@ -98,27 +94,27 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
98
94
|
}
|
|
99
95
|
}
|
|
100
96
|
},
|
|
101
|
-
setAsIncomplete:
|
|
97
|
+
setAsIncomplete: () => {
|
|
102
98
|
result.isIncomplete = true;
|
|
103
99
|
},
|
|
104
|
-
error:
|
|
100
|
+
error: (message) => {
|
|
105
101
|
console.error(message);
|
|
106
102
|
},
|
|
107
|
-
log:
|
|
103
|
+
log: (message) => {
|
|
108
104
|
console.log(message);
|
|
109
105
|
},
|
|
110
|
-
getNumberOfProposals:
|
|
106
|
+
getNumberOfProposals: () => {
|
|
111
107
|
return result.items.length;
|
|
112
108
|
}
|
|
113
109
|
};
|
|
114
|
-
return this.schemaService.getSchemaForResource(document.uri, doc).then(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
return this.schemaService.getSchemaForResource(document.uri, doc).then((schema) => {
|
|
111
|
+
const collectionPromises = [];
|
|
112
|
+
let addValue = true;
|
|
113
|
+
let currentKey = '';
|
|
114
|
+
let currentProperty = undefined;
|
|
119
115
|
if (node) {
|
|
120
116
|
if (node.type === 'string') {
|
|
121
|
-
|
|
117
|
+
const parent = node.parent;
|
|
122
118
|
if (parent && parent.type === 'property' && parent.keyNode === node) {
|
|
123
119
|
addValue = !parent.valueNode;
|
|
124
120
|
currentProperty = parent;
|
|
@@ -136,27 +132,27 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
136
132
|
return result;
|
|
137
133
|
}
|
|
138
134
|
// don't suggest properties that are already present
|
|
139
|
-
|
|
140
|
-
properties.forEach(
|
|
135
|
+
const properties = node.properties;
|
|
136
|
+
properties.forEach(p => {
|
|
141
137
|
if (!currentProperty || currentProperty !== p) {
|
|
142
138
|
proposed[p.keyNode.value] = CompletionItem.create('__');
|
|
143
139
|
}
|
|
144
140
|
});
|
|
145
|
-
|
|
141
|
+
let separatorAfter = '';
|
|
146
142
|
if (addValue) {
|
|
147
|
-
|
|
143
|
+
separatorAfter = this.evaluateSeparatorAfter(document, document.offsetAt(overwriteRange.end));
|
|
148
144
|
}
|
|
149
145
|
if (schema) {
|
|
150
146
|
// property proposals with schema
|
|
151
|
-
|
|
147
|
+
this.getPropertyCompletions(schema, doc, node, addValue, separatorAfter, collector);
|
|
152
148
|
}
|
|
153
149
|
else {
|
|
154
150
|
// property proposals without schema
|
|
155
|
-
|
|
151
|
+
this.getSchemaLessPropertyCompletions(doc, node, currentKey, collector);
|
|
156
152
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
153
|
+
const location = Parser.getNodePath(node);
|
|
154
|
+
this.contributions.forEach((contribution) => {
|
|
155
|
+
const collectPromise = contribution.collectPropertyCompletions(document.uri, location, currentWord, addValue, separatorAfter === '', collector);
|
|
160
156
|
if (collectPromise) {
|
|
161
157
|
collectionPromises.push(collectPromise);
|
|
162
158
|
}
|
|
@@ -164,61 +160,60 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
164
160
|
if ((!schema && currentWord.length > 0 && text.charAt(offset - currentWord.length - 1) !== '"')) {
|
|
165
161
|
collector.add({
|
|
166
162
|
kind: CompletionItemKind.Property,
|
|
167
|
-
label:
|
|
168
|
-
insertText:
|
|
163
|
+
label: this.getLabelForValue(currentWord),
|
|
164
|
+
insertText: this.getInsertTextForProperty(currentWord, undefined, false, separatorAfter),
|
|
169
165
|
insertTextFormat: InsertTextFormat.Snippet, documentation: '',
|
|
170
166
|
});
|
|
171
167
|
collector.setAsIncomplete();
|
|
172
168
|
}
|
|
173
169
|
}
|
|
174
170
|
// proposals for values
|
|
175
|
-
|
|
171
|
+
const types = {};
|
|
176
172
|
if (schema) {
|
|
177
173
|
// value proposals with schema
|
|
178
|
-
|
|
174
|
+
this.getValueCompletions(schema, doc, node, offset, document, collector, types);
|
|
179
175
|
}
|
|
180
176
|
else {
|
|
181
177
|
// value proposals without schema
|
|
182
|
-
|
|
178
|
+
this.getSchemaLessValueCompletions(doc, node, offset, document, collector);
|
|
183
179
|
}
|
|
184
|
-
if (
|
|
185
|
-
|
|
180
|
+
if (this.contributions.length > 0) {
|
|
181
|
+
this.getContributedValueCompletions(doc, node, offset, document, collector, collectionPromises);
|
|
186
182
|
}
|
|
187
|
-
return
|
|
183
|
+
return this.promiseConstructor.all(collectionPromises).then(() => {
|
|
188
184
|
if (collector.getNumberOfProposals() === 0) {
|
|
189
|
-
|
|
185
|
+
let offsetForSeparator = offset;
|
|
190
186
|
if (node && (node.type === 'string' || node.type === 'number' || node.type === 'boolean' || node.type === 'null')) {
|
|
191
187
|
offsetForSeparator = node.offset + node.length;
|
|
192
188
|
}
|
|
193
|
-
|
|
194
|
-
|
|
189
|
+
const separatorAfter = this.evaluateSeparatorAfter(document, offsetForSeparator);
|
|
190
|
+
this.addFillerValueCompletions(types, separatorAfter, collector);
|
|
195
191
|
}
|
|
196
192
|
return result;
|
|
197
193
|
});
|
|
198
194
|
});
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
matchingSchemas.forEach(function (s) {
|
|
195
|
+
}
|
|
196
|
+
getPropertyCompletions(schema, doc, node, addValue, separatorAfter, collector) {
|
|
197
|
+
const matchingSchemas = doc.getMatchingSchemas(schema.schema, node.offset);
|
|
198
|
+
matchingSchemas.forEach((s) => {
|
|
204
199
|
if (s.node === node && !s.inverted) {
|
|
205
|
-
|
|
206
|
-
if (
|
|
207
|
-
Object.keys(
|
|
208
|
-
|
|
200
|
+
const schemaProperties = s.schema.properties;
|
|
201
|
+
if (schemaProperties) {
|
|
202
|
+
Object.keys(schemaProperties).forEach((key) => {
|
|
203
|
+
const propertySchema = schemaProperties[key];
|
|
209
204
|
if (typeof propertySchema === 'object' && !propertySchema.deprecationMessage && !propertySchema.doNotSuggest) {
|
|
210
|
-
|
|
205
|
+
const proposal = {
|
|
211
206
|
kind: CompletionItemKind.Property,
|
|
212
207
|
label: key,
|
|
213
|
-
insertText:
|
|
208
|
+
insertText: this.getInsertTextForProperty(key, propertySchema, addValue, separatorAfter),
|
|
214
209
|
insertTextFormat: InsertTextFormat.Snippet,
|
|
215
|
-
filterText:
|
|
216
|
-
documentation:
|
|
210
|
+
filterText: this.getFilterTextForValue(key),
|
|
211
|
+
documentation: this.fromMarkup(propertySchema.markdownDescription) || propertySchema.description || '',
|
|
217
212
|
};
|
|
218
213
|
if (propertySchema.suggestSortText !== undefined) {
|
|
219
214
|
proposal.sortText = propertySchema.suggestSortText;
|
|
220
215
|
}
|
|
221
|
-
if (proposal.insertText && endsWith(proposal.insertText,
|
|
216
|
+
if (proposal.insertText && endsWith(proposal.insertText, `$1${separatorAfter}`)) {
|
|
222
217
|
proposal.command = {
|
|
223
218
|
title: 'Suggest',
|
|
224
219
|
command: 'editor.action.triggerSuggest'
|
|
@@ -228,22 +223,21 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
228
223
|
}
|
|
229
224
|
});
|
|
230
225
|
}
|
|
231
|
-
|
|
232
|
-
if (typeof
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
var proposal = {
|
|
226
|
+
const schemaPropertyNames = s.schema.propertyNames;
|
|
227
|
+
if (typeof schemaPropertyNames === 'object' && !schemaPropertyNames.deprecationMessage && !schemaPropertyNames.doNotSuggest) {
|
|
228
|
+
const propertyNameCompletionItem = (name, enumDescription = undefined) => {
|
|
229
|
+
const proposal = {
|
|
236
230
|
kind: CompletionItemKind.Property,
|
|
237
231
|
label: name,
|
|
238
|
-
insertText:
|
|
232
|
+
insertText: this.getInsertTextForProperty(name, undefined, addValue, separatorAfter),
|
|
239
233
|
insertTextFormat: InsertTextFormat.Snippet,
|
|
240
|
-
filterText:
|
|
241
|
-
documentation: enumDescription ||
|
|
234
|
+
filterText: this.getFilterTextForValue(name),
|
|
235
|
+
documentation: enumDescription || this.fromMarkup(schemaPropertyNames.markdownDescription) || schemaPropertyNames.description || '',
|
|
242
236
|
};
|
|
243
|
-
if (
|
|
244
|
-
proposal.sortText =
|
|
237
|
+
if (schemaPropertyNames.suggestSortText !== undefined) {
|
|
238
|
+
proposal.sortText = schemaPropertyNames.suggestSortText;
|
|
245
239
|
}
|
|
246
|
-
if (proposal.insertText && endsWith(proposal.insertText,
|
|
240
|
+
if (proposal.insertText && endsWith(proposal.insertText, `$1${separatorAfter}`)) {
|
|
247
241
|
proposal.command = {
|
|
248
242
|
title: 'Suggest',
|
|
249
243
|
command: 'editor.action.triggerSuggest'
|
|
@@ -251,36 +245,35 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
251
245
|
}
|
|
252
246
|
collector.add(proposal);
|
|
253
247
|
};
|
|
254
|
-
if (
|
|
255
|
-
for (
|
|
256
|
-
|
|
257
|
-
if (
|
|
258
|
-
enumDescription =
|
|
248
|
+
if (schemaPropertyNames.enum) {
|
|
249
|
+
for (let i = 0; i < schemaPropertyNames.enum.length; i++) {
|
|
250
|
+
let enumDescription = undefined;
|
|
251
|
+
if (schemaPropertyNames.markdownEnumDescriptions && i < schemaPropertyNames.markdownEnumDescriptions.length) {
|
|
252
|
+
enumDescription = this.fromMarkup(schemaPropertyNames.markdownEnumDescriptions[i]);
|
|
259
253
|
}
|
|
260
|
-
else if (
|
|
261
|
-
enumDescription =
|
|
254
|
+
else if (schemaPropertyNames.enumDescriptions && i < schemaPropertyNames.enumDescriptions.length) {
|
|
255
|
+
enumDescription = schemaPropertyNames.enumDescriptions[i];
|
|
262
256
|
}
|
|
263
|
-
propertyNameCompletionItem(
|
|
257
|
+
propertyNameCompletionItem(schemaPropertyNames.enum[i], enumDescription);
|
|
264
258
|
}
|
|
265
259
|
}
|
|
266
|
-
if (
|
|
267
|
-
propertyNameCompletionItem(
|
|
260
|
+
if (schemaPropertyNames.const) {
|
|
261
|
+
propertyNameCompletionItem(schemaPropertyNames.const);
|
|
268
262
|
}
|
|
269
263
|
}
|
|
270
264
|
}
|
|
271
265
|
});
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
var key = p.keyNode.value;
|
|
266
|
+
}
|
|
267
|
+
getSchemaLessPropertyCompletions(doc, node, currentKey, collector) {
|
|
268
|
+
const collectCompletionsForSimilarObject = (obj) => {
|
|
269
|
+
obj.properties.forEach((p) => {
|
|
270
|
+
const key = p.keyNode.value;
|
|
278
271
|
collector.add({
|
|
279
272
|
kind: CompletionItemKind.Property,
|
|
280
273
|
label: key,
|
|
281
|
-
insertText:
|
|
274
|
+
insertText: this.getInsertTextForValue(key, ''),
|
|
282
275
|
insertTextFormat: InsertTextFormat.Snippet,
|
|
283
|
-
filterText:
|
|
276
|
+
filterText: this.getFilterTextForValue(key),
|
|
284
277
|
documentation: ''
|
|
285
278
|
});
|
|
286
279
|
});
|
|
@@ -288,9 +281,9 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
288
281
|
if (node.parent) {
|
|
289
282
|
if (node.parent.type === 'property') {
|
|
290
283
|
// if the object is a property value, check the tree for other objects that hang under a property of the same name
|
|
291
|
-
|
|
292
|
-
doc.visit(
|
|
293
|
-
if (n.type === 'property' && n !== node.parent && n.keyNode.value ===
|
|
284
|
+
const parentKey = node.parent.keyNode.value;
|
|
285
|
+
doc.visit(n => {
|
|
286
|
+
if (n.type === 'property' && n !== node.parent && n.keyNode.value === parentKey && n.valueNode && n.valueNode.type === 'object') {
|
|
294
287
|
collectCompletionsForSimilarObject(n.valueNode);
|
|
295
288
|
}
|
|
296
289
|
return true;
|
|
@@ -298,7 +291,7 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
298
291
|
}
|
|
299
292
|
else if (node.parent.type === 'array') {
|
|
300
293
|
// if the object is in an array, use all other array elements as similar objects
|
|
301
|
-
node.parent.items.forEach(
|
|
294
|
+
node.parent.items.forEach(n => {
|
|
302
295
|
if (n.type === 'object' && n !== node) {
|
|
303
296
|
collectCompletionsForSimilarObject(n);
|
|
304
297
|
}
|
|
@@ -314,10 +307,9 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
314
307
|
filterText: this.getFilterTextForValue("$schema")
|
|
315
308
|
});
|
|
316
309
|
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
var offsetForSeparator = offset;
|
|
310
|
+
}
|
|
311
|
+
getSchemaLessValueCompletions(doc, node, offset, document, collector) {
|
|
312
|
+
let offsetForSeparator = offset;
|
|
321
313
|
if (node && (node.type === 'string' || node.type === 'number' || node.type === 'boolean' || node.type === 'null')) {
|
|
322
314
|
offsetForSeparator = node.offset + node.length;
|
|
323
315
|
node = node.parent;
|
|
@@ -339,35 +331,35 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
339
331
|
});
|
|
340
332
|
return;
|
|
341
333
|
}
|
|
342
|
-
|
|
343
|
-
|
|
334
|
+
const separatorAfter = this.evaluateSeparatorAfter(document, offsetForSeparator);
|
|
335
|
+
const collectSuggestionsForValues = (value) => {
|
|
344
336
|
if (value.parent && !Parser.contains(value.parent, offset, true)) {
|
|
345
337
|
collector.add({
|
|
346
|
-
kind:
|
|
347
|
-
label:
|
|
348
|
-
insertText:
|
|
338
|
+
kind: this.getSuggestionKind(value.type),
|
|
339
|
+
label: this.getLabelTextForMatchingNode(value, document),
|
|
340
|
+
insertText: this.getInsertTextForMatchingNode(value, document, separatorAfter),
|
|
349
341
|
insertTextFormat: InsertTextFormat.Snippet, documentation: ''
|
|
350
342
|
});
|
|
351
343
|
}
|
|
352
344
|
if (value.type === 'boolean') {
|
|
353
|
-
|
|
345
|
+
this.addBooleanValueCompletion(!value.value, separatorAfter, collector);
|
|
354
346
|
}
|
|
355
347
|
};
|
|
356
348
|
if (node.type === 'property') {
|
|
357
349
|
if (offset > (node.colonOffset || 0)) {
|
|
358
|
-
|
|
350
|
+
const valueNode = node.valueNode;
|
|
359
351
|
if (valueNode && (offset > (valueNode.offset + valueNode.length) || valueNode.type === 'object' || valueNode.type === 'array')) {
|
|
360
352
|
return;
|
|
361
353
|
}
|
|
362
354
|
// suggest values at the same key
|
|
363
|
-
|
|
364
|
-
doc.visit(
|
|
365
|
-
if (n.type === 'property' && n.keyNode.value ===
|
|
355
|
+
const parentKey = node.keyNode.value;
|
|
356
|
+
doc.visit(n => {
|
|
357
|
+
if (n.type === 'property' && n.keyNode.value === parentKey && n.valueNode) {
|
|
366
358
|
collectSuggestionsForValues(n.valueNode);
|
|
367
359
|
}
|
|
368
360
|
return true;
|
|
369
361
|
});
|
|
370
|
-
if (
|
|
362
|
+
if (parentKey === '$schema' && node.parent && !node.parent.parent) {
|
|
371
363
|
this.addDollarSchemaCompletions(separatorAfter, collector);
|
|
372
364
|
}
|
|
373
365
|
}
|
|
@@ -375,9 +367,9 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
375
367
|
if (node.type === 'array') {
|
|
376
368
|
if (node.parent && node.parent.type === 'property') {
|
|
377
369
|
// suggest items of an array at the same key
|
|
378
|
-
|
|
379
|
-
doc.visit(
|
|
380
|
-
if (n.type === 'property' && n.keyNode.value ===
|
|
370
|
+
const parentKey = node.parent.keyNode.value;
|
|
371
|
+
doc.visit((n) => {
|
|
372
|
+
if (n.type === 'property' && n.keyNode.value === parentKey && n.valueNode && n.valueNode.type === 'array') {
|
|
381
373
|
n.valueNode.items.forEach(collectSuggestionsForValues);
|
|
382
374
|
}
|
|
383
375
|
return true;
|
|
@@ -388,11 +380,11 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
388
380
|
node.items.forEach(collectSuggestionsForValues);
|
|
389
381
|
}
|
|
390
382
|
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
383
|
+
}
|
|
384
|
+
getValueCompletions(schema, doc, node, offset, document, collector, types) {
|
|
385
|
+
let offsetForSeparator = offset;
|
|
386
|
+
let parentKey = undefined;
|
|
387
|
+
let valueNode = undefined;
|
|
396
388
|
if (node && (node.type === 'string' || node.type === 'number' || node.type === 'boolean' || node.type === 'null')) {
|
|
397
389
|
offsetForSeparator = node.offset + node.length;
|
|
398
390
|
valueNode = node;
|
|
@@ -403,22 +395,21 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
403
395
|
return;
|
|
404
396
|
}
|
|
405
397
|
if ((node.type === 'property') && offset > (node.colonOffset || 0)) {
|
|
406
|
-
|
|
407
|
-
if (
|
|
398
|
+
const valueNode = node.valueNode;
|
|
399
|
+
if (valueNode && offset > (valueNode.offset + valueNode.length)) {
|
|
408
400
|
return; // we are past the value node
|
|
409
401
|
}
|
|
410
402
|
parentKey = node.keyNode.value;
|
|
411
403
|
node = node.parent;
|
|
412
404
|
}
|
|
413
405
|
if (node && (parentKey !== undefined || node.type === 'array')) {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
for (
|
|
417
|
-
var s = matchingSchemas_1[_i];
|
|
406
|
+
const separatorAfter = this.evaluateSeparatorAfter(document, offsetForSeparator);
|
|
407
|
+
const matchingSchemas = doc.getMatchingSchemas(schema.schema, node.offset, valueNode);
|
|
408
|
+
for (const s of matchingSchemas) {
|
|
418
409
|
if (s.node === node && !s.inverted && s.schema) {
|
|
419
410
|
if (node.type === 'array' && s.schema.items) {
|
|
420
411
|
if (Array.isArray(s.schema.items)) {
|
|
421
|
-
|
|
412
|
+
const index = this.findItemAtOffset(node, document, offset);
|
|
422
413
|
if (index < s.schema.items.length) {
|
|
423
414
|
this.addSchemaValueCompletions(s.schema.items[index], separatorAfter, collector, types);
|
|
424
415
|
}
|
|
@@ -428,27 +419,26 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
428
419
|
}
|
|
429
420
|
}
|
|
430
421
|
if (parentKey !== undefined) {
|
|
431
|
-
|
|
422
|
+
let propertyMatched = false;
|
|
432
423
|
if (s.schema.properties) {
|
|
433
|
-
|
|
424
|
+
const propertySchema = s.schema.properties[parentKey];
|
|
434
425
|
if (propertySchema) {
|
|
435
426
|
propertyMatched = true;
|
|
436
427
|
this.addSchemaValueCompletions(propertySchema, separatorAfter, collector, types);
|
|
437
428
|
}
|
|
438
429
|
}
|
|
439
430
|
if (s.schema.patternProperties && !propertyMatched) {
|
|
440
|
-
for (
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
if (regex === null || regex === void 0 ? void 0 : regex.test(parentKey)) {
|
|
431
|
+
for (const pattern of Object.keys(s.schema.patternProperties)) {
|
|
432
|
+
const regex = extendedRegExp(pattern);
|
|
433
|
+
if (regex?.test(parentKey)) {
|
|
444
434
|
propertyMatched = true;
|
|
445
|
-
|
|
435
|
+
const propertySchema = s.schema.patternProperties[pattern];
|
|
446
436
|
this.addSchemaValueCompletions(propertySchema, separatorAfter, collector, types);
|
|
447
437
|
}
|
|
448
438
|
}
|
|
449
439
|
}
|
|
450
440
|
if (s.schema.additionalProperties && !propertyMatched) {
|
|
451
|
-
|
|
441
|
+
const propertySchema = s.schema.additionalProperties;
|
|
452
442
|
this.addSchemaValueCompletions(propertySchema, separatorAfter, collector, types);
|
|
453
443
|
}
|
|
454
444
|
}
|
|
@@ -465,11 +455,11 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
465
455
|
this.addNullValueCompletion(separatorAfter, collector);
|
|
466
456
|
}
|
|
467
457
|
}
|
|
468
|
-
}
|
|
469
|
-
|
|
458
|
+
}
|
|
459
|
+
getContributedValueCompletions(doc, node, offset, document, collector, collectionPromises) {
|
|
470
460
|
if (!node) {
|
|
471
|
-
this.contributions.forEach(
|
|
472
|
-
|
|
461
|
+
this.contributions.forEach((contribution) => {
|
|
462
|
+
const collectPromise = contribution.collectDefaultCompletions(document.uri, collector);
|
|
473
463
|
if (collectPromise) {
|
|
474
464
|
collectionPromises.push(collectPromise);
|
|
475
465
|
}
|
|
@@ -480,12 +470,12 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
480
470
|
node = node.parent;
|
|
481
471
|
}
|
|
482
472
|
if (node && (node.type === 'property') && offset > (node.colonOffset || 0)) {
|
|
483
|
-
|
|
484
|
-
|
|
473
|
+
const parentKey = node.keyNode.value;
|
|
474
|
+
const valueNode = node.valueNode;
|
|
485
475
|
if ((!valueNode || offset <= (valueNode.offset + valueNode.length)) && node.parent) {
|
|
486
|
-
|
|
487
|
-
this.contributions.forEach(
|
|
488
|
-
|
|
476
|
+
const location = Parser.getNodePath(node.parent);
|
|
477
|
+
this.contributions.forEach((contribution) => {
|
|
478
|
+
const collectPromise = contribution.collectValueCompletions(document.uri, location, parentKey, collector);
|
|
489
479
|
if (collectPromise) {
|
|
490
480
|
collectionPromises.push(collectPromise);
|
|
491
481
|
}
|
|
@@ -493,32 +483,29 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
493
483
|
}
|
|
494
484
|
}
|
|
495
485
|
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
var _this = this;
|
|
486
|
+
}
|
|
487
|
+
addSchemaValueCompletions(schema, separatorAfter, collector, types) {
|
|
499
488
|
if (typeof schema === 'object') {
|
|
500
489
|
this.addEnumValueCompletions(schema, separatorAfter, collector);
|
|
501
490
|
this.addDefaultValueCompletions(schema, separatorAfter, collector);
|
|
502
491
|
this.collectTypes(schema, types);
|
|
503
492
|
if (Array.isArray(schema.allOf)) {
|
|
504
|
-
schema.allOf.forEach(
|
|
493
|
+
schema.allOf.forEach(s => this.addSchemaValueCompletions(s, separatorAfter, collector, types));
|
|
505
494
|
}
|
|
506
495
|
if (Array.isArray(schema.anyOf)) {
|
|
507
|
-
schema.anyOf.forEach(
|
|
496
|
+
schema.anyOf.forEach(s => this.addSchemaValueCompletions(s, separatorAfter, collector, types));
|
|
508
497
|
}
|
|
509
498
|
if (Array.isArray(schema.oneOf)) {
|
|
510
|
-
schema.oneOf.forEach(
|
|
499
|
+
schema.oneOf.forEach(s => this.addSchemaValueCompletions(s, separatorAfter, collector, types));
|
|
511
500
|
}
|
|
512
501
|
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
if (arrayDepth === void 0) { arrayDepth = 0; }
|
|
517
|
-
var hasProposals = false;
|
|
502
|
+
}
|
|
503
|
+
addDefaultValueCompletions(schema, separatorAfter, collector, arrayDepth = 0) {
|
|
504
|
+
let hasProposals = false;
|
|
518
505
|
if (isDefined(schema.default)) {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
for (
|
|
506
|
+
let type = schema.type;
|
|
507
|
+
let value = schema.default;
|
|
508
|
+
for (let i = arrayDepth; i > 0; i--) {
|
|
522
509
|
value = [value];
|
|
523
510
|
type = 'array';
|
|
524
511
|
}
|
|
@@ -532,42 +519,42 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
532
519
|
hasProposals = true;
|
|
533
520
|
}
|
|
534
521
|
if (Array.isArray(schema.examples)) {
|
|
535
|
-
schema.examples.forEach(
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
for (
|
|
522
|
+
schema.examples.forEach(example => {
|
|
523
|
+
let type = schema.type;
|
|
524
|
+
let value = example;
|
|
525
|
+
for (let i = arrayDepth; i > 0; i--) {
|
|
539
526
|
value = [value];
|
|
540
527
|
type = 'array';
|
|
541
528
|
}
|
|
542
529
|
collector.add({
|
|
543
|
-
kind:
|
|
544
|
-
label:
|
|
545
|
-
insertText:
|
|
530
|
+
kind: this.getSuggestionKind(type),
|
|
531
|
+
label: this.getLabelForValue(value),
|
|
532
|
+
insertText: this.getInsertTextForValue(value, separatorAfter),
|
|
546
533
|
insertTextFormat: InsertTextFormat.Snippet
|
|
547
534
|
});
|
|
548
535
|
hasProposals = true;
|
|
549
536
|
});
|
|
550
537
|
}
|
|
551
538
|
if (Array.isArray(schema.defaultSnippets)) {
|
|
552
|
-
schema.defaultSnippets.forEach(
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
539
|
+
schema.defaultSnippets.forEach(s => {
|
|
540
|
+
let type = schema.type;
|
|
541
|
+
let value = s.body;
|
|
542
|
+
let label = s.label;
|
|
543
|
+
let insertText;
|
|
544
|
+
let filterText;
|
|
558
545
|
if (isDefined(value)) {
|
|
559
|
-
|
|
560
|
-
for (
|
|
546
|
+
let type = schema.type;
|
|
547
|
+
for (let i = arrayDepth; i > 0; i--) {
|
|
561
548
|
value = [value];
|
|
562
|
-
|
|
549
|
+
type = 'array';
|
|
563
550
|
}
|
|
564
|
-
insertText =
|
|
565
|
-
filterText =
|
|
566
|
-
label = label ||
|
|
551
|
+
insertText = this.getInsertTextForSnippetValue(value, separatorAfter);
|
|
552
|
+
filterText = this.getFilterTextForSnippetValue(value);
|
|
553
|
+
label = label || this.getLabelForSnippetValue(value);
|
|
567
554
|
}
|
|
568
555
|
else if (typeof s.bodyText === 'string') {
|
|
569
|
-
|
|
570
|
-
for (
|
|
556
|
+
let prefix = '', suffix = '', indent = '';
|
|
557
|
+
for (let i = arrayDepth; i > 0; i--) {
|
|
571
558
|
prefix = prefix + indent + '[\n';
|
|
572
559
|
suffix = suffix + '\n' + indent + ']';
|
|
573
560
|
indent += '\t';
|
|
@@ -581,12 +568,12 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
581
568
|
return;
|
|
582
569
|
}
|
|
583
570
|
collector.add({
|
|
584
|
-
kind:
|
|
585
|
-
label
|
|
586
|
-
documentation:
|
|
587
|
-
insertText
|
|
571
|
+
kind: this.getSuggestionKind(type),
|
|
572
|
+
label,
|
|
573
|
+
documentation: this.fromMarkup(s.markdownDescription) || s.description,
|
|
574
|
+
insertText,
|
|
588
575
|
insertTextFormat: InsertTextFormat.Snippet,
|
|
589
|
-
filterText
|
|
576
|
+
filterText
|
|
590
577
|
});
|
|
591
578
|
hasProposals = true;
|
|
592
579
|
});
|
|
@@ -594,8 +581,8 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
594
581
|
if (!hasProposals && typeof schema.items === 'object' && !Array.isArray(schema.items) && arrayDepth < 5 /* beware of recursion */) {
|
|
595
582
|
this.addDefaultValueCompletions(schema.items, separatorAfter, collector, arrayDepth + 1);
|
|
596
583
|
}
|
|
597
|
-
}
|
|
598
|
-
|
|
584
|
+
}
|
|
585
|
+
addEnumValueCompletions(schema, separatorAfter, collector) {
|
|
599
586
|
if (isDefined(schema.const)) {
|
|
600
587
|
collector.add({
|
|
601
588
|
kind: this.getSuggestionKind(schema.type),
|
|
@@ -606,9 +593,9 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
606
593
|
});
|
|
607
594
|
}
|
|
608
595
|
if (Array.isArray(schema.enum)) {
|
|
609
|
-
for (
|
|
610
|
-
|
|
611
|
-
|
|
596
|
+
for (let i = 0, length = schema.enum.length; i < length; i++) {
|
|
597
|
+
const enm = schema.enum[i];
|
|
598
|
+
let documentation = this.fromMarkup(schema.markdownDescription) || schema.description;
|
|
612
599
|
if (schema.markdownEnumDescriptions && i < schema.markdownEnumDescriptions.length && this.doesSupportMarkdown()) {
|
|
613
600
|
documentation = this.fromMarkup(schema.markdownEnumDescriptions[i]);
|
|
614
601
|
}
|
|
@@ -620,24 +607,24 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
620
607
|
label: this.getLabelForValue(enm),
|
|
621
608
|
insertText: this.getInsertTextForValue(enm, separatorAfter),
|
|
622
609
|
insertTextFormat: InsertTextFormat.Snippet,
|
|
623
|
-
documentation
|
|
610
|
+
documentation
|
|
624
611
|
});
|
|
625
612
|
}
|
|
626
613
|
}
|
|
627
|
-
}
|
|
628
|
-
|
|
614
|
+
}
|
|
615
|
+
collectTypes(schema, types) {
|
|
629
616
|
if (Array.isArray(schema.enum) || isDefined(schema.const)) {
|
|
630
617
|
return;
|
|
631
618
|
}
|
|
632
|
-
|
|
619
|
+
const type = schema.type;
|
|
633
620
|
if (Array.isArray(type)) {
|
|
634
|
-
type.forEach(
|
|
621
|
+
type.forEach(t => types[t] = true);
|
|
635
622
|
}
|
|
636
623
|
else if (type) {
|
|
637
624
|
types[type] = true;
|
|
638
625
|
}
|
|
639
|
-
}
|
|
640
|
-
|
|
626
|
+
}
|
|
627
|
+
addFillerValueCompletions(types, separatorAfter, collector) {
|
|
641
628
|
if (types['object']) {
|
|
642
629
|
collector.add({
|
|
643
630
|
kind: this.getSuggestionKind('object'),
|
|
@@ -658,8 +645,8 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
658
645
|
documentation: ''
|
|
659
646
|
});
|
|
660
647
|
}
|
|
661
|
-
}
|
|
662
|
-
|
|
648
|
+
}
|
|
649
|
+
addBooleanValueCompletion(value, separatorAfter, collector) {
|
|
663
650
|
collector.add({
|
|
664
651
|
kind: this.getSuggestionKind('boolean'),
|
|
665
652
|
label: value ? 'true' : 'false',
|
|
@@ -667,8 +654,8 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
667
654
|
insertTextFormat: InsertTextFormat.Snippet,
|
|
668
655
|
documentation: ''
|
|
669
656
|
});
|
|
670
|
-
}
|
|
671
|
-
|
|
657
|
+
}
|
|
658
|
+
addNullValueCompletion(separatorAfter, collector) {
|
|
672
659
|
collector.add({
|
|
673
660
|
kind: this.getSuggestionKind('null'),
|
|
674
661
|
label: 'null',
|
|
@@ -676,35 +663,34 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
676
663
|
insertTextFormat: InsertTextFormat.Snippet,
|
|
677
664
|
documentation: ''
|
|
678
665
|
});
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
schemaIds.forEach(function (schemaId) { return collector.add({
|
|
666
|
+
}
|
|
667
|
+
addDollarSchemaCompletions(separatorAfter, collector) {
|
|
668
|
+
const schemaIds = this.schemaService.getRegisteredSchemaIds(schema => schema === 'http' || schema === 'https');
|
|
669
|
+
schemaIds.forEach(schemaId => collector.add({
|
|
684
670
|
kind: CompletionItemKind.Module,
|
|
685
|
-
label:
|
|
686
|
-
filterText:
|
|
687
|
-
insertText:
|
|
671
|
+
label: this.getLabelForValue(schemaId),
|
|
672
|
+
filterText: this.getFilterTextForValue(schemaId),
|
|
673
|
+
insertText: this.getInsertTextForValue(schemaId, separatorAfter),
|
|
688
674
|
insertTextFormat: InsertTextFormat.Snippet, documentation: ''
|
|
689
|
-
})
|
|
690
|
-
}
|
|
691
|
-
|
|
675
|
+
}));
|
|
676
|
+
}
|
|
677
|
+
getLabelForValue(value) {
|
|
692
678
|
return JSON.stringify(value);
|
|
693
|
-
}
|
|
694
|
-
|
|
679
|
+
}
|
|
680
|
+
getFilterTextForValue(value) {
|
|
695
681
|
return JSON.stringify(value);
|
|
696
|
-
}
|
|
697
|
-
|
|
682
|
+
}
|
|
683
|
+
getFilterTextForSnippetValue(value) {
|
|
698
684
|
return JSON.stringify(value).replace(/\$\{\d+:([^}]+)\}|\$\d+/g, '$1');
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
|
|
685
|
+
}
|
|
686
|
+
getLabelForSnippetValue(value) {
|
|
687
|
+
const label = JSON.stringify(value);
|
|
702
688
|
return label.replace(/\$\{\d+:([^}]+)\}|\$\d+/g, '$1');
|
|
703
|
-
}
|
|
704
|
-
|
|
689
|
+
}
|
|
690
|
+
getInsertTextForPlainText(text) {
|
|
705
691
|
return text.replace(/[\\\$\}]/g, '\\$&'); // escape $, \ and }
|
|
706
|
-
}
|
|
707
|
-
|
|
692
|
+
}
|
|
693
|
+
getInsertTextForValue(value, separatorAfter) {
|
|
708
694
|
var text = JSON.stringify(value, null, '\t');
|
|
709
695
|
if (text === '{}') {
|
|
710
696
|
return '{$1}' + separatorAfter;
|
|
@@ -713,9 +699,9 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
713
699
|
return '[$1]' + separatorAfter;
|
|
714
700
|
}
|
|
715
701
|
return this.getInsertTextForPlainText(text + separatorAfter);
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
|
|
702
|
+
}
|
|
703
|
+
getInsertTextForSnippetValue(value, separatorAfter) {
|
|
704
|
+
const replacer = (value) => {
|
|
719
705
|
if (typeof value === 'string') {
|
|
720
706
|
if (value[0] === '^') {
|
|
721
707
|
return value.substr(1);
|
|
@@ -724,8 +710,8 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
724
710
|
return JSON.stringify(value);
|
|
725
711
|
};
|
|
726
712
|
return stringifyObject(value, '', replacer) + separatorAfter;
|
|
727
|
-
}
|
|
728
|
-
|
|
713
|
+
}
|
|
714
|
+
getInsertTextForGuessedValue(value, separatorAfter) {
|
|
729
715
|
switch (typeof value) {
|
|
730
716
|
case 'object':
|
|
731
717
|
if (value === null) {
|
|
@@ -733,7 +719,7 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
733
719
|
}
|
|
734
720
|
return this.getInsertTextForValue(value, separatorAfter);
|
|
735
721
|
case 'string':
|
|
736
|
-
|
|
722
|
+
let snippetValue = JSON.stringify(value);
|
|
737
723
|
snippetValue = snippetValue.substr(1, snippetValue.length - 2); // remove quotes
|
|
738
724
|
snippetValue = this.getInsertTextForPlainText(snippetValue); // escape \ and }
|
|
739
725
|
return '"${1:' + snippetValue + '}"' + separatorAfter;
|
|
@@ -742,10 +728,10 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
742
728
|
return '${1:' + JSON.stringify(value) + '}' + separatorAfter;
|
|
743
729
|
}
|
|
744
730
|
return this.getInsertTextForValue(value, separatorAfter);
|
|
745
|
-
}
|
|
746
|
-
|
|
731
|
+
}
|
|
732
|
+
getSuggestionKind(type) {
|
|
747
733
|
if (Array.isArray(type)) {
|
|
748
|
-
|
|
734
|
+
const array = type;
|
|
749
735
|
type = array.length > 0 ? array[0] : undefined;
|
|
750
736
|
}
|
|
751
737
|
if (!type) {
|
|
@@ -757,41 +743,41 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
757
743
|
case 'property': return CompletionItemKind.Property;
|
|
758
744
|
default: return CompletionItemKind.Value;
|
|
759
745
|
}
|
|
760
|
-
}
|
|
761
|
-
|
|
746
|
+
}
|
|
747
|
+
getLabelTextForMatchingNode(node, document) {
|
|
762
748
|
switch (node.type) {
|
|
763
749
|
case 'array':
|
|
764
750
|
return '[]';
|
|
765
751
|
case 'object':
|
|
766
752
|
return '{}';
|
|
767
753
|
default:
|
|
768
|
-
|
|
754
|
+
const content = document.getText().substr(node.offset, node.length);
|
|
769
755
|
return content;
|
|
770
756
|
}
|
|
771
|
-
}
|
|
772
|
-
|
|
757
|
+
}
|
|
758
|
+
getInsertTextForMatchingNode(node, document, separatorAfter) {
|
|
773
759
|
switch (node.type) {
|
|
774
760
|
case 'array':
|
|
775
761
|
return this.getInsertTextForValue([], separatorAfter);
|
|
776
762
|
case 'object':
|
|
777
763
|
return this.getInsertTextForValue({}, separatorAfter);
|
|
778
764
|
default:
|
|
779
|
-
|
|
765
|
+
const content = document.getText().substr(node.offset, node.length) + separatorAfter;
|
|
780
766
|
return this.getInsertTextForPlainText(content);
|
|
781
767
|
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
|
|
768
|
+
}
|
|
769
|
+
getInsertTextForProperty(key, propertySchema, addValue, separatorAfter) {
|
|
770
|
+
const propertyText = this.getInsertTextForValue(key, '');
|
|
785
771
|
if (!addValue) {
|
|
786
772
|
return propertyText;
|
|
787
773
|
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
774
|
+
const resultText = propertyText + ': ';
|
|
775
|
+
let value;
|
|
776
|
+
let nValueProposals = 0;
|
|
791
777
|
if (propertySchema) {
|
|
792
778
|
if (Array.isArray(propertySchema.defaultSnippets)) {
|
|
793
779
|
if (propertySchema.defaultSnippets.length === 1) {
|
|
794
|
-
|
|
780
|
+
const body = propertySchema.defaultSnippets[0].body;
|
|
795
781
|
if (isDefined(body)) {
|
|
796
782
|
value = this.getInsertTextForSnippetValue(body, '');
|
|
797
783
|
}
|
|
@@ -804,6 +790,12 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
804
790
|
}
|
|
805
791
|
nValueProposals += propertySchema.enum.length;
|
|
806
792
|
}
|
|
793
|
+
if (isDefined(propertySchema.const)) {
|
|
794
|
+
if (!value) {
|
|
795
|
+
value = this.getInsertTextForGuessedValue(propertySchema.const, '');
|
|
796
|
+
}
|
|
797
|
+
nValueProposals++;
|
|
798
|
+
}
|
|
807
799
|
if (isDefined(propertySchema.default)) {
|
|
808
800
|
if (!value) {
|
|
809
801
|
value = this.getInsertTextForGuessedValue(propertySchema.default, '');
|
|
@@ -855,38 +847,38 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
855
847
|
value = '$1';
|
|
856
848
|
}
|
|
857
849
|
return resultText + value + separatorAfter;
|
|
858
|
-
}
|
|
859
|
-
|
|
850
|
+
}
|
|
851
|
+
getCurrentWord(document, offset) {
|
|
860
852
|
var i = offset - 1;
|
|
861
853
|
var text = document.getText();
|
|
862
854
|
while (i >= 0 && ' \t\n\r\v":{[,]}'.indexOf(text.charAt(i)) === -1) {
|
|
863
855
|
i--;
|
|
864
856
|
}
|
|
865
857
|
return text.substring(i + 1, offset);
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
|
|
858
|
+
}
|
|
859
|
+
evaluateSeparatorAfter(document, offset) {
|
|
860
|
+
const scanner = Json.createScanner(document.getText(), true);
|
|
869
861
|
scanner.setPosition(offset);
|
|
870
|
-
|
|
862
|
+
const token = scanner.scan();
|
|
871
863
|
switch (token) {
|
|
872
|
-
case 5 /* CommaToken */:
|
|
873
|
-
case 2 /* CloseBraceToken */:
|
|
874
|
-
case 4 /* CloseBracketToken */:
|
|
875
|
-
case 17 /* EOF */:
|
|
864
|
+
case 5 /* Json.SyntaxKind.CommaToken */:
|
|
865
|
+
case 2 /* Json.SyntaxKind.CloseBraceToken */:
|
|
866
|
+
case 4 /* Json.SyntaxKind.CloseBracketToken */:
|
|
867
|
+
case 17 /* Json.SyntaxKind.EOF */:
|
|
876
868
|
return '';
|
|
877
869
|
default:
|
|
878
870
|
return ',';
|
|
879
871
|
}
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
for (
|
|
885
|
-
|
|
872
|
+
}
|
|
873
|
+
findItemAtOffset(node, document, offset) {
|
|
874
|
+
const scanner = Json.createScanner(document.getText(), true);
|
|
875
|
+
const children = node.items;
|
|
876
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
877
|
+
const child = children[i];
|
|
886
878
|
if (offset > child.offset + child.length) {
|
|
887
879
|
scanner.setPosition(child.offset + child.length);
|
|
888
|
-
|
|
889
|
-
if (token === 5 /* CommaToken */ && offset >= scanner.getTokenOffset() + scanner.getTokenLength()) {
|
|
880
|
+
const token = scanner.scan();
|
|
881
|
+
if (token === 5 /* Json.SyntaxKind.CommaToken */ && offset >= scanner.getTokenOffset() + scanner.getTokenLength()) {
|
|
890
882
|
return i + 1;
|
|
891
883
|
}
|
|
892
884
|
return i;
|
|
@@ -896,17 +888,17 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
896
888
|
}
|
|
897
889
|
}
|
|
898
890
|
return 0;
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
|
|
891
|
+
}
|
|
892
|
+
isInComment(document, start, offset) {
|
|
893
|
+
const scanner = Json.createScanner(document.getText(), false);
|
|
902
894
|
scanner.setPosition(start);
|
|
903
|
-
|
|
904
|
-
while (token !== 17 /* EOF */ && (scanner.getTokenOffset() + scanner.getTokenLength() < offset)) {
|
|
895
|
+
let token = scanner.scan();
|
|
896
|
+
while (token !== 17 /* Json.SyntaxKind.EOF */ && (scanner.getTokenOffset() + scanner.getTokenLength() < offset)) {
|
|
905
897
|
token = scanner.scan();
|
|
906
898
|
}
|
|
907
|
-
return (token === 12 /* LineCommentTrivia */ || token === 13 /* BlockCommentTrivia */) && scanner.getTokenOffset() <= offset;
|
|
908
|
-
}
|
|
909
|
-
|
|
899
|
+
return (token === 12 /* Json.SyntaxKind.LineCommentTrivia */ || token === 13 /* Json.SyntaxKind.BlockCommentTrivia */) && scanner.getTokenOffset() <= offset;
|
|
900
|
+
}
|
|
901
|
+
fromMarkup(markupString) {
|
|
910
902
|
if (markupString && this.doesSupportMarkdown()) {
|
|
911
903
|
return {
|
|
912
904
|
kind: MarkupKind.Markdown,
|
|
@@ -914,21 +906,19 @@ var JSONCompletion = /** @class */ (function () {
|
|
|
914
906
|
};
|
|
915
907
|
}
|
|
916
908
|
return undefined;
|
|
917
|
-
}
|
|
918
|
-
|
|
909
|
+
}
|
|
910
|
+
doesSupportMarkdown() {
|
|
919
911
|
if (!isDefined(this.supportsMarkdown)) {
|
|
920
|
-
|
|
912
|
+
const completion = this.clientCapabilities.textDocument && this.clientCapabilities.textDocument.completion;
|
|
921
913
|
this.supportsMarkdown = completion && completion.completionItem && Array.isArray(completion.completionItem.documentationFormat) && completion.completionItem.documentationFormat.indexOf(MarkupKind.Markdown) !== -1;
|
|
922
914
|
}
|
|
923
915
|
return this.supportsMarkdown;
|
|
924
|
-
}
|
|
925
|
-
|
|
916
|
+
}
|
|
917
|
+
doesSupportsCommitCharacters() {
|
|
926
918
|
if (!isDefined(this.supportsCommitCharacters)) {
|
|
927
|
-
|
|
919
|
+
const completion = this.clientCapabilities.textDocument && this.clientCapabilities.textDocument.completion;
|
|
928
920
|
this.supportsCommitCharacters = completion && completion.completionItem && !!completion.completionItem.commitCharactersSupport;
|
|
929
921
|
}
|
|
930
922
|
return this.supportsCommitCharacters;
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
}());
|
|
934
|
-
export { JSONCompletion };
|
|
923
|
+
}
|
|
924
|
+
}
|