UNPKG

@linaria/utils

Version:

Blazing fast zero-runtime CSS in JS library

62 lines (58 loc) 2.03 kB
import { getScope } from './getScope'; function isInUnary(path) { return path.parentPath?.isUnaryExpression() ?? false; } // It's possible for non-strict mode code to have variable deletions. function isInDelete(path) { return path.parentPath.node.operator === 'delete'; } function isBindingIdentifier(path) { return path.isBindingIdentifier() && (!isInUnary(path) || isInDelete(path)); } function isReferencedIdentifier(path) { return path.isReferencedIdentifier() || isInUnary(path) && !isInDelete(path); } // For some reasons, `isBindingIdentifier` returns true for identifiers inside unary expressions. const checkers = { any: ex => isBindingIdentifier(ex) || isReferencedIdentifier(ex), binding: ex => isBindingIdentifier(ex), declaration: ex => isBindingIdentifier(ex) && ex.scope.getBinding(ex.node.name)?.identifier === ex.node, reference: ex => isReferencedIdentifier(ex) }; export function nonType(path) { return !path.find(p => p.isTSTypeReference() || p.isTSTypeQuery() || p.isFlowType() || p.isFlowDeclaration() || p.isTSInterfaceDeclaration()); } export default function findIdentifiers(expressions, type = 'reference') { const identifiers = []; expressions.forEach(ex => { const emit = path => { if (!path.node || path.removed || !checkers[type](path)) { return; } // TODO: Is there a better way to check that it's a local variable? const binding = getScope(path).getBinding(path.node.name); if (!binding) { return; } if (type === 'reference' && ex.isAncestor(binding.path)) { // This identifier is declared inside the expression. We don't need it. return; } identifiers.push(path); }; if (ex.isIdentifier() || ex.isJSXIdentifier()) { emit(ex); } else { ex.traverse({ Identifier(path) { emit(path); }, JSXIdentifier(path) { emit(path); } }); } }); return identifiers; } //# sourceMappingURL=findIdentifiers.js.map