Skip to content

Commit 537695c

Browse files
author
Andy
authored
In TypeScript code, never bind JSDoc normally, just set parent pointers (#16555)
1 parent 675e7f0 commit 537695c

File tree

4 files changed

+49
-18
lines changed

4 files changed

+49
-18
lines changed

src/compiler/binder.ts

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,19 @@ namespace ts {
595595
// Binding of JsDocComment should be done before the current block scope container changes.
596596
// because the scope of JsDocComment should not be affected by whether the current node is a
597597
// container or not.
598-
forEach(node.jsDoc, bind);
598+
if (node.jsDoc) {
599+
if (isInJavaScriptFile(node)) {
600+
for (const j of node.jsDoc) {
601+
bind(j);
602+
}
603+
}
604+
else {
605+
for (const j of node.jsDoc) {
606+
setParentPointers(node, j);
607+
}
608+
}
609+
}
610+
599611
if (checkUnreachable(node)) {
600612
bindEachChild(node);
601613
return;
@@ -1903,7 +1915,7 @@ namespace ts {
19031915
// Here the current node is "foo", which is a container, but the scope of "MyType" should
19041916
// not be inside "foo". Therefore we always bind @typedef before bind the parent node,
19051917
// and skip binding this tag later when binding all the other jsdoc tags.
1906-
bindJSDocTypedefTagIfAny(node);
1918+
if (isInJavaScriptFile(node)) bindJSDocTypedefTagIfAny(node);
19071919

19081920
// First we bind declaration nodes to a symbol if possible. We'll both create a symbol
19091921
// and then potentially add the symbol to an appropriate symbol table. Possible
@@ -1991,7 +2003,7 @@ namespace ts {
19912003
// for typedef type names with namespaces, bind the new jsdoc type symbol here
19922004
// because it requires all containing namespaces to be in effect, namely the
19932005
// current "blockScopeContainer" needs to be set to its immediate namespace parent.
1994-
if (isInJavaScriptFile(node) && (<Identifier>node).isInJSDocNamespace) {
2006+
if ((<Identifier>node).isInJSDocNamespace) {
19952007
let parentNode = node.parent;
19962008
while (parentNode && parentNode.kind !== SyntaxKind.JSDocTypedefTag) {
19972009
parentNode = parentNode.parent;
@@ -2053,10 +2065,7 @@ namespace ts {
20532065
case SyntaxKind.TypePredicate:
20542066
return checkTypePredicate(node as TypePredicateNode);
20552067
case SyntaxKind.TypeParameter:
2056-
if (node.parent.kind !== ts.SyntaxKind.JSDocTemplateTag || isInJavaScriptFile(node)) {
2057-
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
2058-
}
2059-
return;
2068+
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
20602069
case SyntaxKind.Parameter:
20612070
return bindParameter(<ParameterDeclaration>node);
20622071
case SyntaxKind.VariableDeclaration:
@@ -2138,10 +2147,7 @@ namespace ts {
21382147
case SyntaxKind.EnumDeclaration:
21392148
return bindEnumDeclaration(<EnumDeclaration>node);
21402149
case SyntaxKind.ModuleDeclaration:
2141-
if (node.parent.kind !== ts.SyntaxKind.JSDocTypedefTag || isInJavaScriptFile(node)) {
2142-
return bindModuleDeclaration(<ModuleDeclaration>node);
2143-
}
2144-
return undefined;
2150+
return bindModuleDeclaration(<ModuleDeclaration>node);
21452151
// Jsx-attributes
21462152
case SyntaxKind.JsxAttributes:
21472153
return bindJsxAttributes(<JsxAttributes>node);
@@ -2173,13 +2179,6 @@ namespace ts {
21732179
case SyntaxKind.ModuleBlock:
21742180
return updateStrictModeStatementList((<Block | ModuleBlock>node).statements);
21752181

2176-
default:
2177-
if (isInJavaScriptFile(node)) return bindJSDocWorker(node);
2178-
}
2179-
}
2180-
2181-
function bindJSDocWorker(node: Node) {
2182-
switch (node.kind) {
21832182
case SyntaxKind.JSDocRecordMember:
21842183
return bindPropertyWorker(node as JSDocRecordMember);
21852184
case SyntaxKind.JSDocPropertyTag:
@@ -3605,4 +3604,13 @@ namespace ts {
36053604
return TransformFlags.NodeExcludes;
36063605
}
36073606
}
3607+
3608+
/**
3609+
* "Binds" JSDoc nodes in TypeScript code.
3610+
* Since we will never create symbols for JSDoc, we just set parent pointers instead.
3611+
*/
3612+
function setParentPointers(parent: Node, child: Node): void {
3613+
child.parent = parent;
3614+
forEachChild(child, (childsChild) => setParentPointers(child, childsChild));
3615+
}
36083616
}

tests/baselines/reference/jsdocInTypeScript.errors.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,10 @@ tests/cases/compiler/jsdocInTypeScript.ts(42,12): error TS2503: Cannot find name
6161
import M = N; // Error: @typedef does not create namespaces in TypeScript code.
6262
~
6363
!!! error TS2503: Cannot find namespace 'N'.
64+
65+
// Not legal JSDoc, but that shouldn't matter in TypeScript.
66+
/**
67+
* @type {{foo: (function(string, string): string)}}
68+
*/
69+
const obj = { foo: (a, b) => a + b };
6470

tests/baselines/reference/jsdocInTypeScript.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ let i: I; // Should succeed thanks to type parameter default
4141

4242
/** @typedef {string} N.Str */
4343
import M = N; // Error: @typedef does not create namespaces in TypeScript code.
44+
45+
// Not legal JSDoc, but that shouldn't matter in TypeScript.
46+
/**
47+
* @type {{foo: (function(string, string): string)}}
48+
*/
49+
const obj = { foo: (a, b) => a + b };
4450

4551

4652
//// [jsdocInTypeScript.js]
@@ -68,3 +74,8 @@ function tem(t) { return {}; }
6874
var i; // Should succeed thanks to type parameter default
6975
/** @typedef {string} N.Str */
7076
var M = N; // Error: @typedef does not create namespaces in TypeScript code.
77+
// Not legal JSDoc, but that shouldn't matter in TypeScript.
78+
/**
79+
* @type {{foo: (function(string, string): string)}}
80+
*/
81+
var obj = { foo: function (a, b) { return a + b; } };

tests/cases/compiler/jsdocInTypeScript.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,9 @@ let i: I; // Should succeed thanks to type parameter default
4040

4141
/** @typedef {string} N.Str */
4242
import M = N; // Error: @typedef does not create namespaces in TypeScript code.
43+
44+
// Not legal JSDoc, but that shouldn't matter in TypeScript.
45+
/**
46+
* @type {{foo: (function(string, string): string)}}
47+
*/
48+
const obj = { foo: (a, b) => a + b };

0 commit comments

Comments
 (0)