@descryy/adapter-java 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter.d.ts +31 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +298 -0
- package/dist/adapter.js.map +1 -0
- package/dist/client.d.ts +171 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +471 -0
- package/dist/client.js.map +1 -0
- package/dist/extract.d.ts +49 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +892 -0
- package/dist/extract.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/jpa.d.ts +107 -0
- package/dist/jpa.d.ts.map +1 -0
- package/dist/jpa.js +312 -0
- package/dist/jpa.js.map +1 -0
- package/dist/parse.d.ts +297 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +765 -0
- package/dist/parse.js.map +1 -0
- package/dist/roots.d.ts +9 -0
- package/dist/roots.d.ts.map +1 -0
- package/dist/roots.js +9 -0
- package/dist/roots.js.map +1 -0
- package/dist/spring.d.ts +78 -0
- package/dist/spring.d.ts.map +1 -0
- package/dist/spring.js +397 -0
- package/dist/spring.js.map +1 -0
- package/dist/tree-sitter-java.wasm +0 -0
- package/package.json +36 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The caller's half of the HTTP boundary: `USES_API`, golden pattern 08.
|
|
3
|
+
*
|
|
4
|
+
* `SERVES_API` is minted in `extract.ts` from a route's annotations. This reads
|
|
5
|
+
* the other end — an outbound call with a statically knowable path — and mints
|
|
6
|
+
* the **same** `API_ENDPOINT` node from the same `endpointQsp`, so the two join
|
|
7
|
+
* without either side knowing the other ran. DEC-115's one hard constraint: two
|
|
8
|
+
* producers that mint different ids do not conflict, they silently fail to join.
|
|
9
|
+
*
|
|
10
|
+
* FUNCTION ──USES_API──▶ API_ENDPOINT ◀──SERVES_API── API_ROUTE
|
|
11
|
+
*
|
|
12
|
+
* ## What these edges actually mean, and why it must be said in the edge
|
|
13
|
+
*
|
|
14
|
+
* Measured before this was written (`bench/client-call-census.mjs`, DEC-189):
|
|
15
|
+
* across `shopizer`, `mall`, `morphia`, `okhttp` and `spring-petclinic` there
|
|
16
|
+
* are **16** client call sites carrying a repository-relative literal path.
|
|
17
|
+
* **Twelve are in test files, four are on a mock transport, and none are
|
|
18
|
+
* production code.**
|
|
19
|
+
*
|
|
20
|
+
* So in Java these edges are almost entirely `TEST_CASE`-shaped: an integration
|
|
21
|
+
* test driving `TestRestTemplate` at the application's own routes. That is real
|
|
22
|
+
* and it is useful — it answers *which routes have integration coverage*, which
|
|
23
|
+
* is the **Verification status** axis (AI layer §20, §42), a separate axis from
|
|
24
|
+
* the confidence label. It is **not** service-to-service coupling, and a
|
|
25
|
+
* consumer reading it as "this service calls that service" would be wrong.
|
|
26
|
+
*
|
|
27
|
+
* The distinction therefore travels **in the edge**, as `attrs.callerKind`, not
|
|
28
|
+
* in a comment here. A count in a decision record is invisible to a consumer;
|
|
29
|
+
* `attrs` is what the edge carries. (`attrs` is not read above the IR — which is
|
|
30
|
+
* exactly why the same fact is also stated in the disclosure below, where a
|
|
31
|
+
* reader will see it.)
|
|
32
|
+
*
|
|
33
|
+
* ## Why the receiver's type is required
|
|
34
|
+
*
|
|
35
|
+
* `execute`, `put`, `delete` and `uri` are ordinary method names. Admitting a
|
|
36
|
+
* call on its name alone would emit `USES_API` for `list.put("/tmp/x")`, and a
|
|
37
|
+
* wrong edge here joins a caller to a route it never calls — which root-cause
|
|
38
|
+
* traversal then follows. So a call is admitted only when its receiver's
|
|
39
|
+
* **declared type** is a known client. That is R2 evidence: a reference resolved
|
|
40
|
+
* to a definition through a written annotation, exactly as the rest of this
|
|
41
|
+
* adapter reads receivers.
|
|
42
|
+
*
|
|
43
|
+
* The cost is disclosed rather than hidden: a chained builder
|
|
44
|
+
* (`new Request.Builder().url("/")`) has no receiver with a written type and is
|
|
45
|
+
* refused. All four such sites in the corpora are `mockWebServer`, so nothing
|
|
46
|
+
* real is lost today — but the refusal is a rule, not a measurement, and it will
|
|
47
|
+
* cost real call sites in a codebase that chains.
|
|
48
|
+
*
|
|
49
|
+
* ## Ledger row D-FIX-3: a known client this reader does not extract
|
|
50
|
+
*
|
|
51
|
+
* Everything above requires the receiver's type to already be in
|
|
52
|
+
* {@link CLIENT_TYPES} before any refusal fires — so a call through a client
|
|
53
|
+
* this adapter has never heard of took neither branch. It matched no name in
|
|
54
|
+
* {@link URL_FIRST}'s companion set below, `typeOfReceiver` was never asked,
|
|
55
|
+
* and the reference fell out of the loop with `continue` before reaching a
|
|
56
|
+
* single `refuse(...)` call. **Zero edges and zero ledger rows is the same
|
|
57
|
+
* output a repository with no HTTP calls at all produces.** Sherpa's
|
|
58
|
+
* TypeScript diagnosis found the identical shape — 26 wrapped-`axios` call
|
|
59
|
+
* sites across 14 files, none reaching the refusal ledger — and it is the
|
|
60
|
+
* reason this row exists rather than being filed as ordinary recall.
|
|
61
|
+
*
|
|
62
|
+
* {@link BUILDER_CLIENT_TYPES} closes it for the two client families measured
|
|
63
|
+
* on the reference corpora (`bench/client-call-census.mjs`'s `CLIENTS.java`
|
|
64
|
+
* list, `okhttp3.OkHttpClient` and `java.net.http.HttpClient`) — **not by
|
|
65
|
+
* reading their calls**, but by recognising the receiver type and filing a
|
|
66
|
+
* refusal for every call through it. Both clients pass the outbound request as
|
|
67
|
+
* a **separately constructed object** (`Request`, `HttpRequest`) rather than a
|
|
68
|
+
* literal argument on the call itself, so building real extraction for them is
|
|
69
|
+
* a different, larger row — a second `firstStringArgument`-shaped read through
|
|
70
|
+
* a builder chain — and is out of scope here. What is in scope is closing the
|
|
71
|
+
* silence: **every** call through a receiver whose declared type names one of
|
|
72
|
+
* these clients is now accounted for, either as an edge (impossible for these
|
|
73
|
+
* two, by construction) or as a ledger row.
|
|
74
|
+
*
|
|
75
|
+
* ### Why the trigger is receiver-type resolution, not a file-level import scan
|
|
76
|
+
*
|
|
77
|
+
* The population D-FIX-3 was scoped against is "a file that imports a known
|
|
78
|
+
* HTTP client and makes calls the extractor did not claim." Read literally,
|
|
79
|
+
* that would fire on **every** method call in a file that merely imports
|
|
80
|
+
* `okhttp3.OkHttpClient` anywhere — including calls with no relation to it —
|
|
81
|
+
* which is exactly the "fires on everything" failure the row warns against.
|
|
82
|
+
* This adapter already has a narrower, previously-measured discriminator for
|
|
83
|
+
* the identical question: `typeOfReceiver`, R2 evidence, a written declaration
|
|
84
|
+
* this reader can point at. Reusing it means the new population is *provably*
|
|
85
|
+
* bounded to calls whose receiver is declared as one of these types — no
|
|
86
|
+
* broader — and it costs nothing new: `writtenReceiverType` in `extract.ts`
|
|
87
|
+
* already resolves an arbitrary type name syntactically, whether or not this
|
|
88
|
+
* adapter goes on to model it, so `OkHttpClient` and `HttpClient` resolve
|
|
89
|
+
* exactly as `RestTemplate` does today.
|
|
90
|
+
*
|
|
91
|
+
* ### The reconciliation this row makes an assertion rather than a discipline
|
|
92
|
+
*
|
|
93
|
+
* `candidateClientRefs` (below) recomputes, independently of the loop in
|
|
94
|
+
* {@link clientCalls}, which references in a method are candidates at all —
|
|
95
|
+
* same predicate, factored out so a future edit to the loop cannot silently
|
|
96
|
+
* narrow what counts as a candidate without the test that calls both noticing.
|
|
97
|
+
* `test/client.test.ts` asserts `calls.length + refusals.length ===
|
|
98
|
+
* candidateClientRefs(method).length` on every fixture, which is the shape
|
|
99
|
+
* DEC-098 found missing the hard way: a guard that dropped 113 of 140 call
|
|
100
|
+
* sites with no edge, no row, and no failing test.
|
|
101
|
+
*/
|
|
102
|
+
import { endpointQsp, nodeId } from "@descryy/ir";
|
|
103
|
+
/**
|
|
104
|
+
* Client types whose methods name an outbound HTTP call.
|
|
105
|
+
*
|
|
106
|
+
* `TestRestTemplate` is here deliberately. It is Spring's own integration-test
|
|
107
|
+
* client and it drives **real HTTP at the application's real routes** — the
|
|
108
|
+
* transport is what decides whether a call site is a route reference, not the
|
|
109
|
+
* directory the file sits in. That distinction cost this project a gate: a
|
|
110
|
+
* census that split on the file path reported two `mockWebServer` calls as
|
|
111
|
+
* production code.
|
|
112
|
+
*/
|
|
113
|
+
const CLIENT_TYPES = new Set([
|
|
114
|
+
"RestTemplate",
|
|
115
|
+
"TestRestTemplate",
|
|
116
|
+
"WebClient",
|
|
117
|
+
"RestClient",
|
|
118
|
+
"AsyncRestTemplate",
|
|
119
|
+
]);
|
|
120
|
+
/**
|
|
121
|
+
* Methods that take a URL or path as their first argument.
|
|
122
|
+
*
|
|
123
|
+
* `exchange` and `execute` are `RestTemplate`'s general forms; `uri` is
|
|
124
|
+
* `WebClient`'s fluent builder step. Every one is admitted only in combination
|
|
125
|
+
* with a receiver of a {@link CLIENT_TYPES} type.
|
|
126
|
+
*/
|
|
127
|
+
const URL_FIRST = new Set([
|
|
128
|
+
"getForObject",
|
|
129
|
+
"getForEntity",
|
|
130
|
+
"postForObject",
|
|
131
|
+
"postForEntity",
|
|
132
|
+
"postForLocation",
|
|
133
|
+
"patchForObject",
|
|
134
|
+
"put",
|
|
135
|
+
"delete",
|
|
136
|
+
"exchange",
|
|
137
|
+
"execute",
|
|
138
|
+
"uri",
|
|
139
|
+
]);
|
|
140
|
+
/**
|
|
141
|
+
* Known HTTP clients this reader recognises by declared type but does not
|
|
142
|
+
* extract — see "Ledger row D-FIX-3" above. Keyed by type name, valued by the
|
|
143
|
+
* method names on that type which initiate a request; every such call is
|
|
144
|
+
* refused, unconditionally, because the URL and verb live inside a request
|
|
145
|
+
* object built in a separate expression rather than in this call's own
|
|
146
|
+
* arguments — there is nothing for `firstStringArgument` to read.
|
|
147
|
+
*
|
|
148
|
+
* `java.net.http.HttpClient`'s simple name is `HttpClient`, distinct from
|
|
149
|
+
* Spring's `WebClient` — no collision with {@link CLIENT_TYPES}.
|
|
150
|
+
*/
|
|
151
|
+
const BUILDER_CLIENT_TYPES = {
|
|
152
|
+
OkHttpClient: new Set(["newCall"]),
|
|
153
|
+
HttpClient: new Set(["send", "sendAsync"]),
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* `WebClient`/`RestClient`'s own intermediate builder-step interfaces —
|
|
157
|
+
* `WebClient.RequestHeadersUriSpec`, `RestClient.RequestBodyUriSpec`, and
|
|
158
|
+
* their siblings, always referred to by simple name since nobody writes the
|
|
159
|
+
* outer-class-qualified form. Reached when the chain is split across a local
|
|
160
|
+
* variable (`var spec = client.get(); spec.uri("/x");`) rather than written
|
|
161
|
+
* inline — the other half of ledger row D-FIX-3, alongside the inline chain
|
|
162
|
+
* {@link BUILDER_VERB} closes. This adapter has no initializer-tracing (the
|
|
163
|
+
* verb-bearing `.get()`/`.post()` call is a separate statement, gone by the
|
|
164
|
+
* time `spec`'s declared type is the only thing left to read), so every call
|
|
165
|
+
* through one of these is refused rather than silently dropped — the same
|
|
166
|
+
* "account for it as an edge or a ledger row, never nothing" standard
|
|
167
|
+
* {@link BUILDER_CLIENT_TYPES} already holds OkHttp/`HttpClient` to.
|
|
168
|
+
*/
|
|
169
|
+
const WEBCLIENT_SPLIT_BUILDER_TYPES = new Set([
|
|
170
|
+
"RequestHeadersUriSpec",
|
|
171
|
+
"RequestBodyUriSpec",
|
|
172
|
+
"RequestHeadersSpec",
|
|
173
|
+
"RequestBodySpec",
|
|
174
|
+
]);
|
|
175
|
+
/**
|
|
176
|
+
* `WebClient`/`RestClient`'s fluent verb-starters — the call that opens the
|
|
177
|
+
* chain a real call site always uses (`client.get().uri("/x")...`), not the
|
|
178
|
+
* client's own declared type's method. This is why {@link URL_FIRST}'s `uri`
|
|
179
|
+
* entry alone was never enough: nothing in `VERB` maps `uri` to a verb,
|
|
180
|
+
* because `uri` never carries one — the verb sits one call earlier in the
|
|
181
|
+
* chain, on the call `uri`'s receiver expression *is*. See ledger row
|
|
182
|
+
* D-FIX-3 in the file header.
|
|
183
|
+
*
|
|
184
|
+
* `head`/`options` are real `WebClientRequestSpec`/`RestClient` entry points
|
|
185
|
+
* with no `VERB`-string precedent elsewhere in this file, so they are spelled
|
|
186
|
+
* out here rather than derived.
|
|
187
|
+
*/
|
|
188
|
+
const BUILDER_VERB = {
|
|
189
|
+
get: "GET",
|
|
190
|
+
post: "POST",
|
|
191
|
+
put: "PUT",
|
|
192
|
+
patch: "PATCH",
|
|
193
|
+
delete: "DELETE",
|
|
194
|
+
head: "HEAD",
|
|
195
|
+
options: "OPTIONS",
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Matches `parse.ts`'s `receiverName` chain encoding for a `method_invocation`
|
|
199
|
+
* object: `<base>.<name>()`. The literal `()` is a label, not a copy of the
|
|
200
|
+
* call's real arguments — see that function's doc.
|
|
201
|
+
*/
|
|
202
|
+
const CHAIN_PATTERN = /^(.+)\.([A-Za-z_$][A-Za-z0-9_$]*)\(\)$/;
|
|
203
|
+
/** Every method name either extraction path or the builder-client path acts on. */
|
|
204
|
+
const TRACKED_METHODS = new Set([...URL_FIRST, ...Object.values(BUILDER_CLIENT_TYPES).flatMap((s) => [...s])]);
|
|
205
|
+
/**
|
|
206
|
+
* The HTTP verb a method name implies.
|
|
207
|
+
*
|
|
208
|
+
* `exchange`, `execute` and `uri` take the verb as a *separate argument* — an
|
|
209
|
+
* enum reference, not a literal — so they cannot be read here and are refused
|
|
210
|
+
* rather than defaulted to `GET`. A wrong verb produces an `endpointQsp` that
|
|
211
|
+
* joins nothing, which is a silent miss, or worse joins the wrong route.
|
|
212
|
+
*/
|
|
213
|
+
const VERB = {
|
|
214
|
+
getForObject: "GET",
|
|
215
|
+
getForEntity: "GET",
|
|
216
|
+
postForObject: "POST",
|
|
217
|
+
postForEntity: "POST",
|
|
218
|
+
postForLocation: "POST",
|
|
219
|
+
patchForObject: "PATCH",
|
|
220
|
+
put: "PUT",
|
|
221
|
+
delete: "DELETE",
|
|
222
|
+
};
|
|
223
|
+
const CAPABILITY_GAP = { blockedBy: null, refusalClass: "capability-gap" };
|
|
224
|
+
const VARIES_PER_CALL = { blockedBy: null, refusalClass: "varies-per-call" };
|
|
225
|
+
/** `System.getenv("X")`, `System.getenv().get("X")`, and Spring's `env`/`environment`-named `Environment.getProperty("X")`. */
|
|
226
|
+
const ENV_READ_PATTERNS = [
|
|
227
|
+
/^System\.getenv\(\s*"[^"]*"\s*\)$/,
|
|
228
|
+
/^System\.getenv\(\s*\)\.get\(\s*"[^"]*"\s*\)$/,
|
|
229
|
+
/^\w*(?:[Ee]nv|[Ee]nvironment)\w*\.getProperty\(\s*"[^"]*"\s*\)$/,
|
|
230
|
+
];
|
|
231
|
+
/** Same heuristic as every other adapter's — see `adapter-rust/src/client.ts`'s doc. */
|
|
232
|
+
function argumentKindOf(text) {
|
|
233
|
+
if (text.endsWith(")") && text.includes("("))
|
|
234
|
+
return "call";
|
|
235
|
+
if (text.includes("+"))
|
|
236
|
+
return "concatenation";
|
|
237
|
+
if (/^[A-Za-z_$][A-Za-z0-9_$]*(\.[A-Za-z_$][A-Za-z0-9_$]*)*$/.test(text))
|
|
238
|
+
return "field";
|
|
239
|
+
return "other";
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Why the first argument of a client call could not be read as a literal
|
|
243
|
+
* path — mirrors `firstArgumentTextOf`'s own reach: a bare identifier, a
|
|
244
|
+
* known environment-read call, or something this reader does not trace.
|
|
245
|
+
*/
|
|
246
|
+
function diagnoseArgument(text, parameterNames) {
|
|
247
|
+
if (text === undefined)
|
|
248
|
+
return CAPABILITY_GAP;
|
|
249
|
+
const trimmed = text.trim();
|
|
250
|
+
if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(trimmed) && parameterNames.has(trimmed))
|
|
251
|
+
return VARIES_PER_CALL;
|
|
252
|
+
if (ENV_READ_PATTERNS.some((pattern) => pattern.test(trimmed))) {
|
|
253
|
+
return { blockedBy: trimmed, refusalClass: "value-unknown" };
|
|
254
|
+
}
|
|
255
|
+
return { ...CAPABILITY_GAP, argumentKind: argumentKindOf(trimmed) };
|
|
256
|
+
}
|
|
257
|
+
/** A path this reader will claim: repository-relative, no scheme, no assembly. */
|
|
258
|
+
function relativePath(value) {
|
|
259
|
+
if (!value.startsWith("/"))
|
|
260
|
+
return undefined;
|
|
261
|
+
// `//host/path` is protocol-relative and names another origin.
|
|
262
|
+
if (value.startsWith("//"))
|
|
263
|
+
return undefined;
|
|
264
|
+
// A query string is not part of the route template. `?` and everything after
|
|
265
|
+
// it is dropped, because `SERVES_API` never mints one and keeping it would
|
|
266
|
+
// guarantee the join fails.
|
|
267
|
+
const cut = value.indexOf("?");
|
|
268
|
+
return cut === -1 ? value : value.slice(0, cut);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* A literal this reader can say, with no ambiguity, names a *different*
|
|
272
|
+
* origin — an explicit scheme (`http://...`) or a protocol-relative URL
|
|
273
|
+
* (`//host/...`). Anything else that fails {@link relativePath} (a bare
|
|
274
|
+
* relative path with no leading slash, e.g. `"orders/5"`) is NOT covered by
|
|
275
|
+
* this check and must not be reported through it.
|
|
276
|
+
*
|
|
277
|
+
* Split out after DEC-260's C# origin-check row found the shared bug one
|
|
278
|
+
* language over: `adapter-csharp` originally treated "does not start with
|
|
279
|
+
* `/`" as sufficient evidence of another origin, and that misfired on real
|
|
280
|
+
* `jellyfin`/`eShopOnWeb` call sites — bare relative paths resolved against
|
|
281
|
+
* `HttpClient.BaseAddress` at runtime, same-repository calls incorrectly
|
|
282
|
+
* filed as a scope boundary. Spring's `RestTemplate`/`WebClient` support the
|
|
283
|
+
* identical pattern (`RootUriTemplateHandler`, `WebClient.baseUrl(...)`), so
|
|
284
|
+
* the same rule, applied here unchanged since before that row, carries the
|
|
285
|
+
* identical latent defect — confirmed synthetically
|
|
286
|
+
* (`restTemplate.getForObject("orders/5", String.class)` was filed as
|
|
287
|
+
* "another origin" before this fix). **Not observed in either admitted
|
|
288
|
+
* corpus** (`spring-petclinic`, `shopizer` — all 3 real `USES_API` refusals
|
|
289
|
+
* naming another origin are unambiguous `http://` URLs, unaffected by this
|
|
290
|
+
* change), so this closes a rule that was correct only because nothing had
|
|
291
|
+
* tested it yet, not a live regression.
|
|
292
|
+
*/
|
|
293
|
+
function namesAnotherOrigin(value) {
|
|
294
|
+
return /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(value) || value.startsWith("//");
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Every reference in a method that {@link clientCalls} will act on — an edge,
|
|
298
|
+
* a refusal, or (only past this point, where the receiver's type is unknown)
|
|
299
|
+
* a true silence. Factored out of the loop below so the reconciliation
|
|
300
|
+
* assertion in `test/client.test.ts` recomputes candidacy independently of
|
|
301
|
+
* whatever the loop does with each candidate: a future edit that narrows the
|
|
302
|
+
* loop's own filter without touching this function fails the test instead of
|
|
303
|
+
* silently dropping call sites the way DEC-098's `containerOf` guard did.
|
|
304
|
+
*
|
|
305
|
+
* Receiver-type resolution is deliberately **not** done here — it needs
|
|
306
|
+
* `extract.ts`'s scope tables, which this module does not have — so a
|
|
307
|
+
* candidate here may still turn out to be a true silence in
|
|
308
|
+
* {@link clientCalls} if `typeOfReceiver` returns `undefined`. That is the
|
|
309
|
+
* one gap this reconciliation cannot close, and it is the same gap every
|
|
310
|
+
* other refusal ledger in this project discloses rather than guesses past:
|
|
311
|
+
* an unresolved receiver is not evidence the call is or is not a client.
|
|
312
|
+
*/
|
|
313
|
+
export function candidateClientRefs(method) {
|
|
314
|
+
return method.refs.filter((ref) => ref.kind === "call" &&
|
|
315
|
+
TRACKED_METHODS.has(ref.name) &&
|
|
316
|
+
ref.receiver !== undefined &&
|
|
317
|
+
ref.receiver !== "this");
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Read one method's calls for outbound HTTP.
|
|
321
|
+
*
|
|
322
|
+
* `typeOfReceiver` resolves a receiver name to its declared type's simple name
|
|
323
|
+
* and is supplied by the caller, because the scope rules for that live in
|
|
324
|
+
* `extract.ts` and a second copy of them would drift — the failure that
|
|
325
|
+
* `scopesFor`'s own header records.
|
|
326
|
+
*/
|
|
327
|
+
export function clientCalls(method, fromId, typeOfReceiver, inTestSourceSet) {
|
|
328
|
+
const calls = [];
|
|
329
|
+
const refusals = [];
|
|
330
|
+
/**
|
|
331
|
+
* Read `ref`'s first argument as a path and either push a `ClientCall` or a
|
|
332
|
+
* refusal — the shared tail every admitted verb reaches, whether the verb
|
|
333
|
+
* came from `VERB[ref.name]` directly or from a builder-chain's opening
|
|
334
|
+
* call via {@link BUILDER_VERB}.
|
|
335
|
+
*/
|
|
336
|
+
const readPathAndEmit = (receiverType, ref, verb, refuse) => {
|
|
337
|
+
if (ref.firstStringArgument === undefined) {
|
|
338
|
+
refuse(`an HTTP call through ${receiverType}, but its path is not a bare string literal — a ` +
|
|
339
|
+
`variable, a concatenation, or a builder. A path assembled at run time is not one ` +
|
|
340
|
+
`this adapter can read, and an endpoint template invented here would join this ` +
|
|
341
|
+
`caller to a route it never calls.`, diagnoseArgument(ref.firstArgumentText, method.parameterNames));
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const template = relativePath(ref.firstStringArgument);
|
|
345
|
+
if (template === undefined) {
|
|
346
|
+
if (namesAnotherOrigin(ref.firstStringArgument)) {
|
|
347
|
+
refuse(`an HTTP call through ${receiverType} to \`${ref.firstStringArgument}\`, which names ` +
|
|
348
|
+
`another origin rather than a path in this repository. A scope boundary, not a gap.`, { blockedBy: null, refusalClass: "out-of-scope" });
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
// A bare relative path with no leading slash and no scheme —
|
|
352
|
+
// structurally identical to C#'s `HttpClient.BaseAddress` case. It may
|
|
353
|
+
// resolve inside this repository, against a configured root URI
|
|
354
|
+
// (`RootUriTemplateHandler`, `WebClient.baseUrl(...)`), or it may not;
|
|
355
|
+
// this reader does not see that configuration, so neither an edge nor
|
|
356
|
+
// an out-of-scope claim is honest here — rule 2, applied to a
|
|
357
|
+
// classification rather than an edge. Not a per-call value and not a
|
|
358
|
+
// named blocking expression either, so `capability-gap` rather than
|
|
359
|
+
// `varies-per-call`: nothing here is caller-supplied, this reader just
|
|
360
|
+
// cannot see the base configuration.
|
|
361
|
+
refuse(`an HTTP call through ${receiverType} to \`${ref.firstStringArgument}\`, a relative path ` +
|
|
362
|
+
`with no leading slash. This reader cannot tell whether it resolves inside this repository ` +
|
|
363
|
+
`— against a configured base URI this call site does not state — or elsewhere, so neither ` +
|
|
364
|
+
`an endpoint nor a scope boundary is claimed.`, CAPABILITY_GAP);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
calls.push({
|
|
368
|
+
fromId,
|
|
369
|
+
method: ref.name,
|
|
370
|
+
template,
|
|
371
|
+
verb,
|
|
372
|
+
line: ref.line,
|
|
373
|
+
// **The source set, not just the annotation.** `method.isTest` reads
|
|
374
|
+
// `@Test`, and shopizer's `ServicesTestSupport.getHeader` drives
|
|
375
|
+
// `TestRestTemplate` from an unannotated helper — so annotation alone
|
|
376
|
+
// labelled two of nine edges `production` when both sit in
|
|
377
|
+
// `src/test/java`. The build system states which source set is test code;
|
|
378
|
+
// inferring it from the annotation asks a narrower question than the one
|
|
379
|
+
// being answered. If the framework will tell you, never infer it.
|
|
380
|
+
callerKind: method.isTest || inTestSourceSet ? "test" : "production",
|
|
381
|
+
});
|
|
382
|
+
};
|
|
383
|
+
for (const ref of candidateClientRefs(method)) {
|
|
384
|
+
// WebClient/RestClient's fluent chain: `client.get().uri("/x")`. The
|
|
385
|
+
// receiver `parse.ts` hands back for the `uri` call is the *opening* call
|
|
386
|
+
// encoded as text (`client.get()`), not a name `typeOfReceiver` can look
|
|
387
|
+
// up directly — so the base is resolved instead, and the verb comes from
|
|
388
|
+
// the chain, not from `uri` itself. See ledger row D-FIX-3 and
|
|
389
|
+
// {@link BUILDER_VERB}'s doc.
|
|
390
|
+
const chain = ref.name === "uri" ? CHAIN_PATTERN.exec(ref.receiver) : null;
|
|
391
|
+
if (chain !== null) {
|
|
392
|
+
// Both groups are guaranteed by `CHAIN_PATTERN`'s two capturing groups
|
|
393
|
+
// once `exec` succeeds — `noUncheckedIndexedAccess` cannot see that from
|
|
394
|
+
// the pattern alone.
|
|
395
|
+
const base = chain[1];
|
|
396
|
+
const opener = chain[2];
|
|
397
|
+
const receiverType = typeOfReceiver(base);
|
|
398
|
+
if (receiverType === undefined || !CLIENT_TYPES.has(receiverType))
|
|
399
|
+
continue;
|
|
400
|
+
const refuse = (reason, diagnosis) => {
|
|
401
|
+
refusals.push({ fromId, raw: ref.raw, line: ref.line, reason, ...diagnosis });
|
|
402
|
+
};
|
|
403
|
+
const verb = BUILDER_VERB[opener];
|
|
404
|
+
if (verb === undefined) {
|
|
405
|
+
refuse(`an HTTP call through ${receiverType}, but \`${opener}\` takes its method as a ` +
|
|
406
|
+
`separate argument — an enum reference this adapter does not read. Refused rather ` +
|
|
407
|
+
`than defaulted to GET: a wrong verb mints an endpoint that joins the wrong route, ` +
|
|
408
|
+
`or none, and root-cause traversal would follow it.`, CAPABILITY_GAP);
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
readPathAndEmit(receiverType, ref, verb, refuse);
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
const receiverType = typeOfReceiver(ref.receiver);
|
|
415
|
+
if (receiverType === undefined)
|
|
416
|
+
continue;
|
|
417
|
+
const refuse = (reason, diagnosis) => {
|
|
418
|
+
refusals.push({ fromId, raw: ref.raw, line: ref.line, reason, ...diagnosis });
|
|
419
|
+
};
|
|
420
|
+
const builderMethods = BUILDER_CLIENT_TYPES[receiverType];
|
|
421
|
+
if (builderMethods?.has(ref.name) === true) {
|
|
422
|
+
refuse(`an HTTP call through ${receiverType}, via a request object built in a separate expression ` +
|
|
423
|
+
`— this adapter reads only a path passed directly as this call's own argument, not one ` +
|
|
424
|
+
`assembled through a separate constructor or builder chain and passed in.`, CAPABILITY_GAP);
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
if (WEBCLIENT_SPLIT_BUILDER_TYPES.has(receiverType) && ref.name === "uri") {
|
|
428
|
+
refuse(`a WebClient/RestClient \`.uri(...)\` call through a ${receiverType} held in a variable — ` +
|
|
429
|
+
`the opening \`.get()\`/\`.post()\`/... call that carries the verb is a separate statement ` +
|
|
430
|
+
`this adapter does not trace back to, so the verb is unrecoverable here even though the ` +
|
|
431
|
+
`path is a literal. See ledger row D-FIX-3's split-variable case.`, CAPABILITY_GAP);
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
if (!CLIENT_TYPES.has(receiverType))
|
|
435
|
+
continue;
|
|
436
|
+
if (!URL_FIRST.has(ref.name))
|
|
437
|
+
continue;
|
|
438
|
+
const verb = VERB[ref.name];
|
|
439
|
+
if (verb === undefined) {
|
|
440
|
+
refuse(`an HTTP call through ${receiverType}, but \`${ref.name}\` takes its method as a ` +
|
|
441
|
+
`separate argument — an enum reference this adapter does not read. Refused rather ` +
|
|
442
|
+
`than defaulted to GET: a wrong verb mints an endpoint that joins the wrong route, ` +
|
|
443
|
+
`or none, and root-cause traversal would follow it.`, CAPABILITY_GAP);
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
readPathAndEmit(receiverType, ref, verb, refuse);
|
|
447
|
+
}
|
|
448
|
+
return { calls, refusals };
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* The `API_ENDPOINT` a call joins to — minted identically to the route side.
|
|
452
|
+
*
|
|
453
|
+
* Shares `endpointQsp` with `extract.ts`'s `SERVES_API` block rather than
|
|
454
|
+
* recomputing the id, because the two must agree exactly and the failure when
|
|
455
|
+
* they do not is silent.
|
|
456
|
+
*/
|
|
457
|
+
export function endpointFor(scope, call, producedBy, normalise) {
|
|
458
|
+
const template = normalise(call.template);
|
|
459
|
+
return {
|
|
460
|
+
id: nodeId(scope, "API_ENDPOINT", endpointQsp(call.verb, call.template), null),
|
|
461
|
+
type: "API_ENDPOINT",
|
|
462
|
+
name: `${call.verb} ${template}`,
|
|
463
|
+
file: null,
|
|
464
|
+
range: null,
|
|
465
|
+
language: null,
|
|
466
|
+
producedBy,
|
|
467
|
+
resolution: 2,
|
|
468
|
+
attrs: { method: call.verb, pathTemplate: template },
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Java units to Canonical IR.
|
|
3
|
+
*
|
|
4
|
+
* ## Why a breadth adapter reaches further in Java than in most languages
|
|
5
|
+
*
|
|
6
|
+
* Every import is explicit and fully qualified, every field and parameter
|
|
7
|
+
* carries a written type, and a public type's simple name is its file's name.
|
|
8
|
+
* None of that needs a type checker to read, so `repo.findById(id)` resolves
|
|
9
|
+
* from the declaration `private final OwnerRepository repo` alone — a call
|
|
10
|
+
* through a receiver, which in TypeScript needed R3.
|
|
11
|
+
*
|
|
12
|
+
* That is read as **R2 evidence, and never R3**. R2 is a reference resolved to a
|
|
13
|
+
* specific definition, which is exactly what happens here — the level names the
|
|
14
|
+
* evidence, not the machinery, and Java hands over the same evidence an LSP
|
|
15
|
+
* would without one being run. R3 is a *checked shape*, and a written annotation
|
|
16
|
+
* is not one: it can be shadowed, it can be generic, and nothing here verifies
|
|
17
|
+
* which overload the compiler would select. Claiming R3 for a name-level fact is
|
|
18
|
+
* the confusion DEC-058 was written about, where 83% of an adapter's edges
|
|
19
|
+
* claimed a level they had not earned.
|
|
20
|
+
*
|
|
21
|
+
* `IMPORTS` stays at R1. An import is module resolution and nothing more.
|
|
22
|
+
*
|
|
23
|
+
* ## What is deliberately not resolved
|
|
24
|
+
*
|
|
25
|
+
* `var` declarations, chained calls whose receiver is another call, generic type
|
|
26
|
+
* variables, and any name reachable only through a wildcard import that matches
|
|
27
|
+
* more than one analysed type. Each goes to the ledger with its reason. A
|
|
28
|
+
* missing edge is a disclosed gap; a guessed one corrupts every layer above.
|
|
29
|
+
*/
|
|
30
|
+
import { type IdentityScope, type IREdge, type IRNode, type ResolutionLevel, type UnresolvedRef } from "@descryy/ir";
|
|
31
|
+
import type { JavaUnit } from "./parse.ts";
|
|
32
|
+
export declare const LANGUAGE = "java";
|
|
33
|
+
/** A compilation unit with no `package` declaration. Not a legal package name,
|
|
34
|
+
* so it cannot collide with one. */
|
|
35
|
+
export declare const DEFAULT_PACKAGE = "(default)";
|
|
36
|
+
export interface ExtractInput {
|
|
37
|
+
readonly repo: string;
|
|
38
|
+
readonly scope: IdentityScope;
|
|
39
|
+
readonly producedBy: string;
|
|
40
|
+
readonly reached: ResolutionLevel;
|
|
41
|
+
readonly units: readonly JavaUnit[];
|
|
42
|
+
}
|
|
43
|
+
export interface Extraction {
|
|
44
|
+
readonly nodes: readonly IRNode[];
|
|
45
|
+
readonly edges: readonly IREdge[];
|
|
46
|
+
readonly unresolved: readonly UnresolvedRef[];
|
|
47
|
+
}
|
|
48
|
+
export declare function extract(input: ExtractInput): Extraction;
|
|
49
|
+
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAiC,QAAQ,EAAE,MAAM,YAAY,CAAC;AAK1E,eAAO,MAAM,QAAQ,SAAS,CAAC;AAK/B;qCACqC;AACrC,eAAO,MAAM,eAAe,cAAc,CAAC;AAwC3C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;CAC/C;AAwJD,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,UAAU,CA+vBvD"}
|