diff options
author | Sebastian <sebasjm@gmail.com> | 2021-08-23 16:46:06 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2021-08-23 16:48:30 -0300 |
commit | 38acabfa6089ab8ac469c12b5f55022fb96935e5 (patch) | |
tree | 453dbf70000cc5e338b06201af1eaca8343f8f73 /@linaria/packages/shaker/src/Visitors.ts | |
parent | f26125e039143b92dc0d84e7775f508ab0cdcaa8 (diff) | |
download | node-vendor-38acabfa6089ab8ac469c12b5f55022fb96935e5.tar.gz node-vendor-38acabfa6089ab8ac469c12b5f55022fb96935e5.tar.bz2 node-vendor-38acabfa6089ab8ac469c12b5f55022fb96935e5.zip |
Diffstat (limited to '@linaria/packages/shaker/src/Visitors.ts')
-rw-r--r-- | @linaria/packages/shaker/src/Visitors.ts | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/@linaria/packages/shaker/src/Visitors.ts b/@linaria/packages/shaker/src/Visitors.ts new file mode 100644 index 0000000..0228d4a --- /dev/null +++ b/@linaria/packages/shaker/src/Visitors.ts @@ -0,0 +1,87 @@ +import { types as t } from '@babel/core'; +import type { Identifier, Node, VisitorKeys } from '@babel/types'; +import { warn } from '@linaria/logger'; +import { peek } from '@linaria/babel-preset'; +import GraphBuilderState from './GraphBuilderState'; +import identifierHandlers from './identifierHandlers'; +import type { Visitor, Visitors } from './types'; + +import { visitors as core } from './langs/core'; + +const visitors: Visitors = { + Identifier<TParent extends Node>( + this: GraphBuilderState, + node: Identifier, + parent: TParent | null, + parentKey: VisitorKeys[TParent['type']] | null, + listIdx: number | null = null + ) { + if (!parent || !parentKey) { + return; + } + + const handler = identifierHandlers[`${parent.type}:${parentKey}`]; + + if (typeof handler === 'function') { + handler(this, node, parent, parentKey, listIdx); + return; + } + + if (handler === 'keep') { + return; + } + + if (handler === 'declare') { + const kindOfDeclaration = this.meta.get('kind-of-declaration'); + this.scope.declare(node, kindOfDeclaration === 'var', null); + return; + } + + if (handler === 'refer') { + const declaration = this.scope.addReference(node); + // Let's check that it's not a global variable + if (declaration) { + // usage of a variable depends on its declaration + this.graph.addEdge(node, declaration); + + const context = peek(this.context); + if (context === 'lval') { + // This is an identifier in the left side of an assignment expression and a variable value depends on that. + this.graph.addEdge(declaration, node); + } + } + + return; + } + + /* + * There is an unhandled identifier. + * This case should be added to ./identifierHandlers.ts + */ + warn( + 'evaluator:shaker', + 'Unhandled identifier', + node.name, + parent.type, + parentKey, + listIdx + ); + }, + + ...core, +}; + +const isKeyOfVisitors = (type: string): type is keyof Visitors => + type in visitors; + +export function getVisitors<TNode extends Node>(node: TNode): Visitor<TNode>[] { + const aliases = t.ALIAS_KEYS[node.type] || []; + const aliasVisitors = aliases + .map((type) => (isKeyOfVisitors(type) ? visitors[type] : null)) + .filter((i) => i) as Visitor<TNode>[]; + return [...aliasVisitors, visitors[node.type] as Visitor<TNode>].filter( + (v) => v + ); +} + +export default visitors; |