in packages/babel-plugin-fbt/src/FbtUtil.js [766:840]
function convertToStringArrayNodeIfNeeded(
moduleName: JSModuleNameType,
node: $ElementType<
$PropertyType<BabelNodeCallExpression, 'arguments'>,
number,
>,
): BabelNodeArrayExpression {
let initialElements;
let didStartWithArray = false;
switch (node.type) {
case 'ArrayExpression':
initialElements = nullthrows(node.elements);
didStartWithArray = true;
break;
case 'CallExpression':
case 'StringLiteral':
initialElements = [node];
break;
case 'BinaryExpression': {
initialElements = getBinaryExpressionOperands(moduleName, node);
break;
}
case 'TemplateLiteral': {
initialElements = convertTemplateLiteralToArrayElements(moduleName, node);
break;
}
default:
throw errorAt(
node,
`Unexpected node type: ${node.type}. ` +
`${moduleName}()'s first argument should be a string literal, ` +
`a construct like ${moduleName}.param() or an array of those.`,
);
}
// Let's also convert the 1st level of elements of the array
// to process nested string concatenations and template literals one last time.
// We're not making this fully recursive since, from a syntax POV,
// it wouldn't be elegant to allow developers to nest lots of template literals.
return arrayExpression(
initialElements.reduce((elements, element) => {
if (element == null) {
return elements;
}
if (
didStartWithArray &&
(element.type === 'BinaryExpression' ||
(element.type === 'TemplateLiteral' && element.expressions.length))
) {
throw errorAt(
element,
`${moduleName}(array) only supports items that are string literals, ` +
`template literals without any expressions, or fbt constructs`,
);
}
switch (element.type) {
case 'BinaryExpression': {
elements.push(...getBinaryExpressionOperands(moduleName, element));
break;
}
case 'TemplateLiteral': {
elements.push(
...convertTemplateLiteralToArrayElements(moduleName, element),
);
break;
}
default:
elements.push(element);
}
return elements;
}, []),
);
}