Question: Parallelization of AST Parsing (Plus a few other things)

Author: fforresCreated Apr 29, 2022Updated Dec 16, 2023
Labelsquestion

Summary

Have a few questions

Context

First of all, want to start saying that dependency-cruiser is a great tool. We've been using it for a while at BrexHQ, and has made a few things a lot easier. So thanks for all the work you have done with it.

We are mainly using it to enforce architecture patterns across our codebase, structure migrations and detect what sections of our codebase have the most "violation" in order to prioritize work (Side-note, really helpful to structure long and gradual migrations )

I do have a question (/suggestion/me asking for pointers). Right now for all our main frontend codebase, (which is 100% typescript), it takes the full dependency analysis around 2 minutes to finalize. We are then running a few html-reports over it on CI and reporting the artifacts in a few ways.

2 minutes is not a long time in the grand scheme of things, however in our specific case, we are projecting a lot of growth on that codebase specifically, and we are also looking into a mono-repo structure for a lot of JS code (Which...yeah, that'll be huge )

So enough context, to my question. Been looking into the AST parsing sections of this cod and had a couple of questions:

  • The change from swc to tsc, I'm wondering why it happened? Saw a comment on What were the features you did not see in SWC that made you default for TSC? Is this something you are thinking on revisiting after a while?
  • (I haven't done any measuring, so I'm only assuming) Am I correct in thinking the AST parsing sections of the codebase are the slowest ones? If so, have you looked into parallelization of it?
    • My thought process was that a mixture of workers and shared-memory-arrays could help avoiding the serialization.
    • Maybe for TS you need the whole project to be loaded in memory first? (Unsure if that's what typescript.createSourceFile is doing )
    • I guess, same question goes for other non-tsc extractors.
  • Have you thought on supporting a templating language for rule's comment field?
    • This is mainly to improve DX for engineers that see reports but have little-to-no idea of depenency-cruiser's configuriation, for example, I have seen myself doing some of the following: (see the usage of allowedPaths/rulePathText).
    • ```JS
        const restrictedImportFactory = (path, ruleId, allowedPaths) => {
          // We allow certain imports for this file
          const allowedPaths = [
            ...allowedPaths,
            "src/__generated__/globalTypes.ts",
          ];
        
          const rulePathText = allowedPaths.map(
            (rulePath) => `    - ${rulePath}\n`,
          );
          const id =  slugify(ruleId);
          return {
            // Prevent a directory from reaching into other domains
            name: `module-has-restricted-imports---${id}`,
            comment: `"${path}" is defined to have specifically restricted imports, that means it should NOT import code from any other file than specifically allowed files.
        Allowed imports:
        
        ${rulePathText}`,
            severity,
            from: { path: [path] },
            to: {
              path: "src/.*",
              pathNot: allowedPaths,
              preCompilationOnly: shouldConsiderOnlyTypes,
            },
          };
        };
      
    • For example, something like
    • javascript
         comment: `
             Allowed Rules:
             {{#each rule.to.pathNot as |path pathId| }}
                 - {{ path }}
               {{/each}}
         `

Related to this, had another thoughts/questions, (maybe I can put it on another thread to better discuss? LMK)

One thing I find myself often reaching for, is a way to analyze what a module that I'm depending on is exporting. Like, if we could expose import-specific information, we could be able to do more granular rules (Started thinking of if after #588)

For example, let's say we a file performanceHelpers.ts that exports maaaany things (bunch of types, default export, several named exports) and amongst all of them, a function measureControllerPerformance. If I want to enforce that fileThatNeedsMeasurement.ts imports performanceHelpers.ts, I can do it... However, i cannot enforce that measureControllerPerformance.

(We can argue that we cannot enforce measureControllerPerformance is being used... so what's the point but it gives us users a bit control over their rules)

We could also expose a module's "export information" and be able to create rules that enforce that a xxxController.tsx for example, has to have a specifically named export. etc


Sorry for the wall of text
I had a few thoughts after using this tool for a bit, and wanted to pick your brain, maybe you have thought of all of these already and decided for-against them, or not.

Been getting familiarized with the code, and I'd be more than happy to either help on any of this or tbh, just discuss about it. Didn't want to come across as the "fix your opensource stuff for me" kind of reporter

Either way, thanks a lot for the work you've done here

Environment

  • Version used:
  • Node version:
  • Operating System and version:
  • Link to your project:

Source: sverweij/dependency-cruiser