Skip to content

only search require calls in JS files #28168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/compiler/inspectValue.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// <reference types="@types/node"/>
/* @internal */
namespace ts {
export interface InspectValueOptions {
Expand Down
28 changes: 19 additions & 9 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2012,8 +2012,11 @@ namespace ts {
for (const node of file.statements) {
collectModuleReferences(node, /*inAmbientModule*/ false);
}
if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) {
collectDynamicImportOrRequireCalls(file);
if (file.flags & NodeFlags.PossiblyContainsDynamicImport) {
collectDynamicImports();
}
if (isJavaScriptFile) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can still keep this a single pass by passing regexp instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible, but IMO not very useful. It would save around 4 lines of code just to add new code to get determine the correct regexp to use. It also adds complexity by moving the regexp out of the function where its matches are used.
I doubt having a single pass of a complex regexp outperforms two passes with a simple regex each (also considering potential inlining).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will save pass I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like I already said: I don't think there will be a noticeable difference in performance because of optimizations in the VM (like inlining). It's not like we are walking the whole AST twice.

collectRequireCalls();
}

file.imports = imports || emptyArray;
Expand Down Expand Up @@ -2065,15 +2068,22 @@ namespace ts {
}
}

function collectDynamicImportOrRequireCalls(file: SourceFile) {
const r = /import|require/g;
function collectRequireCalls() {
const r = /\brequire\b/g;
while (r.exec(file.text) !== null) {
const node = getNodeAtPosition(file, r.lastIndex);
const node = getNodeAtPosition(r.lastIndex);
if (isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) {
imports = append(imports, node.arguments[0]);
}
}
}

function collectDynamicImports() {
const r = /\bimport\b/g;
while (r.exec(file.text) !== null) {
const node = getNodeAtPosition(r.lastIndex, isJavaScriptFile);
// we have to check the argument list has length of 1. We will still have to process these even though we have parsing error.
else if (isImportCall(node) && node.arguments.length === 1 && isStringLiteralLike(node.arguments[0])) {
if (isImportCall(node) && node.arguments.length === 1 && isStringLiteralLike(node.arguments[0])) {
imports = append(imports, node.arguments[0] as StringLiteralLike);
}
else if (isLiteralImportTypeNode(node)) {
Expand All @@ -2083,15 +2093,15 @@ namespace ts {
}

/** Returns a token if position is in [start-of-leading-trivia, end), includes JSDoc only in JS files */
function getNodeAtPosition(sourceFile: SourceFile, position: number): Node {
let current: Node = sourceFile;
function getNodeAtPosition(position: number, allowJsDoc?: boolean): Node {
let current: Node = file;
const getContainingChild = (child: Node) => {
if (child.pos <= position && (position < child.end || (position === child.end && (child.kind === SyntaxKind.EndOfFileToken)))) {
return child;
}
};
while (true) {
const child = isJavaScriptFile && hasJSDocNodes(current) && forEach(current.jsDoc, getContainingChild) || forEachChild(current, getContainingChild);
const child = allowJsDoc && hasJSDocNodes(current) && forEach(current.jsDoc, getContainingChild) || forEachChild(current, getContainingChild);
if (!child) {
return current;
}
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/sys.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/// <reference types="@types/node"/>

declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;

Expand Down
2 changes: 1 addition & 1 deletion tests/cases/user/prettier/prettier
Submodule prettier updated 1910 files