jsdoc-tsimport-plugin icon indicating copy to clipboard operation
jsdoc-tsimport-plugin copied to clipboard

Importing modules by folder throws EISDIR

Open bryan-hoang opened this issue 2 years ago • 0 comments

VS Code supports resolving import("./folder") style typedefs in JSDoc comments, but the plugin assumes that the basename of the path will be a file rather than a folder.

A minimal repro of the error:

echo '{}' > package.json
npm add --save-dev jsdoc jsdoc-tsimport-plugin
npm pkg set scripts.jsdoc='jsdoc -c jsdoc.config.json index.js'
echo '{ "plugins": ["node_modules/jsdoc-tsimport-plugin/index.js"] }' > jsdoc.config.json
echo '/** @typedef {import("./src").foo} foo */' > index.js
mkdir src
cat > src/index.js <<EOL
/** @typedef {string} foo */
module.exports = {};
EOL
npm run jsdoc

The key part being import("./src") instead of import("./src/index") or import("./src/index.js").

Error output
Error: EISDIR: illegal operation on a directory, read
    at Object.readSync (node:fs:772:3)
    at tryReadSync (node:fs:441:20)
    at Object.readFileSync (node:fs:495:19)
    at getFileInfo (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc-tsimport-plugin/index.js:82:6)
    at getModuleId (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc-tsimport-plugin/index.js:159:10)
    at /home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc-tsimport-plugin/index.js:138:26
    at String.replace (<anonymous>)
    at /home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc-tsimport-plugin/index.js:136:24
    at String.replace (<anonymous>)
    at Parser.beforeParse (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc-tsimport-plugin/index.js:134:23)
    at Parser.emit (node:events:514:28)
    at Parser._parseSourceCode (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc/lib/jsdoc/src/parser.js:288:18)
    at Parser.parse (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc/lib/jsdoc/src/parser.js:202:22)
    at module.exports.cli.parseFiles (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc/cli.js:365:46)
    at module.exports.cli.main (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc/cli.js:234:18)
    at module.exports.cli.runCommand (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc/cli.js:186:9) {
  errno: -21,
  syscall: 'read',
  code: 'EISDIR'
}
Suggestion for a potential fix
diff --git i/index.js w/index.js
index 4d8309e..7731951 100644
--- i/index.js
+++ w/index.js
@@ -160,7 +160,7 @@ function getModuleId(filename, relImportPath) {
   }

   const p = relPath(filename, relImportPath);
-  const absPath = inferExtension(p);
+  const absPath = require.resolve(p);
   return getFileInfo(absPath).moduleId;
 }

@@ -177,30 +177,6 @@ function relPath(root, relative) {
     path.join(path.dirname(root), relative));
 }

-/**
- * Given a filename, if there is no extension, scan the files for the
- * most likely match.
- *
- * @param {string} filename The filename with or without an
- * extension to resolve.
- * @returns {string} The path to the resolved file.
- */
-function inferExtension(filename) {
-  const filenameNor = path.normalize(filename);
-  const ext = path.extname(filenameNor);
-  if (ext && fs.existsSync(filename)) return ext;
-  const files = fs.readdirSync(path.dirname(filenameNor));
-
-  const name = path.basename(filenameNor);
-  const foundFile = files.find((iFile) => {
-    if (noExtension(iFile) == name) {
-      return true;
-    }
-  });
-  if (foundFile === undefined) return filename;
-  return path.join(path.dirname(filenameNor), foundFile);
-}
-
 /**
  * Strips the extension off of a filename.
  *

Replacing inferExtension with require.resolve to use the built-in module system to figure out the file being required could be a way to get around having to re-implement the module file resolution algorithm that VS Code uses. It works with CJS modules, but I haven't tried it with ES modules.

I could live with switching to importing ./src/index, but it'll be annoying having to inform teammates about this restriction in the future when it looks fine for them in VS Code.

bryan-hoang avatar Sep 22 '23 18:09 bryan-hoang