add yields tag (#1388)

This commit is contained in:
Jeff Williams 2017-07-09 12:46:27 -07:00
parent f31a011755
commit c50a4c027a
8 changed files with 102 additions and 10 deletions

View File

@ -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
}
}
};

View File

@ -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']
}
};

View File

@ -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;

View File

@ -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);
@ -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('|') );

View File

@ -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) ?>

22
test/fixtures/yieldstag.js vendored Normal file
View File

@ -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() {}

View File

@ -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: [
@ -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;

View File

@ -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();
});
});