Skip to content

Commit

Permalink
walk children of ES6 nodes (jsdoc#555)
Browse files Browse the repository at this point in the history
For now, the node visitor discards these and logs a warning.
  • Loading branch information
hegemonic committed Apr 7, 2014
1 parent f454e8a commit 6240641
Show file tree
Hide file tree
Showing 7 changed files with 300 additions and 53 deletions.
17 changes: 16 additions & 1 deletion lib/jsdoc/src/syntax.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,26 @@
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',
ContinueStatement: 'ContinueStatement',
DebuggerStatement: 'DebuggerStatement',
DoWhileStatement: 'DoWhileStatement',
EmptyStatement: 'EmptyStatement',
ExportBatchSpecifier: 'ExportBatchSpecifier',
ExportDeclaration: 'ExportDeclaration',
ExportSpecifier: 'ExportSpecifier',
ExpressionStatement: 'ExpressionStatement',
ForInStatement: 'ForInStatement',
ForOfStatement: 'ForOfStatement',
Expand All @@ -25,20 +32,28 @@ 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',
Program: 'Program',
Property: 'Property',
ReturnStatement: 'ReturnStatement',
SequenceExpression: 'SequenceExpression',
SpreadElement: 'SpreadElement',
SwitchCase: 'SwitchCase',
SwitchStatement: 'SwitchStatement',
TaggedTemplateExpression: 'TaggedTemplateExpression',
TemplateElement: 'TemplateElement',
TemplateLiteral: 'TemplateLiteral',
ThisExpression: 'ThisExpression',
ThrowStatement: 'ThrowStatement',
TryStatement: 'TryStatement',
Expand Down
23 changes: 23 additions & 0 deletions lib/jsdoc/src/visitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
}
Expand Down
181 changes: 138 additions & 43 deletions lib/jsdoc/src/walker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {};

Expand All @@ -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);
Expand Down Expand Up @@ -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);
}

if (node.superClass) {
cb(node.superClass, node, state);
}

walkers[Syntax.ClassExpression] = unsupportedNode;
if (node.body) {
cb(node.body, node, state);
}
};

walkers[Syntax.ClassHeritage] = unsupportedNode;
walkers[Syntax.ClassExpression] = walkers[Syntax.ClassDeclaration];

// TODO: verify correctness
walkers[Syntax.ComprehensionBlock] = walkers[Syntax.AssignmentExpression];
Expand Down Expand Up @@ -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] = function exportDeclaration(node, parent, state, cb) {
var i;
var l;

if (node.declaration) {
for (i = 0, l = node.declaration.length; i < l; i++) {
cb(node.declaration[i], node, state);
}
}

walkers[Syntax.ExportDeclaration] = unsupportedNode;
if (node.specifiers) {
for (i = 0, l = node.specifiers.length; i < l; i++) {
cb(node.specifiers[i], node, state);
}
}

walkers[Syntax.ExportSpecifier] = unsupportedNode;
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);
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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];

Expand Down Expand Up @@ -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) {
Expand All @@ -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] = leafNode;

walkers[Syntax.TemplateElement] = unsupportedNode;
walkers[Syntax.TemplateLiteral] = function templateLiteral(node, parent, state, cb) {
var i;
var l;

walkers[Syntax.TemplateLiteral] = unsupportedNode;
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;

Expand Down
48 changes: 48 additions & 0 deletions test/fixtures/es6.js
Original file line number Diff line number Diff line change
@@ -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}`;
Loading

0 comments on commit 6240641

Please sign in to comment.