Make TS completion item more efficent to compute
For #95324 - Removes repeated calls to `getWordRangeAtPosition` - Only use our fuzzy string logic when using TS 3.8 or older
This commit is contained in:
parent
6c068456e3
commit
948aa4a214
1 changed files with 37 additions and 28 deletions
|
@ -32,8 +32,16 @@ interface CompletionContext {
|
||||||
readonly isNewIdentifierLocation: boolean;
|
readonly isNewIdentifierLocation: boolean;
|
||||||
readonly isMemberCompletion: boolean;
|
readonly isMemberCompletion: boolean;
|
||||||
readonly isInValidCommitCharacterContext: boolean;
|
readonly isInValidCommitCharacterContext: boolean;
|
||||||
readonly enableCallCompletions: boolean;
|
|
||||||
readonly dotAccessorContext?: DotAccessorContext;
|
readonly dotAccessorContext?: DotAccessorContext;
|
||||||
|
|
||||||
|
readonly enableCallCompletions: boolean;
|
||||||
|
readonly useCodeSnippetsOnMethodSuggest: boolean,
|
||||||
|
|
||||||
|
readonly wordRange: vscode.Range | undefined;
|
||||||
|
readonly line: string;
|
||||||
|
|
||||||
|
readonly useFuzzyWordRangeLogic: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyCompletionItem extends vscode.CompletionItem {
|
class MyCompletionItem extends vscode.CompletionItem {
|
||||||
|
@ -42,10 +50,8 @@ class MyCompletionItem extends vscode.CompletionItem {
|
||||||
constructor(
|
constructor(
|
||||||
public readonly position: vscode.Position,
|
public readonly position: vscode.Position,
|
||||||
public readonly document: vscode.TextDocument,
|
public readonly document: vscode.TextDocument,
|
||||||
line: string,
|
|
||||||
public readonly tsEntry: Proto.CompletionEntry,
|
public readonly tsEntry: Proto.CompletionEntry,
|
||||||
useCodeSnippetsOnMethodSuggest: boolean,
|
private readonly completionContext: CompletionContext,
|
||||||
public readonly completionContext: CompletionContext,
|
|
||||||
public readonly metadata: any | undefined,
|
public readonly metadata: any | undefined,
|
||||||
) {
|
) {
|
||||||
super(tsEntry.name, MyCompletionItem.convertKind(tsEntry.kind));
|
super(tsEntry.name, MyCompletionItem.convertKind(tsEntry.kind));
|
||||||
|
@ -63,13 +69,13 @@ class MyCompletionItem extends vscode.CompletionItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.position = position;
|
this.position = position;
|
||||||
this.useCodeSnippet = useCodeSnippetsOnMethodSuggest && (this.kind === vscode.CompletionItemKind.Function || this.kind === vscode.CompletionItemKind.Method);
|
this.useCodeSnippet = completionContext.useCodeSnippetsOnMethodSuggest && (this.kind === vscode.CompletionItemKind.Function || this.kind === vscode.CompletionItemKind.Method);
|
||||||
|
|
||||||
if (tsEntry.replacementSpan) {
|
if (tsEntry.replacementSpan) {
|
||||||
let replaceRange = typeConverters.Range.fromTextSpan(tsEntry.replacementSpan);
|
let replaceRange = typeConverters.Range.fromTextSpan(tsEntry.replacementSpan);
|
||||||
// Make sure we only replace a single line at most
|
// Make sure we only replace a single line at most
|
||||||
if (!replaceRange.isSingleLine) {
|
if (!replaceRange.isSingleLine) {
|
||||||
replaceRange = new vscode.Range(replaceRange.start.line, replaceRange.start.character, replaceRange.start.line, line.length);
|
replaceRange = new vscode.Range(replaceRange.start.line, replaceRange.start.character, replaceRange.start.line, completionContext.line.length);
|
||||||
}
|
}
|
||||||
this.range = {
|
this.range = {
|
||||||
inserting: new vscode.Range(replaceRange.start, position),
|
inserting: new vscode.Range(replaceRange.start, position),
|
||||||
|
@ -78,12 +84,12 @@ class MyCompletionItem extends vscode.CompletionItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.insertText = tsEntry.insertText;
|
this.insertText = tsEntry.insertText;
|
||||||
this.filterText = this.getFilterText(line, tsEntry.insertText);
|
this.filterText = this.getFilterText(completionContext.line, tsEntry.insertText);
|
||||||
|
|
||||||
if (completionContext.isMemberCompletion && completionContext.dotAccessorContext) {
|
if (completionContext.isMemberCompletion && completionContext.dotAccessorContext) {
|
||||||
this.filterText = completionContext.dotAccessorContext.text + (this.insertText || this.label);
|
this.filterText = completionContext.dotAccessorContext.text + (this.insertText || this.label);
|
||||||
if (!this.range) {
|
if (!this.range) {
|
||||||
const replacementRange = this.getReplaceRange(line);
|
const replacementRange = this.getFuzzyWordRange();
|
||||||
if (replacementRange) {
|
if (replacementRange) {
|
||||||
this.range = {
|
this.range = {
|
||||||
inserting: completionContext.dotAccessorContext.range,
|
inserting: completionContext.dotAccessorContext.range,
|
||||||
|
@ -126,13 +132,13 @@ class MyCompletionItem extends vscode.CompletionItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.resolveRange(line);
|
this.resolveRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFilterText(line: string, insertText: string | undefined): string | undefined {
|
private getFilterText(line: string, insertText: string | undefined): string | undefined {
|
||||||
// Handle private field completions
|
// Handle private field completions
|
||||||
if (this.tsEntry.name.startsWith('#')) {
|
if (this.tsEntry.name.startsWith('#')) {
|
||||||
const wordRange = this.document.getWordRangeAtPosition(this.position);
|
const wordRange = this.completionContext.wordRange;
|
||||||
const wordStart = wordRange ? line.charAt(wordRange.start.character) : undefined;
|
const wordStart = wordRange ? line.charAt(wordRange.start.character) : undefined;
|
||||||
if (insertText) {
|
if (insertText) {
|
||||||
if (insertText.startsWith('this.#')) {
|
if (insertText.startsWith('this.#')) {
|
||||||
|
@ -164,12 +170,12 @@ class MyCompletionItem extends vscode.CompletionItem {
|
||||||
return insertText;
|
return insertText;
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveRange(line: string): void {
|
private resolveRange(): void {
|
||||||
if (this.range) {
|
if (this.range) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const replaceRange = this.getReplaceRange(line);
|
const replaceRange = this.getFuzzyWordRange();
|
||||||
if (replaceRange) {
|
if (replaceRange) {
|
||||||
this.range = {
|
this.range = {
|
||||||
inserting: new vscode.Range(replaceRange.start, this.position),
|
inserting: new vscode.Range(replaceRange.start, this.position),
|
||||||
|
@ -178,23 +184,21 @@ class MyCompletionItem extends vscode.CompletionItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getReplaceRange(line: string) {
|
private getFuzzyWordRange() {
|
||||||
const wordRange = this.document.getWordRangeAtPosition(this.position);
|
if (this.completionContext.useFuzzyWordRangeLogic) {
|
||||||
let replaceRange = wordRange;
|
|
||||||
|
|
||||||
// Try getting longer, prefix based range for completions that span words
|
// Try getting longer, prefix based range for completions that span words
|
||||||
const text = line.slice(Math.max(0, this.position.character - this.label.length), this.position.character).toLowerCase();
|
const text = this.completionContext.line.slice(Math.max(0, this.position.character - this.label.length), this.position.character).toLowerCase();
|
||||||
const entryName = this.label.toLowerCase();
|
const entryName = this.label.toLowerCase();
|
||||||
for (let i = entryName.length; i >= 0; --i) {
|
for (let i = entryName.length; i >= 0; --i) {
|
||||||
if (text.endsWith(entryName.substr(0, i)) && (!wordRange || wordRange.start.character > this.position.character - i)) {
|
if (text.endsWith(entryName.substr(0, i)) && (!this.completionContext.wordRange || this.completionContext.wordRange.start.character > this.position.character - i)) {
|
||||||
replaceRange = new vscode.Range(
|
return new vscode.Range(
|
||||||
new vscode.Position(this.position.line, Math.max(0, this.position.character - i)),
|
new vscode.Position(this.position.line, Math.max(0, this.position.character - i)),
|
||||||
this.position);
|
this.position);
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return replaceRange;
|
return this.completionContext.wordRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static convertKind(kind: string): vscode.CompletionItemKind {
|
private static convertKind(kind: string): vscode.CompletionItemKind {
|
||||||
|
@ -498,15 +502,20 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider
|
||||||
metadata = response.metadata;
|
metadata = response.metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const wordRange = document.getWordRangeAtPosition(position);
|
||||||
const isInValidCommitCharacterContext = this.isInValidCommitCharacterContext(document, position);
|
const isInValidCommitCharacterContext = this.isInValidCommitCharacterContext(document, position);
|
||||||
const items = entries
|
const items = entries
|
||||||
.filter(entry => !shouldExcludeCompletionEntry(entry, completionConfiguration))
|
.filter(entry => !shouldExcludeCompletionEntry(entry, completionConfiguration))
|
||||||
.map(entry => new MyCompletionItem(position, document, line.text, entry, completionConfiguration.useCodeSnippetsOnMethodSuggest, {
|
.map(entry => new MyCompletionItem(position, document, entry, {
|
||||||
isNewIdentifierLocation,
|
isNewIdentifierLocation,
|
||||||
isMemberCompletion,
|
isMemberCompletion,
|
||||||
dotAccessorContext,
|
dotAccessorContext,
|
||||||
isInValidCommitCharacterContext,
|
isInValidCommitCharacterContext,
|
||||||
enableCallCompletions: !completionConfiguration.useCodeSnippetsOnMethodSuggest
|
enableCallCompletions: !completionConfiguration.useCodeSnippetsOnMethodSuggest,
|
||||||
|
wordRange,
|
||||||
|
line: line.text,
|
||||||
|
useCodeSnippetsOnMethodSuggest: completionConfiguration.useCodeSnippetsOnMethodSuggest,
|
||||||
|
useFuzzyWordRangeLogic: this.client.apiVersion.lt(API.v390),
|
||||||
}, metadata));
|
}, metadata));
|
||||||
return new vscode.CompletionList(items, isIncomplete);
|
return new vscode.CompletionList(items, isIncomplete);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue