@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
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Java `LanguageAdapter` — all seven methods, breadth tier.
|
|
3
|
+
*
|
|
4
|
+
* The parser is tree-sitter's Java grammar over the shared WASM harness. There
|
|
5
|
+
* is no JDT and no SCIP, and `capabilities()` says so rather than leaving it to
|
|
6
|
+
* be inferred from an empty result.
|
|
7
|
+
*
|
|
8
|
+
* Framework extractors for **Spring** (`spring.ts`) and **JPA** (`jpa.ts`) are
|
|
9
|
+
* bound. Both read declarations rather than names, and both are the FLOOR under
|
|
10
|
+
* DEC-115 — framework introspection would be a promotion over the same node ids
|
|
11
|
+
* and needs a runnable application, which no corpus here is.
|
|
12
|
+
*/
|
|
13
|
+
import { type LanguageAdapter, type ResolutionLevel } from "@descryy/ir";
|
|
14
|
+
import { toRepoRelative } from "@descryy/adapter-common";
|
|
15
|
+
import { LANGUAGE } from "./extract.ts";
|
|
16
|
+
export declare const ADAPTER_ID = "adapter-java";
|
|
17
|
+
export declare const ADAPTER_VERSION = "0.1.0";
|
|
18
|
+
export declare const DEFAULT_JAVA_GLOBS: readonly ["**/*.java"];
|
|
19
|
+
export interface JavaAdapterOptions {
|
|
20
|
+
readonly globs?: readonly string[];
|
|
21
|
+
readonly maxResolution?: ResolutionLevel;
|
|
22
|
+
}
|
|
23
|
+
export interface JavaAdapter extends LanguageAdapter {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly version: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function createJavaAdapter(options?: JavaAdapterOptions): JavaAdapter;
|
|
28
|
+
/** Content hash of a repo-relative file, for `FileRef`. */
|
|
29
|
+
export declare function hashOf(root: string, relative: string): string;
|
|
30
|
+
export { LANGUAGE, toRepoRelative };
|
|
31
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAML,KAAK,eAAe,EAGpB,KAAK,eAAe,EAIrB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAyB,cAAc,EAAwB,MAAM,yBAAyB,CAAC;AAItG,OAAO,EAA4B,QAAQ,EAAmB,MAAM,cAAc,CAAC;AAGnF,eAAO,MAAM,UAAU,iBAAiB,CAAC;AACzC,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,kBAAkB,wBAAyB,CAAC;AA8CzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,eAAe,CAAC;CAC1C;AAYD,MAAM,WAAW,WAAY,SAAQ,eAAe;IAClD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAwO/E;AAED,2DAA2D;AAC3D,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/adapter.js
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Java `LanguageAdapter` — all seven methods, breadth tier.
|
|
3
|
+
*
|
|
4
|
+
* The parser is tree-sitter's Java grammar over the shared WASM harness. There
|
|
5
|
+
* is no JDT and no SCIP, and `capabilities()` says so rather than leaving it to
|
|
6
|
+
* be inferred from an empty result.
|
|
7
|
+
*
|
|
8
|
+
* Framework extractors for **Spring** (`spring.ts`) and **JPA** (`jpa.ts`) are
|
|
9
|
+
* bound. Both read declarations rather than names, and both are the FLOOR under
|
|
10
|
+
* DEC-115 — framework introspection would be a promotion over the same node ids
|
|
11
|
+
* and needs a runnable application, which no corpus here is.
|
|
12
|
+
*/
|
|
13
|
+
import { createHash } from "node:crypto";
|
|
14
|
+
import { createRequire } from "node:module";
|
|
15
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { CLIENT_CALL_EXTRACTOR, ORM_EXTRACTOR, ROUTE_EXTRACTOR, } from "@descryy/ir";
|
|
18
|
+
import { discover, isolateFile, toRepoRelative } from "@descryy/adapter-common";
|
|
19
|
+
import { parserFor, parseText } from "@descryy/adapter-treesitter";
|
|
20
|
+
import { readUnit } from "./parse.js";
|
|
21
|
+
import { extract, DEFAULT_PACKAGE, LANGUAGE } from "./extract.js";
|
|
22
|
+
import { anchorOf, identityPackage, sourceRootOf } from "./roots.js";
|
|
23
|
+
export const ADAPTER_ID = "adapter-java";
|
|
24
|
+
export const ADAPTER_VERSION = "0.1.0";
|
|
25
|
+
export const DEFAULT_JAVA_GLOBS = ["**/*.java"];
|
|
26
|
+
const PRODUCED_BY = `${ADAPTER_ID}@${ADAPTER_VERSION}`;
|
|
27
|
+
/**
|
|
28
|
+
* The grammar, found the same way whether this module was compiled or stripped.
|
|
29
|
+
*
|
|
30
|
+
* A copy is shipped beside the compiled output so an installed package needs
|
|
31
|
+
* nothing resolved at run time. But `node --test` and the conformance runner
|
|
32
|
+
* load `src/*.ts` directly, where `import.meta.dirname` is `src` and the copy is
|
|
33
|
+
* in `dist` — so the declared dependency is the fallback, and it is the one that
|
|
34
|
+
* makes the source path work at all.
|
|
35
|
+
*/
|
|
36
|
+
function grammarPath() {
|
|
37
|
+
const beside = join(import.meta.dirname, "tree-sitter-java.wasm");
|
|
38
|
+
if (existsSync(beside))
|
|
39
|
+
return beside;
|
|
40
|
+
return createRequire(import.meta.url).resolve("tree-sitter-java/tree-sitter-java.wasm");
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Directories that hold build output rather than source.
|
|
44
|
+
*
|
|
45
|
+
* A Java repository routinely contains a generated or copied duplicate of its
|
|
46
|
+
* own classes, and analysing both produces two declarations of one type — a
|
|
47
|
+
* duplicate node id, the failure DEC-077 records arriving by another road.
|
|
48
|
+
*/
|
|
49
|
+
const BUILD_DIRECTORIES = ["/target/", "/build/", "/out/", "/bin/", "/.gradle/"];
|
|
50
|
+
/**
|
|
51
|
+
* Is this path build output rather than source?
|
|
52
|
+
*
|
|
53
|
+
* The name test alone is not safe, and that is not hypothetical: `build`, `bin`
|
|
54
|
+
* and `target` are ordinary package names, so `src/main/java/com/x/build/Cfg.java`
|
|
55
|
+
* is a source file that a bare substring match silently deletes from the graph.
|
|
56
|
+
* A declared source root settles it — anything under `src/` is source no matter
|
|
57
|
+
* what its packages are called, and the name test applies only outside one.
|
|
58
|
+
*
|
|
59
|
+
* This is the general form of the rule rather than the one that happened to work
|
|
60
|
+
* on the repositories in front of it.
|
|
61
|
+
*/
|
|
62
|
+
function isBuildOutput(file) {
|
|
63
|
+
const path = `/${file}`;
|
|
64
|
+
if (path.includes("/src/"))
|
|
65
|
+
return false;
|
|
66
|
+
return BUILD_DIRECTORIES.some((directory) => path.includes(directory));
|
|
67
|
+
}
|
|
68
|
+
export function createJavaAdapter(options = {}) {
|
|
69
|
+
const globs = options.globs ?? DEFAULT_JAVA_GLOBS;
|
|
70
|
+
const ceiling = options.maxResolution ?? 2;
|
|
71
|
+
let session;
|
|
72
|
+
let parser;
|
|
73
|
+
const filesUnder = (root) => discover(root.absolutePath, globs).filter((file) => !isBuildOutput(file));
|
|
74
|
+
return {
|
|
75
|
+
id: ADAPTER_ID,
|
|
76
|
+
version: ADAPTER_VERSION,
|
|
77
|
+
async detect(root) {
|
|
78
|
+
const files = filesUnder(root);
|
|
79
|
+
const evidence = [];
|
|
80
|
+
if (files.length > 0)
|
|
81
|
+
evidence.push(`${files.length} .java files outside build directories`);
|
|
82
|
+
for (const manifest of ["pom.xml", "build.gradle", "build.gradle.kts", "settings.gradle"]) {
|
|
83
|
+
try {
|
|
84
|
+
readFileSync(join(root.absolutePath, manifest));
|
|
85
|
+
evidence.push(`${manifest} at the repository root`);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Absent. A build manifest is corroboration, not a requirement — a
|
|
89
|
+
// source tree with no manifest is still Java.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { detected: files.length > 0, roots: files.length > 0 ? [root.absolutePath] : [], evidence };
|
|
93
|
+
},
|
|
94
|
+
capabilities() {
|
|
95
|
+
return {
|
|
96
|
+
maxResolution: ceiling,
|
|
97
|
+
/**
|
|
98
|
+
* `API_ROUTE`, `API_ENDPOINT` and `MODEL` are now claimed, because the
|
|
99
|
+
* Spring and JPA extractors earn them from **declarations** — an
|
|
100
|
+
* annotation the framework itself acts on — rather than from a name.
|
|
101
|
+
* DEC-043's objection was to the name heuristic, not to the node types.
|
|
102
|
+
*
|
|
103
|
+
* `DTO` stays absent, and golden 07's note says why: in the corpus
|
|
104
|
+
* `Order` and `CreateOrderRequest` are structurally identical and
|
|
105
|
+
* separable only by their names. `@Entity` distinguishes the model;
|
|
106
|
+
* nothing distinguishes the DTO, so nothing claims it.
|
|
107
|
+
*
|
|
108
|
+
* `frameworkExtractors` and `frameworkCapabilities` are declared
|
|
109
|
+
* together, in the change that ships the extractors and not before:
|
|
110
|
+
* `run.ts` skips a pattern requiring a capability only while nothing is
|
|
111
|
+
* bound, so declaring early turns skips into failures.
|
|
112
|
+
*
|
|
113
|
+
* `USES_API` and `client-call-extractor` (`frameworkCapabilities`) are
|
|
114
|
+
* both claimed. `client.ts` (D-FIX-3, DEC-241) genuinely extracts real
|
|
115
|
+
* `USES_API` edges from `RestTemplate`/`WebClient` calls with a literal
|
|
116
|
+
* path, measured live on `shopizer` (9 edges) and `spring-petclinic`
|
|
117
|
+
* (0 edges, an honest zero — see DEC-260).
|
|
118
|
+
*
|
|
119
|
+
* `CLIENT_CALL_EXTRACTOR` was declared, reverted, then declared again —
|
|
120
|
+
* DEC-262 and DEC-246 both have the measurement, in that order.
|
|
121
|
+
* DEC-262 found it correctly unverifiable by the corpus as it then
|
|
122
|
+
* stood: golden pattern 08's caller role (`order_page`) requires a real
|
|
123
|
+
* HTTP call, and the Java fixture's `OrderPage.render()` called
|
|
124
|
+
* `routes.getOrder(id)` in-process, not through any HTTP client shape
|
|
125
|
+
* at all — no fixture change could earn a pass without inventing that
|
|
126
|
+
* shape. DEC-246 built it: `OrderPage.render()` now calls
|
|
127
|
+
* `restTemplate.getForObject("/orders/{id}", ...)`, the same URI-
|
|
128
|
+
* template form Python's and Kotlin's `order_page` already use for the
|
|
129
|
+
* identical role, and pattern 08 now **passes**, not merely skips.
|
|
130
|
+
*
|
|
131
|
+
* `client-base-extractor` stays absent — `client.ts` reads a call's own
|
|
132
|
+
* literal path, never a base URL composed separately, so patterns
|
|
133
|
+
* 08a/08b/08c (DEC-164's strict base-resolution contract) are a
|
|
134
|
+
* different, unaddressed row.
|
|
135
|
+
*/
|
|
136
|
+
nodeTypes: ["MODULE", "CLASS", "FUNCTION", "TEST_CASE", "API_ROUTE", "API_ENDPOINT", "MODEL"],
|
|
137
|
+
edgeTypes: [
|
|
138
|
+
"IMPORTS",
|
|
139
|
+
"CALLS",
|
|
140
|
+
"TESTS",
|
|
141
|
+
"INHERITS",
|
|
142
|
+
"IMPLEMENTS",
|
|
143
|
+
"USES_TYPE",
|
|
144
|
+
"SERVES_API",
|
|
145
|
+
"USES_API",
|
|
146
|
+
],
|
|
147
|
+
hasCallHierarchy: false,
|
|
148
|
+
hasTypeHierarchy: false,
|
|
149
|
+
/**
|
|
150
|
+
* Directories this ecosystem installs dependencies or build output into —
|
|
151
|
+
* DEC-110's end state. The engine used to hold `node_modules`/`vendor`/`target`
|
|
152
|
+
* in a hardcoded list; it holds none of them now and consumes this instead.
|
|
153
|
+
*
|
|
154
|
+
* Maven writes `target/`, Gradle writes `build/`, by those tools' own convention.
|
|
155
|
+
* Declared from the build tools rather than from an existing exclusion, because
|
|
156
|
+
* this adapter has none — its file walk is source-root driven.
|
|
157
|
+
*
|
|
158
|
+
* Names only — the walk matches one path component, so a path or glob matches
|
|
159
|
+
* nothing. Nothing dotted — those are skipped structurally already.
|
|
160
|
+
*/
|
|
161
|
+
noiseDirectories: ["target", "build"],
|
|
162
|
+
// `jaxrs` and `spring-data-mongodb` were added under `language-problems.md`
|
|
163
|
+
// §3's rows 1-3: JAX-RS gets its own route reader in `spring.ts`
|
|
164
|
+
// (`jaxrsRoutes`) rather than being folded into `spring`'s name, because
|
|
165
|
+
// it is a materially different framework reachable without Spring at
|
|
166
|
+
// all; `spring-data-mongodb` names `jpa.ts`'s `@Document` admission
|
|
167
|
+
// rather than a new file, since the field/nullability machinery is
|
|
168
|
+
// shared verbatim with JPA.
|
|
169
|
+
frameworkExtractors: ["spring", "jaxrs", "jpa", "spring-data-mongodb", "client-call-extractor"],
|
|
170
|
+
frameworkCapabilities: [ROUTE_EXTRACTOR, ORM_EXTRACTOR, CLIENT_CALL_EXTRACTOR],
|
|
171
|
+
};
|
|
172
|
+
},
|
|
173
|
+
async prepare(ctx) {
|
|
174
|
+
const files = filesUnder(ctx.root);
|
|
175
|
+
parser ??= await parserFor(grammarPath());
|
|
176
|
+
const units = [];
|
|
177
|
+
const failures = [];
|
|
178
|
+
const unfinished = [];
|
|
179
|
+
const anchors = new Map();
|
|
180
|
+
for (const file of files) {
|
|
181
|
+
if (ctx.signal.aborted)
|
|
182
|
+
break;
|
|
183
|
+
let text;
|
|
184
|
+
try {
|
|
185
|
+
text = readFileSync(join(ctx.root.absolutePath, file), "utf8");
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
failures.push({ kind: "unreadable", file, detail: error instanceof Error ? error.message : String(error) });
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
const outcome = parseText(parser, file, text);
|
|
192
|
+
if (outcome.tree === undefined) {
|
|
193
|
+
if (outcome.failure !== undefined)
|
|
194
|
+
failures.push(outcome.failure);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
// Isolated: a throw in the walk used to cost the run rather than the file.
|
|
198
|
+
const read = isolateFile(file, () => readUnit(outcome.tree.rootNode, file, outcome.tree.rootNode.hasError));
|
|
199
|
+
if (read.failure !== undefined) {
|
|
200
|
+
unfinished.push(read.failure);
|
|
201
|
+
outcome.tree.delete();
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const unit = read.value;
|
|
205
|
+
// The build module and source set are on disk, not in the syntax, so
|
|
206
|
+
// they are resolved here and cached — one `existsSync` walk per source
|
|
207
|
+
// root rather than per file.
|
|
208
|
+
const sourceRoot = sourceRootOf(file, unit.packageName);
|
|
209
|
+
let anchor = sourceRoot === undefined ? undefined : anchors.get(sourceRoot);
|
|
210
|
+
if (anchor === undefined && sourceRoot !== undefined) {
|
|
211
|
+
anchor = anchorOf(ctx.root.absolutePath, sourceRoot);
|
|
212
|
+
anchors.set(sourceRoot, anchor);
|
|
213
|
+
}
|
|
214
|
+
units.push({
|
|
215
|
+
...unit,
|
|
216
|
+
identityPackage: anchor === undefined
|
|
217
|
+
? // The file does not sit where its package declaration says it
|
|
218
|
+
// should. Rather than invent a module for it, it anchors on its
|
|
219
|
+
// package alone and the ambiguity that may cause is disclosed by
|
|
220
|
+
// the resolver rather than hidden by a guess here.
|
|
221
|
+
unit.packageName === "" ? DEFAULT_PACKAGE : unit.packageName
|
|
222
|
+
: identityPackage(anchor, unit.packageName, DEFAULT_PACKAGE),
|
|
223
|
+
});
|
|
224
|
+
outcome.tree.delete();
|
|
225
|
+
}
|
|
226
|
+
// Every level this adapter offers rests on the same parse: imports are in
|
|
227
|
+
// the source, so R1 is reached whenever parsing succeeded at all. There is
|
|
228
|
+
// no rung between 0 and the ceiling to fall back to.
|
|
229
|
+
const reached = units.length === 0 ? 0 : ceiling;
|
|
230
|
+
session = { root: ctx.root, files, units, reached, failures, unfinished };
|
|
231
|
+
return reached;
|
|
232
|
+
},
|
|
233
|
+
async parseFiles(files) {
|
|
234
|
+
// Independent of `prepare` by contract: R0 must be achievable with nothing
|
|
235
|
+
// resolved. The unit is the parsed record when one exists and an empty
|
|
236
|
+
// placeholder otherwise, because the caller owns the file list.
|
|
237
|
+
const byFile = new Map((session?.units ?? []).map((unit) => [unit.file, unit]));
|
|
238
|
+
return files.map((file) => ({ file, tree: byFile.get(file.path) ?? {} }));
|
|
239
|
+
},
|
|
240
|
+
extractNodes() {
|
|
241
|
+
return current().nodes;
|
|
242
|
+
},
|
|
243
|
+
extractEdges() {
|
|
244
|
+
return current().edges;
|
|
245
|
+
},
|
|
246
|
+
async emit(ctx) {
|
|
247
|
+
const reached = await this.prepare(ctx);
|
|
248
|
+
const active = session;
|
|
249
|
+
const extraction = current();
|
|
250
|
+
const failedFiles = new Set([...active.failures.map((f) => f.file), ...active.unfinished.map((f) => f.file)]);
|
|
251
|
+
return {
|
|
252
|
+
repo: ctx.root.repo,
|
|
253
|
+
...(ctx.root.workspace === undefined ? {} : { workspace: ctx.root.workspace }),
|
|
254
|
+
commitSha: ctx.root.commitSha,
|
|
255
|
+
producedBy: PRODUCED_BY,
|
|
256
|
+
sourceFiles: active.files.filter((f) => !failedFiles.has(f)),
|
|
257
|
+
skippedFiles: [
|
|
258
|
+
...active.failures.map((f) => ({ file: f.file, reason: f.kind, detail: f.detail })),
|
|
259
|
+
// `other`: it parsed, and what failed is our walk of it. The detail says which.
|
|
260
|
+
...active.unfinished.map((f) => ({ file: f.file, reason: "other", detail: f.detail })),
|
|
261
|
+
],
|
|
262
|
+
reachedResolution: reached,
|
|
263
|
+
nodes: extraction.nodes,
|
|
264
|
+
edges: extraction.edges,
|
|
265
|
+
unresolved: extraction.unresolved,
|
|
266
|
+
};
|
|
267
|
+
},
|
|
268
|
+
async dispose() {
|
|
269
|
+
session = undefined;
|
|
270
|
+
parser?.delete();
|
|
271
|
+
parser = undefined;
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
function current() {
|
|
275
|
+
const active = session;
|
|
276
|
+
if (active === undefined || active.units.length === 0) {
|
|
277
|
+
return { nodes: [], edges: [], unresolved: [] };
|
|
278
|
+
}
|
|
279
|
+
return extract({
|
|
280
|
+
repo: active.root.repo,
|
|
281
|
+
scope: { repo: active.root.repo, ...(active.root.workspace === undefined ? {} : { workspace: active.root.workspace }) },
|
|
282
|
+
producedBy: PRODUCED_BY,
|
|
283
|
+
reached: active.reached,
|
|
284
|
+
units: active.units,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/** Content hash of a repo-relative file, for `FileRef`. */
|
|
289
|
+
export function hashOf(root, relative) {
|
|
290
|
+
try {
|
|
291
|
+
return createHash("sha256").update(readFileSync(join(root, relative))).digest("hex").slice(0, 32);
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
return "";
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
export { LANGUAGE, toRepoRelative };
|
|
298
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
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 { type IdentityScope, type IRNode } from "@descryy/ir";
|
|
103
|
+
import type { JavaMethod, JavaRef } from "./parse.ts";
|
|
104
|
+
export interface ClientCall {
|
|
105
|
+
/** The `FUNCTION` node making the call. */
|
|
106
|
+
readonly fromId: string;
|
|
107
|
+
readonly method: string;
|
|
108
|
+
readonly template: string;
|
|
109
|
+
readonly verb: string;
|
|
110
|
+
readonly line: number;
|
|
111
|
+
/** `test` when the enclosing method is a test case, else `production`. */
|
|
112
|
+
readonly callerKind: "test" | "production";
|
|
113
|
+
}
|
|
114
|
+
export interface ClientRefusal {
|
|
115
|
+
readonly fromId: string;
|
|
116
|
+
readonly raw: string;
|
|
117
|
+
readonly line: number;
|
|
118
|
+
readonly reason: string;
|
|
119
|
+
/** DEC-242's `attrs.blockedBy` — the literal blocking expression, or `null`. */
|
|
120
|
+
readonly blockedBy: string | null;
|
|
121
|
+
/** DEC-242's `attrs.refusalClass` — `undefined` means unclassified, never askable. */
|
|
122
|
+
readonly refusalClass: BaseRefusalClass | "out-of-scope" | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* Diagnostic only, not part of DEC-242 — see `adapter-rust/src/client.ts`'s
|
|
125
|
+
* own doc for what this is and why it is not shipped as part of the
|
|
126
|
+
* contract. Present only on the generic fallthrough of `diagnoseArgument`.
|
|
127
|
+
*/
|
|
128
|
+
readonly argumentKind?: "field" | "call" | "concatenation" | "other";
|
|
129
|
+
}
|
|
130
|
+
export type BaseRefusalClass = "value-unknown" | "varies-per-call" | "capability-gap";
|
|
131
|
+
/**
|
|
132
|
+
* Every reference in a method that {@link clientCalls} will act on — an edge,
|
|
133
|
+
* a refusal, or (only past this point, where the receiver's type is unknown)
|
|
134
|
+
* a true silence. Factored out of the loop below so the reconciliation
|
|
135
|
+
* assertion in `test/client.test.ts` recomputes candidacy independently of
|
|
136
|
+
* whatever the loop does with each candidate: a future edit that narrows the
|
|
137
|
+
* loop's own filter without touching this function fails the test instead of
|
|
138
|
+
* silently dropping call sites the way DEC-098's `containerOf` guard did.
|
|
139
|
+
*
|
|
140
|
+
* Receiver-type resolution is deliberately **not** done here — it needs
|
|
141
|
+
* `extract.ts`'s scope tables, which this module does not have — so a
|
|
142
|
+
* candidate here may still turn out to be a true silence in
|
|
143
|
+
* {@link clientCalls} if `typeOfReceiver` returns `undefined`. That is the
|
|
144
|
+
* one gap this reconciliation cannot close, and it is the same gap every
|
|
145
|
+
* other refusal ledger in this project discloses rather than guesses past:
|
|
146
|
+
* an unresolved receiver is not evidence the call is or is not a client.
|
|
147
|
+
*/
|
|
148
|
+
export declare function candidateClientRefs(method: JavaMethod): readonly (JavaRef & {
|
|
149
|
+
readonly receiver: string;
|
|
150
|
+
})[];
|
|
151
|
+
/**
|
|
152
|
+
* Read one method's calls for outbound HTTP.
|
|
153
|
+
*
|
|
154
|
+
* `typeOfReceiver` resolves a receiver name to its declared type's simple name
|
|
155
|
+
* and is supplied by the caller, because the scope rules for that live in
|
|
156
|
+
* `extract.ts` and a second copy of them would drift — the failure that
|
|
157
|
+
* `scopesFor`'s own header records.
|
|
158
|
+
*/
|
|
159
|
+
export declare function clientCalls(method: JavaMethod, fromId: string, typeOfReceiver: (name: string) => string | undefined, inTestSourceSet: boolean): {
|
|
160
|
+
readonly calls: readonly ClientCall[];
|
|
161
|
+
readonly refusals: readonly ClientRefusal[];
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* The `API_ENDPOINT` a call joins to — minted identically to the route side.
|
|
165
|
+
*
|
|
166
|
+
* Shares `endpointQsp` with `extract.ts`'s `SERVES_API` block rather than
|
|
167
|
+
* recomputing the id, because the two must agree exactly and the failure when
|
|
168
|
+
* they do not is silent.
|
|
169
|
+
*/
|
|
170
|
+
export declare function endpointFor(scope: IdentityScope, call: ClientCall, producedBy: string, normalise: (template: string) => string): IRNode;
|
|
171
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoGG;AAEH,OAAO,EAAuB,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAEnF,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAkItD,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,sFAAsF;IACtF,QAAQ,CAAC,YAAY,EAAE,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAC;IACrE;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,eAAe,GAAG,OAAO,CAAC;CACtE;AAoBD,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAgFtF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,GACjB,SAAS,CAAC,OAAO,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,CAQtD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EACpD,eAAe,EAAE,OAAO,GACvB;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,CA+JxF;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GACtC,MAAM,CAaR"}
|