summaryrefslogtreecommitdiff
path: root/@linaria/packages/shaker/src/dumpNode.ts
diff options
context:
space:
mode:
Diffstat (limited to '@linaria/packages/shaker/src/dumpNode.ts')
-rw-r--r--@linaria/packages/shaker/src/dumpNode.ts63
1 files changed, 63 insertions, 0 deletions
diff --git a/@linaria/packages/shaker/src/dumpNode.ts b/@linaria/packages/shaker/src/dumpNode.ts
new file mode 100644
index 0000000..f6d1c84
--- /dev/null
+++ b/@linaria/packages/shaker/src/dumpNode.ts
@@ -0,0 +1,63 @@
+import { types as t } from '@babel/core';
+import type {
+ BinaryExpression,
+ Identifier,
+ Node,
+ NumericLiteral,
+ StringLiteral,
+} from '@babel/types';
+
+type Hooks = {
+ [key: string]: (node: any) => string | number;
+};
+
+const hooks: Hooks = {
+ Identifier: (node: Identifier) => node.name,
+ BinaryExpression: (node: BinaryExpression) => node.operator,
+ NumericLiteral: (node: NumericLiteral) => node.value,
+ StringLiteral: (node: StringLiteral) => node.value,
+};
+
+function isNode(obj: any): obj is Node {
+ return !!obj;
+}
+
+export default function dumpNode<T extends Node>(
+ node: T,
+ alive: Set<Node> | null = null,
+ level = 0,
+ idx: number | null = null
+) {
+ let result = level === 0 ? '\n' : '';
+ const prefix =
+ level === 0
+ ? ''
+ : `${'| '.repeat(level - 1)}${idx === null ? '|' : idx}${
+ (idx || 0) < 10 ? '=' : ''
+ }`;
+
+ const { type } = node;
+ result += `${prefix}${type}${type in hooks ? ` ${hooks[type](node)}` : ''}`;
+
+ if (alive) {
+ result += alive.has(node) ? ' ✅' : ' ❌';
+ }
+
+ result += '\n';
+ const keys = t.VISITOR_KEYS[type] as Array<keyof T>;
+ for (const key of keys) {
+ const subNode = node[key];
+
+ result += `${'| '.repeat(level)}|-${key}\n`;
+ if (Array.isArray(subNode)) {
+ for (let i = 0; i < subNode.length; i++) {
+ const child = subNode[i];
+ if (child) result += dumpNode(child, alive, level + 2, i);
+ }
+ } else if (isNode(subNode)) {
+ result += dumpNode(subNode, alive, level + 2);
+ }
+ }
+
+ return result;
+}