@descryy/adapter-csharp 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 +263 -0
- package/dist/adapter.js.map +1 -0
- package/dist/aspnetcore.d.ts +207 -0
- package/dist/aspnetcore.d.ts.map +1 -0
- package/dist/aspnetcore.js +410 -0
- package/dist/aspnetcore.js.map +1 -0
- package/dist/client-base.d.ts +123 -0
- package/dist/client-base.d.ts.map +1 -0
- package/dist/client-base.js +123 -0
- package/dist/client-base.js.map +1 -0
- package/dist/client.d.ts +168 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +387 -0
- package/dist/client.js.map +1 -0
- package/dist/efcore.d.ts +198 -0
- package/dist/efcore.d.ts.map +1 -0
- package/dist/efcore.js +611 -0
- package/dist/efcore.js.map +1 -0
- package/dist/extract.d.ts +83 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +1120 -0
- package/dist/extract.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/nullability.d.ts +117 -0
- package/dist/nullability.d.ts.map +1 -0
- package/dist/nullability.js +152 -0
- package/dist/nullability.js.map +1 -0
- package/dist/parse.d.ts +240 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +861 -0
- package/dist/parse.js.map +1 -0
- package/dist/projects.d.ts +87 -0
- package/dist/projects.d.ts.map +1 -0
- package/dist/projects.js +226 -0
- package/dist/projects.js.map +1 -0
- package/dist/tree-sitter-c_sharp.wasm +0 -0
- package/package.json +35 -0
package/dist/efcore.js
ADDED
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ORM framework extractor for C# — Entity Framework Core.
|
|
3
|
+
*
|
|
4
|
+
* **A `MODEL` is a framework claim, and this file is where it is earned.**
|
|
5
|
+
* DEC-128 fixed the rules before extraction and **DEC-180 amended them after
|
|
6
|
+
* counting the corpus**, which is the part worth reading first: four of
|
|
7
|
+
* DEC-128's ORM rules were wrong, and every one of them was wrong in the same
|
|
8
|
+
* way — written from how EF Core is documented rather than from how the corpus
|
|
9
|
+
* is spelled. That is how a rule acquires zero witnesses.
|
|
10
|
+
*
|
|
11
|
+
* ## Admission — what the corpus actually contains
|
|
12
|
+
*
|
|
13
|
+
* | evidence | jellyfin | Ocelot | eShopOnWeb | CleanArchitecture |
|
|
14
|
+
* | --- | --- | --- | --- | --- |
|
|
15
|
+
* | `DbSet<` | 71 | 0 | 7 | 4 |
|
|
16
|
+
* | `IEntityTypeConfiguration<` | 26 | 0 | 7 | 2 |
|
|
17
|
+
* | `modelBuilder.Entity<` | **0** | **0** | **0** | **0** |
|
|
18
|
+
* | `[Table(` | **0** | **0** | **0** | **0** |
|
|
19
|
+
*
|
|
20
|
+
* So the admission grounds are:
|
|
21
|
+
*
|
|
22
|
+
* 1. **`DbSet<T>` on a `DbContext`.** Primary, and the only rule with witnesses
|
|
23
|
+
* in three of four corpora.
|
|
24
|
+
* 2. **`IEntityTypeConfiguration<T>`.** This *replaces* DEC-128's
|
|
25
|
+
* `modelBuilder.Entity<T>()` rule, which is the same fact written in a form
|
|
26
|
+
* the corpus does not contain.
|
|
27
|
+
* 3. `[Table]` and `modelBuilder.Entity<T>()` are still **read** where they
|
|
28
|
+
* appear, and are reported as **unwitnessed** — `0 of 0`, undefined, never as
|
|
29
|
+
* passing. A rule with zero witnesses cannot be shown to work or to fail, and
|
|
30
|
+
* its green is the green of a branch never taken.
|
|
31
|
+
*
|
|
32
|
+
* **Refused:** a type in a `Models` or `Entities` namespace with no mapping
|
|
33
|
+
* evidence — the `IFoo` guess this project forbids — and an owned type reached
|
|
34
|
+
* through `OwnsOne`, which shares its owner's table and has none of its own.
|
|
35
|
+
*
|
|
36
|
+
* ## Generated migrations are excluded, and the exclusion is counted
|
|
37
|
+
*
|
|
38
|
+
* DEC-128 read the table name from `ToTable(…)`. Measured: **1,338 of
|
|
39
|
+
* `jellyfin`'s 1,339 `ToTable` calls are inside `Migrations/`**, under a
|
|
40
|
+
* `// <auto-generated />` header, and 50 of `eShopOnWeb`'s 51. Those files are
|
|
41
|
+
* EF Core's serialised model from whenever someone last scaffolded a migration —
|
|
42
|
+
* an artefact of an operation, read as evidence about the world.
|
|
43
|
+
*
|
|
44
|
+
* An extractor reading them without excluding them is, to three significant
|
|
45
|
+
* figures, reading **only** generated code. So they are excluded — and the count
|
|
46
|
+
* is **reported**, because a silent exclusion of 1,338 of 1,339 is a correct
|
|
47
|
+
* decision that looks identical to a reader that never found them.
|
|
48
|
+
*
|
|
49
|
+
* ## No corpus can exercise the provenance rule
|
|
50
|
+
*
|
|
51
|
+
* `Dapper`, `NHibernate` and `linq2db` occur **zero** times across all four
|
|
52
|
+
* corpora. There is no C# repository here in which a rival ORM's types are
|
|
53
|
+
* present for these rules to correctly refuse — the identical hole the Java
|
|
54
|
+
* control set has. Stated before extraction rather than discovered after a green
|
|
55
|
+
* run, and every report carries the EF negative control as `0 of 0 — undefined`.
|
|
56
|
+
*/
|
|
57
|
+
import { referenceTypeNullable } from "./nullability.js";
|
|
58
|
+
const EF_NAMESPACES = ["Microsoft.EntityFrameworkCore"];
|
|
59
|
+
/**
|
|
60
|
+
* The built-in value types, which can never be null without a `?`.
|
|
61
|
+
*
|
|
62
|
+
* **Counted from the corpora, not copied from the language reference** — that is
|
|
63
|
+
* countermeasure 0, and the ORM half of DEC-128 is what happens without it. The
|
|
64
|
+
* declared property types across `jellyfin`, `eShopOnWeb` and `CleanArchitecture`
|
|
65
|
+
* are dominated by exactly this set: `string` 786, `bool` 539, `string?` 508,
|
|
66
|
+
* `int?` 332, `int` 218, `bool?` 156, `Guid` 111, `DateTime?` 69, `DateTime` 68,
|
|
67
|
+
* `long` 59, `Guid?` 51, `decimal`, `DateTimeOffset`.
|
|
68
|
+
*
|
|
69
|
+
* A user-declared `struct` or `enum` is also a value type — `CleanArchitecture`'s
|
|
70
|
+
* `PriorityLevel` is the witnessed case — and is resolved from the repository's
|
|
71
|
+
* own declarations rather than guessed from its name.
|
|
72
|
+
*/
|
|
73
|
+
const VALUE_TYPES = new Set([
|
|
74
|
+
"int", "uint", "long", "ulong", "short", "ushort", "byte", "sbyte",
|
|
75
|
+
"float", "double", "decimal", "bool", "char", "nint", "nuint",
|
|
76
|
+
"Int32", "Int64", "Boolean", "Decimal", "Double", "Single",
|
|
77
|
+
"Guid", "DateTime", "DateTimeOffset", "TimeSpan", "DateOnly", "TimeOnly",
|
|
78
|
+
]);
|
|
79
|
+
const importsIn = (file, namespaces, onlyGlobal = false) => file.usings.some((using) => (!onlyGlobal || using.isGlobal) &&
|
|
80
|
+
namespaces.some((ns) => using.target === ns || using.target.startsWith(`${ns}.`)));
|
|
81
|
+
/**
|
|
82
|
+
* Does this file import EF Core at all? Provenance, not spelling.
|
|
83
|
+
*
|
|
84
|
+
* **A `global using` counts, and it is in force across the whole assembly.**
|
|
85
|
+
* That is not an edge case: `eShop`'s `OrderingContext` declares nine
|
|
86
|
+
* `DbSet<T>` and its only file-local `using` is `eShop.IntegrationEventLogEF` —
|
|
87
|
+
* `Microsoft.EntityFrameworkCore` arrives from `GlobalUsings.cs` three files
|
|
88
|
+
* away. Checking file-local usings alone read **zero** models from a corpus with
|
|
89
|
+
* nine, silently.
|
|
90
|
+
*
|
|
91
|
+
* `parse.ts` already says a `global using` is *"in force for every file in the
|
|
92
|
+
* project, not just this one"* and models the flag. This is the first consumer
|
|
93
|
+
* to act on it. Modern C# leans on it heavily — .NET 6 onward emits an implicit
|
|
94
|
+
* global-usings file per project — so a reader that ignores it fails on new
|
|
95
|
+
* codebases specifically.
|
|
96
|
+
*
|
|
97
|
+
* Scoped by **assembly**, because that is what a project is. A global using in
|
|
98
|
+
* one project does not reach another.
|
|
99
|
+
*/
|
|
100
|
+
export function importsEfCore(file, globalsByAssembly) {
|
|
101
|
+
if (importsIn(file, EF_NAMESPACES))
|
|
102
|
+
return true;
|
|
103
|
+
return globalsByAssembly?.get(file.assembly) === true;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Is this file generated?
|
|
107
|
+
*
|
|
108
|
+
* Two signals, and both are needed. The `// <auto-generated />` header is the
|
|
109
|
+
* language's own convention and is what EF Core's scaffolder emits. The
|
|
110
|
+
* `Migrations/` path catches the migration classes beside the snapshot, which
|
|
111
|
+
* carry no header of their own in every version.
|
|
112
|
+
*/
|
|
113
|
+
export function isGenerated(path, source) {
|
|
114
|
+
if (/(^|\/)Migrations\//.test(path))
|
|
115
|
+
return true;
|
|
116
|
+
// Only the opening of the file: the marker is a header, and a mention of it
|
|
117
|
+
// deeper in a file is a comment about generated code, not a claim to be one.
|
|
118
|
+
return /<auto-generated/i.test(source.slice(0, 400));
|
|
119
|
+
}
|
|
120
|
+
/** `Foo<Bar>` -> `Bar`, for the single-argument generic forms read here. */
|
|
121
|
+
function typeArgument(written, generic) {
|
|
122
|
+
const match = new RegExp(`\\b${generic}\\s*<\\s*([A-Za-z_][A-Za-z0-9_.]*)`).exec(written);
|
|
123
|
+
return match?.[1]?.split(".").pop();
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Every type named inside a written type, the outer one and its arguments.
|
|
127
|
+
*
|
|
128
|
+
* `IReadOnlyCollection<OrderItem>` names both `IReadOnlyCollection` and
|
|
129
|
+
* `OrderItem`, and only the second decides whether the property is a navigation.
|
|
130
|
+
* Reading the outer name alone published `OrderItems` and `Items` as columns —
|
|
131
|
+
* a column per collection navigation, on a table that has no such column.
|
|
132
|
+
*/
|
|
133
|
+
function namesIn(written) {
|
|
134
|
+
return (written.match(/[A-Za-z_][A-Za-z0-9_.]*/g) ?? []).map((each) => each.split(".").pop());
|
|
135
|
+
}
|
|
136
|
+
/** The base name of a written type, `?` and generics removed. */
|
|
137
|
+
function baseOf(written) {
|
|
138
|
+
return written.replace(/\?+\s*$/, "").replace(/<.*$/, "").replace(/\[\]\s*$/, "").split(".").pop() ?? "";
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Is a written type a value type, a reference type, or not decidable here?
|
|
142
|
+
*
|
|
143
|
+
* `undefined` is the third answer and is the one that matters: an unknown type
|
|
144
|
+
* may be a `struct` this run did not analyse, and guessing "reference" would
|
|
145
|
+
* hand the question to the NRT context, which answers confidently. The lane's
|
|
146
|
+
* standing rule — a stated answer read as its opposite is worse than an unread
|
|
147
|
+
* one — applies to the type just as it does to the annotation.
|
|
148
|
+
*/
|
|
149
|
+
function isValueType(written, declaredForms) {
|
|
150
|
+
const base = baseOf(written);
|
|
151
|
+
if (written.trimEnd().endsWith("[]"))
|
|
152
|
+
return false; // An array is a reference type.
|
|
153
|
+
if (VALUE_TYPES.has(base))
|
|
154
|
+
return true;
|
|
155
|
+
if (base === "string" || base === "String" || base === "object")
|
|
156
|
+
return false;
|
|
157
|
+
const form = declaredForms.get(base);
|
|
158
|
+
if (form === "struct" || form === "enum")
|
|
159
|
+
return true;
|
|
160
|
+
if (form === "class" || form === "interface" || form === "record")
|
|
161
|
+
return false;
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
const EMPTY_FACTS = {
|
|
165
|
+
table: null,
|
|
166
|
+
required: new Set(),
|
|
167
|
+
optional: new Set(),
|
|
168
|
+
ignored: new Set(),
|
|
169
|
+
keys: new Set(),
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Read `builder.Property(x => x.Name).IsRequired()` and friends from source text.
|
|
173
|
+
*
|
|
174
|
+
* Deliberately textual and deliberately narrow. The Fluent API is a chained
|
|
175
|
+
* builder whose shape a syntax walk would have to model in full to read
|
|
176
|
+
* faithfully, and a partial walk that silently drops a link in the chain is the
|
|
177
|
+
* recall hole this lane has already paid for once. A regex over the configuring
|
|
178
|
+
* method's text answers the four questions DEC-128 §3 asks and **refuses
|
|
179
|
+
* everything else**, which is a smaller claim honestly made.
|
|
180
|
+
*
|
|
181
|
+
* `.IsRequired(false)` is read as *optional*, not skipped — it is the one form
|
|
182
|
+
* where the same call means the opposite thing, and dropping it would let the
|
|
183
|
+
* `[Required]` rule below answer for a member the Fluent API has explicitly made
|
|
184
|
+
* optional.
|
|
185
|
+
*/
|
|
186
|
+
function fluentFacts(source) {
|
|
187
|
+
const required = new Set();
|
|
188
|
+
const optional = new Set();
|
|
189
|
+
const ignored = new Set();
|
|
190
|
+
const keys = new Set();
|
|
191
|
+
const member = /Property\s*\(\s*[A-Za-z_][A-Za-z0-9_]*\s*=>\s*[A-Za-z_][A-Za-z0-9_]*\.([A-Za-z_][A-Za-z0-9_]*)\s*\)([^;]*)/g;
|
|
192
|
+
for (let match = member.exec(source); match !== null; match = member.exec(source)) {
|
|
193
|
+
const name = match[1];
|
|
194
|
+
const chain = match[2] ?? "";
|
|
195
|
+
if (/\.IsRequired\s*\(\s*false\s*\)/.test(chain))
|
|
196
|
+
optional.add(name);
|
|
197
|
+
else if (/\.IsRequired\s*\(/.test(chain))
|
|
198
|
+
required.add(name);
|
|
199
|
+
}
|
|
200
|
+
const ignore = /Ignore\s*\(\s*[A-Za-z_][A-Za-z0-9_]*\s*=>\s*[A-Za-z_][A-Za-z0-9_]*\.([A-Za-z_][A-Za-z0-9_]*)\s*\)/g;
|
|
201
|
+
for (let match = ignore.exec(source); match !== null; match = ignore.exec(source))
|
|
202
|
+
ignored.add(match[1]);
|
|
203
|
+
const key = /HasKey\s*\(\s*[A-Za-z_][A-Za-z0-9_]*\s*=>\s*[A-Za-z_][A-Za-z0-9_]*\.([A-Za-z_][A-Za-z0-9_]*)\s*\)/g;
|
|
204
|
+
for (let match = key.exec(source); match !== null; match = key.exec(source))
|
|
205
|
+
keys.add(match[1]);
|
|
206
|
+
const table = /\.ToTable\s*\(\s*"([^"]+)"/.exec(source);
|
|
207
|
+
return { table: table?.[1] ?? null, required, optional, ignored, keys };
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* The properties an entity inherits from non-entity ancestors.
|
|
211
|
+
*
|
|
212
|
+
* **The fourth instance of one construct class: the evidence is on an ancestor
|
|
213
|
+
* and the subject is the descendant.** JPA's `@MappedSuperclass` cost a third of
|
|
214
|
+
* an entity population; ASP.NET's base controller cost 98% of a corpus; this is
|
|
215
|
+
* the same shape in the C# ORM half, and it was checked for by name rather than
|
|
216
|
+
* met by surprise.
|
|
217
|
+
*
|
|
218
|
+
* `eShopOnWeb` declares every entity as `class BasketItem : BaseEntity` with
|
|
219
|
+
*
|
|
220
|
+
* public abstract class BaseEntity { public virtual int Id { get; protected set; } }
|
|
221
|
+
*
|
|
222
|
+
* so **every one of its models was missing its primary key column**.
|
|
223
|
+
*
|
|
224
|
+
* ## An entity ancestor stops the walk
|
|
225
|
+
*
|
|
226
|
+
* A base that is itself an admitted entity is an EF inheritance strategy —
|
|
227
|
+
* table-per-hierarchy, table-per-type, table-per-concrete — and which one applies
|
|
228
|
+
* decides whether the parent's properties are columns on this table, on a joined
|
|
229
|
+
* table, or on neither. That is a `HasDiscriminator`/`UseTptMappingStrategy` fact
|
|
230
|
+
* this does not read, so the walk stops rather than guessing. The identical rule
|
|
231
|
+
* `jpa.ts` applies to an `@Entity` parent, for the identical reason.
|
|
232
|
+
*/
|
|
233
|
+
function inheritedProperties(type, file, byName, isEntity) {
|
|
234
|
+
const chain = [];
|
|
235
|
+
const seen = new Set([`${file.file}::${type.path.join(".")}`]);
|
|
236
|
+
let current = { type, file };
|
|
237
|
+
// C# has single class inheritance, so this is a chain and not a search. The
|
|
238
|
+
// base class is the FIRST entry by DEC-084 — position is the evidence, and the
|
|
239
|
+
// `IFoo` convention is never read.
|
|
240
|
+
for (;;) {
|
|
241
|
+
const base = current.type.baseList[0];
|
|
242
|
+
if (base === undefined)
|
|
243
|
+
break;
|
|
244
|
+
// An interface first means there is no base class at all.
|
|
245
|
+
const candidates = byName.get(base);
|
|
246
|
+
if (candidates === undefined || candidates.length !== 1)
|
|
247
|
+
break;
|
|
248
|
+
const parent = candidates[0];
|
|
249
|
+
if (parent.type.form === "interface")
|
|
250
|
+
break;
|
|
251
|
+
const key = `${parent.file.file}::${parent.type.path.join(".")}`;
|
|
252
|
+
if (seen.has(key))
|
|
253
|
+
break;
|
|
254
|
+
seen.add(key);
|
|
255
|
+
if (isEntity(parent.type.name))
|
|
256
|
+
break;
|
|
257
|
+
// Nearest ancestor last, so the deepest base's `Id` sits at the far end and
|
|
258
|
+
// the entity's own properties still come first overall. Deterministic, which
|
|
259
|
+
// is what a node's `attrs` has to be across runs.
|
|
260
|
+
chain.unshift(...parent.type.properties);
|
|
261
|
+
current = parent;
|
|
262
|
+
}
|
|
263
|
+
return chain;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Is a property a persistent member? DEC-128 §3: public, with a getter, not
|
|
267
|
+
* `[NotMapped]` and not `.Ignore()`d.
|
|
268
|
+
*/
|
|
269
|
+
function isPersistent(property, facts) {
|
|
270
|
+
if (!property.isPublic || !property.hasGetter)
|
|
271
|
+
return false;
|
|
272
|
+
if (property.attributes.includes("NotMapped"))
|
|
273
|
+
return false;
|
|
274
|
+
return !facts.ignored.has(property.name);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Nullability, in DEC-128 §3's precedence order.
|
|
278
|
+
*
|
|
279
|
+
* Rule 5 is the one DEC-180 rewrote and the one that decides most of a real
|
|
280
|
+
* corpus. A bare reference type answers **only** under an enabled NRT context;
|
|
281
|
+
* under `off`, `absent` or `unreadable` it is `unresolved` and counted, because
|
|
282
|
+
* unknown is not false and publishing `false` there is a definite claim against
|
|
283
|
+
* a source that has said the compiler is not tracking.
|
|
284
|
+
*/
|
|
285
|
+
function nullabilityOf(property, facts, context, declaredForms) {
|
|
286
|
+
if (facts.required.has(property.name))
|
|
287
|
+
return { nullable: false, from: "fluent" };
|
|
288
|
+
if (facts.optional.has(property.name))
|
|
289
|
+
return { nullable: true, from: "fluent" };
|
|
290
|
+
if (property.attributes.includes("Required"))
|
|
291
|
+
return { nullable: false, from: "annotation" };
|
|
292
|
+
if (property.attributes.includes("Key") || facts.keys.has(property.name)) {
|
|
293
|
+
return { nullable: false, from: "annotation" };
|
|
294
|
+
}
|
|
295
|
+
const written = property.written.trimEnd();
|
|
296
|
+
const value = isValueType(written, declaredForms);
|
|
297
|
+
const optionalMark = written.endsWith("?");
|
|
298
|
+
if (value === true) {
|
|
299
|
+
// `int?` is `Nullable<int>` and is nullable **regardless of the NRT context**
|
|
300
|
+
// — it is a type, not an annotation. This is the case a reader that routes
|
|
301
|
+
// every `?` through the NRT context gets wrong in a file with NRT disabled.
|
|
302
|
+
return optionalMark
|
|
303
|
+
? { nullable: true, from: "nullable-value-type" }
|
|
304
|
+
: { nullable: false, from: "value-type" };
|
|
305
|
+
}
|
|
306
|
+
if (value === false) {
|
|
307
|
+
const answer = referenceTypeNullable(context, written);
|
|
308
|
+
return answer === undefined
|
|
309
|
+
? { nullable: undefined, from: "unresolved" }
|
|
310
|
+
: { nullable: answer, from: "reference-type" };
|
|
311
|
+
}
|
|
312
|
+
// A type this run did not analyse. It may be a struct, so neither the value
|
|
313
|
+
// rule nor the reference rule may claim it.
|
|
314
|
+
return { nullable: undefined, from: "unresolved" };
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Every EF Core model the batch declares, with the exclusions counted.
|
|
318
|
+
*
|
|
319
|
+
* Cross-file by necessity: a `DbSet<Order>` names `Order`, and `Order` is
|
|
320
|
+
* declared somewhere else. Same shape as JPA's mapped-superclass walk.
|
|
321
|
+
*/
|
|
322
|
+
/**
|
|
323
|
+
* Which of several same-named declarations a bare name can mean, from one file.
|
|
324
|
+
*
|
|
325
|
+
* C# does not resolve on the simple name. `parse.ts`'s own header states the
|
|
326
|
+
* rule — *"a bare name is resolved by searching the enclosing namespaces
|
|
327
|
+
* outward and then each import, which means a name may be found in two places,
|
|
328
|
+
* and that is an ambiguity to disclose rather than a tie to break"* — and this
|
|
329
|
+
* file did not implement it. It refused whenever a simple name was declared
|
|
330
|
+
* twice **anywhere in the repository**, which is strictly more conservative
|
|
331
|
+
* than the documented rule and is not the same rule.
|
|
332
|
+
*
|
|
333
|
+
* That cost eight entities across two corpora, every one of them resolvable:
|
|
334
|
+
* `eShopOnWeb`'s four are an entity beside a Blazor DTO in `BlazorShared.Models`,
|
|
335
|
+
* which the `DbContext` does not import; `jellyfin`'s four are an entity beside a
|
|
336
|
+
* transfer object in a namespace the context does not import either.
|
|
337
|
+
*
|
|
338
|
+
* **A rule stated in a comment and not implemented in code** — found by Lane E
|
|
339
|
+
* in a review of my classification, having just found three of the same in their
|
|
340
|
+
* own instrument. The countermeasure I wrote for theirs did not catch mine,
|
|
341
|
+
* which is the argument for a second reader rather than a better checklist.
|
|
342
|
+
*
|
|
343
|
+
* Visible namespaces are the file's own and each ancestor of it, plus every
|
|
344
|
+
* plain `using`, plus the assembly's `global using`s. A nested namespace is
|
|
345
|
+
* **not** visible from its parent by a bare name, which is why the enclosing
|
|
346
|
+
* walk alone does not admit `…Entities.Chapter` from `…Implementations`.
|
|
347
|
+
*
|
|
348
|
+
* Returns every reachable candidate. One is resolved; zero or several is an
|
|
349
|
+
* ambiguity, and the caller refuses exactly as before.
|
|
350
|
+
*/
|
|
351
|
+
function reachableFrom(candidates, from, globalUsings) {
|
|
352
|
+
if (from === undefined)
|
|
353
|
+
return candidates;
|
|
354
|
+
const visible = new Set([""]);
|
|
355
|
+
const segments = from.namespace === "" ? [] : from.namespace.split(".");
|
|
356
|
+
for (let depth = segments.length; depth > 0; depth -= 1)
|
|
357
|
+
visible.add(segments.slice(0, depth).join("."));
|
|
358
|
+
for (const using of from.usings) {
|
|
359
|
+
if (!using.isStatic && using.alias === undefined)
|
|
360
|
+
visible.add(using.target);
|
|
361
|
+
}
|
|
362
|
+
for (const target of globalUsings.get(from.assembly) ?? [])
|
|
363
|
+
visible.add(target);
|
|
364
|
+
return candidates.filter((each) => visible.has(each.file.namespace));
|
|
365
|
+
}
|
|
366
|
+
export function efModels(input) {
|
|
367
|
+
const declaredForms = new Map();
|
|
368
|
+
/** Simple name -> **every** analysed declaration of it. A list, never one. */
|
|
369
|
+
const typesByName = new Map();
|
|
370
|
+
let generatedFilesSkipped = 0;
|
|
371
|
+
let generatedToTableSkipped = 0;
|
|
372
|
+
const live = [];
|
|
373
|
+
for (const each of input.files) {
|
|
374
|
+
if (isGenerated(each.parsed.file, each.source)) {
|
|
375
|
+
generatedFilesSkipped += 1;
|
|
376
|
+
generatedToTableSkipped += (each.source.match(/\.ToTable\s*\(/g) ?? []).length;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
live.push(each);
|
|
380
|
+
for (const type of each.parsed.types) {
|
|
381
|
+
declaredForms.set(type.name, type.form);
|
|
382
|
+
const bucket = typesByName.get(type.name);
|
|
383
|
+
if (bucket === undefined)
|
|
384
|
+
typesByName.set(type.name, [{ type, file: each.parsed }]);
|
|
385
|
+
else
|
|
386
|
+
bucket.push({ type, file: each.parsed });
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
/** entity simple name -> how it was admitted, first rule wins by precedence. */
|
|
390
|
+
const admitted = new Map();
|
|
391
|
+
/** entity simple name -> the Fluent facts configuring it. */
|
|
392
|
+
const factsFor = new Map();
|
|
393
|
+
/** entity simple name -> a table named by `[Table]` or hand-written `ToTable`. */
|
|
394
|
+
const tableFor = new Map();
|
|
395
|
+
/** Types reached through `OwnsOne`, which have no table of their own. */
|
|
396
|
+
const owned = new Set();
|
|
397
|
+
/** Every rule that saw an entity, whether or not it won precedence. */
|
|
398
|
+
const sawByRule = new Map([
|
|
399
|
+
["dbset", new Set()],
|
|
400
|
+
["configuration", new Set()],
|
|
401
|
+
["table-attribute", new Set()],
|
|
402
|
+
["model-builder", new Set()],
|
|
403
|
+
]);
|
|
404
|
+
/**
|
|
405
|
+
* Where each name was admitted from — the file whose `using` block decides
|
|
406
|
+
* which declaration a bare name means. Recorded because a simple name is not
|
|
407
|
+
* the unit C# resolves in, and refusing on simple-name collision alone is
|
|
408
|
+
* strictly more conservative than the rule `parse.ts` documents.
|
|
409
|
+
*/
|
|
410
|
+
const admittedIn = new Map();
|
|
411
|
+
let admittingFile;
|
|
412
|
+
const admit = (name, by) => {
|
|
413
|
+
if (name === undefined || name === "")
|
|
414
|
+
return;
|
|
415
|
+
sawByRule.get(by).add(name);
|
|
416
|
+
admitted.set(name, by);
|
|
417
|
+
if (admittingFile !== undefined)
|
|
418
|
+
admittedIn.set(name, admittingFile);
|
|
419
|
+
};
|
|
420
|
+
// Global usings, gathered once per assembly. See `importsEfCore`.
|
|
421
|
+
const efGlobals = new Map();
|
|
422
|
+
for (const { parsed } of live) {
|
|
423
|
+
if (importsIn(parsed, EF_NAMESPACES, true))
|
|
424
|
+
efGlobals.set(parsed.assembly, true);
|
|
425
|
+
}
|
|
426
|
+
// Namespaces every file in an assembly can see without saying so.
|
|
427
|
+
const globalUsingsByAssembly = new Map();
|
|
428
|
+
for (const { parsed } of live) {
|
|
429
|
+
let set = globalUsingsByAssembly.get(parsed.assembly);
|
|
430
|
+
if (set === undefined) {
|
|
431
|
+
set = new Set();
|
|
432
|
+
globalUsingsByAssembly.set(parsed.assembly, set);
|
|
433
|
+
}
|
|
434
|
+
for (const using of parsed.usings) {
|
|
435
|
+
if (using.isGlobal && !using.isStatic && using.alias === undefined)
|
|
436
|
+
set.add(using.target);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
for (const { parsed, source } of live) {
|
|
440
|
+
if (!importsEfCore(parsed, efGlobals))
|
|
441
|
+
continue;
|
|
442
|
+
admittingFile = parsed;
|
|
443
|
+
for (const type of parsed.types) {
|
|
444
|
+
// 1. `DbSet<T>` on a context. The property's own type carries the entity.
|
|
445
|
+
const isContext = type.baseList.some((base) => baseOf(base).endsWith("DbContext"));
|
|
446
|
+
if (isContext) {
|
|
447
|
+
for (const property of type.properties) {
|
|
448
|
+
const entity = typeArgument(property.written, "DbSet");
|
|
449
|
+
admit(entity, "dbset");
|
|
450
|
+
// EF Core's real convention: an unconfigured entity's table is the
|
|
451
|
+
// DbSet property's name. A framework fact, not an inference.
|
|
452
|
+
if (entity !== undefined && !tableFor.has(entity))
|
|
453
|
+
tableFor.set(entity, property.name);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// 2. `IEntityTypeConfiguration<T>` — DEC-180's replacement for
|
|
457
|
+
// `modelBuilder.Entity<T>()`, which has zero witnesses anywhere.
|
|
458
|
+
for (const base of type.baseListWritten) {
|
|
459
|
+
const entity = typeArgument(base, "IEntityTypeConfiguration");
|
|
460
|
+
if (entity === undefined)
|
|
461
|
+
continue;
|
|
462
|
+
admit(entity, "configuration");
|
|
463
|
+
const facts = fluentFacts(source);
|
|
464
|
+
factsFor.set(entity, facts);
|
|
465
|
+
if (facts.table !== null)
|
|
466
|
+
tableFor.set(entity, facts.table);
|
|
467
|
+
}
|
|
468
|
+
// 3. `[Table]`. Retained, unwitnessed, reported as 0 of 0.
|
|
469
|
+
if (type.attributes.includes("Table"))
|
|
470
|
+
admit(type.name, "table-attribute");
|
|
471
|
+
}
|
|
472
|
+
// 4. `modelBuilder.Entity<T>()`. Also unwitnessed; read where it appears.
|
|
473
|
+
const builder = /\b(?:modelBuilder|builder)\s*\.\s*Entity\s*<\s*([A-Za-z_][A-Za-z0-9_.]*)/g;
|
|
474
|
+
for (let match = builder.exec(source); match !== null; match = builder.exec(source)) {
|
|
475
|
+
admit(match[1].split(".").pop(), "model-builder");
|
|
476
|
+
}
|
|
477
|
+
// An owned type shares its owner's table — EF Core's `@Embeddable`.
|
|
478
|
+
const owns = /\.\s*OwnsOne\s*<?\s*(?:[A-Za-z_][A-Za-z0-9_.]*\s*,\s*)?([A-Za-z_][A-Za-z0-9_.]*)/g;
|
|
479
|
+
for (let match = owns.exec(source); match !== null; match = owns.exec(source)) {
|
|
480
|
+
owned.add(match[1].split(".").pop());
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
// Precedence is settled HERE, after all evidence is in, and not by whichever
|
|
484
|
+
// file happened to be read first. `admit` records every rule that saw an
|
|
485
|
+
// entity; this picks the winner by DEC-180's order. The first version let file
|
|
486
|
+
// order decide, which made `eShopOnWeb` report its models as admitted by
|
|
487
|
+
// configuration and `jellyfin` by DbSet for no reason in the source — a
|
|
488
|
+
// difference between two corpora produced entirely by the reader.
|
|
489
|
+
const PRECEDENCE = ["dbset", "configuration", "table-attribute", "model-builder"];
|
|
490
|
+
for (const name of admitted.keys()) {
|
|
491
|
+
for (const rule of PRECEDENCE) {
|
|
492
|
+
if (sawByRule.get(rule).has(name)) {
|
|
493
|
+
admitted.set(name, rule);
|
|
494
|
+
break;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
const models = [];
|
|
499
|
+
const admittedBy = { dbset: 0, configuration: 0, "table-attribute": 0, "model-builder": 0 };
|
|
500
|
+
const ambiguousEntityNames = [];
|
|
501
|
+
/** Simple-name collisions, split by whether the namespace rule settled them. */
|
|
502
|
+
const resolvedByNamespace = { resolved: 0, unresolved: 0 };
|
|
503
|
+
let navigationsRefused = 0;
|
|
504
|
+
for (const [name, by] of admitted) {
|
|
505
|
+
if (owned.has(name))
|
|
506
|
+
continue;
|
|
507
|
+
const all = typesByName.get(name);
|
|
508
|
+
if (all === undefined || all.length === 0)
|
|
509
|
+
continue; // Named, not analysed.
|
|
510
|
+
const candidates = all.length === 1 ? all : reachableFrom(all, admittedIn.get(name), globalUsingsByAssembly);
|
|
511
|
+
if (candidates.length !== 1) {
|
|
512
|
+
// Ambiguous *after* resolution, or reachable from nowhere. Either way this
|
|
513
|
+
// reader cannot say which declaration was meant, and picking one publishes
|
|
514
|
+
// another type's columns under this entity's name.
|
|
515
|
+
ambiguousEntityNames.push(name);
|
|
516
|
+
if (all.length > 1)
|
|
517
|
+
resolvedByNamespace.unresolved += 1;
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
if (all.length > 1)
|
|
521
|
+
resolvedByNamespace.resolved += 1;
|
|
522
|
+
const found = candidates[0];
|
|
523
|
+
const facts = factsFor.get(name) ?? EMPTY_FACTS;
|
|
524
|
+
const context = input.contextOf(found.file.file);
|
|
525
|
+
const own = new Set(found.type.properties.map((each) => each.name));
|
|
526
|
+
const inherited = inheritedProperties(found.type, found.file, typesByName, (n) => admitted.has(n)).filter(
|
|
527
|
+
// A subclass redeclaring an inherited property keeps its own declaration.
|
|
528
|
+
(each) => !own.has(each.name));
|
|
529
|
+
const columns = [];
|
|
530
|
+
for (const property of [...found.type.properties, ...inherited]) {
|
|
531
|
+
if (!isPersistent(property, facts))
|
|
532
|
+
continue;
|
|
533
|
+
// A navigation is a relationship, not a scalar column, and refusing it is
|
|
534
|
+
// precision rather than caution: `IReadOnlyCollection<OrderItem> Items`
|
|
535
|
+
// published a column named `Items` on a table that has no such column.
|
|
536
|
+
//
|
|
537
|
+
// Both shapes count — a reference to an entity, and a collection OF one —
|
|
538
|
+
// so every name inside the written type is checked, not just the outer.
|
|
539
|
+
// An owned type is refused for the same reason by a different mechanism:
|
|
540
|
+
// EF spreads it across several columns of the owner's table, so it is not
|
|
541
|
+
// one column and this reader cannot say what the several are.
|
|
542
|
+
// See `navigationsRefused`. A scalar column's type is a primitive, a
|
|
543
|
+
// string, an enum, a struct or a byte array. Anything whose declared type
|
|
544
|
+
// resolves to a class, record or interface DECLARED IN THIS REPOSITORY is
|
|
545
|
+
// a navigation or an owned type, and is not one column.
|
|
546
|
+
const referenced = namesIn(property.written);
|
|
547
|
+
const isNavigation = referenced.some((each) => {
|
|
548
|
+
// A type referring to itself is still a navigation. `BaseItemEntity`
|
|
549
|
+
// declares `ICollection<BaseItemEntity>? Extras`, a self-referencing
|
|
550
|
+
// collection, and this guard published it as a column named `Extras` on
|
|
551
|
+
// a table that has no such column — the exact failure the rule above
|
|
552
|
+
// describes, exempted by the one case the rule did not think of.
|
|
553
|
+
//
|
|
554
|
+
// The guard was there so a property whose type is the entity itself did
|
|
555
|
+
// not refuse the entity; but that is the navigation case, not an
|
|
556
|
+
// exception to it. Kept only for the *name* the model is keyed by when
|
|
557
|
+
// the property type is not a reference at all.
|
|
558
|
+
if (each === name)
|
|
559
|
+
return property.written.includes("<") || property.written.replace(/[?\s]/g, "") === name;
|
|
560
|
+
if (admitted.has(each) || owned.has(each))
|
|
561
|
+
return true;
|
|
562
|
+
const form = declaredForms.get(each);
|
|
563
|
+
return form === "class" || form === "record" || form === "interface";
|
|
564
|
+
});
|
|
565
|
+
if (isNavigation) {
|
|
566
|
+
navigationsRefused += 1;
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
const { nullable, from } = nullabilityOf(property, facts, context, declaredForms);
|
|
570
|
+
columns.push({ name: property.name, nullable, nullableFrom: from });
|
|
571
|
+
}
|
|
572
|
+
if (columns.length === 0)
|
|
573
|
+
continue;
|
|
574
|
+
admittedBy[by] += 1;
|
|
575
|
+
models.push({
|
|
576
|
+
typeName: name,
|
|
577
|
+
fqn: found.file.namespace === ""
|
|
578
|
+
? found.type.path.join(".")
|
|
579
|
+
: `${found.file.namespace}.${found.type.path.join(".")}`,
|
|
580
|
+
path: found.type.path,
|
|
581
|
+
table: tableFor.get(name) ?? null,
|
|
582
|
+
admittedBy: by,
|
|
583
|
+
columns,
|
|
584
|
+
line: found.type.startLine,
|
|
585
|
+
file: found.file.file,
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
const emitted = new Set(models.map((model) => model.typeName));
|
|
589
|
+
const evidenceFor = {
|
|
590
|
+
dbset: 0,
|
|
591
|
+
configuration: 0,
|
|
592
|
+
"table-attribute": 0,
|
|
593
|
+
"model-builder": 0,
|
|
594
|
+
};
|
|
595
|
+
for (const [rule, names] of sawByRule) {
|
|
596
|
+
for (const name of names)
|
|
597
|
+
if (emitted.has(name))
|
|
598
|
+
evidenceFor[rule] += 1;
|
|
599
|
+
}
|
|
600
|
+
return {
|
|
601
|
+
models,
|
|
602
|
+
generatedFilesSkipped,
|
|
603
|
+
generatedToTableSkipped,
|
|
604
|
+
ambiguousEntityNames: ambiguousEntityNames.sort(),
|
|
605
|
+
namespaceResolved: { ...resolvedByNamespace },
|
|
606
|
+
navigationsRefused,
|
|
607
|
+
admittedBy,
|
|
608
|
+
evidenceFor,
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
//# sourceMappingURL=efcore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"efcore.js","sourceRoot":"","sources":["../src/efcore.ts"],"names":[],"mappings":"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"}
|