implement API proposal

This commit is contained in:
Johannes Rieken
2019-10-22 16:48:12 +02:00
parent f1583f11ab
commit 9f474febfe
13 changed files with 111 additions and 73 deletions

View File

@@ -970,7 +970,7 @@ export interface ISuggestDataDto {
[ISuggestDataDtoField.preselect]?: boolean;
[ISuggestDataDtoField.insertText]?: string;
[ISuggestDataDtoField.insertTextRules]?: modes.CompletionItemInsertTextRule;
[ISuggestDataDtoField.range]?: IRange;
[ISuggestDataDtoField.range]?: IRange | { insert: IRange, replace: IRange };
[ISuggestDataDtoField.commitCharacters]?: string[];
[ISuggestDataDtoField.additionalTextEdits]?: ISingleEditOperation[];
[ISuggestDataDtoField.command]?: modes.Command;
@@ -981,7 +981,7 @@ export interface ISuggestDataDto {
export interface ISuggestResultDto {
x?: number;
a: IRange;
a: { insert: IRange, replace: IRange };
b: ISuggestDataDto[];
c?: boolean;
}

View File

@@ -658,13 +658,13 @@ class SuggestAdapter {
this._disposables.set(pid, disposables);
// the default text edit range
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos))
.with({ end: pos });
const replaceRange = doc.getWordRangeAtPosition(pos) || new Range(pos, pos);
const insertRange = replaceRange.with({ end: pos });
const result: extHostProtocol.ISuggestResultDto = {
x: pid,
b: [],
a: typeConvert.Range.from(wordRangeBeforePos),
a: { replace: typeConvert.Range.from(replaceRange), insert: typeConvert.Range.from(insertRange) },
c: list.isIncomplete || undefined
};
@@ -751,21 +751,44 @@ class SuggestAdapter {
}
// 'overwrite[Before|After]'-logic
let range: vscode.Range | undefined;
let range: vscode.Range | { insert: vscode.Range, replace: vscode.Range } | undefined;
if (item.textEdit) {
range = item.textEdit.range;
} else if (item.range) {
range = item.range;
}
result[extHostProtocol.ISuggestDataDtoField.range] = typeConvert.Range.from(range);
if (range && (!range.isSingleLine || range.start.line !== position.line)) {
console.warn('INVALID text edit -> must be single line and on the same line');
return undefined;
if (range) {
if (Range.isRange(range)) {
if (!SuggestAdapter._isValidRangeForCompletion(range, position)) {
console.trace('INVALID range -> must be single line and on the same line');
return undefined;
}
result[extHostProtocol.ISuggestDataDtoField.range] = typeConvert.Range.from(range);
} else {
if (
!SuggestAdapter._isValidRangeForCompletion(range.insert, position)
|| !SuggestAdapter._isValidRangeForCompletion(range.replace, position)
|| !range.insert.start.isEqual(range.replace.start)
|| !range.replace.contains(range.insert)
) {
console.trace('INVALID range -> must be single line, on the same line, insert range must be a prefix of replace range');
return undefined;
}
result[extHostProtocol.ISuggestDataDtoField.range] = {
insert: typeConvert.Range.from(range.insert),
replace: typeConvert.Range.from(range.replace)
};
}
}
return result;
}
private static _isValidRangeForCompletion(range: vscode.Range, position: vscode.Position): boolean {
return range.isSingleLine || range.start.line === position.line;
}
}
class SignatureHelpAdapter {

View File

@@ -15,7 +15,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import * as editorRange from 'vs/editor/common/core/range';
import { ISelection } from 'vs/editor/common/core/selection';
import * as htmlContent from 'vs/base/common/htmlContent';
import * as languageSelector from 'vs/editor/common/modes/languageSelector';
@@ -68,9 +68,9 @@ export namespace Selection {
export namespace Range {
export function from(range: undefined): undefined;
export function from(range: RangeLike): IRange;
export function from(range: RangeLike | undefined): IRange | undefined;
export function from(range: RangeLike | undefined): IRange | undefined {
export function from(range: RangeLike): editorRange.IRange;
export function from(range: RangeLike | undefined): editorRange.IRange | undefined;
export function from(range: RangeLike | undefined): editorRange.IRange | undefined {
if (!range) {
return undefined;
}
@@ -84,9 +84,9 @@ export namespace Range {
}
export function to(range: undefined): types.Range;
export function to(range: IRange): types.Range;
export function to(range: IRange | undefined): types.Range | undefined;
export function to(range: IRange | undefined): types.Range | undefined {
export function to(range: editorRange.IRange): types.Range;
export function to(range: editorRange.IRange | undefined): types.Range | undefined;
export function to(range: editorRange.IRange | undefined): types.Range | undefined {
if (!range) {
return undefined;
}
@@ -821,14 +821,14 @@ export namespace CompletionItem {
result.filterText = suggestion.filterText;
result.preselect = suggestion.preselect;
result.commitCharacters = suggestion.commitCharacters;
result.range = Range.to(suggestion.range);
result.range = editorRange.Range.isIRange(suggestion.range) ? Range.to(suggestion.range) : { insert: Range.to(suggestion.range.insert), replace: Range.to(suggestion.range.replace) };
result.keepWhitespace = typeof suggestion.insertTextRules === 'undefined' ? false : Boolean(suggestion.insertTextRules & modes.CompletionItemInsertTextRule.KeepWhitespace);
// 'inserText'-logic
if (typeof suggestion.insertTextRules !== 'undefined' && suggestion.insertTextRules & modes.CompletionItemInsertTextRule.InsertAsSnippet) {
result.insertText = new types.SnippetString(suggestion.insertText);
} else {
result.insertText = suggestion.insertText;
result.textEdit = new types.TextEdit(result.range, result.insertText);
result.textEdit = result.range instanceof types.Range ? new types.TextEdit(result.range, result.insertText) : undefined;
}
// TODO additionalEdits, command

View File

@@ -1343,7 +1343,7 @@ export class CompletionItem implements vscode.CompletionItem {
preselect?: boolean;
insertText?: string | SnippetString;
keepWhitespace?: boolean;
range?: Range;
range?: Range | { insert: Range; replace: Range; };
commitCharacters?: string[];
textEdit?: TextEdit;
additionalTextEdits?: TextEdit[];