diff --git a/lib/jsdoc/src/astbuilder.js b/lib/jsdoc/src/astbuilder.js index e8fb9232..48a8251f 100644 --- a/lib/jsdoc/src/astbuilder.js +++ b/lib/jsdoc/src/astbuilder.js @@ -53,7 +53,8 @@ var acceptsLeadingComments = (function() { return accepts; })(); -var espreeOpts = { +// exported so we can use them in tests +var parserOptions = exports.parserOptions = { comment: true, loc: true, range: true, @@ -152,7 +153,7 @@ function parse(source, filename) { var ast; try { - ast = espree.parse(source, espreeOpts); + ast = espree.parse(source, parserOptions); } catch (e) { jsdoc.util.logger.error('Unable to parse %s: %s', filename, e.message); diff --git a/test/specs/jsdoc/src/astnode.js b/test/specs/jsdoc/src/astnode.js index b22fc279..a270cd25 100644 --- a/test/specs/jsdoc/src/astnode.js +++ b/test/specs/jsdoc/src/astnode.js @@ -1,77 +1,79 @@ 'use strict'; -describe('jsdoc/src/astnode', function() { - var astnode = require('jsdoc/src/astnode'); +describe('jsdoc/src/astNode', function() { + var astBuilder = require('jsdoc/src/astbuilder'); + var astNode = require('jsdoc/src/astnode'); var doop = require('jsdoc/util/doop'); var env = require('jsdoc/env'); var espree = require('espree'); var Syntax = require('jsdoc/src/syntax').Syntax; + function parse(str) { + return espree.parse(str, astBuilder.parserOptions); + } + // create the AST nodes we'll be testing - var arrayExpression = espree.parse('[,]').body[0].expression; - var assignmentExpression = espree.parse('foo = 1;').body[0].expression; - var binaryExpression = espree.parse('foo & foo;').body[0].expression; - var functionDeclaration1 = espree.parse('function foo() {}').body[0]; - var functionDeclaration1a = espree.parse('function bar() {}').body[0]; - var functionDeclaration2 = espree.parse('function foo(bar) {}').body[0]; - var functionDeclaration3 = espree.parse('function foo(bar, baz, qux) {}').body[0]; - var functionExpression1 = espree.parse('var foo = function() {};').body[0].declarations[0] - .init; - var functionExpression2 = espree.parse('var foo = function(bar) {};').body[0].declarations[0] - .init; - var identifier = espree.parse('foo;').body[0].expression; - var literal = espree.parse('1;').body[0].expression; - var memberExpression = espree.parse('foo.bar;').body[0].expression; - var memberExpressionComputed1 = espree.parse('foo["bar"];').body[0].expression; - var memberExpressionComputed2 = espree.parse('foo[\'bar\'];').body[0].expression; - var propertyGet = espree.parse('var foo = { get bar() {} };').body[0].declarations[0].init + var arrayExpression = parse('[,]').body[0].expression; + var assignmentExpression = parse('foo = 1;').body[0].expression; + var binaryExpression = parse('foo & foo;').body[0].expression; + var functionDeclaration1 = parse('function foo() {}').body[0]; + var functionDeclaration1a = parse('function bar() {}').body[0]; + var functionDeclaration2 = parse('function foo(bar) {}').body[0]; + var functionDeclaration3 = parse('function foo(bar, baz, qux) {}').body[0]; + var functionExpression1 = parse('var foo = function() {};').body[0].declarations[0].init; + var functionExpression2 = parse('var foo = function(bar) {};').body[0].declarations[0].init; + var identifier = parse('foo;').body[0].expression; + var literal = parse('1;').body[0].expression; + var memberExpression = parse('foo.bar;').body[0].expression; + var memberExpressionComputed1 = parse('foo["bar"];').body[0].expression; + var memberExpressionComputed2 = parse('foo[\'bar\'];').body[0].expression; + var propertyGet = parse('var foo = { get bar() {} };').body[0].declarations[0].init .properties[0]; - var propertyInit = espree.parse('var foo = { bar: {} };').body[0].declarations[0].init + var propertyInit = parse('var foo = { bar: {} };').body[0].declarations[0].init.properties[0]; + var propertySet = parse('var foo = { set bar(a) {} };').body[0].declarations[0].init .properties[0]; - var propertySet = espree.parse('var foo = { set bar(a) {} };').body[0].declarations[0].init - .properties[0]; - var thisExpression = espree.parse('this;').body[0].expression; - var unaryExpression1 = espree.parse('+1;').body[0].expression; - var unaryExpression2 = espree.parse('+foo;').body[0].expression; - var variableDeclaration1 = espree.parse('var foo = 1;').body[0]; - var variableDeclaration2 = espree.parse('var foo = 1, bar = 2;').body[0]; - var variableDeclarator1 = espree.parse('var foo = 1;').body[0].declarations[0]; - var variableDeclarator2 = espree.parse('var foo;').body[0].declarations[0]; + var thisExpression = parse('this;').body[0].expression; + var unaryExpression1 = parse('+1;').body[0].expression; + var unaryExpression2 = parse('+foo;').body[0].expression; + var variableDeclaration1 = parse('var foo = 1;').body[0]; + var variableDeclaration2 = parse('var foo = 1, bar = 2;').body[0]; + var variableDeclarator1 = parse('var foo = 1;').body[0].declarations[0]; + var variableDeclarator2 = parse('var foo;').body[0].declarations[0]; it('should exist', function() { - expect(typeof astnode).toBe('object'); + expect(typeof astNode).toBe('object'); }); it('should export an addNodeProperties method', function() { - expect(typeof astnode.addNodeProperties).toBe('function'); + expect(typeof astNode.addNodeProperties).toBe('function'); }); it('should export a getInfo method', function() { - expect(typeof astnode.getInfo).toBe('function'); + expect(typeof astNode.getInfo).toBe('function'); }); it('should export a getParamNames method', function() { - expect(typeof astnode.getParamNames).toBe('function'); + expect(typeof astNode.getParamNames).toBe('function'); }); it('should export an isAccessor method', function() { - expect(typeof astnode.isAccessor).toBe('function'); + expect(typeof astNode.isAccessor).toBe('function'); }); it('should export an isAssignment method', function() { - expect(typeof astnode.isAssignment).toBe('function'); + expect(typeof astNode.isAssignment).toBe('function'); }); it('should export an isScope method', function() { - expect(typeof astnode.isScope).toBe('function'); + expect(typeof astNode.isScope).toBe('function'); }); it('should export a nodeToString method', function() { - expect(typeof astnode.nodeToString).toBe('function'); + expect(typeof astNode.nodeToString).toBe('function'); }); it('should export a nodeToValue method', function() { - expect(typeof astnode.nodeToValue).toBe('function'); + expect(typeof astNode.nodeToValue).toBe('function'); }); describe('addNodeProperties', function() { @@ -86,22 +88,22 @@ describe('jsdoc/src/astnode', function() { }); it('should return null for undefined input', function() { - expect( astnode.addNodeProperties() ).toBe(null); + expect( astNode.addNodeProperties() ).toBe(null); }); it('should return null if the input is not an object', function() { - expect( astnode.addNodeProperties('foo') ).toBe(null); + expect( astNode.addNodeProperties('foo') ).toBe(null); }); it('should preserve existing properties that are not "node properties"', function() { - var node = astnode.addNodeProperties({foo: 1}); + var node = astNode.addNodeProperties({foo: 1}); expect(typeof node).toBe('object'); expect(node.foo).toBe(1); }); it('should add a non-enumerable nodeId if necessary', function() { - var node = astnode.addNodeProperties({}); + var node = astNode.addNodeProperties({}); var descriptor = Object.getOwnPropertyDescriptor(node, 'nodeId'); expect(descriptor).toBeDefined(); @@ -111,7 +113,7 @@ describe('jsdoc/src/astnode', function() { it('should not overwrite an existing nodeId', function() { var nodeId = 'foo'; - var node = astnode.addNodeProperties({nodeId: nodeId}); + var node = astNode.addNodeProperties({nodeId: nodeId}); expect(node.nodeId).toBe(nodeId); }); @@ -121,14 +123,14 @@ describe('jsdoc/src/astnode', function() { var node; env.opts.debug = true; - node = astnode.addNodeProperties({}); + node = astNode.addNodeProperties({}); descriptor = Object.getOwnPropertyDescriptor(node, 'nodeId'); expect(descriptor.enumerable).toBe(true); }); it('should add a non-enumerable, writable parent if necessary', function() { - var node = astnode.addNodeProperties({}); + var node = astNode.addNodeProperties({}); var descriptor = Object.getOwnPropertyDescriptor(node, 'parent'); expect(descriptor).toBeDefined(); @@ -139,13 +141,13 @@ describe('jsdoc/src/astnode', function() { it('should not overwrite an existing parent', function() { var parent = {}; - var node = astnode.addNodeProperties({parent: parent}); + var node = astNode.addNodeProperties({parent: parent}); expect(node.parent).toBe(parent); }); it('should not overwrite a null parent', function() { - var node = astnode.addNodeProperties({parent: null}); + var node = astNode.addNodeProperties({parent: null}); expect(node.parent).toBe(null); }); @@ -155,7 +157,7 @@ describe('jsdoc/src/astnode', function() { var node; env.opts.debug = true; - node = astnode.addNodeProperties({}); + node = astNode.addNodeProperties({}); descriptor = Object.getOwnPropertyDescriptor(node, 'parentId'); expect(descriptor).toBeDefined(); @@ -167,7 +169,7 @@ describe('jsdoc/src/astnode', function() { var node; env.opts.debug = true; - node = astnode.addNodeProperties({}); + node = astNode.addNodeProperties({}); expect(node.parentId).toBe(null); }); @@ -178,15 +180,15 @@ describe('jsdoc/src/astnode', function() { var parent; env.opts.debug = true; - node = astnode.addNodeProperties({}); - parent = astnode.addNodeProperties({}); + node = astNode.addNodeProperties({}); + parent = astNode.addNodeProperties({}); node.parent = parent; expect(node.parentId).toBe(parent.nodeId); }); it('should add a non-enumerable, writable enclosingScope if necessary', function() { - var node = astnode.addNodeProperties({}); + var node = astNode.addNodeProperties({}); var descriptor = Object.getOwnPropertyDescriptor(node, 'enclosingScope'); expect(descriptor).toBeDefined(); @@ -197,13 +199,13 @@ describe('jsdoc/src/astnode', function() { it('should not overwrite an existing enclosingScope', function() { var enclosingScope = {}; - var node = astnode.addNodeProperties({enclosingScope: enclosingScope}); + var node = astNode.addNodeProperties({enclosingScope: enclosingScope}); expect(node.enclosingScope).toBe(enclosingScope); }); it('should not overwrite a null enclosingScope', function() { - var node = astnode.addNodeProperties({enclosingScope: null}); + var node = astNode.addNodeProperties({enclosingScope: null}); expect(node.enclosingScope).toBe(null); }); @@ -213,7 +215,7 @@ describe('jsdoc/src/astnode', function() { var node; env.opts.debug = true; - node = astnode.addNodeProperties({}); + node = astNode.addNodeProperties({}); descriptor = Object.getOwnPropertyDescriptor(node, 'enclosingScopeId'); expect(descriptor).toBeDefined(); @@ -226,7 +228,7 @@ describe('jsdoc/src/astnode', function() { var node; env.opts.debug = true; - node = astnode.addNodeProperties({}); + node = astNode.addNodeProperties({}); expect(node.enclosingScopeId).toBe(null); }); @@ -238,8 +240,8 @@ describe('jsdoc/src/astnode', function() { var node; env.opts.debug = true; - node = astnode.addNodeProperties({}); - enclosingScope = astnode.addNodeProperties({}); + node = astNode.addNodeProperties({}); + enclosingScope = astNode.addNodeProperties({}); node.enclosingScope = enclosingScope; expect(node.enclosingScopeId).toBe(enclosingScope.nodeId); @@ -249,14 +251,14 @@ describe('jsdoc/src/astnode', function() { describe('getInfo', function() { it('should throw an error for undefined input', function() { function noNode() { - astnode.getInfo(); + astNode.getInfo(); } expect(noNode).toThrow(); }); it('should return the correct info for an AssignmentExpression', function() { - var info = astnode.getInfo(assignmentExpression); + var info = astNode.getInfo(assignmentExpression); expect(info).toBeDefined(); @@ -270,7 +272,7 @@ describe('jsdoc/src/astnode', function() { }); it('should return the correct info for a FunctionDeclaration', function() { - var info = astnode.getInfo(functionDeclaration2); + var info = astNode.getInfo(functionDeclaration2); expect(info).toBeDefined(); @@ -286,7 +288,7 @@ describe('jsdoc/src/astnode', function() { }); it('should return the correct info for a FunctionExpression', function() { - var info = astnode.getInfo(functionExpression2); + var info = astNode.getInfo(functionExpression2); expect(info).toBeDefined(); @@ -302,7 +304,7 @@ describe('jsdoc/src/astnode', function() { }); it('should return the correct info for a MemberExpression', function() { - var info = astnode.getInfo(memberExpression); + var info = astNode.getInfo(memberExpression); expect(info).toBeDefined(); @@ -314,7 +316,7 @@ describe('jsdoc/src/astnode', function() { }); it('should return the correct info for a computed MemberExpression', function() { - var info = astnode.getInfo(memberExpressionComputed1); + var info = astNode.getInfo(memberExpressionComputed1); expect(info).toBeDefined(); @@ -326,7 +328,7 @@ describe('jsdoc/src/astnode', function() { }); it('should return the correct info for a Property initializer', function() { - var info = astnode.getInfo(propertyInit); + var info = astNode.getInfo(propertyInit); expect(info).toBeDefined(); @@ -338,7 +340,7 @@ describe('jsdoc/src/astnode', function() { }); it('should return the correct info for a Property setter', function() { - var info = astnode.getInfo(propertySet); + var info = astNode.getInfo(propertySet); expect(info).toBeDefined(); @@ -354,7 +356,7 @@ describe('jsdoc/src/astnode', function() { }); it('should return the correct info for a VariableDeclarator with a value', function() { - var info = astnode.getInfo(variableDeclarator1); + var info = astNode.getInfo(variableDeclarator1); expect(info).toBeDefined(); @@ -367,7 +369,7 @@ describe('jsdoc/src/astnode', function() { }); it('should return the correct info for a VariableDeclarator with no value', function() { - var info = astnode.getInfo(variableDeclarator2); + var info = astNode.getInfo(variableDeclarator2); expect(info).toBeDefined(); @@ -380,7 +382,7 @@ describe('jsdoc/src/astnode', function() { }); it('should return the correct info for other node types', function() { - var info = astnode.getInfo(binaryExpression); + var info = astNode.getInfo(binaryExpression); expect(info).toBeDefined(); @@ -391,28 +393,28 @@ describe('jsdoc/src/astnode', function() { describe('getParamNames', function() { it('should return an empty array for undefined input', function() { - var params = astnode.getParamNames(); + var params = astNode.getParamNames(); expect( Array.isArray(params) ).toBe(true); expect(params.length).toBe(0); }); it('should return an empty array if the input has no params property', function() { - var params = astnode.getParamNames({}); + var params = astNode.getParamNames({}); expect( Array.isArray(params) ).toBe(true); expect(params.length).toBe(0); }); it('should return an empty array if the input has no params', function() { - var params = astnode.getParamNames(functionDeclaration1); + var params = astNode.getParamNames(functionDeclaration1); expect( Array.isArray(params) ).toBe(true); expect(params.length).toBe(0); }); it('should return a single-item array if the input has a single param', function() { - var params = astnode.getParamNames(functionDeclaration2); + var params = astNode.getParamNames(functionDeclaration2); expect( Array.isArray(params) ).toBe(true); expect(params.length).toBe(1); @@ -420,7 +422,7 @@ describe('jsdoc/src/astnode', function() { }); it('should return a multi-item array if the input has multiple params', function() { - var params = astnode.getParamNames(functionDeclaration3); + var params = astNode.getParamNames(functionDeclaration3); expect( Array.isArray(params) ).toBe(true); expect(params.length).toBe(3); @@ -432,149 +434,149 @@ describe('jsdoc/src/astnode', function() { describe('isAccessor', function() { it('should return false for undefined values', function() { - expect( astnode.isAccessor() ).toBe(false); + expect( astNode.isAccessor() ).toBe(false); }); it('should return false if the parameter is not an object', function() { - expect( astnode.isAccessor('foo') ).toBe(false); + expect( astNode.isAccessor('foo') ).toBe(false); }); it('should return false for non-Property nodes', function() { - expect( astnode.isAccessor(binaryExpression) ).toBe(false); + expect( astNode.isAccessor(binaryExpression) ).toBe(false); }); it('should return false for Property nodes whose kind is "init"', function() { - expect( astnode.isAccessor(propertyInit) ).toBe(false); + expect( astNode.isAccessor(propertyInit) ).toBe(false); }); it('should return true for Property nodes whose kind is "get"', function() { - expect( astnode.isAccessor(propertyGet) ).toBe(true); + expect( astNode.isAccessor(propertyGet) ).toBe(true); }); it('should return true for Property nodes whose kind is "set"', function() { - expect( astnode.isAccessor(propertySet) ).toBe(true); + expect( astNode.isAccessor(propertySet) ).toBe(true); }); }); describe('isAssignment', function() { it('should return false for undefined values', function() { - expect( astnode.isAssignment() ).toBe(false); + expect( astNode.isAssignment() ).toBe(false); }); it('should return false if the parameter is not an object', function() { - expect( astnode.isAssignment('foo') ).toBe(false); + expect( astNode.isAssignment('foo') ).toBe(false); }); it('should return false for nodes that are not assignments', function() { - expect( astnode.isAssignment(binaryExpression) ).toBe(false); + expect( astNode.isAssignment(binaryExpression) ).toBe(false); }); it('should return true for AssignmentExpression nodes', function() { - expect( astnode.isAssignment(assignmentExpression) ).toBe(true); + expect( astNode.isAssignment(assignmentExpression) ).toBe(true); }); it('should return true for VariableDeclarator nodes', function() { - expect( astnode.isAssignment(variableDeclarator1) ).toBe(true); + expect( astNode.isAssignment(variableDeclarator1) ).toBe(true); }); }); describe('isScope', function() { it('should return false for undefined values', function() { - expect( astnode.isScope() ).toBe(false); + expect( astNode.isScope() ).toBe(false); }); it('should return false if the parameter is not an object', function() { - expect( astnode.isScope('foo') ).toBe(false); + expect( astNode.isScope('foo') ).toBe(false); }); it('should return true for CatchClause nodes', function() { - expect( astnode.isScope({type: Syntax.CatchClause}) ).toBe(true); + expect( astNode.isScope({type: Syntax.CatchClause}) ).toBe(true); }); it('should return true for FunctionDeclaration nodes', function() { - expect( astnode.isScope({type: Syntax.FunctionDeclaration}) ).toBe(true); + expect( astNode.isScope({type: Syntax.FunctionDeclaration}) ).toBe(true); }); it('should return true for FunctionExpression nodes', function() { - expect( astnode.isScope({type: Syntax.FunctionExpression}) ).toBe(true); + expect( astNode.isScope({type: Syntax.FunctionExpression}) ).toBe(true); }); it('should return false for other nodes', function() { - expect( astnode.isScope({type: Syntax.NameExpression}) ).toBe(false); + expect( astNode.isScope({type: Syntax.NameExpression}) ).toBe(false); }); }); describe('nodeToString', function() { it('should be an alias to nodeToValue', function() { - expect(astnode.nodeToString).toBe(astnode.nodeToValue); + expect(astNode.nodeToString).toBe(astNode.nodeToValue); }); }); describe('nodeToValue', function() { it('should return `[null]` for the sparse array `[,]`', function() { - expect( astnode.nodeToValue(arrayExpression) ).toBe('[null]'); + expect( astNode.nodeToValue(arrayExpression) ).toBe('[null]'); }); it('should return the variable name for assignment expressions', function() { - expect( astnode.nodeToValue(assignmentExpression) ).toBe('foo'); + expect( astNode.nodeToValue(assignmentExpression) ).toBe('foo'); }); it('should return "function" for function declarations', function() { - expect( astnode.nodeToValue(functionDeclaration1) ).toBe('function'); + expect( astNode.nodeToValue(functionDeclaration1) ).toBe('function'); }); it('should return "function" for function expressions', function() { - expect( astnode.nodeToValue(functionExpression1) ).toBe('function'); + expect( astNode.nodeToValue(functionExpression1) ).toBe('function'); }); it('should return the identifier name for identifiers', function() { - expect( astnode.nodeToValue(identifier) ).toBe('foo'); + expect( astNode.nodeToValue(identifier) ).toBe('foo'); }); it('should return the literal value for literals', function() { - expect( astnode.nodeToValue(literal) ).toBe(1); + expect( astNode.nodeToValue(literal) ).toBe(1); }); it('should return the object and property for noncomputed member expressions', function() { - expect( astnode.nodeToValue(memberExpression) ).toBe('foo.bar'); + expect( astNode.nodeToValue(memberExpression) ).toBe('foo.bar'); }); it('should return the object and property, with a computed property that uses the same ' + 'quote character as the original source, for computed member expressions', function() { - expect( astnode.nodeToValue(memberExpressionComputed1) ).toBe('foo["bar"]'); - expect( astnode.nodeToValue(memberExpressionComputed2) ).toBe('foo[\'bar\']'); + expect( astNode.nodeToValue(memberExpressionComputed1) ).toBe('foo["bar"]'); + expect( astNode.nodeToValue(memberExpressionComputed2) ).toBe('foo[\'bar\']'); }); it('should return "this" for this expressions', function() { - expect( astnode.nodeToValue(thisExpression) ).toBe('this'); + expect( astNode.nodeToValue(thisExpression) ).toBe('this'); }); it('should return the operator and nodeToValue value for prefix unary expressions', function() { - expect( astnode.nodeToValue(unaryExpression1) ).toBe('+1'); - expect( astnode.nodeToValue(unaryExpression2) ).toBe('+foo'); + expect( astNode.nodeToValue(unaryExpression1) ).toBe('+1'); + expect( astNode.nodeToValue(unaryExpression2) ).toBe('+foo'); }); it('should throw an error for postfix unary expressions', function() { function postfixNodeToValue() { // there's no valid source representation for this one, so we fake it var unaryExpressionPostfix = (function() { - var node = espree.parse('+1;').body[0].expression; + var node = parse('+1;').body[0].expression; node.prefix = false; return node; })(); - return astnode.nodeToValue(unaryExpressionPostfix); + return astNode.nodeToValue(unaryExpressionPostfix); } expect(postfixNodeToValue).toThrow(); }); it('should return the variable name for variable declarators', function() { - expect( astnode.nodeToValue(variableDeclarator1) ).toBe('foo'); + expect( astNode.nodeToValue(variableDeclarator1) ).toBe('foo'); }); it('should return an empty string for all other nodes', function() { - expect( astnode.nodeToValue(binaryExpression) ).toBe(''); + expect( astNode.nodeToValue(binaryExpression) ).toBe(''); }); }); });