Repository: sverweij/dependency-cruiser
Pull request #925 (2024-03-23 20:03:40)

refactor(extract): reorganizes so it's easier to expand functionality
## Description, Motivation and Context

- puts the various ast perusers in their own folders
- moves the 'parse' wrappers to their respective folders
- redistributes responsibilities between extract-depencencies module and parser specific code
- names things slightly more standardly, so it's easier to grok what happens (i.e. use _parse_ when parsing things over various other terminology)

Unifying the 'per-parser' interfaces makes it more easy to add a new one/ or make it a plugin mechanism if necessary. Also, by setting up  the interface we can introduce  a mechanism to do other things with AST's, like providing information on the barelly-ness, LoC, NoS.


## How Has This Been Tested?

- [x] green ci

## Types of changes

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Documentation only change
- [x] Refactor (non-breaking change which fixes an issue without changing functionality)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist

- [x] :book:

  - My change doesn't require a documentation update, or ...
  - it _does_ and I have updated it

- [x] :balance_scale:
  - The contribution will be subject to [The MIT license](https://github.com/sverweij/dependency-cruiser/blob/main/LICENSE), and I'm OK with that.
  - The contribution is my own original work.
  - I am ok with the stuff in [**CONTRIBUTING.md**](https://github.com/sverweij/dependency-cruiser/blob/main/.github/CONTRIBUTING.md).


codeclimate[bot]: Code Climate has analyzed commit 1dda7ab7 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/925).

codeclimate[bot]: Code Climate has analyzed commit f7f6a905 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/925).

codeclimate[bot]: Code Climate has analyzed commit c3b1a5aa and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/925).

codeclimate[bot]: Code Climate has analyzed commit d2cb6900 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/925).


Patch:
diff --git a/.dependency-cruiser.json b/.dependency-cruiser.json
index b0816e50..4b06fd69 100644
--- a/.dependency-cruiser.json
+++ b/.dependency-cruiser.json
@@ -128,7 +128,7 @@
       "from": {
         "pathNot": [
           "^src/main/resolve-options/normalize[.]mjs",
-          "^src/extract/(parse|resolve|gather-initial-sources[.]mjs)",
+          "^src/extract/(acorn|tsc|swc|resolve|gather-initial-sources[.]mjs)",
           "^src/(config-utl|cli|cache|utl/find-all-files[.]mjs)",
           "^src/report/dot-webpage/wrap-in-html[.]mjs",
           "^test",
diff --git a/configs/.dependency-cruiser-show-metrics-config.mjs b/configs/.dependency-cruiser-show-metrics-config.mjs
index d3a4ad60..cd2b9e05 100644
--- a/configs/.dependency-cruiser-show-metrics-config.mjs
+++ b/configs/.dependency-cruiser-show-metrics-config.mjs
@@ -42,6 +42,7 @@ export default {
       folder: "node_modules/.cache/dependency-cruiser/show-metrics",
     },
     includeOnly: { path: "^(bin|src)" },
+    prefix: `vscode://file/${process.cwd()}/`,
     reporterOptions: {
       text: {
         highlightFocused: true,
diff --git a/src/extract/ast-extractors/estree-helpers.mjs b/src/extract/acorn/estree-helpers.mjs
similarity index 91%
rename from src/extract/ast-extractors/estree-helpers.mjs
rename to src/extract/acorn/estree-helpers.mjs
index d09db89b..fce0ac2a 100644
--- a/src/extract/ast-extractors/estree-helpers.mjs
+++ b/src/extract/acorn/estree-helpers.mjs
@@ -10,7 +10,7 @@ function firstArgumentIsAString(pArgumentsNode) {
   );
 }
 
-function isPlaceholderlessTemplateLiteral(pArgument) {
+function isPlaceholderLessTemplateLiteral(pArgument) {
   return (
     pArgument.type === "TemplateLiteral" &&
     pArgument.quasis.length === 1 &&
@@ -22,7 +22,7 @@ function firstArgumentIsATemplateLiteral(pArgumentsNode) {
   return (
     Boolean(pArgumentsNode) &&
     pArgumentsNode[0] &&
-    isPlaceholderlessTemplateLiteral(pArgumentsNode[0])
+    isPlaceholderLessTemplateLiteral(pArgumentsNode[0])
   );
 }
 
@@ -70,7 +70,7 @@ export default {
   firstArgumentIsAString,
   firstArgumentIsATemplateLiteral,
   isStringLiteral,
-  isPlaceholderlessTemplateLiteral,
+  isPlaceholderlessTemplateLiteral: isPlaceholderLessTemplateLiteral,
   isMemberCallExpression,
   isCalleeIdentifier,
   isRequireOfSomeSort,
diff --git a/src/extract/ast-extractors/extract-amd-deps.mjs b/src/extract/acorn/extract-amd-deps.mjs
similarity index 100%
rename from src/extract/ast-extractors/extract-amd-deps.mjs
rename to src/extract/acorn/extract-amd-deps.mjs
diff --git a/src/extract/ast-extractors/extract-cjs-deps.mjs b/src/extract/acorn/extract-cjs-deps.mjs
similarity index 100%
rename from src/extract/ast-extractors/extract-cjs-deps.mjs
rename to src/extract/acorn/extract-cjs-deps.mjs
diff --git a/src/extract/ast-extractors/extract-es6-deps.mjs b/src/extract/acorn/extract-es6-deps.mjs
similarity index 100%
rename from src/extract/ast-extractors/extract-es6-deps.mjs
rename to src/extract/acorn/extract-es6-deps.mjs
diff --git a/src/extract/acorn/extract.mjs b/src/extract/acorn/extract.mjs
new file mode 100644
index 00000000..9e2c2336
--- /dev/null
+++ b/src/extract/acorn/extract.mjs
@@ -0,0 +1,26 @@
+import { join } from "node:path";
+import extractES6Deps from "./extract-es6-deps.mjs";
+import extractCommonJSDeps from "./extract-cjs-deps.mjs";
+import extractAMDDeps from "./extract-amd-deps.mjs";
+import parse from "./parse.mjs";
+
+export function extract(
+  { baseDir, moduleSystems, exoticRequireStrings },
+  pFileName,
+  pTranspileOptions,
+) {
+  let lDependencies = [];
+  const lAST = parse.getASTCached(join(baseDir, pFileName), pTranspileOptions);
+
+  if (moduleSystems.includes("cjs")) {
+    extractCommonJSDeps(lAST, lDependencies, "cjs", exoticRequireStrings);
+  }
+  if (moduleSystems.includes("es6")) {
+    extractES6Deps(lAST, lDependencies);
+  }
+  if (moduleSystems.includes("amd")) {
+    extractAMDDeps(lAST, lDependencies, exoticRequireStrings);
+  }
+
+  return lDependencies;
+}
diff --git a/src/extract/parse/to-javascript-ast.mjs b/src/extract/acorn/parse.mjs
similarity index 100%
rename from src/extract/parse/to-javascript-ast.mjs
rename to src/extract/acorn/parse.mjs
diff --git a/src/extract/clear-caches.mjs b/src/extract/clear-caches.mjs
index 8a654bed..e6a5dbb4 100644
--- a/src/extract/clear-caches.mjs
+++ b/src/extract/clear-caches.mjs
@@ -1,15 +1,15 @@
-import toTypescriptAST from "./parse/to-typescript-ast.mjs";
-import toJavascriptAST from "./parse/to-javascript-ast.mjs";
-import toSwcAST from "./parse/to-swc-ast.mjs";
+import tscParse from "./tsc/parse.mjs";
+import acornParse from "./acorn/parse.mjs";
+import swcParse from "./swc/parse.mjs";
 import { clearCache as externalModuleHelpers_clearCache } from "./resolve/external-module-helpers.mjs";
 import { clearCache as getManifest_clearCache } from "./resolve/get-manifest.mjs";
 import { clearCache as resolveAMD_clearCache } from "./resolve/resolve-amd.mjs";
 import { clearCache as resolve_clearCache } from "./resolve/resolve.mjs";
 
 export default function clearCaches() {
-  toTypescriptAST.clearCache();
-  toJavascriptAST.clearCache();
-  toSwcAST.clearCache();
+  tscParse.clearCache();
+  acornParse.clearCache();
+  swcParse.clearCache();
   externalModuleHelpers_clearCache();
   getManifest_clearCache();
   resolveAMD_clearCache();
diff --git a/src/extract/get-dependencies.mjs b/src/extract/extract-dependencies.mjs
similarity index 61%
rename from src/extract/get-dependencies.mjs
rename to src/extract/extract-dependencies.mjs
index 8c262602..2246a680 100644
--- a/src/extract/get-dependencies.mjs
+++ b/src/extract/extract-dependencies.mjs
@@ -1,117 +1,51 @@
 import { join, extname, dirname } from "node:path";
 import uniqBy from "lodash/uniqBy.js";
+import { extract as acornExtract } from "./acorn/extract.mjs";
+import {
+  extract as tscExtract,
+  shouldUse as tscShouldUse,
+} from "./tsc/extract.mjs";
+import {
+  extract as swcExtract,
+  shouldUse as swcShouldUse,
+} from "./swc/extract.mjs";
 import resolve from "./resolve/index.mjs";
-import extractES6Deps from "./ast-extractors/extract-es6-deps.mjs";
-import extractCommonJSDeps from "./ast-extractors/extract-cjs-deps.mjs";
-import extractAMDDeps from "./ast-extractors/extract-amd-deps.mjs";
-import extractTypeScriptDeps from "./ast-extractors/extract-typescript-deps.mjs";
-import extractSwcDeps from "./ast-extractors/extract-swc-deps.mjs";
-import toJavascriptAST from "./parse/to-javascript-ast.mjs";
-import toTypescriptAST from "./parse/to-typescript-ast.mjs";
-import toSwcAST from "./parse/to-swc-ast.mjs";
 import {
   detectPreCompilationNess,
   extractModuleAttributes,
 } from "./helpers.mjs";
 import { intersects } from "#utl/array-util.mjs";
 
-function extractFromSwcAST({ baseDir, exoticRequireStrings }, pFileName) {
-  return extractSwcDeps(
-    toSwcAST.getASTCached(join(baseDir, pFileName)),
-    exoticRequireStrings,
-  );
-}
-
-function extractFromTypeScriptAST(
-  { baseDir, exoticRequireStrings },
-  pFileName,
-  pTranspileOptions,
-) {
-  return extractTypeScriptDeps(
-    toTypescriptAST.getASTCached(join(baseDir, pFileName), pTranspileOptions),
-    exoticRequireStrings,
-  );
-}
-
-function isTypeScriptCompatible(pFileName) {
-  return [
-    ".ts",
-    ".tsx",
-    ".mts",
-    ".cts",
-    ".js",
-    ".mjs",
-    ".cjs",
-    ".vue",
-  ].includes(extname(pFileName));
-}
-
-function shouldUseTsc({ tsPreCompilationDeps, parser }, pFileName) {
-  return (
-    (tsPreCompilationDeps || parser === "tsc") &&
-    toTypescriptAST.isAvailable() &&
-    isTypeScriptCompatible(pFileName)
-  );
-}
-
-function shouldUseSwc({ parser }, pFileName) {
-  return (
-    parser === "swc" &&
-    toSwcAST.isAvailable() &&
-    isTypeScriptCompatible(pFileName)
-  );
-}
-
-function extractFromJavaScriptAST(
-  { baseDir, moduleSystems, exoticRequireStrings },
-  pFileName,
-  pTranspileOptions,
-) {
-  let lDependencies = [];
-  const lAST = toJavascriptAST.getASTCached(
-    join(baseDir, pFileName),
-    pTranspileOptions,
-  );
-
-  if (moduleSystems.includes("cjs")) {
-    extractCommonJSDeps(lAST, lDependencies, "cjs", exoticRequireStrings);
-  }
-  if (moduleSystems.includes("es6")) {
-    extractES6Deps(lAST, lDependencies);
-  }
-  if (moduleSystems.includes("amd")) {
-    extractAMDDeps(lAST, lDependencies, exoticRequireStrings);
-  }
-
-  return lDependencies;
-}
-
-function extractWithSwc(pCruiseOptions, pFileName) {
-  return extractFromSwcAST(pCruiseOptions, pFileName).filter(
-    ({ moduleSystem }) => pCruiseOptions.moduleSystems.includes(moduleSystem),
-  );
-}
-
 function extractWithTsc(pCruiseOptions, pFileName, pTranspileOptions) {
-  let lDependencies = extractFromTypeScriptAST(
-    pCruiseOptions,
-    pFileName,
-    pTranspileOptions,
-  ).filter(({ moduleSystem }) =>
-    pCruiseOptions.moduleSystems.includes(moduleSystem),
-  );
+  let lDependencies = tscExtract(pCruiseOptions, pFileName, pTranspileOptions);
 
   if (pCruiseOptions.tsPreCompilationDeps === "specify") {
     lDependencies = detectPreCompilationNess(
       lDependencies,
-      extractFromJavaScriptAST(pCruiseOptions, pFileName, pTranspileOptions),
+      acornExtract(pCruiseOptions, pFileName, pTranspileOptions),
     );
   }
   return lDependencies;
 }
 
 /**
- *
+ * @param {IStrictCruiseOptions} pCruiseOptions
+ * @param {string} pFileName
+ * @returns {(IStrictCruiseOptions, string, any) => import("../../types/cruise-result.mjs").IDependency[]}
+ */
+function determineExtractionFunction(pCruiseOptions, pFileName) {
+  let lExtractionFunction = acornExtract;
+
+  if (swcShouldUse(pCruiseOptions, pFileName)) {
+    lExtractionFunction = swcExtract;
+  } else if (tscShouldUse(pCruiseOptions, pFileName)) {
+    lExtractionFunction = extractWithTsc;
+  }
+
+  return lExtractionFunction;
+}
+
+/**
  * @param {import('../../types/dependency-cruiser.js').IStrictCruiseOptions} pCruiseOptions
  * @param {string} pFileName
  * @param {any} pTranspileOptions
@@ -122,21 +56,15 @@ function extractDependencies(pCruiseOptions, pFileName, pTranspileOptions) {
   let lDependencies = [];
 
   if (!pCruiseOptions.extraExtensionsToScan.includes(extname(pFileName))) {
-    if (shouldUseSwc(pCruiseOptions, pFileName)) {
-      lDependencies = extractWithSwc(pCruiseOptions, pFileName);
-    } else if (shouldUseTsc(pCruiseOptions, pFileName)) {
-      lDependencies = extractWithTsc(
-        pCruiseOptions,
-        pFileName,
-        pTranspileOptions,
-      );
-    } else {
-      lDependencies = extractFromJavaScriptAST(
-        pCruiseOptions,
-        pFileName,
-        pTranspileOptions,
-      );
-    }
+    const lExtractionFunction = determineExtractionFunction(
+      pCruiseOptions,
+      pFileName,
+    );
+    lDependencies = lExtractionFunction(
+      pCruiseOptions,
+      pFileName,
+      pTranspileOptions,
+    );
   }
 
   return lDependencies.map((pDependency) => ({
diff --git a/src/extract/helpers.mjs b/src/extract/helpers.mjs
index 94fd9fa7..16da4075 100644
--- a/src/extract/helpers.mjs
+++ b/src/extract/helpers.mjs
@@ -1,3 +1,5 @@
+import { extname } from "node:path";
+
 export function dependenciesEqual(pLeftDependency) {
   // As we're using this to compare (typescript) pre-compilation dependencies
   // with post-compilation dependencies we do not consider the moduleSystem.
@@ -77,6 +79,23 @@ export function extractModuleAttributes(pString) {
  */
 export function stripQueryParameters(pFilenameString) {
   // url.parse(pFilenameString).pathname did this quite admirably, but it's
-  // deprecated, hence this fonky RE replace. And accompanying unit test :-/
+  // deprecated, hence this funky RE replace. And accompanying unit test :-/
   return pFilenameString.replace(/\?.+$/, "");
 }
+/**
+ * Returns true if the file name has a TypeScript compatible extension
+ * @param {string} pFileName
+ * @returns {boolean}
+ */
+export function isTypeScriptCompatible(pFileName) {
+  return [
+    ".ts",
+    ".tsx",
+    ".mts",
+    ".cts",
+    ".js",
+    ".mjs",
+    ".cjs",
+    ".vue",
+  ].includes(extname(pFileName));
+}
diff --git a/src/extract/index.mjs b/src/extract/index.mjs
index 1698f944..ecd7d1b2 100644
--- a/src/extract/index.mjs
+++ b/src/extract/index.mjs
@@ -1,4 +1,4 @@
-import getDependencies from "./get-dependencies.mjs";
+import extractDependencies from "./extract-dependencies.mjs";
 import gatherInitialSources from "./gather-initial-sources.mjs";
 import clearCaches from "./clear-caches.mjs";
 import { bus } from "#utl/bus.mjs";
@@ -15,7 +15,7 @@ function extractRecursive(
   pVisited.add(pFileName);
   const lDependencies =
     pCruiseOptions.maxDepth <= 0 || pDepth < pCruiseOptions.maxDepth
-      ? getDependencies(
+      ? extractDependencies(
           pFileName,
           pCruiseOptions,
           pResolveOptions,
diff --git a/src/extract/ast-extractors/swc-dependency-visitor.mjs b/src/extract/swc/dependency-visitor.mjs
similarity index 100%
rename from src/extract/ast-extractors/swc-dependency-visitor.mjs
rename to src/extract/swc/dependency-visitor.mjs
diff --git a/src/extract/ast-extractors/extract-swc-deps.mjs b/src/extract/swc/extract-swc-deps.mjs
similarity index 86%
rename from src/extract/ast-extractors/extract-swc-deps.mjs
rename to src/extract/swc/extract-swc-deps.mjs
index de810558..5b3cc50b 100644
--- a/src/extract/ast-extractors/extract-swc-deps.mjs
+++ b/src/extract/swc/extract-swc-deps.mjs
@@ -1,4 +1,4 @@
-import SwcDependencyVisitor from "./swc-dependency-visitor.mjs";
+import SwcDependencyVisitor from "./dependency-visitor.mjs";
 
 /**
  * @param {import('@swc/core').ModuleItem[]} pSwcAST
diff --git a/src/extract/swc/extract.mjs b/src/extract/swc/extract.mjs
new file mode 100644
index 00000000..646341ea
--- /dev/null
+++ b/src/extract/swc/extract.mjs
@@ -0,0 +1,20 @@
+import { join } from "node:path/posix";
+import { isTypeScriptCompatible } from "../helpers.mjs";
+import extractSwcDeps from "./extract-swc-deps.mjs";
+import parse from "./parse.mjs";
+
+export function shouldUse({ parser }, pFileName) {
+  return (
+    parser === "swc" && parse.isAvailable() && isTypeScriptCompatible(pFileName)
+  );
+}
+
+export function extract(
+  { baseDir, exoticRequireStrings, moduleSystems },
+  pFileName,
+) {
+  return extractSwcDeps(
+    parse.getASTCached(join(baseDir, pFileName)),
+    exoticRequireStrings,
+  ).filter(({ moduleSystem }) => moduleSystems.includes(moduleSystem));
+}
diff --git a/src/extract/parse/to-swc-ast.mjs b/src/extract/swc/parse.mjs
similarity index 100%
rename from src/extract/parse/to-swc-ast.mjs
rename to src/extract/swc/parse.mjs
diff --git a/src/extract/transpile/index.mjs b/src/extract/transpile/index.mjs
index 7f798d70..f253baf1 100644
--- a/src/extract/transpile/index.mjs
+++ b/src/extract/transpile/index.mjs
@@ -35,7 +35,7 @@ export const EXTENSION2WRAPPER = new Map([
   [".cjsx", coffeeVanillaWrap],
 ]);
 
-const BABELEABLE_EXTENSIONS = [
+const BABEL_ABLE_EXTENSIONS = [
   ".js",
   ".cjs",
   ".mjs",
@@ -47,7 +47,7 @@ const BABELEABLE_EXTENSIONS = [
 
 /**
  * returns the babel wrapper if there's a babelConfig in the transpiler
- * options for babeleable extensions (javascript and typescript - currently
+ * options for babel-  able extensions (javascript and typescript - currently
  * not configurable)
  *
  * returns the wrapper module configured for the extension pExtension if
@@ -63,7 +63,7 @@ const BABELEABLE_EXTENSIONS = [
 export function getWrapper(pExtension, pTranspilerOptions) {
   if (
     Object.keys(pTranspilerOptions?.babelConfig ?? {}).length > 0 &&
-    BABELEABLE_EXTENSIONS.includes(pExtension)
+    BABEL_ABLE_EXTENSIONS.includes(pExtension)
   ) {
     return babelWrap;
   }
diff --git a/src/extract/ast-extractors/extract-typescript-deps.mjs b/src/extract/tsc/extract-typescript-deps.mjs
similarity index 100%
rename from src/extract/ast-extractors/extract-typescript-deps.mjs
rename to src/extract/tsc/extract-typescript-deps.mjs
diff --git a/src/extract/tsc/extract.mjs b/src/extract/tsc/extract.mjs
new file mode 100644
index 00000000..f6536416
--- /dev/null
+++ b/src/extract/tsc/extract.mjs
@@ -0,0 +1,23 @@
+import { join } from "node:path";
+import { isTypeScriptCompatible } from "../helpers.mjs";
+import extractTypeScriptDeps from "./extract-typescript-deps.mjs";
+import parse from "./parse.mjs";
+
+export function shouldUse({ tsPreCompilationDeps, parser }, pFileName) {
+  return (
+    (tsPreCompilationDeps || parser === "tsc") &&
+    parse.isAvailable() &&
+    isTypeScriptCompatible(pFileName)
+  );
+}
+
+export function extract(
+  { baseDir, exoticRequireStrings, moduleSystems },
+  pFileName,
+  pTranspileOptions,
+) {
+  return extractTypeScriptDeps(
+    parse.getASTCached(join(baseDir, pFileName), pTranspileOptions),
+    exoticRequireStrings,
+  ).filter(({ moduleSystem }) => moduleSystems.includes(moduleSystem));
+}
diff --git a/types/options.d.mts b/types/options.d.mts
index b0f82484..9321ef5b 100644
--- a/types/options.d.mts
+++ b/types/options.d.mts
@@ -18,6 +18,7 @@ export type ProgressType =
   | "performance-log"
   | "ndjson"
   | "none";
+export type ParserType = "acorn" | "tsc" | "swc";
 
 export interface ITsConfig {
   fileName?: string;
@@ -261,7 +262,7 @@ export interface ICruiseOptions {
    * typically sort out what the best parser for the job is out of the ones
    * available
    */
-  parser?: "acorn" | "tsc" | "swc";
+  parser?: ParserType;
 
   /**
    * Options used in module resolution that for dependency-cruiser's


Test patch:
diff --git a/src/extract/parse/to-typescript-ast.mjs b/src/extract/tsc/parse.mjs
similarity index 100%
rename from src/extract/parse/to-typescript-ast.mjs
rename to src/extract/tsc/parse.mjs
diff --git a/test/extract/ast-extractors/extract-amd-deps.spec.mjs b/test/extract/acorn/extract-amd-deps.spec.mjs
similarity index 91%
rename from test/extract/ast-extractors/extract-amd-deps.spec.mjs
rename to test/extract/acorn/extract-amd-deps.spec.mjs
index c4750f4b..18b0f688 100644
--- a/test/extract/ast-extractors/extract-amd-deps.spec.mjs
+++ b/test/extract/acorn/extract-amd-deps.spec.mjs
@@ -1,6 +1,6 @@
 import { deepEqual } from "node:assert/strict";
-import extractAMDDeps from "#extract/ast-extractors/extract-amd-deps.mjs";
-import { getASTFromSource } from "#extract/parse/to-javascript-ast.mjs";
+import extractAMDDeps from "#extract/acorn/extract-amd-deps.mjs";
+import { getASTFromSource } from "#extract/acorn/parse.mjs";
 
 const extractAMD = (
   pJavaScriptSource,
@@ -13,7 +13,7 @@ const extractAMD = (
     pExoticRequireStrings,
   );
 
-describe("[U] ast-extractors/extract-AMD-deps", () => {
+describe("[U] acorn/extract-AMD-deps", () => {
   it("amd define", () => {
     let lDeps = [];
 
diff --git a/test/extract/ast-extractors/extract-cjs-deps.spec.mjs b/test/extract/acorn/extract-cjs-deps.spec.mjs
similarity index 92%
rename from test/extract/ast-extractors/extract-cjs-deps.spec.mjs
rename to test/extract/acorn/extract-cjs-deps.spec.mjs
index ef4ef6a5..3c823712 100644
--- a/test/extract/ast-extractors/extract-cjs-deps.spec.mjs
+++ b/test/extract/acorn/extract-cjs-deps.spec.mjs
@@ -1,6 +1,6 @@
 import { deepEqual } from "node:assert/strict";
-import extractcommonJSDeps from "#extract/ast-extractors/extract-cjs-deps.mjs";
-import { getASTFromSource } from "#extract/parse/to-javascript-ast.mjs";
+import extractcommonJSDeps from "#extract/acorn/extract-cjs-deps.mjs";
+import { getASTFromSource } from "#extract/acorn/parse.mjs";
 
 const extractcommonJS = (
   pJavaScriptSource,
@@ -14,7 +14,7 @@ const extractcommonJS = (
     pExoticRequireStrings,
   );
 
-describe("[U] ast-extractors/extract-cjs-deps", () => {
+describe("[U] acorn/extract-cjs-deps", () => {
   it("require with in an assignment", () => {
     let lDeps = [];
 
diff --git a/test/extract/ast-extractors/extract-es6-deps.spec.mjs b/test/extract/acorn/extract-es6-deps.spec.mjs
similarity index 95%
rename from test/extract/ast-extractors/extract-es6-deps.spec.mjs
rename to test/extract/acorn/extract-es6-deps.spec.mjs
index 2e9f34c0..3be8c132 100644
--- a/test/extract/ast-extractors/extract-es6-deps.spec.mjs
+++ b/test/extract/acorn/extract-es6-deps.spec.mjs
@@ -1,6 +1,6 @@
 import { deepEqual } from "node:assert/strict";
-import extractES6Deps from "#extract/ast-extractors/extract-es6-deps.mjs";
-import { getASTFromSource } from "#extract/parse/to-javascript-ast.mjs";
+import extractES6Deps from "#extract/acorn/extract-es6-deps.mjs";
+import { getASTFromSource } from "#extract/acorn/parse.mjs";
 
 const extractES6 = (pJavaScriptSource, pDependencies, pExtension = ".js") =>
   extractES6Deps(
@@ -8,7 +8,7 @@ const extractES6 = (pJavaScriptSource, pDependencies, pExtension = ".js") =>
     pDependencies,
   );
 
-describe("[U] ast-extractors/extract-ES6-deps", () => {
+describe("[U] acorn/extract-ES6-deps", () => {
   it("dynamic imports of strings", () => {
     let lDeps = [];
 
diff --git a/test/extract/ast-extractors/all-shapes-of-import-export.md b/test/extract/all-shapes-of-import-export.md
similarity index 100%
rename from test/extract/ast-extractors/all-shapes-of-import-export.md
rename to test/extract/all-shapes-of-import-export.md
diff --git a/test/extract/get-dependencies.amd.spec.mjs b/test/extract/get-dependencies.amd.spec.mjs
index 8b85340d..384e73a5 100644
--- a/test/extract/get-dependencies.amd.spec.mjs
+++ b/test/extract/get-dependencies.amd.spec.mjs
@@ -7,7 +7,7 @@ import { createRequireJSON } from "../backwards.utl.mjs";
 import { runFixture } from "./run-get-dependencies-fixture.utl.mjs";
 import normalizeResolveOptions from "#main/resolve-options/normalize.mjs";
 import { normalizeCruiseOptions } from "#main/options/normalize.mjs";
-import getDependencies from "#extract/get-dependencies.mjs";
+import extractDependencies from "#extract/extract-dependencies.mjs";
 
 const __dirname = fileURLToPath(new URL(".", import.meta.url));
 const requireJSON = createRequireJSON(import.meta.url);
@@ -53,7 +53,7 @@ describe("[I] extract/getDependencies - AMD - with bangs", () => {
     );
 
     deepEqual(
-      getDependencies(
+      extractDependencies(
         "test/extract/__mocks__/amd-bangs/root_one.js",
         lOptions,
         lResolveOptions,
@@ -70,7 +70,7 @@ describe("[I] extract/getDependencies - AMD - with bangs", () => {
     );
 
     deepEqual(
-      getDependencies(
+      extractDependencies(
         "test/extract/__mocks__/amd-bangs/simplified-commonjs-wrapper.js",
         lOptions,
         lResolveOptions,
diff --git a/test/extract/get-dependencies.cjs.spec.mjs b/test/extract/get-dependencies.cjs.spec.mjs
index ff57e09c..760f71fc 100644
--- a/test/extract/get-dependencies.cjs.spec.mjs
+++ b/test/extract/get-dependencies.cjs.spec.mjs
@@ -6,7 +6,7 @@ import symlinkDir from "symlink-dir";
 import { createRequireJSON } from "../backwards.utl.mjs";
 import normalizeResolveOptions from "#main/resolve-options/normalize.mjs";
 import { normalizeCruiseOptions } from "#main/options/normalize.mjs";
-import getDependencies from "#extract/get-dependencies.mjs";
+import extractDependencies from "#extract/extract-dependencies.mjs";
 
 const __dirname = fileURLToPath(new URL(".", import.meta.url));
 const requireJSON = createRequireJSON(import.meta.url);
@@ -32,7 +32,7 @@ function runFixture(pFixture, pParser = "acorn") {
 
   it(`${pFixture.title} (with '${pParser}' as parser)`, async () => {
     deepEqual(
-      getDependencies(
+      extractDependencies(
         pFixture.input.fileName,
         normalizeCruiseOptions(lOptions),
         await normalizeResolveOptions(
@@ -79,7 +79,7 @@ describe("[I] extract/getDependencies - CommonJS - with bangs", () => {
     );
 
     deepEqual(
-      getDependencies(
+      extractDependencies(
         "test/extract/__mocks__/cjs-bangs/index.js",
         lOptions,
         lResolveOptions,
@@ -109,7 +109,7 @@ describe("[I] extract/getDependencies - CommonJS - with bangs", () => {
     );
 
     deepEqual(
-      getDependencies(
+      extractDependencies(
         "test/extract/__mocks__/cjs-multi-bangs/index.js",
         lOptions,
         lResolveOptions,
diff --git a/test/extract/get-dependencies.odds-and-ends.spec.mjs b/test/extract/get-dependencies.odds-and-ends.spec.mjs
index 914e5a94..d69bd4a9 100644
--- a/test/extract/get-dependencies.odds-and-ends.spec.mjs
+++ b/test/extract/get-dependencies.odds-and-ends.spec.mjs
@@ -3,7 +3,7 @@ import { createRequireJSON } from "../backwards.utl.mjs";
 import { runFixture } from "./run-get-dependencies-fixture.utl.mjs";
 import normalizeResolveOptions from "#main/resolve-options/normalize.mjs";
 import { normalizeCruiseOptions } from "#main/options/normalize.mjs";
-import getDependencies from "#extract/get-dependencies.mjs";
+import extractDependencies from "#extract/extract-dependencies.mjs";
 
 const requireJSON = createRequireJSON(import.meta.url);
 
@@ -27,7 +27,7 @@ describe("[I] extract/getDependencies - Error scenarios - ", () => {
 
     doesNotThrow(
       () =>
-        getDependencies(
+        extractDependencies(
           "test/extract/__mocks__/syntax-error.js",
           lOptions,
           lResolveOptions,
@@ -37,7 +37,11 @@ describe("[I] extract/getDependencies - Error scenarios - ", () => {
   });
   it("Raises an exception on non-existing files", () => {
     throws(() => {
-      getDependencies("non-existing-file.md", normalizeCruiseOptions({}), {});
+      extractDependencies(
+        "non-existing-file.md",
+        normalizeCruiseOptions({}),
+        {},
+      );
     }, /Extracting dependencies ran afoul of...\n\n {2}ENOENT: no such file or directory, open /);
   });
 });
@@ -56,7 +60,7 @@ describe("[I] extract/getDependencies - even when require gets non-string argume
 
   it("Just skips require(481)", () => {
     equal(
-      getDependencies(
+      extractDependencies(
         "./test/extract/__mocks__/cjs-require-non-strings/require-a-number.js",
         lOptions,
         lResolveOptions,
@@ -67,7 +71,7 @@ describe("[I] extract/getDependencies - even when require gets non-string argume
 
   it("Just skips require(a function)", () => {
     equal(
-      getDependencies(
+      extractDependencies(
         "./test/extract/__mocks__/cjs-require-non-strings/require-a-function.js",
         lOptions,
         lResolveOptions,
@@ -78,7 +82,7 @@ describe("[I] extract/getDependencies - even when require gets non-string argume
 
   it("Just skips require(an iife)", () => {
     equal(
-      getDependencies(
+      extractDependencies(
         "./test/extract/__mocks__/cjs-require-non-strings/require-an-iife.js",
         normalizeCruiseOptions({}),
         {},
@@ -99,7 +103,7 @@ describe("[I] extract/getDependencies - include", () => {
     );
 
     deepEqual(
-      getDependencies(
+      extractDependencies(
         "./test/extract/__mocks__/include/src/index.js",
         lOptions,
         lResolveOptions,
@@ -116,7 +120,7 @@ describe("[I] extract/getDependencies - include", () => {
     );
 
     deepEqual(
-      getDependencies(
+      extractDependencies(
         "./test/extract/__mocks__/include/src/index.js",
         lOptions,
         lResolveOptions,
@@ -146,7 +150,7 @@ describe("[I] extract/getDependencies - include", () => {
     );
 
     deepEqual(
-      getDependencies(
+      extractDependencies(
         "./test/extract/__mocks__/include/src/index.js",
         lOptions,
         lResolveOptions,
@@ -188,7 +192,7 @@ describe("[I] extract/getDependencies - include", () => {
     );
 
     deepEqual(
-      getDependencies(
+      extractDependencies(
         "./test/extract/__mocks__/exotic-require/index.js",
         lOptions,
         lResolveOptions,
@@ -222,7 +226,7 @@ describe("[I] extract/getDependencies - include", () => {
     );
 
     deepEqual(
-      getDependencies(
+      extractDependencies(
         "./test/extract/__mocks__/extra-extensions/not-parsed-when-in-extra-extensions.yolo",
         lOptions,
         lResolveOptions,
@@ -241,7 +245,7 @@ describe("[I] extract/getDependencies - include", () => {
     );
 
     deepEqual(
-      getDependencies(
+      extractDependencies(
         "./test/extract/__mocks__/specifyTsPreCompilationDeps/index.ts",
         lOptions,
         lResolveOptions,
diff --git a/test/extract/parse/to-javascript-ast.spec.mjs b/test/extract/parse/to-javascript-ast.spec.mjs
index da406f17..90204a20 100644
--- a/test/extract/parse/to-javascript-ast.spec.mjs
+++ b/test/extract/parse/to-javascript-ast.spec.mjs
@@ -1,6 +1,6 @@
 import { equal } from "node:assert/strict";
 import get from "lodash/get.js";
-import { getASTFromSource } from "#extract/parse/to-javascript-ast.mjs";
+import { getASTFromSource } from "#extract/acorn/parse.mjs";
 
 const TSCONFIG_CONSTANTS = {
   ESNEXT: 99,
diff --git a/test/extract/run-get-dependencies-fixture.utl.mjs b/test/extract/run-get-dependencies-fixture.utl.mjs
index 6aefdab3..d19b9dc5 100644
--- a/test/extract/run-get-dependencies-fixture.utl.mjs
+++ b/test/extract/run-get-dependencies-fixture.utl.mjs
@@ -1,7 +1,7 @@
 import { deepEqual } from "node:assert/strict";
 import { normalizeCruiseOptions } from "#main/options/normalize.mjs";
 import normalizeResolveOptions from "#main/resolve-options/normalize.mjs";
-import getDependencies from "#extract/get-dependencies.mjs";
+import extractDependencies from "#extract/extract-dependencies.mjs";
 
 /* eslint-disable mocha/no-exports */
 export function runFixture(pFixture, pParser = "acorn") {
@@ -21,7 +21,7 @@ export function runFixture(pFixture, pParser = "acorn") {
 
   it(`${pFixture.title} (with '${pParser}' as parser)`, async () => {
     deepEqual(
-      getDependencies(
+      extractDependencies(
         pFixture.input.fileName,
         normalizeCruiseOptions(lOptions),
         await normalizeResolveOptions(
diff --git a/test/extract/ast-extractors/extract-with-swc-commonjs.spec.mjs b/test/extract/swc/extract-with-swc-commonjs.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-with-swc-commonjs.spec.mjs
rename to test/extract/swc/extract-with-swc-commonjs.spec.mjs
diff --git a/test/extract/ast-extractors/extract-with-swc-dynamic-imports.spec.mjs b/test/extract/swc/extract-with-swc-dynamic-imports.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-with-swc-dynamic-imports.spec.mjs
rename to test/extract/swc/extract-with-swc-dynamic-imports.spec.mjs
diff --git a/test/extract/ast-extractors/extract-with-swc-exotics.spec.mjs b/test/extract/swc/extract-with-swc-exotics.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-with-swc-exotics.spec.mjs
rename to test/extract/swc/extract-with-swc-exotics.spec.mjs
diff --git a/test/extract/ast-extractors/extract-with-swc-exports.spec.mjs b/test/extract/swc/extract-with-swc-exports.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-with-swc-exports.spec.mjs
rename to test/extract/swc/extract-with-swc-exports.spec.mjs
diff --git a/test/extract/ast-extractors/extract-with-swc-imports.spec.mjs b/test/extract/swc/extract-with-swc-imports.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-with-swc-imports.spec.mjs
rename to test/extract/swc/extract-with-swc-imports.spec.mjs
diff --git a/test/extract/ast-extractors/extract-with-swc-type-imports.spec.mjs b/test/extract/swc/extract-with-swc-type-imports.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-with-swc-type-imports.spec.mjs
rename to test/extract/swc/extract-with-swc-type-imports.spec.mjs
diff --git a/test/extract/ast-extractors/extract-with-swc.utl.mjs b/test/extract/swc/extract-with-swc.utl.mjs
similarity index 52%
rename from test/extract/ast-extractors/extract-with-swc.utl.mjs
rename to test/extract/swc/extract-with-swc.utl.mjs
index ae5610d5..d98d4442 100644
--- a/test/extract/ast-extractors/extract-with-swc.utl.mjs
+++ b/test/extract/swc/extract-with-swc.utl.mjs
@@ -1,5 +1,5 @@
-import extractSwcDependencies from "#extract/ast-extractors/extract-swc-deps.mjs";
-import { getASTFromSource } from "#extract/parse/to-swc-ast.mjs";
+import extractSwcDependencies from "#extract/swc/extract-swc-deps.mjs";
+import { getASTFromSource } from "#extract/swc/parse.mjs";
 
 export default (pTypesScriptSource, pExoticRequireStrings = []) =>
   extractSwcDependencies(
diff --git a/test/extract/ast-extractors/__mocks__/typescript2.8-union-types-ast.json b/test/extract/tsc/__mocks__/typescript2.8-union-types-ast.json
similarity index 100%
rename from test/extract/ast-extractors/__mocks__/typescript2.8-union-types-ast.json
rename to test/extract/tsc/__mocks__/typescript2.8-union-types-ast.json
diff --git a/test/extract/ast-extractors/extract-typescript-commonjs.spec.mjs b/test/extract/tsc/extract-typescript-commonjs.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-typescript-commonjs.spec.mjs
rename to test/extract/tsc/extract-typescript-commonjs.spec.mjs
diff --git a/test/extract/ast-extractors/extract-typescript-dynamic-imports.spec.mjs b/test/extract/tsc/extract-typescript-dynamic-imports.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-typescript-dynamic-imports.spec.mjs
rename to test/extract/tsc/extract-typescript-dynamic-imports.spec.mjs
diff --git a/test/extract/ast-extractors/extract-typescript-exotics.spec.mjs b/test/extract/tsc/extract-typescript-exotics.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-typescript-exotics.spec.mjs
rename to test/extract/tsc/extract-typescript-exotics.spec.mjs
diff --git a/test/extract/ast-extractors/extract-typescript-exports.spec.mjs b/test/extract/tsc/extract-typescript-exports.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-typescript-exports.spec.mjs
rename to test/extract/tsc/extract-typescript-exports.spec.mjs
diff --git a/test/extract/ast-extractors/extract-typescript-imports.spec.mjs b/test/extract/tsc/extract-typescript-imports.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-typescript-imports.spec.mjs
rename to test/extract/tsc/extract-typescript-imports.spec.mjs
diff --git a/test/extract/ast-extractors/extract-typescript-others.spec.mjs b/test/extract/tsc/extract-typescript-others.spec.mjs
similarity index 89%
rename from test/extract/ast-extractors/extract-typescript-others.spec.mjs
rename to test/extract/tsc/extract-typescript-others.spec.mjs
index 1b569ccf..e2bc8b7b 100644
--- a/test/extract/ast-extractors/extract-typescript-others.spec.mjs
+++ b/test/extract/tsc/extract-typescript-others.spec.mjs
@@ -1,7 +1,7 @@
 import { deepEqual } from "node:assert/strict";
 import { readFileSync } from "node:fs";
 import { fileURLToPath } from "node:url";
-import extractTypescriptFromAST from "#extract/ast-extractors/extract-typescript-deps.mjs";
+import extractTypescriptFromAST from "#extract/tsc/extract-typescript-deps.mjs";
 
 describe("[U] ast-extractors/extract-typescript - others", () => {
   // see issue #167 - union types on tsc 2.8 and before don't deliver/
diff --git a/test/extract/ast-extractors/extract-typescript-triple-slash-directives.spec.mjs b/test/extract/tsc/extract-typescript-triple-slash-directives.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-typescript-triple-slash-directives.spec.mjs
rename to test/extract/tsc/extract-typescript-triple-slash-directives.spec.mjs
diff --git a/test/extract/ast-extractors/extract-typescript-type-imports-and-exports.spec.mjs b/test/extract/tsc/extract-typescript-type-imports-and-exports.spec.mjs
similarity index 100%
rename from test/extract/ast-extractors/extract-typescript-type-imports-and-exports.spec.mjs
rename to test/extract/tsc/extract-typescript-type-imports-and-exports.spec.mjs
diff --git a/test/extract/ast-extractors/extract-typescript.utl.mjs b/test/extract/tsc/extract-typescript.utl.mjs
similarity index 52%
rename from test/extract/ast-extractors/extract-typescript.utl.mjs
rename to test/extract/tsc/extract-typescript.utl.mjs
index 570b2d85..3da404d9 100644
--- a/test/extract/ast-extractors/extract-typescript.utl.mjs
+++ b/test/extract/tsc/extract-typescript.utl.mjs
@@ -1,5 +1,5 @@
-import extractTypescript from "#extract/ast-extractors/extract-typescript-deps.mjs";
-import { getASTFromSource } from "#extract/parse/to-typescript-ast.mjs";
+import extractTypescript from "#extract/tsc/extract-typescript-deps.mjs";
+import { getASTFromSource } from "#extract/tsc/parse.mjs";
 
 export default (pTypesScriptSource, pExoticRequireStrings = []) =>
   extractTypescript(