mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-17 01:49:41 -05:00
Don't ignore completions at source file locations (#61909)
This commit is contained in:
committed by
GitHub
parent
479285d0ac
commit
78c16795cd
@@ -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;
|
||||
}
|
||||
// Filter out variables from their own initializers
|
||||
// `const a = /* no 'a' here */`
|
||||
if (closestSymbolDeclaration && tryCast(closestSymbolDeclaration, isVariableDeclaration)) {
|
||||
if (symbol.valueDeclaration === closestSymbolDeclaration) {
|
||||
return false;
|
||||
}
|
||||
// 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<T = /* no 'T' and 'T2' here */>(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;
|
||||
}
|
||||
}
|
||||
else if (isTypeParameterDeclaration(closestSymbolDeclaration) && isTypeParameterDeclaration(symbolDeclaration)) {
|
||||
if (closestSymbolDeclaration === symbolDeclaration && contextToken?.kind === SyntaxKind.ExtendsKeyword) {
|
||||
// filter out the directly self-recursive type parameters
|
||||
// `type A<K extends /* no 'K' here*/> = 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)
|
||||
) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
// const { a } = /* no 'a' here */;
|
||||
if (isBindingPattern(closestSymbolDeclaration.name) && closestSymbolDeclaration.name.elements.some(e => e === symbol.valueDeclaration)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isTypeOnlyLocation) {
|
||||
// It's a type, but you can reach it by namespace.type as well
|
||||
return symbolCanBeReferencedAtTypeLocation(symbol, typeChecker);
|
||||
// Filter out current and latter parameters from defaults
|
||||
// `function f(a = /* no 'a' and 'b' here */, b) { }` or
|
||||
// `function f<T = /* no 'T' and 'T2' here */>(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;
|
||||
}
|
||||
}
|
||||
else if (isTypeParameterDeclaration(closestSymbolDeclaration) && isTypeParameterDeclaration(symbolDeclaration)) {
|
||||
if (closestSymbolDeclaration === symbolDeclaration && contextToken?.kind === SyntaxKind.ExtendsKeyword) {
|
||||
// filter out the directly self-recursive type parameters
|
||||
// `type A<K extends /* no 'K' here*/> = 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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": [
|
||||
|
||||
9
tests/cases/fourslash/asOperatorCompletion2.ts
Normal file
9
tests/cases/fourslash/asOperatorCompletion2.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// type T = number;
|
||||
//// var x;
|
||||
//// var y = x as /**/
|
||||
////
|
||||
|
||||
verify.completions({ marker: "", includes: "T" });
|
||||
|
||||
8
tests/cases/fourslash/asOperatorCompletion3.ts
Normal file
8
tests/cases/fourslash/asOperatorCompletion3.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// type T = number;
|
||||
//// var x;
|
||||
//// var y = x as /**/ // comment
|
||||
|
||||
verify.completions({ marker: "", includes: "T" });
|
||||
|
||||
Reference in New Issue
Block a user