Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support @throws tag #305

Merged
merged 4 commits into from
Jan 15, 2015
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/syntax/index.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ toJSON: function () {
<a href="#for">`@for`</a>,
<a href="#param">`@param`</a>,
<a href="#return">`@return`</a>,
<a href="#throws">`@throws`</a>,
<a href="#static">`@static`</a>.
</p>
</td>
Expand Down Expand Up @@ -700,6 +701,27 @@ ATTRS[RENDERED] = {
</p>
</td>
</tr>
<tr id="throws">
<td>`throws`</td>
<td>
```
/**
* @method generateClientId
* @throws {Error} An error.
*/
```
</td>
<td>
<p>Specifies an error which method throws.
A `@throws` tag has the structure `@throws {type} description`.
The `{type}` is optional.</p>
<p>
See also:
<a href="#method">`@method`</a>,
<a href="#return">`@return`</a>.
</p>
</td>
</tr>
<tr id="for">
<td>`for`</td>
<td>
Expand Down
30 changes: 27 additions & 3 deletions lib/docparser.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ YUI.add('docparser', function (Y) {
'augments': 'uses', // YUI convention for prototype mixins
'depreciated': 'deprecated', // subtle difference
'desciption': 'description', // shouldn't need the @description tag at all
'exception': 'throws', // need to standardize on one or the other
'extend': 'extends', // typo
'function': 'method', // we may want standalone inner functions at some point
'member': 'method', // probably meant method
Expand All @@ -191,7 +192,8 @@ YUI.add('docparser', function (Y) {
'parma': 'param', // typo
'propery': 'property', // typo
'prop': 'property', // probably meant property
'returns': 'return' // need to standardize on one or the other
'returns': 'return', // need to standardize on one or the other
'throw': 'throws' // need to standardize on one or the other
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need throw or exception unless users tell us it's a common mistake.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, OK! Moved out.

},

/**
Expand Down Expand Up @@ -376,7 +378,6 @@ YUI.add('docparser', function (Y) {

// @return {type} description // methods
// @returns {type} description // methods
// @throws {type} an error #2173342
// @injects {HTML|CSS|script} description
// can be used by anthing that has an optional {type} and a description
'return': function (tagname, value, target, block) {
Expand All @@ -401,7 +402,30 @@ YUI.add('docparser', function (Y) {
target[tagname] = result;

},
'throws': 'return',

// @throws {type} description
'throws': function (tagname, value, target) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can do 'throws': 'return' since it's the same implementation. See https://github.com/okuryu/yuidoc/blob/throws/lib/docparser.js#L586-L589

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It was deliberate because I have the potential of change @return implementation to support returnning complex object (see #37). Anyway, I'd like to do it as you suggest for now.

var desc = implodeString(trim(value)),
type,
match = REGEX_TYPE.exec(desc),
result;

if (match) {
type = fixType(trim(match[2]));
desc = trim(match[1] + match[3]);
}

result = {
description: Y.unindent(explodeString(desc))
};

if (type) {
result.type = type;
}

target[tagname] = result;
},

'injects': 'return',

// trying to overwrite the constructor value is a bad idea
Expand Down
11 changes: 11 additions & 0 deletions tests/input/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
* @evil
* @injects {HTML} uses a string parameter to populate innerHTML
* @returns something without a type
* @throw throw error without a type
* @example
* This is code
* @example
Expand All @@ -61,20 +62,23 @@
* @param {string} anobject.prop1 prop1
* @param {bool} anobject.prop2 prop2
* @return {string} something with a type
* @throws {error} error with a type
*/

/**
* test 0..n param
* @method test0ton
* @param {string} [optionalandmultiple]* my desc
* @returns something without a type
* @throw throw error without a type
*/

/**
* test 1..n param
* @method test1ton
* @param {string} multiple* my desc
* @returns something without a type
* @throw throw error without a type
*/

/**
Expand All @@ -83,6 +87,7 @@ test alternative 1..n param with ...args
@method testrestparam1n
@param {String} ...multiple my desc
@returns something without a type
@throw throw error without a type
**/

/**
Expand All @@ -91,6 +96,7 @@ test alternative 0..n param with ...args
@method testrestparam0n
@param {String} [...multiple] my desc
@returns something without a type
@throw throw error without a type
**/

/**
Expand All @@ -110,6 +116,11 @@ Test newlines before descriptions.
Sometimes true, sometimes false.

Nobody knows!

@throws {Error}
Throws an error.

Catch me.
**/

/**
Expand Down
15 changes: 14 additions & 1 deletion tests/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ suite.add(new YUITest.TestCase({
'evil',
'injects',
'return',
'throws',
'example',
'class',
'module',
Expand All @@ -254,10 +255,12 @@ suite.add(new YUITest.TestCase({
Assert.areSame('HTML', item.injects.type, 'Injection type not found');

Assert.isUndefined(item["return"].type, 'Type should be missing');
Assert.isUndefined(item.throws.type, 'Type should be missing');
Assert.areSame(2, item.example.length, 'Should have 2 example snippets');

item2 = this.findByName('testobjectparam', 'myclass');
Assert.areSame('String', item2["return"].type, 'Type should not be missing');
Assert.areSame('Error', item2.throws.type, 'Type should not be missing');
},
'test: parameter parsing': function () {
var item, item2, item3, item4;
Expand Down Expand Up @@ -289,27 +292,31 @@ suite.add(new YUITest.TestCase({
Assert.isTrue(item2.params[0].optional, 'Optional not set');
Assert.isTrue(item2.params[0].multiple, 'Multiple not set');
Assert.isUndefined(item2["return"].type, 'Type should be missing');
Assert.isUndefined(item2.throws.type, 'Type should be missing');

item2 = this.findByName('test1ton', 'myclass');
Assert.isArray(item2.params, 'Params should be an array');
Assert.areSame(1, item2.params.length, 'Failed to parse all 5 parameters');
Assert.isUndefined(item2.params[0].optional, 'Optional should not be set');
Assert.isTrue(item2.params[0].multiple, 'Multiple not set');
Assert.isUndefined(item2["return"].type, 'Type should be missing');
Assert.isUndefined(item2.throws.type, 'Type should be missing');

item3 = this.findByName('testrestparam0n', 'myclass');
Assert.isArray(item3.params, 'Params should be an array');
Assert.areSame(1, item3.params.length, 'Failed to parse all 5 parameters');
Assert.isTrue(item3.params[0].optional, 'Optional not set');
Assert.isTrue(item3.params[0].multiple, 'Multiple not set');
Assert.isUndefined(item3['return'].type, 'Type should be missing');
Assert.isUndefined(item3.throws.type, 'Type should be missing');

item4 = this.findByName('testrestparam1n', 'myclass');
Assert.isArray(item4.params, 'Params should be an array');
Assert.areSame(1, item4.params.length, 'Failed to parse all 5 parameters');
Assert.isUndefined(item4.params[0].optional, 'Optional should not be set');
Assert.isTrue(item4.params[0].multiple, 'Multiple not set');
Assert.isUndefined(item4['return'].type, 'Type should be missing');
Assert.isUndefined(item4.throws.type, 'Type should be missing');

item = this.findByName('testNewlineBeforeDescription', 'myclass');
Assert.isArray(item.params, 'Params should be an array.');
Expand All @@ -329,7 +336,7 @@ suite.add(new YUITest.TestCase({
'Param 1 should have the correct description.'
);
},
'test: indented return description': function () {
'test: indented description': function () {
var item = this.findByName('testNewlineBeforeDescription', 'myclass');

Assert.areSame('Boolean', item['return'].type, 'Type should be correct.');
Expand All @@ -338,6 +345,12 @@ suite.add(new YUITest.TestCase({
item['return'].description,
'Description indentation should be normalized to the first line.'
);
Assert.areSame('Error', item.throws.type, 'Type should be correct.');
Assert.areSame(
'Throws an error.\nCatch me.',
item.throws.description,
'Description indentation should be normalized to the first line.'
);
},
'test: object parameters': function () {
var item, props;
Expand Down
19 changes: 19 additions & 0 deletions themes/default/partials/method.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,25 @@
</div>
{{/return}}

{{#throws}}
<div class="throws">
<h4>Throws:</h4>

<div class="throws-description">
{{#if description}}
{{#if type}}
<span class="type">{{#crossLink type}}{{/crossLink}}</span>:
{{/if}}
{{{description}}}
{{else}}
{{#if type}}
<span class="type">{{#crossLink type}}{{/crossLink}}</span>:
{{/if}}
{{/if}}
</div>
</div>
{{/throws}}

{{#example}}
<div class="example">
<h4>Example:</h4>
Expand Down
5 changes: 5 additions & 0 deletions themes/simple/partials/method.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
<br><div class="returns"><strong>Returns:</strong> {{#if type}}&lt;{{#crossLink type}}{{/crossLink}}&gt; {{/if}}{{{description}}}</div>
{{/return}}
{{/if}}
{{#if throws}}
{{#throws}}
<br><div class="throws"><strong>Throws:</strong> {{#if type}}&lt;{{#crossLink type}}{{/crossLink}}&gt; {{/if}}{{{description}}}</div>
{{/throws}}
{{/if}}
{{#if example}}
<h5>Example</h5>
{{{example}}}
Expand Down