diff --git a/package.json b/package.json index c2434ce4dd2..6e1ee5ee268 100644 --- a/package.json +++ b/package.json @@ -46,10 +46,12 @@ "license": "MIT", "dependencies": { "@babel/core": "^7.7.5", + "@babel/generator": "^7.12.11", "@babel/runtime": "^7.7.6", "ast-types": "^0.14.2", "commander": "^2.19.0", "doctrine": "^3.0.0", + "estree-to-babel": "^3.1.0", "neo-async": "^2.6.1", "node-dir": "^0.1.10", "resolve": "^1.17.0", diff --git a/src/utils/__tests__/printValue-test.js b/src/utils/__tests__/printValue-test.js index b5856c71770..bcbd29d1efa 100644 --- a/src/utils/__tests__/printValue-test.js +++ b/src/utils/__tests__/printValue-test.js @@ -6,6 +6,7 @@ * */ +import { builders, NodePath } from 'ast-types'; import { parse } from '../../../tests/utils'; import printValue from '../printValue'; @@ -21,4 +22,32 @@ describe('printValue', () => { it('does not print trailing comments', () => { expect(printValue(pathFromSource('bar//foo'))).toEqual('bar'); }); + + it('handles arbitrary generated nodes', () => { + expect( + printValue( + new NodePath( + builders.arrayExpression([ + builders.literal('bar'), + builders.literal('foo'), + builders.literal(1), + builders.literal(2), + builders.literal(3), + builders.literal(null), + builders.memberExpression( + builders.identifier('foo'), + builders.identifier('bar'), + ), + builders.jsxElement( + builders.jsxOpeningElement( + builders.jsxIdentifier('Baz'), + [], + true, + ), + ), + ]), + ), + ), + ).toEqual('["bar", "foo", 1, 2, 3, null, foo.bar, ]'); + }); }); diff --git a/src/utils/printValue.js b/src/utils/printValue.js index 288bc42023d..bcf0cc19867 100644 --- a/src/utils/printValue.js +++ b/src/utils/printValue.js @@ -8,6 +8,8 @@ */ import strip from 'strip-indent'; +import toBabel from 'estree-to-babel'; +import generate from '@babel/generator'; function deindent(code: string): string { const firstNewLine = code.indexOf('\n'); @@ -35,15 +37,28 @@ function getSrcFromAst(path: NodePath): string { */ export default function printValue(path: NodePath): string { if (path.node.start == null) { - // This only happens when we use AST builders to create nodes that do not actually - // exist in the source (e.g. when resolving Object.keys()). We might need to enhance - // this if we start using builders from `ast-types` more. - if (path.node.type === 'Literal') { - return `"${path.node.value}"`; + try { + const nodeCopy = { + ...path.node, + }; + + // `estree-to-babel` expects the `comments` property to exist on the top-level node + if (!nodeCopy.comments) { + nodeCopy.comments = []; + } + + return generate(toBabel(nodeCopy), { + comments: false, + concise: true, + }).code; + } catch (err) { + throw new Error( + `Cannot print raw value for type '${path.node.type}'. Please report this with an example at https://github.com/reactjs/react-docgen/issues. + +Original error: +${err.stack}`, + ); } - throw new Error( - `Cannot print raw value for type '${path.node.type}'. Please report this with an example at https://github.com/reactjs/react-docgen/issues`, - ); } const src = getSrcFromAst(path); diff --git a/yarn.lock b/yarn.lock index 463249fb7c4..75d75776136 100644 --- a/yarn.lock +++ b/yarn.lock @@ -52,10 +52,10 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.12.10", "@babel/generator@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.13.tgz#5f6ebe6c85db99886db2d7b044409196f872a503" - integrity sha512-9qQ8Fgo8HaSvHEt6A5+BATP7XktD/AdAnObUeTRz5/e2y3kbrxZgz32qUJJsdmwUvBJzF4AeV21nGTNwv05Mpw== +"@babel/generator@^7.12.10", "@babel/generator@^7.12.11", "@babel/generator@^7.12.13": + version "7.12.15" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.15.tgz#4617b5d0b25cc572474cc1aafee1edeaf9b5368f" + integrity sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ== dependencies: "@babel/types" "^7.12.13" jsesc "^2.5.1" @@ -255,9 +255,9 @@ js-tokens "^4.0.0" "@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.13", "@babel/parser@^7.7.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.13.tgz#3ee7be4131fe657ba9143d5c5b3a9f253fdb75e9" - integrity sha512-z7n7ybOUzaRc3wwqLpAX8UFIXsrVXUJhtNGBwAnLz6d1KUapqyq7ad2La8gZ6CXhHmGAIL32cop8Tst4/PNWLw== + version "7.12.15" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.15.tgz#2b20de7f0b4b332d9b119dd9c33409c538b8aacf" + integrity sha512-AQBOU2Z9kWwSZMd6lNjCX0GUgFonL1wAM1db8L8PMk9UDaGsRCArBkU4Sc+UCM3AE4hjbXx+h58Lb3QT4oRmrA== "@babel/plugin-proposal-async-generator-functions@^7.12.13": version "7.12.13" @@ -843,7 +843,7 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.13", "@babel/traverse@^7.12.5", "@babel/traverse@^7.7.0": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.1.6", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.13", "@babel/traverse@^7.12.5", "@babel/traverse@^7.7.0": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.13.tgz#689f0e4b4c08587ad26622832632735fb8c4e0c0" integrity sha512-3Zb4w7eE/OslI0fTp8c7b286/cQps3+vdLW3UcwC8VSJC6GbKn55aeVVu2QJNuCDoeKyptLOFrPq8WqZZBodyA== @@ -858,7 +858,7 @@ globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": +"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.13.tgz#8be1aa8f2c876da11a9cf650c0ecf656913ad611" integrity sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ== @@ -2130,6 +2130,14 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== +estree-to-babel@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/estree-to-babel/-/estree-to-babel-3.1.1.tgz#5f74a79408245978a68d05ff31de6575b0366316" + integrity sha512-dSTnpw8W0AFPp06ZXeeeFC9ZB6q8MS+U5sUHkZmQZkPncivYionH2RjNDQSnVjfhWViVsIH8FcZ1lSnuYkYKOQ== + dependencies: + "@babel/traverse" "^7.1.6" + "@babel/types" "^7.2.0" + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"