Skip to content

fix(resolve): probe .mts/.cts extensions for extension-less imports - #2564

Merged
carlos-alm merged 2 commits into
mainfrom
fix/issue-2464
Aug 18, 2026
Merged

fix(resolve): probe .mts/.cts extensions for extension-less imports#2564
carlos-alm merged 2 commits into
mainfrom
fix/issue-2464

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

Discovered while fixing #2299 (the .mjs.mts/.cjs.cts emitted-extension remap). A separate, distinct code path — resolving an extension-less relative specifier like import './foo' by probing a fixed list of candidate extensions — never tries .mts/.cts in either engine, even though both engines otherwise recognize and parse .mts/.cts files (#2073).

  • TS: the extension-probing loop in resolveImportPathJS (src/domain/graph/resolve.ts) tried ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.py', '.pyi', ...index variants] — no .mts/.cts.
  • Rust: probe_known_extensions's EXTENSIONS constant (crates/codegraph-core/src/domain/graph/resolve.rs) had the identical list, same gap.

So import './foo' resolving to a source file foo.mts/foo.cts (as opposed to the emitted-specifier form import './foo.mjs', which #2299 covers) fell through to proximity-based confidence instead of an import-aware match.

Fix

Added .mts/.cts to both extension lists, in both engines, placed alongside .ts/.tsx to keep TypeScript-family extensions grouped (matching the existing ordering convention where TS extensions precede JS extensions in the list).

Test plan

  • New tests in tests/unit/resolve.test.ts: extension-less specifier resolves to .mts, extension-less specifier resolves to .cts — reusing the exact fixture files (src/esm/util.mts, src/cjs/legacy.cts) Import resolution doesn't remap .mjs/.cjs specifiers to .mts/.cts sources #2299's own remap tests already set up, but exercising the extension-probing loop directly (no extension on the specifier at all) rather than EMIT_EXTENSION_REMAPS
  • New tests in crates/codegraph-core/src/domain/graph/resolve.rs mirroring both cases
  • Revert-verified on both engines: temporarily removed .mts/.cts from each list and confirmed the corresponding new tests fail with the exact pre-fix output (resolves to the bare specifier, no extension); restored and confirmed green
  • cargo test --lib (full suite) — 1096 passed (up from 1094, +2 new)
  • cargo clippy --lib -- -D warnings — clean
  • npm test (full suite) — 339 files, 5449 passed
  • npx tsc --noEmit — clean
  • npm run lint — clean

Closes #2464

Discovered while fixing #2299 (the .mjs->.mts/.cjs->.cts emitted-extension
remap). A separate, distinct code path -- resolving an extension-less
relative specifier like `import './foo'` by probing a fixed list of
candidate extensions -- never tried .mts/.cts in either engine, even
though both engines otherwise recognize and parse .mts/.cts files (#2073).

Adds .mts/.cts to the extension-probing list in resolveImportPathJS
(src/domain/graph/resolve.ts) and probe_known_extensions's EXTENSIONS
constant (crates/codegraph-core/src/domain/graph/resolve.rs), keeping the
two lists in sync per the dual-engine parity requirement. Placed alongside
.ts/.tsx to keep TypeScript-family extensions grouped, matching the
existing ordering convention.

docs check acknowledged -- bug fix only, no new language support, feature,
or architectural change to document.

Impact: 1 functions changed, 19 affected
@github-actions

Copy link
Copy Markdown
Contributor

Heads up: this PR references #2073 without a closing keyword (Closes #N / Fixes #N). If this PR fully resolves #2073, update the description so the issue auto-closes on merge — otherwise disregard this comment.

@greptile-apps

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR extends extension-less import resolution to recognize .mts and .cts files in both resolver engines and completes the previously missing directory-index behavior.

  • Adds direct .mts and .cts extension probes in the TypeScript and Rust resolvers.
  • Adds /index.mts and /index.cts probes in both implementations.
  • Adds mirrored tests for direct-file and directory-index resolution.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
crates/codegraph-core/src/domain/graph/resolve.rs Adds .mts/.cts direct and index probes to the native resolver with coverage for all four cases.
src/domain/graph/resolve.ts Keeps the TypeScript resolver in parity by adding matching direct and directory-index probes.
tests/unit/resolve.test.ts Adds filesystem fixtures and regression tests for extension-less .mts/.cts file and directory imports.

Reviews (2): Last reviewed commit: "fix(resolve): also probe /index.mts and ..." | Re-trigger Greptile

Comment thread src/domain/graph/resolve.ts
@github-actions

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

1 functions changed19 callers affected across 4 files

  • resolveImportPathJS in src/domain/graph/resolve.ts:1202 (19 transitive callers)

Follow-up to Greptile review on this same PR: the direct .mts/.cts
candidates alone don't cover the directory-index convention
(import './dir' -> dir/index.mts), which every other extension already
in this list (.ts, .tsx, .js) supports via its own /index.<ext> entry.

Adds /index.mts and /index.cts to both engines' extension-probing lists,
alongside the existing /index.ts and /index.tsx entries.

docs check acknowledged -- bug fix only, no new language support, feature,
or architectural change to document.

Impact: 1 functions changed, 19 affected
@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm
carlos-alm merged commit 32fa923 into main Aug 18, 2026
30 checks passed
@carlos-alm
carlos-alm deleted the fix/issue-2464 branch August 18, 2026 08:25
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extension-less import resolution never probes .mts/.cts (only .ts/.tsx/.js/.jsx/.mjs)

1 participant