in packages/flow-upgrade/src/codemods/ReactUtils.js [84:144]
function getImportedComponentClassPattern(path: any): Function | null {
// All of the places where we want to treat as React.
const REACT_MODULES = new Set([
'React',
'react',
'react/addons',
'react-native',
]);
// The names of the exports from `REACT_MODULES` that are components
// classes.
const COMPONENT_CLASSES = new Set(['Component', 'PureComponent']);
// Do we require React?
const requiresReact =
path
.findVariableDeclarators()
.filter(
j.filters.VariableDeclarator.requiresModule(
Array.from(REACT_MODULES),
),
)
.size() > 0;
// Do we import React?
const importsReact =
path
.find(j.ImportDeclaration, {
type: 'ImportDeclaration',
source: {
type: 'Literal',
value: value => REACT_MODULES.has(value),
},
})
.size() > 0;
// If we neither require React or import React then we cannot get a
// component class pattern.
if (!requiresReact && !importsReact) {
return null;
}
// We want to match two different patterns so we jump straight to a
// function.
//
// For now we use a simple implementation where we assume Component and/or
// PureComponent has not been renamed. In the future if it becomes a problem
// then we should check to see if Component and/or PureComponent were
// renamed.
return (node: any) =>
node &&
// Matches: `Component`.
((node.type === 'Identifier' && COMPONENT_CLASSES.has(node.name)) ||
// Matches: `React.Component`.
(node.type === 'MemberExpression' &&
node.object.type === 'Identifier' &&
node.object.name === 'React' &&
node.property.type === 'Identifier' &&
COMPONENT_CLASSES.has(node.property.name)) ||
// Matches: `React.Component` but in the type position.
(node.type === 'QualifiedTypeIdentifier' &&
node.qualification.type === 'Identifier' &&
node.qualification.name === 'React' &&
node.id.type === 'Identifier' &&
COMPONENT_CLASSES.has(node.id.name)));
}