UNPKG

react-docgen

Version:

A CLI and toolkit to extract information from React components for documentation generation.

112 lines (93 loc) 3.58 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = normalizeClassDefinition; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _getMemberExpressionRoot = _interopRequireDefault(require("../utils/getMemberExpressionRoot")); var _getMembers3 = _interopRequireDefault(require("../utils/getMembers")); var _recast = _interopRequireDefault(require("recast")); /* * Copyright (c) 2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * */ const _recast$types = _recast.default.types, types = _recast$types.namedTypes, builders = _recast$types.builders; const ignore = () => false; /** * Given a class definition (i.e. `class` declaration or expression), this * function "normalizes" the definition, by looking for assignments of static * properties and converting them to ClassProperties. * * Example: * * class MyComponent extends React.Component { * // ... * } * MyComponent.propTypes = { ... }; * * is converted to * * class MyComponent extends React.Component { * // ... * static propTypes = { ... }; * } */ function normalizeClassDefinition(classDefinition) { let variableName; if (types.ClassDeclaration.check(classDefinition.node)) { // Class declarations don't have an id, e.g.: `export default class extends React.Component {}` if (classDefinition.node.id) { variableName = classDefinition.node.id.name; } } else if (types.ClassExpression.check(classDefinition.node)) { let 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; } const scopeRoot = classDefinition.scope; _recast.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)) { const first = (0, _getMemberExpressionRoot.default)(path.get('left')); if (types.Identifier.check(first.node) && first.node.name === variableName) { const _getMembers = (0, _getMembers3.default)(path.get('left')), _getMembers2 = (0, _slicedToArray2.default)(_getMembers, 1), member = _getMembers2[0]; if (member && !member.path.node.computed) { const 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; } } }); }