Skip to content

Commit b1d821a

Browse files
authored
Fixed crash in go to definition related to expando classes in JS files (#57628)
1 parent 42f238b commit b1d821a

File tree

5 files changed

+100
-4
lines changed

5 files changed

+100
-4
lines changed

src/services/goToDefinition.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
createTextSpanFromBounds,
1010
createTextSpanFromNode,
1111
createTextSpanFromRange,
12-
Debug,
1312
Declaration,
1413
DefinitionInfo,
1514
DefinitionInfoAndBoundSpan,
@@ -581,16 +580,20 @@ function isExpandoDeclaration(node: Declaration): boolean {
581580

582581
function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node, failedAliasResolution?: boolean, excludeDeclaration?: Node): DefinitionInfo[] | undefined {
583582
const filteredDeclarations = filter(symbol.declarations, d => d !== excludeDeclaration);
583+
const signatureDefinition = getConstructSignatureDefinition() || getCallSignatureDefinition();
584+
if (signatureDefinition) {
585+
return signatureDefinition;
586+
}
584587
const withoutExpandos = filter(filteredDeclarations, d => !isExpandoDeclaration(d));
585588
const results = some(withoutExpandos) ? withoutExpandos : filteredDeclarations;
586-
return getConstructSignatureDefinition() || getCallSignatureDefinition() || map(results, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution));
589+
return map(results, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution));
587590

588591
function getConstructSignatureDefinition(): DefinitionInfo[] | undefined {
589592
// Applicable only if we are in a new expression, or we are on a constructor declaration
590593
// and in either case the symbol has a construct signature definition, i.e. class
591594
if (symbol.flags & SymbolFlags.Class && !(symbol.flags & (SymbolFlags.Function | SymbolFlags.Variable)) && (isNewExpressionTarget(node) || node.kind === SyntaxKind.ConstructorKeyword)) {
592-
const cls = find(filteredDeclarations, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration");
593-
return getSignatureDefinition(cls.members, /*selectConstructors*/ true);
595+
const cls = find(filteredDeclarations, isClassLike);
596+
return cls && getSignatureDefinition(cls.members, /*selectConstructors*/ true);
594597
}
595598
}
596599

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// === goToDefinition ===
2+
// === /tests/cases/fourslash/index.js ===
3+
// const Core = {}
4+
//
5+
// <|Core.[|Test|]|> = class { }
6+
//
7+
// Core.Test.prototype.foo = 10
8+
//
9+
// new Core.Tes/*GOTO DEF*/t()
10+
11+
// === Details ===
12+
[
13+
{
14+
"kind": "property",
15+
"name": "Test",
16+
"containerName": "Core",
17+
"isLocal": true,
18+
"isAmbient": false,
19+
"unverified": false,
20+
"failedAliasResolution": false
21+
}
22+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// === goToDefinition ===
2+
// === /tests/cases/fourslash/index.js ===
3+
// const Core = {}
4+
//
5+
// <|Core.[|{| defId: 0 |}Test|]|> = class {
6+
// [|{| defId: 1 |}constructor() { }|]
7+
// }
8+
//
9+
// Core.Test.prototype.foo = 10
10+
//
11+
// new Core.Tes/*GOTO DEF*/t()
12+
13+
// === Details ===
14+
[
15+
{
16+
"defId": 0,
17+
"kind": "property",
18+
"name": "Test",
19+
"containerName": "Core",
20+
"isLocal": true,
21+
"isAmbient": false,
22+
"unverified": false,
23+
"failedAliasResolution": false
24+
},
25+
{
26+
"defId": 1,
27+
"kind": "constructor",
28+
"name": "__constructor",
29+
"containerName": "Test",
30+
"isLocal": true,
31+
"isAmbient": false,
32+
"unverified": false,
33+
"failedAliasResolution": false
34+
}
35+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @strict: true
4+
// @allowJs: true
5+
// @checkJs: true
6+
7+
// @filename: index.js
8+
9+
//// const Core = {}
10+
////
11+
//// Core.Test = class { }
12+
////
13+
//// Core.Test.prototype.foo = 10
14+
////
15+
//// new Core.Tes/*1*/t()
16+
17+
verify.baselineGoToDefinition("1");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @strict: true
4+
// @allowJs: true
5+
// @checkJs: true
6+
7+
// @filename: index.js
8+
9+
//// const Core = {}
10+
////
11+
//// Core.Test = class {
12+
//// constructor() { }
13+
//// }
14+
////
15+
//// Core.Test.prototype.foo = 10
16+
////
17+
//// new Core.Tes/*1*/t()
18+
19+
verify.baselineGoToDefinition("1");

0 commit comments

Comments
 (0)