function defaultParse( // eslint-disable-line no-unused-vars src, resolver, // eslint-disable-line no-shadow handlers // eslint-disable-line no-shadow ) {
if (!resolver) {
resolver = defaultResolver;
}
if (!handlers) {
handlers = defaultHandlers;
}
return (0, _parse2.default)(src, resolver, handlers);
}...
## API
The tool can be used programmatically to extract component information and customize the extraction process:
```js
var reactDocs = require('react-docgen');
var componentInfo = reactDocs.parse(src);
```
As with the CLI, this will look for the exported component created through `React.createClass` or a class definition in the provided
source. The whole process of analyzing the source code is separated into two parts:
- Locating/finding the nodes in the AST which define the component
- Extracting information from those nodes
...function propTypeHandler(documentation, path) {
var propTypesPath = (0, _getMemberValuePath2.default)(path, 'propTypes');
if (!propTypesPath) {
return;
}
propTypesPath = (0, _resolveToValue2.default)(propTypesPath);
if (!propTypesPath) {
return;
}
amendPropTypes(documentation, propTypesPath);
}n/a
function propTypeCompositionHandler(documentation, path) {
var propTypesPath = (0, _getMemberValuePath2.default)(path, 'propTypes');
if (!propTypesPath) {
return;
}
propTypesPath = (0, _resolveToValue2.default)(propTypesPath);
if (!propTypesPath) {
return;
}
switch (propTypesPath.node.type) {
case types.ObjectExpression.name:
processObjectExpression(documentation, propTypesPath);
break;
default:
amendComposes(documentation, propTypesPath);
break;
}
}n/a
function propDocBlockHandler(documentation, path) {
var propTypesPath = (0, _getMemberValuePath2.default)(path, 'propTypes');
if (!propTypesPath) {
return;
}
propTypesPath = (0, _resolveToValue2.default)(propTypesPath);
if (!propTypesPath || !types.ObjectExpression.check(propTypesPath.node)) {
return;
}
propTypesPath.get('properties').each(function (propertyPath) {
// we only support documentation of actual properties, not spread
if (types.Property.check(propertyPath.node)) {
(0, _setPropDescription2.default)(documentation, propertyPath);
}
});
}n/a
function flowTypeHandler(documentation, path) {
var flowTypesPath = (0, _getFlowTypeFromReactComponent2.default)(path);
if (!flowTypesPath) {
return;
}
(0, _getFlowTypeFromReactComponent.applyToFlowTypeProperties)(flowTypesPath, function (propertyPath) {
setPropDescriptor(documentation, propertyPath);
});
}n/a
function flowTypeDocBlockHandler(documentation, path) {
var flowTypesPath = (0, _getFlowTypeFromReactComponent2.default)(path);
if (!flowTypesPath) {
return;
}
(0, _getFlowTypeFromReactComponent.applyToFlowTypeProperties)(flowTypesPath, function (propertyPath) {
return (0, _setPropDescription2.default)(documentation, propertyPath);
});
}n/a
function defaultPropsHandler(documentation, componentDefinition) {
var statelessProps = null;
var defaultPropsPath = getDefaultPropsPath(componentDefinition);
if ((0, _isStatelessComponent2.default)(componentDefinition)) {
statelessProps = getStatelessPropsPath(componentDefinition);
}
// Do both statelessProps and defaultProps if both are available so defaultProps can override
if (statelessProps && types.ObjectPattern.check(statelessProps.node)) {
getDefaultValuesFromProps(statelessProps.get('properties'), documentation, true);
}
if (defaultPropsPath && types.ObjectExpression.check(defaultPropsPath.node)) {
getDefaultValuesFromProps(defaultPropsPath.get('properties'), documentation, false);
}
}n/a
function componentDocblockHandler(documentation, path) {
var description = null;
// Find parent statement (e.g. var Component = React.createClass(<path>);)
var searchPath = path;
while (searchPath && !types.Statement.check(searchPath.node)) {
searchPath = searchPath.parent;
}
if (searchPath) {
// If the parent is an export statement, we have to traverse one more up
if (types.ExportNamedDeclaration.check(searchPath.parentPath.node) || types.ExportDefaultDeclaration.check(searchPath.parentPath
.node)) {
searchPath = searchPath.parentPath;
}
description = (0, _docblock.getDocblock)(searchPath);
}
if (description == null && isClassDefinition(path)) {
// If we have a class declaration or expression, then the comment might be
// attached to the first decorator instead.
if (path.node.decorators && path.node.decorators.length > 0) {
description = (0, _docblock.getDocblock)(path.get('decorators', 0));
}
}
if (description == null) {
// If this is the first statement in the module body, the comment is attached
// to the program node
var programPath = searchPath;
while (programPath && !types.Program.check(programPath.node)) {
programPath = programPath.parent;
}
if (programPath.get('body', 0) === searchPath) {
description = (0, _docblock.getDocblock)(programPath);
}
}
documentation.set('description', description || '');
}n/a
function displayNameHandler(documentation, path) {
var displayNamePath = (0, _getMemberValuePath2.default)(path, 'displayName');
if (!displayNamePath) {
return;
}
displayNamePath = (0, _resolveToValue2.default)(displayNamePath);
// If display name is defined as a getter we get a function expression as
// value. In that case we try to determine the value from the return
// statement.
if (types.FunctionExpression.check(displayNamePath.node)) {
(0, _traverse.traverseShallow)(displayNamePath.get('body'), {
visitReturnStatement: function visitReturnStatement(path) {
displayNamePath = (0, _resolveToValue2.default)(path.get('argument'));
return false;
}
});
}
if (!displayNamePath || !types.Literal.check(displayNamePath.node)) {
return;
}
documentation.set('displayName', displayNamePath.node.value);
}n/a
function componentMethodsHandler(documentation, path) {
// Extract all methods from the class or object.
var methodPaths = [];
if ((0, _isReactComponentClass2.default)(path)) {
methodPaths = path.get('body', 'body').filter(function (p) {
return types.MethodDefinition.check(p.node) && p.node.kind !== 'constructor';
});
} else if (types.ObjectExpression.check(path.node)) {
methodPaths = path.get('properties').filter(isFunctionExpression);
// Add the statics object properties.
var statics = (0, _getMemberValuePath2.default)(path, 'statics');
if (statics) {
statics.get('properties').each(function (p) {
if (isFunctionExpression(p)) {
p.node.static = true;
methodPaths.push(p);
}
});
}
}
var methods = getMethodsDoc(methodPaths);
documentation.set('methods', methods);
}n/a
function componentMethodsJsDocHandler(documentation) {
var methods = documentation.get('methods');
if (!methods) {
return;
}
methods = methods.map(function (method) {
if (!method.docblock) {
return method;
}
var jsDoc = (0, _parseJsDoc2.default)(method.docblock);
var returns = merge(jsDoc.returns, method.returns);
var params = method.params.map(function (param) {
var jsDocParam = jsDoc.params.find(function (p) {
return p.name === param.name;
});
return merge(jsDocParam, param);
});
return (0, _extends3.default)({}, method, {
description: jsDoc.description || null,
returns: returns,
params: params
});
});
documentation.set('methods', methods);
}n/a
function componentDocblockHandler(documentation, path) {
var description = null;
// Find parent statement (e.g. var Component = React.createClass(<path>);)
var searchPath = path;
while (searchPath && !types.Statement.check(searchPath.node)) {
searchPath = searchPath.parent;
}
if (searchPath) {
// If the parent is an export statement, we have to traverse one more up
if (types.ExportNamedDeclaration.check(searchPath.parentPath.node) || types.ExportDefaultDeclaration.check(searchPath.parentPath
.node)) {
searchPath = searchPath.parentPath;
}
description = (0, _docblock.getDocblock)(searchPath);
}
if (description == null && isClassDefinition(path)) {
// If we have a class declaration or expression, then the comment might be
// attached to the first decorator instead.
if (path.node.decorators && path.node.decorators.length > 0) {
description = (0, _docblock.getDocblock)(path.get('decorators', 0));
}
}
if (description == null) {
// If this is the first statement in the module body, the comment is attached
// to the program node
var programPath = searchPath;
while (programPath && !types.Program.check(programPath.node)) {
programPath = programPath.parent;
}
if (programPath.get('body', 0) === searchPath) {
description = (0, _docblock.getDocblock)(programPath);
}
}
documentation.set('description', description || '');
}n/a
function componentMethodsHandler(documentation, path) {
// Extract all methods from the class or object.
var methodPaths = [];
if ((0, _isReactComponentClass2.default)(path)) {
methodPaths = path.get('body', 'body').filter(function (p) {
return types.MethodDefinition.check(p.node) && p.node.kind !== 'constructor';
});
} else if (types.ObjectExpression.check(path.node)) {
methodPaths = path.get('properties').filter(isFunctionExpression);
// Add the statics object properties.
var statics = (0, _getMemberValuePath2.default)(path, 'statics');
if (statics) {
statics.get('properties').each(function (p) {
if (isFunctionExpression(p)) {
p.node.static = true;
methodPaths.push(p);
}
});
}
}
var methods = getMethodsDoc(methodPaths);
documentation.set('methods', methods);
}n/a
function componentMethodsJsDocHandler(documentation) {
var methods = documentation.get('methods');
if (!methods) {
return;
}
methods = methods.map(function (method) {
if (!method.docblock) {
return method;
}
var jsDoc = (0, _parseJsDoc2.default)(method.docblock);
var returns = merge(jsDoc.returns, method.returns);
var params = method.params.map(function (param) {
var jsDocParam = jsDoc.params.find(function (p) {
return p.name === param.name;
});
return merge(jsDocParam, param);
});
return (0, _extends3.default)({}, method, {
description: jsDoc.description || null,
returns: returns,
params: params
});
});
documentation.set('methods', methods);
}n/a
function defaultPropsHandler(documentation, componentDefinition) {
var statelessProps = null;
var defaultPropsPath = getDefaultPropsPath(componentDefinition);
if ((0, _isStatelessComponent2.default)(componentDefinition)) {
statelessProps = getStatelessPropsPath(componentDefinition);
}
// Do both statelessProps and defaultProps if both are available so defaultProps can override
if (statelessProps && types.ObjectPattern.check(statelessProps.node)) {
getDefaultValuesFromProps(statelessProps.get('properties'), documentation, true);
}
if (defaultPropsPath && types.ObjectExpression.check(defaultPropsPath.node)) {
getDefaultValuesFromProps(defaultPropsPath.get('properties'), documentation, false);
}
}n/a
function displayNameHandler(documentation, path) {
var displayNamePath = (0, _getMemberValuePath2.default)(path, 'displayName');
if (!displayNamePath) {
return;
}
displayNamePath = (0, _resolveToValue2.default)(displayNamePath);
// If display name is defined as a getter we get a function expression as
// value. In that case we try to determine the value from the return
// statement.
if (types.FunctionExpression.check(displayNamePath.node)) {
(0, _traverse.traverseShallow)(displayNamePath.get('body'), {
visitReturnStatement: function visitReturnStatement(path) {
displayNamePath = (0, _resolveToValue2.default)(path.get('argument'));
return false;
}
});
}
if (!displayNamePath || !types.Literal.check(displayNamePath.node)) {
return;
}
documentation.set('displayName', displayNamePath.node.value);
}n/a
function flowTypeDocBlockHandler(documentation, path) {
var flowTypesPath = (0, _getFlowTypeFromReactComponent2.default)(path);
if (!flowTypesPath) {
return;
}
(0, _getFlowTypeFromReactComponent.applyToFlowTypeProperties)(flowTypesPath, function (propertyPath) {
return (0, _setPropDescription2.default)(documentation, propertyPath);
});
}n/a
function flowTypeHandler(documentation, path) {
var flowTypesPath = (0, _getFlowTypeFromReactComponent2.default)(path);
if (!flowTypesPath) {
return;
}
(0, _getFlowTypeFromReactComponent.applyToFlowTypeProperties)(flowTypesPath, function (propertyPath) {
setPropDescriptor(documentation, propertyPath);
});
}n/a
function propDocBlockHandler(documentation, path) {
var propTypesPath = (0, _getMemberValuePath2.default)(path, 'propTypes');
if (!propTypesPath) {
return;
}
propTypesPath = (0, _resolveToValue2.default)(propTypesPath);
if (!propTypesPath || !types.ObjectExpression.check(propTypesPath.node)) {
return;
}
propTypesPath.get('properties').each(function (propertyPath) {
// we only support documentation of actual properties, not spread
if (types.Property.check(propertyPath.node)) {
(0, _setPropDescription2.default)(documentation, propertyPath);
}
});
}n/a
function propTypeCompositionHandler(documentation, path) {
var propTypesPath = (0, _getMemberValuePath2.default)(path, 'propTypes');
if (!propTypesPath) {
return;
}
propTypesPath = (0, _resolveToValue2.default)(propTypesPath);
if (!propTypesPath) {
return;
}
switch (propTypesPath.node.type) {
case types.ObjectExpression.name:
processObjectExpression(documentation, propTypesPath);
break;
default:
amendComposes(documentation, propTypesPath);
break;
}
}n/a
function propTypeHandler(documentation, path) {
var propTypesPath = (0, _getMemberValuePath2.default)(path, 'propTypes');
if (!propTypesPath) {
return;
}
propTypesPath = (0, _resolveToValue2.default)(propTypesPath);
if (!propTypesPath) {
return;
}
amendPropTypes(documentation, propTypesPath);
}n/a
function findAllReactCreateClassCalls(ast, recast) {
var types = recast.types.namedTypes;
var definitions = [];
function classVisitor(path) {
if ((0, _isReactComponentClass2.default)(path)) {
(0, _normalizeClassDefinition2.default)(path);
definitions.push(path);
}
return false;
}
function statelessVisitor(path) {
if ((0, _isStatelessComponent2.default)(path)) {
definitions.push(path);
}
return false;
}
recast.visit(ast, {
visitFunctionDeclaration: statelessVisitor,
visitFunctionExpression: statelessVisitor,
visitArrowFunctionExpression: statelessVisitor,
visitClassExpression: classVisitor,
visitClassDeclaration: classVisitor,
visitCallExpression: function visitCallExpression(path) {
if (!(0, _isReactCreateClassCall2.default)(path)) {
return false;
}
var resolvedPath = (0, _resolveToValue2.default)(path.get('arguments', 0));
if (types.ObjectExpression.check(resolvedPath.node)) {
definitions.push(resolvedPath);
}
return false;
}
});
return definitions;
}n/a
function findExportedComponentDefinitions(ast, recast) {
var types = recast.types.namedTypes;
var components = [];
function exportDeclaration(path) {
var definitions = (0, _resolveExportDeclaration2.default)(path, types).reduce(function (acc, definition) {
if (isComponentDefinition(definition)) {
acc.push(definition);
} else {
var resolved = (0, _resolveToValue2.default)((0, _resolveHOC2.default)(definition));
if (isComponentDefinition(resolved)) {
acc.push(resolved);
}
}
return acc;
}, []).map(function (definition) {
return resolveDefinition(definition, types);
});
if (definitions.length === 0) {
return false;
}
definitions.forEach(function (definition) {
if (definition && components.indexOf(definition) === -1) {
components.push(definition);
}
});
return false;
}
recast.visit(ast, {
visitFunctionDeclaration: ignore,
visitFunctionExpression: ignore,
visitClassDeclaration: ignore,
visitClassExpression: ignore,
visitIfStatement: ignore,
visitWithStatement: ignore,
visitSwitchStatement: ignore,
visitCatchCause: ignore,
visitWhileStatement: ignore,
visitDoWhileStatement: ignore,
visitForStatement: ignore,
visitForInStatement: ignore,
visitExportDeclaration: exportDeclaration,
visitExportNamedDeclaration: exportDeclaration,
visitExportDefaultDeclaration: exportDeclaration,
visitAssignmentExpression: function visitAssignmentExpression(path) {
// Ignore anything that is not `exports.X = ...;` or
// `module.exports = ...;`
if (!(0, _isExportsOrModuleAssignment2.default)(path)) {
return false;
}
// Resolve the value of the right hand side. It should resolve to a call
// expression, something like React.createClass
path = (0, _resolveToValue2.default)(path.get('right'));
if (!isComponentDefinition(path)) {
path = (0, _resolveToValue2.default)((0, _resolveHOC2.default)(path));
if (!isComponentDefinition(path)) {
return false;
}
}
var definition = resolveDefinition(path, types);
if (definition && components.indexOf(definition) === -1) {
components.push(definition);
}
return false;
}
});
return components;
}n/a
function findExportedComponentDefinition(ast, recast) {
var types = recast.types.namedTypes;
var definition;
function exportDeclaration(path) {
var definitions = (0, _resolveExportDeclaration2.default)(path, types).reduce(function (acc, definition) {
if (isComponentDefinition(definition)) {
acc.push(definition);
} else {
var resolved = (0, _resolveToValue2.default)((0, _resolveHOC2.default)(definition));
if (isComponentDefinition(resolved)) {
acc.push(resolved);
}
}
return acc;
}, []);
if (definitions.length === 0) {
return false;
}
if (definitions.length > 1 || definition) {
// If a file exports multiple components, ... complain!
throw new Error(ERROR_MULTIPLE_DEFINITIONS);
}
definition = resolveDefinition(definitions[0], types);
return false;
}
recast.visit(ast, {
visitFunctionDeclaration: ignore,
visitFunctionExpression: ignore,
visitClassDeclaration: ignore,
visitClassExpression: ignore,
visitIfStatement: ignore,
visitWithStatement: ignore,
visitSwitchStatement: ignore,
visitCatchCause: ignore,
visitWhileStatement: ignore,
visitDoWhileStatement: ignore,
visitForStatement: ignore,
visitForInStatement: ignore,
visitExportDeclaration: exportDeclaration,
visitExportNamedDeclaration: exportDeclaration,
visitExportDefaultDeclaration: exportDeclaration,
visitAssignmentExpression: function visitAssignmentExpression(path) {
// Ignore anything that is not `exports.X = ...;` or
// `module.exports = ...;`
if (!(0, _isExportsOrModuleAssignment2.default)(path)) {
return false;
}
// Resolve the value of the right hand side. It should resolve to a call
// expression, something like React.createClass
path = (0, _resolveToValue2.default)(path.get('right'));
if (!isComponentDefinition(path)) {
path = (0, _resolveToValue2.default)((0, _resolveHOC2.default)(path));
if (!isComponentDefinition(path)) {
return false;
}
}
if (definition) {
// If a file exports multiple components, ... complain!
throw new Error(ERROR_MULTIPLE_DEFINITIONS);
}
definition = resolveDefinition(path, types);
return false;
}
});
return definition;
}n/a
function getClassMemberValuePath(classDefinition, memberName) {
// Fortunately it seems like that all members of a class body, be it
// ClassProperty or MethodDefinition, have the same structure: They have a
// "key" and a "value"
return classDefinition.get('body', 'body').filter(function (memberPath) {
return (!memberPath.node.computed || types.Literal.check(memberPath.node.key)) && (0, _getNameOrValue2.default)(memberPath.get
('key')) === memberName && memberPath.node.kind !== 'set';
}).map(function (memberPath) {
return memberPath.get('value');
})[0];
}n/a
function getFlowType(path) {
var node = path.node;
var type = void 0;
if (types.Type.check(node)) {
if (node.type in flowTypes) {
type = { name: flowTypes[node.type] };
} else if (node.type in flowLiteralTypes) {
type = { name: 'literal', value: node.raw || '' + node.value };
} else if (node.type in namedTypes) {
type = namedTypes[node.type](path);
}
}
if (!type) {
type = { name: 'unknown' };
}
return type;
}n/a
getFlowTypeFromReactComponent = function (path) {
var typePath = void 0;
if ((0, _isReactComponentClass2.default)(path)) {
var superTypes = path.get('superTypeParameters');
if (superTypes.value) {
typePath = superTypes.get('params').get(1);
} else {
var propsMemberPath = (0, _getMemberValuePath2.default)(path, 'props');
if (!propsMemberPath) {
return null;
}
typePath = (0, _getTypeAnnotation2.default)(propsMemberPath.parentPath);
}
} else if ((0, _isStatelessComponent2.default)(path)) {
var param = path.get('params').get(0);
typePath = (0, _getTypeAnnotation2.default)(param);
}
if (typePath && types.GenericTypeAnnotation.check(typePath.node)) {
typePath = (0, _resolveToValue2.default)(typePath.get('id'));
if (!typePath || types.Identifier.check(typePath.node) || (0, _isUnreachableFlowType2.default)(typePath)) {
return;
}
typePath = typePath.get('right');
}
return typePath;
}n/a
function getMemberExpressionRoot(memberExpressionPath) {
do {
memberExpressionPath = memberExpressionPath.get('object');
} while (types.MemberExpression.check(memberExpressionPath.node));
return memberExpressionPath;
}n/a
function getMemberValuePath(componentDefinition, memberName) {
if (!isSupportedDefinitionType(componentDefinition)) {
throw new TypeError('Got unsupported definition type. Definition must be one of ' + 'ObjectExpression, ClassDeclaration, ClassExpression
,' + 'VariableDeclaration, ArrowFunctionExpression, FunctionExpression, or ' + 'FunctionDeclaration. Got "' + componentDefinition
.node.type + '"' + 'instead.');
}
var lookupMethod = LOOKUP_METHOD[componentDefinition.node.type];
var result = lookupMethod(componentDefinition, memberName);
if (!result && SYNONYMS[memberName]) {
return lookupMethod(componentDefinition, SYNONYMS[memberName]);
}
return result;
}n/a
function getMembers(path) {
var includeRoot = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var result = [];
var argumentsPath = null;
loop: while (true) {
// eslint-disable-line no-constant-condition
switch (true) {
case types.MemberExpression.check(path.node):
result.push({
path: path.get('property'),
computed: path.node.computed,
argumentsPath: argumentsPath
});
argumentsPath = null;
path = path.get('object');
break;
case types.CallExpression.check(path.node):
argumentsPath = path.get('arguments');
path = path.get('callee');
break;
default:
break loop;
}
}
if (includeRoot && result.length > 0) {
result.push({
path: path,
computed: false,
argumentsPath: argumentsPath
});
}
return result.reverse();
}n/a
function getMethodDocumentation(methodPath) {
var name = (0, _getPropertyName2.default)(methodPath);
var docblock = (0, _docblock.getDocblock)(methodPath);
return {
name: name,
docblock: docblock,
modifiers: getMethodModifiers(methodPath),
params: getMethodParamsDoc(methodPath),
returns: getMethodReturnDoc(methodPath)
};
}n/a
function getNameOrValue(path, raw) {
var node = path.node;
switch (node.type) {
case types.Identifier.name:
return node.name;
case types.Literal.name:
return raw ? node.raw : node.value;
default:
throw new TypeError('Argument must be an Identifier or a Literal');
}
}n/a
function getParameterName(parameterPath) {
switch (parameterPath.node.type) {
case types.Identifier.name:
return parameterPath.node.name;
case types.AssignmentPattern.name:
return getParameterName(parameterPath.get('left'));
case types.ObjectPattern.name:
return (0, _printValue2.default)(parameterPath);
case types.RestElement.name:
return '...' + getParameterName(parameterPath.get('argument'));
default:
throw new TypeError('Parameter name must be an Identifier, an AssignmentPattern an ' + ('ObjectPattern or a RestElement, got
' + parameterPath.node.type));
}
}n/a
function getPropType(path) {
var descriptor;
(0, _getMembers2.default)(path, true).some(function (member) {
var node = member.path.node;
var name;
if (types.Literal.check(node)) {
name = node.value;
} else if (types.Identifier.check(node) && !member.computed) {
name = node.name;
}
if (name) {
if (simplePropTypes.hasOwnProperty(name)) {
descriptor = { name: name };
return true;
} else if (propTypes.hasOwnProperty(name) && member.argumentsPath) {
descriptor = propTypes[name](member.argumentsPath.get(0));
return true;
}
}
});
if (!descriptor) {
var node = path.node;
if (types.Identifier.check(node) && simplePropTypes.hasOwnProperty(node.name)) {
descriptor = { name: node.name };
} else if (types.CallExpression.check(node) && types.Identifier.check(node.callee) && propTypes.hasOwnProperty(node.callee.name
)) {
descriptor = propTypes[node.callee.name](path.get('arguments', 0));
} else {
descriptor = { name: 'custom', raw: (0, _printValue2.default)(path) };
}
}
return descriptor;
}n/a
function getPropertyName(propertyPath) {
if (propertyPath.node.computed) {
throw new TypeError('Propery name must be an Identifier or a Literal');
}
return (0, _getNameOrValue2.default)(propertyPath.get('key'), false);
}n/a
function getPropertyValuePath(path, propertyName) {
types.ObjectExpression.assert(path.node);
return path.get('properties').filter(function (propertyPath) {
return (0, _getPropertyName2.default)(propertyPath) === propertyName;
}).map(function (propertyPath) {
return propertyPath.get('value');
})[0];
}n/a
function getTypeAnnotation(path) {
if (!hasTypeAnnotation(path)) return null;
var resultPath = path;
do {
resultPath = resultPath.get('typeAnnotation');
} while (hasTypeAnnotation(resultPath) && !types.Type.check(resultPath.node));
return resultPath;
}n/a
function isExportsOrModuleAssignment(path) {
if (types.ExpressionStatement.check(path.node)) {
path = path.get('expression');
}
if (!types.AssignmentExpression.check(path.node) || !types.MemberExpression.check(path.node.left)) {
return false;
}
var exprArr = expressionTo.Array(path.get('left'));
return exprArr[0] === 'module' && exprArr[1] === 'exports' || exprArr[0] === 'exports';
}n/a
function isReactComponentClass(path) {
var node = path.node;
if (!types.ClassDeclaration.check(node) && !types.ClassExpression.check(node)) {
return false;
}
// render method
if (node.body.body.some(isRenderMethod)) {
return true;
}
// extends ReactComponent?
if (!node.superClass) {
return false;
}
var superClass = (0, _resolveToValue2.default)(path.get('superClass'));
if (!(0, _match2.default)(superClass.node, { property: { name: 'Component' } })) {
return false;
}
var module = (0, _resolveToModule2.default)(superClass);
return !!module && (0, _isReactModuleName2.default)(module);
}n/a
isReactComponentMethod = function (methodPath) {
if (!types.MethodDefinition.check(methodPath.node) && !types.Property.check(methodPath.node)) {
return false;
}
var name = (0, _getPropertyName2.default)(methodPath);
return componentMethods.indexOf(name) !== -1;
}n/a
function isReactCreateClassCall(path) {
if (types.ExpressionStatement.check(path.node)) {
path = path.get('expression');
}
if (!(0, _match2.default)(path.node, { callee: { property: { name: 'createClass' } } })) {
return false;
}
var module = (0, _resolveToModule2.default)(path.get('callee', 'object'));
return Boolean(module && (0, _isReactModuleName2.default)(module));
}n/a
function isReactModuleName(moduleName) {
return reactModules.some(function (reactModuleName) {
return reactModuleName === moduleName.toLowerCase();
});
}n/a
function isStatelessComponent(path) {
var node = path.node;
if (validPossibleStatelessComponentTypes.indexOf(node.type) === -1) {
return false;
}
if (node.type === 'Property') {
if ((0, _isReactCreateClassCall2.default)(path.parent) || (0, _isReactComponentClass2.default)(path.parent)) {
return false;
}
}
if (returnsJSXElementOrReactCreateElementCall(path)) {
return true;
}
return false;
}n/a
function match(node, pattern) {
if (!node) {
return false;
}
for (var prop in pattern) {
if (!node[prop]) {
return false;
}
if (pattern[prop] && (0, _typeof3.default)(pattern[prop]) === 'object') {
if (!match(node[prop], pattern[prop])) {
return false;
}
} else if (node[prop] !== pattern[prop]) {
return false;
}
}
return true;
}n/a
function normalizeClassDefinition(classDefinition) {
var variableName;
if (types.ClassDeclaration.check(classDefinition.node)) {
variableName = classDefinition.node.id.name;
} else if (types.ClassExpression.check(classDefinition.node)) {
var parentPath = classDefinition.parentPath;
while (parentPath.node !== classDefinition.scope.node && !types.BlockStatement.check(parentPath.node)) {
if (types.VariableDeclarator.check(parentPath.node) && types.Identifier.check(parentPath.node.id)) {
variableName = parentPath.node.id.name;
break;
} else if (types.AssignmentExpression.check(parentPath.node) && types.Identifier.check(parentPath.node.left)) {
variableName = parentPath.node.left.name;
break;
}
parentPath = parentPath.parentPath;
}
}
if (!variableName) {
return;
}
var scopeRoot = classDefinition.scope;
_recast2.default.visit(scopeRoot.node, {
visitFunction: ignore,
visitClassDeclaration: ignore,
visitClassExpression: ignore,
visitForInStatement: ignore,
visitForStatement: ignore,
visitAssignmentExpression: function visitAssignmentExpression(path) {
if (types.MemberExpression.check(path.node.left)) {
var first = (0, _getMemberExpressionRoot2.default)(path.get('left'));
if (types.Identifier.check(first.node) && first.node.name === variableName) {
var _getMembers = (0, _getMembers4.default)(path.get('left')),
_getMembers2 = (0, _slicedToArray3.default)(_getMembers, 1),
member = _getMembers2[0];
if (member && !member.path.node.computed) {
var classProperty = builders.classProperty(member.path.node, path.node.right, null, true);
classDefinition.get('body', 'body').value.push(classProperty);
return false;
}
}
this.traverse(path);
} else {
return false;
}
}
});
}n/a
function normalizeClassDefinition(classDefinition) {
var variableName;
if (types.ClassDeclaration.check(classDefinition.node)) {
variableName = classDefinition.node.id.name;
} else if (types.ClassExpression.check(classDefinition.node)) {
var parentPath = classDefinition.parentPath;
while (parentPath.node !== classDefinition.scope.node && !types.BlockStatement.check(parentPath.node)) {
if (types.VariableDeclarator.check(parentPath.node) && types.Identifier.check(parentPath.node.id)) {
variableName = parentPath.node.id.name;
break;
} else if (types.AssignmentExpression.check(parentPath.node) && types.Identifier.check(parentPath.node.left)) {
variableName = parentPath.node.left.name;
break;
}
parentPath = parentPath.parentPath;
}
}
if (!variableName) {
return;
}
var scopeRoot = classDefinition.scope;
_recast2.default.visit(scopeRoot.node, {
visitFunction: ignore,
visitClassDeclaration: ignore,
visitClassExpression: ignore,
visitForInStatement: ignore,
visitForStatement: ignore,
visitAssignmentExpression: function visitAssignmentExpression(path) {
if (types.MemberExpression.check(path.node.left)) {
var first = (0, _getMemberExpressionRoot2.default)(path.get('left'));
if (types.Identifier.check(first.node) && first.node.name === variableName) {
var _getMembers = (0, _getMembers4.default)(path.get('left')),
_getMembers2 = (0, _slicedToArray3.default)(_getMembers, 1),
member = _getMembers2[0];
if (member && !member.path.node.computed) {
var classProperty = builders.classProperty(member.path.node, path.node.right, null, true);
classDefinition.get('body', 'body').value.push(classProperty);
return false;
}
}
this.traverse(path);
} else {
return false;
}
}
});
}n/a
function printValue(path) {
if (path.node.comments) {
path.node.comments.length = 0;
}
return _recast2.default.print(path).code;
}n/a
function resolveExportDeclaration(path) {
var types = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _types;
var definitions = [];
if (path.node.default) {
definitions.push(path.get('declaration'));
} else if (path.node.declaration) {
if (types.VariableDeclaration.check(path.node.declaration)) {
path.get('declaration', 'declarations').each(function (declarator) {
return definitions.push(declarator);
});
} else {
definitions.push(path.get('declaration'));
}
} else if (path.node.specifiers) {
path.get('specifiers').each(function (specifier) {
return definitions.push(specifier.node.id ? specifier.get('id') : specifier.get('local'));
});
}
return definitions.map(function (definition) {
return (0, _resolveToValue2.default)(definition);
});
}n/a
function resolveToModule(path) {
var node = path.node;
switch (node.type) {
case types.VariableDeclarator.name:
if (node.init) {
return resolveToModule(path.get('init'));
}
break;
case types.CallExpression.name:
if ((0, _match2.default)(node.callee, { type: types.Identifier.name, name: 'require' })) {
return node.arguments[0].value;
}
return resolveToModule(path.get('callee'));
case types.Identifier.name:
var valuePath = (0, _resolveToValue2.default)(path);
if (valuePath !== path) {
return resolveToModule(valuePath);
}
break;
case types.ImportDeclaration.name:
return node.source.value;
case types.MemberExpression.name:
while (path && types.MemberExpression.check(path.node)) {
path = path.get('object');
}
if (path) {
return resolveToModule(path);
}
}
}n/a
function resolveToValue(path) {
var node = path.node;
if (types.VariableDeclarator.check(node)) {
if (node.init) {
return resolveToValue(path.get('init'));
}
} else if (types.MemberExpression.check(node)) {
var resolved = resolveToValue((0, _getMemberExpressionRoot2.default)(path));
if (types.ObjectExpression.check(resolved.node)) {
var memberParts = (0, _expressionTo.Array)(path).slice(1);
var init = memberParts.reduce(function (propertyPath, propertyName) {
propertyPath = resolveToValue(propertyPath);
return types.ObjectExpression.check(propertyPath.node) ? (0, _getPropertyValuePath2.default)(propertyPath, propertyName) :
null;
}, resolved);
return init ? resolveToValue(init) : path;
}
} else if (types.ImportDefaultSpecifier.check(node) || types.ImportNamespaceSpecifier.check(node) || types.ImportSpecifier.check
(node)) {
return path.parentPath;
} else if (types.AssignmentExpression.check(node)) {
if (node.operator === '=') {
return resolveToValue(path.get('right'));
}
} else if (types.Identifier.check(node)) {
if ((types.ClassDeclaration.check(path.parentPath.node) || types.ClassExpression.check(path.parentPath.node) || types.Function
.check(path.parentPath.node)) && path.parentPath.get('id') === path) {
return path.parentPath;
}
var scope = path.scope.lookup(node.name);
var resolvedPath = void 0;
if (scope) {
// The variable may be assigned a different value after initialization.
// We are first trying to find all assignments to the variable in the
// block where it is defined (i.e. we are not traversing into statements)
resolvedPath = findLastAssignedValue(scope, node.name);
if (!resolvedPath) {
var bindings = scope.getBindings()[node.name];
resolvedPath = findScopePath(bindings, path);
}
} else {
scope = path.scope.lookupType(node.name);
if (scope) {
var _types = scope.getTypes()[node.name];
resolvedPath = findScopePath(_types, path);
}
}
return resolvedPath || path;
}
return path;
}n/a
function getDocblock(path) {
var comments = [];
if (path.node.leadingComments) {
comments = path.node.leadingComments.filter(function (comment) {
return comment.type === 'CommentBlock' && DOCBLOCK_HEADER.test(comment.value);
});
} else if (path.node.comments) {
comments = path.node.comments.filter(function (comment) {
return comment.leading && comment.type === 'CommentBlock' && DOCBLOCK_HEADER.test(comment.value);
});
}
if (comments.length > 0) {
return parseDocblock(comments[comments.length - 1].value);
}
return null;
}n/a
function getDoclets(str) {
var doclets = (0, _create2.default)(null);
var match = DOCLET_PATTERN.exec(str);
for (; match; match = DOCLET_PATTERN.exec(str)) {
doclets[match[1]] = match[2] || true;
}
return doclets;
}n/a