diff --git a/src/services/completions.ts b/src/services/completions.ts index 343a323f34544..02427425fdf1f 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -4829,7 +4829,7 @@ function tryGetObjectTypeDeclarationCompletionContainer(sourceFile: SourceFile, return cls; } break; - case SyntaxKind.Identifier: { + case SyntaxKind.Identifier: { const originalKeywordKind = identifierToKeywordKind(location as Identifier); if (originalKeywordKind) { return undefined; @@ -4868,16 +4868,17 @@ function tryGetObjectTypeDeclarationCompletionContainer(sourceFile: SourceFile, case SyntaxKind.CommaToken: // class c {getValue(): number, | } return tryCast(contextToken.parent, isObjectTypeDeclaration); default: - if (!isFromObjectTypeDeclaration(contextToken)) { - // class c extends React.Component { a: () => 1\n| } - if (getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line !== getLineAndCharacterOfPosition(sourceFile, position).line && isObjectTypeDeclaration(location)) { + if (isObjectTypeDeclaration(location)) { + // class C extends React.Component { a: () => 1\n| } + // class C { prop = ""\n | } + if (getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line !== getLineAndCharacterOfPosition(sourceFile, position).line) { return location; } - return undefined; + const isValidKeyword = isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword; + return (isValidKeyword(contextToken.kind) || contextToken.kind === SyntaxKind.AsteriskToken || isIdentifier(contextToken) && isValidKeyword(identifierToKeywordKind(contextToken) ?? SyntaxKind.Unknown)) + ? contextToken.parent.parent as ObjectTypeDeclaration : undefined; } - const isValidKeyword = isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword; - return (isValidKeyword(contextToken.kind) || contextToken.kind === SyntaxKind.AsteriskToken || isIdentifier(contextToken) && isValidKeyword(identifierToKeywordKind(contextToken) ?? SyntaxKind.Unknown)) - ? contextToken.parent.parent as ObjectTypeDeclaration : undefined; + return undefined; } } diff --git a/tests/baselines/reference/completionsClassMembers1.baseline b/tests/baselines/reference/completionsClassMembers1.baseline new file mode 100644 index 0000000000000..e08c00fcc4481 --- /dev/null +++ b/tests/baselines/reference/completionsClassMembers1.baseline @@ -0,0 +1,230 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/completionsClassMembers1.ts", + "position": 93, + "name": "" + }, + "completionList": { + "flags": 0, + "isGlobalCompletion": false, + "isMemberCompletion": true, + "isNewIdentifierLocation": true, + "entries": [ + { + "name": "method", + "kind": "method", + "kindModifiers": "", + "sortText": "11", + "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", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "abstract", + "kind": "keyword" + } + ] + }, + { + "name": "accessor", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "accessor", + "kind": "keyword" + } + ] + }, + { + "name": "async", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "async", + "kind": "keyword" + } + ] + }, + { + "name": "constructor", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "constructor", + "kind": "keyword" + } + ] + }, + { + "name": "declare", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "declare", + "kind": "keyword" + } + ] + }, + { + "name": "get", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "get", + "kind": "keyword" + } + ] + }, + { + "name": "override", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "override", + "kind": "keyword" + } + ] + }, + { + "name": "private", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "private", + "kind": "keyword" + } + ] + }, + { + "name": "protected", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "protected", + "kind": "keyword" + } + ] + }, + { + "name": "public", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "public", + "kind": "keyword" + } + ] + }, + { + "name": "readonly", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "readonly", + "kind": "keyword" + } + ] + }, + { + "name": "set", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "set", + "kind": "keyword" + } + ] + }, + { + "name": "static", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "static", + "kind": "keyword" + } + ] + } + ] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/completionsClassMembers2.baseline b/tests/baselines/reference/completionsClassMembers2.baseline new file mode 100644 index 0000000000000..eb68eaf45a2ea --- /dev/null +++ b/tests/baselines/reference/completionsClassMembers2.baseline @@ -0,0 +1,235 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/completionsClassMembers2.ts", + "position": 93, + "name": "" + }, + "completionList": { + "flags": 0, + "isGlobalCompletion": false, + "isMemberCompletion": true, + "isNewIdentifierLocation": true, + "entries": [ + { + "name": "abstract", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "abstract", + "kind": "keyword" + } + ] + }, + { + "name": "accessor", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "accessor", + "kind": "keyword" + } + ] + }, + { + "name": "async", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "async", + "kind": "keyword" + } + ] + }, + { + "name": "constructor", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "constructor", + "kind": "keyword" + } + ] + }, + { + "name": "declare", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "declare", + "kind": "keyword" + } + ] + }, + { + "name": "get", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "get", + "kind": "keyword" + } + ] + }, + { + "name": "override", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "override", + "kind": "keyword" + } + ] + }, + { + "name": "private", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "private", + "kind": "keyword" + } + ] + }, + { + "name": "protected", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "protected", + "kind": "keyword" + } + ] + }, + { + "name": "public", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "public", + "kind": "keyword" + } + ] + }, + { + "name": "readonly", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "readonly", + "kind": "keyword" + } + ] + }, + { + "name": "set", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "set", + "kind": "keyword" + } + ] + }, + { + "name": "static", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "static", + "kind": "keyword" + } + ] + }, + { + "name": "method", + "kind": "method", + "kindModifiers": "", + "sortText": "17", + "insertText": "method(): void {\r\n}", + "replacementSpan": { + "start": 71, + "length": 16 + }, + "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": [] + } + ] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/completionsClassMembers3.baseline b/tests/baselines/reference/completionsClassMembers3.baseline new file mode 100644 index 0000000000000..4d83c1f170378 --- /dev/null +++ b/tests/baselines/reference/completionsClassMembers3.baseline @@ -0,0 +1,230 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/completionsClassMembers3.ts", + "position": 101, + "name": "" + }, + "completionList": { + "flags": 0, + "isGlobalCompletion": false, + "isMemberCompletion": true, + "isNewIdentifierLocation": true, + "entries": [ + { + "name": "method", + "kind": "method", + "kindModifiers": "", + "sortText": "11", + "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", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "abstract", + "kind": "keyword" + } + ] + }, + { + "name": "accessor", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "accessor", + "kind": "keyword" + } + ] + }, + { + "name": "async", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "async", + "kind": "keyword" + } + ] + }, + { + "name": "constructor", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "constructor", + "kind": "keyword" + } + ] + }, + { + "name": "declare", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "declare", + "kind": "keyword" + } + ] + }, + { + "name": "get", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "get", + "kind": "keyword" + } + ] + }, + { + "name": "override", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "override", + "kind": "keyword" + } + ] + }, + { + "name": "private", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "private", + "kind": "keyword" + } + ] + }, + { + "name": "protected", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "protected", + "kind": "keyword" + } + ] + }, + { + "name": "public", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "public", + "kind": "keyword" + } + ] + }, + { + "name": "readonly", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "readonly", + "kind": "keyword" + } + ] + }, + { + "name": "set", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "set", + "kind": "keyword" + } + ] + }, + { + "name": "static", + "kind": "keyword", + "kindModifiers": "", + "sortText": "15", + "displayParts": [ + { + "text": "static", + "kind": "keyword" + } + ] + } + ] + } + } +] \ No newline at end of file diff --git a/tests/cases/fourslash/completionsClassMembers1.ts b/tests/cases/fourslash/completionsClassMembers1.ts new file mode 100644 index 0000000000000..094039a61853c --- /dev/null +++ b/tests/cases/fourslash/completionsClassMembers1.ts @@ -0,0 +1,13 @@ +/// + +////interface I { +//// method(): void; +////} +//// +////export class C implements I { +//// property = "foo" +//// +//// /**/ +////} + +verify.baselineCompletions(); diff --git a/tests/cases/fourslash/completionsClassMembers2.ts b/tests/cases/fourslash/completionsClassMembers2.ts new file mode 100644 index 0000000000000..039334e14c735 --- /dev/null +++ b/tests/cases/fourslash/completionsClassMembers2.ts @@ -0,0 +1,16 @@ +/// + +////interface I { +//// method(): void; +////} +//// +////export class C implements I { +//// property = "foo" +//// +//// /**/ +////} + +verify.baselineCompletions({ + includeCompletionsWithInsertText: true, + includeCompletionsWithClassMemberSnippets: true, +}); diff --git a/tests/cases/fourslash/completionsClassMembers3.ts b/tests/cases/fourslash/completionsClassMembers3.ts new file mode 100644 index 0000000000000..f648ef0ab433d --- /dev/null +++ b/tests/cases/fourslash/completionsClassMembers3.ts @@ -0,0 +1,13 @@ +/// + +////interface I { +//// method(): void; +////} +//// +////export class C implements I { +//// property = "foo" + "foo" +//// +//// /**/ +////} + +verify.baselineCompletions();