@descryy/adapter-java 0.4.1 → 0.5.1

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.
@@ -0,0 +1,262 @@
1
+ /**
2
+ * The dependency boundary, Java side.
3
+ *
4
+ * `LoggerFactory.getLogger(Foo.class)` leaves the repository. Today that becomes
5
+ * a ledger row saying "names a type this run did not analyse" and the call graph
6
+ * stops. This module answers the one question that turns the boundary into a
7
+ * fact the graph can hold: **which package, and which symbol in it.**
8
+ *
9
+ * ## The rule everything here rests on: attribute only from a binding the
10
+ * developer wrote
11
+ *
12
+ * In Go (`adapter-go/src/external.ts`, the model for this file) that binding is
13
+ * the file's own `import` block. Java's is the same statement, and it is the
14
+ * cleanest of the ten: `import org.slf4j.Logger;` binds the simple name `Logger`
15
+ * to a fully-qualified name **written in the file**, and `import static
16
+ * org.junit.jupiter.api.Assertions.assertEquals;` binds a bare member name to
17
+ * the type that declares it. Nothing here reads `pom.xml`'s dependency list, a
18
+ * Gradle configuration, `~/.m2`, or a jar. Two reasons, the same two Go gives:
19
+ *
20
+ * 1. Most checkouts have no dependencies fetched, so an identity taken from a
21
+ * resolved classpath would exist for some runs and not others.
22
+ * 2. It would *move* the first time somebody ran `mvn dependency:resolve`.
23
+ *
24
+ * ## Why the Maven coordinate is not the identity
25
+ *
26
+ * `org.slf4j:slf4j-api` is the obvious answer and it is the one this module
27
+ * refuses. A jar's package-to-coordinate mapping lives in the jar, and the root
28
+ * `pom.xml`'s `<dependencies>` block binds a coordinate to no package at all —
29
+ * so there is no declared mapping to read without the resolved classpath. The
30
+ * **package** is written, in the import statement, by the developer, in the
31
+ * file. So the package is the identity, exactly as Go's import path is Go's and
32
+ * PHP's namespace is PHP's.
33
+ *
34
+ * ## The three shapes Java attributes, and what each costs
35
+ *
36
+ * - `import a.b.C;` … `C x` or `C.m()` — a single-type import. The direct
37
+ * analogue of Go's package-qualified call.
38
+ * - `import a.b.C;` … `C x; x.m()` — a call through a local or field whose
39
+ * **written type** is an imported name. Java writes its types down where Go
40
+ * and PHP do not, and this is the half that makes Java worth doing.
41
+ * - `import static a.b.C.m;` … `m()` — a bare name bound by a static import.
42
+ * This is how every JUnit assertion is written, so without it a test file's
43
+ * calls are almost entirely unattributable. Python's `from x import y` is
44
+ * the same shape and was the larger half there too.
45
+ *
46
+ * ## What Java makes harder than Go, and the refusals it earns
47
+ *
48
+ * Go has no fallback: an unqualified name is package-local, full stop. Java has
49
+ * three, and none of them is a binding a developer wrote:
50
+ *
51
+ * - **`java.lang` is imported implicitly.** `String`, `Integer`, `Exception`
52
+ * appear with no import statement anywhere. A language rule filling a
53
+ * silence is not a written binding, so they are declined — the same call
54
+ * PHP's `external.ts` makes about its global-namespace fallback.
55
+ * - **A wildcard import binds no name.** `import java.util.*;` then `List`
56
+ * could be `java.util.List` or a type from any other wildcard in the file,
57
+ * and telling them apart needs the classpath this module refuses to read.
58
+ * Python's `from x import *` refusal, for the same reason.
59
+ * - **Same-package types resolve without an import.** A name settled that way
60
+ * is ours by construction, and `resolveType` has already claimed it.
61
+ *
62
+ * One more refusal is Java-specific and is a **precision** refusal rather than a
63
+ * recall one: `extract.ts`'s `REASONS.outside` discloses that some `outside`
64
+ * rows are declarations in *another language in this same repository* — 238 of
65
+ * `okhttp`'s 458 are in `.kt` files. The own-package check below is what keeps
66
+ * those from being called dependencies, and it is whole-segment, so a Kotlin
67
+ * class in a package this repository's Java sources also declare is ours.
68
+ *
69
+ * **Everything this module does not attribute is a deliberate refusal.** Rule 2
70
+ * prices a wrong edge far above a missing one.
71
+ */
72
+ /**
73
+ * Provenance of the platform-package list, carried on every attributed node.
74
+ * A property of the language and its JDK, frozen into this source — never read
75
+ * from whatever JDK a developer happens to have installed, which would make the
76
+ * answer depend on the machine.
77
+ *
78
+ * `javax` is split rather than taken whole: `javax.swing` ships with the JDK and
79
+ * `javax.persistence` never did. Taking the whole prefix either way is a wrong
80
+ * disclosure on thousands of nodes, and the list is short enough to write down.
81
+ */
82
+ export const PLATFORM_BASIS = "jdk-21 java./jdk./sun./com.sun. roots, plus the JDK's own javax subpackages";
83
+ /** Package roots the JDK owns outright. */
84
+ const PLATFORM_ROOTS = ["java", "jdk", "sun", "com.sun"];
85
+ /** The `javax` subpackages the JDK ships. Everything else under `javax` is a jar. */
86
+ const PLATFORM_JAVAX = new Set([
87
+ "javax.accessibility", "javax.annotation", "javax.crypto", "javax.imageio",
88
+ "javax.lang", "javax.management", "javax.naming", "javax.net", "javax.print",
89
+ "javax.rmi", "javax.script", "javax.security", "javax.smartcardio", "javax.sound",
90
+ "javax.sql", "javax.swing", "javax.tools", "javax.transaction", "javax.xml",
91
+ ]);
92
+ /**
93
+ * The packages whose whole purpose is to make a call target dynamic.
94
+ *
95
+ * `java.lang.reflect.Method.invoke` and `java.lang.invoke`'s method handles are
96
+ * where a Java call graph deliberately stops being readable, and golden pattern
97
+ * 12 — the corpus's most important fixture — forbids a `CALLS` edge out of a
98
+ * method that dispatches through them *to any target at any resolution*. The
99
+ * edge this module would otherwise mint is true (`method.invoke` really does
100
+ * reach `Method.invoke`), and it is still the one edge that pattern exists to
101
+ * forbid: it makes a traversal look as though it continued through a site where
102
+ * the graph cannot see the next hop.
103
+ *
104
+ * So these are declined, and the cost is disclosed rather than argued away:
105
+ * measured at 3 nodes and 3 edges on `airbyte`, and 0 of either on
106
+ * `spring-petclinic`. Neither subject moved a recall point.
107
+ * Filed as `DEC-NEXT-external-nodes-through-the-reflection-packages`.
108
+ */
109
+ const DYNAMIC_DISPATCH_PACKAGES = ["java.lang.reflect", "java.lang.invoke"];
110
+ /** Is `name` the package `prefix`, or inside it? Whole segments only — a raw
111
+ * `startsWith` would put `com.acme.servicebus` inside `com.acme.service`, which
112
+ * is the vendor-namespace hazard rule 2 prices above a missing edge. */
113
+ function isUnder(name, prefix) {
114
+ return name === prefix || name.startsWith(`${prefix}.`);
115
+ }
116
+ function isPlatform(pkg) {
117
+ for (const root of PLATFORM_ROOTS) {
118
+ if (isUnder(pkg, root))
119
+ return true;
120
+ }
121
+ const head = pkg.split(".").slice(0, 2).join(".");
122
+ return PLATFORM_JAVAX.has(head);
123
+ }
124
+ /** A package segment, by Java's own naming convention: packages are lowercase
125
+ * and types are capitalised. Read from the source text and nothing else — the
126
+ * alternative is the classpath, which this module does not read. */
127
+ function isPackageSegment(segment) {
128
+ return /^[a-z_$]/.test(segment);
129
+ }
130
+ /**
131
+ * A fully-qualified name split into the package that names it and the symbol
132
+ * chain inside it: `java.util.Map.Entry` -> `java.util` + `Map.Entry`.
133
+ *
134
+ * `null` when the convention does not settle it — no lowercase prefix (a
135
+ * default-package name, or a name already inside a type) or no capitalised
136
+ * segment at all (`foo.bar.baz`, which is a value traversal and not a type).
137
+ */
138
+ export function splitQualifiedName(fqn) {
139
+ const parts = fqn.split(".");
140
+ if (parts.some((part) => part === ""))
141
+ return null;
142
+ let cut = 0;
143
+ while (cut < parts.length && isPackageSegment(parts[cut]))
144
+ cut += 1;
145
+ if (cut === 0 || cut === parts.length)
146
+ return null;
147
+ return { pkg: parts.slice(0, cut).join("."), symbols: parts.slice(cut) };
148
+ }
149
+ /** Generic arguments and array brackets are not part of a name's identity, and
150
+ * the type arguments inside them are separate references the extractor already
151
+ * files on their own. */
152
+ export function bareTypeName(written) {
153
+ const cut = written.indexOf("<");
154
+ const head = (cut === -1 ? written : written.slice(0, cut)).trim();
155
+ return head.replace(/(\[\s*\])+$/, "").replace(/\.\.\.$/, "").trim();
156
+ }
157
+ /** The fully-qualified name a written type resolves to, and what bound it. */
158
+ function qualify(written, imports) {
159
+ const name = bareTypeName(written);
160
+ if (name === "")
161
+ return null;
162
+ const separator = name.indexOf(".");
163
+ const head = separator === -1 ? name : name.slice(0, separator);
164
+ const imported = imports.singleTypeImports.get(head);
165
+ if (imported !== undefined && imported !== "") {
166
+ const rest = separator === -1 ? "" : name.slice(separator + 1);
167
+ return { fqn: rest === "" ? imported : `${imported}.${rest}`, binding: "single-type-import" };
168
+ }
169
+ // Written out in full at the reference. The developer wrote every segment, so
170
+ // it is as much a written binding as an import is — and unlike PHP's leading
171
+ // `\`, Java marks it with nothing, so the naming convention is what separates
172
+ // `java.util.List` from `status.value` and from `Status.PENDING`.
173
+ if (separator !== -1 && splitQualifiedName(name) !== null && isPackageSegment(head)) {
174
+ return { fqn: name, binding: "written-fully-qualified" };
175
+ }
176
+ // Nothing written bound it: `java.lang`, a wildcard import, the same package,
177
+ // or a nested type reached through an enclosing name we never resolved.
178
+ return null;
179
+ }
180
+ /** Ours, whether or not this run read it. */
181
+ function isOurs(fqn, context) {
182
+ if (context.analysed.has(fqn))
183
+ return true;
184
+ for (const own of context.ownPackages) {
185
+ if (own !== "" && isUnder(fqn, own))
186
+ return true;
187
+ }
188
+ return false;
189
+ }
190
+ function attribute(fqn, binding, extra, context) {
191
+ if (isOurs(fqn, context))
192
+ return null;
193
+ const split = splitQualifiedName(fqn);
194
+ if (split === null)
195
+ return null;
196
+ for (const dynamic of DYNAMIC_DISPATCH_PACKAGES) {
197
+ if (isUnder(split.pkg, dynamic))
198
+ return null;
199
+ }
200
+ const symbolPath = [...split.symbols, ...extra];
201
+ if (symbolPath.some((part) => part === ""))
202
+ return null;
203
+ return {
204
+ moduleOrNamespace: split.pkg,
205
+ symbolPath,
206
+ binding,
207
+ thirdParty: !isPlatform(split.pkg),
208
+ };
209
+ }
210
+ /**
211
+ * The package and type behind a **type reference** that left the repository, or
212
+ * `null` when no binding the developer wrote settles it.
213
+ *
214
+ * `written` is the name exactly as the source wrote it — `Logger`,
215
+ * `java.util.List`, `Map.Entry`.
216
+ */
217
+ export function attributeExternalType(written, context) {
218
+ const qualified = qualify(written, context.imports);
219
+ if (qualified === null)
220
+ return null;
221
+ return attribute(qualified.fqn, qualified.binding, [], context);
222
+ }
223
+ /**
224
+ * The package, type and member behind a **call** that left the repository, or
225
+ * `null` when no binding the developer wrote settles it.
226
+ *
227
+ * `receiverType` is the receiver's type **as the source wrote it**: the declared
228
+ * type of a local or field, or the type name itself for a static call. It is
229
+ * never inferred — a `var`, a chained call or a generic type variable writes no
230
+ * type at the reference and `extract.ts` hands `undefined` here for all three.
231
+ */
232
+ export function attributeExternalCall(receiverType, method, context) {
233
+ if (receiverType === undefined || method === "")
234
+ return null;
235
+ const qualified = qualify(receiverType, context.imports);
236
+ if (qualified === null)
237
+ return null;
238
+ return attribute(qualified.fqn, qualified.binding, [method], context);
239
+ }
240
+ /**
241
+ * The package, type and member behind an **unqualified call bound by a static
242
+ * import**, or `null` when no such binding exists.
243
+ *
244
+ * `assertEquals(a, b)` under `import static org.junit.jupiter.api.Assertions.assertEquals;`
245
+ * is a binding the developer wrote and the language guarantees it — following it
246
+ * is resolution, not inference. A bare name with no static import is declined:
247
+ * it is the enclosing type's own member, or an inherited one from a supertype
248
+ * this run did not read, and neither is a dependency.
249
+ *
250
+ * `import static a.b.C.*;` binds no name and is never recorded in
251
+ * `staticMemberImports`, so it cannot arrive here — Python's `import *` refusal
252
+ * in the form Java's parse already applies.
253
+ */
254
+ export function attributeExternalStaticCall(method, context) {
255
+ if (method === "")
256
+ return null;
257
+ const owner = context.imports.staticMemberImports.get(method);
258
+ if (owner === undefined || owner === "")
259
+ return null;
260
+ return attribute(owner, "static-import", [method], context);
261
+ }
262
+ //# sourceMappingURL=external.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external.js","sourceRoot":"","sources":["../src/external.ts"],"names":[],"mappings":"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"}
package/dist/extract.d.ts CHANGED
@@ -60,5 +60,34 @@ export interface Extraction {
60
60
  readonly edges: readonly IREdge[];
61
61
  readonly unresolved: readonly UnresolvedRef[];
62
62
  }
63
+ /**
64
+ * The fallback graph when `extract()` throws mid-run, per
65
+ * `DEC-NEXT-degraded-graph-shape-for-adapters-without-one.md`.
66
+ *
67
+ * `FILE`, not `MODULE`: a Java module's identity here is `identityPackage`,
68
+ * and `identityPackage` is derived from `unit.packageName` — the `package
69
+ * a.b.c;` statement *inside* the file (`roots.ts`'s `identityPackage`,
70
+ * layered over a source-set anchor only when one resolves; the package name
71
+ * itself is never filesystem-derivable, since Java allows — and this corpus
72
+ * contains — a file whose directory does not match its declared package).
73
+ * A mid-extraction throw means exactly this machinery cannot be trusted to
74
+ * have run to completion. Unlike Go's import path or Rust's crate/module
75
+ * path — both resolved from the file's own location plus a manifest, never
76
+ * from parsed content — nothing about a Java file's identity is recoverable
77
+ * without a successful parse. `FILE` (via the shared
78
+ * `@descryy/adapter-common#fileNode` helper) is the fact that survives: the
79
+ * file exists, on disk, at this path, and that is all this function claims.
80
+ *
81
+ * One disclosure row, not one per file — the fact is about the run. Anchored
82
+ * to the first file's `FILE` node because the ledger requires a `fromNodeId`
83
+ * and `FILE` is the only node type this path emits.
84
+ */
85
+ export declare function degradedGraph(input: {
86
+ readonly repo: string;
87
+ readonly workspace: string | undefined;
88
+ readonly producedBy: string;
89
+ readonly files: readonly string[];
90
+ readonly cause: string;
91
+ }): Extraction;
63
92
  export declare function extract(input: ExtractInput): Extraction;
64
93
  //# sourceMappingURL=extract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;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;AAC1E,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKpD,eAAO,MAAM,QAAQ,SAAS,CAAC;AAK/B;qCACqC;AACrC,eAAO,MAAM,eAAe,cAAc,CAAC;AAyC3C,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;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACnD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CA6BtF;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;AA6ID,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,UAAU,CAqrBvD"}
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAQL,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAIrB,OAAO,KAAK,EAAiC,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAepD,eAAO,MAAM,QAAQ,SAAS,CAAC;AAiB/B;qCACqC;AACrC,eAAO,MAAM,eAAe,cAAc,CAAC;AA2E3C,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;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACnD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CA6BtF;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;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,GAAG,UAAU,CA0Bb;AA6ID,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,UAAU,CA+lCvD"}