Skip to content

Commit 78c1679

Browse files
authored
Don't ignore completions at source file locations (#61909)
1 parent 479285d commit 78c1679

6 files changed

+125
-163
lines changed

src/services/completions.ts

Lines changed: 57 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2738,78 +2738,76 @@ export function getCompletionEntriesFromSymbols(
27382738

27392739
function shouldIncludeSymbol(symbol: Symbol, symbolToSortTextMap: SymbolSortTextMap): boolean {
27402740
let allFlags = symbol.flags;
2741-
if (!isSourceFile(location)) {
2742-
// export = /**/ here we want to get all meanings, so any symbol is ok
2743-
if (isExportAssignment(location.parent)) {
2744-
return true;
2741+
// export = /**/ here we want to get all meanings, so any symbol is ok
2742+
if (location.parent && isExportAssignment(location.parent)) {
2743+
return true;
2744+
}
2745+
// Filter out variables from their own initializers
2746+
// `const a = /* no 'a' here */`
2747+
if (closestSymbolDeclaration && tryCast(closestSymbolDeclaration, isVariableDeclaration)) {
2748+
if (symbol.valueDeclaration === closestSymbolDeclaration) {
2749+
return false;
27452750
}
2746-
// Filter out variables from their own initializers
2747-
// `const a = /* no 'a' here */`
2748-
if (closestSymbolDeclaration && tryCast(closestSymbolDeclaration, isVariableDeclaration)) {
2749-
if (symbol.valueDeclaration === closestSymbolDeclaration) {
2751+
// const { a } = /* no 'a' here */;
2752+
if (isBindingPattern(closestSymbolDeclaration.name) && closestSymbolDeclaration.name.elements.some(e => e === symbol.valueDeclaration)) {
2753+
return false;
2754+
}
2755+
}
2756+
2757+
// Filter out current and latter parameters from defaults
2758+
// `function f(a = /* no 'a' and 'b' here */, b) { }` or
2759+
// `function f<T = /* no 'T' and 'T2' here */>(a: T, b: T2) { }`
2760+
const symbolDeclaration = symbol.valueDeclaration ?? symbol.declarations?.[0];
2761+
if (closestSymbolDeclaration && symbolDeclaration) {
2762+
if (isParameter(closestSymbolDeclaration) && isParameter(symbolDeclaration)) {
2763+
const parameters = closestSymbolDeclaration.parent.parameters;
2764+
if (symbolDeclaration.pos >= closestSymbolDeclaration.pos && symbolDeclaration.pos < parameters.end) {
27502765
return false;
27512766
}
2752-
// const { a } = /* no 'a' here */;
2753-
if (isBindingPattern(closestSymbolDeclaration.name) && closestSymbolDeclaration.name.elements.some(e => e === symbol.valueDeclaration)) {
2767+
}
2768+
else if (isTypeParameterDeclaration(closestSymbolDeclaration) && isTypeParameterDeclaration(symbolDeclaration)) {
2769+
if (closestSymbolDeclaration === symbolDeclaration && contextToken?.kind === SyntaxKind.ExtendsKeyword) {
2770+
// filter out the directly self-recursive type parameters
2771+
// `type A<K extends /* no 'K' here*/> = K`
27542772
return false;
27552773
}
2756-
}
2757-
2758-
// Filter out current and latter parameters from defaults
2759-
// `function f(a = /* no 'a' and 'b' here */, b) { }` or
2760-
// `function f<T = /* no 'T' and 'T2' here */>(a: T, b: T2) { }`
2761-
const symbolDeclaration = symbol.valueDeclaration ?? symbol.declarations?.[0];
2762-
if (closestSymbolDeclaration && symbolDeclaration) {
2763-
if (isParameter(closestSymbolDeclaration) && isParameter(symbolDeclaration)) {
2764-
const parameters = closestSymbolDeclaration.parent.parameters;
2765-
if (symbolDeclaration.pos >= closestSymbolDeclaration.pos && symbolDeclaration.pos < parameters.end) {
2774+
if (isInTypeParameterDefault(contextToken) && !isInferTypeNode(closestSymbolDeclaration.parent)) {
2775+
const typeParameters = closestSymbolDeclaration.parent.typeParameters;
2776+
if (typeParameters && symbolDeclaration.pos >= closestSymbolDeclaration.pos && symbolDeclaration.pos < typeParameters.end) {
27662777
return false;
27672778
}
27682779
}
2769-
else if (isTypeParameterDeclaration(closestSymbolDeclaration) && isTypeParameterDeclaration(symbolDeclaration)) {
2770-
if (closestSymbolDeclaration === symbolDeclaration && contextToken?.kind === SyntaxKind.ExtendsKeyword) {
2771-
// filter out the directly self-recursive type parameters
2772-
// `type A<K extends /* no 'K' here*/> = K`
2773-
return false;
2774-
}
2775-
if (isInTypeParameterDefault(contextToken) && !isInferTypeNode(closestSymbolDeclaration.parent)) {
2776-
const typeParameters = closestSymbolDeclaration.parent.typeParameters;
2777-
if (typeParameters && symbolDeclaration.pos >= closestSymbolDeclaration.pos && symbolDeclaration.pos < typeParameters.end) {
2778-
return false;
2779-
}
2780-
}
2781-
}
27822780
}
2781+
}
27832782

2784-
// External modules can have global export declarations that will be
2785-
// available as global keywords in all scopes. But if the external module
2786-
// already has an explicit export and user only wants to user explicit
2787-
// module imports then the global keywords will be filtered out so auto
2788-
// import suggestions will win in the completion
2789-
const symbolOrigin = skipAlias(symbol, typeChecker);
2790-
// We only want to filter out the global keywords
2791-
// Auto Imports are not available for scripts so this conditional is always false
2792-
if (
2793-
!!sourceFile.externalModuleIndicator
2794-
&& !compilerOptions.allowUmdGlobalAccess
2795-
&& symbolToSortTextMap[getSymbolId(symbol)] === SortText.GlobalsOrKeywords
2796-
&& (symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.AutoImportSuggestions
2797-
|| symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.LocationPriority)
2798-
) {
2799-
return false;
2800-
}
2783+
// External modules can have global export declarations that will be
2784+
// available as global keywords in all scopes. But if the external module
2785+
// already has an explicit export and user only wants to user explicit
2786+
// module imports then the global keywords will be filtered out so auto
2787+
// import suggestions will win in the completion
2788+
const symbolOrigin = skipAlias(symbol, typeChecker);
2789+
// We only want to filter out the global keywords
2790+
// Auto Imports are not available for scripts so this conditional is always false
2791+
if (
2792+
!!sourceFile.externalModuleIndicator
2793+
&& !compilerOptions.allowUmdGlobalAccess
2794+
&& symbolToSortTextMap[getSymbolId(symbol)] === SortText.GlobalsOrKeywords
2795+
&& (symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.AutoImportSuggestions
2796+
|| symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.LocationPriority)
2797+
) {
2798+
return false;
2799+
}
28012800

2802-
allFlags |= getCombinedLocalAndExportSymbolFlags(symbolOrigin);
2801+
allFlags |= getCombinedLocalAndExportSymbolFlags(symbolOrigin);
28032802

2804-
// import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
2805-
if (isInRightSideOfInternalImportEqualsDeclaration(location)) {
2806-
return !!(allFlags & SymbolFlags.Namespace);
2807-
}
2803+
// import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
2804+
if (isInRightSideOfInternalImportEqualsDeclaration(location)) {
2805+
return !!(allFlags & SymbolFlags.Namespace);
2806+
}
28082807

2809-
if (isTypeOnlyLocation) {
2810-
// It's a type, but you can reach it by namespace.type as well
2811-
return symbolCanBeReferencedAtTypeLocation(symbol, typeChecker);
2812-
}
2808+
if (isTypeOnlyLocation) {
2809+
// It's a type, but you can reach it by namespace.type as well
2810+
return symbolCanBeReferencedAtTypeLocation(symbol, typeChecker);
28132811
}
28142812

28152813
// expressions are value space (which includes the value namespaces)

src/services/utilities.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,9 @@ function getMeaningFromRightHandSideOfImportEquals(node: Node): SemanticMeaning
520520

521521
/** @internal */
522522
export function isInRightSideOfInternalImportEqualsDeclaration(node: Node): boolean {
523+
if (!node.parent) {
524+
return false;
525+
}
523526
while (node.parent.kind === SyntaxKind.QualifiedName) {
524527
node = node.parent;
525528
}

tests/baselines/reference/tsserver/completions/in-project-reference-setup-with-path-mapping-with-existing-import-without-includeCompletionsForModuleExports.js

Lines changed: 24 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,12 @@ Info seq [hh:mm:ss:mss] response:
407407
"isMemberCompletion": false,
408408
"isNewIdentifierLocation": false,
409409
"entries": [
410+
{
411+
"name": "MyClass",
412+
"kind": "alias",
413+
"kindModifiers": "export",
414+
"sortText": "11"
415+
},
410416
{
411417
"name": "abstract",
412418
"kind": "keyword",
@@ -814,19 +820,6 @@ Info seq [hh:mm:ss:mss] response:
814820
"kind": "keyword",
815821
"kindModifiers": "",
816822
"sortText": "15"
817-
},
818-
{
819-
"name": "MyClass",
820-
"kind": "class",
821-
"kindModifiers": "export",
822-
"sortText": "16",
823-
"source": "/user/username/projects/shared/src/index",
824-
"hasAction": true,
825-
"data": {
826-
"exportName": "MyClass",
827-
"exportMapKey": "7 * MyClass ",
828-
"fileName": "/user/username/projects/shared/src/index.ts"
829-
}
830823
}
831824
],
832825
"defaultCommitCharacters": [
@@ -898,6 +891,12 @@ Info seq [hh:mm:ss:mss] response:
898891
"isMemberCompletion": false,
899892
"isNewIdentifierLocation": false,
900893
"entries": [
894+
{
895+
"name": "MyClass",
896+
"kind": "alias",
897+
"kindModifiers": "export",
898+
"sortText": "11"
899+
},
901900
{
902901
"name": "abstract",
903902
"kind": "keyword",
@@ -1305,19 +1304,6 @@ Info seq [hh:mm:ss:mss] response:
13051304
"kind": "keyword",
13061305
"kindModifiers": "",
13071306
"sortText": "15"
1308-
},
1309-
{
1310-
"name": "MyClass",
1311-
"kind": "class",
1312-
"kindModifiers": "export",
1313-
"sortText": "16",
1314-
"source": "/user/username/projects/shared/src/index",
1315-
"hasAction": true,
1316-
"data": {
1317-
"exportName": "MyClass",
1318-
"exportMapKey": "7 * MyClass ",
1319-
"fileName": "/user/username/projects/shared/src/index.ts"
1320-
}
13211307
}
13221308
],
13231309
"defaultCommitCharacters": [
@@ -1401,6 +1387,12 @@ Info seq [hh:mm:ss:mss] response:
14011387
"isMemberCompletion": false,
14021388
"isNewIdentifierLocation": false,
14031389
"entries": [
1390+
{
1391+
"name": "MyClass",
1392+
"kind": "alias",
1393+
"kindModifiers": "export",
1394+
"sortText": "11"
1395+
},
14041396
{
14051397
"name": "abstract",
14061398
"kind": "keyword",
@@ -1808,19 +1800,6 @@ Info seq [hh:mm:ss:mss] response:
18081800
"kind": "keyword",
18091801
"kindModifiers": "",
18101802
"sortText": "15"
1811-
},
1812-
{
1813-
"name": "MyClass",
1814-
"kind": "class",
1815-
"kindModifiers": "export",
1816-
"sortText": "16",
1817-
"source": "/user/username/projects/shared/src/index",
1818-
"hasAction": true,
1819-
"data": {
1820-
"exportName": "MyClass",
1821-
"exportMapKey": "7 * MyClass ",
1822-
"fileName": "/user/username/projects/shared/src/index.ts"
1823-
}
18241803
}
18251804
],
18261805
"defaultCommitCharacters": [
@@ -1922,6 +1901,12 @@ Info seq [hh:mm:ss:mss] response:
19221901
"isMemberCompletion": false,
19231902
"isNewIdentifierLocation": false,
19241903
"entries": [
1904+
{
1905+
"name": "MyClass",
1906+
"kind": "alias",
1907+
"kindModifiers": "export",
1908+
"sortText": "11"
1909+
},
19251910
{
19261911
"name": "abstract",
19271912
"kind": "keyword",
@@ -2329,19 +2314,6 @@ Info seq [hh:mm:ss:mss] response:
23292314
"kind": "keyword",
23302315
"kindModifiers": "",
23312316
"sortText": "15"
2332-
},
2333-
{
2334-
"name": "MyClass",
2335-
"kind": "class",
2336-
"kindModifiers": "export",
2337-
"sortText": "16",
2338-
"source": "/user/username/projects/shared/src/index",
2339-
"hasAction": true,
2340-
"data": {
2341-
"exportName": "MyClass",
2342-
"exportMapKey": "7 * MyClass ",
2343-
"fileName": "/user/username/projects/shared/src/index.ts"
2344-
}
23452317
}
23462318
],
23472319
"defaultCommitCharacters": [

0 commit comments

Comments
 (0)