Add TypeScript import path resolver with tsconfig paths support - #642
Add TypeScript import path resolver with tsconfig paths support#642alex4o wants to merge 4 commits into
Conversation
Use the tsx tree-sitter grammar for .tsx files (the typescript grammar misparses JSX as type assertions). Override _find_calls() in TypescriptJSXTreeSitterParser to capture jsx_opening_element and jsx_self_closing_element nodes, filtering to PascalCase names only. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve TS/JS import specifiers to absolute file paths during indexing so that Module nodes use resolved paths instead of raw specifiers. This makes File->Module->File traversal work correctly for relative and alias imports. - Create ts_import_resolver.py handling relative, alias (tsconfig paths), and bare specifier imports with extension/index file resolution - Fix lang routing bug: include 'typescript' and 'typescriptjsx' alongside 'javascript' in the import handling branch of graph_builder - Parse tsconfig.json once per indexing run (supports baseUrl, paths, extends, comments, trailing commas) - Store raw_specifier on Module nodes for debugging - Add test fixture files with tsconfig paths aliases (@utils/*, @models/*, @shared/*, @app/*) and corresponding source files - Add 50 unit + integration tests covering resolver, tsconfig parsing, and end-to-end resolution with real TS parser output Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ts_import_resolver for resolving TypeScript path aliases from tsconfig.json - Track JSX component usage as CALLS relationships in graph builder - Add TSX test fixtures and e2e test for TypeScript indexing - Update sample TypeScript project with TSX components Amp-Thread-ID: https://ampcode.com/threads/T-019c6303-d1c9-763f-b9ab-08be8da73f8a Co-authored-by: Amp <amp@ampcode.com>
|
@alex4o is attempting to deploy a commit to the shashankss1205's projects Team on Vercel. A member of the Team first needs to authorize it. |
…icity - Resolve baseUrl-only imports (e.g. "utils/foo") before dismissing as bare specifiers - Replace naive regex comment stripping with state-aware parser to avoid corrupting strings containing "//" - Sort tsconfig path patterns by specificity (longest first) to match TypeScript behavior - Remove debug log from graph_builder.py - Improve E2E test assertions to parse JSON values instead of fragile string checks - Restore .cgcignore file Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
👋 Thanks for contributing to CodeGraphContext! Since this PR was opened, |
|
Triage update: this tsconfig-paths resolver is still something we want — TS monorepos with path aliases currently lose those import edges. The branch has drifted a long way from main (the indexing pipeline was restructured into tools/indexing/), so it needs a rebase before it can be reviewed. @alex4o are you still interested in bringing it up to date? If not, we'll treat this as a design reference and reimplement against the current pipeline. Thanks for the substantial work either way! 🙏 |
|
Sry I don't have the time to contribute to this anymore |
|
I spent a solid session trying to land this and did not get it over the line. Recording everything so the effort is not lost — my working attempt is pushed to This is a port, not a rebase
So What is definitely good
$ pytest tests/unit/parsers/test_ts_import_resolver.py -q
35 passedDriven directly it does exactly what it claims: What I could not finishI wired the resolver into Relative specifiers resolve; tsconfig aliases do not, even though the same aliases resolve when the resolver is called directly. My hypothesis was that Partial resolution is arguably worse than none: it leaves One thing worth knowing, since it looks alarmingRegenerating the TS golden with your fixtures shows CALLS 389 → 262 and HEURISTIC_CALLS 0 → 141. I chased that specifically, because that exact signature is why I abandoned a different import fix in #1526. It is not caused by the resolver. I isolated it by regenerating with the fixtures present but the wiring removed — every edge count was identical: So the shift comes from the new fixture files themselves. Most likely they introduce same-named symbols across files, making previously-unambiguous calls ambiguous — which may be correct behaviour, but is worth a look, since it is a large swing for a fixture addition. Suggested path
Happy to review whenever you pick it up. |
|
Thanks for this, and sorry it's sat so long — the tsconfig path resolution is genuinely useful and What changed on
The good news is that the actual substance of your PR — If you rebase onto current |
What
Index
<JSXComponent />tags as call-sites so component usage shows up in the code graph.Resolve TS/TSX import paths (aliases from
tsconfig.jsonand relative imports) to absolute file paths so two files importing the same module share oneModulenode instead of creating duplicates.Why
Without this:
<Layout>or<Button />in.tsxfiles are invisible to the graph — noCALLSedge is created.import { capitalize } from "@utils/string-helpers"andimport { capitalize } from "./utils/string-helpers"produce two separateModulenodes for the same file, fragmenting the graph.How
JSX call-site indexing
TypescriptJSXTreeSitterParser(extends the TS parser) with a_find_callsoverride that runs a tree-sitter query forjsx_opening_element/jsx_self_closing_element.<div>) is ignored..tsxfiles now use the newtypescriptjsxparser instead of reusingtypescript.TS import resolution
ts_import_resolver.pymodule with:parse_tsconfig_paths(project_root)— readstsconfig.json(handles//comments, trailing commas, one level ofextends), returnsbaseUrl+pathsmap.resolve_ts_import(specifier, importing_file, ...)— resolves in order: relative → alias → baseUrl → bare (returnsNonefor npm packages)._try_resolve_file(base)— tries exact path →.ts/.tsx/.js/.jsx→index.{ts,tsx,js,jsx}.graph_builder.pycallsparse_tsconfig_pathsonce per indexing run, then passes the config toadd_file_to_graphwhere each import is resolved beforeMERGE (m:Module {name: $resolved_path}).Modulenodes now also storeraw_specifier(the original import string) for debugging.Example
Testing
test_ts_import_resolver.py, 25 tests):_try_resolve_file, relative imports, bare specifiers, alias imports,tsconfig.jsonparsing (comments, trailing commas, extends).test_ts_import_resolver_integration.py, 14 tests): parse the real fixtureapp-service.tswith tree-sitter, then resolve every import against the fixture'stsconfig.json.test_ts_indexing.py): index the full TS fixture into the DB and verify via Cypher that alias imports resolve to absolute paths, bare specifiers stay raw, JSX component calls are detected, and no duplicateModulenodes exist.sample_project_typescriptwithtsconfig.jsonpaths,.tsxcomponents (App.tsx,Layout.tsx,Button.tsx), alias-imported modules (string-helpers,math-helpers,user-model,constants,logger), andapp-service.tsexercising all import patterns.