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
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 });
}
});
}