[ ] Babel |
export default function({types: t}) {
return {
visitor: {}
};
}
visitor
, (), , FunctionDeclaration
StringLiteral
( ), (path) . Identifier
. export default function({types: t}) {
return {
visitor: {
Identifier(path, {opts: options}) {
}
}
};
}
.opts
. , . :{
plugins: [[
"babel-plugin-auto-import",
{ declarations: [{name: "React", path: "react"}] }
]]
}
.["is" + ]()
. , path.isIdentifier()
. , .find(callback)
, , .findParent(callback)
. .parentPath
.Identifier
. . , :React.Component
{
type: "MemberExpression",
object: {
type: "Identifier",
name: "React"
},
property: {
type: "Identifier",
name: "Component"
},
computed: false
}
.type
, , . MemberExpression
. . Object
. . computed
, , x["a" + b]
. Property
, , .Identifier
: React
Component
. React
, Component
. , MemberExpression
, , .object
MemberExpression
. :export default function({types: t}) {
return {
visitor: {
Identifier(path, {opts: options}) {
if (!isCorrectIdentifier(path))
return;
}
}
};
function isCorrectIdentifier(path) {
let {parentPath} = path;
if (parentPath.isMemberExpression() && parentPath.get("object") == path)
return true;
}
}
function isCorrectIdentifier(path) {
let {parentPath} = path;
if (parentPath.isArrayExpression())
return true;
else
if (parentPath.isArrowFunctionExpression())
return true;
else
if (parentPath.isAssignmentExpression() && parentPath.get("right") == path)
return true;
else
if (parentPath.isAwaitExpression())
return true;
else
if (parentPath.isBinaryExpression())
return true;
else
if (parentPath.bindExpression && parentPath.bindExpression())
return true;
else
if (parentPath.isCallExpression())
return true;
else
if (parentPath.isClassDeclaration() && parentPath.get("superClass") == path)
return true;
else
if (parentPath.isClassExpression() && parentPath.get("superClass") == path)
return true;
else
if (parentPath.isConditionalExpression())
return true;
else
if (parentPath.isDecorator())
return true;
else
if (parentPath.isDoWhileStatement())
return true;
else
if (parentPath.isExpressionStatement())
return true;
else
if (parentPath.isExportDefaultDeclaration())
return true;
else
if (parentPath.isForInStatement())
return true;
else
if (parentPath.isForStatement())
return true;
else
if (parentPath.isIfStatement())
return true;
else
if (parentPath.isLogicalExpression())
return true;
else
if (parentPath.isMemberExpression() && parentPath.get("object") == path)
return true;
else
if (parentPath.isNewExpression())
return true;
else
if (parentPath.isObjectProperty() && parentPath.get("value") == path)
return !parentPath.node.shorthand;
else
if (parentPath.isReturnStatement())
return true;
else
if (parentPath.isSpreadElement())
return true;
else
if (parentPath.isSwitchStatement())
return true;
else
if (parentPath.isTaggedTemplateExpression())
return true;
else
if (parentPath.isThrowStatement())
return true;
else
if (parentPath.isUnaryExpression())
return true;
else
if (parentPath.isVariableDeclarator() && parentPath.get("init") == path)
return true;
return false;
}
scope
. , . .bindings
. .parent
. , .export default function({types: t}) {
return {
visitor: {
Identifier(path, {opts: options}) {
if (!isCorrectIdentifier(path))
return;
let {node: identifier, scope} = path;
if (isDefined(identifier, scope))
return;
}
}
};
// ...
function isDefined(identifier, {bindings, parent}) {
let variables = Object.keys(bindings);
if (variables.some(has, identifier))
return true;
return parent ? isDefined(identifier, parent) : false;
}
function has(identifier) {
let {name} = this;
return identifier == name;
}
}
options
:let {declarations} = options;
declarations.some(declaration => {
if (declaration.name == identifier.name) {
let program = path.findParent(path => path.isProgram());
insertImport(program, declaration);
return true;
}
});
.reduce
, ImportDeclaration
:function insertImport(program, { name, path }) {
let programBody = program.get("body");
let currentImportDeclarations =
programBody.reduce(currentPath => {
if (currentPath.isImportDeclaration())
list.push(currentPath);
return list;
}, []);
}
let importDidAppend =
currentImportDeclarations.some(({node: importDeclaration}) => {
if (importDeclaration.source.value == path) {
return importDeclaration.specifiers.some(specifier => specifier.local.name == name);
}
});
t
. . importDeclaration
. , (.. ) .export default ...
). . StringLiteral
.let specifier = t.importDefaultSpecifier(t.identifier(name));
let pathToModule = t.stringLiteral(path);
let importDeclaration = t.importDeclaration([specifier], pathToModule);
.replaceWith(node)
, , .replaceWithMultiple([...nodes])
. .remove()
. .insertBefore(node)
.insertAfter(node)
, .program
.body
, , . -, pushContainer
unshiftContainer
. :program.unshiftContainer("body", importNode);