mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
refactor(jsdoc-doclet): make combineDoclets a static method on Doclet
This change puts `combineDoclets` in the same place as methods like `clone` and `emptyDoclet`.
This commit is contained in:
parent
4c4a58260d
commit
8a0b40502e
@ -22,10 +22,10 @@
|
||||
*/
|
||||
import * as augment from './lib/augment.js';
|
||||
import { resolveBorrows } from './lib/borrow.js';
|
||||
import { combineDoclets, Doclet } from './lib/doclet.js';
|
||||
import { Doclet } from './lib/doclet.js';
|
||||
import { DocletStore } from './lib/doclet-store.js';
|
||||
import { Package } from './lib/package.js';
|
||||
import * as schema from './lib/schema.js';
|
||||
|
||||
export { augment, combineDoclets, Doclet, DocletStore, Package, resolveBorrows, schema };
|
||||
export default { augment, combineDoclets, Doclet, DocletStore, Package, resolveBorrows, schema };
|
||||
export { augment, Doclet, DocletStore, Package, resolveBorrows, schema };
|
||||
export default { augment, Doclet, DocletStore, Package, resolveBorrows, schema };
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
import { fromParts, SCOPE, toParts } from '@jsdoc/name';
|
||||
|
||||
import { combineDoclets, Doclet } from './doclet.js';
|
||||
import { Doclet } from './doclet.js';
|
||||
|
||||
const DEPENDENCY_KINDS = ['class', 'external', 'interface', 'mixin'];
|
||||
|
||||
@ -225,7 +225,7 @@ function getInheritedAdditions(depDoclets, docletStore) {
|
||||
childDoclet = {};
|
||||
}
|
||||
|
||||
member = combineDoclets(childDoclet, parentDoclet);
|
||||
member = Doclet.combineDoclets(childDoclet, parentDoclet);
|
||||
|
||||
if (!member.inherited) {
|
||||
member.inherits = member.longname;
|
||||
@ -411,7 +411,7 @@ function getImplementedAdditions(implDoclets, docletStore) {
|
||||
childDoclet = {};
|
||||
}
|
||||
|
||||
implementationDoclet = combineDoclets(childDoclet, parentDoclet);
|
||||
implementationDoclet = Doclet.combineDoclets(childDoclet, parentDoclet);
|
||||
|
||||
reparentDoclet(doclet, implementationDoclet);
|
||||
updateImplements(implementationDoclet, parentDoclet.longname);
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
import { SCOPE } from '@jsdoc/name';
|
||||
|
||||
import { combineDoclets, Doclet } from './doclet.js';
|
||||
import { Doclet } from './doclet.js';
|
||||
|
||||
function cloneBorrowedDoclets({ borrowed, longname }, docletStore) {
|
||||
borrowed?.forEach(({ from, as }) => {
|
||||
@ -32,7 +32,7 @@ function cloneBorrowedDoclets({ borrowed, longname }, docletStore) {
|
||||
if (borrowedDoclets) {
|
||||
borrowedAs = borrowedAs.replace(/^prototype\./, SCOPE.PUNC.INSTANCE);
|
||||
borrowedDoclets.forEach((borrowedDoclet) => {
|
||||
const clone = combineDoclets(borrowedDoclet, Doclet.emptyDoclet(borrowedDoclet.env));
|
||||
const clone = Doclet.clone(borrowedDoclet);
|
||||
|
||||
// TODO: this will fail on longnames like '"Foo#bar".baz'
|
||||
parts = borrowedAs.split(SCOPE.PUNC.INSTANCE);
|
||||
|
||||
@ -409,30 +409,6 @@ function copyPropsWithIncludelist(primary, secondary, target, include) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines two doclets into a new doclet.
|
||||
*
|
||||
* @alias module:@jsdoc/doclet.combineDoclets
|
||||
* @param {module:@jsdoc/doclet.Doclet} primary - The doclet whose properties will be used.
|
||||
* @param {module:@jsdoc/doclet.Doclet} secondary - The doclet to use as a fallback for properties
|
||||
* that the primary doclet does not have.
|
||||
* @returns {module:@jsdoc/doclet.Doclet} A new doclet that combines the primary and secondary
|
||||
* doclets.
|
||||
*/
|
||||
export function combineDoclets(primary, secondary) {
|
||||
const excludelist = ['env', 'params', 'properties', 'undocumented'];
|
||||
const includelist = ['params', 'properties'];
|
||||
const target = Doclet.emptyDoclet(secondary.env);
|
||||
|
||||
// First, copy most properties to the target doclet.
|
||||
copyPropsWithExcludelist(primary, secondary, target, excludelist);
|
||||
// Then copy a few specific properties to the target doclet, as long as they're not falsy and
|
||||
// have a length greater than 0.
|
||||
copyPropsWithIncludelist(primary, secondary, target, includelist);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a single JSDoc comment, or a single symbol in a source file.
|
||||
*
|
||||
@ -504,7 +480,30 @@ Doclet = class {
|
||||
* @returns {module:@jsdoc/doclet.Doclet} A copy of the doclet.
|
||||
*/
|
||||
static clone(doclet) {
|
||||
return combineDoclets(doclet, Doclet.emptyDoclet(doclet.env));
|
||||
return Doclet.combineDoclets(doclet, Doclet.emptyDoclet(doclet.env));
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines two doclets into a new doclet.
|
||||
*
|
||||
* @param {module:@jsdoc/doclet.Doclet} primary - The doclet whose properties will be used.
|
||||
* @param {module:@jsdoc/doclet.Doclet} secondary - The doclet to use as a fallback for properties
|
||||
* that the primary doclet does not have.
|
||||
* @returns {module:@jsdoc/doclet.Doclet} A new doclet that combines the primary and secondary
|
||||
* doclets.
|
||||
*/
|
||||
static combineDoclets(primary, secondary) {
|
||||
const excludelist = ['env', 'params', 'properties', 'undocumented'];
|
||||
const includelist = ['params', 'properties'];
|
||||
const target = Doclet.emptyDoclet(secondary.env);
|
||||
|
||||
// First, copy most properties to the target doclet.
|
||||
copyPropsWithExcludelist(primary, secondary, target, excludelist);
|
||||
// Then copy a few specific properties to the target doclet, as long as they're not falsy and
|
||||
// have a length greater than 0.
|
||||
copyPropsWithIncludelist(primary, secondary, target, includelist);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
import doclet from '../../index.js';
|
||||
import * as augment from '../../lib/augment.js';
|
||||
import { resolveBorrows } from '../../lib/borrow.js';
|
||||
import { combineDoclets, Doclet } from '../../lib/doclet.js';
|
||||
import { Doclet } from '../../lib/doclet.js';
|
||||
import { DocletStore } from '../../lib/doclet-store.js';
|
||||
import { Package } from '../../lib/package.js';
|
||||
import * as schema from '../../lib/schema.js';
|
||||
@ -33,12 +33,6 @@ describe('@jsdoc/doclet', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('combineDoclets', () => {
|
||||
it('is lib/doclet.combineDoclets', () => {
|
||||
expect(doclet.combineDoclets).toEqual(combineDoclets);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Doclet', () => {
|
||||
it('is lib/doclet.Doclet', () => {
|
||||
expect(doclet.Doclet).toEqual(Doclet);
|
||||
|
||||
@ -29,10 +29,6 @@ describe('@jsdoc/doclet/lib/doclet', () => {
|
||||
expect(doclet).toBeObject();
|
||||
});
|
||||
|
||||
it('has a combineDoclets method', () => {
|
||||
expect(doclet.combineDoclets).toBeFunction();
|
||||
});
|
||||
|
||||
it('has a Doclet class', () => {
|
||||
expect(doclet.Doclet).toBeFunction();
|
||||
});
|
||||
@ -41,74 +37,6 @@ describe('@jsdoc/doclet/lib/doclet', () => {
|
||||
expect(doclet.WATCHABLE_PROPS).toBeArrayOfStrings();
|
||||
});
|
||||
|
||||
describe('combineDoclets', () => {
|
||||
it('overrides most properties of the secondary doclet', () => {
|
||||
let descriptors;
|
||||
const primaryDoclet = new Doclet('/** New and improved!\n@version 2.0.0 */', null, jsdoc.env);
|
||||
const secondaryDoclet = new Doclet('/** Hello!\n@version 1.0.0 */', null, jsdoc.env);
|
||||
const newDoclet = doclet.combineDoclets(primaryDoclet, secondaryDoclet);
|
||||
|
||||
descriptors = Object.getOwnPropertyDescriptors(newDoclet);
|
||||
Object.keys(descriptors).forEach((property) => {
|
||||
if (!descriptors[property].enumerable) {
|
||||
return;
|
||||
}
|
||||
|
||||
expect(newDoclet[property]).toEqual(primaryDoclet[property]);
|
||||
});
|
||||
});
|
||||
|
||||
it('adds properties from the secondary doclet that are missing', () => {
|
||||
const primaryDoclet = new Doclet('/** Hello!\n@version 2.0.0 */', null, jsdoc.env);
|
||||
const secondaryDoclet = new Doclet('/** Hello! */', null, jsdoc.env);
|
||||
const newDoclet = doclet.combineDoclets(primaryDoclet, secondaryDoclet);
|
||||
|
||||
expect(newDoclet.version).toBe('2.0.0');
|
||||
});
|
||||
|
||||
describe('params and properties', () => {
|
||||
const properties = ['params', 'properties'];
|
||||
|
||||
it('uses params and properties from the secondary doclet if the primary lacks them', () => {
|
||||
const primaryDoclet = new Doclet('/** Hello! */', null, jsdoc.env);
|
||||
const secondaryComment = [
|
||||
'/**',
|
||||
' * @param {string} foo - The foo.',
|
||||
' * @property {number} bar - The bar.',
|
||||
' */',
|
||||
].join('\n');
|
||||
const secondaryDoclet = new Doclet(secondaryComment, null, jsdoc.env);
|
||||
const newDoclet = doclet.combineDoclets(primaryDoclet, secondaryDoclet);
|
||||
|
||||
properties.forEach((property) => {
|
||||
expect(newDoclet[property]).toEqual(secondaryDoclet[property]);
|
||||
});
|
||||
});
|
||||
|
||||
it('uses params and properties from the primary doclet, if present', () => {
|
||||
const primaryComment = [
|
||||
'/**',
|
||||
' * @param {number} baz - The baz.',
|
||||
' * @property {string} qux - The qux.',
|
||||
' */',
|
||||
].join('\n');
|
||||
const primaryDoclet = new Doclet(primaryComment, null, jsdoc.env);
|
||||
const secondaryComment = [
|
||||
'/**',
|
||||
' * @param {string} foo - The foo.',
|
||||
' * @property {number} bar - The bar.',
|
||||
' */',
|
||||
].join('\n');
|
||||
const secondaryDoclet = new Doclet(secondaryComment, null, jsdoc.env);
|
||||
const newDoclet = doclet.combineDoclets(primaryDoclet, secondaryDoclet);
|
||||
|
||||
properties.forEach((property) => {
|
||||
expect(newDoclet[property]).toEqual(primaryDoclet[property]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Doclet', () => {
|
||||
function makeDoclet(tagStrings, env) {
|
||||
const comment = `/**\n${tagStrings.join('\n')}\n*/`;
|
||||
@ -305,6 +233,86 @@ describe('@jsdoc/doclet/lib/doclet', () => {
|
||||
xit('TODO: write tests');
|
||||
});
|
||||
|
||||
xdescribe('clone', () => {
|
||||
xit('TODO: write tests');
|
||||
});
|
||||
|
||||
describe('combineDoclets', () => {
|
||||
it('overrides most properties of the secondary doclet', () => {
|
||||
let descriptors;
|
||||
const primaryDoclet = new Doclet(
|
||||
'/** New and improved!\n@version 2.0.0 */',
|
||||
null,
|
||||
jsdoc.env
|
||||
);
|
||||
const secondaryDoclet = new Doclet('/** Hello!\n@version 1.0.0 */', null, jsdoc.env);
|
||||
const newDoclet = Doclet.combineDoclets(primaryDoclet, secondaryDoclet);
|
||||
|
||||
descriptors = Object.getOwnPropertyDescriptors(newDoclet);
|
||||
Object.keys(descriptors).forEach((property) => {
|
||||
if (!descriptors[property].enumerable) {
|
||||
return;
|
||||
}
|
||||
|
||||
expect(newDoclet[property]).toEqual(primaryDoclet[property]);
|
||||
});
|
||||
});
|
||||
|
||||
it('adds properties from the secondary doclet that are missing', () => {
|
||||
const primaryDoclet = new Doclet('/** Hello!\n@version 2.0.0 */', null, jsdoc.env);
|
||||
const secondaryDoclet = new Doclet('/** Hello! */', null, jsdoc.env);
|
||||
const newDoclet = Doclet.combineDoclets(primaryDoclet, secondaryDoclet);
|
||||
|
||||
expect(newDoclet.version).toBe('2.0.0');
|
||||
});
|
||||
|
||||
describe('params and properties', () => {
|
||||
const properties = ['params', 'properties'];
|
||||
|
||||
it('uses params and properties from the secondary doclet if the primary lacks them', () => {
|
||||
const primaryDoclet = new Doclet('/** Hello! */', null, jsdoc.env);
|
||||
const secondaryComment = [
|
||||
'/**',
|
||||
' * @param {string} foo - The foo.',
|
||||
' * @property {number} bar - The bar.',
|
||||
' */',
|
||||
].join('\n');
|
||||
const secondaryDoclet = new Doclet(secondaryComment, null, jsdoc.env);
|
||||
const newDoclet = Doclet.combineDoclets(primaryDoclet, secondaryDoclet);
|
||||
|
||||
properties.forEach((property) => {
|
||||
expect(newDoclet[property]).toEqual(secondaryDoclet[property]);
|
||||
});
|
||||
});
|
||||
|
||||
it('uses params and properties from the primary doclet, if present', () => {
|
||||
const primaryComment = [
|
||||
'/**',
|
||||
' * @param {number} baz - The baz.',
|
||||
' * @property {string} qux - The qux.',
|
||||
' */',
|
||||
].join('\n');
|
||||
const primaryDoclet = new Doclet(primaryComment, null, jsdoc.env);
|
||||
const secondaryComment = [
|
||||
'/**',
|
||||
' * @param {string} foo - The foo.',
|
||||
' * @property {number} bar - The bar.',
|
||||
' */',
|
||||
].join('\n');
|
||||
const secondaryDoclet = new Doclet(secondaryComment, null, jsdoc.env);
|
||||
const newDoclet = Doclet.combineDoclets(primaryDoclet, secondaryDoclet);
|
||||
|
||||
properties.forEach((property) => {
|
||||
expect(newDoclet[property]).toEqual(primaryDoclet[property]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
xdescribe('emptyDoclet', () => {
|
||||
xit('TODO: write tests');
|
||||
});
|
||||
|
||||
describe('isGlobal', () => {
|
||||
it('identifies global constants', () => {
|
||||
const newDoclet = makeDoclet(['@constant', '@global', '@name foo']);
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import { astNode, Syntax } from '@jsdoc/ast';
|
||||
import { combineDoclets } from '@jsdoc/doclet';
|
||||
import { Doclet } from '@jsdoc/doclet';
|
||||
import * as name from '@jsdoc/name';
|
||||
|
||||
const { getBasename, LONGNAMES } = name;
|
||||
@ -333,7 +333,7 @@ function makeConstructorFinisher(parser) {
|
||||
|
||||
// We prefer the parent doclet because it has the correct kind, longname, and memberof.
|
||||
// The child doclet might or might not have the correct kind, longname, and memberof.
|
||||
combined = combineDoclets(parentDoclet, eventDoclet, parser.env);
|
||||
combined = Doclet.combineDoclets(parentDoclet, eventDoclet, parser.env);
|
||||
parser.addResult(combined);
|
||||
|
||||
parentDoclet.undocumented = eventDoclet.undocumented = true;
|
||||
|
||||
@ -20,7 +20,7 @@ import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
import { Syntax, Walker } from '@jsdoc/ast';
|
||||
import { combineDoclets, Doclet } from '@jsdoc/doclet';
|
||||
import { Doclet } from '@jsdoc/doclet';
|
||||
|
||||
import { attachTo } from '../../../lib/handlers.js';
|
||||
import * as jsdocParser from '../../../lib/parser.js';
|
||||
@ -156,7 +156,7 @@ describe('@jsdoc/parse/lib/parser', () => {
|
||||
const sourceCode = 'javascript:/** @class */function Foo() {}';
|
||||
|
||||
function handler(e) {
|
||||
e.doclet = combineDoclets(e.doclet, new Doclet('', {}, jsdoc.env));
|
||||
e.doclet = Doclet.combineDoclets(e.doclet, new Doclet('', {}, jsdoc.env));
|
||||
e.doclet.foo = 'bar';
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user