Skip to content

Commit

Permalink
Merge be5e6d4 into 6f6eff5
Browse files Browse the repository at this point in the history
  • Loading branch information
mrseanryan committed Mar 1, 2020
2 parents 6f6eff5 + be5e6d4 commit ec58c0c
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 11 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### Changed

- Handle dynamic import with dereferencing

## [6.0.0] - 24 Jan 2020

### Added
Expand Down
16 changes: 16 additions & 0 deletions features/include-dynamic-imports.feature
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,19 @@ Scenario: Dynamically import default function
"""
When analyzing "tsconfig.json"
Then the result is { "b.ts": ["B_unused"] }

Scenario: Dynamically import with dereference
Given file "a.ts" is
"""
export const A = 1;
export const A_unused = 2;
"""
And file "b.ts" is
"""
import("./a").then(A_imported => {
console.log(A_imported.A);
});
export const B_unused = 0;
"""
When analyzing "tsconfig.json"
Then the result is { "b.ts": ["B_unused"], "a.ts": ["A_unused"] }
60 changes: 49 additions & 11 deletions src/parser/dynamic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,50 @@ function isWithArguments(node: ts.Node): node is WithArguments {
return !!myInterface.arguments;
}

const recurseIntoChildren = (
next: ts.Node,
fun: (node: ts.Node) => void,
): void => {
fun(next);

next
.getChildren()
.filter(c => !namespaceBlacklist.includes(c.kind))
.forEach(node => recurseIntoChildren(node, fun));
};

/* Handle lambdas where the content uses imported types, via dereferencing.
* example:
* A_imported => {
* console.log(A_imported.A);
* }
*/
const findLambdasWithDereferencing = (node: ts.Node): string[] => {
const what: string[] = [];

const processLambda = (lambda: ts.Node): void => {
if (lambda.getChildCount() === 3) {
const paramName = lambda.getChildren()[0].getText();

const usagePrefix = `${paramName}.`;
recurseIntoChildren(lambda, child => {
if (child.getText().startsWith(usagePrefix)) {
const usage = child.getText().substring(usagePrefix.length);
what.push(usage);
}
});
}
};

recurseIntoChildren(node, child => {
if (child.kind === ts.SyntaxKind.ArrowFunction) {
processLambda(child);
}
});

return what;
};

export const addDynamicImports = (
node: ts.Node,
addImport: (fw: FromWhat) => void,
Expand All @@ -47,9 +91,11 @@ export const addDynamicImports = (
const importing = getArgumentFrom(expr);

if (!!importing) {
const what = ['default'].concat(findLambdasWithDereferencing(node));

addImport({
from: getFromText(importing),
what: ['default'],
what,
});
}
}
Expand All @@ -63,14 +109,6 @@ export const addDynamicImports = (
}
};

const recurseIntoChildren = (next: ts.Node): void => {
addImportsInAnyExpression(next);

next
.getChildren()
.filter(c => !namespaceBlacklist.includes(c.kind))
.forEach(recurseIntoChildren);
};

recurseIntoChildren(node);
// Recurse, since dynamic imports can occur at nested levels within the code
recurseIntoChildren(node, addImportsInAnyExpression);
};

0 comments on commit ec58c0c

Please sign in to comment.