@typespec/emitter-framework 0.9.0-dev.1 → 0.9.0-dev.10
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/components/output.d.ts +4 -4
- package/dist/src/core/components/output.d.ts.map +1 -1
- package/dist/src/core/components/output.js +3 -3
- package/dist/src/core/context/name-policy-context.d.ts +2 -2
- package/dist/src/core/context/name-policy-context.d.ts.map +1 -1
- package/dist/src/core/context/tsp-context.d.ts +2 -2
- package/dist/src/core/context/tsp-context.d.ts.map +1 -1
- package/dist/src/core/transport-name-policy.d.ts +1 -1
- package/dist/src/core/transport-name-policy.d.ts.map +1 -1
- package/dist/src/core/write-output.d.ts +2 -2
- package/dist/src/core/write-output.d.ts.map +1 -1
- package/dist/src/csharp/components/class/declaration.d.ts +13 -0
- package/dist/src/csharp/components/class/declaration.d.ts.map +1 -0
- package/dist/src/csharp/components/class/declaration.js +91 -0
- package/dist/src/csharp/components/class/declaration.test.d.ts +2 -0
- package/dist/src/csharp/components/class/declaration.test.d.ts.map +1 -0
- package/dist/src/csharp/components/class/declaration.test.js +377 -0
- package/dist/src/csharp/components/enum/declaration.d.ts +9 -0
- package/dist/src/csharp/components/enum/declaration.d.ts.map +1 -0
- package/dist/src/csharp/components/enum/declaration.js +55 -0
- package/dist/src/csharp/components/enum/declaration.test.d.ts +2 -0
- package/dist/src/csharp/components/enum/declaration.test.d.ts.map +1 -0
- package/dist/src/csharp/components/enum/declaration.test.js +309 -0
- package/dist/src/csharp/components/index.d.ts +5 -0
- package/dist/src/csharp/components/index.d.ts.map +1 -0
- package/dist/src/csharp/components/index.js +4 -0
- package/dist/src/csharp/components/property/property.d.ts +15 -0
- package/dist/src/csharp/components/property/property.d.ts.map +1 -0
- package/dist/src/csharp/components/property/property.js +85 -0
- package/dist/src/csharp/components/property/property.test.d.ts +2 -0
- package/dist/src/csharp/components/property/property.test.d.ts.map +1 -0
- package/dist/src/csharp/components/property/property.test.js +117 -0
- package/dist/src/csharp/components/type-expression.d.ts +11 -0
- package/dist/src/csharp/components/type-expression.d.ts.map +1 -0
- package/dist/src/csharp/components/type-expression.js +143 -0
- package/dist/src/csharp/components/type-expression.test.d.ts +2 -0
- package/dist/src/csharp/components/type-expression.test.d.ts.map +1 -0
- package/dist/src/csharp/components/type-expression.test.js +128 -0
- package/dist/src/csharp/components/utils/doc-comments.d.ts +14 -0
- package/dist/src/csharp/components/utils/doc-comments.d.ts.map +1 -0
- package/dist/src/csharp/components/utils/doc-comments.js +67 -0
- package/dist/src/csharp/components/utils/refkey.d.ts +23 -0
- package/dist/src/csharp/components/utils/refkey.d.ts.map +1 -0
- package/dist/src/csharp/components/utils/refkey.js +35 -0
- package/dist/src/csharp/index.d.ts +2 -0
- package/dist/src/csharp/index.d.ts.map +1 -0
- package/dist/src/csharp/index.js +1 -0
- package/dist/src/testing/index.d.ts +1 -1
- package/dist/src/testing/index.d.ts.map +1 -1
- package/dist/src/testing/scenario-test/code-block-expectation.d.ts +33 -0
- package/dist/src/testing/scenario-test/code-block-expectation.d.ts.map +1 -0
- package/dist/src/testing/scenario-test/code-block-expectation.js +69 -0
- package/dist/src/testing/scenario-test/code-block-expectation.test.d.ts +2 -0
- package/dist/src/testing/scenario-test/code-block-expectation.test.d.ts.map +1 -0
- package/dist/src/testing/scenario-test/code-block-expectation.test.js +80 -0
- package/dist/src/testing/scenario-test/harness.d.ts +3 -3
- package/dist/src/testing/scenario-test/harness.d.ts.map +1 -1
- package/dist/src/testing/scenario-test/harness.js +69 -158
- package/dist/src/testing/scenario-test/index.d.ts +0 -1
- package/dist/src/testing/scenario-test/index.d.ts.map +1 -1
- package/dist/src/testing/scenario-test/index.js +1 -2
- package/dist/src/testing/scenario-test/snippet-extractor.d.ts +1 -1
- package/dist/src/testing/scenario-test/snippet-extractor.js +1 -1
- package/dist/src/typescript/components/array-expression.d.ts +2 -3
- package/dist/src/typescript/components/array-expression.d.ts.map +1 -1
- package/dist/src/typescript/components/array-expression.js +2 -2
- package/dist/src/typescript/components/arrow-function.d.ts +2 -2
- package/dist/src/typescript/components/arrow-function.d.ts.map +1 -1
- package/dist/src/typescript/components/arrow-function.js +2 -1
- package/dist/src/typescript/components/class-method.d.ts +1 -1
- package/dist/src/typescript/components/class-method.d.ts.map +1 -1
- package/dist/src/typescript/components/enum-declaration.d.ts +6 -6
- package/dist/src/typescript/components/enum-declaration.d.ts.map +1 -1
- package/dist/src/typescript/components/enum-declaration.js +2 -2
- package/dist/src/typescript/components/function-declaration.d.ts +1 -1
- package/dist/src/typescript/components/function-declaration.d.ts.map +1 -1
- package/dist/src/typescript/components/function-expression.d.ts +2 -2
- package/dist/src/typescript/components/function-expression.d.ts.map +1 -1
- package/dist/src/typescript/components/function-expression.js +2 -1
- package/dist/src/typescript/components/function-type.d.ts +2 -2
- package/dist/src/typescript/components/function-type.d.ts.map +1 -1
- package/dist/src/typescript/components/function-type.js +2 -1
- package/dist/src/typescript/components/interface-declaration.d.ts +4 -4
- package/dist/src/typescript/components/interface-declaration.d.ts.map +1 -1
- package/dist/src/typescript/components/interface-declaration.js +3 -4
- package/dist/src/typescript/components/interface-member.d.ts +2 -2
- package/dist/src/typescript/components/interface-member.d.ts.map +1 -1
- package/dist/src/typescript/components/interface-method.d.ts +2 -2
- package/dist/src/typescript/components/interface-method.d.ts.map +1 -1
- package/dist/src/typescript/components/record-expression.d.ts +1 -1
- package/dist/src/typescript/components/record-expression.d.ts.map +1 -1
- package/dist/src/typescript/components/type-alias-declaration.d.ts +1 -1
- package/dist/src/typescript/components/type-alias-declaration.d.ts.map +1 -1
- package/dist/src/typescript/components/type-declaration.d.ts +1 -1
- package/dist/src/typescript/components/type-declaration.d.ts.map +1 -1
- package/dist/src/typescript/components/type-expression.d.ts +1 -1
- package/dist/src/typescript/components/type-expression.d.ts.map +1 -1
- package/dist/src/typescript/components/type-transform.d.ts +2 -2
- package/dist/src/typescript/components/type-transform.d.ts.map +1 -1
- package/dist/src/typescript/components/union-declaration.d.ts +2 -2
- package/dist/src/typescript/components/union-declaration.d.ts.map +1 -1
- package/dist/src/typescript/components/union-expression.d.ts +3 -4
- package/dist/src/typescript/components/union-expression.d.ts.map +1 -1
- package/dist/src/typescript/components/union-expression.js +3 -3
- package/dist/src/typescript/components/value-expression.d.ts +2 -2
- package/dist/src/typescript/components/value-expression.d.ts.map +1 -1
- package/dist/src/typescript/utils/operation.d.ts +2 -2
- package/dist/src/typescript/utils/operation.d.ts.map +1 -1
- package/dist/test/test-host.d.ts +2 -0
- package/dist/test/test-host.d.ts.map +1 -0
- package/dist/test/test-host.js +5 -0
- package/dist/test/testing/snippet-extractor-csharp.test.js +3 -3
- package/dist/test/testing/snippet-extractor-java.test.js +3 -3
- package/dist/test/testing/snippet-extractor-python.test.js +2 -2
- package/dist/test/testing/snippet-extractor-typescript.test.js +3 -3
- package/dist/test/typescript/components/member-expression.test.js +5 -5
- package/dist/test/typescript/test-host.d.ts +1 -1
- package/dist/test/typescript/test-host.d.ts.map +1 -1
- package/dist/test/utils.d.ts +2 -2
- package/dist/test/utils.d.ts.map +1 -1
- package/dist/test/vitest.setup.d.ts +2 -0
- package/dist/test/vitest.setup.d.ts.map +1 -0
- package/dist/test/vitest.setup.js +1 -0
- package/package.json +26 -8
- package/src/core/components/output.tsx +9 -5
- package/src/core/context/name-policy-context.ts +2 -2
- package/src/core/context/tsp-context.ts +2 -2
- package/src/core/transport-name-policy.ts +1 -1
- package/src/core/write-output.ts +2 -2
- package/src/csharp/components/class/declaration.test.tsx +339 -0
- package/src/csharp/components/class/declaration.tsx +86 -0
- package/src/csharp/components/enum/declaration.test.tsx +267 -0
- package/src/csharp/components/enum/declaration.tsx +56 -0
- package/src/csharp/components/index.ts +4 -0
- package/src/csharp/components/property/property.test.tsx +97 -0
- package/src/csharp/components/property/property.tsx +62 -0
- package/src/csharp/components/type-expression.test.tsx +133 -0
- package/src/csharp/components/type-expression.tsx +119 -0
- package/src/csharp/components/utils/doc-comments.tsx +58 -0
- package/src/csharp/components/utils/refkey.ts +36 -0
- package/src/csharp/index.ts +1 -0
- package/src/testing/index.ts +1 -1
- package/src/testing/scenario-test/code-block-expectation.test.ts +95 -0
- package/src/testing/scenario-test/code-block-expectation.ts +115 -0
- package/src/testing/scenario-test/harness.ts +92 -237
- package/src/testing/scenario-test/index.ts +0 -1
- package/src/testing/scenario-test/snippet-extractor.ts +1 -1
- package/src/typescript/components/array-expression.tsx +3 -3
- package/src/typescript/components/arrow-function.tsx +2 -2
- package/src/typescript/components/class-method.tsx +1 -1
- package/src/typescript/components/enum-declaration.tsx +6 -6
- package/src/typescript/components/function-declaration.tsx +1 -1
- package/src/typescript/components/function-expression.tsx +2 -2
- package/src/typescript/components/function-type.tsx +2 -2
- package/src/typescript/components/interface-declaration.tsx +11 -12
- package/src/typescript/components/interface-member.tsx +2 -2
- package/src/typescript/components/interface-method.tsx +2 -2
- package/src/typescript/components/record-expression.tsx +1 -1
- package/src/typescript/components/type-alias-declaration.tsx +1 -1
- package/src/typescript/components/type-declaration.tsx +1 -1
- package/src/typescript/components/type-expression.tsx +2 -2
- package/src/typescript/components/type-transform.tsx +3 -3
- package/src/typescript/components/union-declaration.tsx +2 -2
- package/src/typescript/components/union-expression.tsx +12 -7
- package/src/typescript/components/value-expression.tsx +2 -2
- package/src/typescript/utils/operation.ts +2 -2
- package/test/test-host.ts +4 -0
- package/test/testing/snippet-extractor-csharp.test.ts +4 -4
- package/test/testing/snippet-extractor-java.test.ts +4 -4
- package/test/testing/snippet-extractor-python.test.ts +3 -3
- package/test/testing/snippet-extractor-typescript.test.ts +4 -4
- package/test/typescript/components/arrow-function.test.tsx +2 -2
- package/test/typescript/components/enum-declaration.test.tsx +1 -1
- package/test/typescript/components/function-declaration.test.tsx +1 -1
- package/test/typescript/components/function-expression.test.tsx +2 -2
- package/test/typescript/components/function-type.test.tsx +2 -2
- package/test/typescript/components/interface-declaration.test.tsx +1 -1
- package/test/typescript/components/interface-method.test.tsx +2 -2
- package/test/typescript/components/member-expression.test.tsx +10 -10
- package/test/typescript/components/type-alias-declaration.test.tsx +1 -1
- package/test/typescript/components/type-transform.test.tsx +2 -2
- package/test/typescript/components/union-declaration.test.tsx +2 -2
- package/test/typescript/components/value-expression.test.tsx +6 -6
- package/test/typescript/test-host.ts +1 -1
- package/test/utils.ts +2 -2
- package/test/vitest.setup.ts +1 -0
- package/tsconfig.json +3 -1
- package/vitest.config.ts +2 -1
- package/dist/src/testing/scenario-test/test-host.d.ts +0 -8
- package/dist/src/testing/scenario-test/test-host.d.ts.map +0 -1
- package/dist/src/testing/scenario-test/test-host.js +0 -49
- package/src/testing/scenario-test/test-host.ts +0 -83
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { Tester } from "#test/test-host.js";
|
|
2
|
+
import { type Children } from "@alloy-js/core";
|
|
3
|
+
import { createCSharpNamePolicy, Namespace, SourceFile } from "@alloy-js/csharp";
|
|
4
|
+
import { t, type TesterInstance } from "@typespec/compiler/testing";
|
|
5
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
6
|
+
import { Output } from "../../../core/index.js";
|
|
7
|
+
import { ClassDeclaration, EnumDeclaration } from "../../index.js";
|
|
8
|
+
|
|
9
|
+
let runner: TesterInstance;
|
|
10
|
+
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
runner = await Tester.createInstance();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
function Wrapper(props: { children: Children }) {
|
|
16
|
+
const policy = createCSharpNamePolicy();
|
|
17
|
+
return (
|
|
18
|
+
<Output program={runner.program} namePolicy={policy}>
|
|
19
|
+
<Namespace name="TestNamespace">
|
|
20
|
+
<SourceFile path="test.cs">{props.children}</SourceFile>
|
|
21
|
+
</Namespace>
|
|
22
|
+
</Output>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
it("renders an empty class declaration", async () => {
|
|
27
|
+
const { TestModel } = await runner.compile(t.code`
|
|
28
|
+
model ${t.model("TestModel")} {}
|
|
29
|
+
`);
|
|
30
|
+
|
|
31
|
+
expect(
|
|
32
|
+
<Wrapper>
|
|
33
|
+
<ClassDeclaration type={TestModel} />
|
|
34
|
+
</Wrapper>,
|
|
35
|
+
).toRenderTo(`
|
|
36
|
+
namespace TestNamespace
|
|
37
|
+
{
|
|
38
|
+
class TestModel
|
|
39
|
+
{
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
`);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("renders a class declaration with properties", async () => {
|
|
47
|
+
const { TestModel } = await runner.compile(t.code`
|
|
48
|
+
model ${t.model("TestModel")} {
|
|
49
|
+
@test Prop1: string;
|
|
50
|
+
@test Prop2: int32;
|
|
51
|
+
}
|
|
52
|
+
`);
|
|
53
|
+
|
|
54
|
+
expect(
|
|
55
|
+
<Wrapper>
|
|
56
|
+
<ClassDeclaration type={TestModel} />
|
|
57
|
+
</Wrapper>,
|
|
58
|
+
).toRenderTo(`
|
|
59
|
+
namespace TestNamespace
|
|
60
|
+
{
|
|
61
|
+
class TestModel
|
|
62
|
+
{
|
|
63
|
+
public required string Prop1 { get; set; }
|
|
64
|
+
public required int Prop2 { get; set; }
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("can override class name", async () => {
|
|
71
|
+
const { TestModel } = await runner.compile(t.code`
|
|
72
|
+
model ${t.model("TestModel")} {}
|
|
73
|
+
`);
|
|
74
|
+
|
|
75
|
+
expect(
|
|
76
|
+
<Wrapper>
|
|
77
|
+
<ClassDeclaration type={TestModel} name="CustomClassName" />
|
|
78
|
+
</Wrapper>,
|
|
79
|
+
).toRenderTo(`
|
|
80
|
+
namespace TestNamespace
|
|
81
|
+
{
|
|
82
|
+
class CustomClassName
|
|
83
|
+
{
|
|
84
|
+
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
`);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("renders a class with access modifiers", async () => {
|
|
91
|
+
const { TestModel } = await runner.compile(t.code`
|
|
92
|
+
model ${t.model("TestModel")} {
|
|
93
|
+
}
|
|
94
|
+
`);
|
|
95
|
+
|
|
96
|
+
expect(
|
|
97
|
+
<Wrapper>
|
|
98
|
+
<ClassDeclaration type={TestModel} protected />
|
|
99
|
+
</Wrapper>,
|
|
100
|
+
).toRenderTo(`
|
|
101
|
+
namespace TestNamespace
|
|
102
|
+
{
|
|
103
|
+
protected class TestModel
|
|
104
|
+
{
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
`);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe("from an interface", () => {
|
|
112
|
+
it("renders an empty class", async () => {
|
|
113
|
+
const { TestInterface } = await runner.compile(t.code`
|
|
114
|
+
interface ${t.interface("TestInterface")} {
|
|
115
|
+
}
|
|
116
|
+
`);
|
|
117
|
+
|
|
118
|
+
expect(
|
|
119
|
+
<Wrapper>
|
|
120
|
+
<ClassDeclaration type={TestInterface} />
|
|
121
|
+
</Wrapper>,
|
|
122
|
+
).toRenderTo(`
|
|
123
|
+
namespace TestNamespace
|
|
124
|
+
{
|
|
125
|
+
class TestInterface
|
|
126
|
+
{
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
`);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("renders a class with operations", async () => {
|
|
134
|
+
const { TestInterface } = await runner.compile(t.code`
|
|
135
|
+
interface ${t.interface("TestInterface")} {
|
|
136
|
+
op getName(id: string): string;
|
|
137
|
+
}
|
|
138
|
+
`);
|
|
139
|
+
|
|
140
|
+
expect(
|
|
141
|
+
<Wrapper>
|
|
142
|
+
<ClassDeclaration type={TestInterface} />
|
|
143
|
+
</Wrapper>,
|
|
144
|
+
).toRenderTo(`
|
|
145
|
+
namespace TestNamespace
|
|
146
|
+
{
|
|
147
|
+
class TestInterface
|
|
148
|
+
{
|
|
149
|
+
public abstract string GetName(string id);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
`);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("renders a class with model members", async () => {
|
|
157
|
+
const { TestModel, TestReference } = await runner.compile(t.code`
|
|
158
|
+
model ${t.model("TestReference")} { }
|
|
159
|
+
model ${t.model("TestModel")} {
|
|
160
|
+
prop1: TestReference;
|
|
161
|
+
}
|
|
162
|
+
`);
|
|
163
|
+
|
|
164
|
+
expect(
|
|
165
|
+
<Wrapper>
|
|
166
|
+
<ClassDeclaration type={TestReference} />
|
|
167
|
+
<hbr />
|
|
168
|
+
<ClassDeclaration type={TestModel} />
|
|
169
|
+
</Wrapper>,
|
|
170
|
+
).toRenderTo(`
|
|
171
|
+
namespace TestNamespace
|
|
172
|
+
{
|
|
173
|
+
class TestReference
|
|
174
|
+
{
|
|
175
|
+
|
|
176
|
+
}
|
|
177
|
+
class TestModel
|
|
178
|
+
{
|
|
179
|
+
public required TestReference Prop1 { get; set; }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
`);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("renders a class with enum members", async () => {
|
|
186
|
+
const { TestModel, TestEnum } = await runner.compile(t.code`
|
|
187
|
+
@test enum ${t.enum("TestEnum")} {
|
|
188
|
+
Value1;
|
|
189
|
+
Value2;
|
|
190
|
+
}
|
|
191
|
+
model ${t.model("TestModel")} {
|
|
192
|
+
@test prop1: TestEnum;
|
|
193
|
+
}
|
|
194
|
+
`);
|
|
195
|
+
|
|
196
|
+
expect(
|
|
197
|
+
<Wrapper>
|
|
198
|
+
<EnumDeclaration type={TestEnum} />
|
|
199
|
+
<hbr />
|
|
200
|
+
<ClassDeclaration type={TestModel} />
|
|
201
|
+
</Wrapper>,
|
|
202
|
+
).toRenderTo(`
|
|
203
|
+
namespace TestNamespace
|
|
204
|
+
{
|
|
205
|
+
enum TestEnum
|
|
206
|
+
{
|
|
207
|
+
Value1,
|
|
208
|
+
Value2
|
|
209
|
+
}
|
|
210
|
+
class TestModel
|
|
211
|
+
{
|
|
212
|
+
public required TestEnum Prop1 { get; set; }
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
`);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("maps prop: string | null to nullable property", async () => {
|
|
219
|
+
const { TestModel } = await runner.compile(t.code`
|
|
220
|
+
model ${t.model("TestModel")} {
|
|
221
|
+
prop1: string | null;
|
|
222
|
+
}
|
|
223
|
+
`);
|
|
224
|
+
|
|
225
|
+
expect(
|
|
226
|
+
<Wrapper>
|
|
227
|
+
<ClassDeclaration type={TestModel} />
|
|
228
|
+
</Wrapper>,
|
|
229
|
+
).toRenderTo(`
|
|
230
|
+
namespace TestNamespace
|
|
231
|
+
{
|
|
232
|
+
class TestModel
|
|
233
|
+
{
|
|
234
|
+
public required string? Prop1 { get; set; }
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
`);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it("renders a class with string enums", async () => {
|
|
241
|
+
const { TestModel, TestEnum } = await runner.compile(t.code`
|
|
242
|
+
@test enum ${t.enum("TestEnum")} {
|
|
243
|
+
Value1;
|
|
244
|
+
Value2;
|
|
245
|
+
}
|
|
246
|
+
model ${t.model("TestModel")} {
|
|
247
|
+
@test prop1: TestEnum;
|
|
248
|
+
}
|
|
249
|
+
`);
|
|
250
|
+
|
|
251
|
+
expect(
|
|
252
|
+
<Wrapper>
|
|
253
|
+
<EnumDeclaration type={TestEnum} />
|
|
254
|
+
<hbr />
|
|
255
|
+
<ClassDeclaration type={TestModel} />
|
|
256
|
+
</Wrapper>,
|
|
257
|
+
).toRenderTo(`
|
|
258
|
+
namespace TestNamespace
|
|
259
|
+
{
|
|
260
|
+
enum TestEnum
|
|
261
|
+
{
|
|
262
|
+
Value1,
|
|
263
|
+
Value2
|
|
264
|
+
}
|
|
265
|
+
class TestModel
|
|
266
|
+
{
|
|
267
|
+
public required TestEnum Prop1 { get; set; }
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
`);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
describe("with doc comments", () => {
|
|
274
|
+
it("renders a model with docs", async () => {
|
|
275
|
+
const { TestModel } = await runner.compile(t.code`
|
|
276
|
+
@doc("This is a test model")
|
|
277
|
+
model ${t.model("TestModel")} {
|
|
278
|
+
@doc("This is a test property")
|
|
279
|
+
prop1: string;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
`);
|
|
283
|
+
|
|
284
|
+
expect(
|
|
285
|
+
<Wrapper>
|
|
286
|
+
<ClassDeclaration type={TestModel} />
|
|
287
|
+
</Wrapper>,
|
|
288
|
+
).toRenderTo(`
|
|
289
|
+
namespace TestNamespace
|
|
290
|
+
{
|
|
291
|
+
/// <summary>
|
|
292
|
+
/// This is a test model
|
|
293
|
+
/// </summary>
|
|
294
|
+
class TestModel
|
|
295
|
+
{
|
|
296
|
+
/// <summary>
|
|
297
|
+
/// This is a test property
|
|
298
|
+
/// </summary>
|
|
299
|
+
public required string Prop1 { get; set; }
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
`);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it("renders an interface with docs", async () => {
|
|
306
|
+
const { TestInterface } = await runner.compile(t.code`
|
|
307
|
+
@doc("This is a test interface")
|
|
308
|
+
@test interface ${t.interface("TestInterface")} {
|
|
309
|
+
@doc("This is a test operation")
|
|
310
|
+
@returnsDoc("The name of the item")
|
|
311
|
+
op getName(id: string): string;
|
|
312
|
+
}
|
|
313
|
+
`);
|
|
314
|
+
|
|
315
|
+
expect(
|
|
316
|
+
<Wrapper>
|
|
317
|
+
<ClassDeclaration type={TestInterface} />
|
|
318
|
+
</Wrapper>,
|
|
319
|
+
).toRenderTo(`
|
|
320
|
+
namespace TestNamespace
|
|
321
|
+
{
|
|
322
|
+
/// <summary>
|
|
323
|
+
/// This is a test interface
|
|
324
|
+
/// </summary>
|
|
325
|
+
class TestInterface
|
|
326
|
+
{
|
|
327
|
+
/// <summary>
|
|
328
|
+
/// This is a test operation
|
|
329
|
+
/// </summary>
|
|
330
|
+
///
|
|
331
|
+
/// <returns>
|
|
332
|
+
/// The name of the item
|
|
333
|
+
/// </returns>
|
|
334
|
+
public abstract string GetName(string id);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
`);
|
|
338
|
+
});
|
|
339
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { type Children, For } from "@alloy-js/core";
|
|
2
|
+
import * as cs from "@alloy-js/csharp";
|
|
3
|
+
import type { Interface, Model } from "@typespec/compiler";
|
|
4
|
+
import { useTsp } from "../../../core/index.js";
|
|
5
|
+
import { Property } from "../property/property.jsx";
|
|
6
|
+
import { TypeExpression } from "../type-expression.jsx";
|
|
7
|
+
import { getDocComments } from "../utils/doc-comments.jsx";
|
|
8
|
+
import { declarationRefkeys } from "../utils/refkey.js";
|
|
9
|
+
|
|
10
|
+
export interface ClassDeclarationProps extends Omit<cs.ClassDeclarationProps, "name"> {
|
|
11
|
+
/** Set an alternative name for the class. Otherwise default to the type name. */
|
|
12
|
+
name?: string;
|
|
13
|
+
/** Type to use to create this class. */
|
|
14
|
+
type: Model | Interface;
|
|
15
|
+
/** If set the property will add the json serialization attributes(using System.Text.Json). */
|
|
16
|
+
jsonAttributes?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface ClassPropertiesProps {
|
|
20
|
+
type: Model;
|
|
21
|
+
/** If set the property will add the json serialization attributes(using System.Text.Json). */
|
|
22
|
+
jsonAttributes?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface ClassMethodsProps {
|
|
26
|
+
type: Interface;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function ClassDeclaration(props: ClassDeclarationProps): Children {
|
|
30
|
+
const { $ } = useTsp();
|
|
31
|
+
|
|
32
|
+
const namePolicy = cs.useCSharpNamePolicy();
|
|
33
|
+
const className = props.name ?? namePolicy.getName(props.type.name, "class");
|
|
34
|
+
|
|
35
|
+
const refkeys = declarationRefkeys(props.refkey, props.type)[0]; // TODO: support multiple refkeys for declarations in alloy
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<>
|
|
39
|
+
<cs.ClassDeclaration
|
|
40
|
+
{...props}
|
|
41
|
+
name={className}
|
|
42
|
+
refkey={refkeys}
|
|
43
|
+
doc={getDocComments($, props.type)}
|
|
44
|
+
>
|
|
45
|
+
{props.type.kind === "Model" && (
|
|
46
|
+
<ClassProperties type={props.type} jsonAttributes={props.jsonAttributes} />
|
|
47
|
+
)}
|
|
48
|
+
{props.type.kind === "Interface" && <ClassMethods type={props.type} />}
|
|
49
|
+
</cs.ClassDeclaration>
|
|
50
|
+
</>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function ClassProperties(props: ClassPropertiesProps): Children {
|
|
55
|
+
return (
|
|
56
|
+
<For each={props.type.properties.entries()} hardline>
|
|
57
|
+
{([name, property]) => <Property type={property} jsonAttributes={props.jsonAttributes} />}
|
|
58
|
+
</For>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function ClassMethods(props: ClassMethodsProps): Children {
|
|
63
|
+
const { $ } = useTsp();
|
|
64
|
+
const namePolicy = cs.useCSharpNamePolicy();
|
|
65
|
+
|
|
66
|
+
const abstractMethods: Children = [];
|
|
67
|
+
for (const [name, method] of props.type.operations) {
|
|
68
|
+
abstractMethods.push(
|
|
69
|
+
<cs.ClassMethod
|
|
70
|
+
name={namePolicy.getName(name, "class-method")}
|
|
71
|
+
abstract
|
|
72
|
+
parameters={[...method.parameters.properties.entries()].map(([name, prop]) => {
|
|
73
|
+
return {
|
|
74
|
+
name: namePolicy.getName(name, "type-parameter"),
|
|
75
|
+
type: <TypeExpression type={prop.type} />,
|
|
76
|
+
};
|
|
77
|
+
})}
|
|
78
|
+
public
|
|
79
|
+
doc={getDocComments($, method)}
|
|
80
|
+
returns={<TypeExpression type={method.returnType} />}
|
|
81
|
+
/>,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return <>{abstractMethods}</>;
|
|
86
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { Tester } from "#test/test-host.js";
|
|
2
|
+
import { type Children } from "@alloy-js/core";
|
|
3
|
+
import { createCSharpNamePolicy, Namespace, SourceFile } from "@alloy-js/csharp";
|
|
4
|
+
import { t, type TesterInstance } from "@typespec/compiler/testing";
|
|
5
|
+
import { beforeEach, expect, it } from "vitest";
|
|
6
|
+
import { Output } from "../../../core/index.js";
|
|
7
|
+
import { EnumDeclaration } from "../../index.js";
|
|
8
|
+
|
|
9
|
+
let runner: TesterInstance;
|
|
10
|
+
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
runner = await Tester.createInstance();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
function Wrapper(props: { children: Children }) {
|
|
16
|
+
const policy = createCSharpNamePolicy();
|
|
17
|
+
return (
|
|
18
|
+
<Output program={runner.program} namePolicy={policy}>
|
|
19
|
+
<Namespace name="TestNamespace">
|
|
20
|
+
<SourceFile path="test.cs">{props.children}</SourceFile>
|
|
21
|
+
</Namespace>
|
|
22
|
+
</Output>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
it("renders a basic enum declaration", async () => {
|
|
27
|
+
const { TestEnum } = await runner.compile(t.code`
|
|
28
|
+
@test enum ${t.enum("TestEnum")} {
|
|
29
|
+
Value1;
|
|
30
|
+
Value2;
|
|
31
|
+
Value3;
|
|
32
|
+
}
|
|
33
|
+
`);
|
|
34
|
+
|
|
35
|
+
expect(
|
|
36
|
+
<Wrapper>
|
|
37
|
+
<EnumDeclaration type={TestEnum} />
|
|
38
|
+
</Wrapper>,
|
|
39
|
+
).toRenderTo(`
|
|
40
|
+
namespace TestNamespace
|
|
41
|
+
{
|
|
42
|
+
enum TestEnum
|
|
43
|
+
{
|
|
44
|
+
Value1,
|
|
45
|
+
Value2,
|
|
46
|
+
Value3
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
`);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("renders an empty enum declaration", async () => {
|
|
53
|
+
const { TestEnum } = await runner.compile(t.code`
|
|
54
|
+
@test enum ${t.enum("TestEnum")} {}
|
|
55
|
+
`);
|
|
56
|
+
|
|
57
|
+
expect(
|
|
58
|
+
<Wrapper>
|
|
59
|
+
<EnumDeclaration type={TestEnum} />
|
|
60
|
+
</Wrapper>,
|
|
61
|
+
).toRenderTo(`
|
|
62
|
+
namespace TestNamespace
|
|
63
|
+
{
|
|
64
|
+
enum TestEnum
|
|
65
|
+
{
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
`);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("can override enum name", async () => {
|
|
73
|
+
const { TestEnum } = await runner.compile(t.code`
|
|
74
|
+
@test enum ${t.enum("TestEnum")} {
|
|
75
|
+
Value1;
|
|
76
|
+
Value2;
|
|
77
|
+
}
|
|
78
|
+
`);
|
|
79
|
+
|
|
80
|
+
expect(
|
|
81
|
+
<Wrapper>
|
|
82
|
+
<EnumDeclaration type={TestEnum} name="CustomEnumName" />
|
|
83
|
+
</Wrapper>,
|
|
84
|
+
).toRenderTo(`
|
|
85
|
+
namespace TestNamespace
|
|
86
|
+
{
|
|
87
|
+
enum CustomEnumName
|
|
88
|
+
{
|
|
89
|
+
Value1,
|
|
90
|
+
Value2
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
`);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("renders an enum with access modifiers", async () => {
|
|
97
|
+
const { TestEnum } = await runner.compile(t.code`
|
|
98
|
+
@test enum ${t.enum("TestEnum")} {
|
|
99
|
+
Value1;
|
|
100
|
+
Value2;
|
|
101
|
+
}
|
|
102
|
+
`);
|
|
103
|
+
|
|
104
|
+
expect(
|
|
105
|
+
<Wrapper>
|
|
106
|
+
<EnumDeclaration type={TestEnum} internal />
|
|
107
|
+
</Wrapper>,
|
|
108
|
+
).toRenderTo(`
|
|
109
|
+
namespace TestNamespace
|
|
110
|
+
{
|
|
111
|
+
internal enum TestEnum
|
|
112
|
+
{
|
|
113
|
+
Value1,
|
|
114
|
+
Value2
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
`);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("renders enum with C# naming conventions", async () => {
|
|
121
|
+
const { TestEnum } = await runner.compile(t.code`
|
|
122
|
+
@test enum ${t.enum("TestEnum")} {
|
|
123
|
+
value_one;
|
|
124
|
+
value_two;
|
|
125
|
+
value_three;
|
|
126
|
+
}
|
|
127
|
+
`);
|
|
128
|
+
|
|
129
|
+
expect(
|
|
130
|
+
<Output program={runner.program} namePolicy={createCSharpNamePolicy()}>
|
|
131
|
+
<Namespace name="TestNamespace">
|
|
132
|
+
<SourceFile path="test.cs">
|
|
133
|
+
<EnumDeclaration type={TestEnum} />
|
|
134
|
+
</SourceFile>
|
|
135
|
+
</Namespace>
|
|
136
|
+
</Output>,
|
|
137
|
+
).toRenderTo(`
|
|
138
|
+
namespace TestNamespace
|
|
139
|
+
{
|
|
140
|
+
enum TestEnum
|
|
141
|
+
{
|
|
142
|
+
ValueOne,
|
|
143
|
+
ValueTwo,
|
|
144
|
+
ValueThree
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
`);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("renders enum with single value", async () => {
|
|
151
|
+
const { TestEnum } = await runner.compile(t.code`
|
|
152
|
+
@test enum ${t.enum("TestEnum")} {
|
|
153
|
+
OnlyValue;
|
|
154
|
+
}
|
|
155
|
+
`);
|
|
156
|
+
|
|
157
|
+
expect(
|
|
158
|
+
<Wrapper>
|
|
159
|
+
<EnumDeclaration type={TestEnum} />
|
|
160
|
+
</Wrapper>,
|
|
161
|
+
).toRenderTo(`
|
|
162
|
+
namespace TestNamespace
|
|
163
|
+
{
|
|
164
|
+
enum TestEnum
|
|
165
|
+
{
|
|
166
|
+
OnlyValue
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
`);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("renders enum with numeric-like member names", async () => {
|
|
173
|
+
const { TestEnum } = await runner.compile(t.code`
|
|
174
|
+
@test enum ${t.enum("TestEnum")} {
|
|
175
|
+
Value0;
|
|
176
|
+
Value1;
|
|
177
|
+
Value10;
|
|
178
|
+
Value100;
|
|
179
|
+
}
|
|
180
|
+
`);
|
|
181
|
+
|
|
182
|
+
expect(
|
|
183
|
+
<Wrapper>
|
|
184
|
+
<EnumDeclaration type={TestEnum} />
|
|
185
|
+
</Wrapper>,
|
|
186
|
+
).toRenderTo(`
|
|
187
|
+
namespace TestNamespace
|
|
188
|
+
{
|
|
189
|
+
enum TestEnum
|
|
190
|
+
{
|
|
191
|
+
Value0,
|
|
192
|
+
Value1,
|
|
193
|
+
Value10,
|
|
194
|
+
Value100
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
`);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("renders multiple enums in the same namespace", async () => {
|
|
201
|
+
const { TestEnum1, TestEnum2 } = await runner.compile(t.code`
|
|
202
|
+
@test enum ${t.enum("TestEnum1")} {
|
|
203
|
+
Value1;
|
|
204
|
+
Value2;
|
|
205
|
+
}
|
|
206
|
+
@test enum ${t.enum("TestEnum2")} {
|
|
207
|
+
OptionA;
|
|
208
|
+
OptionB;
|
|
209
|
+
OptionC;
|
|
210
|
+
}
|
|
211
|
+
`);
|
|
212
|
+
|
|
213
|
+
expect(
|
|
214
|
+
<Wrapper>
|
|
215
|
+
<EnumDeclaration type={TestEnum1} />
|
|
216
|
+
<hbr />
|
|
217
|
+
<EnumDeclaration type={TestEnum2} />
|
|
218
|
+
</Wrapper>,
|
|
219
|
+
).toRenderTo(`
|
|
220
|
+
namespace TestNamespace
|
|
221
|
+
{
|
|
222
|
+
enum TestEnum1
|
|
223
|
+
{
|
|
224
|
+
Value1,
|
|
225
|
+
Value2
|
|
226
|
+
}
|
|
227
|
+
enum TestEnum2
|
|
228
|
+
{
|
|
229
|
+
OptionA,
|
|
230
|
+
OptionB,
|
|
231
|
+
OptionC
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
`);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("renders an enum with doc comments", async () => {
|
|
238
|
+
const { TestEnum } = await runner.compile(t.code`
|
|
239
|
+
@test enum ${t.enum("TestEnum")} {
|
|
240
|
+
@doc("This is value one")
|
|
241
|
+
Value1;
|
|
242
|
+
/** This is value two */
|
|
243
|
+
Value2;
|
|
244
|
+
}
|
|
245
|
+
`);
|
|
246
|
+
|
|
247
|
+
expect(
|
|
248
|
+
<Wrapper>
|
|
249
|
+
<EnumDeclaration type={TestEnum} />
|
|
250
|
+
</Wrapper>,
|
|
251
|
+
).toRenderTo(`
|
|
252
|
+
namespace TestNamespace
|
|
253
|
+
{
|
|
254
|
+
enum TestEnum
|
|
255
|
+
{
|
|
256
|
+
/// <summary>
|
|
257
|
+
/// This is value one
|
|
258
|
+
/// </summary>
|
|
259
|
+
Value1,
|
|
260
|
+
/// <summary>
|
|
261
|
+
/// This is value two
|
|
262
|
+
/// </summary>
|
|
263
|
+
Value2
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
`);
|
|
267
|
+
});
|