@typespec/emitter-framework 0.15.0-dev.1 → 0.15.0-dev.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/src/core/index.d.ts +2 -0
- package/dist/src/core/index.d.ts.map +1 -1
- package/dist/src/core/index.js +2 -0
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/core/scc-set.d.ts +59 -0
- package/dist/src/core/scc-set.d.ts.map +1 -0
- package/dist/src/core/scc-set.js +633 -0
- package/dist/src/core/scc-set.js.map +1 -0
- package/dist/src/core/scc-set.test.d.ts +2 -0
- package/dist/src/core/scc-set.test.d.ts.map +1 -0
- package/dist/src/core/scc-set.test.js +192 -0
- package/dist/src/core/scc-set.test.js.map +1 -0
- package/dist/src/core/type-connector.d.ts +8 -0
- package/dist/src/core/type-connector.d.ts.map +1 -0
- package/dist/src/core/type-connector.js +63 -0
- package/dist/src/core/type-connector.js.map +1 -0
- package/package.json +3 -3
- package/package.json.bak +3 -3
- package/src/core/index.ts +2 -0
- package/src/core/scc-set.test.ts +293 -0
- package/src/core/scc-set.ts +777 -0
- package/src/core/type-connector.ts +67 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { Tester } from "#test/test-host.js";
|
|
2
|
+
import { computed } from "@alloy-js/core";
|
|
3
|
+
import { t } from "@typespec/compiler/testing";
|
|
4
|
+
import { describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { SCCSet } from "./scc-set.js";
|
|
6
|
+
import { typeDependencyConnector } from "./type-connector.js";
|
|
7
|
+
describe("SCCSet", () => {
|
|
8
|
+
it("topologically orders items", () => {
|
|
9
|
+
const edges = new Map([["model", ["serializer"]], ["serializer", ["helpers"]], ["helpers", []]]);
|
|
10
|
+
const set = new SCCSet(item => edges.get(item) ?? []);
|
|
11
|
+
set.add("model");
|
|
12
|
+
set.add("serializer");
|
|
13
|
+
set.add("helpers");
|
|
14
|
+
expect([...set.items]).toEqual(["helpers", "serializer", "model"]);
|
|
15
|
+
expect(componentValues(set)).toEqual(["helpers", "serializer", "model"]);
|
|
16
|
+
});
|
|
17
|
+
it("groups strongly connected components", () => {
|
|
18
|
+
const edges = new Map([["a", ["b"]], ["b", ["a", "c"]], ["c", []]]);
|
|
19
|
+
const set = new SCCSet(item => edges.get(item) ?? []);
|
|
20
|
+
set.add("a");
|
|
21
|
+
set.add("b");
|
|
22
|
+
set.add("c");
|
|
23
|
+
expect(componentValues(set)).toEqual(["c", ["a", "b"]]);
|
|
24
|
+
expect(set.items).toEqual(["c", "a", "b"]);
|
|
25
|
+
});
|
|
26
|
+
it("defers placeholders until added", () => {
|
|
27
|
+
const edges = new Map([["root", ["child"]], ["child", []]]);
|
|
28
|
+
const set = new SCCSet(item => edges.get(item) ?? []);
|
|
29
|
+
set.add("root");
|
|
30
|
+
expect(set.items).toEqual(["root"]);
|
|
31
|
+
expect(componentValues(set)).toEqual(["root"]);
|
|
32
|
+
set.add("child");
|
|
33
|
+
expect(set.items).toEqual(["child", "root"]);
|
|
34
|
+
expect(componentValues(set)).toEqual(["child", "root"]);
|
|
35
|
+
});
|
|
36
|
+
it("surfaces reachable nodes when requested", () => {
|
|
37
|
+
const edges = new Map([["root", ["child"]], ["child", ["leaf"]], ["leaf", []]]);
|
|
38
|
+
const set = new SCCSet(item => edges.get(item) ?? [], {
|
|
39
|
+
includeReachable: true
|
|
40
|
+
});
|
|
41
|
+
set.add("root");
|
|
42
|
+
expect(set.items).toEqual(["leaf", "child", "root"]);
|
|
43
|
+
expect(componentValues(set)).toEqual(["leaf", "child", "root"]);
|
|
44
|
+
});
|
|
45
|
+
it("mutates arrays in place when adding", () => {
|
|
46
|
+
const edges = new Map([["only", []]]);
|
|
47
|
+
const connector = vi.fn(item => edges.get(item) ?? []);
|
|
48
|
+
const set = new SCCSet(connector);
|
|
49
|
+
set.add("only");
|
|
50
|
+
const firstItems = set.items;
|
|
51
|
+
const firstComponents = set.components;
|
|
52
|
+
expect(set.items).toBe(firstItems);
|
|
53
|
+
expect(set.components).toBe(firstComponents);
|
|
54
|
+
expect(connector).toHaveBeenCalledTimes(1);
|
|
55
|
+
set.add("late");
|
|
56
|
+
expect(connector).toHaveBeenCalledTimes(2);
|
|
57
|
+
expect(set.items).toBe(firstItems);
|
|
58
|
+
expect(set.components).toBe(firstComponents);
|
|
59
|
+
expect(firstItems).toEqual(["only", "late"]);
|
|
60
|
+
expect(componentValuesFrom(firstComponents)).toEqual(["only", "late"]);
|
|
61
|
+
});
|
|
62
|
+
it("notifies computed observers", () => {
|
|
63
|
+
const edges = new Map([["model", ["serializer"]], ["serializer", ["helpers"]], ["helpers", []], ["cycle-a", ["cycle-b"]], ["cycle-b", ["cycle-a"]]]);
|
|
64
|
+
const set = new SCCSet(item => edges.get(item) ?? []);
|
|
65
|
+
const observedItems = computed(() => [...set.items]);
|
|
66
|
+
const observedComponents = computed(() => componentValues(set));
|
|
67
|
+
const observedCycle = computed(() => {
|
|
68
|
+
const cycle = set.components.find(component => Array.isArray(component.value));
|
|
69
|
+
if (!cycle || !Array.isArray(cycle.value)) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
return [...cycle.value];
|
|
73
|
+
});
|
|
74
|
+
expect(observedItems.value).toEqual([]);
|
|
75
|
+
expect(observedComponents.value).toEqual([]);
|
|
76
|
+
expect(observedCycle.value).toEqual([]);
|
|
77
|
+
set.add("model");
|
|
78
|
+
expect(observedItems.value).toEqual(["model"]);
|
|
79
|
+
expect(observedComponents.value).toEqual(["model"]);
|
|
80
|
+
set.add("serializer");
|
|
81
|
+
expect(observedItems.value).toEqual(["serializer", "model"]);
|
|
82
|
+
expect(observedComponents.value).toEqual(["serializer", "model"]);
|
|
83
|
+
set.add("helpers");
|
|
84
|
+
expect(observedItems.value).toEqual(["helpers", "serializer", "model"]);
|
|
85
|
+
expect(observedComponents.value).toEqual(["helpers", "serializer", "model"]);
|
|
86
|
+
set.add("cycle-a");
|
|
87
|
+
expect(observedCycle.value).toEqual([]);
|
|
88
|
+
set.add("cycle-b");
|
|
89
|
+
expect(observedCycle.value).toEqual(["cycle-a", "cycle-b"]);
|
|
90
|
+
});
|
|
91
|
+
it("orders dependent nodes even when added out of order", () => {
|
|
92
|
+
const edges = new Map([["Leaf", []], ["Indexed", ["Record"]], ["Record", ["Leaf"]], ["Base", ["Leaf"]], ["Derived", ["Base", "Indexed"]], ["CycleA", ["CycleB"]], ["CycleB", ["CycleA"]]]);
|
|
93
|
+
const insertionOrder = ["Derived", "Indexed", "Leaf", "Base", "CycleA", "CycleB"];
|
|
94
|
+
const set = new SCCSet(item => edges.get(item) ?? []);
|
|
95
|
+
for (const item of insertionOrder) {
|
|
96
|
+
set.add(item);
|
|
97
|
+
}
|
|
98
|
+
expect([...set.items]).toEqual(["Leaf", "Indexed", "Base", "Derived", "CycleA", "CycleB"]);
|
|
99
|
+
expect(componentValues(set)).toEqual(["Leaf", "Indexed", "Base", "Derived", ["CycleA", "CycleB"]]);
|
|
100
|
+
});
|
|
101
|
+
it("batch adds nodes and recomputes once", () => {
|
|
102
|
+
const edges = new Map([["Leaf", []], ["Indexed", ["Record"]], ["Record", ["Leaf"]], ["Base", ["Leaf"]], ["Derived", ["Base", "Indexed"]], ["CycleA", ["CycleB"]], ["CycleB", ["CycleA"]]]);
|
|
103
|
+
const insertionOrder = ["Derived", "Indexed", "Leaf", "Base", "CycleA", "CycleB"];
|
|
104
|
+
const set = new SCCSet(item => edges.get(item) ?? []);
|
|
105
|
+
set.addAll(insertionOrder);
|
|
106
|
+
expect([...set.items]).toEqual(["Leaf", "Indexed", "Base", "Derived", "CycleA", "CycleB"]);
|
|
107
|
+
expect(componentValues(set)).toEqual(["Leaf", "Indexed", "Base", "Derived", ["CycleA", "CycleB"]]);
|
|
108
|
+
});
|
|
109
|
+
it("exposes component connections", () => {
|
|
110
|
+
const edges = new Map([["Leaf", []], ["Base", ["Leaf"]], ["Indexed", ["Leaf"]], ["Derived", ["Base", "Indexed"]], ["CycleA", ["CycleB"]], ["CycleB", ["CycleA"]]]);
|
|
111
|
+
const set = new SCCSet(item => edges.get(item) ?? []);
|
|
112
|
+
set.addAll(["Derived", "Base", "Indexed", "Leaf", "CycleA", "CycleB"]);
|
|
113
|
+
const getSingleton = name => set.components.find(component => component.value === name);
|
|
114
|
+
const format = components => Array.from(components, component => Array.isArray(component.value) ? component.value.join(",") : component.value).sort();
|
|
115
|
+
const derived = getSingleton("Derived");
|
|
116
|
+
const base = getSingleton("Base");
|
|
117
|
+
const indexed = getSingleton("Indexed");
|
|
118
|
+
const leaf = getSingleton("Leaf");
|
|
119
|
+
const cycle = set.components.find(component => Array.isArray(component.value));
|
|
120
|
+
expect(format(derived.references)).toEqual(["Base", "Indexed"]);
|
|
121
|
+
expect(format(base.references)).toEqual(["Leaf"]);
|
|
122
|
+
expect(format(base.referencedBy)).toEqual(["Derived"]);
|
|
123
|
+
expect(format(indexed.referencedBy)).toEqual(["Derived"]);
|
|
124
|
+
expect(format(leaf.referencedBy)).toEqual(["Base", "Indexed"]);
|
|
125
|
+
expect(format(cycle.references)).toEqual([]);
|
|
126
|
+
expect(format(cycle.referencedBy)).toEqual([]);
|
|
127
|
+
});
|
|
128
|
+
it("orders TypeSpec models via connector", async () => {
|
|
129
|
+
const tester = await Tester.createInstance();
|
|
130
|
+
const {
|
|
131
|
+
Leaf,
|
|
132
|
+
Indexed,
|
|
133
|
+
Base,
|
|
134
|
+
Derived,
|
|
135
|
+
CycleA,
|
|
136
|
+
CycleB
|
|
137
|
+
} = await tester.compile(t.code`
|
|
138
|
+
@test model ${t.model("Leaf")} {
|
|
139
|
+
value: string;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@test model ${t.model("Indexed")} extends Record<Leaf> {}
|
|
143
|
+
|
|
144
|
+
@test model ${t.model("Base")} {
|
|
145
|
+
leaf: Leaf;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@test model ${t.model("Derived")} extends Base {
|
|
149
|
+
payload: Indexed;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@test model ${t.model("CycleA")} {
|
|
153
|
+
next: CycleB;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@test model ${t.model("CycleB")} {
|
|
157
|
+
prev: CycleA;
|
|
158
|
+
}
|
|
159
|
+
`);
|
|
160
|
+
const models = [Derived, Indexed, Leaf, Base, CycleA, CycleB];
|
|
161
|
+
const set = new SCCSet(typeDependencyConnector);
|
|
162
|
+
for (const type of models) {
|
|
163
|
+
set.add(type);
|
|
164
|
+
}
|
|
165
|
+
const itemNames = set.items.map(getTypeLabel);
|
|
166
|
+
expect(itemNames).toEqual(["Leaf", "Indexed", "Base", "Derived", "CycleA", "CycleB"]);
|
|
167
|
+
const componentNames = set.components.map(formatComponent);
|
|
168
|
+
expect(componentNames).toEqual(["Leaf", "Indexed", "Base", "Derived", ["CycleA", "CycleB"]]);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
function componentValues(set) {
|
|
172
|
+
return componentValuesFrom(set.components);
|
|
173
|
+
}
|
|
174
|
+
function componentValuesFrom(components) {
|
|
175
|
+
return components.map(component => component.value);
|
|
176
|
+
}
|
|
177
|
+
function getTypeLabel(type) {
|
|
178
|
+
if ("name" in type && typeof type.name === "string" && type.name) {
|
|
179
|
+
return type.name;
|
|
180
|
+
}
|
|
181
|
+
return type.kind;
|
|
182
|
+
}
|
|
183
|
+
function formatComponent(component) {
|
|
184
|
+
return formatComponentValue(component.value);
|
|
185
|
+
}
|
|
186
|
+
function formatComponentValue(componentValue) {
|
|
187
|
+
if (Array.isArray(componentValue)) {
|
|
188
|
+
return componentValue.map(getTypeLabel);
|
|
189
|
+
}
|
|
190
|
+
return getTypeLabel(componentValue);
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=scc-set.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Tester","computed","t","describe","expect","it","vi","SCCSet","typeDependencyConnector","edges","Map","set","item","get","add","items","toEqual","componentValues","includeReachable","connector","fn","firstItems","firstComponents","components","toBe","toHaveBeenCalledTimes","componentValuesFrom","observedItems","observedComponents","observedCycle","cycle","find","component","Array","isArray","value","insertionOrder","addAll","getSingleton","name","format","from","join","sort","derived","base","indexed","leaf","references","referencedBy","tester","createInstance","Leaf","Indexed","Base","Derived","CycleA","CycleB","compile","code","model","models","type","itemNames","map","getTypeLabel","componentNames","formatComponent","kind","formatComponentValue","componentValue"],"sources":["../../../src/core/scc-set.test.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Type } from "@typespec/compiler";
|
|
2
|
+
/**
|
|
3
|
+
* Connector for {@link TypeSpec} {@link Type}s that captures the type graph edges used for
|
|
4
|
+
* topological ordering. Each returned dependency represents an incoming edge for the source
|
|
5
|
+
* type, e.g. a model depends on its base model, property types, and indexer key/value types.
|
|
6
|
+
*/
|
|
7
|
+
export declare function typeDependencyConnector(type: Type): Iterable<Type>;
|
|
8
|
+
//# sourceMappingURL=type-connector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-connector.d.ts","sourceRoot":"","sources":["../../../src/core/type-connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAElE"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connector for {@link TypeSpec} {@link Type}s that captures the type graph edges used for
|
|
3
|
+
* topological ordering. Each returned dependency represents an incoming edge for the source
|
|
4
|
+
* type, e.g. a model depends on its base model, property types, and indexer key/value types.
|
|
5
|
+
*/
|
|
6
|
+
export function typeDependencyConnector(type) {
|
|
7
|
+
return iterateTypeDependencies(type);
|
|
8
|
+
}
|
|
9
|
+
function* iterateTypeDependencies(type) {
|
|
10
|
+
switch (type.kind) {
|
|
11
|
+
case "Model":
|
|
12
|
+
if (type.baseModel) {
|
|
13
|
+
yield type.baseModel;
|
|
14
|
+
}
|
|
15
|
+
if (type.indexer) {
|
|
16
|
+
yield type.indexer.key;
|
|
17
|
+
yield type.indexer.value;
|
|
18
|
+
}
|
|
19
|
+
for (const property of type.properties.values()) {
|
|
20
|
+
yield property.type;
|
|
21
|
+
}
|
|
22
|
+
break;
|
|
23
|
+
case "ModelProperty":
|
|
24
|
+
yield type.type;
|
|
25
|
+
break;
|
|
26
|
+
case "Interface":
|
|
27
|
+
for (const operation of type.operations.values()) {
|
|
28
|
+
yield operation;
|
|
29
|
+
}
|
|
30
|
+
break;
|
|
31
|
+
case "Operation":
|
|
32
|
+
yield type.parameters;
|
|
33
|
+
yield type.returnType;
|
|
34
|
+
break;
|
|
35
|
+
case "Union":
|
|
36
|
+
for (const variant of type.variants.values()) {
|
|
37
|
+
yield variant;
|
|
38
|
+
}
|
|
39
|
+
break;
|
|
40
|
+
case "UnionVariant":
|
|
41
|
+
yield type.type;
|
|
42
|
+
break;
|
|
43
|
+
case "Tuple":
|
|
44
|
+
yield* type.values;
|
|
45
|
+
break;
|
|
46
|
+
case "Enum":
|
|
47
|
+
for (const member of type.members.values()) {
|
|
48
|
+
yield member;
|
|
49
|
+
}
|
|
50
|
+
break;
|
|
51
|
+
case "EnumMember":
|
|
52
|
+
if (type.sourceMember) {
|
|
53
|
+
yield type.sourceMember;
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
case "Scalar":
|
|
57
|
+
if (type.baseScalar) {
|
|
58
|
+
yield type.baseScalar;
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=type-connector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["typeDependencyConnector","type","iterateTypeDependencies","kind","baseModel","indexer","key","value","property","properties","values","operation","operations","parameters","returnType","variant","variants","member","members","sourceMember","baseScalar"],"sources":["../../../src/core/type-connector.ts"],"sourcesContent":[null],"mappings":"AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,uBAAuBA,CAACC,IAAU,EAAkB;EAClE,OAAOC,uBAAuB,CAACD,IAAI,CAAC;AACtC;AAEA,UAAUC,uBAAuBA,CAACD,IAAU,EAA0B;EACpE,QAAQA,IAAI,CAACE,IAAI;IACf,KAAK,OAAO;MACV,IAAIF,IAAI,CAACG,SAAS,EAAE;QAClB,MAAMH,IAAI,CAACG,SAAS;MACtB;MAEA,IAAIH,IAAI,CAACI,OAAO,EAAE;QAChB,MAAMJ,IAAI,CAACI,OAAO,CAACC,GAAG;QACtB,MAAML,IAAI,CAACI,OAAO,CAACE,KAAK;MAC1B;MAEA,KAAK,MAAMC,QAAQ,IAAIP,IAAI,CAACQ,UAAU,CAACC,MAAM,CAAC,CAAC,EAAE;QAC/C,MAAMF,QAAQ,CAACP,IAAI;MACrB;MACA;IACF,KAAK,eAAe;MAClB,MAAMA,IAAI,CAACA,IAAI;MACf;IACF,KAAK,WAAW;MACd,KAAK,MAAMU,SAAS,IAAIV,IAAI,CAACW,UAAU,CAACF,MAAM,CAAC,CAAC,EAAE;QAChD,MAAMC,SAAS;MACjB;MACA;IACF,KAAK,WAAW;MACd,MAAMV,IAAI,CAACY,UAAU;MACrB,MAAMZ,IAAI,CAACa,UAAU;MACrB;IACF,KAAK,OAAO;MACV,KAAK,MAAMC,OAAO,IAAId,IAAI,CAACe,QAAQ,CAACN,MAAM,CAAC,CAAC,EAAE;QAC5C,MAAMK,OAAO;MACf;MACA;IACF,KAAK,cAAc;MACjB,MAAMd,IAAI,CAACA,IAAI;MACf;IACF,KAAK,OAAO;MACV,OAAOA,IAAI,CAACS,MAAM;MAClB;IACF,KAAK,MAAM;MACT,KAAK,MAAMO,MAAM,IAAIhB,IAAI,CAACiB,OAAO,CAACR,MAAM,CAAC,CAAC,EAAE;QAC1C,MAAMO,MAAM;MACd;MACA;IACF,KAAK,YAAY;MACf,IAAIhB,IAAI,CAACkB,YAAY,EAAE;QACrB,MAAMlB,IAAI,CAACkB,YAAY;MACzB;MACA;IACF,KAAK,QAAQ;MACX,IAAIlB,IAAI,CAACmB,UAAU,EAAE;QACnB,MAAMnB,IAAI,CAACmB,UAAU;MACvB;MACA;EACJ;AACF","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typespec/emitter-framework",
|
|
3
|
-
"version": "0.15.0-dev.
|
|
3
|
+
"version": "0.15.0-dev.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"repository": {
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"@alloy-js/core": "^0.22.0",
|
|
42
42
|
"@alloy-js/csharp": "^0.22.0",
|
|
43
43
|
"@alloy-js/typescript": "^0.22.0",
|
|
44
|
-
"@typespec/compiler": "^1.7.
|
|
44
|
+
"@typespec/compiler": "^1.7.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@alloy-js/cli": "^0.22.0",
|
|
48
48
|
"@alloy-js/core": "^0.22.0",
|
|
49
49
|
"@alloy-js/rollup-plugin": "^0.1.0",
|
|
50
50
|
"@alloy-js/typescript": "^0.22.0",
|
|
51
|
-
"@typespec/compiler": "^1.7.
|
|
51
|
+
"@typespec/compiler": "^1.7.1",
|
|
52
52
|
"concurrently": "^9.1.2",
|
|
53
53
|
"pathe": "^2.0.3",
|
|
54
54
|
"prettier": "~3.6.2",
|
package/package.json.bak
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typespec/emitter-framework",
|
|
3
|
-
"version": "0.15.0-dev.
|
|
3
|
+
"version": "0.15.0-dev.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"repository": {
|
|
@@ -58,14 +58,14 @@
|
|
|
58
58
|
"@alloy-js/core": "^0.22.0",
|
|
59
59
|
"@alloy-js/csharp": "^0.22.0",
|
|
60
60
|
"@alloy-js/typescript": "^0.22.0",
|
|
61
|
-
"@typespec/compiler": "^1.7.
|
|
61
|
+
"@typespec/compiler": "^1.7.1"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@alloy-js/cli": "^0.22.0",
|
|
65
65
|
"@alloy-js/core": "^0.22.0",
|
|
66
66
|
"@alloy-js/rollup-plugin": "^0.1.0",
|
|
67
67
|
"@alloy-js/typescript": "^0.22.0",
|
|
68
|
-
"@typespec/compiler": "^1.7.
|
|
68
|
+
"@typespec/compiler": "^1.7.1",
|
|
69
69
|
"concurrently": "^9.1.2",
|
|
70
70
|
"pathe": "^2.0.3",
|
|
71
71
|
"prettier": "~3.6.2",
|
package/src/core/index.ts
CHANGED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { Tester } from "#test/test-host.js";
|
|
2
|
+
import { computed } from "@alloy-js/core";
|
|
3
|
+
import type { Type } from "@typespec/compiler";
|
|
4
|
+
import { t } from "@typespec/compiler/testing";
|
|
5
|
+
import { describe, expect, it, vi } from "vitest";
|
|
6
|
+
import { SCCSet, type NestedArray, type SCCComponent } from "./scc-set.js";
|
|
7
|
+
import { typeDependencyConnector } from "./type-connector.js";
|
|
8
|
+
|
|
9
|
+
describe("SCCSet", () => {
|
|
10
|
+
it("topologically orders items", () => {
|
|
11
|
+
const edges = new Map<string, string[]>([
|
|
12
|
+
["model", ["serializer"]],
|
|
13
|
+
["serializer", ["helpers"]],
|
|
14
|
+
["helpers", []],
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
const set = new SCCSet<string>((item) => edges.get(item) ?? []);
|
|
18
|
+
set.add("model");
|
|
19
|
+
set.add("serializer");
|
|
20
|
+
set.add("helpers");
|
|
21
|
+
|
|
22
|
+
expect([...set.items]).toEqual(["helpers", "serializer", "model"]);
|
|
23
|
+
expect(componentValues(set)).toEqual(["helpers", "serializer", "model"]);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("groups strongly connected components", () => {
|
|
27
|
+
const edges = new Map<string, string[]>([
|
|
28
|
+
["a", ["b"]],
|
|
29
|
+
["b", ["a", "c"]],
|
|
30
|
+
["c", []],
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
const set = new SCCSet<string>((item) => edges.get(item) ?? []);
|
|
34
|
+
set.add("a");
|
|
35
|
+
set.add("b");
|
|
36
|
+
set.add("c");
|
|
37
|
+
|
|
38
|
+
expect(componentValues(set)).toEqual(["c", ["a", "b"]]);
|
|
39
|
+
expect(set.items).toEqual(["c", "a", "b"]);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("defers placeholders until added", () => {
|
|
43
|
+
const edges = new Map<string, string[]>([
|
|
44
|
+
["root", ["child"]],
|
|
45
|
+
["child", []],
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
const set = new SCCSet<string>((item) => edges.get(item) ?? []);
|
|
49
|
+
|
|
50
|
+
set.add("root");
|
|
51
|
+
expect(set.items).toEqual(["root"]);
|
|
52
|
+
expect(componentValues(set)).toEqual(["root"]);
|
|
53
|
+
|
|
54
|
+
set.add("child");
|
|
55
|
+
expect(set.items).toEqual(["child", "root"]);
|
|
56
|
+
expect(componentValues(set)).toEqual(["child", "root"]);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("surfaces reachable nodes when requested", () => {
|
|
60
|
+
const edges = new Map<string, string[]>([
|
|
61
|
+
["root", ["child"]],
|
|
62
|
+
["child", ["leaf"]],
|
|
63
|
+
["leaf", []],
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
const set = new SCCSet<string>((item) => edges.get(item) ?? [], { includeReachable: true });
|
|
67
|
+
set.add("root");
|
|
68
|
+
|
|
69
|
+
expect(set.items).toEqual(["leaf", "child", "root"]);
|
|
70
|
+
expect(componentValues(set)).toEqual(["leaf", "child", "root"]);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("mutates arrays in place when adding", () => {
|
|
74
|
+
const edges = new Map<string, string[]>([["only", []]]);
|
|
75
|
+
const connector = vi.fn((item: string) => edges.get(item) ?? []);
|
|
76
|
+
|
|
77
|
+
const set = new SCCSet(connector);
|
|
78
|
+
set.add("only");
|
|
79
|
+
|
|
80
|
+
const firstItems = set.items;
|
|
81
|
+
const firstComponents = set.components;
|
|
82
|
+
|
|
83
|
+
expect(set.items).toBe(firstItems);
|
|
84
|
+
expect(set.components).toBe(firstComponents);
|
|
85
|
+
expect(connector).toHaveBeenCalledTimes(1);
|
|
86
|
+
|
|
87
|
+
set.add("late");
|
|
88
|
+
expect(connector).toHaveBeenCalledTimes(2);
|
|
89
|
+
expect(set.items).toBe(firstItems);
|
|
90
|
+
expect(set.components).toBe(firstComponents);
|
|
91
|
+
expect(firstItems).toEqual(["only", "late"]);
|
|
92
|
+
expect(componentValuesFrom(firstComponents)).toEqual(["only", "late"]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("notifies computed observers", () => {
|
|
96
|
+
const edges = new Map<string, string[]>([
|
|
97
|
+
["model", ["serializer"]],
|
|
98
|
+
["serializer", ["helpers"]],
|
|
99
|
+
["helpers", []],
|
|
100
|
+
["cycle-a", ["cycle-b"]],
|
|
101
|
+
["cycle-b", ["cycle-a"]],
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
const set = new SCCSet<string>((item) => edges.get(item) ?? []);
|
|
105
|
+
const observedItems = computed(() => [...set.items]);
|
|
106
|
+
const observedComponents = computed(() => componentValues(set));
|
|
107
|
+
const observedCycle = computed(() => {
|
|
108
|
+
const cycle = set.components.find((component) => Array.isArray(component.value));
|
|
109
|
+
if (!cycle || !Array.isArray(cycle.value)) {
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
return [...cycle.value];
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
expect(observedItems.value).toEqual([]);
|
|
116
|
+
expect(observedComponents.value).toEqual([]);
|
|
117
|
+
expect(observedCycle.value).toEqual([]);
|
|
118
|
+
|
|
119
|
+
set.add("model");
|
|
120
|
+
expect(observedItems.value).toEqual(["model"]);
|
|
121
|
+
expect(observedComponents.value).toEqual(["model"]);
|
|
122
|
+
|
|
123
|
+
set.add("serializer");
|
|
124
|
+
expect(observedItems.value).toEqual(["serializer", "model"]);
|
|
125
|
+
expect(observedComponents.value).toEqual(["serializer", "model"]);
|
|
126
|
+
|
|
127
|
+
set.add("helpers");
|
|
128
|
+
expect(observedItems.value).toEqual(["helpers", "serializer", "model"]);
|
|
129
|
+
expect(observedComponents.value).toEqual(["helpers", "serializer", "model"]);
|
|
130
|
+
|
|
131
|
+
set.add("cycle-a");
|
|
132
|
+
expect(observedCycle.value).toEqual([]);
|
|
133
|
+
|
|
134
|
+
set.add("cycle-b");
|
|
135
|
+
expect(observedCycle.value).toEqual(["cycle-a", "cycle-b"]);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("orders dependent nodes even when added out of order", () => {
|
|
139
|
+
const edges = new Map<string, string[]>([
|
|
140
|
+
["Leaf", []],
|
|
141
|
+
["Indexed", ["Record"]],
|
|
142
|
+
["Record", ["Leaf"]],
|
|
143
|
+
["Base", ["Leaf"]],
|
|
144
|
+
["Derived", ["Base", "Indexed"]],
|
|
145
|
+
["CycleA", ["CycleB"]],
|
|
146
|
+
["CycleB", ["CycleA"]],
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
const insertionOrder = ["Derived", "Indexed", "Leaf", "Base", "CycleA", "CycleB"];
|
|
150
|
+
const set = new SCCSet<string>((item) => edges.get(item) ?? []);
|
|
151
|
+
for (const item of insertionOrder) {
|
|
152
|
+
set.add(item);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
expect([...set.items]).toEqual(["Leaf", "Indexed", "Base", "Derived", "CycleA", "CycleB"]);
|
|
156
|
+
expect(componentValues(set)).toEqual([
|
|
157
|
+
"Leaf",
|
|
158
|
+
"Indexed",
|
|
159
|
+
"Base",
|
|
160
|
+
"Derived",
|
|
161
|
+
["CycleA", "CycleB"],
|
|
162
|
+
]);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("batch adds nodes and recomputes once", () => {
|
|
166
|
+
const edges = new Map<string, string[]>([
|
|
167
|
+
["Leaf", []],
|
|
168
|
+
["Indexed", ["Record"]],
|
|
169
|
+
["Record", ["Leaf"]],
|
|
170
|
+
["Base", ["Leaf"]],
|
|
171
|
+
["Derived", ["Base", "Indexed"]],
|
|
172
|
+
["CycleA", ["CycleB"]],
|
|
173
|
+
["CycleB", ["CycleA"]],
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
const insertionOrder = ["Derived", "Indexed", "Leaf", "Base", "CycleA", "CycleB"];
|
|
177
|
+
const set = new SCCSet<string>((item) => edges.get(item) ?? []);
|
|
178
|
+
set.addAll(insertionOrder);
|
|
179
|
+
|
|
180
|
+
expect([...set.items]).toEqual(["Leaf", "Indexed", "Base", "Derived", "CycleA", "CycleB"]);
|
|
181
|
+
expect(componentValues(set)).toEqual([
|
|
182
|
+
"Leaf",
|
|
183
|
+
"Indexed",
|
|
184
|
+
"Base",
|
|
185
|
+
"Derived",
|
|
186
|
+
["CycleA", "CycleB"],
|
|
187
|
+
]);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("exposes component connections", () => {
|
|
191
|
+
const edges = new Map<string, string[]>([
|
|
192
|
+
["Leaf", []],
|
|
193
|
+
["Base", ["Leaf"]],
|
|
194
|
+
["Indexed", ["Leaf"]],
|
|
195
|
+
["Derived", ["Base", "Indexed"]],
|
|
196
|
+
["CycleA", ["CycleB"]],
|
|
197
|
+
["CycleB", ["CycleA"]],
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
const set = new SCCSet<string>((item) => edges.get(item) ?? []);
|
|
201
|
+
set.addAll(["Derived", "Base", "Indexed", "Leaf", "CycleA", "CycleB"]);
|
|
202
|
+
|
|
203
|
+
const getSingleton = (name: string) =>
|
|
204
|
+
set.components.find((component) => component.value === name)!;
|
|
205
|
+
const format = (components: Iterable<SCCComponent<string>>) =>
|
|
206
|
+
Array.from(components, (component) =>
|
|
207
|
+
Array.isArray(component.value) ? component.value.join(",") : component.value,
|
|
208
|
+
).sort();
|
|
209
|
+
|
|
210
|
+
const derived = getSingleton("Derived");
|
|
211
|
+
const base = getSingleton("Base");
|
|
212
|
+
const indexed = getSingleton("Indexed");
|
|
213
|
+
const leaf = getSingleton("Leaf");
|
|
214
|
+
const cycle = set.components.find((component) => Array.isArray(component.value))!;
|
|
215
|
+
|
|
216
|
+
expect(format(derived.references)).toEqual(["Base", "Indexed"]);
|
|
217
|
+
expect(format(base.references)).toEqual(["Leaf"]);
|
|
218
|
+
expect(format(base.referencedBy)).toEqual(["Derived"]);
|
|
219
|
+
expect(format(indexed.referencedBy)).toEqual(["Derived"]);
|
|
220
|
+
expect(format(leaf.referencedBy)).toEqual(["Base", "Indexed"]);
|
|
221
|
+
expect(format(cycle.references)).toEqual([]);
|
|
222
|
+
expect(format(cycle.referencedBy)).toEqual([]);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("orders TypeSpec models via connector", async () => {
|
|
226
|
+
const tester = await Tester.createInstance();
|
|
227
|
+
const { Leaf, Indexed, Base, Derived, CycleA, CycleB } = await tester.compile(
|
|
228
|
+
t.code`
|
|
229
|
+
@test model ${t.model("Leaf")} {
|
|
230
|
+
value: string;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@test model ${t.model("Indexed")} extends Record<Leaf> {}
|
|
234
|
+
|
|
235
|
+
@test model ${t.model("Base")} {
|
|
236
|
+
leaf: Leaf;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
@test model ${t.model("Derived")} extends Base {
|
|
240
|
+
payload: Indexed;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@test model ${t.model("CycleA")} {
|
|
244
|
+
next: CycleB;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@test model ${t.model("CycleB")} {
|
|
248
|
+
prev: CycleA;
|
|
249
|
+
}
|
|
250
|
+
`,
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
const models = [Derived, Indexed, Leaf, Base, CycleA, CycleB] as Type[];
|
|
254
|
+
const set = new SCCSet<Type>(typeDependencyConnector);
|
|
255
|
+
for (const type of models) {
|
|
256
|
+
set.add(type);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const itemNames = set.items.map(getTypeLabel);
|
|
260
|
+
expect(itemNames).toEqual(["Leaf", "Indexed", "Base", "Derived", "CycleA", "CycleB"]);
|
|
261
|
+
|
|
262
|
+
const componentNames = set.components.map(formatComponent);
|
|
263
|
+
expect(componentNames).toEqual(["Leaf", "Indexed", "Base", "Derived", ["CycleA", "CycleB"]]);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
function componentValues<T>(set: SCCSet<T>): NestedArray<T>[] {
|
|
268
|
+
return componentValuesFrom(set.components);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function componentValuesFrom<T>(components: readonly SCCComponent<T>[]): NestedArray<T>[] {
|
|
272
|
+
return components.map((component) => component.value);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function getTypeLabel(type: Type): string {
|
|
276
|
+
if ("name" in type && typeof type.name === "string" && type.name) {
|
|
277
|
+
return type.name;
|
|
278
|
+
}
|
|
279
|
+
return type.kind;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
type ComponentLabel = string | string[];
|
|
283
|
+
|
|
284
|
+
function formatComponent(component: SCCComponent<Type>): ComponentLabel {
|
|
285
|
+
return formatComponentValue(component.value);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function formatComponentValue(componentValue: NestedArray<Type>): ComponentLabel {
|
|
289
|
+
if (Array.isArray(componentValue)) {
|
|
290
|
+
return (componentValue as Type[]).map(getTypeLabel);
|
|
291
|
+
}
|
|
292
|
+
return getTypeLabel(componentValue);
|
|
293
|
+
}
|