Add SnippetString to standalone languages

This commit is contained in:
Martin Aeschlimann
2017-01-19 10:07:22 +01:00
parent 70ae00f624
commit 83bcded107
2 changed files with 113 additions and 41 deletions
@@ -395,6 +395,25 @@ export enum CompletionItemKind {
Reference,
Folder
}
/**
* A snippet string is a template which allows to insert text
* and to control the editor cursor when insertion happens.
*
* A snippet can define tab stops and placeholders with `$1`, `$2`
* and `${3:foo}`. `$0` defines the final tab stop, it defaults to
* the end of the snippet. Variables are defined with `$name` and
* `${name:default value}`. The full snippet syntax is documented
* [here](http://code.visualstudio.com/docs/customization/userdefinedsnippets#_creating-your-own-snippets).
*/
export interface SnippetString {
/**
* The snippet string.
*/
value: string;
}
/**
* A completion item represents a text snippet that is
* proposed to complete text that is being typed.
@@ -433,18 +452,30 @@ export interface CompletionItem {
*/
filterText?: string;
/**
* A string that should be inserted in a document when selecting
* A string or snippet that should be inserted in a document when selecting
* this completion. When `falsy` the [label](#CompletionItem.label)
* is used.
*/
insertText?: string;
insertText?: string | SnippetString;
/**
* An [edit](#TextEdit) which is applied to a document when selecting
* this completion. When an edit is provided the value of
* [insertText](#CompletionItem.insertText) is ignored.
* A range of text that should be replaced by this completion item.
*
* The [range](#Range) of the edit must be single-line and one the same
* line completions where [requested](#CompletionItemProvider.provideCompletionItems) at.
* Defaults to a range from the start of the [current word](#TextDocument.getWordRangeAtPosition) to the
* current position.
*
* *Note:* The range must be a [single line](#Range.isSingleLine) and it must
* [contain](#Range.contains) the position at which completion has been [requested](#CompletionItemProvider.provideCompletionItems).
*/
range?: Range;
/**
* @deprecated **Deprecated** in favor of `CompletionItem.insertText` and `CompletionItem.range`.
*
* ~~An [edit](#TextEdit) which is applied to a document when selecting
* this completion. When an edit is provided the value of
* [insertText](#CompletionItem.insertText) is ignored.~~
*
* ~~The [range](#Range) of the edit must be single-line and on the same
* line completions were [requested](#CompletionItemProvider.provideCompletionItems) at.~~
*/
textEdit?: editorCommon.ISingleEditOperation;
}
@@ -524,11 +555,11 @@ class SuggestAdapter {
this._provider = provider;
}
private static from(item: CompletionItem): ISuggestion2 {
return {
private static from(item: CompletionItem, position: Position, wordStartPos: Position): ISuggestion2 {
let suggestion: ISuggestion2 = {
_actual: item,
label: item.label,
insertText: item.insertText || item.label,
insertText: item.label,
type: convertKind(item.kind),
detail: item.detail,
documentation: item.documentation,
@@ -536,6 +567,33 @@ class SuggestAdapter {
filterText: item.filterText,
snippetType: 'internal'
};
let editRange = item.textEdit ? item.textEdit.range : item.range;
if (editRange) {
let isSingleLine = (editRange.startLineNumber === editRange.endLineNumber);
// invalid text edit
if (!isSingleLine || editRange.startLineNumber !== position.lineNumber) {
console.warn('INVALID range, must be single line and on the same line');
return null;
}
// insert the text of the edit and create a dedicated
// suggestion-container with overwrite[Before|After]
suggestion.overwriteBefore = position.column - editRange.startColumn;
suggestion.overwriteAfter = editRange.endColumn - position.column;
} else {
suggestion.overwriteBefore = position.column - wordStartPos.column;
suggestion.overwriteAfter = 0;
}
if (item.textEdit) {
suggestion.insertText = item.textEdit.text;
} else if (typeof item.insertText === 'object' && typeof item.insertText.value === 'string') {
suggestion.insertText = item.insertText.value;
suggestion.snippetType = 'textmate';
} else if (typeof item.insertText === 'string') {
suggestion.insertText = item.insertText;
}
return suggestion;
}
provideCompletionItems(model: editorCommon.IReadOnlyModel, position: Position, token: CancellationToken): Thenable<modes.ISuggestResult> {
@@ -571,30 +629,10 @@ class SuggestAdapter {
for (let i = 0; i < list.items.length; i++) {
const item = list.items[i];
const suggestion = SuggestAdapter.from(item);
if (item.textEdit) {
let editRange = item.textEdit.range;
let isSingleLine = (editRange.startLineNumber === editRange.endLineNumber);
// invalid text edit
if (!isSingleLine || editRange.startLineNumber !== position.lineNumber) {
console.warn('INVALID text edit, must be single line and on the same line');
continue;
}
// insert the text of the edit and create a dedicated
// suggestion-container with overwrite[Before|After]
suggestion.insertText = item.textEdit.text;
suggestion.overwriteBefore = position.column - editRange.startColumn;
suggestion.overwriteAfter = editRange.endColumn - position.column;
} else {
suggestion.overwriteBefore = position.column - wordStartPos.column;
suggestion.overwriteAfter = 0;
const suggestion = SuggestAdapter.from(item, position, wordStartPos);
if (suggestion) {
result.suggestions.push(suggestion);
}
result.suggestions.push(suggestion);
}
return result;
@@ -612,7 +650,12 @@ class SuggestAdapter {
}
return toThenable(this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
return SuggestAdapter.from(resolvedItem);
let wordStartPos = position;
const word = model.getWordUntilPosition(position);
if (word) {
wordStartPos = new Position(wordStartPos.lineNumber, word.startColumn);
}
return SuggestAdapter.from(resolvedItem, position, wordStartPos);
});
}
}
+36 -7
View File
@@ -4015,6 +4015,23 @@ declare module monaco.languages {
Folder = 18,
}
/**
* A snippet string is a template which allows to insert text
* and to control the editor cursor when insertion happens.
*
* A snippet can define tab stops and placeholders with `$1`, `$2`
* and `${3:foo}`. `$0` defines the final tab stop, it defaults to
* the end of the snippet. Variables are defined with `$name` and
* `${name:default value}`. The full snippet syntax is documented
* [here](http://code.visualstudio.com/docs/customization/userdefinedsnippets#_creating-your-own-snippets).
*/
export interface SnippetString {
/**
* The snippet string.
*/
value: string;
}
/**
* A completion item represents a text snippet that is
* proposed to complete text that is being typed.
@@ -4053,18 +4070,30 @@ declare module monaco.languages {
*/
filterText?: string;
/**
* A string that should be inserted in a document when selecting
* A string or snippet that should be inserted in a document when selecting
* this completion. When `falsy` the [label](#CompletionItem.label)
* is used.
*/
insertText?: string;
insertText?: string | SnippetString;
/**
* An [edit](#TextEdit) which is applied to a document when selecting
* this completion. When an edit is provided the value of
* [insertText](#CompletionItem.insertText) is ignored.
* A range of text that should be replaced by this completion item.
*
* The [range](#Range) of the edit must be single-line and one the same
* line completions where [requested](#CompletionItemProvider.provideCompletionItems) at.
* Defaults to a range from the start of the [current word](#TextDocument.getWordRangeAtPosition) to the
* current position.
*
* *Note:* The range must be a [single line](#Range.isSingleLine) and it must
* [contain](#Range.contains) the position at which completion has been [requested](#CompletionItemProvider.provideCompletionItems).
*/
range?: Range;
/**
* @deprecated **Deprecated** in favor of `CompletionItem.insertText` and `CompletionItem.range`.
*
* ~~An [edit](#TextEdit) which is applied to a document when selecting
* this completion. When an edit is provided the value of
* [insertText](#CompletionItem.insertText) is ignored.~~
*
* ~~The [range](#Range) of the edit must be single-line and on the same
* line completions were [requested](#CompletionItemProvider.provideCompletionItems) at.~~
*/
textEdit?: editor.ISingleEditOperation;
}