diff --git a/src/services/completions.ts b/src/services/completions.ts index 488af58a2f0..878b4bcd130 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1021,7 +1021,8 @@ namespace ts.Completions { const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; isInSnippetScope = isSnippetScope(scopeNode); - const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; + const isTypeOnly = isTypeOnlyCompletion(); + const symbolMeanings = (isTypeOnly ? SymbolFlags.None : SymbolFlags.Value) | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias; symbols = Debug.assertEachDefined(typeChecker.getSymbolsInScope(scopeNode, symbolMeanings), "getSymbolsInScope() should all be defined"); @@ -1070,9 +1071,9 @@ namespace ts.Completions { } function filterGlobalCompletion(symbols: Symbol[]): void { - const isTypeOnlyCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)); - const allowTypes = isTypeOnlyCompletion || !isContextTokenValueLocation(contextToken) && isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker); - if (isTypeOnlyCompletion) keywordFilters = KeywordCompletionFilters.TypeKeywords; + const isTypeOnly = isTypeOnlyCompletion(); + const allowTypes = isTypeOnly || !isContextTokenValueLocation(contextToken) && isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker); + if (isTypeOnly) keywordFilters = KeywordCompletionFilters.TypeKeywords; filterMutate(symbols, symbol => { if (!isSourceFile(location)) { @@ -1091,7 +1092,7 @@ namespace ts.Completions { if (allowTypes) { // Its a type, but you can reach it by namespace.type as well const symbolAllowedAsType = symbolCanBeReferencedAtTypeLocation(symbol); - if (symbolAllowedAsType || isTypeOnlyCompletion) { + if (symbolAllowedAsType || isTypeOnly) { return symbolAllowedAsType; } } @@ -1102,6 +1103,10 @@ namespace ts.Completions { }); } + function isTypeOnlyCompletion(): boolean { + return insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)); + } + function isContextTokenValueLocation(contextToken: Node) { return contextToken && contextToken.kind === SyntaxKind.TypeOfKeyword && diff --git a/tests/cases/fourslash/completionsIsTypeOnlyCompletion.ts b/tests/cases/fourslash/completionsIsTypeOnlyCompletion.ts new file mode 100644 index 00000000000..b14f7bc0efe --- /dev/null +++ b/tests/cases/fourslash/completionsIsTypeOnlyCompletion.ts @@ -0,0 +1,19 @@ +/// + +// @noLib: true + +// @Filename: /abc.ts +////export type Abc = number; + +// @Filename: /user.ts +//// import { Abc } from "./abc"; +////function f(Abc: Ab/**/) {} + +verify.completions({ + marker: "", + // Should not have an import completion for 'Abc', should use the local one + exact: ["Abc", ...completion.typeKeywords], + preferences: { + includeCompletionsForModuleExports: true, + }, +});