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