Detect destructured formatMessage usage
fsmaia opened this issue · 6 comments
Which package?
babel-plugin-react-intl
Is your feature request related to a problem? Please describe.
When using formatMessage
by destructuring intl
, like in the following snippet, it isn't detected by the plugin:
const { formatMessage } = intl;
formatMessage({ id: 'id' });
Describe the solution you'd like
Although intrusive, we could check for all the formatMessage
callees, as a kind of reserved word.
Describe alternatives you've considered
- Removing all intl destructuring
- Extending this plugin to receive an
isFormatMessageCall
function as configuration - Trying to improve this rule by detecting destructuring inside babel
A way to achieve it would be performing the following verification inside isFormatMessageCall
:
callee.isIdentifier() && callee.node.name === 'formatMessage'
To improve the rule, we could check the callee scope to find expressions like:
const { intl: { formatMessage } } = this.props;
const { formatMessage } = intl;
Any suggestions?
it's technically possible you would need to make sure references are kept track of properly, e.g const {formatMessage: f} = intl
PR's always welcome :) along w/ test cases to demo your use case
I solved the biggest part of the problem, by detecting const { intl: { formatMessage } } = this.props
in class components, and destructured usaged in stateless components, with the following excerpt:
function isFormatMessageDestructuring(scope: Scope) {
const binding = scope.getBinding('formatMessage');
const block = scope.block as t.FunctionDeclaration;
if (binding && t.isVariableDeclarator(binding.path.node)) {
const nodeObject = binding.path.node.id as ObjectPattern;
return nodeObject.properties.find(
(value: any) => value.key.name === 'intl'
);
}
if (t.isObjectPattern(block.params[0])) {
return block.params[0].properties.find(
(value: any) => value.key.name === 'intl'
);
}
return false;
}
function isFormatMessageCall(
callee: NodePath<Expression | V8IntrinsicIdentifier>,
path: any
) {
if (
callee.isIdentifier() &&
callee.node.name === 'formatMessage' &&
isFormatMessageDestructuring(path.scope)
) {
return true;
}
//..
Now I'm missing const { props: { intl: { formatMessage } } } = this
pattern.
So close :)
you prob will have to handle aliasing as well, e.g {formatMesage: _} = intl
or something like that