Improve class member snippet completions and keyword completions interaction (#52525)

This commit is contained in:
Gabriela Araujo Britto 2023-05-17 19:14:34 -03:00 committed by GitHub
parent b14264a2eb
commit 24ac9e75c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 780 additions and 522 deletions

View File

@ -125,6 +125,7 @@ import {
getSyntheticLeadingComments,
getSyntheticTrailingComments,
getTextOfIdentifierOrLiteral,
HasDecorators,
hasInvalidEscape,
HasModifiers,
hasProperty,
@ -1023,6 +1024,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
liftToBlock,
mergeLexicalEnvironment,
updateModifiers,
updateModifierLike,
};
forEach(nodeFactoryPatchers, fn => fn(factory));
@ -6989,6 +6991,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
Debug.assertNever(node);
}
function updateModifierLike<T extends HasModifiers & HasDecorators>(node: T, modifiers: readonly ModifierLike[]): T;
function updateModifierLike(node: HasModifiers & HasDecorators, modifierArray: readonly ModifierLike[]) {
return isParameter(node) ? updateParameterDeclaration(node, modifierArray, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) :
isPropertyDeclaration(node) ? updatePropertyDeclaration(node, modifierArray, node.name, node.questionToken ?? node.exclamationToken, node.type, node.initializer) :
isMethodDeclaration(node) ? updateMethodDeclaration(node, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) :
isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.type, node.body) :
isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.body) :
isClassExpression(node) ? updateClassExpression(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) :
isClassDeclaration(node) ? updateClassDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) :
Debug.assertNever(node);
}
function asNodeArray<T extends Node>(array: readonly T[]): NodeArray<T>;
function asNodeArray<T extends Node>(array: readonly T[] | undefined): NodeArray<T> | undefined;
function asNodeArray<T extends Node>(array: readonly T[] | undefined): NodeArray<T> | undefined {

View File

@ -1335,7 +1335,7 @@ export type HasIllegalDecorators =
;
// NOTE: Changing the following list requires changes to:
// - `canHaveModifiers` in factory/utilities.ts
// - `canHaveModifiers` in factory/utilitiesPublic.ts
// - `updateModifiers` in factory/nodeFactory.ts
export type HasModifiers =
| TypeParameterDeclaration
@ -9057,6 +9057,7 @@ export interface NodeFactory {
*/
cloneNode<T extends Node | undefined>(node: T): T;
/** @internal */ updateModifiers<T extends HasModifiers>(node: T, modifiers: readonly Modifier[] | ModifierFlags | undefined): T;
/** @internal */ updateModifierLike<T extends HasModifiers & HasDecorators>(node: T, modifierLike: readonly ModifierLike[] | undefined): T;
}
/** @internal */

View File

@ -1009,8 +1009,18 @@ export class TestState {
assert.equal<boolean | undefined>(actual.isPackageJsonImport, expected.isPackageJsonImport, `At entry ${actual.name}: Expected 'isPackageJsonImport' properties to match`);
}
assert.equal(actual.labelDetails?.description, expected.labelDetails?.description, `At entry ${actual.name}: Expected 'labelDetails.description' properties to match`);
assert.equal(actual.labelDetails?.detail, expected.labelDetails?.detail, `At entry ${actual.name}: Expected 'labelDetails.detail' properties to match`);
assert.equal(
actual.filterText,
expected.filterText,
`At entry ${actual.name}: Completion 'filterText' not match: ${showTextDiff(expected.filterText || "", actual.filterText || "")}`);
assert.equal(
actual.labelDetails?.description,
expected.labelDetails?.description,
`At entry ${actual.name}: Completion 'labelDetails.description' did not match: ${showTextDiff(expected.labelDetails?.description || "", actual.labelDetails?.description || "")}`);
assert.equal(
actual.labelDetails?.detail,
expected.labelDetails?.detail,
`At entry ${actual.name}: Completion 'labelDetails.detail' did not match: ${showTextDiff(expected.labelDetails?.detail || "", actual.labelDetails?.detail || "")}`);
assert.equal(actual.hasAction, expected.hasAction, `At entry ${actual.name}: Expected 'hasAction' properties to match`);
assert.equal(actual.isRecommended, expected.isRecommended, `At entry ${actual.name}: Expected 'isRecommended' properties to match'`);
assert.equal(actual.isSnippet, expected.isSnippet, `At entry ${actual.name}: Expected 'isSnippet' properties to match`);

View File

@ -1738,6 +1738,7 @@ export interface ExpectedCompletionEntryObject {
readonly name: string;
readonly source?: string;
readonly insertText?: string;
readonly filterText?: string;
readonly replacementSpan?: FourSlash.Range;
readonly hasAction?: boolean; // If not specified, will assert that this is false.
readonly isRecommended?: boolean; // If not specified, will assert that this is false.

View File

@ -2335,6 +2335,11 @@ export interface CompletionEntry {
* coupled with `replacementSpan` to replace a dotted access with a bracket access.
*/
insertText?: string;
/**
* A string that should be used when filtering a set of
* completion items.
*/
filterText?: string;
/**
* `insertText` should be interpreted as a snippet if true.
*/

View File

@ -2267,6 +2267,7 @@ export class Session<TMessage = string> implements EventSender {
kindModifiers,
sortText,
insertText,
filterText,
replacementSpan,
hasAction,
source,
@ -2285,6 +2286,7 @@ export class Session<TMessage = string> implements EventSender {
kindModifiers,
sortText,
insertText,
filterText,
replacementSpan: convertedSpan,
isSnippet,
hasAction: hasAction || undefined,

View File

@ -194,7 +194,8 @@ export function addNewNodeForMemberSymbol(
const kind = declaration?.kind ?? SyntaxKind.PropertySignature;
const declarationName = getSynthesizedDeepClone(getNameOfDeclaration(declaration), /*includeTrivia*/ false) as PropertyName;
const effectiveModifierFlags = declaration ? getEffectiveModifierFlags(declaration) : ModifierFlags.None;
let modifierFlags =
let modifierFlags = effectiveModifierFlags & ModifierFlags.Static;
modifierFlags |=
effectiveModifierFlags & ModifierFlags.Public ? ModifierFlags.Public :
effectiveModifierFlags & ModifierFlags.Protected ? ModifierFlags.Protected :
ModifierFlags.None;

View File

@ -7,6 +7,7 @@ import {
BindingPattern,
BreakOrContinueStatement,
CancellationToken,
canHaveDecorators,
canUsePropertyAccess,
CaseBlock,
cast,
@ -44,6 +45,7 @@ import {
createTextSpanFromRange,
Debug,
Declaration,
Decorator,
Diagnostics,
diagnosticToString,
displayPart,
@ -91,6 +93,7 @@ import {
getLineAndCharacterOfPosition,
getLineStartPositionForPosition,
getLocalSymbolForExportDefault,
getModifiers,
getNameOfDeclaration,
getNameTable,
getNewLineCharacter,
@ -145,6 +148,7 @@ import {
isConstructorDeclaration,
isContextualKeyword,
isDeclarationName,
isDecorator,
isDeprecatedDeclaration,
isEntityName,
isEnumMember,
@ -276,6 +280,7 @@ import {
memoizeOne,
MethodDeclaration,
ModifierFlags,
ModifierLike,
modifiersToFlags,
ModifierSyntaxKind,
modifierToFlag,
@ -1609,6 +1614,7 @@ function createCompletionEntry(
includeSymbol: boolean
): CompletionEntry | undefined {
let insertText: string | undefined;
let filterText: string | undefined;
let replacementSpan = getReplacementSpanForContextToken(replacementToken);
let data: CompletionEntryData | undefined;
let isSnippet: true | undefined;
@ -1682,12 +1688,16 @@ function createCompletionEntry(
completionKind === CompletionKind.MemberLike &&
isClassLikeMemberCompletion(symbol, location, sourceFile)) {
let importAdder;
({ insertText, isSnippet, importAdder, replacementSpan } =
getEntryForMemberCompletion(host, program, options, preferences, name, symbol, location, position, contextToken, formatContext));
sortText = SortText.ClassMemberSnippets; // sortText has to be lower priority than the sortText for keywords. See #47852.
if (importAdder?.hasFixes()) {
hasAction = true;
source = CompletionSource.ClassMemberSnippet;
const memberCompletionEntry = getEntryForMemberCompletion(host, program, options, preferences, name, symbol, location, position, contextToken, formatContext);
if (memberCompletionEntry) {
({ insertText, filterText, isSnippet, importAdder } = memberCompletionEntry);
if (importAdder?.hasFixes()) {
hasAction = true;
source = CompletionSource.ClassMemberSnippet;
}
}
else {
return undefined; // Skip this entry
}
}
@ -1755,6 +1765,7 @@ function createCompletionEntry(
hasAction: hasAction ? true : undefined,
isRecommended: isRecommendedCompletionMatch(symbol, recommendedCompletion, typeChecker) || undefined,
insertText,
filterText,
replacementSpan,
sourceDisplay,
labelDetails,
@ -1826,15 +1837,15 @@ function getEntryForMemberCompletion(
position: number,
contextToken: Node | undefined,
formatContext: formatting.FormatContext | undefined,
): { insertText: string, isSnippet?: true, importAdder?: codefix.ImportAdder, replacementSpan?: TextSpan } {
): { insertText: string, filterText?: string, isSnippet?: true, importAdder?: codefix.ImportAdder, eraseRange?: TextRange } | undefined {
const classLikeDeclaration = findAncestor(location, isClassLike);
if (!classLikeDeclaration) {
return { insertText: name };
return undefined; // This should never happen.
}
let isSnippet: true | undefined;
let replacementSpan: TextSpan | undefined;
let insertText: string = name;
const filterText: string = name;
const checker = program.getTypeChecker();
const sourceFile = location.getSourceFile();
@ -1863,11 +1874,11 @@ function getEntryForMemberCompletion(
}
let modifiers = ModifierFlags.None;
const { modifiers: presentModifiers, range: eraseRange, decorators: presentDecorators } = getPresentModifiers(contextToken, sourceFile, position);
// Whether the suggested member should be abstract.
// e.g. in `abstract class C { abstract | }`, we should offer abstract method signatures at position `|`.
const { modifiers: presentModifiers, span: modifiersSpan } = getPresentModifiers(contextToken, sourceFile, position);
const isAbstract = !!(presentModifiers & ModifierFlags.Abstract);
const completionNodes: Node[] = [];
const isAbstract = presentModifiers & ModifierFlags.Abstract && classLikeDeclaration.modifierFlagsCache & ModifierFlags.Abstract;
let completionNodes: codefix.AddNode[] = [];
codefix.addNewNodeForMemberSymbol(
symbol,
classLikeDeclaration,
@ -1896,20 +1907,49 @@ function getEntryForMemberCompletion(
// This is needed when we have overloaded signatures,
// so this callback will be called for multiple nodes/signatures,
// and we need to make sure the modifiers are uniform for all nodes/signatures.
modifiers = node.modifierFlagsCache | requiredModifiers | presentModifiers;
modifiers = node.modifierFlagsCache | requiredModifiers;
}
node = factory.updateModifiers(node, modifiers);
completionNodes.push(node);
},
body,
codefix.PreserveOptionalFlags.Property,
isAbstract);
!!isAbstract);
if (completionNodes.length) {
const isMethod = symbol.flags & SymbolFlags.Method;
let allowedModifiers = modifiers | ModifierFlags.Override | ModifierFlags.Public;
if (!isMethod) {
allowedModifiers |= ModifierFlags.Ambient | ModifierFlags.Readonly;
}
else {
allowedModifiers |= ModifierFlags.Async;
}
const allowedAndPresent = presentModifiers & allowedModifiers;
if (presentModifiers & (~allowedModifiers)) {
return undefined; // This completion entry will be filtered out.
}
// If the original member is protected, we allow it to change to public.
if (modifiers & ModifierFlags.Protected && allowedAndPresent & ModifierFlags.Public) {
modifiers &= ~ModifierFlags.Protected;
}
// `public` modifier is optional and can be dropped.
if (allowedAndPresent !== ModifierFlags.None && !(allowedAndPresent & ModifierFlags.Public)) {
modifiers &= ~ModifierFlags.Public;
}
modifiers |= allowedAndPresent;
completionNodes = completionNodes.map(node => factory.updateModifiers(node, modifiers));
// Add back the decorators that were already present.
if (presentDecorators?.length) {
const lastNode = completionNodes[completionNodes.length - 1];
if (canHaveDecorators(lastNode)) {
completionNodes[completionNodes.length - 1] = factory.updateModifierLike(lastNode, (presentDecorators as ModifierLike[]).concat(getModifiers(lastNode) || []));
}
}
const format = ListFormat.MultiLine | ListFormat.NoTrailingNewLine;
replacementSpan = modifiersSpan;
// If we have access to formatting settings, we print the nodes using the emitter,
// and then format the printed text.
// If we have access to formatting settings, we print the nodes using the emitter,
// and then format the printed text.
if (formatContext) {
insertText = printer.printAndFormatSnippetList(
format,
@ -1925,21 +1965,22 @@ function getEntryForMemberCompletion(
}
}
return { insertText, isSnippet, importAdder, replacementSpan };
return { insertText, filterText, isSnippet, importAdder, eraseRange };
}
function getPresentModifiers(
contextToken: Node | undefined,
sourceFile: SourceFile,
position: number): { modifiers: ModifierFlags, span?: TextSpan } {
position: number): { modifiers: ModifierFlags, decorators?: Decorator[], range?: TextRange } {
if (!contextToken ||
getLineAndCharacterOfPosition(sourceFile, position).line
> getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line) {
return { modifiers: ModifierFlags.None };
}
let modifiers = ModifierFlags.None;
let span;
let decorators: Decorator[] | undefined;
let contextMod;
const range: TextRange = { pos: position, end: position };
/*
Cases supported:
In
@ -1959,15 +2000,19 @@ function getPresentModifiers(
`location.parent` is property declaration ``protected override m``,
`location.parent.parent` is class declaration ``class C { ... }``.
*/
if (contextMod = isModifierLike(contextToken)) {
modifiers |= modifierToFlag(contextMod);
span = createTextSpanFromNode(contextToken);
}
if (isPropertyDeclaration(contextToken.parent)) {
if (isPropertyDeclaration(contextToken.parent) && contextToken.parent.modifiers) {
modifiers |= modifiersToFlags(contextToken.parent.modifiers) & ModifierFlags.Modifier;
span = createTextSpanFromNode(contextToken.parent);
decorators = contextToken.parent.modifiers.filter(isDecorator) || [];
range.pos = Math.min(range.pos, contextToken.parent.modifiers.pos);
}
return { modifiers, span };
if (contextMod = isModifierLike(contextToken)) {
const contextModifierFlag = modifierToFlag(contextMod);
if (!(modifiers & contextModifierFlag)) {
modifiers |= contextModifierFlag;
range.pos = Math.min(range.pos, contextToken.pos);
}
}
return { modifiers, decorators, range: range.pos !== position ? range : undefined };
}
function isModifierLike(node: Node): ModifierSyntaxKind | undefined {
@ -2770,7 +2815,7 @@ function getCompletionEntryCodeActionsAndSourceDisplay(
}
if (source === CompletionSource.ClassMemberSnippet) {
const { importAdder } = getEntryForMemberCompletion(
const { importAdder, eraseRange } = getEntryForMemberCompletion(
host,
program,
compilerOptions,
@ -2780,11 +2825,18 @@ function getCompletionEntryCodeActionsAndSourceDisplay(
location,
position,
contextToken,
formatContext);
if (importAdder) {
formatContext)!;
if (importAdder || eraseRange) {
const changes = textChanges.ChangeTracker.with(
{ host, formatContext, preferences },
importAdder.writeFixes);
tracker => {
if (importAdder) {
importAdder.writeFixes(tracker);
}
if (eraseRange) {
tracker.deleteRange(sourceFile, eraseRange);
}
});
return {
sourceDisplay: undefined,
codeActions: [{

View File

@ -1406,6 +1406,7 @@ export interface CompletionEntry {
kindModifiers?: string; // see ScriptElementKindModifier, comma separated
sortText: string;
insertText?: string;
filterText?: string;
isSnippet?: true;
/**
* An optional span that indicates the text to be replaced by this completion item.

View File

@ -1829,6 +1829,11 @@ declare namespace ts {
* coupled with `replacementSpan` to replace a dotted access with a bracket access.
*/
insertText?: string;
/**
* A string that should be used when filtering a set of
* completion items.
*/
filterText?: string;
/**
* `insertText` should be interpreted as a snippet if true.
*/
@ -10801,6 +10806,7 @@ declare namespace ts {
kindModifiers?: string;
sortText: string;
insertText?: string;
filterText?: string;
isSnippet?: true;
/**
* An optional span that indicates the text to be replaced by this completion item.

View File

@ -6838,6 +6838,7 @@ declare namespace ts {
kindModifiers?: string;
sortText: string;
insertText?: string;
filterText?: string;
isSnippet?: true;
/**
* An optional span that indicates the text to be replaced by this completion item.

View File

@ -8,6 +8,7 @@
//
// ^
// | ----------------------------------------------------------------------
// | (method) I.method(): void
// | abstract
// | accessor
// | async
@ -21,7 +22,6 @@
// | readonly
// | set
// | static
// | (method) I.method(): void
// | ----------------------------------------------------------------------
// }
@ -38,6 +38,65 @@
"isMemberCompletion": true,
"isNewIdentifierLocation": true,
"entries": [
{
"name": "method",
"kind": "method",
"kindModifiers": "",
"sortText": "11",
"insertText": "method(): void {\n}",
"filterText": "method",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "method",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "I",
"kind": "interfaceName"
},
{
"text": ".",
"kind": "punctuation"
},
{
"text": "method",
"kind": "methodName"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "void",
"kind": "keyword"
}
],
"documentation": []
},
{
"name": "abstract",
"kind": "keyword",
@ -193,64 +252,6 @@
"kind": "keyword"
}
]
},
{
"name": "method",
"kind": "method",
"kindModifiers": "",
"sortText": "17",
"insertText": "method(): void {\n}",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "method",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "I",
"kind": "interfaceName"
},
{
"text": ".",
"kind": "punctuation"
},
{
"text": "method",
"kind": "methodName"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "void",
"kind": "keyword"
}
],
"documentation": []
}
]
}

View File

@ -16,6 +16,7 @@
//
// ^
// | ----------------------------------------------------------------------
// | (method) Observable<any>.pipe(): Observable<any> (+10 overloads)
// | abstract
// | accessor
// | async
@ -29,7 +30,6 @@
// | readonly
// | set
// | static
// | (method) Observable<any>.pipe(): Observable<any> (+10 overloads)
// | ----------------------------------------------------------------------
// }
@ -46,6 +46,118 @@
"isMemberCompletion": true,
"isNewIdentifierLocation": true,
"entries": [
{
"name": "pipe",
"kind": "method",
"kindModifiers": "",
"sortText": "11",
"insertText": "pipe(): Observable<any>;\npipe<A>(): Observable<A>;\npipe<A, B>(): Observable<B>;\npipe<A, B, C>(): Observable<C>;\npipe<A, B, C, D>(): Observable<D>;\npipe<A, B, C, D, E>(): Observable<E>;\npipe<A, B, C, D, E, F>(): Observable<F>;\npipe<A, B, C, D, E, F, G>(): Observable<G>;\npipe<A, B, C, D, E, F, G, H>(): Observable<H>;\npipe<A, B, C, D, E, F, G, H, I>(): Observable<I>;\npipe<A, B, C, D, E, F, G, H, I>(): Observable<unknown>;\npipe(): Observable<any> | Observable<A> | Observable<B> | Observable<C> | Observable<D> | Observable<E> | Observable<F> | Observable<G> | Observable<H> | Observable<I> | Observable<unknown> {\n $0\n}",
"filterText": "pipe",
"isSnippet": true,
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "method",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "Observable",
"kind": "className"
},
{
"text": "<",
"kind": "punctuation"
},
{
"text": "any",
"kind": "keyword"
},
{
"text": ">",
"kind": "punctuation"
},
{
"text": ".",
"kind": "punctuation"
},
{
"text": "pipe",
"kind": "methodName"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "Observable",
"kind": "className"
},
{
"text": "<",
"kind": "punctuation"
},
{
"text": "any",
"kind": "keyword"
},
{
"text": ">",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": "+",
"kind": "operator"
},
{
"text": "10",
"kind": "numericLiteral"
},
{
"text": " ",
"kind": "space"
},
{
"text": "overloads",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
}
],
"documentation": []
},
{
"name": "abstract",
"kind": "keyword",
@ -201,117 +313,6 @@
"kind": "keyword"
}
]
},
{
"name": "pipe",
"kind": "method",
"kindModifiers": "",
"sortText": "17",
"insertText": "pipe(): Observable<any>;\npipe<A>(): Observable<A>;\npipe<A, B>(): Observable<B>;\npipe<A, B, C>(): Observable<C>;\npipe<A, B, C, D>(): Observable<D>;\npipe<A, B, C, D, E>(): Observable<E>;\npipe<A, B, C, D, E, F>(): Observable<F>;\npipe<A, B, C, D, E, F, G>(): Observable<G>;\npipe<A, B, C, D, E, F, G, H>(): Observable<H>;\npipe<A, B, C, D, E, F, G, H, I>(): Observable<I>;\npipe<A, B, C, D, E, F, G, H, I>(): Observable<unknown>;\npipe(): Observable<any> | Observable<A> | Observable<B> | Observable<C> | Observable<D> | Observable<E> | Observable<F> | Observable<G> | Observable<H> | Observable<I> | Observable<unknown> {\n $0\n}",
"isSnippet": true,
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "method",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "Observable",
"kind": "className"
},
{
"text": "<",
"kind": "punctuation"
},
{
"text": "any",
"kind": "keyword"
},
{
"text": ">",
"kind": "punctuation"
},
{
"text": ".",
"kind": "punctuation"
},
{
"text": "pipe",
"kind": "methodName"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "Observable",
"kind": "className"
},
{
"text": "<",
"kind": "punctuation"
},
{
"text": "any",
"kind": "keyword"
},
{
"text": ">",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": "+",
"kind": "operator"
},
{
"text": "10",
"kind": "numericLiteral"
},
{
"text": " ",
"kind": "space"
},
{
"text": "overloads",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
}
],
"documentation": []
}
]
}

View File

@ -7,6 +7,7 @@
//
// ^
// | ----------------------------------------------------------------------
// | (property) Base[SOME_CONSTANT]: boolean
// | abstract
// | accessor
// | async
@ -20,7 +21,6 @@
// | readonly
// | set
// | static
// | (property) Base[SOME_CONSTANT]: boolean
// | ----------------------------------------------------------------------
// }
@ -37,6 +37,62 @@
"isMemberCompletion": true,
"isNewIdentifierLocation": true,
"entries": [
{
"name": "[SOME_CONSTANT]",
"kind": "property",
"kindModifiers": "",
"sortText": "11",
"insertText": "[SOME_CONSTANT]: boolean;",
"filterText": "[SOME_CONSTANT]",
"isSnippet": true,
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "Base",
"kind": "className"
},
{
"text": "[",
"kind": "punctuation"
},
{
"text": "SOME_CONSTANT",
"kind": "propertyName"
},
{
"text": "]",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "boolean",
"kind": "keyword"
}
],
"documentation": []
},
{
"name": "abstract",
"kind": "keyword",
@ -192,61 +248,6 @@
"kind": "keyword"
}
]
},
{
"name": "[SOME_CONSTANT]",
"kind": "property",
"kindModifiers": "",
"sortText": "17",
"insertText": "[SOME_CONSTANT]: boolean;",
"isSnippet": true,
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "Base",
"kind": "className"
},
{
"text": "[",
"kind": "punctuation"
},
{
"text": "SOME_CONSTANT",
"kind": "propertyName"
},
{
"text": "]",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "boolean",
"kind": "keyword"
}
],
"documentation": []
}
]
}

View File

@ -7,6 +7,7 @@
//
// ^
// | ----------------------------------------------------------------------
// | (property) B.foo: any
// | abstract
// | accessor
// | async
@ -20,7 +21,6 @@
// | readonly
// | set
// | static
// | (property) B.foo: any
// | ----------------------------------------------------------------------
// }
@ -37,6 +37,57 @@
"isMemberCompletion": true,
"isNewIdentifierLocation": true,
"entries": [
{
"name": "foo",
"kind": "property",
"kindModifiers": "declare",
"sortText": "11",
"insertText": "get foo(): any {\n}\nset foo(value: any) {\n}",
"filterText": "foo",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "B",
"kind": "className"
},
{
"text": ".",
"kind": "punctuation"
},
{
"text": "foo",
"kind": "propertyName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "any",
"kind": "keyword"
}
],
"documentation": []
},
{
"name": "abstract",
"kind": "keyword",
@ -192,56 +243,6 @@
"kind": "keyword"
}
]
},
{
"name": "foo",
"kind": "property",
"kindModifiers": "declare",
"sortText": "17",
"insertText": "get foo(): any {\n}\nset foo(value: any) {\n}",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "B",
"kind": "className"
},
{
"text": ".",
"kind": "punctuation"
},
{
"text": "foo",
"kind": "propertyName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "any",
"kind": "keyword"
}
],
"documentation": []
}
]
}

View File

@ -7,6 +7,7 @@
//
// ^
// | ----------------------------------------------------------------------
// | (property) B.foo: any
// | abstract
// | accessor
// | async
@ -20,7 +21,6 @@
// | readonly
// | set
// | static
// | (property) B.foo: any
// | ----------------------------------------------------------------------
// }
@ -37,6 +37,57 @@
"isMemberCompletion": true,
"isNewIdentifierLocation": true,
"entries": [
{
"name": "foo",
"kind": "property",
"kindModifiers": "declare",
"sortText": "11",
"insertText": "set foo(value: any) {\n}\nget foo(): any {\n}",
"filterText": "foo",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "B",
"kind": "className"
},
{
"text": ".",
"kind": "punctuation"
},
{
"text": "foo",
"kind": "propertyName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "any",
"kind": "keyword"
}
],
"documentation": []
},
{
"name": "abstract",
"kind": "keyword",
@ -192,56 +243,6 @@
"kind": "keyword"
}
]
},
{
"name": "foo",
"kind": "property",
"kindModifiers": "declare",
"sortText": "17",
"insertText": "set foo(value: any) {\n}\nget foo(): any {\n}",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "B",
"kind": "className"
},
{
"text": ".",
"kind": "punctuation"
},
{
"text": "foo",
"kind": "propertyName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "any",
"kind": "keyword"
}
],
"documentation": []
}
]
}

View File

@ -280,6 +280,16 @@ Info seq [hh:mm:ss:mss] response:
}
},
"entries": [
{
"name": "render",
"kind": "method",
"kindModifiers": "abstract",
"sortText": "11",
"insertText": "render(): Element {\n}",
"filterText": "render",
"hasAction": true,
"source": "ClassMemberSnippet/"
},
{
"name": "abstract",
"kind": "keyword",
@ -357,15 +367,6 @@ Info seq [hh:mm:ss:mss] response:
"kind": "keyword",
"kindModifiers": "",
"sortText": "15"
},
{
"name": "render",
"kind": "method",
"kindModifiers": "abstract",
"sortText": "17",
"insertText": "render(): Element {\n}",
"hasAction": true,
"source": "ClassMemberSnippet/"
}
]
},
@ -516,6 +517,16 @@ Info seq [hh:mm:ss:mss] response:
}
},
"entries": [
{
"name": "render2",
"kind": "method",
"kindModifiers": "abstract",
"sortText": "11",
"insertText": "render2(): Element {\n}",
"filterText": "render2",
"hasAction": true,
"source": "ClassMemberSnippet/"
},
{
"name": "abstract",
"kind": "keyword",
@ -593,15 +604,6 @@ Info seq [hh:mm:ss:mss] response:
"kind": "keyword",
"kindModifiers": "",
"sortText": "15"
},
{
"name": "render2",
"kind": "method",
"kindModifiers": "abstract",
"sortText": "17",
"insertText": "render2(): Element {\n}",
"hasAction": true,
"source": "ClassMemberSnippet/"
}
]
},

View File

@ -93,7 +93,7 @@
////
////class HSub extends HBase {
//// /*h1*/
//// [|static|] /*h2*/
//// static /*h2*/
////}
// @Filename: i.ts
@ -123,8 +123,9 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "foo(param1: string, param2: boolean): Promise<void> {\n}",
filterText: "foo",
}
],
});
@ -140,8 +141,9 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "foo(a: string, b: string): string {\n}",
filterText: "foo",
}
],
});
@ -157,8 +159,9 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "foo(a: string): string {\n}",
filterText: "foo",
}
],
});
@ -174,8 +177,9 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "foo(a: string): string {\n}",
filterText: "foo",
}
],
});
@ -191,8 +195,9 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "foo(a: string): string {\n}",
filterText: "foo",
}
],
});
@ -208,8 +213,9 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "foo(a: string): string {\n}",
filterText: "foo",
}
],
});
@ -225,12 +231,13 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText:
`foo(a: string): string;
foo(a: undefined, b: number): string;
foo(a: unknown, b?: unknown): string {
}`,
filterText: "foo",
}
],
});
@ -245,6 +252,7 @@ verify.completions({
},
excludes: "met",
});
verify.completions({
marker: "h2",
isNewIdentifierLocation: true,
@ -256,9 +264,9 @@ verify.completions({
includes: [
{
name: "met",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[0],
sortText: completion.SortText.LocationPriority,
insertText: "static met(n: number): number {\n}",
filterText: "met",
}
],
});
@ -274,13 +282,15 @@ verify.completions({
includes: [
{
name: "met",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "met<T>(t: T): T {\n}",
filterText: "met"
},
{
name: "metcons",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "metcons<T extends string | number>(t: T): T {\n}",
filterText: "metcons"
}
],
});

View File

@ -24,8 +24,9 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "override foo(a: string): void {\n}",
filterText: "foo"
}
],
});

View File

@ -25,24 +25,27 @@ verify.completions({
includes: [
{
name: "a",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "a: string;",
filterText: "a",
},
{
name: "b",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText:
`b(a: string): void {
}`,
filterText: "b",
},
{
name: "c",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText:
`c(a: string): string;
c(a: number): number;
c(a: unknown): string | number {
}`,
filterText: "c",
},
],
});

View File

@ -31,24 +31,27 @@ verify.completions({
includes: [
{
name: "a",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "a: string",
filterText: "a"
},
{
name: "b",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText:
`b(a: string): void {
}`,
filterText: "b"
},
{
name: "c",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText:
`c(a: string): string
c(a: number): number
c(a: unknown): string | number {
}`,
filterText: "c"
},
],
});

View File

@ -10,11 +10,11 @@
////}
////
////abstract class B extends A {
//// [|abstract|] /*a*/
//// abstract /*a*/
////}
////
////abstract class B1 extends A {
//// [|abstract override|] /*b*/
//// abstract override /*b*/
////}
verify.completions({
@ -28,9 +28,9 @@ verify.completions({
includes: [
{
name: "P",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[0],
insertText: "public abstract get P(): string;",
sortText: completion.SortText.LocationPriority,
insertText: "abstract get P(): string;",
filterText: "P",
},
],
});
@ -46,9 +46,9 @@ verify.completions({
includes: [
{
name: "P",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[1],
insertText: "public abstract override get P(): string;",
sortText: completion.SortText.LocationPriority,
insertText: "abstract override get P(): string;",
filterText: "P",
},
],
});

View File

@ -21,11 +21,12 @@ verify.completions({
includeCompletionsWithClassMemberSnippets: true,
},
exact: [
...completion.classElementKeywords,
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "protected foo(): void {\n}",
filterText: "foo",
},
...completion.classElementKeywords,
],
});

View File

@ -22,8 +22,9 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
insertText: "foo(arg: string): number {\n}"
sortText: completion.SortText.LocationPriority,
insertText: "foo(arg: string): number {\n}",
filterText: "foo",
},
],
});

View File

@ -26,9 +26,10 @@ verify.completions({
includes: [
{
name: "method",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "method(): void {\n}",
replacementSpan: undefined,
filterText: "method",
},
],
});

View File

@ -25,27 +25,32 @@ verify.completions({
includes: [
{
name: "$usd",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
isSnippet: true,
insertText: "\"\\$usd\"(a: number): number {\n $0\n}",
filterText: "$usd",
},
{
name: "$cad",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
isSnippet: true,
insertText: "\\$cad(b: number): number {\n $0\n}",
filterText: "$cad",
},
{
name: "cla$$y",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
isSnippet: true,
insertText: "cla\\$\\$y(c: number): number {\n $0\n}",
filterText: "cla$$y",
},
{
name: "isDollarAmountString",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
isSnippet: true,
insertText: "isDollarAmountString(s: string): s is `\\$\\${number}` {\n $0\n}"
insertText: "isDollarAmountString(s: string): s is `\\$\\${number}` {\n $0\n}",
filterText: "isDollarAmountString",
},
],
});

View File

@ -23,8 +23,9 @@ verify.completions({
includes: [
{
name: "boo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "boo(): string;",
filterText: "boo",
}
],
});

View File

@ -42,13 +42,15 @@ verify.completions({
includes: [
{
name: "hint",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "protected hint(): string {\n}",
filterText: "hint",
},
{
name: "refuse",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "public refuse(): string {\n}",
filterText: "refuse",
}
],
});

View File

@ -12,8 +12,8 @@
////
////abstract class Abc extends Ab {
//// /*a*/
//// [|abstract|] /*b*/
//// [|abstract m|]/*c*/
//// abstract /*b*/
//// abstract m/*c*/
////}
@ -28,13 +28,15 @@ verify.completions({
includes: [
{
name: "met",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "met(n: string): void {\n}",
filterText: "met"
},
{
name: "met2",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "met2(n: number): void {\n}",
filterText: "met2"
}
],
});
@ -50,15 +52,15 @@ verify.completions({
includes: [
{
name: "met",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[0],
sortText: completion.SortText.LocationPriority,
insertText: "abstract met(n: string): void;",
filterText: "met"
},
{
name: "met2",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[0],
sortText: completion.SortText.LocationPriority,
insertText: "abstract met2(n: number): void;",
filterText: "met2"
}
],
});
@ -74,15 +76,15 @@ verify.completions({
includes: [
{
name: "met",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[1],
sortText: completion.SortText.LocationPriority,
insertText: "abstract met(n: string): void;",
filterText: "met"
},
{
name: "met2",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[1],
sortText: completion.SortText.LocationPriority,
insertText: "abstract met2(n: number): void;",
filterText: "met2"
}
],
});

View File

@ -2,84 +2,202 @@
// @Filename: a.ts
// @newline: LF
// Case: modifier inheritance/deduplication
////class A {
//// public method(): number {
//// return 0;
//// }
////}
////
////abstract class B extends A {
//// [|public abstract|] /*b*/
////}
////
////class C extends A {
//// [|public override m|]/*a*/
////}
////
////interface D {
//// fun(a: number): number;
//// fun(a: undefined, b: string): number;
////}
////
////class E implements D {
//// [|public f|]/*c*/
////}
// Case: modifiers
//// class Base {
//// method() {}
//// protected prop = 1;
//// }
verify.completions({
marker: "a",
isNewIdentifierLocation: true,
preferences: {
includeCompletionsWithInsertText: true,
includeCompletionsWithSnippetText: false,
includeCompletionsWithClassMemberSnippets: true,
},
includes: [
{
name: "method",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[1],
insertText: "public override method(): number {\n}",
//// class A extends Base {
//// public abstract /*a*/
//// }
//// abstract class Ab extends Base {
//// public abstract /*b*/
//// }
//// class B extends Base {
//// public override m/*c*/
//// }
//// class C extends Base {
//// override /*d*/
//// }
//// class E extends Base {
//// protected notamodifier override /*e*/
//// }
//// class f extends Base {
//// protected /*f*/
//// }
//// declare function decorator(...args: any[]): any;
//// class DecoratorBase {
//// protected foo(a: string): string;
//// protected foo(a: number): number;
//// protected foo(a: any): any {
//// return a;
//// }
//// }
//// class DecoratorSub extends DecoratorBase {
//// @decorator protected /*g*/
//// }
verify.completions(
{
marker: "a",
isNewIdentifierLocation: true,
preferences: {
includeCompletionsWithInsertText: true,
includeCompletionsWithSnippetText: false,
includeCompletionsWithClassMemberSnippets: true,
},
],
});
verify.completions({
marker: "b",
isNewIdentifierLocation: true,
preferences: {
includeCompletionsWithInsertText: true,
includeCompletionsWithSnippetText: false,
includeCompletionsWithClassMemberSnippets: true,
excludes: ["method", "prop"],
},
includes: [
{
name: "method",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[0],
insertText: "public abstract method(): number;",
{
marker: "b",
isNewIdentifierLocation: true,
preferences: {
includeCompletionsWithInsertText: true,
includeCompletionsWithSnippetText: false,
includeCompletionsWithClassMemberSnippets: true,
},
],
});
verify.completions({
marker: "c",
isNewIdentifierLocation: true,
preferences: {
includeCompletionsWithInsertText: true,
includeCompletionsWithSnippetText: false,
includeCompletionsWithClassMemberSnippets: true,
includes: [
{
name: "method",
sortText: completion.SortText.LocationPriority,
insertText: "public abstract method(): void;",
filterText: "method",
replacementSpan: undefined,
},
{
name: "prop",
sortText: completion.SortText.LocationPriority,
insertText: "public abstract prop: number;",
filterText: "prop",
replacementSpan: undefined,
},
],
},
includes: [
{
name: "fun",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[2],
insertText:
`public fun(a: number): number;
public fun(a: undefined, b: string): number;
public fun(a: unknown, b?: unknown): number {
{
marker: "c",
isNewIdentifierLocation: true,
preferences: {
includeCompletionsWithInsertText: true,
includeCompletionsWithSnippetText: false,
includeCompletionsWithClassMemberSnippets: true,
},
includes: [
{
name: "method",
sortText: completion.SortText.LocationPriority,
insertText: "public override method(): void {\n}",
filterText: "method",
replacementSpan: undefined,
},
{
name: "prop",
sortText: completion.SortText.LocationPriority,
insertText: "public override prop: number;",
filterText: "prop",
replacementSpan: undefined,
},
]
},
{
marker: "d",
isNewIdentifierLocation: true,
preferences: {
includeCompletionsWithInsertText: true,
includeCompletionsWithSnippetText: false,
includeCompletionsWithClassMemberSnippets: true,
},
includes: [
{
name: "method",
sortText: completion.SortText.LocationPriority,
insertText: "override method(): void {\n}",
filterText: "method",
replacementSpan: undefined,
},
{
name: "prop",
sortText: completion.SortText.LocationPriority,
insertText: "protected override prop: number;",
filterText: "prop",
replacementSpan: undefined,
},
]
},
{
marker: "e",
isNewIdentifierLocation: true,
preferences: {
includeCompletionsWithInsertText: true,
includeCompletionsWithSnippetText: false,
includeCompletionsWithClassMemberSnippets: true,
},
includes: [
{
name: "method",
sortText: completion.SortText.LocationPriority,
insertText: "override method(): void {\n}",
filterText: "method",
replacementSpan: undefined,
},
{
name: "prop",
sortText: completion.SortText.LocationPriority,
insertText: "protected override prop: number;",
filterText: "prop",
replacementSpan: undefined,
},
]
},
{
marker: "f",
isNewIdentifierLocation: true,
preferences: {
includeCompletionsWithInsertText: true,
includeCompletionsWithSnippetText: false,
includeCompletionsWithClassMemberSnippets: true,
},
excludes: ["method"],
includes: [
{
name: "prop",
sortText: completion.SortText.LocationPriority,
insertText: "protected prop: number;",
filterText: "prop",
replacementSpan: undefined,
},
]
},
{
marker: "g",
isNewIdentifierLocation: true,
preferences: {
includeCompletionsWithInsertText: true,
includeCompletionsWithSnippetText: false,
includeCompletionsWithClassMemberSnippets: true,
},
includes: [
{
name: "foo",
sortText: completion.SortText.LocationPriority,
insertText:
`protected foo(a: string): string;
protected foo(a: number): number;
@decorator
protected foo(a: any) {
}`,
},
],
});
filterText: "foo",
replacementSpan: undefined,
},
]
},
);

View File

@ -9,7 +9,7 @@
////}
////
////abstract class Derived extends Base {
//// [|abstract|] /*a*/
//// abstract /*a*/
////}
verify.completions({
@ -23,11 +23,11 @@ verify.completions({
includes: [
{
name: "M",
sortText: completion.SortText.ClassMemberSnippets,
replacementSpan: test.ranges()[0],
sortText: completion.SortText.LocationPriority,
insertText:
`abstract M<T>(t: T): void;
abstract M<T>(t: T, x: number): void;`,
filterText: "M",
},
],
});

View File

@ -26,10 +26,11 @@ verify.completions({
},
includes: [{
name: "method",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "method(p: I): void {\n}",
hasAction: true,
source: completion.CompletionSource.ClassMemberSnippet,
filterText: "method",
}],
});

View File

@ -22,13 +22,15 @@ verify.completions({
includes: [
{
name: "a",
sortText: completion.SortText.ClassMemberSnippets,
insertText: "a?: number;"
sortText: completion.SortText.LocationPriority,
insertText: "a?: number;",
filterText: "a",
},
{
name: "b",
sortText: completion.SortText.ClassMemberSnippets,
insertText: "b(x: number): void {\n}"
sortText: completion.SortText.LocationPriority,
insertText: "b(x: number): void {\n}",
filterText: "b",
},
],
});

View File

@ -21,8 +21,9 @@ verify.completions({
includes: [
{
name: "setState",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "setState(stateHandler: (oldState: {}, newState: {}) => void): void {\n}",
filterText: "setState",
}
]
});

View File

@ -29,7 +29,8 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
filterText: "foo",
insertText: "foo(): Other {\n}",
hasAction: true,
source: completion.CompletionSource.ClassMemberSnippet,

View File

@ -25,8 +25,9 @@ verify.completions({
includes: [
{
name: "foo",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
insertText: "protected foo: string;",
filterText: "foo"
}
],
});

View File

@ -702,6 +702,7 @@ declare namespace FourSlashInterface {
readonly name: string;
readonly source?: string;
readonly insertText?: string;
readonly filterText?: string;
readonly replacementSpan?: Range;
readonly hasAction?: boolean;
readonly isRecommended?: boolean;

View File

@ -35,7 +35,8 @@ verify.completions({
includes: [
{
name: "render",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
filterText: "render",
isSnippet: true,
insertText: "render(): Element {\r\n $0\r\n}",
hasAction: true,
@ -59,7 +60,8 @@ verify.completions({
includes: [
{
name: "render",
sortText: completion.SortText.ClassMemberSnippets,
sortText: completion.SortText.LocationPriority,
filterText: "render",
isSnippet: true,
insertText: "render(): Element {\r\n $0\r\n}",
hasAction: true,