antv-l7/node_modules/babel-plugin-add-react-disp.../index.js

178 lines
5.6 KiB
JavaScript
Raw Normal View History

2019-11-21 12:04:58 +08:00
module.exports = transform;
var pathMod = require('path')
function transform (babel) {
return {
visitor: {
ClassDeclaration: function (path, state) {
if (classHasRenderMethod(path)) {
setDisplayNameAfter(path, path.node.id, babel.types)
}
},
FunctionDeclaration: function (path, state) {
if (doesReturnJSX(path.node.body) || (path.node.id && path.node.id.name &&
isKnownComponent(path.node.id.name, state.opts.knownComponents))) {
var displayName
if (path.parentPath.node.type === 'ExportDefaultDeclaration') {
if (path.node.id == null) {
// An anonymous function declaration in export default declaration.
// Transform `export default function () { ... }`
// to `var _uid1 = function () { .. }; export default __uid;`
// then add displayName to _uid1
var extension = pathMod.extname(state.file.opts.filename)
var name = pathMod.basename(state.file.opts.filename, extension)
var id = path.scope.generateUidIdentifier("uid");
path.node.id = id
displayName = name
}
setDisplayNameAfter(path, path.node.id, babel.types, displayName)
}else if(path.parentPath.node.type === 'Program' || path.parentPath.node.type == 'ExportNamedDeclaration') {
setDisplayNameAfter(path, path.node.id, babel.types, displayName)
}
}
},
FunctionExpression: function (path, state) {
if(shouldSetDisplayNameForFuncExpr(path, state.opts.knownComponents)) {
var id = findCandidateNameForExpression(path)
if (id) {
setDisplayNameAfter(path, id, babel.types)
}
}
},
ArrowFunctionExpression: function (path, state) {
if(shouldSetDisplayNameForFuncExpr(path, state.opts.knownComponents)) {
var id = findCandidateNameForExpression(path)
if (id) {
setDisplayNameAfter(path, id, babel.types)
}
}
}
}
}
}
function isKnownComponent(name, knownComponents) {
return (name && knownComponents && knownComponents.indexOf(name) > -1)
}
function componentNameFromFilename(filename) {
var extension = pathMod.extname(filename);
var name = pathMod.basename(filename, extension)
return name
}
function shouldSetDisplayNameForFuncExpr(path, knownComponents) {
// Parent must be either 'AssignmentExpression' or 'VariableDeclarator' or 'CallExpression' with a parent of 'VariableDeclarator'
var id
if (path.parentPath.node.type === 'AssignmentExpression' &&
path.parentPath.node.left.type !== 'MemberExpression' && // skip static members
path.parentPath.parentPath.node.type == 'ExpressionStatement' &&
path.parentPath.parentPath.parentPath.node.type == 'Program') {
id = path.parentPath.node.left
}else{
// if parent is a call expression, we have something like (function () { .. })()
// move up, past the call expression and run the rest of the checks as usual
if(path.parentPath.node.type === 'CallExpression') {
path = path.parentPath
}
if(path.parentPath.node.type === 'VariableDeclarator') {
if (path.parentPath.parentPath.parentPath.node.type === 'ExportNamedDeclaration' ||
path.parentPath.parentPath.parentPath.node.type === 'Program') {
id = path.parentPath.node.id
}
}
}
if (id) {
if (id.name && isKnownComponent(id.name, knownComponents)) {
return true
}
return doesReturnJSX(path.node.body)
}
return false
}
function classHasRenderMethod(path) {
if(!path.node.body) {
return false
}
var members = path.node.body.body
for(var i = 0; i < members.length; i++) {
if (members[i].type == 'ClassMethod' && members[i].key.name == 'render') {
return true
}
}
return false
}
// https://github.com/babel/babel/blob/master/packages/babel-plugin-transform-react-display-name/src/index.js#L62-L77
// crawl up the ancestry looking for possible candidates for displayName inference
function findCandidateNameForExpression(path) {
var id
path.find(function (path) {
if (path.isAssignmentExpression()) {
id = path.node.left;
// } else if (path.isObjectProperty()) {
// id = path.node.key;
} else if (path.isVariableDeclarator()) {
id = path.node.id;
} else if (path.isStatement()) {
// we've hit a statement, we should stop crawling up
return true;
}
// we've got an id! no need to continue
if (id) return true;
});
return id
}
function doesReturnJSX (body) {
if (!body) return false
if (body.type === 'JSXElement') {
return true
}
var block = body.body
if (block && block.length) {
var lastBlock = block.slice(0).pop()
if (lastBlock.type === 'ReturnStatement') {
return lastBlock.argument !== null && lastBlock.argument.type === 'JSXElement'
}
}
return false
}
function setDisplayNameAfter(path, nameNodeId, t, displayName) {
if (!displayName) {
displayName = nameNodeId.name
}
var blockLevelStmnt
path.find(function (path) {
if (path.parentPath.isBlock()) {
blockLevelStmnt = path
return true
}
})
if (blockLevelStmnt) {
var trailingComments = blockLevelStmnt.node.trailingComments
delete blockLevelStmnt.node.trailingComments
var setDisplayNameStmn = t.expressionStatement(t.assignmentExpression(
'=',
t.memberExpression(nameNodeId, t.identifier('displayName')),
t.stringLiteral(displayName)
))
blockLevelStmnt.insertAfter(setDisplayNameStmn)
}
}