From b60df463f4dd140d33af9d5ddd1cc572951cb584 Mon Sep 17 00:00:00 2001 From: Jeff Williams Date: Sat, 11 Jan 2025 16:18:46 -0800 Subject: [PATCH] refactor(jsdoc-doclet): minor cleanup --- packages/jsdoc-doclet/lib/doclet-store.js | 21 ++++------ packages/jsdoc-doclet/lib/doclet.js | 48 +++++++++++------------ 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/packages/jsdoc-doclet/lib/doclet-store.js b/packages/jsdoc-doclet/lib/doclet-store.js index 2bfa117a..53bc5d97 100644 --- a/packages/jsdoc-doclet/lib/doclet-store.js +++ b/packages/jsdoc-doclet/lib/doclet-store.js @@ -183,8 +183,10 @@ export class DocletStore { } #toggleVisibility(doclet, { isVisible, setFnName }) { + const action = isVisible ? 'delete' : 'add'; + this.doclets[setFnName](doclet); - this.unusedDoclets[isVisible ? 'delete' : 'add'](doclet); + this.unusedDoclets[action](doclet); } // Updates `this.allDocletsByLongname` _only_. @@ -216,7 +218,8 @@ export class DocletStore { doclet, { property: eventProp, oldValue: oldKey, newValue: newKey, isVisible, wasVisible } ) { - const map = this[DocletStore.#propertyToMapName.get(requestedProp)]; + const mapName = DocletStore.#propertyToMapName.get(requestedProp); + const map = this[mapName]; // If the event didn't specify the property name that we're interested in, then ignore the new // key; it doesn't apply to this property. Instead, get the key from the doclet. @@ -260,16 +263,8 @@ export class DocletStore { } #updateWatchableProperties(doclet, docletInfo) { - const { - isGlobal, - isVisible, - newDoclet, - newValue, - oldValue, - property, - visibilityChanged, - wasVisible, - } = docletInfo; + const { isVisible, newDoclet, newValue, oldValue, property, visibilityChanged, wasVisible } = + docletInfo; // `access` only affects visibility, which is handled above, so we ignore it here. if (visibilityChanged || property === 'augments') { @@ -283,7 +278,7 @@ export class DocletStore { this.#updateSetProperty('implements', doclet, docletInfo); } if (visibilityChanged || property === 'kind') { - this.#toggleGlobal(doclet, { isGlobal, isVisible }); + this.#toggleGlobal(doclet, docletInfo); this.#updateMapProperty('kind', doclet, docletInfo); } if (visibilityChanged || property === 'listens') { diff --git a/packages/jsdoc-doclet/lib/doclet.js b/packages/jsdoc-doclet/lib/doclet.js index a25998bd..e84b45f1 100644 --- a/packages/jsdoc-doclet/lib/doclet.js +++ b/packages/jsdoc-doclet/lib/doclet.js @@ -73,7 +73,7 @@ WATCHABLE_PROPS.sort(); function fakeMeta(node) { return { - type: node ? node.type : null, + type: node?.type, node: node, }; } @@ -105,7 +105,7 @@ function codeToKind(code) { } else if (code.type === Syntax.ExportSpecifier) { // this value will often be an Identifier for a variable, which isn't very useful kind = codeToKind(fakeMeta(node.local)); - } else if (node && node.parent && isFunction(node.parent)) { + } else if (isFunction(node?.parent)) { kind = 'param'; } @@ -245,7 +245,7 @@ function resolve(doclet) { } // The name and memberof are identical and refer to a module, like `@name module:foo` with // `@memberof module:foo`. - else if (name && name === memberof && name.indexOf(MODULE_NAMESPACE) === 0) { + else if (name && name === memberof && name.startsWith(MODULE_NAMESPACE)) { about = toParts(name, forcedMemberof); } // The name and memberof are identical, like `@name foo` with `@memberof foo`. @@ -293,7 +293,7 @@ function resolve(doclet) { if (leadingScope) { doclet.scope = PUNC_TO_SCOPE[leadingScope]; doclet.name = doclet.name.substr(1); - } else if (doclet.meta.code && doclet.meta.code.name) { + } else if (doclet.meta.code?.name) { // HACK: Handle cases where an ES 2015 class is a static memberof something else, and // the class has instance members. In these cases, we have to detect the instance // members' scope by looking at the meta info. There's almost certainly a better way to @@ -370,7 +370,7 @@ function clone(source, target, properties) { * @param {module:@jsdoc/doclet.Doclet} target - The doclet to which properties will be copied. * @param {Array.} exclude - The names of properties to exclude from copying. */ -function copyMostProperties(primary, secondary, target, exclude) { +function copyPropsWithExcludelist(primary, secondary, target, exclude) { // Get names of primary and secondary properties that don't contain the value `undefined`. const primaryPropertyNames = Object.getOwnPropertyNames(primary).filter( (name) => !_.isUndefined(primary[name]) @@ -399,15 +399,11 @@ function copyMostProperties(primary, secondary, target, exclude) { * @param {module:@jsdoc/doclet.Doclet} target - The doclet to which properties will be copied. * @param {Array.} include - The names of properties to copy. */ -function copySpecificProperties(primary, secondary, target, include) { +function copyPropsWithIncludelist(primary, secondary, target, include) { include.forEach((property) => { - if (Object.hasOwn(primary, property) && primary[property] && primary[property].length) { + if (Object.hasOwn(primary, property) && primary[property]?.length) { target[property] = _.cloneDeep(primary[property]); - } else if ( - Object.hasOwn(secondary, property) && - secondary[property] && - secondary[property].length - ) { + } else if (Object.hasOwn(secondary, property) && secondary[property]?.length) { target[property] = _.cloneDeep(secondary[property]); } }); @@ -423,15 +419,15 @@ function copySpecificProperties(primary, secondary, target, include) { * doclets. */ export function combineDoclets(primary, secondary) { - const copyMostPropertiesExclude = ['env', 'params', 'properties', 'undocumented']; - const copySpecificPropertiesInclude = ['params', 'properties']; - const target = new Doclet('', null, secondary.env); + const excludelist = ['env', 'params', 'properties', 'undocumented']; + const includelist = ['params', 'properties']; + const target = Doclet.emptyDoclet(secondary.env); // First, copy most properties to the target doclet. - copyMostProperties(primary, secondary, target, copyMostPropertiesExclude); + 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. - copySpecificProperties(primary, secondary, target, copySpecificPropertiesInclude); + copyPropsWithIncludelist(primary, secondary, target, includelist); return target; } @@ -519,7 +515,7 @@ Doclet = class { this.memberof = undefined; } - if (!this.kind && this.meta && this.meta.code) { + if (!this.kind && this.meta?.code) { this.addTag('kind', codeToKind(this.meta.code)); } @@ -528,7 +524,7 @@ Doclet = class { } // add in any missing param names - if (this.params && this.meta && this.meta.code && this.meta.code.paramnames) { + if (this.params && this.meta?.code?.paramnames) { for (let i = 0, l = this.params.length; i < l; i++) { if (!this.params[i].name) { this.params[i].name = this.meta.code.paramnames[i] || ''; @@ -547,7 +543,7 @@ Doclet = class { const tagDef = this.#dictionary.lookUp(title); const newTag = new Tag(title, text, this.meta, this.env); - if (tagDef && tagDef.onTagged) { + if (tagDef?.onTagged) { tagDef.onTagged(this, newTag); } @@ -580,7 +576,11 @@ Doclet = class { // + Doclets that claim to belong to an anonymous scope // + "Undocumented" doclets (usually code with no JSDoc comment; might also include some odd // artifacts of the parsing process) - if (this.ignore === true || this.memberof === '' || this.undocumented === true) { + if ( + this.ignore === true || + this.memberof === LONGNAMES.ANONYMOUS || + this.undocumented === true + ) { return false; } @@ -694,8 +694,8 @@ Doclet = class { filepath = getFilepath(this); errorMessage = - `The scope name "${scope}" is not recognized. Use one of the ` + - `following values: ${ALL_SCOPE_NAMES}`; + `The scope name "${scope}" is not recognized. Use one of the following values: ` + + `${ALL_SCOPE_NAMES}`; if (filepath) { errorMessage += ` (Source file: ${filepath})`; } @@ -808,7 +808,7 @@ Doclet = class { * * @namespace */ - this.meta.code = this.meta.code || {}; + this.meta.code ??= {}; if (meta.id) { this.meta.code.id = meta.id; }