Skip to content

Commit ee8a535

Browse files
authored
Migrate babylon to @babel/parser (#272)
* Migrate babylon to @babel/parser * Add option to switch back to legacy decorators parsing
1 parent 4383cf1 commit ee8a535

File tree

10 files changed

+118
-72
lines changed

10 files changed

+118
-72
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
`react-docgen` is a CLI and toolbox to help extracting information from [React][] components, and generate documentation from it.
44

5-
It uses [recast][] and [babylon][] to parse the source into an AST and provides methods to process this AST to extract the desired information. The output / return value is a JSON blob / JavaScript object.
5+
It uses [recast][] and [@babel/parser][] to parse the source into an AST and provides methods to process this AST to extract the desired information. The output / return value is a JSON blob / JavaScript object.
66

77
It provides a default implementation for React components defined via
88
`React.createClass`, [ES2015 class definitions][classes] or functions
@@ -381,5 +381,5 @@ The structure of the JSON blob / JavaScript object is as follows:
381381
[react]: http://facebook.github.io/react/
382382
[flow]: http://flowtype.org/
383383
[recast]: https://github.com/benjamn/recast
384-
[babylon]: https://github.com/babel/babylon
384+
[@babel/parser]: https://github.com/babel/babel/tree/master/packages/babel-parser
385385
[classes]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

bin/react-docgen.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ argv
4141
'Filename or regex to exclude. Default: ' + JSON.stringify(defaultExclude),
4242
collect,
4343
[])
44+
.option(
45+
'--legacy-decorators',
46+
'Enable parsing of legacy decorators proposal. By default only the new decorators syntax will be parsable.')
4447
.option(
4548
'-i, --ignore <path>',
4649
'Folders to ignore. Default: ' + JSON.stringify(defaultIgnore),
@@ -100,7 +103,7 @@ if (argv.resolver) {
100103
}
101104

102105
function parse(source) {
103-
return parser.parse(source, resolver);
106+
return parser.parse(source, resolver, null, { legacyDecorators: argv.legacyDecorators });
104107
}
105108

106109
function writeError(msg, filePath) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232
"author": "Felix Kling",
3333
"license": "BSD-3-Clause",
3434
"dependencies": {
35+
"@babel/parser": "7.0.0-beta.48",
3536
"async": "^2.1.4",
3637
"babel-runtime": "^6.9.2",
37-
"babylon": "7.0.0-beta.44",
3838
"commander": "^2.9.0",
3939
"doctrine": "^2.0.0",
4040
"node-dir": "^0.1.10",

src/babelParser.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (c) 2015, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*
9+
* @flow
10+
*
11+
*/
12+
13+
var parser = require('@babel/parser');
14+
15+
var babelParserOptions = {
16+
sourceType: 'module',
17+
strictMode: false,
18+
plugins: [
19+
'jsx',
20+
'flow',
21+
'estree',
22+
'doExpressions',
23+
'objectRestSpread',
24+
'classProperties',
25+
'classPrivateProperties',
26+
'classPrivateMethods',
27+
'exportDefaultFrom',
28+
'exportNamespaceFrom',
29+
'asyncGenerators',
30+
'functionBind',
31+
'functionSent',
32+
'dynamicImport',
33+
'numericSeparator',
34+
'optionalChaining',
35+
'importMeta',
36+
'bigInt',
37+
'optionalCatchBinding',
38+
'throwExpressions',
39+
'pipelineOperator',
40+
'nullishCoalescingOperator',
41+
],
42+
};
43+
44+
export type Options = {
45+
legacyDecorators ?: boolean,
46+
};
47+
48+
function buildOptions(options?: Options = {}) {
49+
const parserOptions = { ...babelParserOptions, plugins: [...babelParserOptions.plugins] };
50+
if (options.legacyDecorators) {
51+
parserOptions.plugins.push('decorators-legacy');
52+
} else {
53+
parserOptions.plugins.push('decorators');
54+
}
55+
56+
return parserOptions;
57+
}
58+
59+
export default function buildParse(options: Options) {
60+
const parserOptions = buildOptions(options);
61+
62+
return {
63+
parse(src: string) {
64+
var file = parser.parse(src, parserOptions);
65+
file.program.comments = file.comments;
66+
return file.program;
67+
},
68+
};
69+
}

src/babylon.js

Lines changed: 0 additions & 48 deletions
This file was deleted.

src/handlers/__tests__/componentDocblockHandler-test.js

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,18 @@ describe('componentDocblockHandler', () => {
8989
* Decorates can only be assigned to class and therefore only make sense for
9090
* class declarations and export declarations.
9191
*/
92-
function testDecorators(definitionSrc, parse) { // eslint-disable-line no-shadow
92+
function testDecorators(classSrc, parse, exportSrc = '') { // eslint-disable-line no-shadow
9393
describe('decorators', () => {
9494
it('uses the docblock above the decorator if it\'s the only one', () => {
9595
var definition = parse(`
9696
import something from 'somewhere';
9797
/**
9898
* Component description
9999
*/
100+
${exportSrc}
100101
@Decorator1
101102
@Decorator2
102-
${definitionSrc}
103+
${classSrc}
103104
`);
104105

105106
componentDocblockHandler(documentation, definition);
@@ -109,15 +110,17 @@ describe('componentDocblockHandler', () => {
109110
it('uses the component docblock if present', () => {
110111
var definition = parse(`
111112
import something from 'somewhere';
113+
114+
${exportSrc}
112115
/**
113-
* Decorator description
114-
*/
116+
* Decorator description
117+
*/
115118
@Decorator1
116119
@Decorator2
117120
/**
118121
* Component description
119122
*/
120-
${definitionSrc}
123+
${classSrc}
121124
`);
122125

123126
componentDocblockHandler(documentation, definition);
@@ -181,8 +184,9 @@ describe('componentDocblockHandler', () => {
181184
src => lastStatement(src).get('declaration')
182185
);
183186
testDecorators(
184-
'export default class Component {}',
185-
src => lastStatement(src).get('declaration')
187+
'class Component {}',
188+
src => lastStatement(src).get('declaration'),
189+
'export default'
186190
);
187191
});
188192

@@ -192,8 +196,9 @@ describe('componentDocblockHandler', () => {
192196
src => lastStatement(src).get('declaration')
193197
);
194198
testDecorators(
195-
'export default class {}',
196-
src => lastStatement(src).get('declaration')
199+
'class {}',
200+
src => lastStatement(src).get('declaration'),
201+
'export default'
197202
);
198203
});
199204

@@ -241,8 +246,9 @@ describe('componentDocblockHandler', () => {
241246
src => lastStatement(src).get('declaration')
242247
);
243248
testDecorators(
244-
'export class Component {}',
245-
src => lastStatement(src).get('declaration')
249+
'class Component {}',
250+
src => lastStatement(src).get('declaration'),
251+
'export'
246252
);
247253
});
248254

src/main.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import * as handlers from './handlers';
1414
import parse from './parse';
1515
import * as resolver from './resolver';
1616
import * as utils from './utils';
17+
import type { Options } from './babelParser';
1718

1819
var defaultResolver = resolver.findExportedComponentDefinition;
1920
var defaultHandlers = [
@@ -45,7 +46,8 @@ var defaultHandlers = [
4546
function defaultParse( // eslint-disable-line no-unused-vars
4647
src: string,
4748
resolver?: ?Resolver, // eslint-disable-line no-shadow
48-
handlers?: ?Array<Handler> // eslint-disable-line no-shadow
49+
handlers?: ?Array<Handler>, // eslint-disable-line no-shadow
50+
options ?: Options = {}
4951
): Array<Object>|Object {
5052
if (!resolver) {
5153
resolver = defaultResolver;
@@ -54,7 +56,7 @@ function defaultParse( // eslint-disable-line no-unused-vars
5456
handlers = defaultHandlers;
5557
}
5658

57-
return parse(src, resolver, handlers);
59+
return parse(src, resolver, handlers, options);
5860
}
5961

6062
export {

src/parse.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import Documentation from './Documentation';
1414
import postProcessDocumentation from './utils/postProcessDocumentation';
1515

16-
import babylon from './babylon';
16+
import buildParser, { type Options } from './babelParser';
1717
import recast from 'recast';
1818

1919
var ERROR_MISSING_DEFINITION = 'No suitable component definition found.';
@@ -49,9 +49,10 @@ function executeHandlers(handlers, componentDefinitions) {
4949
export default function parse(
5050
src: string,
5151
resolver: Resolver,
52-
handlers: Array<Handler>
52+
handlers: Array<Handler>,
53+
options: Options
5354
): Array<Object>|Object {
54-
var ast = recast.parse(src, {esprima: babylon});
55+
var ast = recast.parse(src, { parser: buildParser(options) });
5556
var componentDefinitions = resolver(ast.program, recast);
5657

5758
if (Array.isArray(componentDefinitions)) {

tests/utils.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import _recast from 'recast';
6-
import babylon from '../src/babylon';
6+
import buildParser from '../src/babelParser';
77

88
function stringify(value) {
99
if (Array.isArray(value)) {
@@ -15,9 +15,9 @@ function stringify(value) {
1515
/**
1616
* Returns a NodePath to the program node of the passed node
1717
*/
18-
export function parse(src, recast=_recast) {
18+
export function parse(src, recast = _recast, options = {}) {
1919
return new recast.types.NodePath(
20-
recast.parse(stringify(src), {esprima: babylon}).program
20+
recast.parse(stringify(src), { parser: buildParser(options) }).program
2121
);
2222
}
2323

yarn.lock

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@
6060
esutils "^2.0.2"
6161
js-tokens "^3.0.0"
6262

63+
64+
version "7.0.0-beta.48"
65+
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0-beta.48.tgz#f93895cbacee703c0ec98e5af3901c77edd9f1d7"
66+
6367
6468
version "7.0.0-beta.44"
6569
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f"
@@ -124,7 +128,16 @@ ajv-keywords@^2.1.0:
124128
version "2.1.1"
125129
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762"
126130

127-
ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0:
131+
ajv@^5.1.0:
132+
version "5.3.0"
133+
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.3.0.tgz#4414ff74a50879c208ee5fdc826e32c303549eda"
134+
dependencies:
135+
co "^4.6.0"
136+
fast-deep-equal "^1.0.0"
137+
fast-json-stable-stringify "^2.0.0"
138+
json-schema-traverse "^0.3.0"
139+
140+
ajv@^5.2.3, ajv@^5.3.0:
128141
version "5.5.2"
129142
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
130143
dependencies:

0 commit comments

Comments
 (0)