Skip to content

Commit

Permalink
Pre-support for backeted property completions in js/ts
Browse files Browse the repository at this point in the history
Requires a build of TS with microsoft/TypeScript#20547 Fixes #36429

Also relaxes the matching logic for suggestion items with filter texts
  • Loading branch information
mjbvz committed Jan 9, 2018
1 parent 6195524 commit 5fe3f97
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 11 deletions.
25 changes: 20 additions & 5 deletions extensions/typescript/src/features/completionItemProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ class MyCompletionItem extends CompletionItem {
this.range = tsTextSpanToVsRange(tsEntry.replacementSpan);
}

if (typeof (tsEntry as any).insertText === 'string') {
this.insertText = (tsEntry as any).insertText as string;

if (tsEntry.replacementSpan) {
this.range = tsTextSpanToVsRange(tsEntry.replacementSpan);
if (this.insertText[0] === '[') { // o.x -> o['x']
this.filterText = '.' + this.label;
}
}
}

if (tsEntry.kindModifiers.match(/\boptional\b/)) {
this.insertText = this.label;
this.filterText = this.label;
Expand Down Expand Up @@ -275,8 +286,9 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
try {
const args: Proto.CompletionsRequestArgs = {
...vsPositionToTsFileLocation(file, position),
includeExternalModuleExports: config.autoImportSuggestions
};
includeExternalModuleExports: config.autoImportSuggestions,
includeInsertTextCompletions: true
} as Proto.CompletionsRequestArgs;
const msg = await this.client.execute('completions', args, token);
// This info has to come from the tsserver. See https://github.com/Microsoft/TypeScript/issues/2831
// let isMemberCompletion = false;
Expand Down Expand Up @@ -402,7 +414,7 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
if (detail && item.useCodeSnippet) {
const shouldCompleteFunction = await this.isValidFunctionCompletionContext(filepath, item.position);
if (shouldCompleteFunction) {
item.insertText = this.snippetForFunctionCall(detail);
item.insertText = this.snippetForFunctionCall(item, detail);
}
return item;
}
Expand Down Expand Up @@ -430,12 +442,15 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
}
}

private snippetForFunctionCall(detail: Proto.CompletionEntryDetails): SnippetString {
private snippetForFunctionCall(
item: CompletionItem,
detail: Proto.CompletionEntryDetails
): SnippetString {
let hasOptionalParameters = false;
let hasAddedParameters = false;

const snippet = new SnippetString();
snippet.appendText(detail.name);
snippet.appendText(item.label || item.insertText as string);
snippet.appendText('(');

let parenCount = 0;
Expand Down
16 changes: 16 additions & 0 deletions src/vs/base/common/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,22 @@ export function matchesFuzzy(word: string, wordToMatchAgainst: string, enableSep
return enableSeparateSubstringMatching ? fuzzySeparateFilter(word, wordToMatchAgainst) : fuzzyContiguousFilter(word, wordToMatchAgainst);
}

export function skipScore(pattern: string, word: string, patternMaxWhitespaceIgnore?: number): [number, number[]] {
pattern = pattern.toLowerCase();
word = word.toLowerCase();

const matches: number[] = [];
let idx = 0;
for (let pos = 0; pos < pattern.length; ++pos) {
const thisIdx = word.indexOf(pattern.charAt(pos), idx);
if (thisIdx >= 0) {
matches.push(thisIdx);
idx = thisIdx + 1;
}
}
return [matches.length, matches];
}

//#region --- fuzzyScore ---

export function createMatches(position: number[]): IMatch[] {
Expand Down
9 changes: 3 additions & 6 deletions src/vs/editor/contrib/suggest/completionModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

'use strict';

import { fuzzyScore, fuzzyScoreGracefulAggressive } from 'vs/base/common/filters';
import { fuzzyScore, fuzzyScoreGracefulAggressive, skipScore } from 'vs/base/common/filters';
import { ISuggestSupport, ISuggestResult } from 'vs/editor/common/modes';
import { ISuggestionItem, SnippetConfig } from './suggest';
import { isDisposable } from 'vs/base/common/lifecycle';
Expand Down Expand Up @@ -185,11 +185,8 @@ export class CompletionModel {
continue;
}
item.score = match[0];
item.matches = [];
match = scoreFn(word, suggestion.label, suggestion.overwriteBefore);
if (match) {
item.matches = match[1];
}
item.matches = skipScore(word, suggestion.label)[1];

} else {
// by default match `word` against the `label`
let match = scoreFn(word, suggestion.label, suggestion.overwriteBefore);
Expand Down

0 comments on commit 5fe3f97

Please sign in to comment.