Commit graph

1 commit

Author SHA1 Message Date
henry201605
36ca096e75
feat(ingestion): Java Spring route annotation → Route node extraction (#2078)
* feat(ingestion): add Java Spring route annotation → Route node extraction

Previously, GitNexus only supported Route node generation for JS/TS
ecosystems (Express, Next.js, Fastify, etc.) and Python (FastAPI, Flask).
Java Spring's annotation-based routing (@RequestMapping, @GetMapping,
@PostMapping, etc.) was only supported at the group contract layer
(http-patterns/java.ts) for cross-repo matching, but NOT at the
ingestion layer for generating graph Route nodes.

This commit adds ingestion-layer support:

1. JAVA_QUERIES (tree-sitter-queries.ts):
   - Added method-level annotation captures (@GetMapping, @PostMapping,
     @PutMapping, @DeleteMapping, @PatchMapping) → @decorator captures
   - Added class-level @RequestMapping → @decorator capture (prefix)
   - Supports both positional ("/path") and named (path="/path",
     value="/path") annotation argument forms

2. parse-worker.ts:
   - Java class-level @RequestMapping is detected and stored as a prefix
     (not pushed as a standalone Route)
   - After per-file capture processing, the prefix is applied to all
     method-level routes in the same file via the existing
     ExtractedDecoratorRoute.prefix field
   - The routes phase (normalizeExtractedRoutePath) handles the prefix
     joining, producing final URLs like /api/users/list

3. Tests:
   - Unit test (worker-backed): 4 cases covering prefix joining,
     bare routes, class-level exclusion, multi-file isolation
   - Integration test (full pipeline): 6 cases covering end-to-end
     Route node + HANDLES_ROUTE edge generation

Closes the feature gap where `route_map`, `shape_check`, and
`api_impact` MCP tools returned empty results for Java Spring projects.

* chore(autofix): apply prettier + eslint fixes via /autofix command

* fix: address review findings — extract spring.ts module, fix PatchMapping, multi-class support

Addresses all P2 findings from tri-review:

1. **Architecture**: Extracted Spring route logic from parse-worker.ts into
   a dedicated `route-extractors/spring.ts` module (matching the pattern
   of `laravel.ts` and `fastapi-router-bindings.ts`). parse-worker now
   has a single dispatch line — no language-specific logic inline.

2. **PatchMapping bug**: Added `'PatchMapping'` to `ROUTE_DECORATOR_NAMES`
   (was silently dropped before).

3. **Multi-class bug**: The new `extractSpringRoutes` walks each class
   declaration independently with its own prefix — no more single-scalar
   `javaClassPrefix` last-wins issue.

4. **Test hygiene**: Unit tests now import `extractSpringRoutes` directly
   (no dist build / worker pool dependency). Tests run in all tiers.

5. **Removed JAVA_QUERIES decorator patterns**: The Spring extractor does
   its own AST walk, so the tree-sitter query captures for Java annotations
   are no longer needed (avoids duplicate route emission).

Additional test coverage:
- Multi-class in one file with independent prefixes
- @PatchMapping support
- Named annotation args (path= and value=) on class-level @RequestMapping

* refactor: move Spring route extraction to LanguageProvider hook

Addresses the second review comment: instead of an inline
`if (language === SupportedLanguages.Java)` dispatch in parse-worker,
the Spring route extraction is now wired through a new optional
`extractDecoratorRoutes` hook on LanguageProviderConfig.

- Added `extractDecoratorRoutes` to LanguageProviderConfig interface
- Java provider registers `extractSpringRoutes` as its implementation
- parse-worker calls `provider.extractDecoratorRoutes?.()` generically
- Removed direct import of spring.ts from parse-worker

This keeps parse-worker fully language-agnostic — no language names
appear in the dispatch path for route extraction.

* refactor: rewrite spring.ts with tree-sitter captures, fix inline imports

Addresses all 4 inline review comments:

1. Rewrote spring.ts to use a single predicate-free Parser.Query
   (same pattern as group-layer JAVA_ROUTE_ANNOTATION_PATTERNS).
   Two-phase loop: first pass collects class prefixes by node.id,
   second pass resolves method routes via findEnclosingClass.
   No more manual DFS / recursion.

2-3. Moved inline import(...) type references in language-provider.ts
     to proper top-level imports (Parser, ExtractedDecoratorRoute).

4. Covered by #1 — recursive helpers removed entirely.

Added 3 extra test cases: non-route named args filtering,
prefix isolation across mixed classes, line number accuracy.

* refactor: extract shared Spring route primitives + add parity test

Addresses review follow-up on #2078:

- Extract the primitives shared by the ingestion (route-extractors/spring.ts)
  and group (http-patterns/java.ts) Spring extractors into a new
  route-extractors/spring-shared.ts: METHOD_ANNOTATION_TO_HTTP,
  findEnclosingClass, isRouteMemberKey, and a safe unquoteSpringLiteral.
  Both extractors now import from it (group -> ingestion, the layer-correct
  direction) so the shared semantics can't drift apart.

- Replace spring.ts's local unquote() with the safer unquoteSpringLiteral
  (returns null for non-string nodes instead of assuming a quoted string).

- Add test/unit/spring-route-extractor-parity.test.ts: runs one shared Spring
  fixture through both extractors and asserts they surface the same provider
  method/path combinations.

The broader HttpRouteExtractor source-scan optimization is tracked in #2138.

---------

Co-authored-by: henry <zhangwei2017@unipus.cn>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-06-10 09:44:56 +01:00