@linaria/utils
Version:
Blazing fast zero-runtime CSS in JS library
73 lines (68 loc) • 2.55 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = findIdentifiers;
exports.nonType = nonType;
var _getScope = require("./getScope");
function isInUnary(path) {
var _path$parentPath$isUn, _path$parentPath;
return (_path$parentPath$isUn = (_path$parentPath = path.parentPath) === null || _path$parentPath === void 0 ? void 0 : _path$parentPath.isUnaryExpression()) !== null && _path$parentPath$isUn !== void 0 ? _path$parentPath$isUn : 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 => {
var _ex$scope$getBinding;
return isBindingIdentifier(ex) && ((_ex$scope$getBinding = ex.scope.getBinding(ex.node.name)) === null || _ex$scope$getBinding === void 0 ? void 0 : _ex$scope$getBinding.identifier) === ex.node;
},
reference: ex => isReferencedIdentifier(ex)
};
function nonType(path) {
return !path.find(p => p.isTSTypeReference() || p.isTSTypeQuery() || p.isFlowType() || p.isFlowDeclaration() || p.isTSInterfaceDeclaration());
}
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 = (0, _getScope.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