Skip to content

Commit

Permalink
add yields tag (#1388)
Browse files Browse the repository at this point in the history
  • Loading branch information
hegemonic committed Jul 9, 2017
1 parent f31a011 commit c50a4c0
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 10 deletions.
6 changes: 6 additions & 0 deletions lib/jsdoc/schema.js
Expand Up @@ -597,6 +597,12 @@ var DOCLET_SCHEMA = exports.DOCLET_SCHEMA = {
virtual: {
type: BOOLEAN,
optional: true
},
yields: {
type: ARRAY,
optional: true,
minItems: 1,
items: PARAM_SCHEMA
}
}
};
Expand Down
9 changes: 9 additions & 0 deletions lib/jsdoc/tag/dictionary/definitions.js
Expand Up @@ -819,6 +819,15 @@ var baseTags = exports.baseTags = {
onTagged: function(doclet, tag) {
doclet.version = tag.value;
}
},
yields: {
mustHaveValue: true,
canHaveType: true,
onTagged: function(doclet, tag) {
doclet.yields = doclet.yields || [];
doclet.yields.push(tag.value);
},
synonyms: ['yield']
}
};

Expand Down
8 changes: 4 additions & 4 deletions lib/jsdoc/util/templateHelper.js
Expand Up @@ -751,17 +751,17 @@ exports.getSignatureParams = function(d, optClass) {
};

/**
* Retrieve links to types that the member can return.
* Retrieve links to types that the member can return or yield.
*
* @param {Object} d - The doclet whose types will be retrieved.
* @param {string} [cssClass] - The CSS class to include in the `class` attribute for each link.
* @return {Array.<string>} HTML links to types that the member can return.
* @return {Array.<string>} HTML links to types that the member can return or yield.
*/
exports.getSignatureReturns = function(d, cssClass) {
var returnTypes = [];

if (d.returns) {
d.returns.forEach(function(r) {
if (d.yields || d.returns) {
(d.yields || d.returns).forEach(function(r) {
if (r && r.type && r.type.names) {
if (!returnTypes.length) {
returnTypes = r.type.names;
Expand Down
9 changes: 5 additions & 4 deletions templates/default/publish.js
Expand Up @@ -158,12 +158,13 @@ function addSignatureReturns(f) {
var attribsString = '';
var returnTypes = [];
var returnTypesString = '';
var source = f.yields || f.returns;

// jam all the return-type attributes into an array. this could create odd results (for example,
// if there are both nullable and non-nullable return types), but let's assume that most people
// who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa.
if (f.returns) {
f.returns.forEach(function(item) {
if (source) {
source.forEach(function(item) {
helper.getAttribs(item).forEach(function(attrib) {
if (attribs.indexOf(attrib) === -1) {
attribs.push(attrib);
Expand All @@ -174,8 +175,8 @@ function addSignatureReturns(f) {
attribsString = buildAttribsString(attribs);
}

if (f.returns) {
returnTypes = addNonParamAttributes(f.returns);
if (source) {
returnTypes = addNonParamAttributes(source);
}
if (returnTypes.length) {
returnTypesString = util.format( ' &rarr; %s{%s}', attribsString, returnTypes.join('|') );
Expand Down
12 changes: 12 additions & 0 deletions templates/default/tmpl/method.tmpl
Expand Up @@ -101,6 +101,18 @@ var self = this;
<?js });
} } ?>

<?js if (data.yields && yields.length) { ?>
<h5>Yields:</h5>
<?js if (yields.length > 1) { ?><ul><?js
yields.forEach(function(r) { ?>
<li><?js= self.partial('returns.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
yields.forEach(function(r) { ?>
<?js= self.partial('returns.tmpl', r) ?>
<?js });
} } ?>

<?js if (data.examples && examples.length) { ?>
<h5>Example<?js= examples.length > 1? 's':'' ?></h5>
<?js= this.partial('examples.tmpl', examples) ?>
Expand Down
22 changes: 22 additions & 0 deletions test/fixtures/yieldstag.js
@@ -0,0 +1,22 @@
'use strict';

/**
* Generate the Fibonacci sequence of numbers.
*
* @yields {number} The next number in the Fibonacci sequence.
*/
function* fibonacci() {}

/**
* Generate the Fibonacci sequence of numbers.
*
* @yields The next number in the Fibonacci sequence.
*/
function* fibonacci2() {}

/**
* Generate the Fibonacci sequence of numbers.
*
* @yields {number}
*/
function* fibonacci3() {}
17 changes: 15 additions & 2 deletions test/specs/jsdoc/util/templateHelper.js
Expand Up @@ -956,8 +956,6 @@ describe("jsdoc/util/templateHelper", function() {
});

describe("getSignatureReturns", function() {
// retrieves links to types that the member can return.

it("returns a value with correctly escaped HTML", function() {
var mockDoclet = {
returns: [
Expand Down Expand Up @@ -992,6 +990,21 @@ describe("jsdoc/util/templateHelper", function() {
expect(returns.length).toBe(0);
});

it('uses the value of the `yields` property', function() {
var doc = new doclet.Doclet('/** @yields {string} A string. */', {});
var html = helper.getSignatureReturns(doc);

expect(html).toContain('string');
});

it('prefers `yields` over `returns`', function() {
var doc = new doclet.Doclet('/** @yields {string}\n@returns {number} */', {});
var html = helper.getSignatureReturns(doc);

expect(html).toContain('string');
expect(html).not.toContain('number');
});

it("creates links for return types if relevant", function() {
var doc;
var returns;
Expand Down
29 changes: 29 additions & 0 deletions test/specs/tags/yieldstag.js
@@ -0,0 +1,29 @@
'use strict';

describe('@yields tag', function() {
var docSet = jasmine.getDocSetFromFile('test/fixtures/yieldstag.js');
var fibonacci = docSet.getByLongname('fibonacci')[0];
var fibonacci2 = docSet.getByLongname('fibonacci2')[0];
var fibonacci3 = docSet.getByLongname('fibonacci3')[0];

it('should add the type and description to the doclet\'s `yields` property', function() {
expect(Array.isArray(fibonacci.yields)).toBe(true);
expect(fibonacci.yields.length).toBe(1);
expect(fibonacci.yields[0].type.names.join(', ')).toBe('number');
expect(fibonacci.yields[0].description).toBe('The next number in the Fibonacci sequence.');
});

it('should work when only a description is present', function() {
expect(Array.isArray(fibonacci2.yields)).toBe(true);
expect(fibonacci2.yields.length).toBe(1);
expect(fibonacci2.yields[0].type).not.toBeDefined();
expect(fibonacci2.yields[0].description).toBe('The next number in the Fibonacci sequence.');
});

it('should work when only a type is present', function() {
expect(Array.isArray(fibonacci3.yields)).toBe(true);
expect(fibonacci3.yields.length).toBe(1);
expect(fibonacci3.yields[0].type.names.join(', ')).toBe('number');
expect(fibonacci3.yields[0].description).not.toBeDefined();
});
});

0 comments on commit c50a4c0

Please sign in to comment.