@codingame/monaco-vscode-api 1.76.1 → 1.76.3-next.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.
Files changed (59) hide show
  1. package/README.md +2 -1
  2. package/dist/api.js +3 -860
  3. package/dist/{extHost.js → api2.js} +16555 -13467
  4. package/dist/async.js +107 -2
  5. package/dist/audioCue.js +105 -103
  6. package/dist/button.js +1 -1
  7. package/dist/cancellation.js +3 -0
  8. package/dist/configuration.js +7 -344
  9. package/dist/configuration2.js +339 -0
  10. package/dist/configurationRegistry.js +441 -0
  11. package/dist/contextkeys.js +211 -0
  12. package/dist/debug.d.ts +22 -0
  13. package/dist/debug.js +15842 -0
  14. package/dist/dialogs.js +855 -9
  15. package/dist/extensionResourceLoader.js +96 -0
  16. package/dist/extensions.d.ts +491 -0
  17. package/dist/extensions.js +70 -0
  18. package/dist/{tools.js → extensionsRegistry.js} +2 -30
  19. package/dist/files.js +1407 -334
  20. package/dist/iconv.js +43 -0
  21. package/dist/injection.js +1 -1
  22. package/dist/jschardet.js +7 -0
  23. package/dist/keybindings.d.ts +1 -485
  24. package/dist/keybindings.js +666 -679
  25. package/dist/labels.js +14 -0
  26. package/dist/languageConfiguration.d.ts +1 -2
  27. package/dist/languageConfiguration.js +9 -16
  28. package/dist/languageService.js +112 -8
  29. package/dist/languages.d.ts +1 -473
  30. package/dist/languages.js +2 -12
  31. package/dist/layout.js +4 -3
  32. package/dist/layoutService.js +1 -1
  33. package/dist/missing-services.js +4710 -74
  34. package/dist/modelEditor.d.ts +324 -2
  35. package/dist/modelEditor.js +15 -228
  36. package/dist/monaco.js +7 -72
  37. package/dist/notifications.js +75 -232
  38. package/dist/polyfill.js +10715 -2459
  39. package/dist/resources.js +197 -0
  40. package/dist/services.d.ts +924 -3
  41. package/dist/services.js +1 -2
  42. package/dist/services2.js +2436 -18
  43. package/dist/snippets.d.ts +1 -473
  44. package/dist/snippets.js +8 -867
  45. package/dist/snippetsService.js +868 -0
  46. package/dist/textFileEditorModel.js +2985 -0
  47. package/dist/textmate.d.ts +3 -475
  48. package/dist/textmate.js +19 -29
  49. package/dist/theme.d.ts +1 -3
  50. package/dist/theme.js +24 -70
  51. package/dist/tokenClassification.d.ts +1 -475
  52. package/dist/tokenClassification.js +11 -37
  53. package/dist/tokenClassificationRegistry.js +8 -4
  54. package/dist/variableResolver.js +1711 -0
  55. package/dist/workbenchThemeService.js +1 -1
  56. package/dist/workspaceContext.js +1 -3
  57. package/package.json +27 -12
  58. package/dist/contextkey.js +0 -419
  59. package/dist/dialog.web.contribution.js +0 -945
@@ -0,0 +1,868 @@
1
+ import { y as ISnippetsService, _ as __decorate, a as __param, n as IFileService, l as ITextFileService } from './services2.js';
2
+ import * as monacoSuggest from 'monaco-editor/esm/vs/editor/contrib/suggest/browser/suggest.js';
3
+ import { bU as IUserDataProfileService, bL as ILifecycleService } from './missing-services.js';
4
+ import { _ as isStringArray, p as parse, j as getNodeType, R as Range } from './polyfill.js';
5
+ import { extname as extname$1, basename as basename$1 } from 'monaco-editor/esm/vs/base/common/path.js';
6
+ import { Iterable } from 'monaco-editor/esm/vs/base/common/iterator.js';
7
+ import { isEqualOrParent, extname, basename, relativePath, joinPath } from 'monaco-editor/esm/vs/base/common/resources.js';
8
+ import { IdleValue } from 'monaco-editor/esm/vs/base/common/async.js';
9
+ import { isObject } from 'monaco-editor/esm/vs/base/common/types.js';
10
+ import { localize } from 'monaco-editor/esm/vs/nls.js';
11
+ import { SnippetParser, Placeholder, Variable, Text } from 'monaco-editor/esm/vs/editor/contrib/snippet/browser/snippetParser.js';
12
+ import { tail, insertInto } from 'monaco-editor/esm/vs/base/common/arrays.js';
13
+ import { KnownSnippetVariableNames } from 'monaco-editor/esm/vs/editor/contrib/snippet/browser/snippetVariables.js';
14
+ import { E as ExtensionsRegistry } from './extensionsRegistry.js';
15
+ import { l as languagesExtPoint } from './languageService.js';
16
+ import { CommandsRegistry } from 'monaco-editor/esm/vs/platform/commands/common/commands.js';
17
+ import { getWordAtText } from 'monaco-editor/esm/vs/editor/common/core/wordHelper.js';
18
+ import { isPatternInWord } from 'monaco-editor/esm/vs/base/common/filters.js';
19
+ import { compare, firstNonWhitespaceIndex, compareSubstring, isFalsyOrWhitespace } from 'monaco-editor/esm/vs/base/common/strings.js';
20
+ import { ILanguageService } from 'monaco-editor/esm/vs/editor/common/languages/language.js';
21
+ import { ILanguageConfigurationService } from 'monaco-editor/esm/vs/editor/common/languages/languageConfigurationRegistry.js';
22
+ import { MarkdownString } from 'monaco-editor/esm/vs/base/common/htmlContent.js';
23
+ import { StopWatch } from 'monaco-editor/esm/vs/base/common/stopwatch.js';
24
+ import { I as IExtensionResourceLoaderService } from './extensionResourceLoader.js';
25
+ import { DisposableStore, combinedDisposable } from 'monaco-editor/esm/vs/base/common/lifecycle.js';
26
+ import { ResourceMap } from 'monaco-editor/esm/vs/base/common/map.js';
27
+ import { IStorageService } from 'monaco-editor/esm/vs/platform/storage/common/storage.js';
28
+ import { IEnvironmentService } from 'monaco-editor/esm/vs/platform/environment/common/environment.js';
29
+ import { IWorkspaceContextService } from 'monaco-editor/esm/vs/platform/workspace/common/workspace.js';
30
+ import { ILogService } from 'monaco-editor/esm/vs/platform/log/common/log.js';
31
+ import { IInstantiationService } from 'monaco-editor/esm/vs/platform/instantiation/common/instantiation.js';
32
+ function setSnippetSuggestSupport (support) {
33
+ if (monacoSuggest.setSnippetSuggestSupport != null) {
34
+ monacoSuggest.setSnippetSuggestSupport(support);
35
+ } else {
36
+ console.error(
37
+ `setSnippetSuggestSupport does not exist in monaco-editor.
38
+ It's treeshaked out of monaco editor and needs to be reintroduced.
39
+ If you're using webpack, you can add a loader that will polyfill it:
40
+ \`\`\`
41
+ {
42
+ test: /node_modules\\/monaco-editor\\//,
43
+ loader: 'vscode/webpack-loader'
44
+ }
45
+ \`\`\`
46
+ `);
47
+ }
48
+ }
49
+ class SnippetBodyInsights {
50
+ constructor(body) {
51
+ this.isBogous = false;
52
+ this.isTrivial = false;
53
+ this.usesClipboardVariable = false;
54
+ this.usesSelectionVariable = false;
55
+ this.codeSnippet = body;
56
+ const textmateSnippet = ( (new SnippetParser())).parse(body, false);
57
+ const placeholders = ( (new Map()));
58
+ let placeholderMax = 0;
59
+ for (const placeholder of textmateSnippet.placeholders) {
60
+ placeholderMax = Math.max(placeholderMax, placeholder.index);
61
+ }
62
+ if (textmateSnippet.placeholders.length === 0) {
63
+ this.isTrivial = true;
64
+ }
65
+ else if (placeholderMax === 0) {
66
+ const last = tail(textmateSnippet.children);
67
+ this.isTrivial = last instanceof Placeholder && last.isFinalTabstop;
68
+ }
69
+ const stack = [...textmateSnippet.children];
70
+ while (stack.length > 0) {
71
+ const marker = stack.shift();
72
+ if (marker instanceof Variable) {
73
+ if (marker.children.length === 0 && !KnownSnippetVariableNames[marker.name]) {
74
+ const index = placeholders.has(marker.name) ? placeholders.get(marker.name) : ++placeholderMax;
75
+ placeholders.set(marker.name, index);
76
+ const synthetic = ( (new Placeholder(index))).appendChild(( (new Text(marker.name))));
77
+ textmateSnippet.replace(marker, [synthetic]);
78
+ this.isBogous = true;
79
+ }
80
+ switch (marker.name) {
81
+ case 'CLIPBOARD':
82
+ this.usesClipboardVariable = true;
83
+ break;
84
+ case 'SELECTION':
85
+ case 'TM_SELECTED_TEXT':
86
+ this.usesSelectionVariable = true;
87
+ break;
88
+ }
89
+ }
90
+ else {
91
+ stack.push(...marker.children);
92
+ }
93
+ }
94
+ if (this.isBogous) {
95
+ this.codeSnippet = textmateSnippet.toTextmateString();
96
+ }
97
+ }
98
+ }
99
+ class Snippet {
100
+ constructor(isFileTemplate, scopes, name, prefix, description, body, source, snippetSource, snippetIdentifier, extensionId) {
101
+ this.isFileTemplate = isFileTemplate;
102
+ this.scopes = scopes;
103
+ this.name = name;
104
+ this.prefix = prefix;
105
+ this.description = description;
106
+ this.body = body;
107
+ this.source = source;
108
+ this.snippetSource = snippetSource;
109
+ this.snippetIdentifier = snippetIdentifier;
110
+ this.extensionId = extensionId;
111
+ this.prefixLow = prefix.toLowerCase();
112
+ this._bodyInsights = ( (new IdleValue(() => ( (new SnippetBodyInsights(this.body))))));
113
+ }
114
+ get codeSnippet() {
115
+ return this._bodyInsights.value.codeSnippet;
116
+ }
117
+ get isBogous() {
118
+ return this._bodyInsights.value.isBogous;
119
+ }
120
+ get isTrivial() {
121
+ return this._bodyInsights.value.isTrivial;
122
+ }
123
+ get needsClipboard() {
124
+ return this._bodyInsights.value.usesClipboardVariable;
125
+ }
126
+ get usesSelection() {
127
+ return this._bodyInsights.value.usesSelectionVariable;
128
+ }
129
+ }
130
+ function isJsonSerializedSnippet(thing) {
131
+ return isObject(thing) && Boolean(thing.body);
132
+ }
133
+ class SnippetFile {
134
+ constructor(source, location, defaultScopes, _extension, _fileService, _extensionResourceLoaderService) {
135
+ this.source = source;
136
+ this.location = location;
137
+ this.defaultScopes = defaultScopes;
138
+ this._extension = _extension;
139
+ this._fileService = _fileService;
140
+ this._extensionResourceLoaderService = _extensionResourceLoaderService;
141
+ this.data = [];
142
+ this.isGlobalSnippets = extname$1(location.path) === '.code-snippets';
143
+ this.isUserSnippets = !this._extension;
144
+ }
145
+ select(selector, bucket) {
146
+ if (this.isGlobalSnippets || !this.isUserSnippets) {
147
+ this._scopeSelect(selector, bucket);
148
+ }
149
+ else {
150
+ this._filepathSelect(selector, bucket);
151
+ }
152
+ }
153
+ _filepathSelect(selector, bucket) {
154
+ if (selector + '.json' === basename$1(this.location.path)) {
155
+ bucket.push(...this.data);
156
+ }
157
+ }
158
+ _scopeSelect(selector, bucket) {
159
+ for (const snippet of this.data) {
160
+ const len = snippet.scopes.length;
161
+ if (len === 0) {
162
+ bucket.push(snippet);
163
+ }
164
+ else {
165
+ for (let i = 0; i < len; i++) {
166
+ if (snippet.scopes[i] === selector) {
167
+ bucket.push(snippet);
168
+ break;
169
+ }
170
+ }
171
+ }
172
+ }
173
+ const idx = selector.lastIndexOf('.');
174
+ if (idx >= 0) {
175
+ this._scopeSelect(selector.substring(0, idx), bucket);
176
+ }
177
+ }
178
+ async _load() {
179
+ if (this._extension) {
180
+ return this._extensionResourceLoaderService.readExtensionResource(this.location);
181
+ }
182
+ else {
183
+ const content = await this._fileService.readFile(this.location);
184
+ return (
185
+ (content.value.toString())
186
+ );
187
+ }
188
+ }
189
+ load() {
190
+ if (!this._loadPromise) {
191
+ this._loadPromise = Promise.resolve(this._load()).then(content => {
192
+ const data = parse(content);
193
+ if (getNodeType(data) === 'object') {
194
+ for (const [name, scopeOrTemplate] of Object.entries(data)) {
195
+ if (isJsonSerializedSnippet(scopeOrTemplate)) {
196
+ this._parseSnippet(name, scopeOrTemplate, this.data);
197
+ }
198
+ else {
199
+ for (const [name, template] of Object.entries(scopeOrTemplate)) {
200
+ this._parseSnippet(name, template, this.data);
201
+ }
202
+ }
203
+ }
204
+ }
205
+ return this;
206
+ });
207
+ }
208
+ return this._loadPromise;
209
+ }
210
+ reset() {
211
+ this._loadPromise = undefined;
212
+ this.data.length = 0;
213
+ }
214
+ _parseSnippet(name, snippet, bucket) {
215
+ let { isFileTemplate, prefix, body, description } = snippet;
216
+ if (!prefix) {
217
+ prefix = '';
218
+ }
219
+ if (Array.isArray(body)) {
220
+ body = body.join('\n');
221
+ }
222
+ if (typeof body !== 'string') {
223
+ return;
224
+ }
225
+ if (Array.isArray(description)) {
226
+ description = description.join('\n');
227
+ }
228
+ let scopes;
229
+ if (this.defaultScopes) {
230
+ scopes = this.defaultScopes;
231
+ }
232
+ else if (typeof snippet.scope === 'string') {
233
+ scopes = ( (snippet.scope.split(',').map(s => s.trim()))).filter(Boolean);
234
+ }
235
+ else {
236
+ scopes = [];
237
+ }
238
+ let source;
239
+ if (this._extension) {
240
+ source = this._extension.displayName || this._extension.name;
241
+ }
242
+ else if (this.source === 2 ) {
243
+ source = ( (localize('source.workspaceSnippetGlobal', "Workspace Snippet")));
244
+ }
245
+ else {
246
+ if (this.isGlobalSnippets) {
247
+ source = ( (localize('source.userSnippetGlobal', "Global User Snippet")));
248
+ }
249
+ else {
250
+ source = ( (localize('source.userSnippet', "User Snippet")));
251
+ }
252
+ }
253
+ for (const _prefix of Iterable.wrap(prefix)) {
254
+ bucket.push(( (new Snippet(
255
+ Boolean(isFileTemplate),
256
+ scopes,
257
+ name,
258
+ _prefix,
259
+ description,
260
+ body,
261
+ source,
262
+ this.source,
263
+ this._extension ? `${relativePath(this._extension.extensionLocation, this.location)}/${name}` : `${basename$1(this.location.path)}/${name}`,
264
+ this._extension?.identifier
265
+ ))));
266
+ }
267
+ }
268
+ }
269
+ const markSnippetAsUsed = '_snippet.markAsUsed';
270
+ CommandsRegistry.registerCommand(markSnippetAsUsed, (accessor, ...args) => {
271
+ const snippetsService = accessor.get(ISnippetsService);
272
+ const [first] = args;
273
+ if (first instanceof Snippet) {
274
+ snippetsService.updateUsageTimestamp(first);
275
+ }
276
+ });
277
+ class SnippetCompletion {
278
+ constructor(snippet, range) {
279
+ this.snippet = snippet;
280
+ this.label = { label: snippet.prefix, description: snippet.name };
281
+ this.detail = ( (localize(
282
+ 'detail.snippet',
283
+ "{0} ({1})",
284
+ snippet.description || snippet.name,
285
+ snippet.source
286
+ )));
287
+ this.insertText = snippet.codeSnippet;
288
+ this.extensionId = snippet.extensionId;
289
+ this.range = range;
290
+ this.sortText = `${snippet.snippetSource === 3 ? 'z' : 'a'}-${snippet.prefix}`;
291
+ this.kind = 27 ;
292
+ this.insertTextRules = 4 ;
293
+ this.command = { id: markSnippetAsUsed, title: '', arguments: [snippet] };
294
+ }
295
+ resolve() {
296
+ this.documentation = ( (new MarkdownString())).appendCodeblock('', SnippetParser.asInsertText(this.snippet.codeSnippet));
297
+ return this;
298
+ }
299
+ static compareByLabel(a, b) {
300
+ return compare(a.label.label, b.label.label);
301
+ }
302
+ }
303
+ let SnippetCompletionProvider = class SnippetCompletionProvider {
304
+ constructor(_languageService, _snippets, _languageConfigurationService) {
305
+ this._languageService = _languageService;
306
+ this._snippets = _snippets;
307
+ this._languageConfigurationService = _languageConfigurationService;
308
+ this._debugDisplayName = 'snippetCompletions';
309
+ }
310
+ async provideCompletionItems(model, position, context) {
311
+ const sw = ( (new StopWatch(true)));
312
+ const languageId = this._getLanguageIdAtPosition(model, position);
313
+ const languageConfig = this._languageConfigurationService.getLanguageConfiguration(languageId);
314
+ const snippets = ( (new Set(await this._snippets.getSnippets(languageId))));
315
+ const lineContentLow = model.getLineContent(position.lineNumber).toLowerCase();
316
+ const wordUntil = model.getWordUntilPosition(position).word.toLowerCase();
317
+ const suggestions = [];
318
+ const columnOffset = position.column - 1;
319
+ const triggerCharacterLow = context.triggerCharacter?.toLowerCase() ?? '';
320
+ snippet: for (const snippet of snippets) {
321
+ if (context.triggerKind === 1 && !snippet.prefixLow.startsWith(triggerCharacterLow)) {
322
+ continue snippet;
323
+ }
324
+ const word = getWordAtText(1, languageConfig.getWordDefinition(), snippet.prefixLow, 0);
325
+ if (wordUntil && word && !isPatternInWord(wordUntil, 0, wordUntil.length, snippet.prefixLow, 0, snippet.prefixLow.length)) {
326
+ continue snippet;
327
+ }
328
+ const minPos = firstNonWhitespaceIndex(snippet.prefixLow) === 0
329
+ ? Math.max(0, model.getLineFirstNonWhitespaceColumn(position.lineNumber) - 1)
330
+ : 0;
331
+ column: for (let pos = Math.max(minPos, columnOffset - snippet.prefixLow.length); pos < lineContentLow.length; pos++) {
332
+ if (!isPatternInWord(lineContentLow, pos, columnOffset, snippet.prefixLow, 0, snippet.prefixLow.length)) {
333
+ continue column;
334
+ }
335
+ const prefixRestLen = snippet.prefixLow.length - (columnOffset - pos);
336
+ const endsWithPrefixRest = compareSubstring(lineContentLow, snippet.prefixLow, columnOffset, columnOffset + prefixRestLen, columnOffset - pos);
337
+ const startPosition = position.with(undefined, pos + 1);
338
+ if (wordUntil && position.equals(startPosition)) {
339
+ continue snippet;
340
+ }
341
+ let endColumn = endsWithPrefixRest === 0 ? position.column + prefixRestLen : position.column;
342
+ if (columnOffset < lineContentLow.length) {
343
+ const autoClosingPairs = languageConfig.getAutoClosingPairs();
344
+ const standardAutoClosingPairConditionals = autoClosingPairs.autoClosingPairsCloseSingleChar.get(lineContentLow[columnOffset]);
345
+ if (standardAutoClosingPairConditionals?.some(p =>
346
+ p.open === lineContentLow[startPosition.column - 1] &&
347
+ snippet.prefix.startsWith(p.open) &&
348
+ snippet.prefix[snippet.prefix.length - 1] === p.close)) {
349
+ endColumn++;
350
+ }
351
+ }
352
+ const replace = Range.fromPositions(startPosition, { lineNumber: position.lineNumber, column: endColumn });
353
+ const insert = replace.setEndPosition(position.lineNumber, position.column);
354
+ suggestions.push(( (new SnippetCompletion(snippet, { replace, insert }))));
355
+ snippets.delete(snippet);
356
+ break;
357
+ }
358
+ }
359
+ if (!triggerCharacterLow) {
360
+ const endsInWhitespace = /\s/.test(lineContentLow[position.column - 2]);
361
+ if (endsInWhitespace || !lineContentLow ) {
362
+ for (const snippet of snippets) {
363
+ const insert = Range.fromPositions(position);
364
+ const replace = lineContentLow.indexOf(snippet.prefixLow, columnOffset) === columnOffset ? insert.setEndPosition(position.lineNumber, position.column + snippet.prefixLow.length) : insert;
365
+ suggestions.push(( (new SnippetCompletion(snippet, { replace, insert }))));
366
+ }
367
+ }
368
+ }
369
+ suggestions.sort(SnippetCompletion.compareByLabel);
370
+ for (let i = 0; i < suggestions.length; i++) {
371
+ const item = suggestions[i];
372
+ let to = i + 1;
373
+ for (; to < suggestions.length && item.label === suggestions[to].label; to++) {
374
+ suggestions[to].label.label = ( (localize(
375
+ 'snippetSuggest.longLabel',
376
+ "{0}, {1}",
377
+ suggestions[to].label.label,
378
+ suggestions[to].snippet.name
379
+ )));
380
+ }
381
+ if (to > i + 1) {
382
+ suggestions[i].label.label = ( (localize(
383
+ 'snippetSuggest.longLabel',
384
+ "{0}, {1}",
385
+ suggestions[i].label.label,
386
+ suggestions[i].snippet.name
387
+ )));
388
+ i = to;
389
+ }
390
+ }
391
+ return {
392
+ suggestions,
393
+ duration: sw.elapsed()
394
+ };
395
+ }
396
+ resolveCompletionItem(item) {
397
+ return (item instanceof SnippetCompletion) ? item.resolve() : item;
398
+ }
399
+ _getLanguageIdAtPosition(model, position) {
400
+ model.tokenization.tokenizeIfCheap(position.lineNumber);
401
+ let languageId = model.getLanguageIdAtPosition(position.lineNumber, position.column);
402
+ if (!this._languageService.getLanguageName(languageId)) {
403
+ languageId = model.getLanguageId();
404
+ }
405
+ return languageId;
406
+ }
407
+ };
408
+ SnippetCompletionProvider = ( (__decorate([
409
+ ( (__param(0, ILanguageService))),
410
+ ( (__param(1, ISnippetsService))),
411
+ ( (__param(2, ILanguageConfigurationService)))
412
+ ], SnippetCompletionProvider)));
413
+ var snippetExt;
414
+ ( ((function(snippetExt) {
415
+ function toValidSnippet(extension, snippet, languageService) {
416
+ if (isFalsyOrWhitespace(snippet.path)) {
417
+ extension.collector.error(( (localize(
418
+ 'invalid.path.0',
419
+ "Expected string in `contributes.{0}.path`. Provided value: {1}",
420
+ extension.description.name,
421
+ String(snippet.path)
422
+ ))));
423
+ return null;
424
+ }
425
+ if (isFalsyOrWhitespace(snippet.language) && !snippet.path.endsWith('.code-snippets')) {
426
+ extension.collector.error(( (localize(
427
+ 'invalid.language.0',
428
+ "When omitting the language, the value of `contributes.{0}.path` must be a `.code-snippets`-file. Provided value: {1}",
429
+ extension.description.name,
430
+ String(snippet.path)
431
+ ))));
432
+ return null;
433
+ }
434
+ if (!isFalsyOrWhitespace(snippet.language) && !languageService.isRegisteredLanguageId(snippet.language)) {
435
+ extension.collector.error(( (localize(
436
+ 'invalid.language',
437
+ "Unknown language in `contributes.{0}.language`. Provided value: {1}",
438
+ extension.description.name,
439
+ String(snippet.language)
440
+ ))));
441
+ return null;
442
+ }
443
+ const extensionLocation = extension.description.extensionLocation;
444
+ const snippetLocation = joinPath(extensionLocation, snippet.path);
445
+ if (!isEqualOrParent(snippetLocation, extensionLocation)) {
446
+ extension.collector.error(( (localize(
447
+ 'invalid.path.1',
448
+ "Expected `contributes.{0}.path` ({1}) to be included inside extension's folder ({2}). This might make the extension non-portable.",
449
+ extension.description.name,
450
+ snippetLocation.path,
451
+ extensionLocation.path
452
+ ))));
453
+ return null;
454
+ }
455
+ return {
456
+ language: snippet.language,
457
+ location: snippetLocation
458
+ };
459
+ }
460
+ snippetExt.toValidSnippet = toValidSnippet;
461
+ snippetExt.snippetsContribution = {
462
+ description: ( (localize('vscode.extension.contributes.snippets', 'Contributes snippets.'))),
463
+ type: 'array',
464
+ defaultSnippets: [{ body: [{ language: '', path: '' }] }],
465
+ items: {
466
+ type: 'object',
467
+ defaultSnippets: [{ body: { language: '${1:id}', path: './snippets/${2:id}.json.' } }],
468
+ properties: {
469
+ language: {
470
+ description: ( (localize(
471
+ 'vscode.extension.contributes.snippets-language',
472
+ 'Language identifier for which this snippet is contributed to.'
473
+ ))),
474
+ type: 'string'
475
+ },
476
+ path: {
477
+ description: ( (localize(
478
+ 'vscode.extension.contributes.snippets-path',
479
+ 'Path of the snippets file. The path is relative to the extension folder and typically starts with \'./snippets/\'.'
480
+ ))),
481
+ type: 'string'
482
+ }
483
+ }
484
+ }
485
+ };
486
+ snippetExt.point = ( (ExtensionsRegistry.registerExtensionPoint({
487
+ extensionPoint: 'snippets',
488
+ deps: [languagesExtPoint],
489
+ jsonSchema: snippetExt.snippetsContribution
490
+ })));
491
+ })(snippetExt || (snippetExt = {}))));
492
+ function watch(service, resource, callback) {
493
+ return combinedDisposable(service.watch(resource), service.onDidFilesChange(e => {
494
+ if (e.affects(resource)) {
495
+ callback();
496
+ }
497
+ }));
498
+ }
499
+ let SnippetEnablement = class SnippetEnablement {
500
+ constructor(_storageService) {
501
+ this._storageService = _storageService;
502
+ const raw = _storageService.get(SnippetEnablement._key, 0 , '');
503
+ let data;
504
+ try {
505
+ data = JSON.parse(raw);
506
+ }
507
+ catch { }
508
+ this._ignored = isStringArray(data) ? ( (new Set(data))) : ( (new Set()));
509
+ }
510
+ isIgnored(id) {
511
+ return this._ignored.has(id);
512
+ }
513
+ updateIgnored(id, value) {
514
+ let changed = false;
515
+ if (this._ignored.has(id) && !value) {
516
+ this._ignored.delete(id);
517
+ changed = true;
518
+ }
519
+ else if (!this._ignored.has(id) && value) {
520
+ this._ignored.add(id);
521
+ changed = true;
522
+ }
523
+ if (changed) {
524
+ this._storageService.store(SnippetEnablement._key, JSON.stringify(Array.from(this._ignored)), 0 , 0 );
525
+ }
526
+ }
527
+ };
528
+ SnippetEnablement._key = 'snippets.ignoredSnippets';
529
+ SnippetEnablement = ( (__decorate([
530
+ ( (__param(0, IStorageService)))
531
+ ], SnippetEnablement)));
532
+ let SnippetUsageTimestamps = class SnippetUsageTimestamps {
533
+ constructor(_storageService) {
534
+ this._storageService = _storageService;
535
+ const raw = _storageService.get(SnippetUsageTimestamps._key, 0 , '');
536
+ let data;
537
+ try {
538
+ data = JSON.parse(raw);
539
+ }
540
+ catch {
541
+ data = [];
542
+ }
543
+ this._usages = Array.isArray(data) ? ( (new Map(data))) : ( (new Map()));
544
+ }
545
+ getUsageTimestamp(id) {
546
+ return this._usages.get(id);
547
+ }
548
+ updateUsageTimestamp(id) {
549
+ this._usages.delete(id);
550
+ this._usages.set(id, Date.now());
551
+ const all = [...this._usages].slice(-100);
552
+ this._storageService.store(SnippetUsageTimestamps._key, JSON.stringify(all), 0 , 0 );
553
+ }
554
+ };
555
+ SnippetUsageTimestamps._key = 'snippets.usageTimestamps';
556
+ SnippetUsageTimestamps = ( (__decorate([
557
+ ( (__param(0, IStorageService)))
558
+ ], SnippetUsageTimestamps)));
559
+ let SnippetsService = class SnippetsService {
560
+ constructor(_environmentService, _userDataProfileService, _contextService, _languageService, _logService, _fileService, _textfileService, _extensionResourceLoaderService, lifecycleService, instantiationService, languageConfigurationService) {
561
+ this._environmentService = _environmentService;
562
+ this._userDataProfileService = _userDataProfileService;
563
+ this._contextService = _contextService;
564
+ this._languageService = _languageService;
565
+ this._logService = _logService;
566
+ this._fileService = _fileService;
567
+ this._textfileService = _textfileService;
568
+ this._extensionResourceLoaderService = _extensionResourceLoaderService;
569
+ this._disposables = ( (new DisposableStore()));
570
+ this._pendingWork = [];
571
+ this._files = ( (new ResourceMap()));
572
+ this._pendingWork.push(Promise.resolve(lifecycleService.when(3 ).then(() => {
573
+ this._initExtensionSnippets();
574
+ this._initUserSnippets();
575
+ this._initWorkspaceSnippets();
576
+ })));
577
+ setSnippetSuggestSupport(( (new SnippetCompletionProvider(this._languageService, this, languageConfigurationService))));
578
+ this._enablement = instantiationService.createInstance(SnippetEnablement);
579
+ this._usageTimestamps = instantiationService.createInstance(SnippetUsageTimestamps);
580
+ }
581
+ dispose() {
582
+ this._disposables.dispose();
583
+ }
584
+ isEnabled(snippet) {
585
+ return !this._enablement.isIgnored(snippet.snippetIdentifier);
586
+ }
587
+ updateEnablement(snippet, enabled) {
588
+ this._enablement.updateIgnored(snippet.snippetIdentifier, !enabled);
589
+ }
590
+ updateUsageTimestamp(snippet) {
591
+ this._usageTimestamps.updateUsageTimestamp(snippet.snippetIdentifier);
592
+ }
593
+ _joinSnippets() {
594
+ const promises = this._pendingWork.slice(0);
595
+ this._pendingWork.length = 0;
596
+ return Promise.all(promises);
597
+ }
598
+ async getSnippetFiles() {
599
+ await this._joinSnippets();
600
+ return (
601
+ (this._files.values())
602
+ );
603
+ }
604
+ async getSnippets(languageId, opts) {
605
+ await this._joinSnippets();
606
+ const result = [];
607
+ const promises = [];
608
+ if (languageId) {
609
+ if (this._languageService.isRegisteredLanguageId(languageId)) {
610
+ for (const file of ( (this._files.values()))) {
611
+ promises.push(file.load()
612
+ .then(file => file.select(languageId, result))
613
+ .catch(err => this._logService.error(err, ( (file.location.toString())))));
614
+ }
615
+ }
616
+ }
617
+ else {
618
+ for (const file of ( (this._files.values()))) {
619
+ promises.push(file.load()
620
+ .then(file => insertInto(result, result.length, file.data))
621
+ .catch(err => this._logService.error(err, ( (file.location.toString())))));
622
+ }
623
+ }
624
+ await Promise.all(promises);
625
+ return this._filterAndSortSnippets(result, opts);
626
+ }
627
+ getSnippetsSync(languageId, opts) {
628
+ const result = [];
629
+ if (this._languageService.isRegisteredLanguageId(languageId)) {
630
+ for (const file of ( (this._files.values()))) {
631
+ file.load().catch(_err => { });
632
+ file.select(languageId, result);
633
+ }
634
+ }
635
+ return this._filterAndSortSnippets(result, opts);
636
+ }
637
+ _filterAndSortSnippets(snippets, opts) {
638
+ const result = [];
639
+ for (const snippet of snippets) {
640
+ if (!snippet.prefix && !opts?.includeNoPrefixSnippets) {
641
+ continue;
642
+ }
643
+ if (!this.isEnabled(snippet) && !opts?.includeDisabledSnippets) {
644
+ continue;
645
+ }
646
+ if (typeof opts?.fileTemplateSnippets === 'boolean' && opts.fileTemplateSnippets !== snippet.isFileTemplate) {
647
+ continue;
648
+ }
649
+ result.push(snippet);
650
+ }
651
+ return result.sort((a, b) => {
652
+ let result = 0;
653
+ if (!opts?.noRecencySort) {
654
+ const val1 = this._usageTimestamps.getUsageTimestamp(a.snippetIdentifier) ?? -1;
655
+ const val2 = this._usageTimestamps.getUsageTimestamp(b.snippetIdentifier) ?? -1;
656
+ result = val2 - val1;
657
+ }
658
+ if (result === 0) {
659
+ result = this._compareSnippet(a, b);
660
+ }
661
+ return result;
662
+ });
663
+ }
664
+ _compareSnippet(a, b) {
665
+ if (a.snippetSource < b.snippetSource) {
666
+ return -1;
667
+ }
668
+ else if (a.snippetSource > b.snippetSource) {
669
+ return 1;
670
+ }
671
+ else if (a.source < b.source) {
672
+ return -1;
673
+ }
674
+ else if (a.source > b.source) {
675
+ return 1;
676
+ }
677
+ else if (a.name > b.name) {
678
+ return 1;
679
+ }
680
+ else if (a.name < b.name) {
681
+ return -1;
682
+ }
683
+ else {
684
+ return 0;
685
+ }
686
+ }
687
+ _initExtensionSnippets() {
688
+ snippetExt.point.setHandler(extensions => {
689
+ for (const [key, value] of this._files) {
690
+ if (value.source === 3 ) {
691
+ this._files.delete(key);
692
+ }
693
+ }
694
+ for (const extension of extensions) {
695
+ for (const contribution of extension.value) {
696
+ const validContribution = snippetExt.toValidSnippet(extension, contribution, this._languageService);
697
+ if (!validContribution) {
698
+ continue;
699
+ }
700
+ const file = this._files.get(validContribution.location);
701
+ if (file) {
702
+ if (file.defaultScopes) {
703
+ file.defaultScopes.push(validContribution.language);
704
+ }
705
+ else {
706
+ file.defaultScopes = [];
707
+ }
708
+ }
709
+ else {
710
+ const file = ( (new SnippetFile(
711
+ 3 ,
712
+ validContribution.location,
713
+ validContribution.language ? [validContribution.language] : undefined,
714
+ extension.description,
715
+ this._fileService,
716
+ this._extensionResourceLoaderService
717
+ )));
718
+ this._files.set(file.location, file);
719
+ if (this._environmentService.isExtensionDevelopment) {
720
+ file.load().then(file => {
721
+ if (file.data.some(snippet => snippet.isBogous)) {
722
+ extension.collector.warn(( (localize(
723
+ 'badVariableUse',
724
+ "One or more snippets from the extension '{0}' very likely confuse snippet-variables and snippet-placeholders (see https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax for more details)",
725
+ extension.description.name
726
+ ))));
727
+ }
728
+ }, err => {
729
+ extension.collector.warn(( (localize(
730
+ 'badFile',
731
+ "The snippet file \"{0}\" could not be read.",
732
+ (file.location.toString())
733
+ ))));
734
+ });
735
+ }
736
+ }
737
+ }
738
+ }
739
+ });
740
+ }
741
+ _initWorkspaceSnippets() {
742
+ const disposables = ( (new DisposableStore()));
743
+ const updateWorkspaceSnippets = () => {
744
+ disposables.clear();
745
+ this._pendingWork.push(this._initWorkspaceFolderSnippets(this._contextService.getWorkspace(), disposables));
746
+ };
747
+ this._disposables.add(disposables);
748
+ this._disposables.add(this._contextService.onDidChangeWorkspaceFolders(updateWorkspaceSnippets));
749
+ this._disposables.add(this._contextService.onDidChangeWorkbenchState(updateWorkspaceSnippets));
750
+ updateWorkspaceSnippets();
751
+ }
752
+ async _initWorkspaceFolderSnippets(workspace, bucket) {
753
+ const promises = ( (workspace.folders.map(async (folder) => {
754
+ const snippetFolder = folder.toResource('.vscode');
755
+ const value = await this._fileService.exists(snippetFolder);
756
+ if (value) {
757
+ this._initFolderSnippets(2 , snippetFolder, bucket);
758
+ }
759
+ else {
760
+ bucket.add(this._fileService.onDidFilesChange(e => {
761
+ if (e.contains(snippetFolder, 1 )) {
762
+ this._initFolderSnippets(2 , snippetFolder, bucket);
763
+ }
764
+ }));
765
+ }
766
+ })));
767
+ await Promise.all(promises);
768
+ }
769
+ async _initUserSnippets() {
770
+ const disposables = ( (new DisposableStore()));
771
+ const updateUserSnippets = async () => {
772
+ disposables.clear();
773
+ const userSnippetsFolder = this._userDataProfileService.currentProfile.snippetsHome;
774
+ await this._fileService.createFolder(userSnippetsFolder);
775
+ await this._initFolderSnippets(1 , userSnippetsFolder, disposables);
776
+ };
777
+ this._disposables.add(disposables);
778
+ this._disposables.add(this._userDataProfileService.onDidChangeCurrentProfile(e => e.join((async () => {
779
+ if (e.preserveData) {
780
+ await this._fileService.copy(e.previous.snippetsHome, e.profile.snippetsHome);
781
+ }
782
+ this._pendingWork.push(updateUserSnippets());
783
+ })())));
784
+ await updateUserSnippets();
785
+ }
786
+ _initFolderSnippets(source, folder, bucket) {
787
+ const disposables = ( (new DisposableStore()));
788
+ const addFolderSnippets = async () => {
789
+ disposables.clear();
790
+ if (!(await this._fileService.exists(folder))) {
791
+ return;
792
+ }
793
+ try {
794
+ const stat = await this._fileService.resolve(folder);
795
+ for (const entry of stat.children || []) {
796
+ disposables.add(this._addSnippetFile(entry.resource, source));
797
+ }
798
+ }
799
+ catch (err) {
800
+ this._logService.error(`Failed snippets from folder '${( ( folder.toString()))}'`, err);
801
+ }
802
+ };
803
+ bucket.add(this._textfileService.files.onDidSave(e => {
804
+ if (isEqualOrParent(e.model.resource, folder)) {
805
+ addFolderSnippets();
806
+ }
807
+ }));
808
+ bucket.add(watch(this._fileService, folder, addFolderSnippets));
809
+ bucket.add(disposables);
810
+ return addFolderSnippets();
811
+ }
812
+ _addSnippetFile(uri, source) {
813
+ const ext = extname(uri);
814
+ if (source === 1 && ext === '.json') {
815
+ const langName = basename(uri).replace(/\.json/, '');
816
+ this._files.set(uri, ( (new SnippetFile(
817
+ source,
818
+ uri,
819
+ [langName],
820
+ undefined,
821
+ this._fileService,
822
+ this._extensionResourceLoaderService
823
+ ))));
824
+ }
825
+ else if (ext === '.code-snippets') {
826
+ this._files.set(uri, ( (new SnippetFile(
827
+ source,
828
+ uri,
829
+ undefined,
830
+ undefined,
831
+ this._fileService,
832
+ this._extensionResourceLoaderService
833
+ ))));
834
+ }
835
+ return {
836
+ dispose: () => this._files.delete(uri)
837
+ };
838
+ }
839
+ };
840
+ SnippetsService = ( (__decorate([
841
+ ( (__param(0, IEnvironmentService))),
842
+ ( (__param(1, IUserDataProfileService))),
843
+ ( (__param(2, IWorkspaceContextService))),
844
+ ( (__param(3, ILanguageService))),
845
+ ( (__param(4, ILogService))),
846
+ ( (__param(5, IFileService))),
847
+ ( (__param(6, ITextFileService))),
848
+ ( (__param(7, IExtensionResourceLoaderService))),
849
+ ( (__param(8, ILifecycleService))),
850
+ ( (__param(9, IInstantiationService))),
851
+ ( (__param(10, ILanguageConfigurationService)))
852
+ ], SnippetsService)));
853
+ function getNonWhitespacePrefix(model, position) {
854
+ const MAX_PREFIX_LENGTH = 100;
855
+ const line = model.getLineContent(position.lineNumber).substr(0, position.column - 1);
856
+ const minChIndex = Math.max(0, line.length - MAX_PREFIX_LENGTH);
857
+ for (let chIndex = line.length - 1; chIndex >= minChIndex; chIndex--) {
858
+ const ch = line.charAt(chIndex);
859
+ if (/\s/.test(ch)) {
860
+ return line.substr(chIndex + 1);
861
+ }
862
+ }
863
+ if (minChIndex === 0) {
864
+ return line;
865
+ }
866
+ return '';
867
+ }
868
+ export { SnippetsService as S, SnippetCompletion as a, getNonWhitespacePrefix as g };