Permalink
Browse files

feat(parser): switch a parser to babylon

#293
this is breaking change.
  • Loading branch information...
h13i32maru committed Aug 14, 2016
1 parent 52f8ce3 commit 8130a3f42b497e81f9ec6fc4cf0ef07ed5a7fa22
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -22,16 +22,17 @@
"color-logger": "0.0.3",
"core-js": "2.4.1",
"escape-html": "1.0.3",
- "escodegen": "1.8.1",
- "espree": "2.2.0",
- "estraverse": "4.2.0",
+ "babylon": "6.8.4",
+ "babel-generator": "6.11.4",
+ "babel-traverse": "6.12.0",
"fs-extra": "0.30.0",
"ice-cap": "0.0.4",
"marked": "0.3.6",
"minimist": "1.2.0",
"taffydb": "2.7.2"
},
"devDependencies": {
+ "espree": "2.2.0",
"babel-register": "6.11.6",
"babel-cli": "6.11.4",
"babel-plugin-transform-es2015-modules-commonjs": "6.11.5",
View
@@ -1,6 +1,6 @@
#!/usr/bin/env node
-require('babel/register');
-var ESParser = require('../src/Parser/ESParser.js');
+require('babel-register');
+var ESParser = require('../src/Parser/ESParser.js').default;
var Plugin = require('../src/Plugin/Plugin.js').default;
Plugin.init([]);
View
@@ -633,7 +633,7 @@ export default class AbstractDoc {
*/
_findClassLongname(className) {
// find in same file.
- for (let node of this._ast.body) {
+ for (let node of this._ast.program.body) {
if (!['ExportDefaultDeclaration', 'ExportNamedDeclaration'].includes(node.type)) continue;
if (node.declaration && node.declaration.type === 'ClassDeclaration' && node.declaration.id.name === className) {
return `${this._pathResolver.filePath}~${className}`;
View
@@ -36,7 +36,7 @@ export default class MemberDoc extends AbstractDoc {
let parent = this._node.parent;
while (parent) {
- if (parent.type === 'MethodDefinition') {
+ if (parent.type === 'ClassMethod') {
this._value.static = parent.static;
break;
}
View
@@ -1,6 +1,6 @@
-import escodegen from 'escodegen';
import AbstractDoc from './AbstractDoc.js';
import ParamParser from '../Parser/ParamParser.js';
+import babelGenerator from 'babel-generator';
/**
* Doc Class from Method Definition AST node.
@@ -30,12 +30,8 @@ export default class MethodDoc extends AbstractDoc {
AbstractDoc.prototype['@_name'].call(this);
if (this._value.name) return;
- // todo: espree parses ``*[foo.bar](){}`` as not computed.
- // so, I hacked ``!this._node.key.name`` condition.
- // this condition is not needed with acorn.
- // see https://github.com/esdoc/esdoc/issues/107
- if (this._node.computed || !this._node.key.name) {
- const expression = escodegen.generate(this._node.key);
+ if (this._node.computed) {
+ const expression = babelGenerator(this._node.key).code;
this._value.name = `[${expression}]`;
} else {
this._value.name = this._node.key.name;
@@ -66,7 +62,7 @@ export default class MethodDoc extends AbstractDoc {
if (['set', 'get'].includes(this._value.kind)) return;
- this._value.params = ParamParser.guessParams(this._node.value.params);
+ this._value.params = ParamParser.guessParams(this._node.params);
}
/** if @type is not exists, guess type by using self node. only ``get`` and ``set`` are guess. */
@@ -79,7 +75,7 @@ export default class MethodDoc extends AbstractDoc {
this._value.type = ParamParser.guessType(this._node.right);
break;
case 'get':
- let result = ParamParser.guessReturnParam(this._node.value.body);
+ let result = ParamParser.guessReturnParam(this._node.body);
if (result) this._value.type = result;
break;
}
@@ -92,7 +88,7 @@ export default class MethodDoc extends AbstractDoc {
if (['constructor', 'set', 'get'].includes(this._value.kind)) return;
- let result = ParamParser.guessReturnParam(this._node.value.body);
+ let result = ParamParser.guessReturnParam(this._node.body);
if (result) {
this._value.return = result;
}
@@ -103,6 +99,6 @@ export default class MethodDoc extends AbstractDoc {
super['@_generator']();
if ('generator' in this._value) return;
- this._value.generator = this._node.value.generator;
+ this._value.generator = this._node.generator;
}
}
View
@@ -49,8 +49,8 @@ export default class DocFactory {
this._results.push(doc.value);
// ast does not child, so only comment.
- if (ast.body.length === 0 && ast.leadingComments) {
- let results = this._traverseComments(ast, null, ast.leadingComments);
+ if (ast.program.body.length === 0 && ast.program.innerComments) {
+ let results = this._traverseComments(ast, null, ast.program.innerComments);
this._results.push(...results);
}
}
@@ -86,7 +86,7 @@ export default class DocFactory {
_inspectExportDefaultDeclaration() {
let pseudoExportNodes = [];
- for (let exportNode of this._ast.body) {
+ for (let exportNode of this._ast.program.body) {
if (exportNode.type !== 'ExportDefaultDeclaration') continue;
let targetClassName = null;
@@ -159,7 +159,7 @@ export default class DocFactory {
}
}
- this._ast.body.push(...pseudoExportNodes);
+ this._ast.program.body.push(...pseudoExportNodes);
}
/**
@@ -186,7 +186,7 @@ export default class DocFactory {
_inspectExportNamedDeclaration() {
let pseudoExportNodes = [];
- for (let exportNode of this._ast.body) {
+ for (let exportNode of this._ast.program.body) {
if (exportNode.type !== 'ExportNamedDeclaration') continue;
if (exportNode.declaration && exportNode.declaration.type === 'VariableDeclaration') {
@@ -261,7 +261,7 @@ export default class DocFactory {
}
}
- this._ast.body.push(...pseudoExportNodes);
+ this._ast.program.body.push(...pseudoExportNodes);
}
/**
@@ -315,19 +315,6 @@ export default class DocFactory {
node = virtualNode;
}
- // hack: leadingComment of MethodDefinition with Literal is not valid by espree(v2.0.2)
- //if (node.type === 'MethodDefinition' && node.key.type === 'Literal') {
- // todo: switch espree to acorn
- if (node.type === 'MethodDefinition' && (node.computed || !node.key.name)) {
- let line = node.loc.start.line - 1;
- for (let comment of this._ast.comments || []) {
- if (comment.loc.end.line === line) {
- comments = [comment];
- break;
- }
- }
- }
-
if (comments && comments.length) {
let temp = [];
for (let comment of comments) {
@@ -339,7 +326,7 @@ export default class DocFactory {
}
if (comments.length === 0) {
- comments = [{type: 'Block', value: '* @_undocument'}];
+ comments = [{type: 'CommentBlock', value: '* @_undocument'}];
}
let results = [];
@@ -427,7 +414,7 @@ export default class DocFactory {
switch (node.type) {
case 'ClassDeclaration':
return this._decideClassDeclarationType(node);
- case 'MethodDefinition':
+ case 'ClassMethod': // for babylon
return this._decideMethodDefinitionType(node);
case 'ExpressionStatement':
return this._decideExpressionStatementType(node);
@@ -449,7 +436,7 @@ export default class DocFactory {
* @private
*/
_decideClassDeclarationType(node) {
- if (!this._isTopDepthInBody(node, this._ast.body)) return {type: null, node: null};
+ if (!this._isTopDepthInBody(node, this._ast.program.body)) return {type: null, node: null};
return {type: 'Class', node: node};
}
@@ -477,7 +464,7 @@ export default class DocFactory {
* @private
*/
_decideFunctionDeclarationType(node) {
- if (!this._isTopDepthInBody(node, this._ast.body)) return {type: null, node: null};
+ if (!this._isTopDepthInBody(node, this._ast.program.body)) return {type: null, node: null};
return {type: 'Function', node: node};
}
@@ -489,7 +476,7 @@ export default class DocFactory {
* @private
*/
_decideExpressionStatementType(node) {
- let isTop = this._isTopDepthInBody(node, this._ast.body);
+ let isTop = this._isTopDepthInBody(node, this._ast.program.body);
Object.defineProperty(node.expression, 'parent', {value: node});
node = node.expression;
node[already] = true;
@@ -542,7 +529,7 @@ export default class DocFactory {
* @private
*/
_decideVariableType(node) {
- if (!this._isTopDepthInBody(node, this._ast.body)) return {type: null, node: null};
+ if (!this._isTopDepthInBody(node, this._ast.program.body)) return {type: null, node: null};
let innerType = null;
let innerNode = null;
@@ -575,7 +562,7 @@ export default class DocFactory {
* @private
*/
_decideAssignmentType(node) {
- if (!this._isTopDepthInBody(node, this._ast.body)) return {type: null, node: null};
+ if (!this._isTopDepthInBody(node, this._ast.program.body)) return {type: null, node: null};
let innerType;
let innerNode;
@@ -12,7 +12,7 @@ export default class CommentParser {
* parse comment to tags.
* @param {ASTNode} commentNode - comment node.
* @param {string} commentNode.value - comment body.
- * @param {string} commentNode.type - Block or Line.
+ * @param {string} commentNode.type - CommentBlock or CommentLine.
* @returns {Tag[]} parsed comment.
*/
static parse(commentNode) {
@@ -59,7 +59,7 @@ export default class CommentParser {
* @returns {boolean} if true, this comment node is doc comment.
*/
static isESDoc(commentNode) {
- if (commentNode.type !== 'Block') return false;
+ if (commentNode.type !== 'CommentBlock') return false;
return commentNode.value.charAt(0) === '*';
}
}
View
@@ -1,7 +1,7 @@
import fs from 'fs-extra';
-import path from 'path';
import espree from 'espree';
import Plugin from '../Plugin/Plugin.js';
+import * as babylon from 'babylon';
/**
* ECMAScript Parser class.
@@ -16,6 +16,11 @@ export default class ESParser {
* @returns {AST} AST of source code.
*/
static parse(filePath) {
+ return this.parseWithBabylon(filePath);
+ // return this.parseWithEspree(filePath);
+ }
+
+ static parseWithEspree(filePath) {
let code = fs.readFileSync(filePath, {encode: 'utf8'}).toString();
code = Plugin.onHandleCode(code, filePath);
@@ -66,4 +71,27 @@ export default class ESParser {
return ast;
}
+
+ static parseWithBabylon(filePath) {
+ let code = fs.readFileSync(filePath, {encode: 'utf8'}).toString();
+ code = Plugin.onHandleCode(code, filePath);
+ if (code.charAt(0) === '#') code = code.replace(/^#!/, '//');
+
+ const option = {
+ sourceType: 'module',
+ plugins: ['jsx']
+ };
+
+ let parser = (code) => {
+ return babylon.parse(code, option);
+ };
+
+ parser = Plugin.onHandleCodeParser(parser, option, filePath, code);
+
+ let ast = parser(code);
+
+ ast = Plugin.onHandleAST(ast, filePath, code);
+
+ return ast;
+ }
}
@@ -117,7 +117,7 @@ export default class ParamParser {
else {
result.types = [''];
}
-
+
if (result.types.some(t => !t)) {
throw new Error(`Empty Type found name=${paramName} desc=${paramDesc}`);
}
@@ -185,7 +185,7 @@ export default class ParamParser {
result.optional = true;
- if (param.right.type === 'Literal') {
+ if (param.right.type.includes('Literal')) {
// e.g. func(a = 10){}
result.types = param.right.value === null ? ['*'] : [typeof param.right.value];
result.defaultRaw = param.right.value;
@@ -274,7 +274,8 @@ export default class ParamParser {
if (!node.argument) return;
- switch (node.argument.type) {
+ const type = node.argument.type.includes('Literal') ? 'Literal' : node.argument.type;
+ switch (type) {
case 'Literal':
if (node.argument.value === null) {
result.types = result.types || ['*'];
@@ -304,7 +305,7 @@ export default class ParamParser {
* @returns {ParsedParam}
*/
static guessType(right) {
- let value = right && right.type === 'Literal' ? right.value : null;
+ let value = right && right.type.includes('Literal') ? right.value : null;
if (value === null || value === undefined) {
return {types: ['*']};
@@ -46,8 +46,8 @@ export default class LintDocBuilder extends DocBuilder {
case 'FunctionDeclaration':
params = node.params || [];
break;
- case 'MethodDefinition':
- params = node.value.params || [];
+ case 'ClassMethod':
+ params = node.params || [];
break;
default:
throw new Error(`unknown node type. type = ${node.type}`);
Oops, something went wrong.

0 comments on commit 8130a3f

Please sign in to comment.