@descryy/adapter-go 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/client.js ADDED
@@ -0,0 +1,342 @@
1
+ /**
2
+ * The caller's half of the HTTP boundary: `USES_API`, golden pattern 08.
3
+ *
4
+ * `SERVES_API` is minted in `routes.ts`/`extract.ts` from a route registration.
5
+ * This reads the other end — an outbound call with a statically knowable path —
6
+ * and mints the **same** `API_ENDPOINT` node from the same `endpointQsp`, so the
7
+ * two join without either side knowing the other ran (DEC-115).
8
+ *
9
+ * FUNCTION ──USES_API──▶ API_ENDPOINT ◀──SERVES_API── API_ROUTE
10
+ *
11
+ * ## Structured like `routes.ts`, not like Java's `client.ts`
12
+ *
13
+ * Java's client reader walks `JavaRef` — a flat, already-collected list of
14
+ * references with a `firstStringArgument` field captured at parse time. Go has
15
+ * no equivalent: `GoRef` keeps a short `raw` summary but not positional argument
16
+ * access, because nothing before this needed it. `net/http.NewRequest(method,
17
+ * url, body)` needs **two** literal positions read out of one call — the verb
18
+ * and the path both — so this reads `call_expression` nodes directly off the
19
+ * tree, the same shape `routes.ts`'s `readCall` already uses for the provider
20
+ * side of this exact boundary.
21
+ *
22
+ * ## Three shapes, one budget
23
+ *
24
+ * | shape | evidence |
25
+ * | --- | --- |
26
+ * | `http.Get(url)` / `Head` / `Post` / `PostForm` | the receiver is the `net/http` package itself, resolved through the file's own import table |
27
+ * | `client.Get(url)` / `Head` / `Post` / `PostForm` / `Do(req)` | the receiver's **declared type** is `http.Client` (pointer stripped), from a parameter, a `:=` composite literal, or a `var` |
28
+ * | `http.NewRequest(method, url, body)` / `NewRequestWithContext(ctx, method, url, body)` | the receiver is the `net/http` package; verb **and** path are both this call's own arguments — the verb as a string literal or one of `net/http`'s own exported `Method*` constants, the path as a string literal |
29
+ *
30
+ * `Do(req)` is refused unconditionally, never traced back to whatever built
31
+ * `req` — the same shape Java's `OkHttpClient`/`java.net.http.HttpClient`
32
+ * builder-client rows are refused for (D-FIX-3): the request is a separately
33
+ * constructed object, and reading through a builder chain to find where it was
34
+ * built is a different, larger row. `NewRequest`'s own call is a separate,
35
+ * independent extraction site — its literal arguments are read directly, never
36
+ * traced forward into whatever `.Do()` call eventually consumes the request it
37
+ * returns, so nothing here double-counts one HTTP call as two edges.
38
+ *
39
+ * ## Why the receiver's type must be written down
40
+ *
41
+ * `Get`, `Post`, `Do` are ordinary method names — a cache client, a mock, a
42
+ * test double could all have one. Admitting a call on the name alone would emit
43
+ * `USES_API` for anything shaped like `thing.Get(x)`, joining a caller to a
44
+ * route it never calls. So `client.*` is only admitted when the receiver's
45
+ * declared type resolves, through the import table, to `net/http.Client` —
46
+ * the same discipline `routes.ts` already holds for `NewServeMux`.
47
+ *
48
+ * ## The origin check, reused rather than re-derived
49
+ *
50
+ * `namesAnotherOrigin`/`relativePath` are copied verbatim from
51
+ * `adapter-java/src/client.ts` (via `adapter-csharp`'s DEC-260/261 fix): only an
52
+ * unambiguous absolute form (an explicit scheme, or `//host/...`) earns
53
+ * "another origin"; a bare relative path with no leading slash is `undetermined`
54
+ * — it may resolve against a `Client.BaseURL` this reader does not see, or it
55
+ * may not, and claiming either is a guess. This project has now found the
56
+ * identical latent bug in three languages that copied "does not start with a
57
+ * scheme" as sufficient evidence; the fourth and fifth (Rust, Ruby, PHP) reuse
58
+ * this same text rather than re-deriving it a fourth time.
59
+ */
60
+ import { endpointQsp, nodeId } from "@descryy/ir";
61
+ const HTTP_PACKAGE = "net/http";
62
+ /** Convenience methods whose name states the verb, on either the package or a `*Client`. */
63
+ const VERB_METHODS = new Map([
64
+ ["Get", "GET"],
65
+ ["Head", "HEAD"],
66
+ ["Post", "POST"],
67
+ ["PostForm", "POST"],
68
+ ]);
69
+ /**
70
+ * `net/http`'s own exported verb constants — `http.MethodGet`, and so on.
71
+ *
72
+ * Reading these is resolution, not inference: `http.MethodGet`'s value is
73
+ * fixed by the stdlib's own public API (RFC 7231's registered methods), the
74
+ * same way `http.NewServeMux` names a known constructor in `routes.ts`. This
75
+ * is the idiomatic form: on `gin` and `prometheus`, `http.NewRequest(http.MethodGet,
76
+ * ...)` outnumbers a bare `"GET"` string literal by a wide margin. Missing it
77
+ * would have meant refusing nearly every real `NewRequest` call in both
78
+ * corpora as "not a bare string literal" — technically true of the argument's
79
+ * *node type*, but not of what the source actually states.
80
+ */
81
+ const HTTP_METHOD_CONSTANTS = new Map([
82
+ ["MethodGet", "GET"],
83
+ ["MethodHead", "HEAD"],
84
+ ["MethodPost", "POST"],
85
+ ["MethodPut", "PUT"],
86
+ ["MethodPatch", "PATCH"],
87
+ ["MethodDelete", "DELETE"],
88
+ ["MethodConnect", "CONNECT"],
89
+ ["MethodOptions", "OPTIONS"],
90
+ ["MethodTrace", "TRACE"],
91
+ ]);
92
+ const CAPABILITY_GAP = { blockedBy: null, refusalClass: "capability-gap" };
93
+ const VARIES_PER_CALL = { blockedBy: null, refusalClass: "varies-per-call" };
94
+ /** `os.Getenv("X")`, `os.LookupEnv("X")` — the stdlib's own env-read functions. */
95
+ const ENV_READ_PATTERNS = [/^os\.Getenv\(\s*"[^"]*"\s*\)$/, /^os\.LookupEnv\(\s*"[^"]*"\s*\)$/];
96
+ /** Same heuristic as every other adapter's — see `adapter-rust/src/client.ts`'s doc. */
97
+ function argumentKindOf(text) {
98
+ if (text.endsWith(")") && text.includes("("))
99
+ return "call";
100
+ if (text.includes("+"))
101
+ return "concatenation";
102
+ if (/^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(text))
103
+ return "field";
104
+ return "other";
105
+ }
106
+ /**
107
+ * Why an argument node could not be read as a literal path — a bare
108
+ * identifier that is the enclosing function's own input parameter, a known
109
+ * environment-read call, or something this reader does not trace.
110
+ */
111
+ function diagnoseArgument(text, parameterNames) {
112
+ if (text === undefined)
113
+ return CAPABILITY_GAP;
114
+ const trimmed = text.trim();
115
+ if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(trimmed) && parameterNames.has(trimmed))
116
+ return VARIES_PER_CALL;
117
+ if (ENV_READ_PATTERNS.some((pattern) => pattern.test(trimmed))) {
118
+ return { blockedBy: trimmed, refusalClass: "value-unknown" };
119
+ }
120
+ return { ...CAPABILITY_GAP, argumentKind: argumentKindOf(trimmed) };
121
+ }
122
+ /** The text of a string literal, or `undefined` for anything assembled elsewhere. */
123
+ function literalOf(node) {
124
+ if (node === null)
125
+ return undefined;
126
+ if (node.type !== "interpreted_string_literal" && node.type !== "raw_string_literal")
127
+ return undefined;
128
+ const text = node.text;
129
+ if (text.includes("\\"))
130
+ return undefined;
131
+ return text.replace(/^["`]|["`]$/g, "");
132
+ }
133
+ /**
134
+ * A path this reader will claim: repository-relative, no scheme, no assembly.
135
+ *
136
+ * Copied from `adapter-java`/`adapter-csharp`'s `client.ts` — see this file's
137
+ * own header for why re-derivation is exactly what this row was told not to do.
138
+ */
139
+ function relativePath(value) {
140
+ if (!value.startsWith("/"))
141
+ return undefined;
142
+ if (value.startsWith("//"))
143
+ return undefined;
144
+ const cut = value.indexOf("?");
145
+ return cut === -1 ? value : value.slice(0, cut);
146
+ }
147
+ /** A literal that unambiguously names a *different* origin. Copied, not re-derived. */
148
+ function namesAnotherOrigin(value) {
149
+ return /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(value) || value.startsWith("//");
150
+ }
151
+ /**
152
+ * Does `base` (as written at a call site) resolve to `net/http` through this
153
+ * file's own import table? The alias may not be `http` — `import xhttp "net/http"`
154
+ * is legal Go, and the import table is exactly what already resolves it.
155
+ */
156
+ function isHttpPackage(base, unit) {
157
+ return unit.imports.get(base) === HTTP_PACKAGE;
158
+ }
159
+ /**
160
+ * A verb, from either a string literal (`"GET"`, case-normalised) or one of
161
+ * `net/http`'s own exported constants (`http.MethodGet`) — see
162
+ * {@link HTTP_METHOD_CONSTANTS}.
163
+ */
164
+ function verbOf(node, unit) {
165
+ const literal = literalOf(node);
166
+ if (literal !== undefined)
167
+ return literal.toUpperCase();
168
+ if (node === null || node.type !== "selector_expression")
169
+ return undefined;
170
+ const operand = node.childForFieldName("operand");
171
+ const field = node.childForFieldName("field");
172
+ if (operand === null || field === null || operand.type !== "identifier")
173
+ return undefined;
174
+ if (!isHttpPackage(operand.text, unit))
175
+ return undefined;
176
+ return HTTP_METHOD_CONSTANTS.get(field.text);
177
+ }
178
+ /**
179
+ * Does a written type name (pointer already stripped by `baseTypeName`, e.g.
180
+ * `"http.Client"` or `"xhttp.Client"`) resolve to `net/http.Client`?
181
+ *
182
+ * `baseTypeName` returns a `qualified_type`'s text verbatim — whatever
183
+ * qualifier the source actually wrote — so the qualifier is resolved through
184
+ * the import table exactly as {@link isHttpPackage} does for a package-level
185
+ * call, rather than string-matched against the literal text `"http.Client"`.
186
+ */
187
+ function isHttpClientType(written, unit) {
188
+ if (written === null || written === undefined)
189
+ return false;
190
+ const cut = written.indexOf(".");
191
+ if (cut === -1)
192
+ return false;
193
+ const qualifier = written.slice(0, cut);
194
+ const name = written.slice(cut + 1);
195
+ return name === "Client" && unit.imports.get(qualifier) === HTTP_PACKAGE;
196
+ }
197
+ /**
198
+ * Every outbound HTTP call in one function body, with a ledger row for each
199
+ * refusal.
200
+ *
201
+ * `locals` is the function's **already-fully-walked** local table — parameters
202
+ * and `:=`/`var` declarations alike — so a `*http.Client` parameter and a
203
+ * `client := &http.Client{}` local are both visible with no separate pass. It
204
+ * is read, never written: this module adds no new declarations to it.
205
+ */
206
+ export function readGoClientCalls(body, unit, locals, isTest, parameterNames = new Set()) {
207
+ const calls = [];
208
+ const refusals = [];
209
+ const callerKind = isTest ? "test" : "production";
210
+ const admit = (method, verb, rawUrl, line) => {
211
+ const template = relativePath(rawUrl);
212
+ if (template !== undefined) {
213
+ calls.push({ method, verb, template, line, callerKind });
214
+ return;
215
+ }
216
+ if (namesAnotherOrigin(rawUrl)) {
217
+ refusals.push({
218
+ raw: `${method}(${rawUrl})`,
219
+ line,
220
+ reason: `an HTTP call to \`${rawUrl}\`, which names another origin rather than a path in this repository. A scope boundary, not a gap.`,
221
+ blockedBy: null,
222
+ refusalClass: "out-of-scope",
223
+ });
224
+ return;
225
+ }
226
+ refusals.push({
227
+ raw: `${method}(${rawUrl})`,
228
+ line,
229
+ reason: `an HTTP call to \`${rawUrl}\`, a relative path with no leading slash. This reader cannot tell ` +
230
+ `whether it resolves inside this repository — against a base URL this call site does not state ` +
231
+ `— or elsewhere, so neither an endpoint nor a scope boundary is claimed.`,
232
+ // Not a per-call value and not a named blocking expression either —
233
+ // this reader just cannot see the base configuration.
234
+ ...CAPABILITY_GAP,
235
+ });
236
+ };
237
+ const readCall = (call) => {
238
+ const callee = call.childForFieldName("function");
239
+ if (callee === null || callee.type !== "selector_expression")
240
+ return;
241
+ const base = callee.childForFieldName("operand");
242
+ const member = callee.childForFieldName("field");
243
+ if (base === null || member === null || base.type !== "identifier")
244
+ return;
245
+ const method = member.text;
246
+ const line = call.startPosition.row + 1;
247
+ const args = call.childForFieldName("arguments");
248
+ const receiverIsPackage = isHttpPackage(base.text, unit);
249
+ const receiverIsClient = isHttpClientType(locals.get(base.text), unit);
250
+ if (!receiverIsPackage && !receiverIsClient)
251
+ return;
252
+ if (method === "NewRequest" || method === "NewRequestWithContext") {
253
+ if (!receiverIsPackage)
254
+ return;
255
+ // `NewRequest(method, url, body)` / `NewRequestWithContext(ctx, method, url, body)`.
256
+ const skip = method === "NewRequestWithContext" ? 1 : 0;
257
+ const methodArg = args?.namedChild(skip) ?? null;
258
+ const urlArg = args?.namedChild(skip + 1) ?? null;
259
+ const verb = verbOf(methodArg, unit);
260
+ const rawUrl = literalOf(urlArg);
261
+ if (verb === undefined || rawUrl === undefined) {
262
+ refusals.push({
263
+ raw: `${base.text}.${method}(...)`,
264
+ line,
265
+ reason: `an HTTP request construction whose method is neither a bare string literal nor one of ` +
266
+ `net/http's own exported Method constants, or whose URL is not a bare string literal — a ` +
267
+ `variable, a concatenation, or an expression this reader does not evaluate.`,
268
+ // The URL is the argument DEC-242 cares about naming; a bad verb
269
+ // with a fine URL has nothing to name and stays capability-gap.
270
+ ...(rawUrl === undefined ? diagnoseArgument(urlArg?.text, parameterNames) : CAPABILITY_GAP),
271
+ });
272
+ return;
273
+ }
274
+ admit(`${base.text}.${method}`, verb, rawUrl, line);
275
+ return;
276
+ }
277
+ if (method === "Do") {
278
+ if (!receiverIsClient)
279
+ return;
280
+ refusals.push({
281
+ raw: `${base.text}.Do(...)`,
282
+ line,
283
+ reason: `an HTTP call through a *http.Client, via a *http.Request built in a separate expression — ` +
284
+ `this adapter reads only \`http.NewRequest\`/\`http.NewRequestWithContext\`'s own literal ` +
285
+ `arguments, not a request assembled elsewhere and passed in.`,
286
+ ...CAPABILITY_GAP,
287
+ });
288
+ return;
289
+ }
290
+ const verb = VERB_METHODS.get(method);
291
+ if (verb === undefined)
292
+ return;
293
+ // `Get`/`Head`/`Post`/`PostForm` all take the URL as their first argument.
294
+ const urlArg = args?.namedChild(0) ?? null;
295
+ const rawUrl = literalOf(urlArg);
296
+ if (rawUrl === undefined) {
297
+ refusals.push({
298
+ raw: `${base.text}.${method}(...)`,
299
+ line,
300
+ reason: `an HTTP call through ${receiverIsPackage ? "the net/http package" : "a *http.Client"} whose ` +
301
+ `path is not a bare string literal — a variable, a concatenation, or an expression this ` +
302
+ `reader does not evaluate.`,
303
+ ...diagnoseArgument(urlArg?.text, parameterNames),
304
+ });
305
+ return;
306
+ }
307
+ admit(`${base.text}.${method}`, verb, rawUrl, line);
308
+ };
309
+ const visit = (node) => {
310
+ if (node.type === "call_expression")
311
+ readCall(node);
312
+ for (let i = 0; i < node.namedChildCount; i += 1) {
313
+ const child = node.namedChild(i);
314
+ if (child !== null)
315
+ visit(child);
316
+ }
317
+ };
318
+ visit(body);
319
+ return { calls, refusals };
320
+ }
321
+ /**
322
+ * The `API_ENDPOINT` a call joins to — minted identically to the route side.
323
+ *
324
+ * Shares `endpointQsp` with `extract.ts`'s `SERVES_API` block, so the two ids
325
+ * agree exactly. DEC-115's one hard constraint: two producers that mint
326
+ * different ids for the same route do not conflict, they silently fail to join.
327
+ */
328
+ export function endpointFor(scope, call, producedBy, normalise) {
329
+ const template = normalise(call.template);
330
+ return {
331
+ id: nodeId(scope, "API_ENDPOINT", endpointQsp(call.verb, call.template), null),
332
+ type: "API_ENDPOINT",
333
+ name: `${call.verb} ${template}`,
334
+ file: null,
335
+ range: null,
336
+ language: null,
337
+ producedBy,
338
+ resolution: 2,
339
+ attrs: { method: call.verb, pathTemplate: template },
340
+ };
341
+ }
342
+ //# 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,54 @@
1
+ /**
2
+ * Go files to Canonical IR.
3
+ *
4
+ * ## The package is the unit, and that changes resolution rather than identity
5
+ *
6
+ * Files in one Go package share a namespace completely: an unqualified name in
7
+ * one file resolves to a declaration in another that never mentions it. So the
8
+ * resolver's first scope is not the file but the package, which is the opposite
9
+ * of Java and TypeScript, where a file must import what it uses.
10
+ *
11
+ * Identity is the easy half. A package's import path is a declared name that
12
+ * other code writes verbatim, so `qsp = importPath::Symbol` needs none of the
13
+ * anchor inference TypeScript needs (DEC-047) or the source-set disambiguation
14
+ * Java needs. Go states it.
15
+ *
16
+ * ## What is deliberately not claimed
17
+ *
18
+ * **Interface satisfaction.** Go's is structural: a type implements an interface
19
+ * by having the right methods, and nothing in the source says so. Computing it
20
+ * needs full method-set comparison, which is R3 evidence, and guessing it from
21
+ * name similarity would be exactly the kind of edge that corrupts every layer
22
+ * above. `IMPLEMENTS` is therefore never emitted, and `capabilities()` says so.
23
+ * Embedding *is* explicit and becomes `INHERITS`.
24
+ *
25
+ * `:=` with anything but a composite literal, dot imports, and any receiver that
26
+ * is not a written name all go to the ledger with their reason.
27
+ */
28
+ import { type IdentityScope, type IREdge, type IRNode, type ResolutionLevel, type UnresolvedRef } from "@descryy/ir";
29
+ import type { GoFile } from "./parse.ts";
30
+ export declare const LANGUAGE = "go";
31
+ declare const REASONS: {
32
+ readonly outside: string;
33
+ readonly unmodelled: string;
34
+ readonly untypedReceiver: string;
35
+ readonly dotImport: string;
36
+ readonly noImportPath: string;
37
+ readonly unknownName: "no declaration for this name in the package, its imports, or the analysed set.";
38
+ readonly routeIdCollision: string;
39
+ };
40
+ export interface ExtractInput {
41
+ readonly repo: string;
42
+ readonly scope: IdentityScope;
43
+ readonly producedBy: string;
44
+ readonly reached: ResolutionLevel;
45
+ readonly files: readonly GoFile[];
46
+ }
47
+ export interface Extraction {
48
+ readonly nodes: readonly IRNode[];
49
+ readonly edges: readonly IREdge[];
50
+ readonly unresolved: readonly UnresolvedRef[];
51
+ }
52
+ export declare function extract(input: ExtractInput): Extraction;
53
+ export { REASONS };
54
+ //# sourceMappingURL=extract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAAE,MAAM,EAA6C,MAAM,YAAY,CAAC;AAGpF,eAAO,MAAM,QAAQ,OAAO,CAAC;AAI7B,QAAA,MAAM,OAAO;;;;;;;;CAqBH,CAAC;AAEX,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,MAAM,EAAE,CAAC;CACnC;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;AAoDD,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,UAAU,CA40BvD;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}