diff --git a/lib/jsdoc/src/astbuilder.js b/lib/jsdoc/src/astbuilder.js index b5aaf8ef..fc7a0edb 100644 --- a/lib/jsdoc/src/astbuilder.js +++ b/lib/jsdoc/src/astbuilder.js @@ -86,7 +86,7 @@ var parserOptions = exports.parserOptions = { forOf: true, generators: true, globalReturn: true, - jsx: false, + jsx: true, modules: true, newTarget: true, objectLiteralComputedProperties: true, diff --git a/lib/jsdoc/src/syntax.js b/lib/jsdoc/src/syntax.js index 942f6a18..5bf36ce6 100644 --- a/lib/jsdoc/src/syntax.js +++ b/lib/jsdoc/src/syntax.js @@ -40,6 +40,17 @@ exports.Syntax = { ImportDefaultSpecifier: 'ImportDefaultSpecifier', ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', ImportSpecifier: 'ImportSpecifier', + JSXAttribute: 'JSXAttribute', + JSXClosingElement: 'JSXClosingElement', + JSXElement: 'JSXElement', + JSXEmptyExpression: 'JSXEmptyExpression', + JSXExpressionContainer: 'JSXExpressionContainer', + JSXIdentifier: 'JSXIdentifier', + JSXMemberExpression: 'JSXMemberExpression', + JSXNamespacedName: 'JSXNamespacedName', + JSXOpeningElement: 'JSXOpeningElement', + JSXSpreadAttribute: 'JSXSpreadAttribute', + JSXText: 'JSXText', LabeledStatement: 'LabeledStatement', LetStatement: 'LetStatement', // TODO: update Rhino to use VariableDeclaration Literal: 'Literal', diff --git a/lib/jsdoc/src/walker.js b/lib/jsdoc/src/walker.js index 02c7febd..fbca5218 100644 --- a/lib/jsdoc/src/walker.js +++ b/lib/jsdoc/src/walker.js @@ -251,11 +251,8 @@ walkers[Syntax.IfStatement] = function(node, parent, state, cb) { }; walkers[Syntax.ImportDeclaration] = function(node, parent, state, cb) { - var i; - var l; - if (node.specifiers) { - for (i = 0, l = node.specifiers.length; i < l; i++) { + for (var i = 0, l = node.specifiers.length; i < l; i++) { cb(node.specifiers[i], node, state); } } @@ -275,6 +272,62 @@ walkers[Syntax.ImportNamespaceSpecifier] = walkers[Syntax.ImportDefaultSpecifier walkers[Syntax.ImportSpecifier] = walkers[Syntax.ExportSpecifier]; +walkers[Syntax.JSXAttribute] = function(node, parent, state, cb) { + cb(node.name, node, state); + + cb(node.value, node, state); +}; + +walkers[Syntax.JSXClosingElement] = function(node, parent, state, cb) { + cb(node.name, node, state); +}; + +walkers[Syntax.JSXElement] = function(node, parent, state, cb) { + cb(node.openingElement, node, state); + + if (node.closingElement) { + cb(node.closingElement, node, state); + } + + for (var i = 0, l = node.children.length; i < l; i++) { + cb(node.children[i], node, state); + } +}; + +walkers[Syntax.JSXEmptyExpression] = leafNode; + +walkers[Syntax.JSXExpressionContainer] = function(node, parent, state, cb) { + cb(node.expression, node, state); +}; + +walkers[Syntax.JSXIdentifier] = leafNode; + +walkers[Syntax.JSXMemberExpression] = function(node, parent, state, cb) { + cb(node.object, node, state); + + cb(node.property. node, state); +}; + +walkers[Syntax.JSXNamespacedName] = function(node, parent, state, cb) { + cb(node.namespace, node, state); + + cb(node.name, node, state); +}; + +walkers[Syntax.JSXOpeningElement] = function(node, parent, state, cb) { + cb(node.name, node, state); + + for (var i = 0, l = node.attributes.length; i < l; i++) { + cb(node.attributes[i], node, state); + } +}; + +walkers[Syntax.JSXSpreadAttribute] = function(node, parent, state, cb) { + cb(node.argument, node, state); +}; + +walkers[Syntax.JSXText] = leafNode; + walkers[Syntax.LabeledStatement] = function(node, parent, state, cb) { cb(node.body, node, state); }; diff --git a/test/fixtures/jsx.js b/test/fixtures/jsx.js new file mode 100644 index 00000000..5f8fd87f --- /dev/null +++ b/test/fixtures/jsx.js @@ -0,0 +1,2 @@ +var myDivElement =
; +React.render(myDivElement, document.getElementById('example')); diff --git a/test/specs/documentation/jsx.js b/test/specs/documentation/jsx.js new file mode 100644 index 00000000..bf04cc5d --- /dev/null +++ b/test/specs/documentation/jsx.js @@ -0,0 +1,17 @@ +'use strict'; + +if (jasmine.jsParser !== 'rhino') { + describe('JSX support', function() { + it('should parse JSX files without errors', function() { + var logger = require('jsdoc/util/logger'); + + function parseJsx() { + return jasmine.getDocSetFromFile('test/fixtures/jsx.js'); + } + + spyOn(logger, 'error'); + expect(parseJsx).not.toThrow(); + expect(logger.error).not.toHaveBeenCalled(); + }); + }); +} diff --git a/test/specs/jsdoc/src/syntax.js b/test/specs/jsdoc/src/syntax.js index 1896a263..ba83be19 100644 --- a/test/specs/jsdoc/src/syntax.js +++ b/test/specs/jsdoc/src/syntax.js @@ -8,14 +8,12 @@ describe('jsdoc/src/syntax', function() { expect(typeof Syntax).toBe('object'); }); - it('should define all of the non-JSX node types that are defined by Espree', function() { + it('should define all of the node types that are defined by Espree', function() { var espreeSyntax = require('espree').Syntax; Object.keys(espreeSyntax).forEach(function(nodeType) { - if (nodeType.indexOf('JSX') !== 0) { - expect(Syntax[nodeType]).toBeDefined(); - expect(Syntax[nodeType]).toBe(espreeSyntax[nodeType]); - } + expect(Syntax[nodeType]).toBeDefined(); + expect(Syntax[nodeType]).toBe(espreeSyntax[nodeType]); }); });