Skip to content

Commit ff6f947

Browse files
authored
Use regex+getTokenAtPosition to find dynamic import (#28104)
Instead of walking the entire tree. This stack overflows for large trees. Still need to adapt a test.
1 parent eadf44d commit ff6f947

File tree

1 file changed

+30
-20
lines changed

1 file changed

+30
-20
lines changed

src/compiler/program.ts

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,12 +1895,9 @@ namespace ts {
18951895

18961896
for (const node of file.statements) {
18971897
collectModuleReferences(node, /*inAmbientModule*/ false);
1898-
if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) {
1899-
collectDynamicImportOrRequireCalls(node);
1900-
}
19011898
}
19021899
if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) {
1903-
collectDynamicImportOrRequireCalls(file.endOfFileToken);
1900+
collectDynamicImportOrRequireCalls(file);
19041901
}
19051902

19061903
file.imports = imports || emptyArray;
@@ -1952,25 +1949,38 @@ namespace ts {
19521949
}
19531950
}
19541951

1955-
function collectDynamicImportOrRequireCalls(node: Node): void {
1956-
if (isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) {
1957-
imports = append(imports, node.arguments[0]);
1958-
}
1959-
// we have to check the argument list has length of 1. We will still have to process these even though we have parsing error.
1960-
else if (isImportCall(node) && node.arguments.length === 1 && isStringLiteralLike(node.arguments[0])) {
1961-
imports = append(imports, node.arguments[0] as StringLiteralLike);
1962-
}
1963-
else if (isLiteralImportTypeNode(node)) {
1964-
imports = append(imports, node.argument.literal);
1965-
}
1966-
collectDynamicImportOrRequireCallsForEachChild(node);
1967-
if (hasJSDocNodes(node)) {
1968-
forEach(node.jsDoc, collectDynamicImportOrRequireCallsForEachChild);
1952+
function collectDynamicImportOrRequireCalls(file: SourceFile) {
1953+
const r = /import|require/g;
1954+
while (r.exec(file.text) !== null) {
1955+
const node = getTokenAtPosition(file, r.lastIndex);
1956+
if (isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) {
1957+
imports = append(imports, node.arguments[0]);
1958+
}
1959+
// we have to check the argument list has length of 1. We will still have to process these even though we have parsing error.
1960+
else if (isImportCall(node) && node.arguments.length === 1 && isStringLiteralLike(node.arguments[0])) {
1961+
imports = append(imports, node.arguments[0] as StringLiteralLike);
1962+
}
1963+
else if (isLiteralImportTypeNode(node)) {
1964+
imports = append(imports, node.argument.literal);
1965+
}
19691966
}
19701967
}
19711968

1972-
function collectDynamicImportOrRequireCallsForEachChild(node: Node) {
1973-
forEachChild(node, collectDynamicImportOrRequireCalls);
1969+
/** Returns a token if position is in [start-of-leading-trivia, end) */
1970+
function getTokenAtPosition(sourceFile: SourceFile, position: number): Node {
1971+
let current: Node = sourceFile;
1972+
const getContainingChild = (child: Node) => {
1973+
if (child.pos <= position && (position < child.end || (position === child.end && (child.kind === SyntaxKind.EndOfFileToken)))) {
1974+
return child;
1975+
}
1976+
};
1977+
while (true) {
1978+
const child = hasJSDocNodes(current) && forEach(current.jsDoc, getContainingChild) || forEachChild(current, getContainingChild);
1979+
if (!child) {
1980+
return current;
1981+
}
1982+
current = child;
1983+
}
19741984
}
19751985
}
19761986

0 commit comments

Comments
 (0)