diff --git a/src/parser.js b/src/parser.js index 2bf9faf..2ad7cd4 100644 --- a/src/parser.js +++ b/src/parser.js @@ -223,6 +223,7 @@ Parser.prototype.parseTopStatement = function () { return this.parseAnnotation(); } // ignore it + this.token = this.lexer.lex(); return null; }; @@ -251,23 +252,17 @@ Parser.prototype.parseAnnotation = function () { if (this.token === '(') { // method annotation - do { - result = { - kind: 'annotation', - type: type, - arguments: [] - }; - this.token = this.lexer.lex(); - item = this.parseTopStatement(); - if (item !== null) { - result.arguments.push(item); - } - } while (this.token !== ')' && this.token !== this.lexer._t.T_EOF); + this.token = this.lexer.lex(); + result = { + kind: 'annotation', + name: type, + arguments: this.parseMethodArguments() + }; } else { // generic doc block result = { kind: 'block', - type: type, + name: type, options: [] }; while (line === this.lexer.line) { @@ -282,6 +277,36 @@ Parser.prototype.parseAnnotation = function () { return null; }; +/** + * Parse a list of arguments + */ +Parser.prototype.parseMethodArguments = function () { + var result = []; + var item; + do { + item = this.parseTopStatement(); + if (item !== null) { + if (this.token === '=' || this.token === '=>') { + // key value + this.token = this.lexer.lex(); + item = { + kind: 'key', + name: this.getJsonValue(item), + value: this.parseTopStatement() + }; + } + result.push(item); + } + if (this.token === ',') { + this.token = this.lexer.lex(); // read next argument + } + } while (this.token !== ')' && this.token !== this.lexer._t.T_EOF); + if (this.token === ')') { + this.token = this.lexer.lex(); + } + return result; +}; + /** * Parsing a rule */ @@ -601,19 +626,12 @@ Parser.prototype.parseStatement = function () { }; } else if (this.token === '(') { // method - var result = { + this.token = this.lexer.lex(); + return { kind: 'method', name: name, - arguments: [] + arguments: this.parseMethodArguments() }; - do { - this.token = this.lexer.lex(); - var item = this.parseTopStatement(); - if (item !== null) { - result.arguments.push(item); - } - } while (this.token !== ')' && this.token !== this.lexer._t.T_EOF); - return result; } return { kind: 'word', diff --git a/test/annotations.js b/test/annotations.js index e69de29..e483adf 100644 --- a/test/annotations.js +++ b/test/annotations.js @@ -0,0 +1,34 @@ +/*! + * Copyright (C) 2017 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/docblock-parser/graphs/contributors + * @url http://glayzzle.com/docblock-parser + */ + +// eslint-disable-next-line no-unused-vars +var should = require('should'); +var DocBlockParser = require('../src/index'); + +describe('Test annotations', function () { + var doc = new DocBlockParser(); + it('should parse', function () { + var ast = doc.parse([ + '/**', + ' * @foobar("arg", @bar("foo" => true))', + ' * bark(as => dog)', + ' */' + ].join('\r\n')); + ast.body[0].kind.should.be.exactly('annotation'); + ast.body[0].name.should.be.exactly('foobar'); + ast.body[0].arguments[0].kind.should.be.exactly('text'); + ast.body[0].arguments[1].kind.should.be.exactly('annotation'); + ast.body[0].arguments[1].arguments[0].kind.should.be.exactly('key'); + ast.body[0].arguments[1].arguments[0].name.should.be.exactly('foo'); + ast.body[0].arguments[1].arguments[0].value.kind.should.be.exactly('boolean'); + ast.body[0].arguments[1].arguments[0].value.value.should.be.exactly(true); + ast.body[1].kind.should.be.exactly('method'); + ast.body[1].name.should.be.exactly('bark'); + ast.body[1].arguments[0].kind.should.be.exactly('key'); + ast.body[1].arguments[0].name.should.be.exactly('as'); + ast.body[1].arguments[0].value.should.be.exactly('dog'); + }); +}); diff --git a/test/parser.js b/test/parser.js index 6619730..2b0eb7d 100644 --- a/test/parser.js +++ b/test/parser.js @@ -68,7 +68,7 @@ describe('Test parser', function () { ' * @test 123 1.23 null', ' */' ].join('\r\n')); - ast.body[0].type.should.be.exactly('test'); + ast.body[0].name.should.be.exactly('test'); ast.body[0].options.length.should.be.exactly(3); ast.body[0].options[0].kind.should.be.exactly('number'); ast.body[0].options[0].value.should.be.exactly(123); @@ -83,7 +83,7 @@ describe('Test parser', function () { ' * @test [1, 2, a => b]', ' */' ].join('\r\n')); - ast.body[0].type.should.be.exactly('test'); + ast.body[0].name.should.be.exactly('test'); ast.body[0].options.length.should.be.exactly(1); ast.body[0].options[0].kind.should.be.exactly('array'); // @todo console.log(ast.body[0].options[0]); @@ -95,7 +95,7 @@ describe('Test parser', function () { ' * @test true false', ' */' ].join('\r\n')); - ast.body[0].type.should.be.exactly('test'); + ast.body[0].name.should.be.exactly('test'); ast.body[0].options.length.should.be.exactly(2); ast.body[0].options[0].kind.should.be.exactly('boolean'); ast.body[0].options[0].value.should.be.exactly(true);