Skip to content

fix: keep import edges when file_list holds relative paths - #696

Open
wkeuppens wants to merge 1 commit into
peteromallet:mainfrom
wkeuppens:fix/import-graph-relative-file-list
Open

fix: keep import edges when file_list holds relative paths#696
wkeuppens wants to merge 1 commit into
peteromallet:mainfrom
wkeuppens:fix/import-graph-relative-file-list

Conversation

@wkeuppens

Copy link
Copy Markdown

Problem

ts_build_dep_graph discards every import edge when file_list holds relative paths, so every file in the project is reported as orphaned.

resolve_import returns a path in the same space as the source_file it is handed — a relative file_list therefore produces relative results. graph.py then unconditionally joins those onto the absolute scan_path and tests membership against the relative file_set, so the lookup never matches.

Reproduced in isolation on a real React Router project, same file set both ways:

relative file_list  →   0 edges
absolute file_list  → 142 edges

A db.server.js with 15 importers was reported as having zero.

End to end, scanning that project:

before after
orphaned findings 49 24
Code quality 42.8% 72.0%
total issues 96 76

The remaining 24 are React Router route files and framework entry points, which genuinely have no importers — a separate concern, see below.

This was easy to miss because the existing test happens to cover the one combination that works: an absolute file_list with a scan_path-relative resolver.

Fix

Match the resolved path against the file set in whichever space that set uses, indexing by absolute path. The previous scan_path-relative interpretation is kept as a fallback, so existing callers are unaffected.

Added a regression test for the relative-file_list case. It fails before the change (assert set() == {'src/support.js'}) and passes after.

5811 passed, 5 skipped

Two things I did not fix here, to keep this focused

  1. Dynamic imports are not counted. import_query matches (import_statement ...) only, so await import('./thing') produces no edge. One file in the project above is orphaned for exactly this reason.
  2. File-based routers have no entry patterns. React Router / Next.js route modules and root.jsx / entry.server.jsx are loaded by convention and correctly have zero importers, but are still reported as orphaned. Several languages already have an "entry patterns" concept for this.

Happy to follow up on either if useful.

ts_build_dep_graph discarded every import edge when file_list used relative
paths, which made every file in the project look orphaned.

resolve_import returns a path in the same space as the source_file it is
handed, so a relative file_list produces relative results. The builder then
unconditionally joined those onto the absolute scan_path and tested membership
against the relative file_set, so the lookup never matched.

Reproduced on a real React Router project: same file set, relative file_list
gives 0 edges, absolute gives 142, and a db.server.js with 15 importers was
reported as having zero. Running the scanner over that project, orphaned
findings drop from 49 to 24 and code quality goes from 42.8% to 72.0%.

Resolved paths are now matched against the file set in whichever space it
uses, with the previous scan_path-relative interpretation kept as a fallback.

The existing test only covered an absolute file_list with a scan_path-relative
resolver, which is the one combination that worked. Added a regression test for
the relative case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant