@descryy/adapter-csharp 0.5.0 → 0.5.2
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 +28 -7
- package/dist/adapter.js.map +1 -1
- package/dist/aspnetcore.d.ts +35 -0
- package/dist/aspnetcore.d.ts.map +1 -1
- package/dist/aspnetcore.js +186 -6
- package/dist/aspnetcore.js.map +1 -1
- package/dist/client.d.ts +18 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -1
- package/dist/dto.d.ts +5 -0
- package/dist/dto.d.ts.map +1 -1
- package/dist/dto.js +4 -2
- package/dist/dto.js.map +1 -1
- package/dist/external.d.ts +167 -0
- package/dist/external.d.ts.map +1 -0
- package/dist/external.js +262 -0
- package/dist/external.js.map +1 -0
- package/dist/extract.d.ts +27 -0
- package/dist/extract.d.ts.map +1 -1
- package/dist/extract.js +271 -8
- package/dist/extract.js.map +1 -1
- package/dist/json.d.ts +50 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +60 -0
- package/dist/json.js.map +1 -0
- package/dist/parse.d.ts +10 -0
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +21 -0
- package/dist/parse.js.map +1 -1
- package/dist/shape-reach.d.ts +22 -4
- package/dist/shape-reach.d.ts.map +1 -1
- package/dist/shape-reach.js +36 -5
- package/dist/shape-reach.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dependency boundary, C# side — and the narrowest of the ten by a wide
|
|
3
|
+
* margin, which is the finding rather than a shortfall against it.
|
|
4
|
+
*
|
|
5
|
+
* ## The measurement this module does not contest
|
|
6
|
+
*
|
|
7
|
+
* `lane-extmint6` filed
|
|
8
|
+
* `DEC-NEXT-csharp-cannot-attribute-a-dependency-boundary-from-source` after
|
|
9
|
+
* measuring two facts that are structural and remain true:
|
|
10
|
+
*
|
|
11
|
+
* **1. A `using` binds a namespace, not a name.** `using System.IO;` does not
|
|
12
|
+
* say `Path` is `System.IO.Path`; it says `System.IO` is one of eleven places a
|
|
13
|
+
* bare name may be found. That is `adapter-java`'s wildcard import and
|
|
14
|
+
* `adapter-python`'s `from x import *`, and in C# it is not a minority idiom —
|
|
15
|
+
* it is the only idiom. Counted: `jellyfin` 13,435 plain usings, `eShopOnWeb`
|
|
16
|
+
* 884. Every one of them is refused here, and that refusal is the module's
|
|
17
|
+
* largest single behaviour.
|
|
18
|
+
*
|
|
19
|
+
* **2. A dotted C# name cannot be split into namespace and symbol by
|
|
20
|
+
* convention.** Go splits on the import path, Java and Kotlin at the first
|
|
21
|
+
* capitalised segment, PHP at the last `\`. C# namespaces and type names are
|
|
22
|
+
* both PascalCase, so `System.Text.Json.JsonSerializer` offers nothing that says
|
|
23
|
+
* where the namespace stops.
|
|
24
|
+
*
|
|
25
|
+
* ## What is attributable anyway, and the one thing the prior measurement did
|
|
26
|
+
* not use
|
|
27
|
+
*
|
|
28
|
+
* Two written forms name a symbol rather than a namespace, and both are read:
|
|
29
|
+
*
|
|
30
|
+
* - **`using Alias = N.T;`** binds one name outright. The developer wrote the
|
|
31
|
+
* name, the target, and (by using the alias in type or static-call position)
|
|
32
|
+
* that the target is a type.
|
|
33
|
+
* - **a name written out in full at the reference** — `System.Text.Json.
|
|
34
|
+
* JsonSerializer.Serialize(x)`. Every segment is written by the developer at
|
|
35
|
+
* the site.
|
|
36
|
+
*
|
|
37
|
+
* Fact 2 blocks both, and the way past it is not a convention but **another
|
|
38
|
+
* written binding**: a plain `using N;` is the language's own guarantee that `N`
|
|
39
|
+
* is a namespace. So the repository's plain usings — the very population this
|
|
40
|
+
* module refuses to resolve *names* with — are read instead as a **dictionary of
|
|
41
|
+
* strings the source states are namespaces**, and a dotted target is split at
|
|
42
|
+
* the longest prefix that appears in it. `System.Text.Json` is a namespace
|
|
43
|
+
* because some file in this repository wrote `using System.Text.Json;`, not
|
|
44
|
+
* because three segments looked like enough. A target whose prefix no file
|
|
45
|
+
* writes down is refused, not guessed.
|
|
46
|
+
*
|
|
47
|
+
* This reads no `.csproj` `<PackageReference>`, no `packages.lock.json`, no
|
|
48
|
+
* `~/.nuget`, no assembly. Two reasons, Go's two: most checkouts have nothing
|
|
49
|
+
* restored, and an identity taken from a restored graph would move the first
|
|
50
|
+
* time somebody ran `dotnet restore`.
|
|
51
|
+
*
|
|
52
|
+
* ## `using static` is read as a namespace fact and never as a name binding
|
|
53
|
+
*
|
|
54
|
+
* `using static N.T;` is the other form the task named, and it is **refused for
|
|
55
|
+
* edges on purpose.** Unlike Java's `import static a.b.C.m`, C#'s form names no
|
|
56
|
+
* member: it imports *every* static member of `T`, so an unqualified `m()` under
|
|
57
|
+
* it is a member of the enclosing type, or of an unread base type, or one of
|
|
58
|
+
* `T`'s — and the file writes down nothing that chooses. That is fact 1 again in
|
|
59
|
+
* a smaller population. What the directive does write down is that `N` is a
|
|
60
|
+
* namespace-or-type and `T` a type, so its prefix joins the namespace dictionary
|
|
61
|
+
* and nothing else.
|
|
62
|
+
*
|
|
63
|
+
* ## What this is worth, measured
|
|
64
|
+
*
|
|
65
|
+
* Counted over the C# reference subjects, and the honest headline is that the
|
|
66
|
+
* attributable population is tiny **and mostly in-repo**:
|
|
67
|
+
*
|
|
68
|
+
* | subject | plain `using` | `using static` | alias `using` | of those, target OUTSIDE the repo |
|
|
69
|
+
* | --- | --- | --- | --- | --- |
|
|
70
|
+
* | `jellyfin` | 13,435 | 9 | 125 | **11** |
|
|
71
|
+
* | `eShopOnWeb` | 884 | 0 | 0 | **0** |
|
|
72
|
+
*
|
|
73
|
+
* `jellyfin`'s 125 aliases are overwhelmingly `Episode = MediaBrowser.
|
|
74
|
+
* Controller.Entities.TV.Episode` — a shortening of its own name, not a
|
|
75
|
+
* dependency. Eleven name something outside, over six distinct targets. So this
|
|
76
|
+
* module's yield on `jellyfin` is a two-digit number of edges against a graded
|
|
77
|
+
* population of 74,383 calls, and on `eShopOnWeb` it is zero. **That is the
|
|
78
|
+
* result, reported rather than improved by lowering the bar**, and it is what
|
|
79
|
+
* the prior lane predicted.
|
|
80
|
+
*/
|
|
81
|
+
/** What written form bound the name. */
|
|
82
|
+
export type CsBinding = "alias-using" | "written-fully-qualified";
|
|
83
|
+
export interface ExternalContext {
|
|
84
|
+
/**
|
|
85
|
+
* Alias -> target, for one file: its own `using X = N.T;` plus the assembly's
|
|
86
|
+
* `global using X = N.T;`. The one C# directive that binds a name.
|
|
87
|
+
*/
|
|
88
|
+
readonly aliases: ReadonlyMap<string, string>;
|
|
89
|
+
/**
|
|
90
|
+
* Every string this repository's own source states is a namespace: the target
|
|
91
|
+
* of every plain `using N;`, and every prefix of one, plus the prefixes of
|
|
92
|
+
* `using static` targets. Repository-wide on purpose — a namespace is a
|
|
93
|
+
* property of the string, not of the file that wrote it down.
|
|
94
|
+
*/
|
|
95
|
+
readonly writtenNamespaces: ReadonlySet<string>;
|
|
96
|
+
/** Namespaces this repository declares. A type under one is OURS whether or
|
|
97
|
+
* not this run read it — calling unanalysed code of ours a dependency is the
|
|
98
|
+
* error that never surfaces. */
|
|
99
|
+
readonly ownNamespaces: ReadonlySet<string>;
|
|
100
|
+
/** Fully-qualified names this run actually read. One of ours is not a
|
|
101
|
+
* boundary. */
|
|
102
|
+
readonly analysed: (fqn: string) => boolean;
|
|
103
|
+
}
|
|
104
|
+
export interface ExternalAttribution {
|
|
105
|
+
/** The namespace **as the repository's own source writes it down** — this is
|
|
106
|
+
* the identity. Never a NuGet package id, never an assembly, never a version:
|
|
107
|
+
* a package-to-namespace mapping lives inside the assembly, and
|
|
108
|
+
* `<PackageReference>` binds an id to no namespace at all. */
|
|
109
|
+
readonly moduleOrNamespace: string;
|
|
110
|
+
/** The type chain, then any member named on it. */
|
|
111
|
+
readonly symbolPath: readonly string[];
|
|
112
|
+
readonly binding: CsBinding;
|
|
113
|
+
/** Outside the .NET base class library, decided from the namespace alone
|
|
114
|
+
* against `PLATFORM_BASIS`. Disclosure only, and outside the hash: a
|
|
115
|
+
* namespace that moved between the two would otherwise change identity with
|
|
116
|
+
* no line of source changing. */
|
|
117
|
+
readonly thirdParty: boolean;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Provenance of the platform-namespace list, carried on every attributed node.
|
|
121
|
+
* A property of the framework, frozen into this source — never read from
|
|
122
|
+
* whatever SDK a developer happens to have installed, which would make the
|
|
123
|
+
* answer depend on the machine.
|
|
124
|
+
*
|
|
125
|
+
* `Microsoft` is **not** taken whole, and that is the whole reason this constant
|
|
126
|
+
* is a list rather than two prefixes: `Microsoft.Extensions.*` and
|
|
127
|
+
* `Microsoft.AspNetCore.*` ship as NuGet packages, `Microsoft.Win32` and
|
|
128
|
+
* `Microsoft.CSharp` ship with the runtime. Taking the prefix either way would
|
|
129
|
+
* be a wrong disclosure on every node under it.
|
|
130
|
+
*/
|
|
131
|
+
export declare const PLATFORM_BASIS = "dotnet base class library: System.* roots, plus the runtime's own Microsoft.* namespaces";
|
|
132
|
+
/** Is `name` the namespace `prefix`, or inside it? Whole segments only — a raw
|
|
133
|
+
* `startsWith` would put `Acme.ServiceBus` inside `Acme.Service`, which is the
|
|
134
|
+
* vendor-namespace hazard rule 2 prices above a missing edge. */
|
|
135
|
+
export declare function isUnder(name: string, prefix: string): boolean;
|
|
136
|
+
/** Generic arguments, nullable marks, array brackets and `global::` are not part
|
|
137
|
+
* of a name's identity, and the type arguments inside them are separate
|
|
138
|
+
* references the extractor already files on their own. */
|
|
139
|
+
export declare function bareTypeName(written: string): string;
|
|
140
|
+
/**
|
|
141
|
+
* A dotted name split into the namespace the repository states it is in and the
|
|
142
|
+
* symbol chain inside it, or `null` when no plain `using` in this repository
|
|
143
|
+
* writes a namespace that prefixes it.
|
|
144
|
+
*
|
|
145
|
+
* The **longest** written prefix wins, and it must be a proper prefix: a name
|
|
146
|
+
* that is itself a written namespace names no symbol and is refused.
|
|
147
|
+
*/
|
|
148
|
+
export declare function splitAtWrittenNamespace(fqn: string, writtenNamespaces: ReadonlySet<string>): {
|
|
149
|
+
namespace: string;
|
|
150
|
+
symbols: string[];
|
|
151
|
+
} | null;
|
|
152
|
+
/**
|
|
153
|
+
* The namespace and type behind a **type reference** that left the repository,
|
|
154
|
+
* or `null` when no binding the developer wrote settles it.
|
|
155
|
+
*/
|
|
156
|
+
export declare function attributeExternalType(written: string, context: ExternalContext): ExternalAttribution | null;
|
|
157
|
+
/**
|
|
158
|
+
* The namespace, type and member behind a **call** that left the repository, or
|
|
159
|
+
* `null` when no binding the developer wrote settles it.
|
|
160
|
+
*
|
|
161
|
+
* `receiverWritten` is the receiver exactly as the source wrote it — an alias, or
|
|
162
|
+
* a dotted path written out in full. A local, a field, a property or a `var` is
|
|
163
|
+
* not a written type and `extract.ts` never reaches here with one, because it
|
|
164
|
+
* consults this module only where its own resolution already declined.
|
|
165
|
+
*/
|
|
166
|
+
export declare function attributeExternalCall(receiverWritten: string | undefined, method: string, context: ExternalContext): ExternalAttribution | null;
|
|
167
|
+
//# sourceMappingURL=external.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external.d.ts","sourceRoot":"","sources":["../src/external.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AAEH,wCAAwC;AACxC,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,yBAAyB,CAAC;AAElE,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChD;;qCAEiC;IACjC,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5C;oBACgB;IAChB,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CAC7C;AAED,MAAM,WAAW,mBAAmB;IAClC;;;mEAG+D;IAC/D,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,mDAAmD;IACnD,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B;;;sCAGkC;IAClC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,6FAA6F,CAAC;AA0BzH;;kEAEkE;AAClE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7D;AAYD;;2DAE2D;AAC3D,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,GACrC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAUjD;AA+ED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,eAAe,GACvB,mBAAmB,GAAG,IAAI,CAI5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,GACvB,mBAAmB,GAAG,IAAI,CAK5B"}
|
package/dist/external.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dependency boundary, C# side — and the narrowest of the ten by a wide
|
|
3
|
+
* margin, which is the finding rather than a shortfall against it.
|
|
4
|
+
*
|
|
5
|
+
* ## The measurement this module does not contest
|
|
6
|
+
*
|
|
7
|
+
* `lane-extmint6` filed
|
|
8
|
+
* `DEC-NEXT-csharp-cannot-attribute-a-dependency-boundary-from-source` after
|
|
9
|
+
* measuring two facts that are structural and remain true:
|
|
10
|
+
*
|
|
11
|
+
* **1. A `using` binds a namespace, not a name.** `using System.IO;` does not
|
|
12
|
+
* say `Path` is `System.IO.Path`; it says `System.IO` is one of eleven places a
|
|
13
|
+
* bare name may be found. That is `adapter-java`'s wildcard import and
|
|
14
|
+
* `adapter-python`'s `from x import *`, and in C# it is not a minority idiom —
|
|
15
|
+
* it is the only idiom. Counted: `jellyfin` 13,435 plain usings, `eShopOnWeb`
|
|
16
|
+
* 884. Every one of them is refused here, and that refusal is the module's
|
|
17
|
+
* largest single behaviour.
|
|
18
|
+
*
|
|
19
|
+
* **2. A dotted C# name cannot be split into namespace and symbol by
|
|
20
|
+
* convention.** Go splits on the import path, Java and Kotlin at the first
|
|
21
|
+
* capitalised segment, PHP at the last `\`. C# namespaces and type names are
|
|
22
|
+
* both PascalCase, so `System.Text.Json.JsonSerializer` offers nothing that says
|
|
23
|
+
* where the namespace stops.
|
|
24
|
+
*
|
|
25
|
+
* ## What is attributable anyway, and the one thing the prior measurement did
|
|
26
|
+
* not use
|
|
27
|
+
*
|
|
28
|
+
* Two written forms name a symbol rather than a namespace, and both are read:
|
|
29
|
+
*
|
|
30
|
+
* - **`using Alias = N.T;`** binds one name outright. The developer wrote the
|
|
31
|
+
* name, the target, and (by using the alias in type or static-call position)
|
|
32
|
+
* that the target is a type.
|
|
33
|
+
* - **a name written out in full at the reference** — `System.Text.Json.
|
|
34
|
+
* JsonSerializer.Serialize(x)`. Every segment is written by the developer at
|
|
35
|
+
* the site.
|
|
36
|
+
*
|
|
37
|
+
* Fact 2 blocks both, and the way past it is not a convention but **another
|
|
38
|
+
* written binding**: a plain `using N;` is the language's own guarantee that `N`
|
|
39
|
+
* is a namespace. So the repository's plain usings — the very population this
|
|
40
|
+
* module refuses to resolve *names* with — are read instead as a **dictionary of
|
|
41
|
+
* strings the source states are namespaces**, and a dotted target is split at
|
|
42
|
+
* the longest prefix that appears in it. `System.Text.Json` is a namespace
|
|
43
|
+
* because some file in this repository wrote `using System.Text.Json;`, not
|
|
44
|
+
* because three segments looked like enough. A target whose prefix no file
|
|
45
|
+
* writes down is refused, not guessed.
|
|
46
|
+
*
|
|
47
|
+
* This reads no `.csproj` `<PackageReference>`, no `packages.lock.json`, no
|
|
48
|
+
* `~/.nuget`, no assembly. Two reasons, Go's two: most checkouts have nothing
|
|
49
|
+
* restored, and an identity taken from a restored graph would move the first
|
|
50
|
+
* time somebody ran `dotnet restore`.
|
|
51
|
+
*
|
|
52
|
+
* ## `using static` is read as a namespace fact and never as a name binding
|
|
53
|
+
*
|
|
54
|
+
* `using static N.T;` is the other form the task named, and it is **refused for
|
|
55
|
+
* edges on purpose.** Unlike Java's `import static a.b.C.m`, C#'s form names no
|
|
56
|
+
* member: it imports *every* static member of `T`, so an unqualified `m()` under
|
|
57
|
+
* it is a member of the enclosing type, or of an unread base type, or one of
|
|
58
|
+
* `T`'s — and the file writes down nothing that chooses. That is fact 1 again in
|
|
59
|
+
* a smaller population. What the directive does write down is that `N` is a
|
|
60
|
+
* namespace-or-type and `T` a type, so its prefix joins the namespace dictionary
|
|
61
|
+
* and nothing else.
|
|
62
|
+
*
|
|
63
|
+
* ## What this is worth, measured
|
|
64
|
+
*
|
|
65
|
+
* Counted over the C# reference subjects, and the honest headline is that the
|
|
66
|
+
* attributable population is tiny **and mostly in-repo**:
|
|
67
|
+
*
|
|
68
|
+
* | subject | plain `using` | `using static` | alias `using` | of those, target OUTSIDE the repo |
|
|
69
|
+
* | --- | --- | --- | --- | --- |
|
|
70
|
+
* | `jellyfin` | 13,435 | 9 | 125 | **11** |
|
|
71
|
+
* | `eShopOnWeb` | 884 | 0 | 0 | **0** |
|
|
72
|
+
*
|
|
73
|
+
* `jellyfin`'s 125 aliases are overwhelmingly `Episode = MediaBrowser.
|
|
74
|
+
* Controller.Entities.TV.Episode` — a shortening of its own name, not a
|
|
75
|
+
* dependency. Eleven name something outside, over six distinct targets. So this
|
|
76
|
+
* module's yield on `jellyfin` is a two-digit number of edges against a graded
|
|
77
|
+
* population of 74,383 calls, and on `eShopOnWeb` it is zero. **That is the
|
|
78
|
+
* result, reported rather than improved by lowering the bar**, and it is what
|
|
79
|
+
* the prior lane predicted.
|
|
80
|
+
*/
|
|
81
|
+
/**
|
|
82
|
+
* Provenance of the platform-namespace list, carried on every attributed node.
|
|
83
|
+
* A property of the framework, frozen into this source — never read from
|
|
84
|
+
* whatever SDK a developer happens to have installed, which would make the
|
|
85
|
+
* answer depend on the machine.
|
|
86
|
+
*
|
|
87
|
+
* `Microsoft` is **not** taken whole, and that is the whole reason this constant
|
|
88
|
+
* is a list rather than two prefixes: `Microsoft.Extensions.*` and
|
|
89
|
+
* `Microsoft.AspNetCore.*` ship as NuGet packages, `Microsoft.Win32` and
|
|
90
|
+
* `Microsoft.CSharp` ship with the runtime. Taking the prefix either way would
|
|
91
|
+
* be a wrong disclosure on every node under it.
|
|
92
|
+
*/
|
|
93
|
+
export const PLATFORM_BASIS = "dotnet base class library: System.* roots, plus the runtime's own Microsoft.* namespaces";
|
|
94
|
+
/** Namespace roots the runtime owns outright. */
|
|
95
|
+
const PLATFORM_ROOTS = ["System"];
|
|
96
|
+
/** The `Microsoft` subnamespaces the runtime ships. Everything else under
|
|
97
|
+
* `Microsoft` is a package. */
|
|
98
|
+
const PLATFORM_MICROSOFT = new Set([
|
|
99
|
+
"Microsoft.Win32", "Microsoft.CSharp", "Microsoft.VisualBasic", "Microsoft.SafeHandles",
|
|
100
|
+
]);
|
|
101
|
+
/**
|
|
102
|
+
* Namespaces whose whole purpose is to make a call target dynamic.
|
|
103
|
+
*
|
|
104
|
+
* `System.Reflection`'s `MethodInfo.Invoke` and `System.Linq.Expressions`'
|
|
105
|
+
* compiled delegates are where a C# call graph deliberately stops being
|
|
106
|
+
* readable, and golden pattern 12 — the corpus's most important fixture —
|
|
107
|
+
* forbids a `CALLS` edge out of a method that dispatches through them *to any
|
|
108
|
+
* target at any resolution*. The edge would be true and it is still the one
|
|
109
|
+
* edge that pattern exists to forbid: it makes a traversal look as though it
|
|
110
|
+
* continued through a site where the graph cannot see the next hop. Java's
|
|
111
|
+
* `external.ts` declines `java.lang.reflect` and `java.lang.invoke` for exactly
|
|
112
|
+
* this reason (`DEC-NEXT-external-nodes-through-the-reflection-packages`).
|
|
113
|
+
*/
|
|
114
|
+
const DYNAMIC_DISPATCH_NAMESPACES = ["System.Reflection", "System.Linq.Expressions"];
|
|
115
|
+
/** Is `name` the namespace `prefix`, or inside it? Whole segments only — a raw
|
|
116
|
+
* `startsWith` would put `Acme.ServiceBus` inside `Acme.Service`, which is the
|
|
117
|
+
* vendor-namespace hazard rule 2 prices above a missing edge. */
|
|
118
|
+
export function isUnder(name, prefix) {
|
|
119
|
+
return name === prefix || name.startsWith(`${prefix}.`);
|
|
120
|
+
}
|
|
121
|
+
function isPlatform(namespace) {
|
|
122
|
+
for (const root of PLATFORM_ROOTS) {
|
|
123
|
+
if (isUnder(namespace, root))
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
for (const known of PLATFORM_MICROSOFT) {
|
|
127
|
+
if (isUnder(namespace, known))
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
/** Generic arguments, nullable marks, array brackets and `global::` are not part
|
|
133
|
+
* of a name's identity, and the type arguments inside them are separate
|
|
134
|
+
* references the extractor already files on their own. */
|
|
135
|
+
export function bareTypeName(written) {
|
|
136
|
+
const stripped = written.trim().replace(/^global::/, "");
|
|
137
|
+
const cut = stripped.indexOf("<");
|
|
138
|
+
const head = (cut === -1 ? stripped : stripped.slice(0, cut)).trim();
|
|
139
|
+
return head.replace(/(\[[\s,]*\])+$/, "").replace(/\?+$/, "").trim();
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* A dotted name split into the namespace the repository states it is in and the
|
|
143
|
+
* symbol chain inside it, or `null` when no plain `using` in this repository
|
|
144
|
+
* writes a namespace that prefixes it.
|
|
145
|
+
*
|
|
146
|
+
* The **longest** written prefix wins, and it must be a proper prefix: a name
|
|
147
|
+
* that is itself a written namespace names no symbol and is refused.
|
|
148
|
+
*/
|
|
149
|
+
export function splitAtWrittenNamespace(fqn, writtenNamespaces) {
|
|
150
|
+
const parts = fqn.split(".");
|
|
151
|
+
if (parts.length < 2 || parts.some((part) => part === ""))
|
|
152
|
+
return null;
|
|
153
|
+
for (let cut = parts.length - 1; cut >= 1; cut -= 1) {
|
|
154
|
+
const prefix = parts.slice(0, cut).join(".");
|
|
155
|
+
if (writtenNamespaces.has(prefix)) {
|
|
156
|
+
return { namespace: prefix, symbols: parts.slice(cut) };
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
/** Ours, whether or not this run read it. */
|
|
162
|
+
function isOurs(fqn, context) {
|
|
163
|
+
if (context.analysed(fqn))
|
|
164
|
+
return true;
|
|
165
|
+
for (const own of context.ownNamespaces) {
|
|
166
|
+
if (own !== "" && isUnder(fqn, own))
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
function attribute(fqn, binding, extra, context) {
|
|
172
|
+
if (isOurs(fqn, context))
|
|
173
|
+
return null;
|
|
174
|
+
// The whole written name is itself a namespace some file states is one. A
|
|
175
|
+
// namespace declares no members, so there is nothing here to point at.
|
|
176
|
+
if (context.writtenNamespaces.has(fqn))
|
|
177
|
+
return null;
|
|
178
|
+
const split = splitAtWrittenNamespace(fqn, context.writtenNamespaces);
|
|
179
|
+
if (split === null)
|
|
180
|
+
return null;
|
|
181
|
+
if (isOurs(split.namespace, context))
|
|
182
|
+
return null;
|
|
183
|
+
// The written namespace must be the type's IMMEDIATE parent, and this is an
|
|
184
|
+
// identity rule rather than a taste one. `Microsoft.AspNetCore.WebUtilities.
|
|
185
|
+
// QueryHelpers.AddQueryString` splits at `Microsoft.AspNetCore` when no file
|
|
186
|
+
// happens to write `using Microsoft.AspNetCore.WebUtilities;` and at the
|
|
187
|
+
// deeper namespace when one does — so the same symbol would carry two
|
|
188
|
+
// different node ids depending on a `using` in an unrelated file, and adding
|
|
189
|
+
// that line would silently move the node. Capping the split at one segment
|
|
190
|
+
// turns that churn into presence or absence, which is what rule 2 asks for: a
|
|
191
|
+
// missing edge is a disclosed gap, a moving identity destroys every link that
|
|
192
|
+
// ever pointed at it. The cost is real and disclosed — a nested type
|
|
193
|
+
// (`System.Text.Encoding.UTF8`, `Map.Entry`'s C# analogue) is refused.
|
|
194
|
+
if (split.symbols.length !== 1)
|
|
195
|
+
return null;
|
|
196
|
+
for (const dynamic of DYNAMIC_DISPATCH_NAMESPACES) {
|
|
197
|
+
if (isUnder(split.namespace, dynamic))
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
const symbolPath = [...split.symbols, ...extra];
|
|
201
|
+
if (symbolPath.some((part) => part === ""))
|
|
202
|
+
return null;
|
|
203
|
+
return {
|
|
204
|
+
moduleOrNamespace: split.namespace,
|
|
205
|
+
symbolPath,
|
|
206
|
+
binding,
|
|
207
|
+
thirdParty: !isPlatform(split.namespace),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/** The fully-qualified name a written type resolves to through the bindings this
|
|
211
|
+
* file wrote, and which binding did it. `null` when none did. */
|
|
212
|
+
function qualify(written, context) {
|
|
213
|
+
const name = bareTypeName(written);
|
|
214
|
+
if (name === "")
|
|
215
|
+
return null;
|
|
216
|
+
const separator = name.indexOf(".");
|
|
217
|
+
const head = separator === -1 ? name : name.slice(0, separator);
|
|
218
|
+
const aliased = context.aliases.get(head);
|
|
219
|
+
if (aliased !== undefined && aliased !== "") {
|
|
220
|
+
const rest = separator === -1 ? "" : name.slice(separator + 1);
|
|
221
|
+
const target = bareTypeName(aliased);
|
|
222
|
+
return { fqn: rest === "" ? target : `${target}.${rest}`, binding: "alias-using" };
|
|
223
|
+
}
|
|
224
|
+
// Written out in full at the reference. Every segment is the developer's, so
|
|
225
|
+
// it is as much a written binding as an alias is — and the namespace boundary
|
|
226
|
+
// inside it is decided by `splitAtWrittenNamespace`, from plain usings, never
|
|
227
|
+
// by how the segments are capitalised.
|
|
228
|
+
if (separator !== -1)
|
|
229
|
+
return { fqn: name, binding: "written-fully-qualified" };
|
|
230
|
+
// A bare name under a plain `using`. The largest population and the refusal
|
|
231
|
+
// this module exists to make: eleven candidate namespaces and nothing written
|
|
232
|
+
// that chooses between them.
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* The namespace and type behind a **type reference** that left the repository,
|
|
237
|
+
* or `null` when no binding the developer wrote settles it.
|
|
238
|
+
*/
|
|
239
|
+
export function attributeExternalType(written, context) {
|
|
240
|
+
const qualified = qualify(written, context);
|
|
241
|
+
if (qualified === null)
|
|
242
|
+
return null;
|
|
243
|
+
return attribute(qualified.fqn, qualified.binding, [], context);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* The namespace, type and member behind a **call** that left the repository, or
|
|
247
|
+
* `null` when no binding the developer wrote settles it.
|
|
248
|
+
*
|
|
249
|
+
* `receiverWritten` is the receiver exactly as the source wrote it — an alias, or
|
|
250
|
+
* a dotted path written out in full. A local, a field, a property or a `var` is
|
|
251
|
+
* not a written type and `extract.ts` never reaches here with one, because it
|
|
252
|
+
* consults this module only where its own resolution already declined.
|
|
253
|
+
*/
|
|
254
|
+
export function attributeExternalCall(receiverWritten, method, context) {
|
|
255
|
+
if (receiverWritten === undefined || method === "")
|
|
256
|
+
return null;
|
|
257
|
+
const qualified = qualify(receiverWritten, context);
|
|
258
|
+
if (qualified === null)
|
|
259
|
+
return null;
|
|
260
|
+
return attribute(qualified.fqn, qualified.binding, [method], context);
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=external.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external.js","sourceRoot":"","sources":["../src/external.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AA2CH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,0FAA0F,CAAC;AAEzH,iDAAiD;AACjD,MAAM,cAAc,GAAsB,CAAC,QAAQ,CAAC,CAAC;AAErD;gCACgC;AAChC,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;IACtD,iBAAiB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,uBAAuB;CACxF,CAAC,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,2BAA2B,GAAsB,CAAC,mBAAmB,EAAE,yBAAyB,CAAC,CAAC;AAExG;;kEAEkE;AAClE,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,MAAc;IAClD,OAAO,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,UAAU,CAAC,SAAiB;IACnC,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QAClC,IAAI,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IAC5C,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,kBAAkB,EAAE,CAAC;QACvC,IAAI,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IAC7C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;2DAE2D;AAC3D,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACvE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CACrC,GAAW,EACX,iBAAsC;IAEtC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACvE,KAAK,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,IAAI,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6CAA6C;AAC7C,SAAS,MAAM,CAAC,GAAW,EAAE,OAAwB;IACnD,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QACxC,IAAI,GAAG,KAAK,EAAE,IAAI,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IACnD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS,CAChB,GAAW,EACX,OAAkB,EAClB,KAAwB,EACxB,OAAwB;IAExB,IAAI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,0EAA0E;IAC1E,uEAAuE;IACvE,IAAI,OAAO,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,MAAM,KAAK,GAAG,uBAAuB,CAAC,GAAG,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACtE,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,4EAA4E;IAC5E,6EAA6E;IAC7E,6EAA6E;IAC7E,yEAAyE;IACzE,sEAAsE;IACtE,6EAA6E;IAC7E,2EAA2E;IAC3E,8EAA8E;IAC9E,8EAA8E;IAC9E,qEAAqE;IACrE,uEAAuE;IACvE,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,KAAK,MAAM,OAAO,IAAI,2BAA2B,EAAE,CAAC;QAClD,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;IACrD,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC;IAChD,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,OAAO;QACL,iBAAiB,EAAE,KAAK,CAAC,SAAS;QAClC,UAAU;QACV,OAAO;QACP,UAAU,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;KACzC,CAAC;AACJ,CAAC;AAED;kEACkE;AAClE,SAAS,OAAO,CACd,OAAe,EACf,OAAwB;IAExB,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAE7B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,EAAE,GAAG,EAAE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IACrF,CAAC;IAED,6EAA6E;IAC7E,8EAA8E;IAC9E,8EAA8E;IAC9E,uCAAuC;IACvC,IAAI,SAAS,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC;IAE/E,4EAA4E;IAC5E,8EAA8E;IAC9E,6BAA6B;IAC7B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,OAAwB;IAExB,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,eAAmC,EACnC,MAAc,EACd,OAAwB;IAExB,IAAI,eAAe,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAChE,MAAM,SAAS,GAAG,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IACpD,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;AACxE,CAAC"}
|
package/dist/extract.d.ts
CHANGED
|
@@ -64,5 +64,32 @@ export interface Extraction {
|
|
|
64
64
|
readonly edges: readonly IREdge[];
|
|
65
65
|
readonly unresolved: readonly UnresolvedRef[];
|
|
66
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* The fallback graph when `extract()` throws mid-run, per
|
|
69
|
+
* `DEC-NEXT-degraded-graph-shape-for-adapters-without-one.md`.
|
|
70
|
+
*
|
|
71
|
+
* `FILE`, not `MODULE`: a C# module's identity here is
|
|
72
|
+
* `assembly::namespace::stem`, and both the assembly (`.csproj` resolution,
|
|
73
|
+
* `projects.ts`) and the namespace (`namespace Foo.Bar;`, a declaration
|
|
74
|
+
* *inside* the file) are exactly the machinery a mid-extraction throw means
|
|
75
|
+
* just failed or cannot be trusted to have finished. Unlike Go's import path
|
|
76
|
+
* or Rust's crate/module path — both resolved from the file's own location
|
|
77
|
+
* plus a manifest, never from the file's parsed content — nothing about a C#
|
|
78
|
+
* file's identity is recoverable without a successful parse. `FILE` (via the
|
|
79
|
+
* shared `@descryy/adapter-common#fileNode` helper) is the fact that
|
|
80
|
+
* survives: the file exists, on disk, at this path, and that is all this
|
|
81
|
+
* function claims.
|
|
82
|
+
*
|
|
83
|
+
* One disclosure row, not one per file — the fact is about the run. Anchored
|
|
84
|
+
* to the first file's `FILE` node because the ledger requires a `fromNodeId`
|
|
85
|
+
* and `FILE` is the only node type this path emits.
|
|
86
|
+
*/
|
|
87
|
+
export declare function degradedGraph(input: {
|
|
88
|
+
readonly repo: string;
|
|
89
|
+
readonly workspace: string | undefined;
|
|
90
|
+
readonly producedBy: string;
|
|
91
|
+
readonly files: readonly string[];
|
|
92
|
+
readonly cause: string;
|
|
93
|
+
}): Extraction;
|
|
67
94
|
export declare function extract(input: ExtractInput): Extraction;
|
|
68
95
|
//# sourceMappingURL=extract.d.ts.map
|
package/dist/extract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAQL,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAIrB,OAAO,KAAK,EAAE,MAAM,EAAwD,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAyB,KAAK,QAAQ,EAAgB,MAAM,aAAa,CAAC;AAKjF,OAAO,EAAuC,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAW7F,eAAO,MAAM,QAAQ,WAAW,CAAC;AA+DjC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C;;;;;;;;OAQG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,eAAe,CAAC;IAC/D;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;CAC/C;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,GAAG,UAAU,CA0Bb;AAiCD,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,UAAU,CA22CvD"}
|