babel-plugin-flow-react-proptypes
Version:
converts flow types to react proptypes
779 lines (634 loc) • 29.5 kB
JavaScript
"use strict";
var _util = require("./util");
var _convertToPropTypes = _interopRequireDefault(require("./convertToPropTypes"));
var _makePropTypesAst = require("./makePropTypesAst");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
// maps between type alias name to prop types
var internalTypes = {}; // maps between type alias to import alias
var importedTypes = {}; // maps from imported-name+location to the local name
var addedImports = {};
var exportedTypes = {};
var suppress = false;
var omitRuntimeTypeExport = false;
var SUPPRESS_STRING = 'no babel-plugin-flow-react-proptypes'; // The template to use for the dead code elimination check
// if it passes, the prop types will be removed
// currently the 'deadCode' option is off by default, but this may change
var DEFAULT_DCE = "process.env.NODE_ENV === 'production'"; // General control flow:
// Parse flow type annotations in index.js
// Convert to intermediate representation via convertToPropTypes.js
// Convert to prop-types AST in makePropTypesAst.js
// Indicates we shouldn't handle a node again
// TODO: use a Symbol or WeakMap
var SKIP = "BPFRPT_SKIP";
var convertNodeToPropTypes = function convertNodeToPropTypes(node) {
return (0, _convertToPropTypes["default"])(node, importedTypes, internalTypes);
};
var getPropsForTypeAnnotation = function getPropsForTypeAnnotation(typeAnnotation) {
var props = null;
if (typeAnnotation.properties || typeAnnotation.type === 'GenericTypeAnnotation' || typeAnnotation.type === 'IntersectionTypeAnnotation' || typeAnnotation.type === 'AnyTypeAnnotation') {
props = convertNodeToPropTypes(typeAnnotation);
} else if (typeAnnotation.properties != null || typeAnnotation.type != null) {
(0, _util.$debug)('typeAnnotation not of expected type, not generating propTypes: ', typeAnnotation);
} else {
throw new Error("Expected prop types, but found none. This is a bug in ".concat(_util.PLUGIN_NAME));
}
return props;
};
module.exports = function flowReactPropTypes(babel) {
var t = babel.types;
var opts = {};
function shouldUseImport() {
return opts.useESModules === true || !opts.deadCode;
}
var impTemplates = {
named: babel.template("import { LOCAL } from 'change me'", {
sourceType: 'module'
}),
renamed: babel.template("import { SOURCE as LOCAL } from 'change me'", {
sourceType: 'module'
}),
"default": babel.template("import NAME from 'change me'", {
sourceType: 'module'
}),
requireDefault: babel.template("require(PATH)"),
requireNamed: babel.template("require(PATH).NAME")
};
function getFromModule(path, _ref) {
var _ref$type = _ref.type,
type = _ref$type === void 0 ? 'default' : _ref$type,
name = _ref.name,
_ref$local = _ref.local,
local = _ref$local === void 0 ? name : _ref$local,
location = _ref.location;
var tid = t.identifier;
var tstr = t.stringLiteral;
var key = "name:".concat(location, ":").concat(name);
if (shouldUseImport()) {
if (!addedImports[key]) {
var localName = local.replace(/[^a-zA-Z0-9]+/g, '_');
var sourceName = name.replace(/[^a-zA-Z0-9]+/g, '_');
addedImports[key] = localName;
var toAdd = null;
if (type === 'default') {
toAdd = impTemplates["default"]({
NAME: tid(localName)
});
} else if (type === 'named') {
if (localName === sourceName) {
toAdd = impTemplates.named({
LOCAL: tid(localName)
});
} else {
toAdd = impTemplates.renamed({
LOCAL: tid(localName),
SOURCE: tid(sourceName)
});
}
}
if (toAdd) {
toAdd.source.value = location;
var ppath = path;
do {
if (ppath.node && ppath.node.type === 'Program') break;
} while (ppath = ppath.parentPath);
if (ppath && ppath.node.body) {
ppath.node.body.push(toAdd);
}
}
}
return tid(addedImports[key]);
} else {
if (type === 'default') {
return impTemplates.requireDefault({
PATH: tstr(location)
}).expression;
} else if (type === 'named') {
return impTemplates.requireNamed({
PATH: tstr(location),
NAME: tid(name)
}).expression;
}
}
}
function getFromPropTypesModule(path, name, isRequired) {
var ptNode = getFromModule(path, {
type: 'default',
name: 'PropTypes',
location: 'prop-types'
});
if (!name) return ptNode;
var ptOptional = t.memberExpression(ptNode, t.identifier(name));
if (!isRequired) return ptOptional;
return t.memberExpression(ptOptional, t.identifier('isRequired'));
}
function addExportTypeDecl(path, exportName) {
var exportValueNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
if (!exportValueNode) {
exportValueNode = t.identifier(exportName);
}
if (!opts.deadCode || shouldUseImport()) {
if (!path.parentPath.isProgram()) return;
var body = path.parentPath.node.body;
var exportAst = t.exportNamedDeclaration(null, [t.exportSpecifier(t.identifier(exportName), exportValueNode)]);
exportAst[SKIP] = true;
body.push(exportAst);
} else {
// add the variable to the exports
var _exportAst = t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('Object'), t.identifier('defineProperty')), [t.identifier('exports'), t.stringLiteral(exportName), t.objectExpression([t.objectProperty(t.identifier('value'), exportValueNode), t.objectProperty(t.identifier('configurable'), t.booleanLiteral(true))])]));
var exportsDefinedCondition = t.binaryExpression('!==', t.unaryExpression('typeof', t.identifier('exports')), t.stringLiteral('undefined'));
var ifCond = exportsDefinedCondition;
if (opts.deadCode) {
var dceConditional = t.unaryExpression('!', getDcePredicate());
ifCond = t.logicalExpression('&&', dceConditional, ifCond);
}
var conditionalExportsAst = t.ifStatement(ifCond, _exportAst);
path.insertAfter(conditionalExportsAst);
}
}
var _templateCache = {};
function getDcePredicate() {
// opts.deadCode could be a boolean (true for DEFAULT_DCE), or a string to be
// used as a template
// if it's falsy, then just return node without any wrapper
if (!opts.deadCode) return null; // cache the template since it's going to be used a lot
var templateCode = typeof opts.deadCode === 'string' ? opts.deadCode : DEFAULT_DCE;
if (!_templateCache[templateCode]) {
_templateCache[templateCode] = babel.template(templateCode, {
placeholderPattern: false
});
} // return a ternary
var predicate = _templateCache[templateCode]({}).expression;
return predicate;
}
function wrapInDceCheck(node) {
var predicate = getDcePredicate(node);
if (!predicate) return node;
var conditional = t.conditionalExpression(predicate, t.nullLiteral(), node);
return conditional;
}
var isFunctionalReactComponent = function isFunctionalReactComponent(path) {
if ((path.type === 'ArrowFunctionExpression' || path.type === 'FunctionExpression') && !path.parent.id) {
// Could be functions inside a React component
return false;
}
if ((0, _util.hasReactElementTypeAnnotationReturn)(path.node)) {
return true;
}
if ((0, _util.containsReactElement)(path.node)) {
return true;
}
return false;
};
var findPresetProperties = function findPresetProperties(path, objectName, propertyName) {
var propNode = null;
var propPath = null;
path.traverse({
ClassProperty: function ClassProperty(path) {
if (path.node.key && path.node.key.name === propertyName) {
propNode = path.node.value;
propPath = path;
}
}
});
if (!propNode) {
path.parentPath.traverse({
ExpressionStatement: function ExpressionStatement(path) {
if (!path.node.expression || !path.node.expression.left) {
return;
}
if (path.node.expression.left.object && path.node.expression.left.property && path.node.expression.left.object.name === objectName && path.node.expression.left.property.name === propertyName) {
propNode = path.node.expression.right;
propPath = path;
}
}
});
}
return [propNode, propPath];
};
var mergeExplicitPropTypes = function mergeExplicitPropTypes(generatedProperties, path, name) {
var _findPresetProperties = findPresetProperties(path, name, 'propTypes'),
_findPresetProperties2 = _slicedToArray(_findPresetProperties, 2),
explicitPropNode = _findPresetProperties2[0],
explicitPropPath = _findPresetProperties2[1];
if (!explicitPropNode || !explicitPropNode.properties) {
return generatedProperties;
}
var generatedAndExplicitProperties = generatedProperties.concat(explicitPropNode.properties).reduce(function (acc, i) {
if (i.type === 'ObjectProperty') {
acc[i.key.name] = i;
} else if (i.type === 'SpreadProperty') {// ignore it for now
}
return acc;
}, {});
var mergedPropTypes = Object.keys(generatedAndExplicitProperties).map(function (k) {
var original = generatedAndExplicitProperties[k]; // delete original line locations to avoid extra new lines
delete original.start;
delete original.end;
return original;
});
explicitPropPath.remove();
return mergedPropTypes;
};
var setDefaultPropsOptional = function setDefaultPropsOptional(generatedProperties, path, name) {
var _findPresetProperties3 = findPresetProperties(path, name, 'defaultProps'),
_findPresetProperties4 = _slicedToArray(_findPresetProperties3, 1),
defaultPropNode = _findPresetProperties4[0];
if (!defaultPropNode || !defaultPropNode.properties) {
return generatedProperties;
}
var defaultProps = defaultPropNode.properties.map(function (prop) {
return prop.key.name;
});
return generatedProperties.map(function (prop) {
if (defaultProps.includes(prop.key)) {
prop.value.isRequired = false;
}
return prop;
});
};
/**
* Adds propTypes or contextTypes annotations to code
*
* Extracts some shared logic from `annotate`.
*
* @param path
* @param name
* @param attribute - target member name ('propTypes' or 'contextTypes')
* @param typesOrVar - propsOrVar / contextOrVar value
*/
var addAnnotationsToAST = function addAnnotationsToAST(path, name, attribute, typesOrVar) {
var attachPropTypesAST; // if type was exported, use the declared variable
var valueNode = null;
if (typeof typesOrVar === 'string') {
valueNode = t.identifier(typesOrVar);
if (name) {
var inner = t.assignmentExpression('=', t.memberExpression(t.identifier(name), t.identifier(attribute)), valueNode);
if (attribute === 'propTypes') {
inner = wrapInDceCheck(inner);
}
attachPropTypesAST = t.expressionStatement(inner);
}
} // type was not exported, generate
else {
var propTypesAST = (0, _makePropTypesAst.makePropTypesAstForPropTypesAssignment)(typesOrVar);
if (propTypesAST == null) {
return;
}
valueNode = propTypesAST;
if (attribute === 'propTypes') {
valueNode = wrapInDceCheck(valueNode);
if (valueNode.properties) {
valueNode.properties = mergeExplicitPropTypes(valueNode.properties, path, name);
}
}
attachPropTypesAST = t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier(name), t.identifier(attribute)), valueNode));
}
if (!opts.noStatic && (path.type === 'ClassDeclaration' || path.type === 'ClassExpression')) {
var newNode = t.classProperty(t.identifier(attribute), valueNode);
newNode["static"] = true;
path.node.body.body.push(newNode);
} else if (attachPropTypesAST) {
path.insertAfter(attachPropTypesAST);
}
};
/**
* Called when visiting a node.
*
* Converts the props param to AST and attaches it at the proper location,
* depending on the path param.
*
*
* @param path
* @param propsOrVar - props or exported props variable reference
* @param contextOrVar - context or exported context variable reference
*/
var annotate = function annotate(path, propsOrVar) {
var contextOrVar = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var name = null;
var targetPath;
if (!opts.noStatic && (path.type === 'ClassDeclaration' || path.type === 'ClassExpression')) {
if (path.node.id) {
name = path.node.id.name;
} else {
// It's an anonymous class but addAnnotationsToAST() needs `name` to be a string anyway
name = "";
}
targetPath = path;
} else if (path.type === 'ArrowFunctionExpression' || path.type === 'FunctionExpression') {
name = path.parent.id.name;
var basePath = path.parentPath.parentPath;
targetPath = t.isExportDeclaration(basePath.parent) ? basePath.parentPath : basePath;
} else if (path.node.id) {
name = path.node.id.name;
targetPath = ['Program', 'BlockStatement'].indexOf(path.parent.type) >= 0 ? path : path.parentPath;
} else {
throw new Error("babel-plugin-flow-react-proptypes attempted to add propTypes to a function/class with no name");
}
if (propsOrVar) {
if (propsOrVar.properties) {
propsOrVar.properties = setDefaultPropsOptional(propsOrVar.properties, targetPath, name);
}
addAnnotationsToAST(targetPath, name, 'propTypes', propsOrVar);
}
if (contextOrVar) {
addAnnotationsToAST(targetPath, name, 'contextTypes', contextOrVar);
}
};
/**
* Visitor for functions.
*
* Determines if a function is a functional react component and
* inserts the proptypes and contexttypes AST via `annotate`.
*
* @param path
*/
var functionVisitor = function functionVisitor(path) {
if (!isFunctionalReactComponent(path)) {
return;
} // Check if this looks like a stateless react component with PropType reference:
var firstParam = path.node.params[0];
var typeAnnotation = firstParam && firstParam.typeAnnotation && firstParam.typeAnnotation.typeAnnotation; // Check if the component has context annotations
var secondParam = path.node.params[1];
var contextAnnotation = secondParam && secondParam.typeAnnotation && secondParam.typeAnnotation.typeAnnotation;
var propsOrVar = null;
if (!typeAnnotation) {
(0, _util.$debug)('Found stateless component without type definition');
} else {
propsOrVar = typeAnnotation.id && exportedTypes[typeAnnotation.id.name] ? exportedTypes[typeAnnotation.id.name] : getPropsForTypeAnnotation(typeAnnotation);
}
var contextOrVar;
if (contextAnnotation) {
contextOrVar = contextAnnotation.id && exportedTypes[contextAnnotation.id.name] ? exportedTypes[contextAnnotation.id.name] : getPropsForTypeAnnotation(contextAnnotation);
} else {
contextOrVar = null;
}
if (propsOrVar) {
annotate(path, propsOrVar, contextOrVar);
}
};
return {
visitor: {
Program: function Program(path, _ref2) {
var _opts = _ref2.opts;
opts = _opts;
internalTypes = {};
importedTypes = {};
exportedTypes = {};
addedImports = {};
(0, _makePropTypesAst.setMakePropTypeImportNode)(function () {
return getFromPropTypesModule(path);
});
suppress = false;
omitRuntimeTypeExport = opts.omitRuntimeTypeExport || false;
var directives = path.node.directives;
if (directives && directives.length) {
var directive = directives[0];
if (directive.value && directive.value.value === SUPPRESS_STRING) {
suppress = true;
}
}
if (this.file && this.file.opts && this.file.opts.filename) {
if (this.file.opts.filename.indexOf('node_modules') >= 0) {
// Suppress any file that lives in node_modules IF the
// ignoreNodeModules setting is true
suppress = opts.ignoreNodeModules;
}
}
},
"TypeAlias|InterfaceDeclaration|OpaqueType": function TypeAliasInterfaceDeclarationOpaqueType(path) {
if (suppress) return;
(0, _util.$debug)('TypeAlias/InterfaceDeclaration/OpaqueType found');
var typeAliasName = path.node.id.name;
if (!typeAliasName) {
throw new Error('Did not find name for type alias');
}
var propTypes = convertNodeToPropTypes(path.node);
internalTypes[typeAliasName] = propTypes;
},
"ClassExpression|ClassDeclaration": function ClassExpressionClassDeclaration(path) {
if (opts.noStatic && path.node.type === 'ClassExpression') return;
if (path.node[SKIP]) return;
path.node[SKIP] = true;
if (suppress) return;
var superClass = path.node.superClass; // check if we're extending React.Compoennt
var extendsReactComponent = superClass && superClass.type === 'MemberExpression' && superClass.object.name === 'React' && (superClass.property.name === 'Component' || superClass.property.name === 'PureComponent');
var extendsComponent = superClass && superClass.type === 'Identifier' && (superClass.name === 'Component' || superClass.name === 'PureComponent');
if (!extendsReactComponent && !extendsComponent) {
(0, _util.$debug)('Found a class that isn\'t a react component', superClass);
return;
}
var propTypes = null,
contextTypes = null; // And have type as property annotations
path.node.body.body.forEach(function (bodyNode) {
if (bodyNode && bodyNode.key.name === 'props' && bodyNode.typeAnnotation) {
var annotation = bodyNode.typeAnnotation.typeAnnotation;
var props = getPropsForTypeAnnotation(annotation);
if (!props) {
throw new TypeError('Couldn\'t process \`class { props: This }`');
}
propTypes = props;
return;
}
if (bodyNode && bodyNode.key.name === 'context' && bodyNode.typeAnnotation) {
var _annotation = bodyNode.typeAnnotation.typeAnnotation;
var context = getPropsForTypeAnnotation(_annotation);
if (!context) {
throw new TypeError('Couldn\'t process \`class { context: This }`');
}
contextTypes = context;
}
}); // or Component<void, Props, Context>
var secondSuperParam = getPropsTypeParam(path.node);
if (secondSuperParam && secondSuperParam.type === 'GenericTypeAnnotation') {
var typeAliasName = secondSuperParam.id.name;
if (typeAliasName === 'Object') return;
var props = internalTypes[typeAliasName] || importedTypes[typeAliasName] && importedTypes[typeAliasName].accessNode;
if (!props) {
(0, _util.$debug)("Couldn't find type \"".concat(typeAliasName, "\""));
return;
}
propTypes = props;
}
if (secondSuperParam && (secondSuperParam.type === 'ObjectTypeAnnotation' || secondSuperParam.type === 'IntersectionTypeAnnotation')) {
propTypes = (0, _convertToPropTypes["default"])(secondSuperParam, importedTypes, internalTypes);
}
var thirdSuperParam = getContextTypeParam(path.node);
if (thirdSuperParam && thirdSuperParam.type === 'GenericTypeAnnotation') {
var _typeAliasName = thirdSuperParam.id.name;
if (_typeAliasName === 'Object') return;
var _props = internalTypes[_typeAliasName] || importedTypes[_typeAliasName] && importedTypes[_typeAliasName].accessNode;
if (!_props) {
throw new TypeError("Couldn't find type \"".concat(_typeAliasName, "\""));
}
contextTypes = _props;
}
annotate(path, propTypes, contextTypes);
},
FunctionExpression: function FunctionExpression(path) {
if (suppress) return;
return functionVisitor(path);
},
FunctionDeclaration: function FunctionDeclaration(path) {
if (suppress) return;
return functionVisitor(path);
},
ArrowFunctionExpression: function ArrowFunctionExpression(path) {
if (suppress) return;
return functionVisitor(path);
},
// See issue:
/**
* Processes exported type aliases.
*
* This function also adds something to the AST directly, instead
* of invoking annotate.
*
* @param path
* @constructor
*/
ExportNamedDeclaration: function ExportNamedDeclaration(path) {
if (suppress) return;
var node = path.node;
if (node.exportKind === 'type' && node.source && node.source.value) {
var _iterator = _createForOfIteratorHelper(node.specifiers),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var spec = _step.value;
var typeName = spec.local.name;
getFromModule(path, {
type: 'named',
name: (0, _util.getExportNameForType)(typeName),
location: node.source.value
});
addExportTypeDecl(path, (0, _util.getExportNameForType)(typeName));
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return;
}
if (node.exportKind === 'type' && !node.source && !node.declaration) {
var _iterator2 = _createForOfIteratorHelper(node.specifiers),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var _spec = _step2.value;
if (!t.isIdentifier(_spec.local)) continue;
var imported = importedTypes[_spec.local.name];
if (!imported) continue;
if (_spec.local.name !== _spec.exported.name) {
// TODO: handle this properly
continue;
}
addExportTypeDecl(path, (0, _util.getExportNameForType)(_spec.local.name), imported.accessNode);
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
return;
}
var declarationObject = null;
if (!node.declaration) return;
if (node.declaration.type === 'TypeAlias') {
declarationObject = node.declaration.right;
}
if (node.declaration.type === 'OpaqueType') {
declarationObject = node.declaration.impltype;
}
if (node.declaration.type === 'InterfaceDeclaration') {
declarationObject = node.declaration.body;
}
if (!declarationObject) return;
var name = node.declaration.id.name;
var propTypes = convertNodeToPropTypes(declarationObject);
internalTypes[name] = propTypes;
var propTypesAst = (0, _makePropTypesAst.makePropTypesAstForExport)(propTypes); // create a variable for reuse
var exportName = (0, _util.getExportNameForType)(name);
exportedTypes[name] = exportName;
var variableDeclarationAst = t.variableDeclaration('var', [t.variableDeclarator(t.identifier(exportName), wrapInDceCheck(propTypesAst))]);
path.insertBefore(variableDeclarationAst);
if (!omitRuntimeTypeExport) {
if (path.node[SKIP]) return;
addExportTypeDecl(path, exportName);
}
},
ImportDeclaration: function ImportDeclaration(path) {
if (suppress) return;
var node = path.node;
if (/^@?\w/.test(node.source.value) && node.source.value !== 'react') return; // https://github.com/brigand/babel-plugin-flow-react-proptypes/issues/62
// if (node.source.value[0] !== '.') {
// return;
// }
node.specifiers.forEach(function (specifier) {
if (node.importKind !== 'type' && specifier.importKind !== 'type') return;
var typeName = specifier.local.name;
var originalTypeName = specifier.type === 'ImportDefaultSpecifier' ? typeName : specifier.imported.name; // Store the name the type so we can use it later. We do
// mark it as importedTypes because we do handle these
// differently than internalTypes.
// imported types are basically realized as imports;
// because we can be somewhat sure that we generated
// the proper exported propTypes in the imported file
// Later, we will check importedTypes to determine if
// we want to put this as a 'raw' type in our internal
// representation
importedTypes[typeName] = {
localName: originalTypeName,
exportName: (0, _util.getExportNameForType)(originalTypeName),
accessNode: null
}; // https://github.com/brigand/babel-plugin-flow-react-proptypes/issues/129
if (node.source.value === 'react' && typeName === 'ComponentType') {
var ptFunc = getFromPropTypesModule(path, 'func');
importedTypes[typeName].accessNode = ptFunc;
return;
}
if (node.source.value === 'react' && typeName === 'Node') {
var _ptFunc = getFromPropTypesModule(path, 'node');
importedTypes[typeName].accessNode = _ptFunc;
return;
}
var accessNode = getFromModule(path, {
type: 'named',
name: (0, _util.getExportNameForType)(originalTypeName),
local: (0, _util.getExportNameForType)(typeName),
location: node.source.value
});
importedTypes[typeName].accessNode = accessNode;
});
}
}
};
};
function getPropsTypeParam(node) {
if (!node) return null;
if (!node.superTypeParameters) return null;
var superTypes = node.superTypeParameters;
if (superTypes.params.length === 2) {
return superTypes.params[0];
} else if (superTypes.params.length === 3) {
return superTypes.params[0];
} else if (superTypes.params.length === 1) {
return superTypes.params[0];
}
return null;
}
function getContextTypeParam(node) {
if (!node) return null;
if (!node.superTypeParameters) return null;
var superTypes = node.superTypeParameters;
if (superTypes.params.length === 3) {
return superTypes.params[2];
}
return null;
}