@linaria/utils
Version:
Blazing fast zero-runtime CSS in JS library
72 lines • 2.67 kB
JavaScript
import { collectExportsAndImports } from './collectExportsAndImports';
import { getScope } from './getScope';
function getCallee(p) {
const callee = p.get('callee');
if (callee.isSequenceExpression()) {
const expressions = callee.get('expressions');
if (expressions.length === 2 && expressions[0].isNumericLiteral({
value: 0
})) {
return expressions[1];
}
return callee;
}
return callee;
}
const JSXRuntimeSource = 'react/jsx-runtime';
function isJSXRuntime(p, imports) {
const jsxRuntime = imports.find(i => i.source === JSXRuntimeSource);
const jsxRuntimeName = jsxRuntime?.local?.isIdentifier() && jsxRuntime?.local?.node?.name;
if (jsxRuntime) {
const callee = getCallee(p);
if (jsxRuntimeName && callee.isIdentifier({
name: jsxRuntimeName
})) {
return true;
}
if (callee.isMemberExpression() && imports.find(i => i.source === JSXRuntimeSource && i.local === callee)) {
return true;
}
}
return false;
}
function isHookOrCreateElement(name) {
return name === 'createElement' || /use[A-Z]/.test(name);
}
function isClassicReactRuntime(p, imports) {
const reactImports = imports.filter(i => i.source === 'react' && (i.imported === 'default' || i.imported && isHookOrCreateElement(i.imported)));
if (reactImports.length === 0) return false;
const callee = getCallee(p);
if (callee.isIdentifier() && isHookOrCreateElement(callee.node.name)) {
const bindingPath = getScope(callee).getBinding(callee.node.name)?.path;
return reactImports.some(i => bindingPath?.isAncestor(i.local));
}
if (callee.isMemberExpression()) {
if (reactImports.some(i => i.local === callee)) {
// It's React.createElement in CJS
return true;
}
const object = callee.get('object');
const property = callee.get('property');
const defaultImport = reactImports.find(i => i.imported === 'default');
if (!defaultImport || !defaultImport.local.isIdentifier() || !property.isIdentifier() || !isHookOrCreateElement(property.node.name) || !object.isIdentifier({
name: defaultImport.local.node.name
})) {
return false;
}
const bindingPath = getScope(object).getBinding(object.node.name)?.path;
return bindingPath?.isAncestor(defaultImport.local) ?? false;
}
return false;
}
export function isUnnecessaryReactCall(path) {
const programPath = path.findParent(p => p.isProgram());
if (!programPath) {
return false;
}
const {
imports
} = collectExportsAndImports(programPath);
return isJSXRuntime(path, imports) || isClassicReactRuntime(path, imports);
}
//# sourceMappingURL=isUnnecessaryReactCall.js.map