diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 5ef3da01819..1149b0b8a44 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -388,20 +388,21 @@ export interface ISuggestion { label: string; codeSnippet: string; type: string; - textEdit?: EditorCommon.ISingleEditOperation; typeLabel?: string; documentationLabel?: string; filterText?: string; sortText?: string; noAutoAccept?: boolean; + overwriteBefore?: number; + overwriteAfter?: number; + + textEdit?: EditorCommon.ISingleEditOperation; } export interface ISuggestResult { currentWord: string; suggestions:ISuggestion[]; incomplete?: boolean; - overwriteBefore?: number; - overwriteAfter?: number; } export interface ISuggestionFilter { diff --git a/src/vs/editor/common/modes/abstractModeWorker.ts b/src/vs/editor/common/modes/abstractModeWorker.ts index 1115ba47ada..2bedd0469e9 100644 --- a/src/vs/editor/common/modes/abstractModeWorker.ts +++ b/src/vs/editor/common/modes/abstractModeWorker.ts @@ -153,9 +153,7 @@ export class AbstractModeWorker { result.push( { currentWord: value.currentWord, suggestions: value.suggestions.filter((element) => !!accept(values[i].currentWord, element)), - incomplete: value.incomplete, - overwriteBefore: value.overwriteBefore, - overwriteAfter: value.overwriteAfter + incomplete: value.incomplete }); } return result; diff --git a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts index bcc77271849..304ce012031 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts @@ -504,8 +504,8 @@ export class SuggestWidget implements EditorBrowser.IContentWidget, IDisposable this.submitTelemetryData(); const container = item.container; - const overwriteBefore = (typeof container.overwriteBefore === 'undefined') ? container.currentWord.length : container.overwriteBefore; - const overwriteAfter = (typeof container.overwriteAfter === 'undefined') ? 0 : Math.max(0, container.overwriteAfter); + const overwriteBefore = (typeof item.suggestion.overwriteBefore === 'undefined') ? container.currentWord.length : item.suggestion.overwriteBefore; + const overwriteAfter = (typeof item.suggestion.overwriteAfter === 'undefined') ? 0 : Math.max(0, item.suggestion.overwriteAfter); this.model.accept(item.suggestion, overwriteBefore, overwriteAfter); this.editor.focus(); diff --git a/src/vs/editor/contrib/suggest/common/suggest.ts b/src/vs/editor/contrib/suggest/common/suggest.ts index 3b38cd5d408..e8bf9d5a3bd 100644 --- a/src/vs/editor/contrib/suggest/common/suggest.ts +++ b/src/vs/editor/contrib/suggest/common/suggest.ts @@ -50,7 +50,6 @@ export function suggest(model: IModel, position: IPosition, triggerCharacter: st if (!suggestResult || !Array.isArray(suggestResult.suggestions) || suggestResult.suggestions.length === 0) { - continue; } @@ -58,8 +57,6 @@ export function suggest(model: IModel, position: IPosition, triggerCharacter: st support, currentWord: suggestResult.currentWord, incomplete: suggestResult.incomplete, - overwriteAfter: suggestResult.overwriteAfter, - overwriteBefore: suggestResult.overwriteBefore, suggestions: suggestResult.suggestions } @@ -70,19 +67,20 @@ export function suggest(model: IModel, position: IPosition, triggerCharacter: st endColumn: position.column }; - if (typeof suggestResult.overwriteBefore === 'number' && suggestResult.overwriteBefore > 0) { - defaultRange.startColumn -= suggestResult.overwriteBefore; - } - if (typeof suggestResult.overwriteAfter === 'number' && suggestResult.overwriteAfter > 0) { - defaultRange.endColumn += suggestResult.overwriteAfter - } - for (let suggestion of suggestResult.suggestions) { if (!suggestion.textEdit) { suggestion.textEdit = { text: suggestion.codeSnippet, range: defaultRange }; + if (typeof suggestion.overwriteBefore === 'number' && suggestion.overwriteBefore > 0 || typeof suggestion.overwriteAfter === 'number' && suggestion.overwriteAfter > 0) { + suggestion.textEdit.range = { + startLineNumber: position.lineNumber, + startColumn: position.column - suggestion.overwriteBefore || 0, + endLineNumber: position.lineNumber, + endColumn: position.column + suggestion.overwriteAfter || 0 + } + } } } diff --git a/src/vs/languages/html/common/htmlWorker.ts b/src/vs/languages/html/common/htmlWorker.ts index ba897aefbbb..996ae2b1d1e 100644 --- a/src/vs/languages/html/common/htmlWorker.ts +++ b/src/vs/languages/html/common/htmlWorker.ts @@ -195,13 +195,14 @@ export class HTMLWorker extends AbstractModeWorker { var contentAfter = model.getLineContent(position.lineNumber).substr(position.column - 1); var closeTag = isWhiteSpace(contentAfter) || strings.startsWith(contentAfter, '<') ? '>' : ''; - var collectClosingTagSuggestion = (correctIndent:boolean) => { + var collectClosingTagSuggestion = (correctIndent:boolean, overwriteBefore: number) => { var endPosition = scanner.getTokenPosition(); var matchingTag = this.findMatchingOpenTag(scanner); if (matchingTag) { var suggestion : Modes.ISuggestion = { label: '/' + matchingTag, codeSnippet: '/' + matchingTag + closeTag, + overwriteBefore: overwriteBefore, type: 'property' }; suggestions.suggestions.push(suggestion); @@ -213,7 +214,7 @@ export class HTMLWorker extends AbstractModeWorker { var startIndent = model.getLineContent(startPosition.lineNumber).substring(0, startPosition.column - 1); var endIndent = model.getLineContent(endPosition.lineNumber).substring(0, endPosition.column - 1); if (isWhiteSpace(startIndent) && isWhiteSpace(endIndent)) { - suggestions.overwriteBefore = position.column - 1; + suggestion.overwriteBefore = position.column - 1; // replace from start of line suggestion.codeSnippet = startIndent + ' { provider.collectTags((tag, label) => { suggestions.suggestions.push({ label: '/' + tag, + overwriteBefore: suggestions.currentWord.length + 1, codeSnippet: '/' + tag + closeTag, type: 'property', documentationLabel: label @@ -244,7 +241,7 @@ export class HTMLWorker extends AbstractModeWorker { }); } } else { - collectClosingTagSuggestion(false); + collectClosingTagSuggestion(false, suggestions.currentWord.length); this._tagProviders.forEach((provider) => { provider.collectTags((tag, label) => { diff --git a/src/vs/languages/json/common/jsonIntellisense.ts b/src/vs/languages/json/common/jsonIntellisense.ts index 46a9957a4e2..555fa88b14a 100644 --- a/src/vs/languages/json/common/jsonIntellisense.ts +++ b/src/vs/languages/json/common/jsonIntellisense.ts @@ -44,11 +44,17 @@ export class JSONIntellisense { incomplete: false, suggestions: [] }; + var overwriteBefore = void 0; + var overwriteAfter = void 0; + var proposed: { [key: string]: boolean } = {}; var collector : JsonWorker.ISuggestionsCollector = { add: (suggestion: Modes.ISuggestion) => { if (!proposed[suggestion.label]) { proposed[suggestion.label] = true; + + suggestion.overwriteBefore = overwriteBefore; + suggestion.overwriteAfter = overwriteAfter; result.suggestions.push(suggestion); } }, @@ -74,8 +80,8 @@ export class JSONIntellisense { var stringNode = node; if (stringNode.isKey) { var nodeRange = modelMirror.getRangeFromOffsetAndLength(node.start, node.end - node.start); - result.overwriteBefore = position.column - nodeRange.startColumn; - result.overwriteAfter = nodeRange.endColumn - position.column; + overwriteBefore = position.column - nodeRange.startColumn; + overwriteAfter = nodeRange.endColumn - position.column; addValue = !(node.parent && (( node.parent).value)); currentProperty = node.parent ? node.parent : null; currentKey = modelMirror.getValueInRange({ startColumn: nodeRange.startColumn + 1, startLineNumber: nodeRange.startLineNumber, endColumn: position.column, endLineNumber: position.lineNumber }); @@ -122,8 +128,8 @@ export class JSONIntellisense { // proposals for values if (node && (node.type === 'string' || node.type === 'number' || node.type === 'boolean' || node.type === 'null')) { var nodeRange = modelMirror.getRangeFromOffsetAndLength(node.start, node.end - node.start); - result.overwriteBefore = position.column - nodeRange.startColumn; - result.overwriteAfter = nodeRange.endColumn - position.column; + overwriteBefore = position.column - nodeRange.startColumn; + overwriteAfter = nodeRange.endColumn - position.column; node = node.parent; } diff --git a/src/vs/workbench/api/common/extHostApiCommands.ts b/src/vs/workbench/api/common/extHostApiCommands.ts index a059a192f41..169afe673c1 100644 --- a/src/vs/workbench/api/common/extHostApiCommands.ts +++ b/src/vs/workbench/api/common/extHostApiCommands.ts @@ -256,7 +256,7 @@ export class ExtHostApiCommands { for (let group of value) { for (let suggestions of group) { for (let suggestion of suggestions.suggestions) { - const item = typeConverters.Suggest.to(suggestion); + const item = typeConverters.Suggest.to(suggestions, position, suggestion); items.push(item); } } diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index e68844d4614..550c26d9428 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -502,12 +502,12 @@ class SuggestAdapter implements modes.ISuggestSupport { // insert the text of the edit and create a dedicated // suggestion-container with overwrite[Before|After] suggestion.codeSnippet = item.textEdit.newText; + suggestion.overwriteBefore = pos.character - editRange.start.character, + suggestion.overwriteAfter = editRange.end.character - pos.character allSuggestions.push({ currentWord: doc.getText(editRange), - suggestions: [suggestion], - overwriteBefore: pos.character - editRange.start.character, - overwriteAfter: editRange.end.character - pos.character + suggestions: [suggestion] }); } else { diff --git a/src/vs/workbench/api/common/pluginHostTypeConverters.ts b/src/vs/workbench/api/common/pluginHostTypeConverters.ts index 312555ec4aa..d6a8901aea9 100644 --- a/src/vs/workbench/api/common/pluginHostTypeConverters.ts +++ b/src/vs/workbench/api/common/pluginHostTypeConverters.ts @@ -326,7 +326,6 @@ export const Suggest = { codeSnippet: item.insertText || item.label, type: types.CompletionItemKind[item.kind || types.CompletionItemKind.Text].toString().toLowerCase(), typeLabel: item.detail, - textEdit: item.textEdit && TextEdit.from(item.textEdit), documentationLabel: item.documentation, sortText: item.sortText, filterText: item.filterText @@ -334,7 +333,7 @@ export const Suggest = { return suggestion; }, - to(suggestion: modes.ISuggestion): types.CompletionItem { + to(container: modes.ISuggestResult, position: types.Position, suggestion: modes.ISuggestion): types.CompletionItem { const result = new types.CompletionItem(suggestion.label); result.insertText = suggestion.codeSnippet; result.kind = types.CompletionItemKind[suggestion.type.charAt(0).toUpperCase() + suggestion.type.substr(1)]; @@ -342,7 +341,15 @@ export const Suggest = { result.documentation = suggestion.documentationLabel; result.sortText = suggestion.sortText; result.filterText = suggestion.filterText; - result.textEdit = suggestion.textEdit && TextEdit.to(suggestion.textEdit); + + var overwriteBefore = (typeof suggestion.overwriteBefore !== 'undefined') ? suggestion.overwriteBefore : container.currentWord.length; + var startPosition = new types.Position(position.line, Math.max(0, position.character - overwriteBefore)); + var endPosition = position; + if (typeof suggestion.overwriteAfter !== 'undefined') { + endPosition = new types.Position(position.line, position.character + suggestion.overwriteAfter); + } + + result.textEdit = types.TextEdit.replace(new types.Range(startPosition, endPosition), suggestion.codeSnippet); return result; } }