Fixed crash in go to definition related to expando classes in JS files (#57628)

This commit is contained in:
Mateusz Burzyński 2024-04-20 00:54:30 +01:00 коммит произвёл GitHub
Родитель 42f238bfbb
Коммит b1d821ae0c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
5 изменённых файлов: 100 добавлений и 4 удалений

Просмотреть файл

@ -9,7 +9,6 @@ import {
createTextSpanFromBounds,
createTextSpanFromNode,
createTextSpanFromRange,
Debug,
Declaration,
DefinitionInfo,
DefinitionInfoAndBoundSpan,
@ -581,16 +580,20 @@ function isExpandoDeclaration(node: Declaration): boolean {
function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node, failedAliasResolution?: boolean, excludeDeclaration?: Node): DefinitionInfo[] | undefined {
const filteredDeclarations = filter(symbol.declarations, d => d !== excludeDeclaration);
const signatureDefinition = getConstructSignatureDefinition() || getCallSignatureDefinition();
if (signatureDefinition) {
return signatureDefinition;
}
const withoutExpandos = filter(filteredDeclarations, d => !isExpandoDeclaration(d));
const results = some(withoutExpandos) ? withoutExpandos : filteredDeclarations;
return getConstructSignatureDefinition() || getCallSignatureDefinition() || map(results, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution));
return map(results, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution));
function getConstructSignatureDefinition(): DefinitionInfo[] | undefined {
// Applicable only if we are in a new expression, or we are on a constructor declaration
// and in either case the symbol has a construct signature definition, i.e. class
if (symbol.flags & SymbolFlags.Class && !(symbol.flags & (SymbolFlags.Function | SymbolFlags.Variable)) && (isNewExpressionTarget(node) || node.kind === SyntaxKind.ConstructorKeyword)) {
const cls = find(filteredDeclarations, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration");
return getSignatureDefinition(cls.members, /*selectConstructors*/ true);
const cls = find(filteredDeclarations, isClassLike);
return cls && getSignatureDefinition(cls.members, /*selectConstructors*/ true);
}
}

Просмотреть файл

@ -0,0 +1,22 @@
// === goToDefinition ===
// === /tests/cases/fourslash/index.js ===
// const Core = {}
//
// <|Core.[|Test|]|> = class { }
//
// Core.Test.prototype.foo = 10
//
// new Core.Tes/*GOTO DEF*/t()
// === Details ===
[
{
"kind": "property",
"name": "Test",
"containerName": "Core",
"isLocal": true,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]

Просмотреть файл

@ -0,0 +1,35 @@
// === goToDefinition ===
// === /tests/cases/fourslash/index.js ===
// const Core = {}
//
// <|Core.[|{| defId: 0 |}Test|]|> = class {
// [|{| defId: 1 |}constructor() { }|]
// }
//
// Core.Test.prototype.foo = 10
//
// new Core.Tes/*GOTO DEF*/t()
// === Details ===
[
{
"defId": 0,
"kind": "property",
"name": "Test",
"containerName": "Core",
"isLocal": true,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
},
{
"defId": 1,
"kind": "constructor",
"name": "__constructor",
"containerName": "Test",
"isLocal": true,
"isAmbient": false,
"unverified": false,
"failedAliasResolution": false
}
]

Просмотреть файл

@ -0,0 +1,17 @@
/// <reference path="fourslash.ts" />
// @strict: true
// @allowJs: true
// @checkJs: true
// @filename: index.js
//// const Core = {}
////
//// Core.Test = class { }
////
//// Core.Test.prototype.foo = 10
////
//// new Core.Tes/*1*/t()
verify.baselineGoToDefinition("1");

Просмотреть файл

@ -0,0 +1,19 @@
/// <reference path="fourslash.ts" />
// @strict: true
// @allowJs: true
// @checkJs: true
// @filename: index.js
//// const Core = {}
////
//// Core.Test = class {
//// constructor() { }
//// }
////
//// Core.Test.prototype.foo = 10
////
//// new Core.Tes/*1*/t()
verify.baselineGoToDefinition("1");