Skip to content

Commit d892fd4

Browse files
authored
Fix expando handling in getTypeReferenceType (microsoft#34712)
* Fix expando handling in getTypeReferenceType getExpandoSymbol looks for the initialiser of a symbol when it is an expando value (IIFEs, function exprs, class exprs and empty object literals) and returns the symbol. Previously, however, it returned the symbol of the initialiser without merging with the declaration symbol itself. This missed, in particular, the prototype assignment in the following pattern: ```js var x = function x() { this.y = 1 } x.prototype = { z() { } } /** @type {x} */ var xx; xx.z // missed! ``` getJSDocValueReference had weird try-again code that relied on calling getTypeOfSymbol, which *does* correctly merge the symbols. This PR re-removes that code and instead makes getExpandoSymbol call mergeJSSymbols itself. * Remove extra newline
1 parent 969634b commit d892fd4

File tree

4 files changed

+42
-47
lines changed

4 files changed

+42
-47
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2629,7 +2629,12 @@ namespace ts {
26292629
return undefined;
26302630
}
26312631
const init = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) : getAssignedExpandoInitializer(decl);
2632-
return init && getSymbolOfNode(init) || undefined;
2632+
if (init) {
2633+
const initSymbol = getSymbolOfNode(init);
2634+
if (initSymbol) {
2635+
return mergeJSSymbols(initSymbol, symbol);
2636+
}
2637+
}
26332638
}
26342639

26352640

@@ -10766,9 +10771,7 @@ namespace ts {
1076610771
&& isCallExpression(decl.initializer)
1076710772
&& isRequireCall(decl.initializer, /*requireStringLiteralLikeArgument*/ true)
1076810773
&& valueType.symbol;
10769-
const isImportType = node.kind === SyntaxKind.ImportType;
10770-
const isDelayedMergeClass = symbol !== valueType.symbol && getMergedSymbol(symbol) === valueType.symbol;
10771-
if (isRequireAlias || isImportType || isDelayedMergeClass) {
10774+
if (isRequireAlias || node.kind === SyntaxKind.ImportType) {
1077210775
typeType = getTypeReferenceType(node, valueType.symbol);
1077310776
}
1077410777
}
@@ -24997,7 +25000,7 @@ namespace ts {
2499725000
}
2499825001

2499925002
function mergeJSSymbols(target: Symbol, source: Symbol | undefined) {
25000-
if (source && (hasEntries(source.exports) || hasEntries(source.members))) {
25003+
if (source) {
2500125004
const links = getSymbolLinks(source);
2500225005
if (!links.inferredClassSymbol || !links.inferredClassSymbol.has("" + getSymbolId(target))) {
2500325006
const inferred = isTransientSymbol(target) ? target : cloneSymbol(target) as TransientSymbol;
Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,32 @@
1-
=== tests/cases/conformance/jsdoc/test.js ===
1+
=== tests/cases/conformance/jsdoc/jsdocTypeReferenceToMergedClass.js ===
22
// https://github.com/microsoft/TypeScript/issues/34685
33

4-
/** @param {Workspace.Project} p */
5-
function demo(p) {
6-
>demo : Symbol(demo, Decl(test.js, 0, 0))
7-
>p : Symbol(p, Decl(test.js, 3, 14))
8-
9-
p.isServiceProject()
10-
>p.isServiceProject : Symbol(isServiceProject, Decl(mod1.js, 3, 31))
11-
>p : Symbol(p, Decl(test.js, 3, 14))
12-
>isServiceProject : Symbol(isServiceProject, Decl(mod1.js, 3, 31))
13-
}
14-
=== tests/cases/conformance/jsdoc/mod1.js ===
15-
// Note: mod1.js needs to appear second to trigger the bug
164
var Workspace = {}
17-
>Workspace : Symbol(Workspace, Decl(mod1.js, 1, 3), Decl(mod1.js, 1, 18), Decl(mod1.js, 2, 37))
5+
>Workspace : Symbol(Workspace, Decl(jsdocTypeReferenceToMergedClass.js, 2, 3), Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 7, 37))
6+
7+
/** @type {Workspace.Project} */
8+
var p;
9+
>p : Symbol(p, Decl(jsdocTypeReferenceToMergedClass.js, 4, 3))
10+
11+
p.isServiceProject()
12+
>p.isServiceProject : Symbol(isServiceProject, Decl(jsdocTypeReferenceToMergedClass.js, 8, 31))
13+
>p : Symbol(p, Decl(jsdocTypeReferenceToMergedClass.js, 4, 3))
14+
>isServiceProject : Symbol(isServiceProject, Decl(jsdocTypeReferenceToMergedClass.js, 8, 31))
1815

1916
Workspace.Project = function wp() { }
20-
>Workspace.Project : Symbol(Workspace.Project, Decl(mod1.js, 1, 18), Decl(mod1.js, 3, 10))
21-
>Workspace : Symbol(Workspace, Decl(mod1.js, 1, 3), Decl(mod1.js, 1, 18), Decl(mod1.js, 2, 37))
22-
>Project : Symbol(Workspace.Project, Decl(mod1.js, 1, 18), Decl(mod1.js, 3, 10))
23-
>wp : Symbol(wp, Decl(mod1.js, 2, 19))
17+
>Workspace.Project : Symbol(Workspace.Project, Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 8, 10))
18+
>Workspace : Symbol(Workspace, Decl(jsdocTypeReferenceToMergedClass.js, 2, 3), Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 7, 37))
19+
>Project : Symbol(Workspace.Project, Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 8, 10))
20+
>wp : Symbol(wp, Decl(jsdocTypeReferenceToMergedClass.js, 7, 19))
2421

2522
Workspace.Project.prototype = {
26-
>Workspace.Project.prototype : Symbol(Workspace.Project.prototype, Decl(mod1.js, 2, 37))
27-
>Workspace.Project : Symbol(Workspace.Project, Decl(mod1.js, 1, 18), Decl(mod1.js, 3, 10))
28-
>Workspace : Symbol(Workspace, Decl(mod1.js, 1, 3), Decl(mod1.js, 1, 18), Decl(mod1.js, 2, 37))
29-
>Project : Symbol(Workspace.Project, Decl(mod1.js, 1, 18), Decl(mod1.js, 3, 10))
30-
>prototype : Symbol(Workspace.Project.prototype, Decl(mod1.js, 2, 37))
23+
>Workspace.Project.prototype : Symbol(Workspace.Project.prototype, Decl(jsdocTypeReferenceToMergedClass.js, 7, 37))
24+
>Workspace.Project : Symbol(Workspace.Project, Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 8, 10))
25+
>Workspace : Symbol(Workspace, Decl(jsdocTypeReferenceToMergedClass.js, 2, 3), Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 7, 37))
26+
>Project : Symbol(Workspace.Project, Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 8, 10))
27+
>prototype : Symbol(Workspace.Project.prototype, Decl(jsdocTypeReferenceToMergedClass.js, 7, 37))
3128

3229
isServiceProject() {}
33-
>isServiceProject : Symbol(isServiceProject, Decl(mod1.js, 3, 31))
30+
>isServiceProject : Symbol(isServiceProject, Decl(jsdocTypeReferenceToMergedClass.js, 8, 31))
3431
}
3532

tests/baselines/reference/jsdocTypeReferenceToMergedClass.types

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
1-
=== tests/cases/conformance/jsdoc/test.js ===
1+
=== tests/cases/conformance/jsdoc/jsdocTypeReferenceToMergedClass.js ===
22
// https://github.com/microsoft/TypeScript/issues/34685
33

4-
/** @param {Workspace.Project} p */
5-
function demo(p) {
6-
>demo : (p: wp) => void
4+
var Workspace = {}
5+
>Workspace : typeof Workspace
6+
>{} : {}
7+
8+
/** @type {Workspace.Project} */
9+
var p;
710
>p : wp
811

9-
p.isServiceProject()
12+
p.isServiceProject()
1013
>p.isServiceProject() : void
1114
>p.isServiceProject : () => void
1215
>p : wp
1316
>isServiceProject : () => void
14-
}
15-
=== tests/cases/conformance/jsdoc/mod1.js ===
16-
// Note: mod1.js needs to appear second to trigger the bug
17-
var Workspace = {}
18-
>Workspace : typeof Workspace
19-
>{} : {}
2017

2118
Workspace.Project = function wp() { }
2219
>Workspace.Project = function wp() { } : typeof wp

tests/cases/conformance/jsdoc/jsdocTypeReferenceToMergedClass.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@
33
// @allowJs: true
44
// @checkJs: true
55

6-
// @Filename: test.js
7-
/** @param {Workspace.Project} p */
8-
function demo(p) {
9-
p.isServiceProject()
10-
}
11-
// @Filename: mod1.js
12-
// Note: mod1.js needs to appear second to trigger the bug
6+
// @Filename: jsdocTypeReferenceToMergedClass.js
137
var Workspace = {}
8+
/** @type {Workspace.Project} */
9+
var p;
10+
p.isServiceProject()
11+
1412
Workspace.Project = function wp() { }
1513
Workspace.Project.prototype = {
1614
isServiceProject() {}

0 commit comments

Comments
 (0)