mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
add merge method to doclets (#1215)
This commit is contained in:
parent
976cc62dc8
commit
0551bd49ed
@ -14,6 +14,9 @@ var jsdoc = {
|
||||
tag: {
|
||||
Tag: require('jsdoc/tag').Tag,
|
||||
dictionary: require('jsdoc/tag/dictionary')
|
||||
},
|
||||
util: {
|
||||
doop: require('jsdoc/util/doop')
|
||||
}
|
||||
};
|
||||
var path = require('jsdoc/path');
|
||||
@ -178,6 +181,8 @@ exports._replaceDictionary = function _replaceDictionary(dict) {
|
||||
var Doclet = exports.Doclet = function(docletSrc, meta) {
|
||||
var newTags = [];
|
||||
|
||||
meta = meta || {};
|
||||
|
||||
/** The original text of the comment from the source code. */
|
||||
this.comment = docletSrc;
|
||||
this.setMeta(meta);
|
||||
@ -462,3 +467,77 @@ Doclet.prototype.setMeta = function(meta) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Extend a destination object with properties from the source object, ignoring properties that
|
||||
* should be excluded.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} source - The source object.
|
||||
* @param {Object} destination - The destination object.
|
||||
* @param {Array.<string>} exclude - The names of properties to exclude from copying.
|
||||
*/
|
||||
function extend(source, destination, exclude) {
|
||||
var properties = _.difference(Object.getOwnPropertyNames(source), exclude);
|
||||
|
||||
properties.forEach(function(property) {
|
||||
switch (typeof source[property]) {
|
||||
case 'function':
|
||||
// do nothing
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
destination[property] = jsdoc.util.doop(source[property]);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
destination[property] = source[property];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend a destination doclet with the specified properties from the source doclet, provided that
|
||||
* the properties from the source doclet appear to be a better fit.
|
||||
*
|
||||
* @private
|
||||
* @param {module:jsdoc/doclet.Doclet} source - The source doclet.
|
||||
* @param {module:jsdoc/doclet.Doclet} destination - The destination doclet.
|
||||
* @param {Array.<string>} include - The names of properties to copy.
|
||||
*/
|
||||
function maybeExtend(source, destination, include) {
|
||||
include.forEach(function(property) {
|
||||
var shouldExtend = false;
|
||||
|
||||
if ({}.hasOwnProperty.call(source, property)) {
|
||||
// use the source property if the destination property is missing or empty
|
||||
if (!destination[property] || !destination[property].length) {
|
||||
shouldExtend = true;
|
||||
}
|
||||
// use the source property if it's at least as long as the destination property
|
||||
else if (source[property].length >= destination[property].length) {
|
||||
shouldExtend = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldExtend) {
|
||||
destination[property] = jsdoc.util.doop(source[property]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge another doclet into this doclet.
|
||||
*
|
||||
* @param {module:jsdoc/doclet.Doclet} doclet - The doclet to merge into this one.
|
||||
*/
|
||||
Doclet.prototype.merge = function(doclet) {
|
||||
var specialCase = [
|
||||
'params',
|
||||
'properties'
|
||||
];
|
||||
|
||||
extend(doclet, this, specialCase);
|
||||
maybeExtend(doclet, this, specialCase);
|
||||
};
|
||||
|
||||
@ -26,7 +26,7 @@ describe('jsdoc/doclet', function() {
|
||||
describe('setScope', function() {
|
||||
it('should accept the correct scope names', function() {
|
||||
function setScope(scopeName) {
|
||||
var doclet = new Doclet('/** Huzzah, a doclet! */', {});
|
||||
var doclet = new Doclet('/** Huzzah, a doclet! */');
|
||||
|
||||
doclet.setScope(scopeName);
|
||||
}
|
||||
@ -38,7 +38,7 @@ describe('jsdoc/doclet', function() {
|
||||
|
||||
it('should throw an error for invalid scope names', function() {
|
||||
function setScope() {
|
||||
var doclet = new Doclet('/** Woe betide this doclet. */', {});
|
||||
var doclet = new Doclet('/** Woe betide this doclet. */');
|
||||
|
||||
doclet.setScope('fiddlesticks');
|
||||
}
|
||||
@ -46,4 +46,93 @@ describe('jsdoc/doclet', function() {
|
||||
expect(setScope).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('merge', function() {
|
||||
it('should override most properties of the original doclet', function() {
|
||||
var originalDoclet = new Doclet('/** Hello!\n@version 1.0.0 */');
|
||||
var newDoclet = new Doclet('/** New and improved!\n@version 2.0.0 */');
|
||||
|
||||
originalDoclet.merge(newDoclet);
|
||||
|
||||
Object.getOwnPropertyNames(originalDoclet).forEach(function(property) {
|
||||
expect(originalDoclet[property]).toEqual(newDoclet[property]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should add properties that are missing from the original doclet', function() {
|
||||
var originalDoclet = new Doclet('/** Hello! */');
|
||||
var newDoclet = new Doclet('/** Hello!\n@version 2.0.0 */');
|
||||
|
||||
originalDoclet.merge(newDoclet);
|
||||
|
||||
expect(originalDoclet.version).toBe('2.0.0');
|
||||
});
|
||||
|
||||
describe('params and properties', function() {
|
||||
var properties = [
|
||||
'params',
|
||||
'properties'
|
||||
];
|
||||
|
||||
it('should use the new doclet\'s params and properties if the original doclet had none',
|
||||
function() {
|
||||
var originalDoclet = new Doclet('/** Hello! */');
|
||||
var newComment = [
|
||||
'/**',
|
||||
' * @param {string} foo - The foo.',
|
||||
' * @property {number} bar - The bar.',
|
||||
' */'
|
||||
].join('\n');
|
||||
var newDoclet = new Doclet(newComment);
|
||||
|
||||
originalDoclet.merge(newDoclet);
|
||||
|
||||
properties.forEach(function(property) {
|
||||
expect(originalDoclet[property]).toEqual(newDoclet[property]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should use the new doclet\'s params and properties if the new doclet has at ' +
|
||||
'least as many of them as the old doclet', function() {
|
||||
var originalComment = [
|
||||
'/**',
|
||||
' * @param {string} foo - The foo.',
|
||||
' * @property {number} bar - The bar.',
|
||||
' */'
|
||||
].join('\n');
|
||||
var originalDoclet = new Doclet(originalComment);
|
||||
var newComment = [
|
||||
'/**',
|
||||
' * @param {number} baz - The baz.',
|
||||
' * @property {string} qux - The qux.',
|
||||
' */'
|
||||
].join('\n');
|
||||
var newDoclet = new Doclet(newComment);
|
||||
|
||||
originalDoclet.merge(newDoclet);
|
||||
|
||||
properties.forEach(function(property) {
|
||||
expect(originalDoclet[property]).toEqual(newDoclet[property]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should use the old doclet\'s params and properties if the new doclet has fewer ' +
|
||||
'of them', function() {
|
||||
var originalComment = [
|
||||
'/**',
|
||||
' * @param {string} foo - The foo.',
|
||||
' * @property {number} bar - The bar.',
|
||||
' */'
|
||||
].join('\n');
|
||||
var originalDoclet = new Doclet(originalComment);
|
||||
var newDoclet = new Doclet('/** Hello! */');
|
||||
|
||||
originalDoclet.merge(newDoclet);
|
||||
|
||||
properties.forEach(function(property) {
|
||||
expect(originalDoclet[property]).not.toEqual(newDoclet[property]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user