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