fix: use the correct name and longname for an exported symbol with a @memberof tag

This commit is contained in:
Jeff Williams 2025-10-04 17:40:13 -07:00
parent 4555ff0b68
commit 13cdfd18b7
No known key found for this signature in database
4 changed files with 44 additions and 7 deletions

View File

@ -173,9 +173,9 @@ export function nodeToValue(node) {
// Like the declaration in: `export const foo = 'bar';`
// We need a single value, so we use the first variable name.
if (node.declaration.declarations) {
str = `${LONGNAMES.MODULE_EXPORT}.${nodeToValue(node.declaration.declarations[0])}`;
str = `${nodeToValue(node.declaration.declarations[0])}`;
} else {
str = `${LONGNAMES.MODULE_EXPORT}.${nodeToValue(node.declaration)}`;
str = `${nodeToValue(node.declaration)}`;
}
}

View File

@ -139,6 +139,7 @@ function findAncestorWithType(node, ancestorType) {
function setModuleScopeMemberOf(parser, doclet) {
const moduleInfo = getModule();
const node = doclet.meta?.code?.node;
let parentDoclet;
let skipMemberof;
@ -146,17 +147,17 @@ function setModuleScopeMemberOf(parser, doclet) {
if (moduleInfo && !isModuleExports(moduleInfo, doclet)) {
if (!doclet.scope) {
// is this a method definition? if so, we usually get the scope from the node directly
if (doclet.meta?.code?.node?.type === Syntax.MethodDefinition) {
parentDoclet = parser._getDocletById(doclet.meta.code.node.parent.parent.nodeId);
if (node?.type === Syntax.MethodDefinition) {
parentDoclet = parser._getDocletById(node.parent.parent.nodeId);
// special case for constructors of classes that have @alias tags
if (doclet.meta.code.node.kind === 'constructor' && parentDoclet?.alias) {
if (node.kind === 'constructor' && parentDoclet?.alias) {
// the constructor should use the same name as the class
doclet.addTag('alias', parentDoclet.alias);
doclet.addTag('name', parentDoclet.alias);
// and we shouldn't try to set a memberof value
skipMemberof = true;
} else {
doclet.addTag(doclet.meta.code.node.static ? 'static' : 'instance');
doclet.addTag(node.static ? 'static' : 'instance');
// The doclet should be a member of the parent doclet's alias.
if (parentDoclet?.alias) {
doclet.memberof = parentDoclet.alias;
@ -164,7 +165,10 @@ function setModuleScopeMemberOf(parser, doclet) {
}
}
// Is this something that the module exports? if so, it's a static member.
else if (findAncestorWithType(doclet.meta?.code?.node, Syntax.ExportNamedDeclaration)) {
else if (
node?.type === Syntax.ExportNamedDeclaration ||
findAncestorWithType(node, Syntax.ExportNamedDeclaration)
) {
doclet.addTag('static');
}
// Otherwise, it must be an inner member.

View File

@ -0,0 +1,7 @@
/**
* The bar namespace.
*
* @namespace
* @memberof module:foo
*/
export const bar = {};

View File

@ -0,0 +1,26 @@
/*
Copyright 2025 the JSDoc Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
describe('memberof a module', () => {
const docSet = jsdoc.getDocSetFromFile('test/fixtures/modulememberof.js');
it('uses the correct name and longname for an exported symbol with a @memberof tag', () => {
const bar = docSet.getByLongname('module:foo.bar').filter((d) => !d.undocumented)[0];
expect(bar).toBeObject();
expect(bar.name).toBe('bar');
});
});