Skip to content

feat(java): add HTTP consumer contract extraction#1872

Merged
magyargergo merged 7 commits into
abhigyanpatwari:mainfrom
ShiningXu:fix/issue-1870-java-http-consumers
May 29, 2026
Merged

feat(java): add HTTP consumer contract extraction#1872
magyargergo merged 7 commits into
abhigyanpatwari:mainfrom
ShiningXu:fix/issue-1870-java-http-consumers

Conversation

@ShiningXu

@ShiningXu ShiningXu commented May 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Part of #1870. Adds low-complexity Java HTTP consumer extraction for common literal client patterns without taking on dynamic URL resolution.

What changed

  • Detects RestTemplate.exchange("/path", HttpMethod.X, ...) consumers.
  • Detects Java WebClient short-form chains like webClient.post().uri("/path").
  • Detects OpenFeign interfaces annotated with @FeignClient plus Spring MVC method annotations.
  • Detects literal Java HttpRequest.newBuilder().uri(URI.create("/path")).GET/POST/... request construction.
  • Detects literal Apache HttpClient HttpGet / HttpPost / HttpPut / HttpDelete / HttpPatch request construction.
  • Uses AST annotation checks for Feign interfaces so @FeignClient text in strings/comments is not misclassified.
  • Keeps these patterns source-scan only and avoids scope-resolution / dynamic URL analysis.

Validation

  • npx vitest run test/unit/group/http-route-extractor.test.ts — 70 passed
  • npx vitest run test/unit/group — 550 passed
  • npx tsc --noEmit
  • ./dist/cli/index.js detect-changes --scope unstaged --repo GitNexus — risk low, 0 affected processes
  • pre-commit hook — formatting, eslint, gitnexus typecheck passed

Follow-up

Dynamic URL assembly, wrapper tracking, fully-qualified route annotation extraction, and broader interface-controller support are intentionally left for #1873.

@vercel

vercel Bot commented May 28, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the NexusCore Team on Vercel.

A member of the Team first needs to authorize it.

@ShiningXu ShiningXu marked this pull request as ready for review May 28, 2026 08:56
@ShiningXu ShiningXu changed the title [codex] Fix Java HTTP consumer contract extraction Fix Java HTTP consumer contract extraction May 28, 2026
@ShiningXu ShiningXu changed the title Fix Java HTTP consumer contract extraction feat(java): add HTTP consumer contract extraction May 28, 2026
@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

CI Report

All checks passed

Pipeline Status

Stage Status Details
✅ Typecheck success tsc --noEmit
✅ Tests success unit tests, 3 platforms
✅ E2E success gitnexus-web changes only

Test Results

Tests Passed Failed Skipped Duration
10057 10053 0 4 630s

✅ All 10053 tests passed

4 test(s) skipped — expand for details
  • PHP pipeline benchmark > scales with file count (workers enabled)
  • Ruby pipeline benchmark > scales with file count (workers enabled)
  • Rust pipeline benchmark > scales with file count (workers enabled)
  • buildTypeEnv > known limitations (documented skip tests) > Ruby block parameter: users.each { |user| } — closure param inference, different feature

Code Coverage

Tests

Metric Coverage Covered Base Delta Status
Statements 79.81% 35278/44198 79.48% 📈 +0.3 🟢 ███████████████░░░░░
Branches 68.38% 22504/32907 68% 📈 +0.4 🟢 █████████████░░░░░░░
Functions 84.81% 3637/4288 84.56% 📈 +0.2 🟢 ████████████████░░░░
Lines 83.37% 31782/38121 82.97% 📈 +0.4 🟢 ████████████████░░░░

📋 View full run · Generated by CI

@github-actions

Copy link
Copy Markdown
Contributor

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

Comment thread gitnexus/src/core/group/extractors/http-patterns/java.ts Outdated
magyargergo and others added 2 commits May 28, 2026 19:05
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

✨ PR Autofix

Found fixable formatting / unused-import issues across 14 changed lines. Comment /autofix on this PR to apply them, or run npm run lint:fix && npm run format locally.

{"schema":"gitnexus.pr-autofix/v2","state":"fixes-available","pr_number":1872,"changed_lines":14,"head_sha":"5bc73bd88659bb6c10cb725a4c6090380f972ce6","run_id":"26593097782","apply_command":"/autofix"}

@magyargergo

Copy link
Copy Markdown
Collaborator

/autofix

@github-actions

Copy link
Copy Markdown
Contributor

✅ Applied autofix and pushed a commit. (apply run)

@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Claude finished @magyargergo's task in 6m 18s —— View job


Senior Review Panel — PR #1872: feat(java): add HTTP consumer contract extraction

All 8 reviewer personas have completed their analysis. Full findings below.


Executive verdict

Request changes — one blocking gap, several non-blocking concerns.

The implementation is structurally sound and the core patterns work. However, the @FeignClient(path=...) + @RequestMapping(...) prefix precedence fix introduced in commit 5bc73bd is not covered by a regression test. The first-wins guard is correct in code but there is no test that would catch a regression. Additionally, WEB_CLIENT_PATTERNS matches a two-argument webClient.method(HttpMethod.X, "/path") call form that does not exist in the Spring WebClient API, making the pattern and its test fixture misleading. Both issues should be resolved before merge.


PR intent summary

Adds source-scan-only Java HTTP consumer detection for five call patterns: RestTemplate convenience methods, RestTemplate.exchange, WebClient short-form chains (.get().uri(...)), OpenFeign interfaces with Spring MVC method annotations, Java 11 HttpRequest builder, and Apache HttpClient constructors. Intentionally defers dynamic URL resolution, wrapper tracking, and fully-qualified annotation support.


Production-readiness bar

Derived from CLAUDE.md + AGENTS.md + GUARDRAILS.md:

  • All new extractor branches require passing unit tests.
  • Consumer contracts: role: "consumer", correct framework, uppercase method, literal path, non-null name only when structurally determinable.
  • Source-scan-only confidence range is 0.65–0.7 (established by existing plugins).
  • No dynamic resolution, no scope-resolution coupling, no group sync internals.
  • hasAnnotation is permitted as a heuristic when AST parent-walk would require significant new plumbing, but risk must be noted.

Findings

Blocking

1. No regression test for @FeignClient(path=...) + @RequestMapping(...) prefix precedence

  • File/function: java.ts:392-399 (feignPrefixByInterfaceId population loop), test file lacks this case.
  • Why it is a bug: The review bot correctly flagged that the three FEIGN_INTERFACE_PREFIX_PATTERNS patterns could silently overwrite each other. Commit 5bc73bd added the first-wins guard (!feignPrefixByInterfaceId.has(interfaceNode.id)), which is correct because runCompiledPatterns iterates patterns in declaration order (pattern 1 = @FeignClient(path=...), patterns 2–3 = @RequestMapping(...) variants). But there is no test that would catch a regression if the pattern order changed or the guard were removed.
  • Reproducer:
    @FeignClient(name = "svc", path = "/feign-path")
    @RequestMapping("/rm-path")
    interface MyClient {
      @GetMapping("/orders")
      List<Order> getOrders();
    }
    Without the guard (or with patterns reordered), this would emit http::GET::/rm-path/orders instead of http::GET::/feign-path/orders.
  • Expected behaviour: @FeignClient(path=...) prefix wins over @RequestMapping(...) prefix when both are present on the same interface.
  • Suggested fix: Add a test case to the consumer extraction suite:
    @FeignClient(name = "svc", path = "/feign-path")
    @RequestMapping("/rm-path")
    interface PrecedenceClient {
      @GetMapping("/orders")
      OrderDto getOrders();
    }
    Assert exactly one consumer http::GET::/feign-path/orders and that http::GET::/rm-path/orders is absent. Fix this →

Non-blocking concerns

2. WEB_CLIENT_PATTERNS matches a non-existent Spring WebClient API form

  • File/function: java.ts:221-238 (WEB_CLIENT_PATTERNS), test at line 1382.
  • Why it is a concern: The query matches webClient.method(HttpMethod.PATCH, "/api/users/42") — a two-argument call. Spring's WebClient API does not have a method(HttpMethod, String) overload; the real signature is method(HttpMethod) returning a RequestBodyUriSpec, with URI set separately via .uri(...). The test fixture line webClient.method(HttpMethod.PATCH, "/api/users/42") tests an imaginary API shape. This means:
    • The pattern will never fire on real Spring WebClient code.
    • The real long-form chain webClient.method(HttpMethod.X).uri("/path") (which IS real Spring code) is not matched — and this is intentionally deferred, which is fine, but the WEB_CLIENT_PATTERNS gives the false impression it handles this case.
  • Expected behaviour: WEB_CLIENT_PATTERNS should be documented as either (a) intentionally targeting non-standard custom wrappers, or (b) removed and replaced with a proper deferred comment explaining the multi-hop chain is not yet supported. The test fixture should not assert extraction from a syntactically valid but semantically non-existent API form.
  • Suggested fix: Add a code comment on WEB_CLIENT_PATTERNS explicitly noting "matches the two-argument form method(HttpMethod, String) — this does not map to the standard Spring WebClient API; real webClient.method(HttpMethod).uri(String) support is deferred." Alternatively, remove WEB_CLIENT_PATTERNS and the corresponding test fixture line and add a "not yet supported" pin test. The WEB_CLIENT_SHORT_FORM_PATTERNS correctly handles the idiomatic .get().uri("/x") form and covers the vast majority of real Spring code.

3. hasAnnotation is regex-over-full-node-text

  • File/function: java.ts:359-361, called at line 413.
  • Why it is a concern: new RegExp('@\\s*FeignClient\\b').test(node.text) runs against the entire interface_declaration text, which includes method bodies, javadoc, and inline comments. An interface with a comment like // Replaces legacy @FeignClient pattern would produce a false positive, routing its @GetMapping methods to consumer instead of provider.
  • Severity: Low in practice — production interfaces rarely reference @FeignClient in comments inside a non-Feign interface. But this is text-pattern matching over AST nodes, which is explicitly an architecture smell when tree-sitter already knows the annotation structure.
  • Suggested fix (non-blocking): Replace with an AST walk that checks the modifiers of the interface_declaration for an annotation node whose name text equals FeignClient. The findEnclosingInterface result is already a SyntaxNode — its children can be inspected without regex.

4. Variable-name hardcoding is not documented as a known limitation

  • File/function: java.ts:191-197, java.ts:254-265.
  • REST_TEMPLATE_PATTERNS only matches variables named literally restTemplate. WEB_CLIENT_SHORT_FORM_PATTERNS only matches variables named webClient. Fields (this.restTemplate), injected fields with different names (template, rt, httpClient), and method parameters with other names are silently ignored.
  • This is intentionally scoped for a low-complexity first pass, but neither the code comments nor the PR body mention this as a known limitation. A reader may assume the patterns cover all RestTemplate/WebClient usages.
  • Suggested fix: Add a one-line comment: // Source-scan only: matches variables named exactly 'restTemplate'/'webClient'; fields, other injection names, and this.x are intentionally out of scope (deferred).

5. HttpPatch is absent from the Apache HttpClient test fixture

  • File/function: Test file line 1540 imports HttpPatch in the Java comment but the fixture code at lines 1554–1557 only tests HttpGet, HttpPost, HttpPut, HttpDelete. HttpPatch is never constructed and its detection via APACHE_HTTP_CLIENT_PATTERNS goes untested.
  • Suggested fix: Add new HttpPatch("/api/orders/5") to the HttpClients.java test fixture and assert http::PATCH::/api/orders/{param} is emitted.

6. Java HttpRequest.Builder has no .PATCH() method — regex dead branch

  • File/function: java.ts:307 regex ^(GET|POST|PUT|DELETE|PATCH)$.
  • Java 11's HttpRequest.Builder exposes .GET(), .POST(body), .PUT(body), .DELETE(). There is no .PATCH() method; PATCH requires .method("PATCH", body), which uses the generic form and is NOT matched by the current query.
  • Including PATCH in the regex is misleading — it suggests the pattern supports PATCH when in practice it never can fire for PATCH via HttpRequest.Builder.
  • Suggested fix: Either remove PATCH from the JAVA_HTTP_CLIENT_PATTERNS method regex and add a comment, or add support for the .method("PATCH", body) form (the latter is the real coverage gap).

7. No integration/group-sync test

  • Issue Java Spring: HTTP consumer contracts missed for common HTTP clients #1870's core problem is that consumer contracts are missing, causing provider-only group sync results. This PR stays at unit extractor level — there is no test showing that an emitted Java consumer contract flows through group sync and produces a crossLink entry matching a Spring MVC provider.
  • For a first-pass PR this is acceptable, but the follow-up issue should explicitly include a group-sync integration test.

Nits / maintainability

  • RestTemplateMeta interface (java.ts:179-181) is thin boilerplate — { framework: 'spring-rest-template' } as a type adds little value over the inline literal. The other patterns use Record<string, never>. Minor inconsistency.
  • joinPath docstring says "Mirrors the semantics of the original regex implementation" — the "original" implementation no longer exists in this diff, making the reference confusing. Consider: "Produces /prefix/sub, stripping duplicate slashes. Empty prefix returns /sub."
  • WEB_CLIENT_SHORT_TO_HTTP map (line 240) duplicates the method-name-to-HTTP mapping already present in the code. Consider combining or cross-referencing for consistency, though this is very minor.

Java / Spring Boot expert review

Spring MVC annotation correctness: The SPRING_METHOD_ROUTE_PATTERNS and SPRING_CLASS_PREFIX_PATTERNS correctly handle positional and named path/value args with the #match? guard on the key capture. The guard preventing non-route attributes (produces, consumes, etc.) from being captured as paths is solid and well-tested.

RestTemplate coverage: getForObject, getForEntity, postForObject, postForEntity, put, delete, patchForObject are all covered. exchange is separately covered. Not covered: getForObject(URI, ...), exchange(URI, ...), execute(...), and this.restTemplate.*. These are intentional gaps for this scope — just ensure they're documented.

WebClient coverage: The short-form .get().uri(...), .post().uri(...), etc. are correctly handled by WEB_CLIENT_SHORT_FORM_PATTERNS. The long-form webClient.method(HttpMethod.X).uri(...) is correctly deferred. The concern is WEB_CLIENT_PATTERNS which targets an API form that doesn't exist — see blocking finding #2 above.

OpenFeign semantics: @FeignClient(name=...), @FeignClient(value=...), and @FeignClient(url=...) are correctly ignored as path prefixes. Only path is captured. The @RequestMapping fallback is correct. The first-wins precedence is correct in code but untested — see blocking finding #1.

Java / Apache HttpClient semantics: The JAVA_HTTP_CLIENT_PATTERNS correctly handles the 3-hop chain HttpRequest.newBuilder().uri(URI.create("/x")).VERB(). Apache HttpClient constructor patterns are correct for the short class name form. Package-qualified names (new org.apache.http.client.methods.HttpGet(...)) are intentionally not matched and this is acceptable.


Contract extraction review

Aspect Assessment
role ✅ All new paths correctly emit "consumer". Feign methods are correctly classified consumer, not provider.
framework ✅ Values are specific and consistent: spring-rest-template, spring-web-client, openfeign, java-http-client, apache-http-client, okhttp. Framework strings match Kotlin plugin parity.
method ✅ Uppercase. RestTemplate methods mapped through REST_TEMPLATE_TO_HTTP. exchange uses .toUpperCase() on the HttpMethod field name. WebClient short-form uses WEB_CLIENT_SHORT_TO_HTTP. Apache uses APACHE_HTTP_CLIENT_TO_HTTP.
path ✅ Comes from unquoteLiteral(). No over-inference. Template placeholders survive to the orchestrator's normalizer.
name ✅ Feign methods set name to the method identifier. RestTemplate/WebClient/Apache/HttpClient use null — correct, since there's no reliable caller name at the call site without scope resolution.
confidence ✅ Spring clients use 0.7, Java/Apache HttpClient use 0.65. OkHttp uses 0.7. Slight concern: OkHttp always defaults to GET regardless of actual verb (known limitation), making its 0.7 confidence arguably high. Consider 0.5 for OkHttp or document the heuristic.
Duplicate risk Low. Patterns run on distinct structural shapes; no two patterns should fire on the same AST node. Feign methods use continue after consumer emission, preventing double-emission as provider.
Group sync impact Consumer contracts have the right shape for cross-linking. But see finding #7 — no integration test confirms the link is actually made.

Test review

Good test cases:

  • extracts Java Spring RestTemplate, WebClient and OkHttp literal calls — covers multiple patterns in one file with full contract verification (framework + confidence).
  • extracts OpenFeign clients as consumers, not providers — explicitly asserts no provider from the same file.
  • extracts OpenFeign clients without an interface path prefix — correct degenerate case.
  • extracts OpenFeign clients with @RequestMapping interface prefixes — tests the @RequestMapping prefix path.
  • extracts Java and Apache HttpClient literal request construction — covers 4/5 Apache verbs and 2 Java HttpClient verbs with framework+confidence checks.
  • Kotlin parity tests are a nice addition; the anti-overreach tests for long-form WebClient and non-restTemplate receiver are exactly right.

Missing test cases:

  1. @FeignClient(path=...) + @RequestMapping(...) precedence (blocking — see finding Add support for Ollama as a local inference backend #1).
  2. HttpPatch via Apache HttpClientnew HttpPatch("/api/orders/5") never appears in the test fixture.
  3. Negative case for dynamic URL in RestTemplate — e.g., restTemplate.getForObject(baseUrl + "/path", ...) — confirm no consumer is emitted. This documents the intentional limitation.
  4. webClient.method(HttpMethod.X).uri("/path") deferred — an anti-overreach test confirming no consumer is emitted from the real long-form chain. (Kotlin has this test but Java does not.)

Weak test cases:

  • The OpenFeign fixture at test line 1433 uses url = "${order.service.url}" which contains an EL expression. The test verifies that this is ignored as a path prefix correctly. But the string would be parsed by tree-sitter as a string_literal containing ${...} — it would be interesting to confirm this edge is actually handled by unquoteLiteral.

Regression and compatibility risks

  1. SPRING_METHOD_ROUTE_PATTERNS now feeds the Feign consumer path. Methods inside a @FeignClient-annotated interface were previously emitted as providers. The continue guard at line 424 now prevents that. This is correct and is tested, but any existing group sync state that has previously stored these as providers from an older analysis run would be stale. Not a code regression, but a schema-state migration concern.

  2. WEB_CLIENT_PATTERNS adds a new consumer extraction path. If any production Java codebase happens to have a custom two-argument webClient.method(HttpMethod.X, "/path") call (e.g., a custom wrapper), it would now emit consumer contracts it didn't before. Extremely unlikely but possible.

  3. hasAnnotation scanning the full interface text. If an interface had // @FeignClient in a method javadoc, its @GetMapping methods would now be promoted from provider to consumer. This is a behaviour change that could silently misclassify routes.


Suggested patch plan

Minimal changes to unblock merge:

Required (blocking):

  1. Add one test case to http-route-extractor.test.ts for @FeignClient(path=...) + @RequestMapping(...) precedence (see finding Add support for Ollama as a local inference backend #1 above for the fixture). This is a small test addition to the existing OpenFeign describe block.

Strongly recommended (non-blocking but should land in this PR or as immediate follow-up):
2. Add new HttpPatch("/api/orders/5") to the Apache HttpClient fixture and assert the PATCH consumer.
3. Add a WEB_CLIENT_PATTERNS code comment (or a "not yet supported" pin test) clarifying the two-argument form matches no real Spring API.
4. Remove PATCH from the JAVA_HTTP_CLIENT_PATTERNS method regex or add a code comment explaining it can never fire (no .PATCH() method on HttpRequest.Builder).

Deferred (follow-up issue):
5. Replace hasAnnotation regex with AST-based annotation checking.
6. Document variable name constraints in code comments.
7. Add group sync integration test for consumer → crossLink → provider.


Final merge recommendation

Do not merge until finding #1 is addressed (add the @FeignClient(path=...) + @RequestMapping(...) precedence regression test). Without this test, the first-wins guard introduced in 5bc73bd could be silently broken by any future pattern reordering.

Finding #2 (WEB_CLIENT_PATTERNS targets non-existent API) should also be resolved — either add the clarifying comment or remove the dead pattern — before merge, since it actively misleads future contributors about what is and isn't supported.

All other findings are non-blocking and can land in a follow-up issue.


· PR branch

@magyargergo

Copy link
Copy Markdown
Collaborator

@ShiningXu could you please look into claude's findings? 🙏

@magyargergo magyargergo merged commit 7b38b8a into abhigyanpatwari:main May 29, 2026
30 of 31 checks passed
henry201605 pushed a commit to henry201605/GitNexus that referenced this pull request May 29, 2026
…atwari#1884

Two minor follow-ups from the production-readiness review:

F1 — Stale block comment at the top of the Kotlin consumer suite
(was: "Three consumer flavors covered here ... long-form deferred
to a follow-up"). Updated to "Four consumer flavors" and removed
the deferred sentence — the deferral is resolved by this PR. The
kotlin.ts file header was already updated; this brings the test
file comment in sync. Per DoD §2.3 (no stale comments).

F2 — Replaced `expect(wcConsumers.length).toBeGreaterThanOrEqual(4)`
with `expect(wcConsumers).toHaveLength(4)` in the multi-verb test.
The fixture is fully deterministic — exactly 4 long-form calls,
no other consumer types — so an exact count assertion is the right
shape per DoD §2.7 ("use toBe / toEqual for exact expectations").
Added a comment explaining what the assertion catches that the
existing per-verb toBeDefined() checks would miss (accidental 5th
consumer from a duplicate query firing or a regressed receiver
constraint).

F3 (HEAD/OPTIONS/TRACE negative test) is intentionally not added
in this PR — same precedent as abhigyanpatwari#1855 where HEAD/OPTIONS/TRACE on
the short form are also implicitly excluded without a pinning
test. Happy to add one in a separate PR if maintainers want
explicit pinning across both forms.

F4 (CI on pre-merge SHA) is the maintainer's call — the merge from
main is theirs to re-trigger CI on. The merge brings only Java
consumer changes (PR abhigyanpatwari#1872) and Go provider changes (PR abhigyanpatwari#1886),
both in entirely separate files from this PR's Kotlin work.

Local validation:
  - test/unit/group/http-route-extractor.test.ts: 73/73 ✅
    (66 from this PR pre-merge + 7 from PR abhigyanpatwari#1872 merged via main)
  - npx prettier --check (changed files): clean ✅
magyargergo added a commit that referenced this pull request May 29, 2026
…action (#1884)

* feat(group): add Kotlin Spring WebClient long-form HTTP consumer extraction

Follow-up to #1855. Extends `kotlin.ts` with the long-form WebClient
fluent chain that #1855 explicitly deferred:

  webClient.method(HttpMethod.GET).uri("/x").retrieve().awaitBody<T>()

This pattern remains common in Kotlin Spring 4 → 5 migrations and in
codebases that prefer the fluent verb-as-enum style. The short form
(`webClient.get().uri("/x")`) was already supported in #1855.

Approach:
  - Single deeper tree-sitter query (`WEB_CLIENT_LONG_PATTERNS`) that
    matches the full chain structurally — both `.method(HttpMethod.X)`
    and `.uri("...")` in one pattern. Verb is captured as the
    `simple_identifier` of the `HttpMethod.X` field access.
  - Verb is whitelisted to GET/POST/PUT/DELETE/PATCH (consistent with
    the short-form's `WEB_CLIENT_SHORT_TO_HTTP` map).
  - Receiver constraint `(#eq? @obj "webClient")` mirrors the short
    form and Java plugin heuristic.

Out of scope (intentional):
  - Variable-bound verbs: `val verb = HttpMethod.PATCH; webClient.method(verb)...`
    Source-scan can't follow the binding without graph context.
    Pinned by an anti-overreach test.
  - HEAD/OPTIONS/TRACE: not in `WEB_CLIENT_SHORT_TO_HTTP` either —
    keeps polyglot symmetry with java.ts and the short form.

Tests: 4 new cases under `consumer extraction — fetch patterns`,
gated by tree-sitter-kotlin grammar availability.

  positive (3)
   - long form GET
   - long form POST / PUT / DELETE / PATCH (4 verbs in 1 fixture)
   - no double-emit pin (long-form chain produces exactly one
     consumer, not one from each query)
  anti-regression (1)
   - variable-bound verb does NOT match (graph-aware concern)

The previous `'does NOT match Kotlin WebClient long form (deferred
to follow-up)'` test from #1855 is replaced by these — the deferred
state is now resolved.

Reverse-validated: temporarily disabling the long-form emit makes
exactly the 3 positive tests fail; the variable-bound-verb anti-
regression test continues to pass (it pins behavior independent
of the emit being on or off).

Local validation:
  - test/unit/group/http-route-extractor.test.ts: 66/66 ✅
  - test/unit/group: 546/546 ✅
  - npx prettier --check (changed files): clean ✅

* test(group): address Claude review findings F1 and F2 on PR #1884

Two minor follow-ups from the production-readiness review:

F1 — Stale block comment at the top of the Kotlin consumer suite
(was: "Three consumer flavors covered here ... long-form deferred
to a follow-up"). Updated to "Four consumer flavors" and removed
the deferred sentence — the deferral is resolved by this PR. The
kotlin.ts file header was already updated; this brings the test
file comment in sync. Per DoD §2.3 (no stale comments).

F2 — Replaced `expect(wcConsumers.length).toBeGreaterThanOrEqual(4)`
with `expect(wcConsumers).toHaveLength(4)` in the multi-verb test.
The fixture is fully deterministic — exactly 4 long-form calls,
no other consumer types — so an exact count assertion is the right
shape per DoD §2.7 ("use toBe / toEqual for exact expectations").
Added a comment explaining what the assertion catches that the
existing per-verb toBeDefined() checks would miss (accidental 5th
consumer from a duplicate query firing or a regressed receiver
constraint).

F3 (HEAD/OPTIONS/TRACE negative test) is intentionally not added
in this PR — same precedent as #1855 where HEAD/OPTIONS/TRACE on
the short form are also implicitly excluded without a pinning
test. Happy to add one in a separate PR if maintainers want
explicit pinning across both forms.

F4 (CI on pre-merge SHA) is the maintainer's call — the merge from
main is theirs to re-trigger CI on. The merge brings only Java
consumer changes (PR #1872) and Go provider changes (PR #1886),
both in entirely separate files from this PR's Kotlin work.

Local validation:
  - test/unit/group/http-route-extractor.test.ts: 73/73 ✅
    (66 from this PR pre-merge + 7 from PR #1872 merged via main)
  - npx prettier --check (changed files): clean ✅

* refactor(group): hoist Kotlin WebClient long-form verb regex to module scope

Address @magyargergo's review request on PR #1884:

  > Can you please extract the regexp from the for loop? 🙏
    (kotlin.ts:510)

Compiles the verb whitelist `^(GET|POST|PUT|DELETE|PATCH)$` once at
module load instead of every iteration of the long-form scan loop.
Mirrors the placement and JSDoc style of the sibling
`WEB_CLIENT_SHORT_TO_HTTP` constant.

Behavior is unchanged — same verb whitelist, same exclusion of
HEAD/OPTIONS/TRACE for symmetry with the short form. The 4
itKotlinConsumer long-form tests added in this PR continue to
pass, and the variable-bound-verb anti-overreach test continues
to pin the deliberate non-match.

Local validation:
  - test/unit/group/http-route-extractor.test.ts: 77/77 ✅
  - test/unit/group: 557/557 ✅
  - npx prettier --check (changed file): clean ✅

---------

Co-authored-by: henry <zhangwei2017@unipus.cn>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
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.

2 participants