mirror of
https://github.com/Microsoft/vscode
synced 2024-10-30 19:12:57 +00:00
implement API proposal
This commit is contained in:
parent
f1583f11ab
commit
9f474febfe
13 changed files with 111 additions and 73 deletions
|
@ -453,7 +453,7 @@ export interface CompletionItem {
|
|||
* *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: IRange;
|
||||
range: IRange | { insert: IRange, replace: IRange };
|
||||
/**
|
||||
* An optional set of characters that when pressed while this completion is active will accept it first and
|
||||
* then type that character. *Note* that all commit characters should have `length=1` and that superfluous
|
||||
|
|
|
@ -160,7 +160,7 @@ export class CompletionModel {
|
|||
// 'word' is that remainder of the current line that we
|
||||
// filter and score against. In theory each suggestion uses a
|
||||
// different word, but in practice not - that's why we cache
|
||||
const overwriteBefore = item.position.column - item.completion.range.startColumn;
|
||||
const overwriteBefore = item.position.column - item.editStart.column;
|
||||
const wordLen = overwriteBefore + characterCountDelta - (item.position.column - this._column);
|
||||
if (word.length !== wordLen) {
|
||||
word = wordLen === 0 ? '' : leadingLineContent.slice(-wordLen);
|
||||
|
|
|
@ -31,6 +31,11 @@ export class CompletionItem {
|
|||
|
||||
readonly resolve: (token: CancellationToken) => Promise<void>;
|
||||
|
||||
//
|
||||
readonly editStart: IPosition;
|
||||
readonly editInsertEnd: IPosition;
|
||||
readonly editReplaceEnd: IPosition;
|
||||
|
||||
// perf
|
||||
readonly labelLow: string;
|
||||
readonly sortTextLow?: string;
|
||||
|
@ -54,6 +59,17 @@ export class CompletionItem {
|
|||
this.sortTextLow = completion.sortText && completion.sortText.toLowerCase();
|
||||
this.filterTextLow = completion.filterText && completion.filterText.toLowerCase();
|
||||
|
||||
// normalize ranges
|
||||
if (Range.isIRange(completion.range)) {
|
||||
this.editStart = new Position(completion.range.startLineNumber, completion.range.startColumn);
|
||||
this.editInsertEnd = new Position(completion.range.endLineNumber, completion.range.endColumn);
|
||||
this.editReplaceEnd = new Position(completion.range.endLineNumber, completion.range.endColumn);
|
||||
} else {
|
||||
this.editStart = new Position(completion.range.insert.startLineNumber, completion.range.insert.startColumn);
|
||||
this.editInsertEnd = new Position(completion.range.insert.endLineNumber, completion.range.insert.endColumn);
|
||||
this.editReplaceEnd = new Position(completion.range.replace.endLineNumber, completion.range.replace.endColumn);
|
||||
}
|
||||
|
||||
// create the suggestion resolver
|
||||
const { resolveCompletionItem } = provider;
|
||||
if (typeof resolveCompletionItem !== 'function') {
|
||||
|
@ -122,8 +138,12 @@ export function provideSuggestionItems(
|
|||
token: CancellationToken = CancellationToken.None
|
||||
): Promise<CompletionItem[]> {
|
||||
|
||||
const wordUntil = model.getWordUntilPosition(position);
|
||||
const defaultRange = new Range(position.lineNumber, wordUntil.startColumn, position.lineNumber, wordUntil.endColumn);
|
||||
const word = model.getWordAtPosition(position);
|
||||
const defaultReplaceRange = word ? new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn) : Range.fromPositions(position);
|
||||
const defaultInsertRange = defaultReplaceRange.setEndPosition(position.lineNumber, position.column);
|
||||
|
||||
// const wordUntil = model.getWordUntilPosition(position);
|
||||
// const defaultRange = new Range(position.lineNumber, wordUntil.startColumn, position.lineNumber, wordUntil.endColumn);
|
||||
|
||||
position = position.clone();
|
||||
|
||||
|
@ -159,7 +179,7 @@ export function provideSuggestionItems(
|
|||
|
||||
// fill in default range when missing
|
||||
if (!suggestion.range) {
|
||||
suggestion.range = defaultRange;
|
||||
suggestion.range = { insert: defaultInsertRange, replace: defaultReplaceRange };
|
||||
}
|
||||
// fill in default sortText when missing
|
||||
if (!suggestion.sortText) {
|
||||
|
|
|
@ -138,7 +138,7 @@ export class SuggestController implements IEditorContribution {
|
|||
this._toDispose.add(widget.onDidFocus(({ item }) => {
|
||||
|
||||
const position = this._editor.getPosition()!;
|
||||
const startColumn = item.completion.range.startColumn;
|
||||
const startColumn = item.editStart.column;
|
||||
const endColumn = position.column;
|
||||
let value = true;
|
||||
if (
|
||||
|
@ -241,7 +241,8 @@ export class SuggestController implements IEditorContribution {
|
|||
|
||||
const model = this._editor.getModel();
|
||||
const modelVersionNow = model.getAlternativeVersionId();
|
||||
const { completion: suggestion, position } = event.item;
|
||||
const { item } = event;
|
||||
const { completion: suggestion, position } = item;
|
||||
const columnDelta = this._editor.getPosition().column - position.column;
|
||||
|
||||
// pushing undo stops *before* additional text edits and
|
||||
|
@ -255,33 +256,20 @@ export class SuggestController implements IEditorContribution {
|
|||
}
|
||||
|
||||
// keep item in memory
|
||||
this._memoryService.memorize(model, this._editor.getPosition(), event.item);
|
||||
this._memoryService.memorize(model, this._editor.getPosition(), item);
|
||||
|
||||
let { insertText } = suggestion;
|
||||
if (!(suggestion.insertTextRules! & CompletionItemInsertTextRule.InsertAsSnippet)) {
|
||||
insertText = SnippetParser.escape(insertText);
|
||||
}
|
||||
|
||||
let overwriteBefore = position.column - suggestion.range.startColumn;
|
||||
let overwriteAfter = suggestion.range.endColumn - position.column;
|
||||
let suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(this._editor.getPosition()) : 0;
|
||||
let word = model.getWordAtPosition(this._editor.getPosition());
|
||||
|
||||
const overwriteConfig = flags & InsertFlags.AlternativeOverwriteConfig
|
||||
? !this._editor.getOption(EditorOption.suggest).overwriteOnAccept
|
||||
: this._editor.getOption(EditorOption.suggest).overwriteOnAccept;
|
||||
if (!overwriteConfig) {
|
||||
if (overwriteAfter > 0 && word && suggestion.range.endColumn === word.endColumn) {
|
||||
// don't overwrite anything right of the cursor, overrule extension even when the
|
||||
// completion only replaces a word...
|
||||
overwriteAfter = 0;
|
||||
}
|
||||
} else {
|
||||
if (overwriteAfter === 0 && word) {
|
||||
// compute fallback overwrite length
|
||||
overwriteAfter = word.endColumn - this._editor.getPosition().column;
|
||||
}
|
||||
}
|
||||
|
||||
const overwriteBefore = position.column - item.editStart.column;
|
||||
const overwriteAfter = (overwriteConfig ? item.editReplaceEnd.column : item.editInsertEnd.column) - position.column;
|
||||
const suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(this._editor.getPosition()) : 0;
|
||||
|
||||
SnippetController2.get(this._editor).insert(insertText, {
|
||||
overwriteBefore: overwriteBefore + columnDelta,
|
||||
|
@ -367,7 +355,7 @@ export class SuggestController implements IEditorContribution {
|
|||
return true;
|
||||
}
|
||||
const position = this._editor.getPosition()!;
|
||||
const startColumn = item.completion.range.startColumn;
|
||||
const startColumn = item.editStart.column;
|
||||
const endColumn = position.column;
|
||||
if (endColumn - startColumn !== item.completion.insertText.length) {
|
||||
// unequal lengths -> makes edit
|
||||
|
|
5
src/vs/monaco.d.ts
vendored
5
src/vs/monaco.d.ts
vendored
|
@ -4765,7 +4765,10 @@ declare namespace monaco.languages {
|
|||
* *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: IRange;
|
||||
range: IRange | {
|
||||
insert: IRange;
|
||||
replace: IRange;
|
||||
};
|
||||
/**
|
||||
* An optional set of characters that when pressed while this completion is active will accept it first and
|
||||
* then type that character. *Note* that all commit characters should have `length=1` and that superfluous
|
||||
|
|
12
src/vs/vscode.d.ts
vendored
12
src/vs/vscode.d.ts
vendored
|
@ -3393,15 +3393,17 @@ declare module 'vscode' {
|
|||
insertText?: string | SnippetString;
|
||||
|
||||
/**
|
||||
* A range of text that should be replaced by this completion item.
|
||||
* A range or a insert and replace range selecting the text that should be replaced by this completion item.
|
||||
*
|
||||
* Defaults to a range from the start of the [current word](#TextDocument.getWordRangeAtPosition) to the
|
||||
* current position.
|
||||
* When omitted, the range of the [current word](#TextDocument.getWordRangeAtPosition) is used as replace-range
|
||||
* and as insert-range the start of the [current word](#TextDocument.getWordRangeAtPosition) to the
|
||||
* current position is used.
|
||||
*
|
||||
* *Note:* The range must be a [single line](#Range.isSingleLine) and it must
|
||||
* *Note 1:* A range must be a [single line](#Range.isSingleLine) and it must
|
||||
* [contain](#Range.contains) the position at which completion has been [requested](#CompletionItemProvider.provideCompletionItems).
|
||||
* *Note 2:* A insert range must be a prefix of a replace range, that means it must be contained and starting at the same position.
|
||||
*/
|
||||
range?: Range;
|
||||
range?: Range | { insert: Range; replace: Range; };
|
||||
|
||||
/**
|
||||
* An optional set of characters that when pressed while this completion is active will accept it first and
|
||||
|
|
|
@ -326,7 +326,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
|||
|
||||
// --- suggest
|
||||
|
||||
private static _inflateSuggestDto(defaultRange: IRange, data: ISuggestDataDto): modes.CompletionItem {
|
||||
private static _inflateSuggestDto(defaultRange: IRange | { insert: IRange, replace: IRange }, data: ISuggestDataDto): modes.CompletionItem {
|
||||
|
||||
return {
|
||||
label: data[ISuggestDataDtoField.label],
|
||||
kind: data[ISuggestDataDtoField.kind],
|
||||
|
@ -337,8 +338,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
|||
filterText: data[ISuggestDataDtoField.filterText],
|
||||
preselect: data[ISuggestDataDtoField.preselect],
|
||||
insertText: typeof data.h === 'undefined' ? data[ISuggestDataDtoField.label] : data.h,
|
||||
insertTextRules: data[ISuggestDataDtoField.insertTextRules],
|
||||
range: data[ISuggestDataDtoField.range] || defaultRange,
|
||||
insertTextRules: data[ISuggestDataDtoField.insertTextRules],
|
||||
commitCharacters: data[ISuggestDataDtoField.commitCharacters],
|
||||
additionalTextEdits: data[ISuggestDataDtoField.additionalTextEdits],
|
||||
command: data[ISuggestDataDtoField.command],
|
||||
|
@ -370,6 +371,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
|||
if (!result) {
|
||||
return suggestion;
|
||||
}
|
||||
|
||||
let newSuggestion = MainThreadLanguageFeatures._inflateSuggestDto(suggestion.range, result);
|
||||
return mixin(suggestion, newSuggestion, true);
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -84,7 +84,7 @@ suite('SnippetsService', function () {
|
|||
assert.equal(result.incomplete, undefined);
|
||||
assert.equal(result.suggestions.length, 1);
|
||||
assert.equal(result.suggestions[0].label, 'bar');
|
||||
assert.equal(result.suggestions[0].range.startColumn, 1);
|
||||
assert.equal((result.suggestions[0].range as any).startColumn, 1);
|
||||
assert.equal(result.suggestions[0].insertText, 'barCodeSnippet');
|
||||
});
|
||||
});
|
||||
|
@ -117,10 +117,10 @@ suite('SnippetsService', function () {
|
|||
assert.equal(result.suggestions.length, 2);
|
||||
assert.equal(result.suggestions[0].label, 'bar');
|
||||
assert.equal(result.suggestions[0].insertText, 's1');
|
||||
assert.equal(result.suggestions[0].range.startColumn, 1);
|
||||
assert.equal((result.suggestions[0].range as any).startColumn, 1);
|
||||
assert.equal(result.suggestions[1].label, 'bar-bar');
|
||||
assert.equal(result.suggestions[1].insertText, 's2');
|
||||
assert.equal(result.suggestions[1].range.startColumn, 1);
|
||||
assert.equal((result.suggestions[1].range as any).startColumn, 1);
|
||||
});
|
||||
|
||||
await provider.provideCompletionItems(model, new Position(1, 5), context)!.then(result => {
|
||||
|
@ -128,7 +128,7 @@ suite('SnippetsService', function () {
|
|||
assert.equal(result.suggestions.length, 1);
|
||||
assert.equal(result.suggestions[0].label, 'bar-bar');
|
||||
assert.equal(result.suggestions[0].insertText, 's2');
|
||||
assert.equal(result.suggestions[0].range.startColumn, 1);
|
||||
assert.equal((result.suggestions[0].range as any).startColumn, 1);
|
||||
});
|
||||
|
||||
await provider.provideCompletionItems(model, new Position(1, 6), context)!.then(result => {
|
||||
|
@ -136,10 +136,10 @@ suite('SnippetsService', function () {
|
|||
assert.equal(result.suggestions.length, 2);
|
||||
assert.equal(result.suggestions[0].label, 'bar');
|
||||
assert.equal(result.suggestions[0].insertText, 's1');
|
||||
assert.equal(result.suggestions[0].range.startColumn, 5);
|
||||
assert.equal((result.suggestions[0].range as any).startColumn, 5);
|
||||
assert.equal(result.suggestions[1].label, 'bar-bar');
|
||||
assert.equal(result.suggestions[1].insertText, 's2');
|
||||
assert.equal(result.suggestions[1].range.startColumn, 1);
|
||||
assert.equal((result.suggestions[1].range as any).startColumn, 1);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -165,14 +165,14 @@ suite('SnippetsService', function () {
|
|||
return provider.provideCompletionItems(model, new Position(1, 4), context)!;
|
||||
}).then(result => {
|
||||
assert.equal(result.suggestions.length, 1);
|
||||
assert.equal(result.suggestions[0].range.startColumn, 2);
|
||||
assert.equal((result.suggestions[0].range as any).startColumn, 2);
|
||||
model.dispose();
|
||||
|
||||
model = TextModel.createFromString('a<?', undefined, modeService.getLanguageIdentifier('fooLang'));
|
||||
return provider.provideCompletionItems(model, new Position(1, 4), context)!;
|
||||
}).then(result => {
|
||||
assert.equal(result.suggestions.length, 1);
|
||||
assert.equal(result.suggestions[0].range.startColumn, 2);
|
||||
assert.equal((result.suggestions[0].range as any).startColumn, 2);
|
||||
model.dispose();
|
||||
});
|
||||
});
|
||||
|
@ -400,13 +400,13 @@ suite('SnippetsService', function () {
|
|||
|
||||
assert.equal(result.suggestions.length, 1);
|
||||
let [first] = result.suggestions;
|
||||
assert.equal(first.range.startColumn, 2);
|
||||
assert.equal((first.range as any).startColumn, 2);
|
||||
|
||||
model = TextModel.createFromString('1', undefined, modeService.getLanguageIdentifier('fooLang'));
|
||||
result = await provider.provideCompletionItems(model, new Position(1, 2), context)!;
|
||||
|
||||
assert.equal(result.suggestions.length, 1);
|
||||
[first] = result.suggestions;
|
||||
assert.equal(first.range.startColumn, 1);
|
||||
assert.equal((first.range as any).startColumn, 1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -412,11 +412,8 @@ suite('ExtHostLanguageFeatureCommands', function () {
|
|||
assert.equal(values.length, 4);
|
||||
let [first, second, third, fourth] = values;
|
||||
assert.equal(first.label, 'item1');
|
||||
assert.equal(first.textEdit!.newText, 'item1');
|
||||
assert.equal(first.textEdit!.range.start.line, 0);
|
||||
assert.equal(first.textEdit!.range.start.character, 0);
|
||||
assert.equal(first.textEdit!.range.end.line, 0);
|
||||
assert.equal(first.textEdit!.range.end.character, 4);
|
||||
assert.equal(first.textEdit, undefined);// no text edit, default ranges
|
||||
assert.ok(!types.Range.isRange(first.range));
|
||||
|
||||
assert.equal(second.label, 'item2');
|
||||
assert.equal(second.textEdit!.newText, 'foo');
|
||||
|
@ -434,10 +431,13 @@ suite('ExtHostLanguageFeatureCommands', function () {
|
|||
|
||||
assert.equal(fourth.label, 'item4');
|
||||
assert.equal(fourth.textEdit, undefined);
|
||||
assert.equal(fourth.range!.start.line, 0);
|
||||
assert.equal(fourth.range!.start.character, 1);
|
||||
assert.equal(fourth.range!.end.line, 0);
|
||||
assert.equal(fourth.range!.end.character, 4);
|
||||
|
||||
const range: any = fourth.range!;
|
||||
assert.ok(types.Range.isRange(range));
|
||||
assert.equal(range.start.line, 0);
|
||||
assert.equal(range.start.character, 1);
|
||||
assert.equal(range.end.line, 0);
|
||||
assert.equal(range.end.character, 4);
|
||||
assert.ok(fourth.insertText instanceof types.SnippetString);
|
||||
assert.equal((<types.SnippetString>fourth.insertText).value, 'foo$0bar');
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue