vscode-json-languageservice 4.1.8

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