@descryy/adapter-csharp 0.1.0 → 0.3.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/parse.d.ts CHANGED
@@ -1,31 +1,21 @@
1
1
  /**
2
2
  * One C# file, read into the shape the resolver wants.
3
3
  *
4
- * Hand-written walk, as in Java, Go, Rust and PHP, and for the same reason:
5
- * containment is what a resolver needs and a query's match set is exactly what
6
- * discards it.
4
+ * Hand-written walk, as in Java/Go/Rust/PHP: containment is what a resolver
5
+ * needs, and a query's match set discards exactly that.
7
6
  *
8
- * ## What C# changes
7
+ * What C# changes:
8
+ * - A type may be declared in several files (`partial class`) — DEC-083
9
+ * settles identity, this reader only collects the parts.
10
+ * - `using` imports a namespace, not one type (unlike PHP's `use`), so a bare
11
+ * name is resolved outward through enclosing namespaces then imports —
12
+ * found in two places is an ambiguity to disclose, not a tie to break.
13
+ * - The base list doesn't say which entry is the class. DEC-084: at most one
14
+ * base class, required first, so later entries are interfaces
15
+ * unconditionally and only the first ever needs resolving. `IFoo` isn't read.
9
16
  *
10
- * Three things here are genuinely new work rather than a translation of an
11
- * earlier language's rules.
12
- *
13
- * - **A type may be declared in several files.** `partial class` is the first
14
- * construct in this project whose declaration is legitimately multi-file and
15
- * says so in the source. DEC-083 settles the identity question; this reader
16
- * only has to collect the parts.
17
- * - **`using` imports a namespace, not a type.** PHP's `use` names one class
18
- * and resolves in one step. C#'s brings in every type in a namespace, so a
19
- * bare name is resolved by searching the enclosing namespaces outward and
20
- * then each import — which means a name may be found in two places, and
21
- * that is an ambiguity to disclose rather than a tie to break.
22
- * - **The base list does not say which entry is the class.** DEC-084 decides
23
- * it: at most one base class, and the language requires it first, so entries
24
- * after the first are interfaces unconditionally and only one entry per
25
- * class declaration ever needs resolving. The `IFoo` convention is not read.
26
- *
27
- * Nested types are ordinary here in a way they are not in PHP, so a type carries
28
- * its nesting path rather than a single name.
17
+ * Nested types are ordinary here (unlike PHP), so a type carries its nesting
18
+ * path, not a single name.
29
19
  */
30
20
  import type { Node } from "@descryy/adapter-treesitter";
31
21
  export interface CsRef {
@@ -51,31 +41,25 @@ export interface CsRef {
51
41
  readonly name: string;
52
42
  };
53
43
  /**
54
- * The name *might* be a type, and might equally be a variable.
55
- *
56
- * `Status.Pending` and `order.Total` are the same node shape, and only the
57
- * resolver knows whether `Status` names a type or `order` names a local. A
58
- * speculative reference that turns out to be a value is not an unresolved
59
- * reference — it is not a type reference at all — so it is dropped silently
60
- * instead of filling the ledger with entries no reader could act on.
44
+ * The name might be a type, might be a variable — `Status.Pending` and
45
+ * `order.Total` are the same node shape, only the resolver knows which.
46
+ * A speculative ref resolving to a value isn't unresolved, it's not a type
47
+ * reference at all, so it's dropped silently rather than ledgered.
61
48
  */
62
49
  readonly speculative?: boolean;
63
50
  readonly line: number;
64
51
  readonly raw: string;
65
52
  /**
66
- * The call's first argument, only when it is a bare string literal —
67
- * mirrors Java's `JavaRef.firstStringArgument` exactly, for the identical
68
- * reason: a `binary_expression` or interpolated first argument returns
69
- * `undefined` rather than a fragment, because the written prefix is not the
70
- * value at run time. See {@link firstStringArgumentOf}.
53
+ * The call's first argument, only when a bare string literal — mirrors
54
+ * Java's `JavaRef.firstStringArgument`: a binary/interpolated expression
55
+ * returns `undefined`, since the written prefix isn't the runtime value.
56
+ * See {@link firstStringArgumentOf}.
71
57
  */
72
58
  readonly firstStringArgument?: string;
73
59
  /**
74
- * The first argument's raw source text, captured whether or not it is a
75
- * literal — mirrors Java's `JavaRef.firstArgumentText` exactly: DEC-242's
76
- * `blockedBy`/`refusalClass` classification needs to see *what* blocked
77
- * resolution when {@link firstStringArgument} is absent, not just that it
78
- * was absent.
60
+ * The first argument's raw text regardless of shape — mirrors Java's
61
+ * `JavaRef.firstArgumentText`: DEC-242 needs to see what blocked resolution
62
+ * when {@link firstStringArgument} is absent, not just that it was.
79
63
  */
80
64
  readonly firstArgumentText?: string;
81
65
  }
@@ -88,23 +72,19 @@ export interface CsScope {
88
72
  readonly locals: Map<string, string | null>;
89
73
  readonly pending: Map<string, PendingType>;
90
74
  /**
91
- * Names declared in the enclosing method's own parameter list — a subset of
92
- * {@link locals}'s keys, kept separately because DEC-242's `varies-per-call`
93
- * classification needs *parameter*, not *local*: a call argument that is a
94
- * bare parameter name is a caller-supplied value with no fixed answer to
95
- * state; a local variable might still be assigned from a constant.
75
+ * Names from the enclosing method's parameter list, a subset of
76
+ * {@link locals}'s keys kept separately: DEC-242's `varies-per-call` needs
77
+ * *parameter*, not *local* — a bare parameter name is caller-supplied with
78
+ * no fixed answer, a local might still be a constant.
96
79
  */
97
80
  readonly parameterNames: Set<string>;
98
81
  /**
99
- * `X = expr;` and `this.X = expr;` where `expr` is a traceable invocation —
100
- * `PendingType`'s own `{receiver, name}` shape, reused rather than duplicated.
101
- * Only consulted for a `.ctor`'s own scope, by D-FIX-3's client-base
102
- * extractor (DEC-164): `public HttpClient Client { get; }` assigned in the
103
- * constructor from `factory.CreateClient()` is the shape eShopOnWeb's whole
104
- * `USES_API` population goes through, and a property has no initialiser of
105
- * its own to read the way a field does — the constructor body is the only
106
- * place the assignment is written. Harmless elsewhere; nothing outside a
107
- * `.ctor` walk reads this map.
82
+ * `X = expr;` / `this.X = expr;` where `expr` is a traceable invocation,
83
+ * reusing `PendingType`'s shape. Consulted only for a `.ctor`'s scope, by
84
+ * the client-base extractor (DEC-164): a property assigned in the
85
+ * constructor from `factory.CreateClient()` (eShopOnWeb's whole `USES_API`
86
+ * population) has no initialiser of its own — the ctor body is the only
87
+ * place the assignment is written.
108
88
  */
109
89
  readonly propertyAssignments: Map<string, PendingType>;
110
90
  }
@@ -124,19 +104,17 @@ export interface CsFunc {
124
104
  readonly scope: CsScope;
125
105
  }
126
106
  /**
127
- * A property declaration, kept alongside the `members` name→type map.
128
- *
129
- * The map answers "what type is this name" for receiver typing. EF Core needs
130
- * four things it cannot carry: the **attributes** (`[Key]`, `[Required]`,
131
- * `[NotMapped]`), the **line**, whether the property is **public with a getter**
132
- * — DEC-128 §3's definition of a persistent member — and the type **as written**.
107
+ * A property declaration, kept alongside the `members` name->type map, which
108
+ * answers "what type is this name" for receiver typing. EF Core needs four
109
+ * things the map can't carry: attributes (`[Key]`, `[Required]`, `[NotMapped]`),
110
+ * line, public-with-getter (DEC-128 §3's persistent-member test), and the
111
+ * type as written.
133
112
  *
134
- * `written` is the raw source text, not the base name, and that is load-bearing.
135
- * `string` and `string?` have the same base name and opposite nullability, and
136
- * `int?` is nullable regardless of the NRT context while `string?` is meaningful
137
- * only under it. A reader that keeps only the base name cannot tell any of those
138
- * apart. Counted across the corpora before choosing this shape: `string` 786 /
139
- * `string?` 508 / `int?` 332 / `int` 218 in `jellyfin` alone.
113
+ * `written` is raw source text, not the base name: `string`/`string?` share a
114
+ * base name but opposite nullability, and `int?` is nullable regardless of
115
+ * NRT context while `string?` is meaningful only under it. Counted across
116
+ * corpora before choosing this shape: `string` 786 / `string?` 508 / `int?`
117
+ * 332 / `int` 218 in jellyfin alone.
140
118
  */
141
119
  export interface CsProperty {
142
120
  readonly name: string;
@@ -159,18 +137,11 @@ export interface CsType {
159
137
  /** The base list **in written order**. DEC-084 reads position as evidence. */
160
138
  readonly baseList: string[];
161
139
  /**
162
- * The same entries **as written**, generic arguments intact.
163
- *
164
- * `baseList` goes through `typeName`, which drops generic arguments on purpose
165
- * — `List<Order>` names `List`, and identity is what the resolver wants. A
166
- * framework extractor wants the opposite: `IEntityTypeConfiguration<Order>`
167
- * *is* the mapping declaration and `Order` is the whole fact, so the collapsed
168
- * form is empty of the thing EF Core is stating.
169
- *
170
- * Both are right and both are kept. This is the second construct where a
171
- * language-level normalisation and a framework-level reading want different
172
- * halves of the same node — the first was a property's written type, where
173
- * `string` and `string?` share a base name and have opposite nullability.
140
+ * The same entries as written, generic arguments intact. `baseList` drops
141
+ * generics via `typeName` (`List<Order>` -> `List`, identity for the
142
+ * resolver), but `IEntityTypeConfiguration<Order>`'s `Order` argument *is*
143
+ * the mapping fact a framework extractor needs — the collapsed form is
144
+ * empty of it. Both kept, same split as a property's written type.
174
145
  */
175
146
  readonly baseListWritten: string[];
176
147
  /** Property and field names -> declared type, `null` when ambiguous. */
@@ -184,13 +155,11 @@ export interface CsType {
184
155
  readonly endLine: number;
185
156
  readonly typeRefs: CsRef[];
186
157
  /**
187
- * A field's own inline initialiser, when it is a traceable invocation —
188
- * `private readonly HttpClient _client = factory.CreateClient();`. Same
189
- * `PendingType` shape and same one reader (D-FIX-3's client-base extractor,
190
- * DEC-164) as `CsScope.propertyAssignments`; kept separate because a field
191
- * initialiser is read here, at the declaration, and a property's is read
192
- * from its `.ctor`'s body — two different places in the source for the
193
- * same fact.
158
+ * A field's own inline initialiser when it's a traceable invocation
159
+ * (`private readonly HttpClient _client = factory.CreateClient();`). Same
160
+ * shape and reader as `CsScope.propertyAssignments`, kept separate because
161
+ * a field initialiser is read at the declaration, a property's from its
162
+ * `.ctor` body — different places in the source for the same fact.
194
163
  */
195
164
  readonly memberProvenance: Map<string, PendingType>;
196
165
  }
@@ -201,14 +170,10 @@ export interface CsUsing {
201
170
  readonly alias: string | undefined;
202
171
  readonly isStatic: boolean;
203
172
  /**
204
- * `global using …` — in force for **every file in the project**, not just
205
- * this one.
206
- *
207
- * Modern C# leans on this heavily: .NET 6 onwards emits a generated file of
208
- * implicit global usings for every project, and an alias declared this way is
209
- * the language's one construct that binds a name here to a type declared
210
- * elsewhere without creating a second symbol. Treating it as file-local would
211
- * make every name it introduces unresolvable everywhere else.
173
+ * `global using …` — in force for every file in the project, not just this
174
+ * one. Modern C# (.NET 6+ implicit global usings) leans on this heavily;
175
+ * treating it as file-local would make every name it introduces
176
+ * unresolvable elsewhere.
212
177
  */
213
178
  readonly isGlobal: boolean;
214
179
  readonly line: number;
@@ -225,15 +190,10 @@ export interface CsFile {
225
190
  readonly assembly: string;
226
191
  }
227
192
  /**
228
- * The type a type expression names.
229
- *
230
- * `undefined` — none (predefined, `var`, or absent).
231
- * `null` — a type is named but which one is ambiguous.
232
- * `string` — the single type named, as written, generic arguments dropped.
233
- *
234
- * Generic arguments are dropped deliberately: `List<Order>` names `List`, and
235
- * `Order` inside it is a separate reference the walker records on its own. A
236
- * single collapsed name would attribute the collection's methods to its element.
193
+ * The type a type expression names. `undefined` = none (predefined/`var`/absent),
194
+ * `null` = named but ambiguous, `string` = the type, generics dropped
195
+ * (`List<Order>` -> `List`; `Order` is recorded as its own reference —
196
+ * collapsing both would attribute the collection's methods to its element).
237
197
  */
238
198
  export declare function typeName(node: Node | null | undefined): string | null | undefined;
239
199
  export declare function readFile(root: Node, file: string, hasError: boolean): CsFile;
@@ -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
@@ -1,31 +1,21 @@
1
1
  /**
2
2
  * One C# file, read into the shape the resolver wants.
3
3
  *
4
- * Hand-written walk, as in Java, Go, Rust and PHP, and for the same reason:
5
- * containment is what a resolver needs and a query's match set is exactly what
6
- * discards it.
4
+ * Hand-written walk, as in Java/Go/Rust/PHP: containment is what a resolver
5
+ * needs, and a query's match set discards exactly that.
7
6
  *
8
- * ## What C# changes
7
+ * What C# changes:
8
+ * - A type may be declared in several files (`partial class`) — DEC-083
9
+ * settles identity, this reader only collects the parts.
10
+ * - `using` imports a namespace, not one type (unlike PHP's `use`), so a bare
11
+ * name is resolved outward through enclosing namespaces then imports —
12
+ * found in two places is an ambiguity to disclose, not a tie to break.
13
+ * - The base list doesn't say which entry is the class. DEC-084: at most one
14
+ * base class, required first, so later entries are interfaces
15
+ * unconditionally and only the first ever needs resolving. `IFoo` isn't read.
9
16
  *
10
- * Three things here are genuinely new work rather than a translation of an
11
- * earlier language's rules.
12
- *
13
- * - **A type may be declared in several files.** `partial class` is the first
14
- * construct in this project whose declaration is legitimately multi-file and
15
- * says so in the source. DEC-083 settles the identity question; this reader
16
- * only has to collect the parts.
17
- * - **`using` imports a namespace, not a type.** PHP's `use` names one class
18
- * and resolves in one step. C#'s brings in every type in a namespace, so a
19
- * bare name is resolved by searching the enclosing namespaces outward and
20
- * then each import — which means a name may be found in two places, and
21
- * that is an ambiguity to disclose rather than a tie to break.
22
- * - **The base list does not say which entry is the class.** DEC-084 decides
23
- * it: at most one base class, and the language requires it first, so entries
24
- * after the first are interfaces unconditionally and only one entry per
25
- * class declaration ever needs resolving. The `IFoo` convention is not read.
26
- *
27
- * Nested types are ordinary here in a way they are not in PHP, so a type carries
28
- * its nesting path rather than a single name.
17
+ * Nested types are ordinary here (unlike PHP), so a type carries its nesting
18
+ * path, not a single name.
29
19
  */
30
20
  /** Keywords that name no user type. `var` is handled separately. */
31
21
  const PREDEFINED = new Set([
@@ -34,15 +24,10 @@ const PREDEFINED = new Set([
34
24
  "void", "dynamic", "nint", "nuint", "var",
35
25
  ]);
36
26
  /**
37
- * The type a type expression names.
38
- *
39
- * `undefined` — none (predefined, `var`, or absent).
40
- * `null` — a type is named but which one is ambiguous.
41
- * `string` — the single type named, as written, generic arguments dropped.
42
- *
43
- * Generic arguments are dropped deliberately: `List<Order>` names `List`, and
44
- * `Order` inside it is a separate reference the walker records on its own. A
45
- * single collapsed name would attribute the collection's methods to its element.
27
+ * The type a type expression names. `undefined` = none (predefined/`var`/absent),
28
+ * `null` = named but ambiguous, `string` = the type, generics dropped
29
+ * (`List<Order>` -> `List`; `Order` is recorded as its own reference —
30
+ * collapsing both would attribute the collection's methods to its element).
46
31
  */
47
32
  export function typeName(node) {
48
33
  if (node === null || node === undefined)
@@ -93,18 +78,12 @@ function hasModifier(node, keyword) {
93
78
  return false;
94
79
  }
95
80
  /**
96
- * `[Fact]`, `[Theory]`, `[Xunit.Fact]` -> the last segment, **and its arguments**.
97
- *
98
- * The names alone were enough while `isTest` was the only consumer. A framework
99
- * extractor needs the other half: `[Route("System/ActivityLog")]` collapses to
100
- * `Route`, and the argument that is dropped **is the route**.
101
- *
102
- * That is the third instance of one shape in this adapter set — identity
103
- * normalises, fidelity preserves, and both readings are correct for different
104
- * consumers. The first two were a property's written type (`string` against
105
- * `string?`) and a base list's generic argument
106
- * (`IEntityTypeConfiguration<Order>`). Each collapse surfaced downstream as a
107
- * clean zero rather than as an error, so both are carried side by side now.
81
+ * `[Fact]`, `[Theory]`, `[Xunit.Fact]` -> the last segment, and its arguments.
82
+ * Names alone were enough while `isTest` was the only consumer; a framework
83
+ * extractor needs the other half — `[Route("System/ActivityLog")]` collapses
84
+ * to `Route`, and the dropped argument *is* the route. Third instance of
85
+ * identity-normalises/fidelity-preserves in this adapter (after a property's
86
+ * written type and a base list's generic argument).
108
87
  */
109
88
  function attributeArgumentsOf(node) {
110
89
  const found = {};
@@ -178,11 +157,9 @@ function describeReceiver(node) {
178
157
  return typeof named === "string" ? { written: undefined, type: named } : { written: undefined, opaque: true };
179
158
  }
180
159
  case "conditional_access_expression": {
181
- // `x?.y.z()` and `a?[0].F()`. The null-conditional changes only whether the
182
- // chain is evaluated, never what it denotes: `x?.y` names exactly what
183
- // `x.y` names. Unwrapping it here is what lets the ordinary member-access
184
- // machinery below do the work; falling through to `default` made every
185
- // such receiver opaque, and before the flag above existed, implicit.
160
+ // `x?.y.z()` / `a?[0].F()`: null-conditional changes only whether the
161
+ // chain evaluates, not what it denotes (`x?.y` names what `x.y` names).
162
+ // Unwrapping here reuses the member-access machinery below.
186
163
  const object = describeReceiver(node.namedChild(0));
187
164
  const binding = node.namedChild(1);
188
165
  if (binding?.type !== "member_binding_expression") {
@@ -199,11 +176,10 @@ function describeReceiver(node) {
199
176
  };
200
177
  }
201
178
  case "member_access_expression": {
202
- // `this._repository.FindById()` — the type is on the member declaration,
203
- // but `Shop.Orders.Money.Format()` is a *namespace* path, not a member
204
- // chain. Both are `member_access_expression`, and telling them apart needs
205
- // the resolver, so the whole written path is handed over and the resolver
206
- // tries it as a qualified name first.
179
+ // `this._repository.FindById()` (type on the member decl) vs.
180
+ // `Shop.Orders.Money.Format()` (a namespace path) are both this node
181
+ // type — telling them apart needs the resolver, so the whole written
182
+ // path is handed over and tried as a qualified name first.
207
183
  const object = describeReceiver(node.childForFieldName("expression"));
208
184
  const member = node.childForFieldName("name");
209
185
  if (member === null)
@@ -257,15 +233,10 @@ function callSignature(node) {
257
233
  return undefined;
258
234
  }
259
235
  /**
260
- * The first argument of an invocation, only when it is a bare string literal.
261
- *
262
- * Mirrors Java's `firstStringArgumentOf` exactly: `argument_list`'s first
263
- * named child is an `argument`, whose own first named child is the value —
264
- * `string_literal` when the call site wrote one, an `identifier` or anything
265
- * else otherwise. `"abc"` -> `abc`; a concatenation or interpolated string
266
- * (`$"..."`, `interpolated_string_expression`) returns `undefined` rather than
267
- * the fragment it can see, the same refusal-not-guess DEC-127 already applies
268
- * to Java's read of the identical shape.
236
+ * The first argument of an invocation, only when a bare string literal.
237
+ * Mirrors Java's `firstStringArgumentOf`: `"abc"` -> `abc`; a concatenation
238
+ * or interpolated string (`$"..."`) returns `undefined` rather than a
239
+ * fragment — DEC-127's refusal-not-guess, same as Java's identical shape.
269
240
  */
270
241
  function firstStringArgumentOf(invocation) {
271
242
  const args = invocation.childForFieldName("arguments");
@@ -339,10 +310,9 @@ function pushInvocation(scope, node) {
339
310
  ...(receiver.call === undefined ? {} : { receiverCall: receiver.call }),
340
311
  line: node.startPosition.row + 1,
341
312
  raw: node.text.slice(0, 200),
342
- // Spread rather than assigned — `exactOptionalPropertyTypes` distinguishes
343
- // absent from present-and-undefined, and the distinction is the point:
344
- // absent means "not a call worth reading further," present-and-undefined
345
- // would wrongly mean "a call whose first argument is nothing."
313
+ // Spread, not assigned: `exactOptionalPropertyTypes` distinguishes
314
+ // absent ("not worth reading further") from present-and-undefined
315
+ // ("a call whose first argument is nothing").
346
316
  ...(literal === undefined ? {} : { firstStringArgument: literal }),
347
317
  ...(argumentText === undefined ? {} : { firstArgumentText: argumentText }),
348
318
  });
@@ -360,13 +330,10 @@ function pushInvocation(scope, node) {
360
330
  });
361
331
  }
362
332
  /**
363
- * A `variable_declarator`'s own initialiser, whether or not the declaration's
364
- * type was written explicitly — `recordDeclarator` only needs this for `var`,
365
- * but a field's own inline initialiser (`private readonly HttpClient _client
366
- * = factory.CreateClient();`) matters for D-FIX-3's client-base extractor
367
- * (DEC-164) even when the field's type is written explicitly, so this is a
368
- * standalone reader rather than folded into `recordDeclarator`'s own `var`
369
- * branch.
333
+ * A `variable_declarator`'s initialiser, whether or not its type was written
334
+ * explicitly. `recordDeclarator` only needs this for `var`, but a field's
335
+ * inline initialiser matters to the client-base extractor (DEC-164) even
336
+ * with an explicit type, hence a standalone reader.
370
337
  */
371
338
  function initialiserOf(declarator) {
372
339
  let initialiser;
@@ -454,12 +421,11 @@ function walkBody(node, scope) {
454
421
  pushInvocation(scope, current);
455
422
  break;
456
423
  case "assignment_expression": {
457
- // `Client = factory.CreateClient(...)` and `this.Client = ...` — only
458
- // D-FIX-3's client-base extractor (DEC-164) reads this, and only from
459
- // a `.ctor`'s own scope (extract.ts's choice, not this reader's). The
460
- // invocation itself is walked normally regardless (it is still a
461
- // child of this node) and produces its own `CsRef`; this case exists
462
- // purely to remember *which name the result was bound to*.
424
+ // `Client = factory.CreateClient(...)` / `this.Client = ...`: only
425
+ // the client-base extractor (DEC-164) reads this, only from a
426
+ // `.ctor`'s scope. The invocation is walked normally regardless and
427
+ // produces its own `CsRef`; this exists only to remember which name
428
+ // the result was bound to.
463
429
  const left = current.childForFieldName("left");
464
430
  const right = current.childForFieldName("right");
465
431
  if (left !== null && right !== null && right.type === "invocation_expression") {
@@ -493,12 +459,10 @@ function walkBody(node, scope) {
493
459
  break;
494
460
  }
495
461
  case "declaration_pattern": {
496
- // `if (item is Folder folder)` and `case Folder folder:` — a pattern
497
- // that BINDS a local whose type is written immediately before it. Every
498
- // call through that local was previously disclosed as an untyped
499
- // receiver, which was honest but wasteful: the type is right there.
500
- // jellyfin's `MetadataService.GetChildrenForMetadataUpdates` is the
501
- // canonical shape, and it is idiomatic modern C# rather than a corner.
462
+ // `if (item is Folder folder)` / `case Folder folder:` binds a local
463
+ // whose type is written right there — previously disclosed as an
464
+ // untyped receiver, honest but wasteful. Idiomatic modern C#
465
+ // (jellyfin's `MetadataService.GetChildrenForMetadataUpdates`), not a corner.
502
466
  const declared = typeName(current.namedChild(0));
503
467
  const bound = current.namedChild(1)?.text.trim();
504
468
  if (bound !== undefined)
@@ -531,10 +495,9 @@ function walkBody(node, scope) {
531
495
  break;
532
496
  }
533
497
  case "member_access_expression": {
534
- // `Status.Pending`, `Order.Empty` — a type referenced as a value, which
535
- // is golden pattern 13. Only recorded when the holder is a bare name;
536
- // the resolver decides whether that name is a type or a variable, and
537
- // declines when it is neither.
498
+ // `Status.Pending`, `Order.Empty` — a type referenced as a value
499
+ // (golden pattern 13). Recorded only when the holder is a bare name;
500
+ // the resolver decides type vs. variable, declining if neither.
538
501
  const holder = current.childForFieldName("expression");
539
502
  if (holder !== null && (holder.type === "identifier" || holder.type === "qualified_name")) {
540
503
  scope.refs.push({
@@ -748,10 +711,8 @@ export function readFile(root, file, hasError) {
748
711
  const field = declarator.childForFieldName("name")?.text.trim();
749
712
  if (field !== undefined)
750
713
  members.set(field, declared ?? null);
751
- // D-FIX-3's client-base extractor (DEC-164): a field's own
752
- // inline initialiser, when it is a traceable invocation.
753
- // `CleanArchitecture`'s `private readonly HttpClient _client =
754
- // factory.CreateClient();` is the measured shape.
714
+ // Client-base extractor (DEC-164): a field's inline initialiser
715
+ // when traceable — CleanArchitecture's measured shape.
755
716
  if (field !== undefined) {
756
717
  const initialiser = initialiserOf(declarator);
757
718
  if (initialiser?.type === "invocation_expression") {
@@ -812,9 +773,8 @@ export function readFile(root, file, hasError) {
812
773
  continue;
813
774
  }
814
775
  if (child.type === "file_scoped_namespace_declaration") {
815
- // `namespace Shop.Orders;` — no body. Everything after it in the file is
816
- // inside it, so the remaining siblings are walked with it in force. This
817
- // is the modern default and permits exactly one namespace per file.
776
+ // `namespace Shop.Orders;` — no body; remaining siblings are inside
777
+ // it. Modern default, permits exactly one namespace per file.
818
778
  const name = child.childForFieldName("name")?.text.trim();
819
779
  const nested = name === undefined ? enclosing : enclosing === "" ? name : `${enclosing}.${name}`;
820
780
  if (namespaceName === "" && nested !== "")
@@ -832,10 +792,9 @@ export function readFile(root, file, hasError) {
832
792
  return;
833
793
  }
834
794
  if (child.type === "namespace_declaration") {
835
- // Block form. A file may legally declare several, and this reader takes
836
- // the *first* — recorded as a known simplification rather than left as a
837
- // silent one. Types after a second `namespace` block would be given a
838
- // namespace they do not have.
795
+ // Block form. A file may legally declare several; this reader takes
796
+ // the first (disclosed simplification) — types after a second block
797
+ // would be given a namespace they don't have.
839
798
  const name = child.childForFieldName("name")?.text.trim();
840
799
  const nested = name === undefined ? enclosing : enclosing === "" ? name : `${enclosing}.${name}`;
841
800
  if (namespaceName === "" && nested !== "")