From 0b80be68ae8fbfcfc90a6d22831dd4f068669d14 Mon Sep 17 00:00:00 2001 From: gengyang Date: Thu, 15 Oct 2020 21:43:38 +0800 Subject: [PATCH] feat: use parseJsDoc to parse propType docblock --- packages/material-parser/src/parse/index.ts | 1 + .../src/parse/js/handlers/index.ts | 2 + .../parse/js/handlers/propTypeJsDocHandler.ts | 36 ++++++++++++ .../material-parser/src/parse/transform.ts | 24 +++++++- .../material-parser/src/parse/ts/index.ts | 4 +- .../single-exported-component/es/index.js | 57 +++++++++++-------- .../single-exported-component/src/index.js | 5 ++ 7 files changed, 101 insertions(+), 28 deletions(-) create mode 100644 packages/material-parser/src/parse/js/handlers/propTypeJsDocHandler.ts diff --git a/packages/material-parser/src/parse/index.ts b/packages/material-parser/src/parse/index.ts index c96f6419c..a6c0043c1 100644 --- a/packages/material-parser/src/parse/index.ts +++ b/packages/material-parser/src/parse/index.ts @@ -31,6 +31,7 @@ export default async (args: IParseArgs) => { try { return parseJS(moduleFileAbsolutePath); } catch (e) { + log(e); await install(args); const info = parseDynamic(mainFileAbsolutePath); if (!info || !info.length) { diff --git a/packages/material-parser/src/parse/js/handlers/index.ts b/packages/material-parser/src/parse/js/handlers/index.ts index 7ad43bc8d..d884612db 100644 --- a/packages/material-parser/src/parse/js/handlers/index.ts +++ b/packages/material-parser/src/parse/js/handlers/index.ts @@ -3,6 +3,7 @@ import defaultPropsHandler from './defaultPropsHandler'; import flowTypeHandler from './flowTypeHandler'; import componentMethodsHandler from './componentMethodsHandler'; import preProcessHandler from './preProcessHandler'; +import propTypeJsDocHandler from './propTypeJsDocHandler'; const { handlers } = require('react-docgen'); @@ -13,6 +14,7 @@ const defaultHandlers = [ childContextTypeHandler, handlers.propTypeCompositionHandler, handlers.propDocBlockHandler, + propTypeJsDocHandler, flowTypeHandler, defaultPropsHandler, handlers.componentDocblockHandler, diff --git a/packages/material-parser/src/parse/js/handlers/propTypeJsDocHandler.ts b/packages/material-parser/src/parse/js/handlers/propTypeJsDocHandler.ts new file mode 100644 index 000000000..12c35bd14 --- /dev/null +++ b/packages/material-parser/src/parse/js/handlers/propTypeJsDocHandler.ts @@ -0,0 +1,36 @@ +/* eslint-disable no-param-reassign */ +const parseJsDoc = require('react-docgen/dist/utils/parseJsDoc').default; +const { getMemberValuePath, resolveToValue } = require('react-docgen').utils; + +function resolveDocumentation(documentation) { + documentation._props.forEach(propDescriptor => { + const { description } = propDescriptor; + if (description.includes('@')) { + const jsDoc = parseJsDoc(description); + propDescriptor.description = jsDoc.description; + if (jsDoc.params) { + propDescriptor.params = jsDoc.params; + } + if (jsDoc.returns) { + propDescriptor.returns = jsDoc.returns; + } + } + }); +} + +/** + * Extract info from the propType jsdoc blocks. Must be run after + * propDocBlockHandler. + */ +export default function propTypeJsDocHandler(documentation, path) { + let propTypesPath = getMemberValuePath(path, 'propTypes'); + if (!propTypesPath) { + return; + } + propTypesPath = resolveToValue(propTypesPath); + if (!propTypesPath) { + return; + } + + resolveDocumentation(documentation); +} diff --git a/packages/material-parser/src/parse/transform.ts b/packages/material-parser/src/parse/transform.ts index 2607b4580..aeed387e4 100644 --- a/packages/material-parser/src/parse/transform.ts +++ b/packages/material-parser/src/parse/transform.ts @@ -6,7 +6,17 @@ const log = debug.extend('parse:transform'); export function transformType(itemType: any) { if (typeof itemType === 'string') return itemType; - const { name, elements, value = elements, computed, required, type, raw } = itemType; + const { + name, + elements, + value = elements, + computed, + required, + type, + raw, + params, + returns, + } = itemType; if (computed !== undefined && value) { return safeEval(value); } @@ -29,11 +39,19 @@ export function transformType(itemType: any) { case 'node': break; case 'func': - if (value) { - result.value = value.map(x => ({ + if (params) { + result.params = params.map(x => ({ ...x, propType: transformType(x.propType), })); + } + if (returns) { + result.returns = returns.map(x => ({ + ...x, + propType: transformType(x.propType), + })); + } + if (raw) { result.raw = raw; } break; diff --git a/packages/material-parser/src/parse/ts/index.ts b/packages/material-parser/src/parse/ts/index.ts index b9e28b1f5..d3187a829 100644 --- a/packages/material-parser/src/parse/ts/index.ts +++ b/packages/material-parser/src/parse/ts/index.ts @@ -321,7 +321,7 @@ function getDocgenTypeHelper( } else if (type?.symbol?.valueDeclaration?.parameters?.length) { return makeResult({ name: 'func', - value: getFunctionParams( + params: getFunctionParams( // @ts-ignore type?.symbol?.valueDeclaration?.parameters, checker, @@ -335,7 +335,7 @@ function getDocgenTypeHelper( ) { return makeResult({ name: 'func', - value: getFunctionParams( + params: getFunctionParams( // @ts-ignore type?.members?.get('__call')?.declarations[0]?.symbol?.declarations[0]?.parameters, checker, diff --git a/packages/material-parser/test/fixtures/single-exported-component/es/index.js b/packages/material-parser/test/fixtures/single-exported-component/es/index.js index 48f49b74b..8009e3dd3 100644 --- a/packages/material-parser/test/fixtures/single-exported-component/es/index.js +++ b/packages/material-parser/test/fixtures/single-exported-component/es/index.js @@ -1,40 +1,47 @@ -import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; -import _createClass from "@babel/runtime/helpers/createClass"; -import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn"; -import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf"; -import _inherits from "@babel/runtime/helpers/inherits"; +import _classCallCheck from '@babel/runtime/helpers/classCallCheck'; +import _createClass from '@babel/runtime/helpers/createClass'; +import _possibleConstructorReturn from '@babel/runtime/helpers/possibleConstructorReturn'; +import _getPrototypeOf from '@babel/runtime/helpers/getPrototypeOf'; +import _inherits from '@babel/runtime/helpers/inherits'; /* eslint-disable react/no-unused-prop-types */ /* eslint-disable react/require-default-props */ import React from 'react'; import PropTypes from 'prop-types'; -import "./main.css"; +import './main.css'; const Demo = -/* #__PURE__ */ -function (_React$Component) { - _inherits(Demo, _React$Component); + /* #__PURE__ */ + (function(_React$Component) { + _inherits(Demo, _React$Component); - function Demo() { - _classCallCheck(this, Demo); + function Demo() { + _classCallCheck(this, Demo); - return _possibleConstructorReturn(this, _getPrototypeOf(Demo).apply(this, arguments)); - } + return _possibleConstructorReturn(this, _getPrototypeOf(Demo).apply(this, arguments)); + } - _createClass(Demo, [{ - key: "render", - value: function render() { - return React.createElement("div", null, " Test "); - }, - }]); + _createClass(Demo, [ + { + key: 'render', + value: function render() { + return React.createElement('div', null, ' Test '); + }, + }, + ]); - return Demo; -}(React.Component); + return Demo; + })(React.Component); Demo.propTypes = { optionalArray: PropTypes.array, optionalBool: PropTypes.bool, + /** + * desc + * @param {{ok:String}} userName + * @returns {any} + */ optionalFunc: PropTypes.func, optionalNumber: PropTypes.number, optionalObject: PropTypes.object, @@ -54,7 +61,11 @@ Demo.propTypes = { // it as an enum. optionalEnum: PropTypes.oneOf(['News', 'Photos']), // An object that could be one of many types - optionalUnion: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.instanceOf(Demo)]), + optionalUnion: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + PropTypes.instanceOf(Demo), + ]), // An array of a certain type optionalArrayOf: PropTypes.arrayOf(PropTypes.number), // An object with property values of a certain type @@ -82,4 +93,4 @@ Demo.propTypes = { Demo.defaultProps = { optionalNumber: 123, }; -export default Demo; \ No newline at end of file +export default Demo; diff --git a/packages/material-parser/test/fixtures/single-exported-component/src/index.js b/packages/material-parser/test/fixtures/single-exported-component/src/index.js index adca5ec9d..9d8e49773 100644 --- a/packages/material-parser/test/fixtures/single-exported-component/src/index.js +++ b/packages/material-parser/test/fixtures/single-exported-component/src/index.js @@ -14,6 +14,11 @@ class Demo extends React.Component { Demo.propTypes = { optionalArray: PropTypes.array, optionalBool: PropTypes.bool, + /** + * desc + * @param {{ok:String}} userName + * @returns {any} + */ optionalFunc: PropTypes.func, optionalNumber: PropTypes.number, optionalObject: PropTypes.object,