Skip to content

Commit 916f9b7

Browse files
authored
Handle jsx runtime implicit synthetic import in find all references (#51319)
1 parent 8947825 commit 916f9b7

6 files changed

+163
-3
lines changed

src/services/findAllReferences.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
escapeLeadingUnderscores,
3030
ExportSpecifier,
3131
Expression,
32+
externalHelpersModuleNameText,
3233
FileIncludeReason,
3334
FileReference,
3435
filter,
@@ -41,6 +42,7 @@ import {
4142
firstOrUndefined,
4243
flatMap,
4344
forEachChild,
45+
forEachChildRecursively,
4446
forEachReturnStatement,
4547
ForInOrOfStatement,
4648
FunctionDeclaration,
@@ -130,6 +132,8 @@ import {
130132
isJSDocMemberName,
131133
isJSDocTag,
132134
isJsxClosingElement,
135+
isJsxElement,
136+
isJsxFragment,
133137
isJsxOpeningElement,
134138
isJsxSelfClosingElement,
135139
isJumpStatementTarget,
@@ -231,6 +235,7 @@ import {
231235
textPart,
232236
TextSpan,
233237
tokenToString,
238+
TransformFlags,
234239
tryAddToSet,
235240
tryCast,
236241
tryGetClassExtendingExpressionWithTypeArguments,
@@ -1125,6 +1130,14 @@ export namespace Core {
11251130
// import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway.
11261131
return nodeEntry(reference.literal);
11271132
}
1133+
else if (reference.kind === "implicit") {
1134+
// Return either: The first JSX node in the (if not a tslib import), the first statement of the file, or the whole file if neither of those exist
1135+
const range = reference.literal.text !== externalHelpersModuleNameText && forEachChildRecursively(
1136+
reference.referencingFile,
1137+
n => !(n.transformFlags & TransformFlags.ContainsJsx) ? "skip" : isJsxElement(n) || isJsxSelfClosingElement(n) || isJsxFragment(n) ? n : undefined
1138+
) || reference.referencingFile.statements[0] || reference.referencingFile;
1139+
return nodeEntry(range);
1140+
}
11281141
else {
11291142
return {
11301143
kind: EntryKind.Span,

src/services/importTracker.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import {
6363
NamedImportsOrExports,
6464
NamespaceImport,
6565
Node,
66+
nodeIsSynthesized,
6667
nodeSeenTracker,
6768
Program,
6869
some,
@@ -450,7 +451,10 @@ export type ModuleReference =
450451
/** "import" also includes require() calls. */
451452
| { kind: "import", literal: StringLiteralLike }
452453
/** <reference path> or <reference types> */
453-
| { kind: "reference", referencingFile: SourceFile, ref: FileReference };
454+
| { kind: "reference", referencingFile: SourceFile, ref: FileReference }
455+
/** Containing file implicitly references the module (eg, via implicit jsx runtime import) */
456+
| { kind: "implicit", literal: StringLiteralLike, referencingFile: SourceFile };
457+
454458
/** @internal */
455459
export function findModuleReferences(program: Program, sourceFiles: readonly SourceFile[], searchModuleSymbol: Symbol): ModuleReference[] {
456460
const refs: ModuleReference[] = [];
@@ -471,10 +475,10 @@ export function findModuleReferences(program: Program, sourceFiles: readonly Sou
471475
}
472476
}
473477

474-
forEachImport(referencingFile, (_importDecl, moduleSpecifier) => {
478+
forEachImport(referencingFile, (importDecl, moduleSpecifier) => {
475479
const moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier);
476480
if (moduleSymbol === searchModuleSymbol) {
477-
refs.push({ kind: "import", literal: moduleSpecifier });
481+
refs.push(nodeIsSynthesized(importDecl) ? { kind: "implicit", literal: moduleSpecifier, referencingFile } : { kind: "import", literal: moduleSpecifier });
478482
}
479483
});
480484
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// === findAllReferences ===
2+
// === /tests/cases/fourslash/project/src/dir/jsx-runtime.ts ===
3+
// [|export {}|]
4+
5+
// === /tests/cases/fourslash/project/src/foo.ts ===
6+
// [|<|import * as x from /*FIND ALL REFS*/"[|@foo/dir/jsx-runtime|]";|]|>
7+
8+
// === /tests/cases/fourslash/project/src/bar.tsx ===
9+
// <|export default [|<div></div>|];|>
10+
11+
// === /tests/cases/fourslash/project/src/baz.tsx ===
12+
// <|export default [|<></>|];|>
13+
14+
// === /tests/cases/fourslash/project/src/bam.tsx ===
15+
// <|export default [|<script src=""/>|];|>
16+
17+
// === /tests/cases/fourslash/project/src/bat.tsx ===
18+
// [|export const a = 1;|]
19+
20+
// === /tests/cases/fourslash/project/src/bal.tsx ===
21+
// [||]
22+
23+
// === Definitions ===
24+
// === /tests/cases/fourslash/project/src/dir/jsx-runtime.ts ===
25+
// [|export {}|]
26+
27+
// === Details ===
28+
[
29+
{
30+
"containerKind": "",
31+
"containerName": "",
32+
"kind": "module",
33+
"name": "module \"/tests/cases/fourslash/project/src/dir/jsx-runtime\"",
34+
"displayParts": [
35+
{
36+
"text": "module",
37+
"kind": "keyword"
38+
},
39+
{
40+
"text": " ",
41+
"kind": "space"
42+
},
43+
{
44+
"text": "\"/tests/cases/fourslash/project/src/dir/jsx-runtime\"",
45+
"kind": "stringLiteral"
46+
}
47+
]
48+
}
49+
]
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// === findAllReferences ===
2+
// === /tests/cases/fourslash/project/src/foo.ts ===
3+
// [|<|import * as x from /*FIND ALL REFS*/"[|tslib|]";|]|>
4+
5+
// === /tests/cases/fourslash/project/src/bar.ts ===
6+
// [|export default "";|]
7+
8+
// === /tests/cases/fourslash/project/src/bal.ts ===
9+
// [||]
10+
11+
// === Definitions ===
12+
// === /tests/cases/fourslash/project/src/dir/tslib.d.ts ===
13+
// [|export function __importDefault(...args: any): any;
14+
// export function __importStar(...args: any): any;|]
15+
16+
// === Details ===
17+
[
18+
{
19+
"containerKind": "",
20+
"containerName": "",
21+
"kind": "module",
22+
"name": "module \"/tests/cases/fourslash/project/src/dir/tslib\"",
23+
"displayParts": [
24+
{
25+
"text": "module",
26+
"kind": "keyword"
27+
},
28+
{
29+
"text": " ",
30+
"kind": "space"
31+
},
32+
{
33+
"text": "\"/tests/cases/fourslash/project/src/dir/tslib\"",
34+
"kind": "stringLiteral"
35+
}
36+
]
37+
}
38+
]
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @Filename: project/src/foo.ts
4+
////import * as x from /**/"@foo/dir/jsx-runtime";
5+
// @Filename: project/src/bar.tsx
6+
////export default <div></div>;
7+
// @Filename: project/src/baz.tsx
8+
////export default <></>;
9+
// @Filename: project/src/bam.tsx
10+
////export default <script src=""/>;
11+
// @Filename: project/src/bat.tsx
12+
////export const a = 1;
13+
// @Filename: project/src/bal.tsx
14+
////
15+
// @Filename: project/src/dir/jsx-runtime.ts
16+
////export {}
17+
// @Filename: project/tsconfig.json
18+
////{
19+
//// "compilerOptions": {
20+
//// "moduleResolution": "node",
21+
//// "module": "es2020",
22+
//// "jsx": "react-jsx",
23+
//// "jsxImportSource": "@foo/dir",
24+
//// "moduleDetection": "force",
25+
//// "paths": {
26+
//// "@foo/dir/jsx-runtime": ["./src/dir/jsx-runtime"]
27+
//// }
28+
//// }
29+
////}
30+
31+
verify.baselineFindAllReferences("");
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @Filename: project/src/foo.ts
4+
////import * as x from /**/"tslib";
5+
// @Filename: project/src/bar.ts
6+
////export default "";
7+
// @Filename: project/src/bal.ts
8+
////
9+
// @Filename: project/src/dir/tslib.d.ts
10+
////export function __importDefault(...args: any): any;
11+
////export function __importStar(...args: any): any;
12+
// @Filename: project/tsconfig.json
13+
////{
14+
//// "compilerOptions": {
15+
//// "moduleResolution": "node",
16+
//// "module": "es2020",
17+
//// "importHelpers": true,
18+
//// "moduleDetection": "force",
19+
//// "paths": {
20+
//// "tslib": ["./src/dir/tslib"]
21+
//// }
22+
//// }
23+
////}
24+
25+
verify.baselineFindAllReferences("");

0 commit comments

Comments
 (0)