in packages/metro-source-map/src/generateFunctionMap.js [180:301]
function getNameForPath(path: NodePath<>): string {
const {node, parent, parentPath} = path;
if (isProgram(node)) {
return '<global>';
}
let {id} = (path: any);
// has an `id` so we don't need to infer one
if (node.id) {
// $FlowFixMe Flow error uncovered by typing Babel more strictly
return node.id.name;
}
let propertyPath;
let kind = '';
// Find or construct an AST node that names the current node.
if (isObjectMethod(node) || isClassMethod(node)) {
// ({ foo() {} });
id = node.key;
if (node.kind !== 'method' && node.kind !== 'constructor') {
// Store the method's kind so we can add it to the final name.
kind = node.kind;
}
// Also store the path to the property so we can find its context
// (object/class) later and add _its_ name to the result.
propertyPath = path;
} else if (isObjectProperty(parent) || isClassProperty(parent)) {
// ({ foo: function() {} });
id = parent.key;
// Also store the path to the property so we can find its context
// (object/class) later and add _its_ name to the result.
propertyPath = parentPath;
} else if (isVariableDeclarator(parent)) {
// let foo = function () {};
id = parent.id;
} else if (isAssignmentExpression(parent)) {
// foo = function () {};
id = parent.left;
} else if (isJSXExpressionContainer(parent)) {
const grandParentNode = parentPath?.parentPath?.node;
if (isJSXElement(grandParentNode)) {
// <foo>{function () {}}</foo>
const openingElement = grandParentNode.openingElement;
id = t.jsxMemberExpression(
// $FlowFixMe Flow error uncovered by typing Babel more strictly
t.jsxMemberExpression(openingElement.name, t.jsxIdentifier('props')),
t.jsxIdentifier('children'),
);
} else if (isJSXAttribute(grandParentNode)) {
// <foo bar={function () {}} />
const openingElement = parentPath?.parentPath?.parentPath?.node;
const prop = grandParentNode;
id = t.jsxMemberExpression(
// $FlowFixMe Flow error uncovered by typing Babel more strictly
t.jsxMemberExpression(openingElement.name, t.jsxIdentifier('props')),
// $FlowFixMe Flow error uncovered by typing Babel more strictly
prop.name,
);
}
}
// Collapse the name AST, if any, into a string.
let name = getNameFromId(id);
if (name == null) {
// We couldn't find a name directly. Try the parent in certain cases.
if (isAnyCallExpression(parent)) {
// foo(function () {})
const argIndex = parent.arguments.indexOf(node);
if (argIndex !== -1) {
const calleeName = getNameFromId(parent.callee);
// var f = Object.freeze(function () {})
if (argIndex === 0 && calleeName === 'Object.freeze') {
return getNameForPath(nullthrows(parentPath));
}
// var f = useCallback(function () {})
if (
argIndex === 0 &&
(calleeName === 'useCallback' || calleeName === 'React.useCallback')
) {
return getNameForPath(nullthrows(parentPath));
}
if (calleeName) {
return `${calleeName}$argument_${argIndex}`;
}
}
}
if (isTypeCastExpression(parent) && parent.expression === node) {
return getNameForPath(nullthrows(parentPath));
}
if (isExportDefaultDeclaration(parent)) {
return 'default';
}
// We couldn't infer a name at all.
return ANONYMOUS_NAME;
}
// Annotate getters and setters.
if (kind) {
name = kind + '__' + name;
}
// Annotate members with the name of their containing object/class.
if (propertyPath) {
if (isClassBody(propertyPath.parent)) {
// $FlowFixMe Disvoered when typing babel-traverse
const className = getNameForPath(propertyPath.parentPath.parentPath);
if (className !== ANONYMOUS_NAME) {
// $FlowFixMe Flow error uncovered by typing Babel more strictly
const separator = propertyPath.node.static ? '.' : '#';
name = className + separator + name;
}
} else if (isObjectExpression(propertyPath.parent)) {
const objectName = getNameForPath(nullthrows(propertyPath.parentPath));
if (objectName !== ANONYMOUS_NAME) {
name = objectName + '.' + name;
}
}
}
return name;
}