mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
walk children of ES6 nodes (#555)
For now, the node visitor discards these and logs a warning.
This commit is contained in:
parent
f454e8ad35
commit
62406412b6
@ -4,12 +4,16 @@
|
||||
exports.Syntax = {
|
||||
ArrayExpression: 'ArrayExpression',
|
||||
ArrayPattern: 'ArrayPattern',
|
||||
ArrowFunctionExpression: 'ArrowFunctionExpression',
|
||||
AssignmentExpression: 'AssignmentExpression',
|
||||
BinaryExpression: 'BinaryExpression',
|
||||
BlockStatement: 'BlockStatement',
|
||||
BreakStatement: 'BreakStatement',
|
||||
CallExpression: 'CallExpression',
|
||||
CatchClause: 'CatchClause',
|
||||
ClassBody: 'ClassBody',
|
||||
ClassDeclaration: 'ClassDeclaration',
|
||||
ClassExpression: 'ClassExpression',
|
||||
ComprehensionBlock: 'ComprehensionBlock',
|
||||
ComprehensionExpression: 'ComprehensionExpression',
|
||||
ConditionalExpression: 'ConditionalExpression',
|
||||
@ -17,6 +21,9 @@ exports.Syntax = {
|
||||
DebuggerStatement: 'DebuggerStatement',
|
||||
DoWhileStatement: 'DoWhileStatement',
|
||||
EmptyStatement: 'EmptyStatement',
|
||||
ExportBatchSpecifier: 'ExportBatchSpecifier',
|
||||
ExportDeclaration: 'ExportDeclaration',
|
||||
ExportSpecifier: 'ExportSpecifier',
|
||||
ExpressionStatement: 'ExpressionStatement',
|
||||
ForInStatement: 'ForInStatement',
|
||||
ForOfStatement: 'ForOfStatement',
|
||||
@ -25,11 +32,15 @@ exports.Syntax = {
|
||||
FunctionExpression: 'FunctionExpression',
|
||||
Identifier: 'Identifier',
|
||||
IfStatement: 'IfStatement',
|
||||
ImportDeclaration: 'ImportDeclaration',
|
||||
ImportSpecifier: 'ImportSpecifier',
|
||||
LabeledStatement: 'LabeledStatement',
|
||||
LetStatement: 'LetStatement',
|
||||
LetStatement: 'LetStatement', // TODO: update Rhino to use VariableDeclaration
|
||||
Literal: 'Literal',
|
||||
LogicalExpression: 'LogicalExpression',
|
||||
MemberExpression: 'MemberExpression',
|
||||
MethodDefinition: 'MethodDefinition',
|
||||
ModuleDeclaration: 'ModuleDeclaration',
|
||||
NewExpression: 'NewExpression',
|
||||
ObjectExpression: 'ObjectExpression',
|
||||
ObjectPattern: 'ObjectPattern',
|
||||
@ -37,8 +48,12 @@ exports.Syntax = {
|
||||
Property: 'Property',
|
||||
ReturnStatement: 'ReturnStatement',
|
||||
SequenceExpression: 'SequenceExpression',
|
||||
SpreadElement: 'SpreadElement',
|
||||
SwitchCase: 'SwitchCase',
|
||||
SwitchStatement: 'SwitchStatement',
|
||||
TaggedTemplateExpression: 'TaggedTemplateExpression',
|
||||
TemplateElement: 'TemplateElement',
|
||||
TemplateLiteral: 'TemplateLiteral',
|
||||
ThisExpression: 'ThisExpression',
|
||||
ThrowStatement: 'ThrowStatement',
|
||||
TryStatement: 'TryStatement',
|
||||
|
||||
@ -306,6 +306,8 @@ function trackVars(parser, node, e) {
|
||||
|
||||
// TODO: docs
|
||||
Visitor.prototype.makeSymbolFoundEvent = function(node, parser, filename) {
|
||||
var logger = require('jsdoc/util/logger');
|
||||
|
||||
var e;
|
||||
var basename;
|
||||
var i;
|
||||
@ -394,6 +396,27 @@ Visitor.prototype.makeSymbolFoundEvent = function(node, parser, filename) {
|
||||
|
||||
break;
|
||||
|
||||
// for now, log a warning for all ES6 nodes, since we don't do anything useful with them
|
||||
case Syntax.ArrowFunctionExpression:
|
||||
case Syntax.ClassBody:
|
||||
case Syntax.ClassDeclaration:
|
||||
case Syntax.ClassExpression:
|
||||
case Syntax.ExportBatchSpecifier:
|
||||
case Syntax.ExportDeclaration:
|
||||
case Syntax.ExportSpecifier:
|
||||
case Syntax.ImportDeclaration:
|
||||
case Syntax.ImportSpecifier:
|
||||
case Syntax.MethodDefinition:
|
||||
case Syntax.ModuleDeclaration:
|
||||
case Syntax.SpreadElement:
|
||||
case Syntax.TaggedTemplateExpression:
|
||||
case Syntax.TemplateElement:
|
||||
case Syntax.TemplateLiteral:
|
||||
logger.warn('JSDoc does not currently handle %s nodes. Source file: %s, line %s',
|
||||
node.type, filename, (node.loc && node.loc.start) ? node.loc.start.line : '??');
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// ignore
|
||||
}
|
||||
|
||||
@ -39,13 +39,6 @@ function moveComments(source, target) {
|
||||
|
||||
function leafNode(node, parent, state, cb) {}
|
||||
|
||||
function unsupportedNode(node, parent, state, cb) {
|
||||
var logger = require('jsdoc/util/logger');
|
||||
|
||||
logger.warn('JSDoc does not currently handle nodes of type %s. Source file: %s', node.type,
|
||||
state.filename);
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
var walkers = exports.walkers = {};
|
||||
|
||||
@ -69,7 +62,30 @@ walkers[Syntax.ArrayPattern] = function arrayPattern(node, parent, state, cb) {
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.ArrowFunctionExpression] = unsupportedNode;
|
||||
walkers[Syntax.ArrowFunctionExpression] =
|
||||
function arrowFunctionExpression(node, parent, state, cb) {
|
||||
var i;
|
||||
var l;
|
||||
|
||||
// used for function declarations, so we include it here
|
||||
if (node.id) {
|
||||
cb(node.id, node, state);
|
||||
}
|
||||
|
||||
for (i = 0, l = node.params.length; i < l; i++) {
|
||||
cb(node.params[i], node, state);
|
||||
}
|
||||
|
||||
for (i = 0, l = node.defaults.length; i < l; i++) {
|
||||
cb(node.defaults[i], node, state);
|
||||
}
|
||||
|
||||
cb(node.body, node, state);
|
||||
|
||||
if (node.rest) {
|
||||
cb(node.rest, node, state);
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.AssignmentExpression] = function assignmentExpression(node, parent, state, cb) {
|
||||
cb(node.left, node, state);
|
||||
@ -103,13 +119,23 @@ walkers[Syntax.CallExpression] = function callExpression(node, parent, state, cb
|
||||
|
||||
walkers[Syntax.CatchClause] = leafNode;
|
||||
|
||||
walkers[Syntax.ClassBody] = unsupportedNode;
|
||||
walkers[Syntax.ClassBody] = walkers[Syntax.BlockStatement];
|
||||
|
||||
walkers[Syntax.ClassDeclaration] = unsupportedNode;
|
||||
walkers[Syntax.ClassDeclaration] = function classDeclaration(node, parent, state, cb) {
|
||||
if (node.id) {
|
||||
cb(node.id, node, state);
|
||||
}
|
||||
|
||||
walkers[Syntax.ClassExpression] = unsupportedNode;
|
||||
if (node.superClass) {
|
||||
cb(node.superClass, node, state);
|
||||
}
|
||||
|
||||
walkers[Syntax.ClassHeritage] = unsupportedNode;
|
||||
if (node.body) {
|
||||
cb(node.body, node, state);
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.ClassExpression] = walkers[Syntax.ClassDeclaration];
|
||||
|
||||
// TODO: verify correctness
|
||||
walkers[Syntax.ComprehensionBlock] = walkers[Syntax.AssignmentExpression];
|
||||
@ -145,11 +171,38 @@ walkers[Syntax.DoWhileStatement] = function doWhileStatement(node, parent, state
|
||||
|
||||
walkers[Syntax.EmptyStatement] = leafNode;
|
||||
|
||||
walkers[Syntax.ExportBatchSpecifier] = unsupportedNode;
|
||||
walkers[Syntax.ExportBatchSpecifier] = leafNode;
|
||||
|
||||
walkers[Syntax.ExportDeclaration] = unsupportedNode;
|
||||
walkers[Syntax.ExportDeclaration] = function exportDeclaration(node, parent, state, cb) {
|
||||
var i;
|
||||
var l;
|
||||
|
||||
walkers[Syntax.ExportSpecifier] = unsupportedNode;
|
||||
if (node.declaration) {
|
||||
for (i = 0, l = node.declaration.length; i < l; i++) {
|
||||
cb(node.declaration[i], node, state);
|
||||
}
|
||||
}
|
||||
|
||||
if (node.specifiers) {
|
||||
for (i = 0, l = node.specifiers.length; i < l; i++) {
|
||||
cb(node.specifiers[i], node, state);
|
||||
}
|
||||
}
|
||||
|
||||
if (node.source) {
|
||||
cb(node.source, node, state);
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.ExportSpecifier] = function exportSpecifier(node, parent, state, cb) {
|
||||
if (node.id) {
|
||||
cb(node.id, node, state);
|
||||
}
|
||||
|
||||
if (node.name) {
|
||||
cb(node.name, node, state);
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.ExpressionStatement] = function expressionStatement(node, parent, state, cb) {
|
||||
cb(node.expression, node, state);
|
||||
@ -179,27 +232,9 @@ walkers[Syntax.ForStatement] = function forStatement(node, parent, state, cb) {
|
||||
cb(node.body, node, state);
|
||||
};
|
||||
|
||||
walkers[Syntax.FunctionDeclaration] = function functionDeclaration(node, parent, state, cb) {
|
||||
var i;
|
||||
var l;
|
||||
walkers[Syntax.FunctionDeclaration] = walkers[Syntax.ArrowFunctionExpression];
|
||||
|
||||
// can be null for function expressions
|
||||
if (node.id) {
|
||||
cb(node.id, node, state);
|
||||
}
|
||||
|
||||
if (node.params && node.params.length) {
|
||||
for (i = 0, l = node.params.length; i < l; i++) {
|
||||
cb(node.params[i], node, state);
|
||||
}
|
||||
}
|
||||
|
||||
// ignore node.defaults and node.rest for now; always empty
|
||||
|
||||
cb(node.body, node, state);
|
||||
};
|
||||
|
||||
walkers[Syntax.FunctionExpression] = walkers[Syntax.FunctionDeclaration];
|
||||
walkers[Syntax.FunctionExpression] = walkers[Syntax.ArrowFunctionExpression];
|
||||
|
||||
walkers[Syntax.Identifier] = leafNode;
|
||||
|
||||
@ -211,9 +246,22 @@ walkers[Syntax.IfStatement] = function ifStatement(node, parent, state, cb) {
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.ImportDeclaration] = unsupportedNode;
|
||||
walkers[Syntax.ImportDeclaration] = function importDeclaration(node, parent, state, cb) {
|
||||
var i;
|
||||
var l;
|
||||
|
||||
walkers[Syntax.ImportSpecifier] = unsupportedNode;
|
||||
if (node.specifiers) {
|
||||
for (i = 0, l = node.specifiers.length; i < l; i++) {
|
||||
cb(node.specifiers[i], node, state);
|
||||
}
|
||||
}
|
||||
|
||||
if (node.source) {
|
||||
cb(node.source, node, state);
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.ImportSpecifier] = walkers[Syntax.ExportSpecifier];
|
||||
|
||||
walkers[Syntax.LabeledStatement] = function labeledStatement(node, parent, state, cb) {
|
||||
cb(node.body, node, state);
|
||||
@ -243,9 +291,29 @@ walkers[Syntax.MemberExpression] = function memberExpression(node, parent, state
|
||||
cb(node.object, node, state);
|
||||
};
|
||||
|
||||
walkers[Syntax.MethodDefinition] = unsupportedNode;
|
||||
walkers[Syntax.MethodDefinition] = function methodDefinition(node, parent, state, cb) {
|
||||
if (node.key) {
|
||||
cb(node.key, node, state);
|
||||
}
|
||||
|
||||
walkers[Syntax.ModuleDeclaration] = unsupportedNode;
|
||||
if (node.value) {
|
||||
cb(node.value, node, state);
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.ModuleDeclaration] = function moduleDeclaration(node, parent, state, cb) {
|
||||
if (node.id) {
|
||||
cb(node.id, node, state);
|
||||
}
|
||||
|
||||
if (node.source) {
|
||||
cb(node.source, node, state);
|
||||
}
|
||||
|
||||
if (node.body) {
|
||||
cb(node.body, node, state);
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.NewExpression] = walkers[Syntax.CallExpression];
|
||||
|
||||
@ -278,7 +346,11 @@ walkers[Syntax.SequenceExpression] = function sequenceExpression(node, parent, s
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.SpreadElement] = unsupportedNode;
|
||||
walkers[Syntax.SpreadElement] = function spreadElement(node, parent, state, cb) {
|
||||
if (node.argument) {
|
||||
cb(node.argument, node, state);
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.SwitchCase] = function switchCase(node, parent, state, cb) {
|
||||
if (node.test) {
|
||||
@ -298,11 +370,34 @@ walkers[Syntax.SwitchStatement] = function switchStatement(node, parent, state,
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.TaggedTemplateExpression] = unsupportedNode;
|
||||
walkers[Syntax.TaggedTemplateExpression] =
|
||||
function taggedTemplateExpression(node, parent, state, cb) {
|
||||
if (node.tag) {
|
||||
cb(node.tag, node, state);
|
||||
}
|
||||
if (node.quasi) {
|
||||
cb(node.quasi, node, state);
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.TemplateElement] = unsupportedNode;
|
||||
walkers[Syntax.TemplateElement] = leafNode;
|
||||
|
||||
walkers[Syntax.TemplateLiteral] = unsupportedNode;
|
||||
walkers[Syntax.TemplateLiteral] = function templateLiteral(node, parent, state, cb) {
|
||||
var i;
|
||||
var l;
|
||||
|
||||
if (node.quasis && node.quasis.length) {
|
||||
for (i = 0, l = node.quasis.length; i < l; i++) {
|
||||
cb(node.quasis[i], node, state);
|
||||
}
|
||||
}
|
||||
|
||||
if (node.expressions && node.expressions.length) {
|
||||
for (i = 0, l = node.expressions.length; i < l; i++) {
|
||||
cb(node.expressions[i], node, state);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
walkers[Syntax.ThisExpression] = leafNode;
|
||||
|
||||
|
||||
48
test/fixtures/es6.js
vendored
Normal file
48
test/fixtures/es6.js
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
// ArrowFunctionExpression
|
||||
["Model", "View", "Controller"].forEach(name => console.log(name));
|
||||
|
||||
// ClassBody, ClassDeclaration, MethodDefinition
|
||||
class Socket {
|
||||
constructor(port) {
|
||||
// ...
|
||||
}
|
||||
open() {
|
||||
// ...
|
||||
}
|
||||
close() {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
// ClassExpression
|
||||
var WebSocket = class extends Socket {
|
||||
// ...
|
||||
};
|
||||
|
||||
// ExportBatchSpecifier, ExportDeclaration
|
||||
export * from 'lib/network';
|
||||
|
||||
// ExportSpecifier
|
||||
export {Socket};
|
||||
|
||||
// ImportDeclaration, ImportSpecifier
|
||||
import {Packet} from 'lib/data';
|
||||
|
||||
// ModuleDeclaration
|
||||
module util from 'lib/util';
|
||||
|
||||
// SpreadElement
|
||||
function logItems(...items) {
|
||||
items.forEach(function(item) {
|
||||
console.log(item);
|
||||
});
|
||||
}
|
||||
logItems(...['hello', 'world!']);
|
||||
|
||||
// TaggedTemplateExpression
|
||||
console.log`hello world!`;
|
||||
|
||||
// TemplateElement, TemplateLiteral
|
||||
var piMessage = `pi equals ${Math.PI}`;
|
||||
@ -1,5 +1,4 @@
|
||||
/*global beforeEach: true, describe: true, env: true, expect: true, it: true, jasmine: true,
|
||||
spyOn: true, xit: true */
|
||||
/*global beforeEach, describe, expect, it, jasmine, spyOn, xit */
|
||||
describe("jsdoc/src/parser", function() {
|
||||
var jsdoc = { src: { parser: require('jsdoc/src/parser') } };
|
||||
|
||||
@ -247,10 +246,26 @@ describe("jsdoc/src/parser", function() {
|
||||
expect(spy.mostRecentCall.args[0].doclets).toBe(doclets);
|
||||
});
|
||||
|
||||
// Rhino can't parse ES6
|
||||
if (jasmine.jsParser !== 'rhino') {
|
||||
it("should not throw errors when parsing files with ES6 syntax", function() {
|
||||
function parse() {
|
||||
var fs = require('jsdoc/fs');
|
||||
var path = require('jsdoc/path');
|
||||
|
||||
var parserSrc = 'javascript:' + fs.readFileSync(
|
||||
path.join(global.env.dirname, 'test/fixtures/es6.js'), 'utf8' );
|
||||
parser.parse(parserSrc);
|
||||
}
|
||||
|
||||
expect(parse).not.toThrow();
|
||||
});
|
||||
}
|
||||
|
||||
it("should be able to parse its own source file", function() {
|
||||
var fs = require('jsdoc/fs'),
|
||||
path = require('path'),
|
||||
parserSrc = 'javascript:' + fs.readFileSync( path.join(env.dirname,
|
||||
parserSrc = 'javascript:' + fs.readFileSync( path.join(global.env.dirname,
|
||||
'lib/jsdoc/src/parser.js'), 'utf8' ),
|
||||
parse = function() {
|
||||
parser.parse(parserSrc);
|
||||
|
||||
@ -1,4 +1,23 @@
|
||||
/*global describe: true, env: true, expect: true, it: true, xdescribe: true */
|
||||
xdescribe('jsdoc/src/syntax', function() {
|
||||
// TODO
|
||||
/*global describe, expect, it */
|
||||
describe('jsdoc/src/syntax', function() {
|
||||
var Syntax = require('jsdoc/src/syntax').Syntax;
|
||||
|
||||
it('should exist', function() {
|
||||
expect(Syntax).toBeDefined();
|
||||
expect(typeof Syntax).toBe('object');
|
||||
});
|
||||
|
||||
it('should define all of the node types that are defined by Esprima', function() {
|
||||
var esprimaSyntax = require('esprima').Syntax;
|
||||
|
||||
Object.keys(esprimaSyntax).forEach(function(nodeType) {
|
||||
expect(Syntax[nodeType]).toBeDefined();
|
||||
expect(Syntax[nodeType]).toBe(esprimaSyntax[nodeType]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should define the LetStatement node type', function() {
|
||||
expect(Syntax.LetStatement).toBeDefined();
|
||||
expect(Syntax.LetStatement).toBe('LetStatement');
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,36 @@
|
||||
/*global describe: true, env: true, expect: true, it: true, xdescribe: true */
|
||||
xdescribe('jsdoc/src/walker', function() {
|
||||
// TODO
|
||||
/*global describe, expect, it, xdescribe */
|
||||
describe('jsdoc/src/walker', function() {
|
||||
var walker = require('jsdoc/src/walker');
|
||||
|
||||
it('should exist', function() {
|
||||
expect(walker).toBeDefined();
|
||||
expect(typeof walker).toBe('object');
|
||||
});
|
||||
|
||||
it('should export a "walkers" object', function() {
|
||||
expect(walker.walkers).toBeDefined();
|
||||
expect(typeof walker.walkers).toBe('object');
|
||||
});
|
||||
|
||||
it('should export a "Walker" class', function() {
|
||||
expect(walker.Walker).toBeDefined();
|
||||
expect(typeof walker.Walker).toBe('function');
|
||||
});
|
||||
|
||||
describe('walkers', function() {
|
||||
var Syntax = require('jsdoc/src/syntax').Syntax;
|
||||
|
||||
// TODO: tests for default functions
|
||||
|
||||
it('should contain a function for each known node type', function() {
|
||||
Object.keys(Syntax).forEach(function(nodeType) {
|
||||
expect(walker.walkers[nodeType]).toBeDefined();
|
||||
expect(typeof walker.walkers[nodeType]).toBe('function');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
xdescribe('Walker', function() {
|
||||
// TODO
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user