Skip to content

Commit 83bcded

Browse files
committed
Add SnippetString to standalone languages
1 parent 70ae00f commit 83bcded

2 files changed

Lines changed: 111 additions & 39 deletions

File tree

src/vs/editor/browser/standalone/standaloneLanguages.ts

Lines changed: 76 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,25 @@ export enum CompletionItemKind {
395395
Reference,
396396
Folder
397397
}
398+
399+
/**
400+
* A snippet string is a template which allows to insert text
401+
* and to control the editor cursor when insertion happens.
402+
*
403+
* A snippet can define tab stops and placeholders with `$1`, `$2`
404+
* and `${3:foo}`. `$0` defines the final tab stop, it defaults to
405+
* the end of the snippet. Variables are defined with `$name` and
406+
* `${name:default value}`. The full snippet syntax is documented
407+
* [here](http://code.visualstudio.com/docs/customization/userdefinedsnippets#_creating-your-own-snippets).
408+
*/
409+
export interface SnippetString {
410+
411+
/**
412+
* The snippet string.
413+
*/
414+
value: string;
415+
}
416+
398417
/**
399418
* A completion item represents a text snippet that is
400419
* proposed to complete text that is being typed.
@@ -433,18 +452,30 @@ export interface CompletionItem {
433452
*/
434453
filterText?: string;
435454
/**
436-
* A string that should be inserted in a document when selecting
455+
* A string or snippet that should be inserted in a document when selecting
437456
* this completion. When `falsy` the [label](#CompletionItem.label)
438457
* is used.
439458
*/
440-
insertText?: string;
459+
insertText?: string | SnippetString;
460+
/**
461+
* A range of text that should be replaced by this completion item.
462+
*
463+
* Defaults to a range from the start of the [current word](#TextDocument.getWordRangeAtPosition) to the
464+
* current position.
465+
*
466+
* *Note:* The range must be a [single line](#Range.isSingleLine) and it must
467+
* [contain](#Range.contains) the position at which completion has been [requested](#CompletionItemProvider.provideCompletionItems).
468+
*/
469+
range?: Range;
441470
/**
442-
* An [edit](#TextEdit) which is applied to a document when selecting
471+
* @deprecated **Deprecated** in favor of `CompletionItem.insertText` and `CompletionItem.range`.
472+
*
473+
* ~~An [edit](#TextEdit) which is applied to a document when selecting
443474
* this completion. When an edit is provided the value of
444-
* [insertText](#CompletionItem.insertText) is ignored.
475+
* [insertText](#CompletionItem.insertText) is ignored.~~
445476
*
446-
* The [range](#Range) of the edit must be single-line and one the same
447-
* line completions where [requested](#CompletionItemProvider.provideCompletionItems) at.
477+
* ~~The [range](#Range) of the edit must be single-line and on the same
478+
* line completions were [requested](#CompletionItemProvider.provideCompletionItems) at.~~
448479
*/
449480
textEdit?: editorCommon.ISingleEditOperation;
450481
}
@@ -524,18 +555,45 @@ class SuggestAdapter {
524555
this._provider = provider;
525556
}
526557

527-
private static from(item: CompletionItem): ISuggestion2 {
528-
return {
558+
private static from(item: CompletionItem, position: Position, wordStartPos: Position): ISuggestion2 {
559+
let suggestion: ISuggestion2 = {
529560
_actual: item,
530561
label: item.label,
531-
insertText: item.insertText || item.label,
562+
insertText: item.label,
532563
type: convertKind(item.kind),
533564
detail: item.detail,
534565
documentation: item.documentation,
535566
sortText: item.sortText,
536567
filterText: item.filterText,
537568
snippetType: 'internal'
538569
};
570+
let editRange = item.textEdit ? item.textEdit.range : item.range;
571+
if (editRange) {
572+
let isSingleLine = (editRange.startLineNumber === editRange.endLineNumber);
573+
574+
// invalid text edit
575+
if (!isSingleLine || editRange.startLineNumber !== position.lineNumber) {
576+
console.warn('INVALID range, must be single line and on the same line');
577+
return null;
578+
}
579+
580+
// insert the text of the edit and create a dedicated
581+
// suggestion-container with overwrite[Before|After]
582+
suggestion.overwriteBefore = position.column - editRange.startColumn;
583+
suggestion.overwriteAfter = editRange.endColumn - position.column;
584+
} else {
585+
suggestion.overwriteBefore = position.column - wordStartPos.column;
586+
suggestion.overwriteAfter = 0;
587+
}
588+
if (item.textEdit) {
589+
suggestion.insertText = item.textEdit.text;
590+
} else if (typeof item.insertText === 'object' && typeof item.insertText.value === 'string') {
591+
suggestion.insertText = item.insertText.value;
592+
suggestion.snippetType = 'textmate';
593+
} else if (typeof item.insertText === 'string') {
594+
suggestion.insertText = item.insertText;
595+
}
596+
return suggestion;
539597
}
540598

541599
provideCompletionItems(model: editorCommon.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<modes.ISuggestResult> {
@@ -571,30 +629,10 @@ class SuggestAdapter {
571629

572630
for (let i = 0; i < list.items.length; i++) {
573631
const item = list.items[i];
574-
const suggestion = SuggestAdapter.from(item);
575-
576-
if (item.textEdit) {
577-
578-
let editRange = item.textEdit.range;
579-
let isSingleLine = (editRange.startLineNumber === editRange.endLineNumber);
580-
581-
// invalid text edit
582-
if (!isSingleLine || editRange.startLineNumber !== position.lineNumber) {
583-
console.warn('INVALID text edit, must be single line and on the same line');
584-
continue;
585-
}
586-
587-
// insert the text of the edit and create a dedicated
588-
// suggestion-container with overwrite[Before|After]
589-
suggestion.insertText = item.textEdit.text;
590-
suggestion.overwriteBefore = position.column - editRange.startColumn;
591-
suggestion.overwriteAfter = editRange.endColumn - position.column;
592-
} else {
593-
suggestion.overwriteBefore = position.column - wordStartPos.column;
594-
suggestion.overwriteAfter = 0;
632+
const suggestion = SuggestAdapter.from(item, position, wordStartPos);
633+
if (suggestion) {
634+
result.suggestions.push(suggestion);
595635
}
596-
597-
result.suggestions.push(suggestion);
598636
}
599637

600638
return result;
@@ -612,7 +650,12 @@ class SuggestAdapter {
612650
}
613651

614652
return toThenable(this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
615-
return SuggestAdapter.from(resolvedItem);
653+
let wordStartPos = position;
654+
const word = model.getWordUntilPosition(position);
655+
if (word) {
656+
wordStartPos = new Position(wordStartPos.lineNumber, word.startColumn);
657+
}
658+
return SuggestAdapter.from(resolvedItem, position, wordStartPos);
616659
});
617660
}
618661
}

src/vs/monaco.d.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4015,6 +4015,23 @@ declare module monaco.languages {
40154015
Folder = 18,
40164016
}
40174017

4018+
/**
4019+
* A snippet string is a template which allows to insert text
4020+
* and to control the editor cursor when insertion happens.
4021+
*
4022+
* A snippet can define tab stops and placeholders with `$1`, `$2`
4023+
* and `${3:foo}`. `$0` defines the final tab stop, it defaults to
4024+
* the end of the snippet. Variables are defined with `$name` and
4025+
* `${name:default value}`. The full snippet syntax is documented
4026+
* [here](http://code.visualstudio.com/docs/customization/userdefinedsnippets#_creating-your-own-snippets).
4027+
*/
4028+
export interface SnippetString {
4029+
/**
4030+
* The snippet string.
4031+
*/
4032+
value: string;
4033+
}
4034+
40184035
/**
40194036
* A completion item represents a text snippet that is
40204037
* proposed to complete text that is being typed.
@@ -4053,18 +4070,30 @@ declare module monaco.languages {
40534070
*/
40544071
filterText?: string;
40554072
/**
4056-
* A string that should be inserted in a document when selecting
4073+
* A string or snippet that should be inserted in a document when selecting
40574074
* this completion. When `falsy` the [label](#CompletionItem.label)
40584075
* is used.
40594076
*/
4060-
insertText?: string;
4077+
insertText?: string | SnippetString;
4078+
/**
4079+
* A range of text that should be replaced by this completion item.
4080+
*
4081+
* Defaults to a range from the start of the [current word](#TextDocument.getWordRangeAtPosition) to the
4082+
* current position.
4083+
*
4084+
* *Note:* The range must be a [single line](#Range.isSingleLine) and it must
4085+
* [contain](#Range.contains) the position at which completion has been [requested](#CompletionItemProvider.provideCompletionItems).
4086+
*/
4087+
range?: Range;
40614088
/**
4062-
* An [edit](#TextEdit) which is applied to a document when selecting
4089+
* @deprecated **Deprecated** in favor of `CompletionItem.insertText` and `CompletionItem.range`.
4090+
*
4091+
* ~~An [edit](#TextEdit) which is applied to a document when selecting
40634092
* this completion. When an edit is provided the value of
4064-
* [insertText](#CompletionItem.insertText) is ignored.
4093+
* [insertText](#CompletionItem.insertText) is ignored.~~
40654094
*
4066-
* The [range](#Range) of the edit must be single-line and one the same
4067-
* line completions where [requested](#CompletionItemProvider.provideCompletionItems) at.
4095+
* ~~The [range](#Range) of the edit must be single-line and on the same
4096+
* line completions were [requested](#CompletionItemProvider.provideCompletionItems) at.~~
40684097
*/
40694098
textEdit?: editor.ISingleEditOperation;
40704099
}

0 commit comments

Comments
 (0)