@descryy/adapter-go 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.
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +98 -10
- package/dist/adapter.js.map +1 -1
- package/dist/client-base.d.ts +83 -0
- package/dist/client-base.d.ts.map +1 -0
- package/dist/client-base.js +79 -0
- package/dist/client-base.js.map +1 -0
- package/dist/client.d.ts +26 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +208 -2
- package/dist/client.js.map +1 -1
- package/dist/extract.d.ts +53 -0
- package/dist/extract.d.ts.map +1 -1
- package/dist/extract.js +443 -25
- package/dist/extract.js.map +1 -1
- package/dist/go-types.d.ts +75 -0
- package/dist/go-types.d.ts.map +1 -0
- package/dist/go-types.js +198 -0
- package/dist/go-types.js.map +1 -0
- package/dist/gorm.d.ts +81 -0
- package/dist/gorm.d.ts.map +1 -0
- package/dist/gorm.js +140 -0
- package/dist/gorm.js.map +1 -0
- package/dist/grpc.d.ts +29 -0
- package/dist/grpc.d.ts.map +1 -1
- package/dist/grpc.js +21 -2
- package/dist/grpc.js.map +1 -1
- package/dist/parse.d.ts +41 -0
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +134 -16
- package/dist/parse.js.map +1 -1
- package/dist/routes.d.ts +18 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +156 -19
- package/dist/routes.js.map +1 -1
- package/goshapes/go.mod +17 -0
- package/goshapes/main.go +596 -0
- package/package.json +8 -7
package/dist/gorm.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GORM — Go's `orm-extractor`.
|
|
3
|
+
*
|
|
4
|
+
* ## Admission is a struct tag, and that has one useful consequence
|
|
5
|
+
*
|
|
6
|
+
* Go has no annotations, so the mapping is declared in a `gorm:"…"` tag — read
|
|
7
|
+
* from the source text. The ORM library therefore never has to be present at
|
|
8
|
+
* all, which is the same standing the Java corpus's uninstalled
|
|
9
|
+
* `jakarta.persistence` import has, reached by a different route.
|
|
10
|
+
*
|
|
11
|
+
* `CreateOrderRequest` in the conformance corpus has the same three members as
|
|
12
|
+
* `Order`. The tag is the only thing separating a table row from a transport
|
|
13
|
+
* shape, and separating them by name is what precision over recall forbids
|
|
14
|
+
* (golden 07's note, DEC-043, DEC-056).
|
|
15
|
+
*
|
|
16
|
+
* ## The table comes from `TableName()`, never from the NamingStrategy
|
|
17
|
+
*
|
|
18
|
+
* GORM derives an untagged type's table from the struct name — snake_cased,
|
|
19
|
+
* pluralised, with a configurable prefix. That is a convention set in
|
|
20
|
+
* application code this adapter never reads, so it is **refused**, exactly as
|
|
21
|
+
* `adapter-java`'s `tableOf()` refuses Hibernate's naming strategy (DEC-127
|
|
22
|
+
* §2). A `TableName()` method returning a literal is a declaration and is read.
|
|
23
|
+
*
|
|
24
|
+
* ## Nullability is the pointer
|
|
25
|
+
*
|
|
26
|
+
* Go has no nullable `int64`. A pointer field is how GORM represents a NULL
|
|
27
|
+
* column and it is the documented mechanism, so the TYPE is the declaration and
|
|
28
|
+
* there is nothing to infer. `gorm:"not null"` is read where written and
|
|
29
|
+
* narrows a pointer field to not-nullable, because that is a constraint the
|
|
30
|
+
* database enforces.
|
|
31
|
+
*
|
|
32
|
+
* ## No DATABASE_TABLE / DATABASE_COLUMN, and the reason is specific to Go
|
|
33
|
+
*
|
|
34
|
+
* A `column:` tag DOES declare a physical name, so it is tempting to mint on it.
|
|
35
|
+
* The problem is that the tag is optional and most real structs omit it, leaving
|
|
36
|
+
* the name to the NamingStrategy. Minting only for the tagged fields would
|
|
37
|
+
* produce a DATABASE_TABLE carrying the three columns that happen to be tagged
|
|
38
|
+
* out of the thirty that exist — a node that reads as a complete table and is
|
|
39
|
+
* not one. Refused wholesale rather than minted for the declared subset.
|
|
40
|
+
*
|
|
41
|
+
* Ruby and Rust differ because `db/schema.rb` and Diesel's `table!` are
|
|
42
|
+
* COMPLETE: every column of the table is in them, by construction.
|
|
43
|
+
*/
|
|
44
|
+
/** The `gorm:"…"` payload of a struct tag, or `undefined`. */
|
|
45
|
+
function gormTag(tag) {
|
|
46
|
+
if (tag === undefined)
|
|
47
|
+
return undefined;
|
|
48
|
+
const match = /\bgorm\s*:\s*"([^"]*)"/.exec(tag);
|
|
49
|
+
return match?.[1];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Is this type declared to be a GORM model?
|
|
53
|
+
*
|
|
54
|
+
* One `gorm` tag anywhere in the struct, or an embedded `gorm.Model` — which is
|
|
55
|
+
* the library's own base and is as explicit as a tag.
|
|
56
|
+
*/
|
|
57
|
+
export function isGormModel(type) {
|
|
58
|
+
if (type.form !== "struct")
|
|
59
|
+
return false;
|
|
60
|
+
if (type.embeds.some((name) => name === "Model" || name.endsWith(".Model"))) {
|
|
61
|
+
// `gorm.Model` embeds ID/CreatedAt/UpdatedAt/DeletedAt. Only accepted when
|
|
62
|
+
// the embed names gorm specifically — a bare `Model` from another package
|
|
63
|
+
// would be a name heuristic.
|
|
64
|
+
if (type.embeds.includes("gorm.Model"))
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
for (const detail of type.fieldDetail.values()) {
|
|
68
|
+
if (gormTag(detail.tag) !== undefined)
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The mapped shape.
|
|
75
|
+
*
|
|
76
|
+
* `methods` is every function whose receiver is this type, so `TableName()` can
|
|
77
|
+
* be found without this module knowing how the adapter indexes them.
|
|
78
|
+
*/
|
|
79
|
+
export function gormShapeOf(type, methods) {
|
|
80
|
+
const tableName = methods.find((fn) => fn.name === "TableName")?.returnedLiteral;
|
|
81
|
+
const fields = [];
|
|
82
|
+
for (const [name, declaredType] of type.fields) {
|
|
83
|
+
const detail = type.fieldDetail.get(name);
|
|
84
|
+
if (detail === undefined)
|
|
85
|
+
continue;
|
|
86
|
+
const tag = gormTag(detail.tag);
|
|
87
|
+
if (tag !== undefined && /(^|;)\s*-\s*(;|$)/.test(tag))
|
|
88
|
+
continue; // `gorm:"-"` is not a column
|
|
89
|
+
if (tag !== undefined && /\bnot\s*null\b/i.test(tag)) {
|
|
90
|
+
fields.push({ name, nullable: false, nullableFrom: "tag" });
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
fields.push(detail.pointer
|
|
94
|
+
? { name, nullable: true, nullableFrom: "pointer" }
|
|
95
|
+
: { name, nullable: false, nullableFrom: "value-type" });
|
|
96
|
+
void declaredType;
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
table: tableName ?? null,
|
|
100
|
+
fields: [...fields].sort((a, b) => a.name.localeCompare(b.name)),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Field reads in one function, per model.
|
|
105
|
+
*
|
|
106
|
+
* Go's parser already records `X.Y` access as a `member` ref, so the only thing
|
|
107
|
+
* needed here is the receiver's declared type — and only a WRITTEN one counts.
|
|
108
|
+
* `order := fetch(id)` states nothing at the binding site.
|
|
109
|
+
*/
|
|
110
|
+
export function fieldReadsIn(fn, resolveModel) {
|
|
111
|
+
const byModel = new Map();
|
|
112
|
+
for (const ref of fn.refs) {
|
|
113
|
+
if (ref.kind !== "member" || ref.receiver === undefined)
|
|
114
|
+
continue;
|
|
115
|
+
const written = fn.locals.get(ref.receiver);
|
|
116
|
+
if (written === undefined || written === null)
|
|
117
|
+
continue;
|
|
118
|
+
const model = resolveModel(written);
|
|
119
|
+
if (model === undefined)
|
|
120
|
+
continue;
|
|
121
|
+
// A `member` ref's `name` is the access AS WRITTEN — `order.TotalAmount`,
|
|
122
|
+
// not `TotalAmount`. Golden 07 compares field NAMES, so the receiver is
|
|
123
|
+
// stripped and only the first segment beyond it is the field this struct
|
|
124
|
+
// declares: in `order.Customer.Name`, `Customer` is Order's field and
|
|
125
|
+
// `Name` belongs to whatever type that is.
|
|
126
|
+
const prefix = `${ref.receiver}.`;
|
|
127
|
+
const member = ref.name.startsWith(prefix) ? ref.name.slice(prefix.length) : ref.name;
|
|
128
|
+
const direct = member.split(".")[0];
|
|
129
|
+
if (direct === undefined || direct === "")
|
|
130
|
+
continue;
|
|
131
|
+
let fields = byModel.get(model);
|
|
132
|
+
if (fields === undefined) {
|
|
133
|
+
fields = new Set();
|
|
134
|
+
byModel.set(model, fields);
|
|
135
|
+
}
|
|
136
|
+
fields.add(direct);
|
|
137
|
+
}
|
|
138
|
+
return [...byModel.entries()].map(([model, fields]) => ({ model, fields: [...fields].sort() }));
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=gorm.js.map
|
package/dist/gorm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gorm.js","sourceRoot":"","sources":["../src/gorm.ts"],"names":[],"mappings":"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"}
|
package/dist/grpc.d.ts
CHANGED
|
@@ -48,12 +48,41 @@ export interface GrpcMethodConst {
|
|
|
48
48
|
readonly method: string;
|
|
49
49
|
readonly path: string;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* The registration's second argument — the value implementing the service —
|
|
53
|
+
* in the two shapes this reader can name a type from without a type checker:
|
|
54
|
+
*
|
|
55
|
+
* `kind: "literal"` `&orderServer{}` / `orderServer{}` — the type is
|
|
56
|
+
* written at the call site itself, `&`/parens unwound.
|
|
57
|
+
* `kind: "name"` `srv` — a bare identifier. Its declared type is not
|
|
58
|
+
* written here; the extract pass resolves it against
|
|
59
|
+
* the enclosing function's locals and the package's
|
|
60
|
+
* vars, the same way it resolves every other receiver.
|
|
61
|
+
*
|
|
62
|
+
* Anything else (a call result, a selector, a type assertion on something
|
|
63
|
+
* other than a composite literal) is not a shape this reader names a type
|
|
64
|
+
* from — `impl` stays `undefined` on the registration, and the extract pass
|
|
65
|
+
* discloses that explicitly rather than staying silent about it.
|
|
66
|
+
*/
|
|
67
|
+
export type GrpcImpl = {
|
|
68
|
+
readonly kind: "literal";
|
|
69
|
+
readonly typeWritten: string;
|
|
70
|
+
} | {
|
|
71
|
+
readonly kind: "name";
|
|
72
|
+
readonly name: string;
|
|
73
|
+
};
|
|
51
74
|
/** `Register<Service>Server(...)` — one per call site, however it was reached. */
|
|
52
75
|
export interface GrpcRegistration {
|
|
53
76
|
readonly service: string;
|
|
54
77
|
/** The package alias the call was made through, or `undefined` for a bare, same-package call. */
|
|
55
78
|
readonly targetPackageAlias: string | undefined;
|
|
56
79
|
readonly line: number;
|
|
80
|
+
/**
|
|
81
|
+
* The `impl` argument's own written shape — see {@link GrpcImpl}.
|
|
82
|
+
* `undefined` when the call did not write exactly two arguments, or the
|
|
83
|
+
* second is not a shape this reader can name a type from at all.
|
|
84
|
+
*/
|
|
85
|
+
readonly impl: GrpcImpl | undefined;
|
|
57
86
|
}
|
|
58
87
|
/** Every `_FullMethodName` const declared at this file's package level. */
|
|
59
88
|
export declare function readGrpcMethodConsts(root: Node): GrpcMethodConst[];
|
package/dist/grpc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grpc.d.ts","sourceRoot":"","sources":["../src/grpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"grpc.d.ts","sourceRoot":"","sources":["../src/grpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAKxD,6FAA6F;AAC7F,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErI,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iGAAiG;IACjG,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;CACrC;AAaD,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,eAAe,EAAE,CA6BlE;AAID,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,gBAAgB,EAAE,CAgCpE"}
|
package/dist/grpc.js
CHANGED
|
@@ -42,6 +42,18 @@
|
|
|
42
42
|
* invented privately here — see `DEC-NEXT-grpc-route-identity.md`.
|
|
43
43
|
*/
|
|
44
44
|
import { literalOf } from "./routes.js";
|
|
45
|
+
import { receiverTypeAtSite } from "./parse.js";
|
|
46
|
+
/** The registration's second argument, read for a type name — never a guess, `undefined` when unreadable. */
|
|
47
|
+
function implArgOf(node) {
|
|
48
|
+
if (node === null)
|
|
49
|
+
return undefined;
|
|
50
|
+
const literalType = receiverTypeAtSite(node);
|
|
51
|
+
if (literalType !== undefined)
|
|
52
|
+
return { kind: "literal", typeWritten: literalType };
|
|
53
|
+
if (node.type === "identifier")
|
|
54
|
+
return { kind: "name", name: node.text };
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
45
57
|
const FULL_METHOD_NAME_CONST = /^([A-Za-z0-9]+)_([A-Za-z0-9]+)_FullMethodName$/;
|
|
46
58
|
/** Every `_FullMethodName` const declared at this file's package level. */
|
|
47
59
|
export function readGrpcMethodConsts(root) {
|
|
@@ -85,10 +97,17 @@ export function readGrpcRegistrations(root) {
|
|
|
85
97
|
if (node.type === "call_expression") {
|
|
86
98
|
const callee = node.childForFieldName("function");
|
|
87
99
|
const line = node.startPosition.row + 1;
|
|
100
|
+
// `Register<Service>Server(server, impl)` — always exactly two
|
|
101
|
+
// arguments in every file `protoc-gen-go-grpc` generates. Anything
|
|
102
|
+
// else means the second position isn't `impl` at all, and `implArgOf`
|
|
103
|
+
// is not asked to guess at it.
|
|
104
|
+
const args = node.childForFieldName("arguments");
|
|
105
|
+
const implNode = args !== null && args.namedChildCount === 2 ? args.namedChild(1) : null;
|
|
106
|
+
const impl = implArgOf(implNode);
|
|
88
107
|
if (callee !== null && callee.type === "identifier") {
|
|
89
108
|
const match = REGISTER_SERVER_CALL.exec(callee.text);
|
|
90
109
|
if (match !== null)
|
|
91
|
-
out.push({ service: match[1], targetPackageAlias: undefined, line });
|
|
110
|
+
out.push({ service: match[1], targetPackageAlias: undefined, line, impl });
|
|
92
111
|
}
|
|
93
112
|
else if (callee !== null && callee.type === "selector_expression") {
|
|
94
113
|
const base = callee.childForFieldName("operand");
|
|
@@ -96,7 +115,7 @@ export function readGrpcRegistrations(root) {
|
|
|
96
115
|
if (base !== null && base.type === "identifier" && member !== null) {
|
|
97
116
|
const match = REGISTER_SERVER_CALL.exec(member.text);
|
|
98
117
|
if (match !== null)
|
|
99
|
-
out.push({ service: match[1], targetPackageAlias: base.text, line });
|
|
118
|
+
out.push({ service: match[1], targetPackageAlias: base.text, line, impl });
|
|
100
119
|
}
|
|
101
120
|
}
|
|
102
121
|
}
|
package/dist/grpc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grpc.js","sourceRoot":"","sources":["../src/grpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"grpc.js","sourceRoot":"","sources":["../src/grpc.ts"],"names":[],"mappings":"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"}
|
package/dist/parse.d.ts
CHANGED
|
@@ -63,6 +63,16 @@ export interface GoFunc extends GoScope {
|
|
|
63
63
|
readonly subtests: GoSubtest[];
|
|
64
64
|
/** Declared result type names, in order. `undefined` where not a named type. */
|
|
65
65
|
readonly results: (string | undefined)[];
|
|
66
|
+
/**
|
|
67
|
+
* The single interpreted string literal a one-statement `return "…"` body
|
|
68
|
+
* returns, when that is the whole function.
|
|
69
|
+
*
|
|
70
|
+
* Narrow on purpose: this is how Go declares a value that other languages put
|
|
71
|
+
* in an annotation — GORM's `TableName()`, and nothing else so far. A body
|
|
72
|
+
* with any other shape states nothing this reader can read, and gets
|
|
73
|
+
* `undefined` rather than a guess.
|
|
74
|
+
*/
|
|
75
|
+
readonly returnedLiteral: string | undefined;
|
|
66
76
|
/** Outbound HTTP calls read from this function's body — DEC-262's fork, Go's half. */
|
|
67
77
|
readonly clientCalls: readonly GoClientCallSite[];
|
|
68
78
|
/** Recognised-but-refused outbound HTTP calls, each with its reason. */
|
|
@@ -84,6 +94,19 @@ export interface GoType {
|
|
|
84
94
|
readonly embeds: string[];
|
|
85
95
|
/** Field name -> declared type name, `null` when ambiguous. */
|
|
86
96
|
readonly fields: Map<string, string | null>;
|
|
97
|
+
/**
|
|
98
|
+
* Per-field detail a framework extractor needs and CALLS resolution does not:
|
|
99
|
+
* the struct TAG as written, and whether the type is a pointer.
|
|
100
|
+
*
|
|
101
|
+
* Strictly additive to {@link fields}, which keeps its exact meaning. Go has
|
|
102
|
+
* no annotations, so a tag is the only place a mapping can be declared — and
|
|
103
|
+
* a pointer is how every Go ORM represents a nullable column, which makes the
|
|
104
|
+
* type itself the declaration rather than a thing to infer.
|
|
105
|
+
*/
|
|
106
|
+
readonly fieldDetail: Map<string, {
|
|
107
|
+
readonly tag: string | undefined;
|
|
108
|
+
readonly pointer: boolean;
|
|
109
|
+
}>;
|
|
87
110
|
readonly typeRefs: GoRef[];
|
|
88
111
|
}
|
|
89
112
|
export interface GoFile {
|
|
@@ -104,6 +127,14 @@ export interface GoFile {
|
|
|
104
127
|
readonly aliases: GoAlias[];
|
|
105
128
|
/** Package-level `var`/`const` -> written type. DEC-081's second shape; package scope wasn't tracked before. */
|
|
106
129
|
readonly packageVars: Map<string, string>;
|
|
130
|
+
/**
|
|
131
|
+
* Package-level `const`/`var` -> its string-literal VALUE, which is the
|
|
132
|
+
* only base table Go's per-file parse can offer DEC-164's reader. A
|
|
133
|
+
* constant declared in a sibling file of the same package is visible to Go
|
|
134
|
+
* and not to this map — a disclosed recall gap, never a precision one, and
|
|
135
|
+
* `client-base.ts`'s header says so.
|
|
136
|
+
*/
|
|
137
|
+
readonly packageConsts: Map<string, string>;
|
|
107
138
|
/** Route registrations read from this file — DEC-117. */
|
|
108
139
|
readonly routes: GoRoute[];
|
|
109
140
|
/** Registrations recognised and refused, each with its reason. */
|
|
@@ -123,5 +154,15 @@ export declare function buildConstraintOf(text: string): string | undefined;
|
|
|
123
154
|
export declare function isUniverse(name: string): boolean;
|
|
124
155
|
/** `*T`, `[]T`, `map[K]T`, `chan T` — the name underneath. */
|
|
125
156
|
export declare function baseTypeName(node: Node | null): string | undefined;
|
|
157
|
+
/**
|
|
158
|
+
* Receiver type when written: a type assertion, or parenthesised composite
|
|
159
|
+
* literal. Both previously became `(computed)`.
|
|
160
|
+
*
|
|
161
|
+
* Exported for `grpc.ts`: a `Register<Service>Server(server, &impl{})`
|
|
162
|
+
* registration's `impl` argument is exactly this same shape — a composite
|
|
163
|
+
* literal, usually behind `&` — and reading it a second, subtly different
|
|
164
|
+
* way in a second file is how two readers of the same construct drift apart.
|
|
165
|
+
*/
|
|
166
|
+
export declare function receiverTypeAtSite(node: Node): string | undefined;
|
|
126
167
|
export declare function readFile(root: Node, file: string, hasError: boolean): GoFile;
|
|
127
168
|
//# sourceMappingURL=parse.d.ts.map
|
package/dist/parse.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"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"}
|
package/dist/parse.js
CHANGED
|
@@ -114,8 +114,16 @@ function receiverName(node) {
|
|
|
114
114
|
// `(*x).f`, `x[0].f`, `f().g` — nothing wrote a name here.
|
|
115
115
|
return "(computed)";
|
|
116
116
|
}
|
|
117
|
-
/**
|
|
118
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Receiver type when written: a type assertion, or parenthesised composite
|
|
119
|
+
* literal. Both previously became `(computed)`.
|
|
120
|
+
*
|
|
121
|
+
* Exported for `grpc.ts`: a `Register<Service>Server(server, &impl{})`
|
|
122
|
+
* registration's `impl` argument is exactly this same shape — a composite
|
|
123
|
+
* literal, usually behind `&` — and reading it a second, subtly different
|
|
124
|
+
* way in a second file is how two readers of the same construct drift apart.
|
|
125
|
+
*/
|
|
126
|
+
export function receiverTypeAtSite(node) {
|
|
119
127
|
if (node.type === "parenthesized_expression") {
|
|
120
128
|
const inner = node.namedChild(0);
|
|
121
129
|
return inner === null ? undefined : receiverTypeAtSite(inner);
|
|
@@ -171,6 +179,7 @@ export function readFile(root, file, hasError) {
|
|
|
171
179
|
funcs: [],
|
|
172
180
|
aliases: [],
|
|
173
181
|
packageVars: new Map(),
|
|
182
|
+
packageConsts: new Map(),
|
|
174
183
|
routes: [],
|
|
175
184
|
routeRefusals: [],
|
|
176
185
|
grpcMethodConsts: [],
|
|
@@ -180,6 +189,8 @@ export function readFile(root, file, hasError) {
|
|
|
180
189
|
buildConstraint: undefined,
|
|
181
190
|
};
|
|
182
191
|
let packageName = "";
|
|
192
|
+
/** Function bodies whose HTTP read is deferred until the whole file is known. */
|
|
193
|
+
const pending = [];
|
|
183
194
|
for (let i = 0; i < root.namedChildCount; i += 1) {
|
|
184
195
|
const statement = root.namedChild(i);
|
|
185
196
|
if (statement === null)
|
|
@@ -207,9 +218,13 @@ export function readFile(root, file, hasError) {
|
|
|
207
218
|
continue;
|
|
208
219
|
}
|
|
209
220
|
if (statement.type === "function_declaration" || statement.type === "method_declaration") {
|
|
210
|
-
readFunc(statement, unit, file);
|
|
221
|
+
readFunc(statement, unit, file, pending);
|
|
211
222
|
}
|
|
212
223
|
}
|
|
224
|
+
// After the loop, for the same reason the route read below is: the file's
|
|
225
|
+
// own `const` block and `import` table may sit anywhere relative to the
|
|
226
|
+
// function that uses them.
|
|
227
|
+
readClients(unit, pending);
|
|
213
228
|
// After the loop, because provenance is decided by the import table and the
|
|
214
229
|
// import declaration may sit anywhere above the call that uses it.
|
|
215
230
|
const read = readGoRoutes(root, unit);
|
|
@@ -258,6 +273,15 @@ function readImports(node, unit) {
|
|
|
258
273
|
unit.imports.set(alias ?? defaultImportAlias(path), path);
|
|
259
274
|
}
|
|
260
275
|
}
|
|
276
|
+
/** The text of an unescaped Go string literal, or `undefined`. Mirrors `client.ts`'s `literalOf` — an escape means this reader would have to evaluate it. */
|
|
277
|
+
function stringLiteralOf(node) {
|
|
278
|
+
if (node.type !== "interpreted_string_literal" && node.type !== "raw_string_literal")
|
|
279
|
+
return undefined;
|
|
280
|
+
const text = node.text;
|
|
281
|
+
if (text.includes("\\"))
|
|
282
|
+
return undefined;
|
|
283
|
+
return text.replace(/^["`]|["`]$/g, "");
|
|
284
|
+
}
|
|
261
285
|
/** Package-level values with a written type: explicit, or a composite literal. A call/expression is left out — no guessing. */
|
|
262
286
|
function readPackageVars(node, unit) {
|
|
263
287
|
for (let i = 0; i < node.namedChildCount; i += 1) {
|
|
@@ -277,16 +301,24 @@ function readPackageVars(node, unit) {
|
|
|
277
301
|
const name = names[0];
|
|
278
302
|
if (name === undefined)
|
|
279
303
|
continue;
|
|
304
|
+
const values = spec.childForFieldName("value");
|
|
305
|
+
const value = values !== null && values.namedChildCount === 1 ? values.namedChild(0) : null;
|
|
306
|
+
// DEC-164's base table. Recorded even when a type is written, because
|
|
307
|
+
// `const apiV1Base string = "..."` is the same constant as the untyped
|
|
308
|
+
// form and the two must not answer differently.
|
|
309
|
+
if (value !== null) {
|
|
310
|
+
const literal = stringLiteralOf(value);
|
|
311
|
+
if (literal !== undefined && !unit.packageConsts.has(name.text))
|
|
312
|
+
unit.packageConsts.set(name.text, literal);
|
|
313
|
+
}
|
|
280
314
|
const declared = baseTypeName(spec.childForFieldName("type"));
|
|
281
315
|
if (declared !== undefined) {
|
|
282
316
|
unit.packageVars.set(name.text, declared);
|
|
283
317
|
continue;
|
|
284
318
|
}
|
|
285
|
-
|
|
286
|
-
if (values === null || values.namedChildCount !== 1)
|
|
319
|
+
if (value === null)
|
|
287
320
|
continue;
|
|
288
|
-
const
|
|
289
|
-
const written = value === null ? undefined : receiverTypeAtSite(value);
|
|
321
|
+
const written = receiverTypeAtSite(value);
|
|
290
322
|
if (written !== undefined)
|
|
291
323
|
unit.packageVars.set(name.text, written);
|
|
292
324
|
}
|
|
@@ -345,6 +377,7 @@ function readType(spec, unit) {
|
|
|
345
377
|
endLine: spec.endPosition.row + 1,
|
|
346
378
|
embeds: [],
|
|
347
379
|
fields: new Map(),
|
|
380
|
+
fieldDetail: new Map(),
|
|
348
381
|
typeRefs: [],
|
|
349
382
|
};
|
|
350
383
|
if (typeNode?.type === "struct_type") {
|
|
@@ -370,6 +403,17 @@ function readType(spec, unit) {
|
|
|
370
403
|
}
|
|
371
404
|
for (const name of names)
|
|
372
405
|
declare(type.fields, name.text, declared);
|
|
406
|
+
// `\`gorm:"column:discount_code"\`` — a raw string literal sibling of the
|
|
407
|
+
// type. Recorded verbatim; what any particular tag MEANS belongs to a
|
|
408
|
+
// framework extractor, not to this reader.
|
|
409
|
+
const tagNode = field.namedChildren.find((child) => child?.type === "raw_string_literal");
|
|
410
|
+
const pointer = fieldType?.type === "pointer_type";
|
|
411
|
+
for (const name of names) {
|
|
412
|
+
type.fieldDetail.set(name.text, {
|
|
413
|
+
tag: tagNode === undefined || tagNode === null ? undefined : tagNode.text,
|
|
414
|
+
pointer,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
373
417
|
const written = [];
|
|
374
418
|
allTypeNames(fieldType, written, params);
|
|
375
419
|
for (const each of written) {
|
|
@@ -415,7 +459,7 @@ function isTestFunc(name, file) {
|
|
|
415
459
|
}
|
|
416
460
|
/** The types whose `Run` method declares a subtest. */
|
|
417
461
|
const TEST_RECEIVERS = new Set(["testing.T", "testing.B", "testing.F"]);
|
|
418
|
-
function readFunc(node, unit, file) {
|
|
462
|
+
function readFunc(node, unit, file, pending) {
|
|
419
463
|
const nameNode = node.childForFieldName("name");
|
|
420
464
|
if (nameNode === null)
|
|
421
465
|
return;
|
|
@@ -440,6 +484,7 @@ function readFunc(node, unit, file) {
|
|
|
440
484
|
parameterNames: new Set(),
|
|
441
485
|
subtests: [],
|
|
442
486
|
results: resultTypes(node.childForFieldName("result")),
|
|
487
|
+
returnedLiteral: soleReturnedLiteral(node.childForFieldName("body")),
|
|
443
488
|
};
|
|
444
489
|
if (receiverList !== null) {
|
|
445
490
|
const declaration = receiverList.namedChild(0);
|
|
@@ -461,8 +506,6 @@ function readFunc(node, unit, file) {
|
|
|
461
506
|
fn.refs.push({ kind: "type", name: each, receiver: undefined, line: fn.startLine, raw: result.text.slice(0, 120) });
|
|
462
507
|
}
|
|
463
508
|
}
|
|
464
|
-
let clientCalls = [];
|
|
465
|
-
let clientRefusals = [];
|
|
466
509
|
const body = node.childForFieldName("body");
|
|
467
510
|
if (body !== null) {
|
|
468
511
|
walkBody(body, fn, {
|
|
@@ -471,13 +514,88 @@ function readFunc(node, unit, file) {
|
|
|
471
514
|
suite: fn.isTest ? [name] : [],
|
|
472
515
|
inTest: fn.isTest,
|
|
473
516
|
});
|
|
474
|
-
// After `walkBody`, so `fn.locals` has every param and `:=`/`var`
|
|
475
|
-
// declaration, including a `*http.Client` built partway through the body.
|
|
476
|
-
const client = readGoClientCalls(body, unit, fn.locals, fn.isTest, fn.parameterNames);
|
|
477
|
-
clientCalls = client.calls;
|
|
478
|
-
clientRefusals = client.refusals;
|
|
479
517
|
}
|
|
480
|
-
|
|
518
|
+
// The HTTP read is DEFERRED to `readClients`, after the whole file is read.
|
|
519
|
+
//
|
|
520
|
+
// It used to run right here, and that put it before the file's own `const`
|
|
521
|
+
// block whenever the constant was written below the function that splices
|
|
522
|
+
// it — so DEC-164's base table answered "not bound" for a base plainly in
|
|
523
|
+
// view. The origin rule needs the same thing one step further: every base
|
|
524
|
+
// in the file, before any single call site can be judged.
|
|
525
|
+
unit.funcs.push({ ...fn, clientCalls: [], clientRefusals: [] });
|
|
526
|
+
if (body !== null)
|
|
527
|
+
pending.push({ index: unit.funcs.length - 1, body });
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* ONE WALK, READ TWICE — DEC-164's origin rule needs every base in the file
|
|
531
|
+
* before any single call site can be judged.
|
|
532
|
+
*
|
|
533
|
+
* `client-base.ts` admits an absolute call path only at an origin some base in
|
|
534
|
+
* this same file resolves to, and a base in a function above is still evidence
|
|
535
|
+
* about this call. The first read collects those origins; the second re-reads
|
|
536
|
+
* with them in hand, which is the only verdict the evidence can change. With
|
|
537
|
+
* no absolute base anywhere the set stays empty and the two reads agree, so
|
|
538
|
+
* the second one costs a tree walk and changes nothing — the same trade
|
|
539
|
+
* `adapter-typescript` makes.
|
|
540
|
+
*/
|
|
541
|
+
function readClients(unit, pending) {
|
|
542
|
+
if (pending.length === 0)
|
|
543
|
+
return;
|
|
544
|
+
const origins = new Set();
|
|
545
|
+
for (const { index, body } of pending) {
|
|
546
|
+
const fn = unit.funcs[index];
|
|
547
|
+
if (fn === undefined)
|
|
548
|
+
continue;
|
|
549
|
+
const first = readGoClientCalls(body, unit, fn.locals, fn.isTest, fn.parameterNames, unit.packageConsts);
|
|
550
|
+
for (const call of first.calls) {
|
|
551
|
+
if (call.baseOrigin !== undefined)
|
|
552
|
+
origins.add(call.baseOrigin);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
for (const { index, body } of pending) {
|
|
556
|
+
const fn = unit.funcs[index];
|
|
557
|
+
if (fn === undefined)
|
|
558
|
+
continue;
|
|
559
|
+
const client = readGoClientCalls(body, unit, fn.locals, fn.isTest, fn.parameterNames, unit.packageConsts, origins);
|
|
560
|
+
unit.funcs[index] = { ...fn, clientCalls: client.calls, clientRefusals: client.refusals };
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* `func (Order) TableName() string { return "orders" }` — the literal, or
|
|
565
|
+
* `undefined` for a body of any other shape.
|
|
566
|
+
*
|
|
567
|
+
* Requires the body to be exactly one `return` of exactly one interpreted
|
|
568
|
+
* string literal. Anything conditional, computed or concatenated is a runtime
|
|
569
|
+
* fact with nothing written down to read.
|
|
570
|
+
*/
|
|
571
|
+
function soleReturnedLiteral(body) {
|
|
572
|
+
if (body === null || body.namedChildCount !== 1)
|
|
573
|
+
return undefined;
|
|
574
|
+
// A `block`'s single named child is a `statement_list`, not the statement —
|
|
575
|
+
// found by probing the grammar rather than assuming it, after the first cut
|
|
576
|
+
// of this read silently returned `undefined` for every method.
|
|
577
|
+
let statement = body.namedChild(0);
|
|
578
|
+
if (statement !== null && statement.type === "statement_list") {
|
|
579
|
+
if (statement.namedChildCount !== 1)
|
|
580
|
+
return undefined;
|
|
581
|
+
statement = statement.namedChild(0);
|
|
582
|
+
}
|
|
583
|
+
if (statement === null || statement.type !== "return_statement")
|
|
584
|
+
return undefined;
|
|
585
|
+
const list = statement.namedChild(0);
|
|
586
|
+
const value = list !== null && list.type === "expression_list" && list.namedChildCount === 1
|
|
587
|
+
? list.namedChild(0)
|
|
588
|
+
: list;
|
|
589
|
+
if (value === null || value.type !== "interpreted_string_literal")
|
|
590
|
+
return undefined;
|
|
591
|
+
for (let i = 0; i < value.namedChildCount; i += 1) {
|
|
592
|
+
const child = value.namedChild(i);
|
|
593
|
+
// An escape sequence means the written text is not the value; refused
|
|
594
|
+
// rather than reported wrong.
|
|
595
|
+
if (child !== null && child.type !== "interpreted_string_literal_content")
|
|
596
|
+
return undefined;
|
|
597
|
+
}
|
|
598
|
+
return value.text.slice(1, -1);
|
|
481
599
|
}
|
|
482
600
|
/** Declared result types, in order. `(a, b Foo)` contributes one entry per name; position is what `x, err := f()` binds by. */
|
|
483
601
|
function resultTypes(result) {
|