Skip to content

Commit 8228dd1

Browse files
Resolve index paths
1 parent 94d35ac commit 8228dd1

1 file changed

Lines changed: 62 additions & 25 deletions

File tree

index.js

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const leadingPathSegmentRegEx = /^(.?.[/\\])+/;
2929

3030
const moduleInfos = {};
3131
const fileNodes = {};
32+
const resolvedPathCache = new Set();
3233

3334
// Without explicit module ids, JSDoc will use the nearest shared parent directory
3435
/** @type {string} */
@@ -71,6 +72,10 @@ function getImplicitModuleRoot() {
7172
}
7273

7374
function getModuleId(modulePath) {
75+
if (moduleInfos[modulePath]) {
76+
return moduleInfos[modulePath].id;
77+
}
78+
7479
// Use moduleRoot if set
7580
if (moduleRootAbsolute) {
7681
return path
@@ -103,13 +108,39 @@ function getModuleId(modulePath) {
103108
.replace(extensionReplaceRegEx, '');
104109
}
105110

111+
/**
112+
* Checks for the existence of `modulePath`, and if it doesn't exist, checks for `modulePath/index.js`.
113+
* @param {string} from The path to the module.
114+
* @param {string} to The path to the module.
115+
* @return {string | null} The resolved path or null if it can't be resolved.
116+
*/
117+
function getResolvedPath(from, to) {
118+
let resolvedPath = path.resolve(from, to);
119+
120+
if (resolvedPathCache.has(resolvedPath) || fs.existsSync(resolvedPath)) {
121+
resolvedPathCache.add(resolvedPath);
122+
123+
return resolvedPath;
124+
}
125+
126+
resolvedPath = resolvedPath.replace(extensionEnsureRegEx, '/index.js');
127+
128+
if (resolvedPathCache.has(resolvedPath) || fs.existsSync(resolvedPath)) {
129+
resolvedPathCache.add(resolvedPath);
130+
131+
return resolvedPath;
132+
}
133+
134+
return null;
135+
}
136+
106137
function getModuleInfo(modulePath, parser) {
138+
if (!modulePath) {
139+
return null;
140+
}
141+
107142
if (!moduleInfos[modulePath]) {
108143
if (!fileNodes[modulePath]) {
109-
if (!fs.existsSync(modulePath)) {
110-
return null;
111-
}
112-
113144
const file = fs.readFileSync(modulePath, 'UTF-8');
114145

115146
fileNodes[modulePath] = parser.astBuilder.build(file, modulePath);
@@ -157,7 +188,7 @@ function getDelimiter(modulePath, symbol) {
157188
return getModuleInfo(modulePath).namedExports[symbol] ? '.' : '~';
158189
}
159190

160-
function withJsExt(filePath) {
191+
function ensureJsExt(filePath) {
161192
return filePath.replace(extensionEnsureRegEx, '.js');
162193
}
163194

@@ -327,23 +358,24 @@ exports.astNodeVisitor = {
327358
lines.push(lines[lines.length - 1]);
328359
const identifier = identifiers[node.superClass.name];
329360
if (identifier) {
330-
const absolutePath = path.resolve(
361+
const absolutePath = getResolvedPath(
331362
path.dirname(currentSourceName),
332-
withJsExt(identifier.value)
363+
ensureJsExt(identifier.value)
333364
);
365+
const moduleInfo = getModuleInfo(absolutePath, parser);
334366

335-
if (getModuleInfo(absolutePath, parser)) {
336-
const moduleId = moduleInfos[absolutePath].id;
337-
367+
if (moduleInfo) {
338368
const exportName = identifier.defaultImport
339369
? getDefaultExportName(absolutePath)
340370
: node.superClass.name;
371+
341372
const delimiter = identifier.defaultImport
342373
? '~'
343374
: getDelimiter(absolutePath, exportName);
375+
344376
lines[lines.length - 2] =
345377
' * @extends ' +
346-
`module:${moduleId.replace(slashRegEx, '/')}${
378+
`module:${moduleInfo.id.replace(slashRegEx, '/')}${
347379
exportName ? delimiter + exportName : ''
348380
}`;
349381
}
@@ -395,23 +427,26 @@ exports.astNodeVisitor = {
395427
replaceAttempt = 0;
396428
}
397429
lastImportPath = importExpression;
398-
const rel = path.resolve(
430+
431+
const rel = getResolvedPath(
399432
path.dirname(currentSourceName),
400-
withJsExt(importSource)
433+
ensureJsExt(importSource)
401434
);
435+
const moduleInfo = getModuleInfo(rel, parser);
402436

403-
if (getModuleInfo(rel, parser)) {
404-
const moduleId = moduleInfos[rel].id;
405-
437+
if (moduleInfo) {
406438
const name =
407439
exportName === 'default'
408440
? getDefaultExportName(rel)
409441
: exportName;
442+
410443
const delimiter =
411444
exportName === 'default' ? '~' : getDelimiter(rel, name);
412-
replacement = `module:${moduleId.replace(slashRegEx, '/')}${
413-
name ? delimiter + name : ''
414-
}`;
445+
446+
replacement = `module:${moduleInfo.id.replace(
447+
slashRegEx,
448+
'/'
449+
)}${name ? delimiter + name : ''}`;
415450
}
416451
}
417452
if (replacement) {
@@ -451,24 +486,26 @@ exports.astNodeVisitor = {
451486
function replace(regex) {
452487
if (regex.test(comment.value)) {
453488
const identifier = identifiers[key];
454-
const absolutePath = path.resolve(
489+
const absolutePath = getResolvedPath(
455490
path.dirname(currentSourceName),
456-
withJsExt(identifier.value)
491+
ensureJsExt(identifier.value)
457492
);
493+
const moduleInfo = getModuleInfo(absolutePath, parser);
458494

459-
if (getModuleInfo(absolutePath, parser)) {
460-
const moduleId = moduleInfos[absolutePath].id;
461-
495+
if (moduleInfo) {
462496
const exportName = identifier.defaultImport
463497
? getDefaultExportName(absolutePath)
464498
: key;
499+
465500
const delimiter = identifier.defaultImport
466501
? '~'
467502
: getDelimiter(absolutePath, exportName);
468-
const replacement = `module:${moduleId.replace(
503+
504+
const replacement = `module:${moduleInfo.id.replace(
469505
slashRegEx,
470506
'/'
471507
)}${exportName ? delimiter + exportName : ''}`;
508+
472509
comment.value = comment.value.replace(
473510
regex,
474511
'@$1' + replacement + '$2'

0 commit comments

Comments
 (0)