diff --git a/src/services/completions.ts b/src/services/completions.ts
index dd623aadeb156..6d0cbf7183ed3 100644
--- a/src/services/completions.ts
+++ b/src/services/completions.ts
@@ -2738,78 +2738,76 @@ export function getCompletionEntriesFromSymbols(
function shouldIncludeSymbol(symbol: Symbol, symbolToSortTextMap: SymbolSortTextMap): boolean {
let allFlags = symbol.flags;
- if (!isSourceFile(location)) {
- // export = /**/ here we want to get all meanings, so any symbol is ok
- if (isExportAssignment(location.parent)) {
- return true;
+ // export = /**/ here we want to get all meanings, so any symbol is ok
+ if (location.parent && isExportAssignment(location.parent)) {
+ return true;
+ }
+ // Filter out variables from their own initializers
+ // `const a = /* no 'a' here */`
+ if (closestSymbolDeclaration && tryCast(closestSymbolDeclaration, isVariableDeclaration)) {
+ if (symbol.valueDeclaration === closestSymbolDeclaration) {
+ return false;
}
- // Filter out variables from their own initializers
- // `const a = /* no 'a' here */`
- if (closestSymbolDeclaration && tryCast(closestSymbolDeclaration, isVariableDeclaration)) {
- if (symbol.valueDeclaration === closestSymbolDeclaration) {
+ // const { a } = /* no 'a' here */;
+ if (isBindingPattern(closestSymbolDeclaration.name) && closestSymbolDeclaration.name.elements.some(e => e === symbol.valueDeclaration)) {
+ return false;
+ }
+ }
+
+ // Filter out current and latter parameters from defaults
+ // `function f(a = /* no 'a' and 'b' here */, b) { }` or
+ // `function f(a: T, b: T2) { }`
+ const symbolDeclaration = symbol.valueDeclaration ?? symbol.declarations?.[0];
+ if (closestSymbolDeclaration && symbolDeclaration) {
+ if (isParameter(closestSymbolDeclaration) && isParameter(symbolDeclaration)) {
+ const parameters = closestSymbolDeclaration.parent.parameters;
+ if (symbolDeclaration.pos >= closestSymbolDeclaration.pos && symbolDeclaration.pos < parameters.end) {
return false;
}
- // const { a } = /* no 'a' here */;
- if (isBindingPattern(closestSymbolDeclaration.name) && closestSymbolDeclaration.name.elements.some(e => e === symbol.valueDeclaration)) {
+ }
+ else if (isTypeParameterDeclaration(closestSymbolDeclaration) && isTypeParameterDeclaration(symbolDeclaration)) {
+ if (closestSymbolDeclaration === symbolDeclaration && contextToken?.kind === SyntaxKind.ExtendsKeyword) {
+ // filter out the directly self-recursive type parameters
+ // `type A = K`
return false;
}
- }
-
- // Filter out current and latter parameters from defaults
- // `function f(a = /* no 'a' and 'b' here */, b) { }` or
- // `function f(a: T, b: T2) { }`
- const symbolDeclaration = symbol.valueDeclaration ?? symbol.declarations?.[0];
- if (closestSymbolDeclaration && symbolDeclaration) {
- if (isParameter(closestSymbolDeclaration) && isParameter(symbolDeclaration)) {
- const parameters = closestSymbolDeclaration.parent.parameters;
- if (symbolDeclaration.pos >= closestSymbolDeclaration.pos && symbolDeclaration.pos < parameters.end) {
+ if (isInTypeParameterDefault(contextToken) && !isInferTypeNode(closestSymbolDeclaration.parent)) {
+ const typeParameters = closestSymbolDeclaration.parent.typeParameters;
+ if (typeParameters && symbolDeclaration.pos >= closestSymbolDeclaration.pos && symbolDeclaration.pos < typeParameters.end) {
return false;
}
}
- else if (isTypeParameterDeclaration(closestSymbolDeclaration) && isTypeParameterDeclaration(symbolDeclaration)) {
- if (closestSymbolDeclaration === symbolDeclaration && contextToken?.kind === SyntaxKind.ExtendsKeyword) {
- // filter out the directly self-recursive type parameters
- // `type A = K`
- return false;
- }
- if (isInTypeParameterDefault(contextToken) && !isInferTypeNode(closestSymbolDeclaration.parent)) {
- const typeParameters = closestSymbolDeclaration.parent.typeParameters;
- if (typeParameters && symbolDeclaration.pos >= closestSymbolDeclaration.pos && symbolDeclaration.pos < typeParameters.end) {
- return false;
- }
- }
- }
}
+ }
- // External modules can have global export declarations that will be
- // available as global keywords in all scopes. But if the external module
- // already has an explicit export and user only wants to user explicit
- // module imports then the global keywords will be filtered out so auto
- // import suggestions will win in the completion
- const symbolOrigin = skipAlias(symbol, typeChecker);
- // We only want to filter out the global keywords
- // Auto Imports are not available for scripts so this conditional is always false
- if (
- !!sourceFile.externalModuleIndicator
- && !compilerOptions.allowUmdGlobalAccess
- && symbolToSortTextMap[getSymbolId(symbol)] === SortText.GlobalsOrKeywords
- && (symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.AutoImportSuggestions
- || symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.LocationPriority)
- ) {
- return false;
- }
+ // External modules can have global export declarations that will be
+ // available as global keywords in all scopes. But if the external module
+ // already has an explicit export and user only wants to user explicit
+ // module imports then the global keywords will be filtered out so auto
+ // import suggestions will win in the completion
+ const symbolOrigin = skipAlias(symbol, typeChecker);
+ // We only want to filter out the global keywords
+ // Auto Imports are not available for scripts so this conditional is always false
+ if (
+ !!sourceFile.externalModuleIndicator
+ && !compilerOptions.allowUmdGlobalAccess
+ && symbolToSortTextMap[getSymbolId(symbol)] === SortText.GlobalsOrKeywords
+ && (symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.AutoImportSuggestions
+ || symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.LocationPriority)
+ ) {
+ return false;
+ }
- allFlags |= getCombinedLocalAndExportSymbolFlags(symbolOrigin);
+ allFlags |= getCombinedLocalAndExportSymbolFlags(symbolOrigin);
- // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
- if (isInRightSideOfInternalImportEqualsDeclaration(location)) {
- return !!(allFlags & SymbolFlags.Namespace);
- }
+ // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
+ if (isInRightSideOfInternalImportEqualsDeclaration(location)) {
+ return !!(allFlags & SymbolFlags.Namespace);
+ }
- if (isTypeOnlyLocation) {
- // It's a type, but you can reach it by namespace.type as well
- return symbolCanBeReferencedAtTypeLocation(symbol, typeChecker);
- }
+ if (isTypeOnlyLocation) {
+ // It's a type, but you can reach it by namespace.type as well
+ return symbolCanBeReferencedAtTypeLocation(symbol, typeChecker);
}
// expressions are value space (which includes the value namespaces)
diff --git a/src/services/utilities.ts b/src/services/utilities.ts
index 75a1cbc94c315..bec7d4b266d20 100644
--- a/src/services/utilities.ts
+++ b/src/services/utilities.ts
@@ -520,6 +520,9 @@ function getMeaningFromRightHandSideOfImportEquals(node: Node): SemanticMeaning
/** @internal */
export function isInRightSideOfInternalImportEqualsDeclaration(node: Node): boolean {
+ if (!node.parent) {
+ return false;
+ }
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
diff --git a/tests/baselines/reference/tsserver/completions/in-project-reference-setup-with-path-mapping-with-existing-import-without-includeCompletionsForModuleExports.js b/tests/baselines/reference/tsserver/completions/in-project-reference-setup-with-path-mapping-with-existing-import-without-includeCompletionsForModuleExports.js
index 8b20553e962dc..be58940da541a 100644
--- a/tests/baselines/reference/tsserver/completions/in-project-reference-setup-with-path-mapping-with-existing-import-without-includeCompletionsForModuleExports.js
+++ b/tests/baselines/reference/tsserver/completions/in-project-reference-setup-with-path-mapping-with-existing-import-without-includeCompletionsForModuleExports.js
@@ -407,6 +407,12 @@ Info seq [hh:mm:ss:mss] response:
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
+ {
+ "name": "MyClass",
+ "kind": "alias",
+ "kindModifiers": "export",
+ "sortText": "11"
+ },
{
"name": "abstract",
"kind": "keyword",
@@ -814,19 +820,6 @@ Info seq [hh:mm:ss:mss] response:
"kind": "keyword",
"kindModifiers": "",
"sortText": "15"
- },
- {
- "name": "MyClass",
- "kind": "class",
- "kindModifiers": "export",
- "sortText": "16",
- "source": "/user/username/projects/shared/src/index",
- "hasAction": true,
- "data": {
- "exportName": "MyClass",
- "exportMapKey": "7 * MyClass ",
- "fileName": "/user/username/projects/shared/src/index.ts"
- }
}
],
"defaultCommitCharacters": [
@@ -898,6 +891,12 @@ Info seq [hh:mm:ss:mss] response:
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
+ {
+ "name": "MyClass",
+ "kind": "alias",
+ "kindModifiers": "export",
+ "sortText": "11"
+ },
{
"name": "abstract",
"kind": "keyword",
@@ -1305,19 +1304,6 @@ Info seq [hh:mm:ss:mss] response:
"kind": "keyword",
"kindModifiers": "",
"sortText": "15"
- },
- {
- "name": "MyClass",
- "kind": "class",
- "kindModifiers": "export",
- "sortText": "16",
- "source": "/user/username/projects/shared/src/index",
- "hasAction": true,
- "data": {
- "exportName": "MyClass",
- "exportMapKey": "7 * MyClass ",
- "fileName": "/user/username/projects/shared/src/index.ts"
- }
}
],
"defaultCommitCharacters": [
@@ -1401,6 +1387,12 @@ Info seq [hh:mm:ss:mss] response:
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
+ {
+ "name": "MyClass",
+ "kind": "alias",
+ "kindModifiers": "export",
+ "sortText": "11"
+ },
{
"name": "abstract",
"kind": "keyword",
@@ -1808,19 +1800,6 @@ Info seq [hh:mm:ss:mss] response:
"kind": "keyword",
"kindModifiers": "",
"sortText": "15"
- },
- {
- "name": "MyClass",
- "kind": "class",
- "kindModifiers": "export",
- "sortText": "16",
- "source": "/user/username/projects/shared/src/index",
- "hasAction": true,
- "data": {
- "exportName": "MyClass",
- "exportMapKey": "7 * MyClass ",
- "fileName": "/user/username/projects/shared/src/index.ts"
- }
}
],
"defaultCommitCharacters": [
@@ -1922,6 +1901,12 @@ Info seq [hh:mm:ss:mss] response:
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
+ {
+ "name": "MyClass",
+ "kind": "alias",
+ "kindModifiers": "export",
+ "sortText": "11"
+ },
{
"name": "abstract",
"kind": "keyword",
@@ -2329,19 +2314,6 @@ Info seq [hh:mm:ss:mss] response:
"kind": "keyword",
"kindModifiers": "",
"sortText": "15"
- },
- {
- "name": "MyClass",
- "kind": "class",
- "kindModifiers": "export",
- "sortText": "16",
- "source": "/user/username/projects/shared/src/index",
- "hasAction": true,
- "data": {
- "exportName": "MyClass",
- "exportMapKey": "7 * MyClass ",
- "fileName": "/user/username/projects/shared/src/index.ts"
- }
}
],
"defaultCommitCharacters": [
diff --git a/tests/baselines/reference/tsserver/completions/in-project-reference-setup-with-path-mapping-with-existing-import.js b/tests/baselines/reference/tsserver/completions/in-project-reference-setup-with-path-mapping-with-existing-import.js
index d2bb01734c1f6..51b48dffffcbc 100644
--- a/tests/baselines/reference/tsserver/completions/in-project-reference-setup-with-path-mapping-with-existing-import.js
+++ b/tests/baselines/reference/tsserver/completions/in-project-reference-setup-with-path-mapping-with-existing-import.js
@@ -436,6 +436,12 @@ Info seq [hh:mm:ss:mss] response:
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
+ {
+ "name": "MyClass",
+ "kind": "alias",
+ "kindModifiers": "export",
+ "sortText": "11"
+ },
{
"name": "abstract",
"kind": "keyword",
@@ -844,19 +850,6 @@ Info seq [hh:mm:ss:mss] response:
"kindModifiers": "",
"sortText": "15"
},
- {
- "name": "MyClass",
- "kind": "class",
- "kindModifiers": "export",
- "sortText": "16",
- "source": "/user/username/projects/shared/src/index",
- "hasAction": true,
- "data": {
- "exportName": "MyClass",
- "exportMapKey": "7 * MyClass ",
- "fileName": "/user/username/projects/shared/src/index.ts"
- }
- },
{
"name": "MyHelper",
"kind": "class",
@@ -966,6 +959,12 @@ Info seq [hh:mm:ss:mss] response:
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
+ {
+ "name": "MyClass",
+ "kind": "alias",
+ "kindModifiers": "export",
+ "sortText": "11"
+ },
{
"name": "abstract",
"kind": "keyword",
@@ -1374,19 +1373,6 @@ Info seq [hh:mm:ss:mss] response:
"kindModifiers": "",
"sortText": "15"
},
- {
- "name": "MyClass",
- "kind": "class",
- "kindModifiers": "export",
- "sortText": "16",
- "source": "/user/username/projects/shared/src/index",
- "hasAction": true,
- "data": {
- "exportName": "MyClass",
- "exportMapKey": "7 * MyClass ",
- "fileName": "/user/username/projects/shared/src/index.ts"
- }
- },
{
"name": "MyHelper",
"kind": "class",
@@ -1564,6 +1550,12 @@ Info seq [hh:mm:ss:mss] response:
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
+ {
+ "name": "MyClass",
+ "kind": "alias",
+ "kindModifiers": "export",
+ "sortText": "11"
+ },
{
"name": "abstract",
"kind": "keyword",
@@ -1972,19 +1964,6 @@ Info seq [hh:mm:ss:mss] response:
"kindModifiers": "",
"sortText": "15"
},
- {
- "name": "MyClass",
- "kind": "class",
- "kindModifiers": "export",
- "sortText": "16",
- "source": "/user/username/projects/shared/src/index",
- "hasAction": true,
- "data": {
- "exportName": "MyClass",
- "exportMapKey": "7 * MyClass ",
- "fileName": "/user/username/projects/shared/src/index.ts"
- }
- },
{
"name": "MyHelper",
"kind": "class",
@@ -2113,6 +2092,12 @@ Info seq [hh:mm:ss:mss] response:
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
+ {
+ "name": "MyClass",
+ "kind": "alias",
+ "kindModifiers": "export",
+ "sortText": "11"
+ },
{
"name": "abstract",
"kind": "keyword",
@@ -2520,19 +2505,6 @@ Info seq [hh:mm:ss:mss] response:
"kind": "keyword",
"kindModifiers": "",
"sortText": "15"
- },
- {
- "name": "MyClass",
- "kind": "class",
- "kindModifiers": "export",
- "sortText": "16",
- "source": "/user/username/projects/shared/src/index",
- "hasAction": true,
- "data": {
- "exportName": "MyClass",
- "exportMapKey": "7 * MyClass ",
- "fileName": "/user/username/projects/shared/src/index.ts"
- }
}
],
"defaultCommitCharacters": [
diff --git a/tests/cases/fourslash/asOperatorCompletion2.ts b/tests/cases/fourslash/asOperatorCompletion2.ts
new file mode 100644
index 0000000000000..feb1c37930b91
--- /dev/null
+++ b/tests/cases/fourslash/asOperatorCompletion2.ts
@@ -0,0 +1,9 @@
+///
+
+//// type T = number;
+//// var x;
+//// var y = x as /**/
+////
+
+verify.completions({ marker: "", includes: "T" });
+
diff --git a/tests/cases/fourslash/asOperatorCompletion3.ts b/tests/cases/fourslash/asOperatorCompletion3.ts
new file mode 100644
index 0000000000000..d7840d8baa3f8
--- /dev/null
+++ b/tests/cases/fourslash/asOperatorCompletion3.ts
@@ -0,0 +1,8 @@
+///
+
+//// type T = number;
+//// var x;
+//// var y = x as /**/ // comment
+
+verify.completions({ marker: "", includes: "T" });
+