diff --git a/internal/fourslash/tests/completionClassMembersAfterConstAssertionInitializer_test.go b/internal/fourslash/tests/completionClassMembersAfterConstAssertionInitializer_test.go new file mode 100644 index 0000000000..ad87a3b6c9 --- /dev/null +++ b/internal/fourslash/tests/completionClassMembersAfterConstAssertionInitializer_test.go @@ -0,0 +1,46 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + . "github.com/microsoft/typescript-go/internal/fourslash/tests/util" + "github.com/microsoft/typescript-go/internal/ls" + "github.com/microsoft/typescript-go/internal/lsp/lsproto" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestClassMembersAfterConstAssertionInitializer(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = ` +interface A { + a: number + def: string +} + +class B implements A { + a = 1 as const + /**/ +} +` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + + f.VerifyCompletions(t, "", &fourslash.CompletionsExpectedList{ + IsIncomplete: false, + ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{ + CommitCharacters: &[]string{}, + EditRange: Ignored, + }, + Items: &fourslash.CompletionsExpectedItems{ + Exact: append([]fourslash.CompletionsExpectedItem{ + &lsproto.CompletionItem{ + Label: "def", + Kind: PtrTo(lsproto.CompletionItemKindField), + SortText: PtrTo(string(ls.SortTextLocationPriority)), + }, + }, CompletionClassElementKeywords...), + }, + }) +} diff --git a/internal/ls/completions.go b/internal/ls/completions.go index e8e7003b36..dec66b86a7 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -4807,9 +4807,10 @@ func isSolelyIdentifierDefinitionLocation( return ast.IsFunctionLike(parent) && !ast.IsMethodDeclaration(parent) } + tokenKind := keywordForNode(contextToken) // If the previous token is keyword corresponding to class member completion keyword // there will be completion available here - if isClassMemberCompletionKeyword(keywordForNode(contextToken)) && isFromObjectTypeDeclaration(contextToken) { + if isClassMemberCompletionKeyword(tokenKind) && isFromObjectTypeDeclaration(contextToken) { return false } @@ -4819,7 +4820,7 @@ func isSolelyIdentifierDefinitionLocation( // - its name of the parameter and not being edited // eg. constructor(a |<- this shouldnt show completion if !ast.IsIdentifier(contextToken) || - ast.IsParameterPropertyModifier(keywordForNode(contextToken)) || + ast.IsParameterPropertyModifier(tokenKind) || isCurrentlyEditingNode(contextToken, file, position) { return false } @@ -4827,7 +4828,7 @@ func isSolelyIdentifierDefinitionLocation( // Previous token may have been a keyword that was converted to an identifier. switch keywordForNode(contextToken) { - case ast.KindAbstractKeyword, ast.KindClassKeyword, ast.KindConstKeyword, ast.KindDeclareKeyword, + case ast.KindAbstractKeyword, ast.KindClassKeyword, ast.KindDeclareKeyword, ast.KindEnumKeyword, ast.KindFunctionKeyword, ast.KindInterfaceKeyword, ast.KindLetKeyword, ast.KindPrivateKeyword, ast.KindProtectedKeyword, ast.KindPublicKeyword, ast.KindStaticKeyword, ast.KindVarKeyword: @@ -4862,7 +4863,9 @@ func isSolelyIdentifierDefinitionLocation( return true } } - + if tokenKind == ast.KindConstKeyword { + return true + } return ast.IsDeclarationName(contextToken) && !ast.IsShorthandPropertyAssignment(parent) && !ast.IsJsxAttribute(parent) &&