Handle jsx runtime implicit synthetic import in find all references (#51319)

This commit is contained in:
Wesley Wigham 2023-03-23 12:08:52 -07:00 committed by GitHub
parent 89478254c8
commit 916f9b7344
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 163 additions and 3 deletions

View File

@ -29,6 +29,7 @@ import {
escapeLeadingUnderscores,
ExportSpecifier,
Expression,
externalHelpersModuleNameText,
FileIncludeReason,
FileReference,
filter,
@ -41,6 +42,7 @@ import {
firstOrUndefined,
flatMap,
forEachChild,
forEachChildRecursively,
forEachReturnStatement,
ForInOrOfStatement,
FunctionDeclaration,
@ -130,6 +132,8 @@ import {
isJSDocMemberName,
isJSDocTag,
isJsxClosingElement,
isJsxElement,
isJsxFragment,
isJsxOpeningElement,
isJsxSelfClosingElement,
isJumpStatementTarget,
@ -231,6 +235,7 @@ import {
textPart,
TextSpan,
tokenToString,
TransformFlags,
tryAddToSet,
tryCast,
tryGetClassExtendingExpressionWithTypeArguments,
@ -1125,6 +1130,14 @@ export namespace Core {
// import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway.
return nodeEntry(reference.literal);
}
else if (reference.kind === "implicit") {
// 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
const range = reference.literal.text !== externalHelpersModuleNameText && forEachChildRecursively(
reference.referencingFile,
n => !(n.transformFlags & TransformFlags.ContainsJsx) ? "skip" : isJsxElement(n) || isJsxSelfClosingElement(n) || isJsxFragment(n) ? n : undefined
) || reference.referencingFile.statements[0] || reference.referencingFile;
return nodeEntry(range);
}
else {
return {
kind: EntryKind.Span,

View File

@ -63,6 +63,7 @@ import {
NamedImportsOrExports,
NamespaceImport,
Node,
nodeIsSynthesized,
nodeSeenTracker,
Program,
some,
@ -450,7 +451,10 @@ export type ModuleReference =
/** "import" also includes require() calls. */
| { kind: "import", literal: StringLiteralLike }
/** <reference path> or <reference types> */
| { kind: "reference", referencingFile: SourceFile, ref: FileReference };
| { kind: "reference", referencingFile: SourceFile, ref: FileReference }
/** Containing file implicitly references the module (eg, via implicit jsx runtime import) */
| { kind: "implicit", literal: StringLiteralLike, referencingFile: SourceFile };
/** @internal */
export function findModuleReferences(program: Program, sourceFiles: readonly SourceFile[], searchModuleSymbol: Symbol): ModuleReference[] {
const refs: ModuleReference[] = [];
@ -471,10 +475,10 @@ export function findModuleReferences(program: Program, sourceFiles: readonly Sou
}
}
forEachImport(referencingFile, (_importDecl, moduleSpecifier) => {
forEachImport(referencingFile, (importDecl, moduleSpecifier) => {
const moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier);
if (moduleSymbol === searchModuleSymbol) {
refs.push({ kind: "import", literal: moduleSpecifier });
refs.push(nodeIsSynthesized(importDecl) ? { kind: "implicit", literal: moduleSpecifier, referencingFile } : { kind: "import", literal: moduleSpecifier });
}
});
}

View File

@ -0,0 +1,49 @@
// === findAllReferences ===
// === /tests/cases/fourslash/project/src/dir/jsx-runtime.ts ===
// [|export {}|]
// === /tests/cases/fourslash/project/src/foo.ts ===
// [|<|import * as x from /*FIND ALL REFS*/"[|@foo/dir/jsx-runtime|]";|]|>
// === /tests/cases/fourslash/project/src/bar.tsx ===
// <|export default [|<div></div>|];|>
// === /tests/cases/fourslash/project/src/baz.tsx ===
// <|export default [|<></>|];|>
// === /tests/cases/fourslash/project/src/bam.tsx ===
// <|export default [|<script src=""/>|];|>
// === /tests/cases/fourslash/project/src/bat.tsx ===
// [|export const a = 1;|]
// === /tests/cases/fourslash/project/src/bal.tsx ===
// [||]
// === Definitions ===
// === /tests/cases/fourslash/project/src/dir/jsx-runtime.ts ===
// [|export {}|]
// === Details ===
[
{
"containerKind": "",
"containerName": "",
"kind": "module",
"name": "module \"/tests/cases/fourslash/project/src/dir/jsx-runtime\"",
"displayParts": [
{
"text": "module",
"kind": "keyword"
},
{
"text": " ",
"kind": "space"
},
{
"text": "\"/tests/cases/fourslash/project/src/dir/jsx-runtime\"",
"kind": "stringLiteral"
}
]
}
]

View File

@ -0,0 +1,38 @@
// === findAllReferences ===
// === /tests/cases/fourslash/project/src/foo.ts ===
// [|<|import * as x from /*FIND ALL REFS*/"[|tslib|]";|]|>
// === /tests/cases/fourslash/project/src/bar.ts ===
// [|export default "";|]
// === /tests/cases/fourslash/project/src/bal.ts ===
// [||]
// === Definitions ===
// === /tests/cases/fourslash/project/src/dir/tslib.d.ts ===
// [|export function __importDefault(...args: any): any;
// export function __importStar(...args: any): any;|]
// === Details ===
[
{
"containerKind": "",
"containerName": "",
"kind": "module",
"name": "module \"/tests/cases/fourslash/project/src/dir/tslib\"",
"displayParts": [
{
"text": "module",
"kind": "keyword"
},
{
"text": " ",
"kind": "space"
},
{
"text": "\"/tests/cases/fourslash/project/src/dir/tslib\"",
"kind": "stringLiteral"
}
]
}
]

View File

@ -0,0 +1,31 @@
/// <reference path="fourslash.ts" />
// @Filename: project/src/foo.ts
////import * as x from /**/"@foo/dir/jsx-runtime";
// @Filename: project/src/bar.tsx
////export default <div></div>;
// @Filename: project/src/baz.tsx
////export default <></>;
// @Filename: project/src/bam.tsx
////export default <script src=""/>;
// @Filename: project/src/bat.tsx
////export const a = 1;
// @Filename: project/src/bal.tsx
////
// @Filename: project/src/dir/jsx-runtime.ts
////export {}
// @Filename: project/tsconfig.json
////{
//// "compilerOptions": {
//// "moduleResolution": "node",
//// "module": "es2020",
//// "jsx": "react-jsx",
//// "jsxImportSource": "@foo/dir",
//// "moduleDetection": "force",
//// "paths": {
//// "@foo/dir/jsx-runtime": ["./src/dir/jsx-runtime"]
//// }
//// }
////}
verify.baselineFindAllReferences("");

View File

@ -0,0 +1,25 @@
/// <reference path="fourslash.ts" />
// @Filename: project/src/foo.ts
////import * as x from /**/"tslib";
// @Filename: project/src/bar.ts
////export default "";
// @Filename: project/src/bal.ts
////
// @Filename: project/src/dir/tslib.d.ts
////export function __importDefault(...args: any): any;
////export function __importStar(...args: any): any;
// @Filename: project/tsconfig.json
////{
//// "compilerOptions": {
//// "moduleResolution": "node",
//// "module": "es2020",
//// "importHelpers": true,
//// "moduleDetection": "force",
//// "paths": {
//// "tslib": ["./src/dir/tslib"]
//// }
//// }
////}
verify.baselineFindAllReferences("");