@alloy-js/csharp 0.19.0 → 0.20.0-dev.1

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.
Files changed (27) hide show
  1. package/dist/src/components/{ClassDeclaration.d.ts → class/declaration.d.ts} +29 -11
  2. package/dist/src/components/class/declaration.d.ts.map +1 -0
  3. package/dist/src/components/{ClassDeclaration.js → class/declaration.js} +22 -14
  4. package/dist/src/components/class/declaration.test.d.ts +2 -0
  5. package/dist/src/components/class/declaration.test.d.ts.map +1 -0
  6. package/dist/{test/class-declaration.test.js → src/components/class/declaration.test.js} +190 -100
  7. package/dist/src/components/constructor/constructor.test.js +1 -1
  8. package/dist/src/components/field/field.test.js +1 -1
  9. package/dist/src/components/index.d.ts +1 -1
  10. package/dist/src/components/index.d.ts.map +1 -1
  11. package/dist/src/components/index.js +1 -1
  12. package/dist/src/components/parameters/parameters.d.ts.map +1 -1
  13. package/dist/src/components/parameters/parameters.js +1 -1
  14. package/dist/src/components/property/property.test.js +1 -1
  15. package/dist/tsconfig.tsbuildinfo +1 -1
  16. package/package.json +6 -6
  17. package/{test/class-declaration.test.tsx → src/components/class/declaration.test.tsx} +204 -125
  18. package/src/components/{ClassDeclaration.tsx → class/declaration.tsx} +53 -22
  19. package/src/components/constructor/constructor.test.tsx +1 -1
  20. package/src/components/field/field.test.tsx +1 -1
  21. package/src/components/index.ts +1 -1
  22. package/src/components/parameters/parameters.tsx +3 -1
  23. package/src/components/property/property.test.tsx +1 -1
  24. package/temp/api.json +41 -9
  25. package/dist/src/components/ClassDeclaration.d.ts.map +0 -1
  26. package/dist/test/class-declaration.test.d.ts +0 -2
  27. package/dist/test/class-declaration.test.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alloy-js/csharp",
3
- "version": "0.19.0",
3
+ "version": "0.20.0-dev.1",
4
4
  "description": "",
5
5
  "exports": {
6
6
  ".": {
@@ -14,19 +14,19 @@
14
14
  "author": "jhendrix@microsoft.com",
15
15
  "license": "MIT",
16
16
  "dependencies": {
17
+ "@alloy-js/core": "~0.19.0 || >= 0.20.0-dev.0",
17
18
  "change-case": "^5.4.4",
18
19
  "marked": "^15.0.12",
19
- "pathe": "^2.0.3",
20
- "@alloy-js/core": "~0.19.0"
20
+ "pathe": "^2.0.3"
21
21
  },
22
22
  "devDependencies": {
23
+ "@alloy-js/cli": "~0.19.0 || >= 0.20.0-dev.0",
24
+ "@alloy-js/rollup-plugin": "~0.1.0 || >= 0.1.1-dev.0",
23
25
  "@microsoft/api-extractor": "~7.52.8",
24
26
  "@rollup/plugin-typescript": "^12.1.2",
25
27
  "concurrently": "^9.1.2",
26
28
  "typescript": "^5.8.3",
27
- "vitest": "^3.2.4",
28
- "@alloy-js/rollup-plugin": "~0.1.0",
29
- "@alloy-js/cli": "~0.19.0"
29
+ "vitest": "^3.2.4"
30
30
  },
31
31
  "type": "module",
32
32
  "scripts": {
@@ -1,21 +1,40 @@
1
- import * as core from "@alloy-js/core";
2
- import { List, refkey } from "@alloy-js/core";
1
+ import {
2
+ Children,
3
+ code,
4
+ createNamePolicy,
5
+ List,
6
+ NamePolicyContext,
7
+ Output,
8
+ refkey,
9
+ render,
10
+ } from "@alloy-js/core";
3
11
  import * as coretest from "@alloy-js/core/testing";
4
12
  import { describe, expect, it } from "vitest";
5
- import { Attribute } from "../src/components/attributes/attributes.jsx";
6
- import { Field } from "../src/components/field/field.jsx";
7
- import { Constructor } from "../src/components/stc/index.js";
8
- import { TypeParameterProps } from "../src/components/type-parameters/type-parameter.jsx";
9
- import * as csharp from "../src/index.js";
10
- import { ClassDeclaration, Property, SourceFile } from "../src/index.js";
11
- import * as utils from "./utils.jsx";
12
- import { findFile } from "./utils.jsx";
13
+ import { findFile, TestNamespace, toSourceText } from "../../../test/utils.jsx";
14
+ import { createCSharpNamePolicy } from "../../name-policy.js";
15
+ import { Attribute } from "../attributes/attributes.jsx";
16
+ import { Field } from "../field/field.jsx";
17
+ import { Method } from "../method/method.jsx";
18
+ import { Namespace } from "../Namespace.jsx";
19
+ import { Property } from "../property/property.jsx";
20
+ import { SourceFile } from "../SourceFile.jsx";
21
+ import { Constructor, EnumDeclaration, EnumMember } from "../stc/index.js";
22
+ import { TypeParameterProps } from "../type-parameters/type-parameter.jsx";
23
+ import { ClassDeclaration } from "./declaration.jsx";
24
+
25
+ function Wrapper({ children }: { children: Children }) {
26
+ return (
27
+ <TestNamespace>
28
+ <SourceFile path="Test.cs">{children}</SourceFile>
29
+ </TestNamespace>
30
+ );
31
+ }
13
32
 
14
33
  it("declares class with no members", () => {
15
34
  expect(
16
- <utils.TestNamespace>
35
+ <TestNamespace>
17
36
  <ClassDeclaration name="TestClass" />
18
- </utils.TestNamespace>,
37
+ </TestNamespace>,
19
38
  ).toRenderTo(`
20
39
  class TestClass;
21
40
  `);
@@ -24,9 +43,9 @@ it("declares class with no members", () => {
24
43
  describe("modifiers", () => {
25
44
  it.each(["public", "private"])("%s", (mod) => {
26
45
  expect(
27
- <utils.TestNamespace>
46
+ <TestNamespace>
28
47
  <ClassDeclaration {...{ [mod]: true }} name="TestClass" />
29
- </utils.TestNamespace>,
48
+ </TestNamespace>,
30
49
  ).toRenderTo(`
31
50
  ${mod} class TestClass;
32
51
  `);
@@ -34,9 +53,9 @@ describe("modifiers", () => {
34
53
 
35
54
  it.each(["partial", "abstract", "static", "sealed"])("%s", (mod) => {
36
55
  expect(
37
- <utils.TestNamespace>
56
+ <TestNamespace>
38
57
  <ClassDeclaration {...{ [mod]: true }} name="TestClass" />
39
- </utils.TestNamespace>,
58
+ </TestNamespace>,
40
59
  ).toRenderTo(`
41
60
  ${mod} class TestClass;
42
61
  `);
@@ -44,9 +63,9 @@ describe("modifiers", () => {
44
63
 
45
64
  it("combines modifiers", () => {
46
65
  expect(
47
- <utils.TestNamespace>
66
+ <TestNamespace>
48
67
  <ClassDeclaration public abstract partial name="TestClass" />
49
- </utils.TestNamespace>,
68
+ </TestNamespace>,
50
69
  ).toRenderTo(`
51
70
  public abstract partial class TestClass;
52
71
  `);
@@ -56,9 +75,9 @@ describe("modifiers", () => {
56
75
  describe("base", () => {
57
76
  it("define base class", () => {
58
77
  expect(
59
- <utils.TestNamespace>
60
- <csharp.ClassDeclaration name="TestClass" baseType="Foo" />
61
- </utils.TestNamespace>,
78
+ <TestNamespace>
79
+ <ClassDeclaration name="TestClass" baseType="Foo" />
80
+ </TestNamespace>,
62
81
  ).toRenderTo(`
63
82
  class TestClass : Foo;
64
83
  `);
@@ -66,12 +85,9 @@ describe("base", () => {
66
85
 
67
86
  it("define multiple interface types", () => {
68
87
  expect(
69
- <utils.TestNamespace>
70
- <csharp.ClassDeclaration
71
- name="TestClass"
72
- interfaceTypes={["Foo", "Bar"]}
73
- />
74
- </utils.TestNamespace>,
88
+ <TestNamespace>
89
+ <ClassDeclaration name="TestClass" interfaceTypes={["Foo", "Bar"]} />
90
+ </TestNamespace>,
75
91
  ).toRenderTo(`
76
92
  class TestClass : Foo, Bar;
77
93
  `);
@@ -79,13 +95,13 @@ describe("base", () => {
79
95
 
80
96
  it("define base class and multiple interface types", () => {
81
97
  expect(
82
- <utils.TestNamespace>
83
- <csharp.ClassDeclaration
98
+ <TestNamespace>
99
+ <ClassDeclaration
84
100
  name="TestClass"
85
101
  baseType="BaseClass"
86
102
  interfaceTypes={["Foo", "Bar"]}
87
103
  />
88
- </utils.TestNamespace>,
104
+ </TestNamespace>,
89
105
  ).toRenderTo(`
90
106
  class TestClass : BaseClass, Foo, Bar;
91
107
  `);
@@ -93,13 +109,13 @@ describe("base", () => {
93
109
  });
94
110
 
95
111
  it("declares class with some members", () => {
96
- const res = utils.toSourceText(
97
- <csharp.ClassDeclaration public name="TestClass">
112
+ const res = toSourceText(
113
+ <ClassDeclaration public name="TestClass">
98
114
  <List>
99
115
  <Field public name="MemberOne" type="string" />
100
116
  <Field public name="MemberTwo" type="int" />
101
117
  </List>
102
- </csharp.ClassDeclaration>,
118
+ </ClassDeclaration>,
103
119
  );
104
120
 
105
121
  expect(res).toBe(coretest.d`
@@ -115,13 +131,13 @@ it("declares class with some members", () => {
115
131
  });
116
132
 
117
133
  it("declares class with some methods", () => {
118
- const res = utils.toSourceText(
119
- <csharp.ClassDeclaration public name="TestClass">
120
- <core.List>
121
- <csharp.Method public name="MethodOne" />
122
- <csharp.Method private virtual name="MethodTwo" />
123
- </core.List>
124
- </csharp.ClassDeclaration>,
134
+ const res = toSourceText(
135
+ <ClassDeclaration public name="TestClass">
136
+ <List>
137
+ <Method public name="MethodOne" />
138
+ <Method private virtual name="MethodTwo" />
139
+ </List>
140
+ </ClassDeclaration>,
125
141
  );
126
142
 
127
143
  expect(res).toBe(coretest.d`
@@ -137,9 +153,9 @@ it("declares class with some methods", () => {
137
153
  });
138
154
 
139
155
  it("uses refkeys for members, params, and return type", () => {
140
- const inputTypeRefkey = core.refkey();
141
- const testResultTypeRefkey = core.refkey();
142
- const enumTypeRefkey = core.refkey();
156
+ const inputTypeRefkey = refkey();
157
+ const testResultTypeRefkey = refkey();
158
+ const enumTypeRefkey = refkey();
143
159
 
144
160
  const params = [
145
161
  {
@@ -152,48 +168,40 @@ it("uses refkeys for members, params, and return type", () => {
152
168
  },
153
169
  ];
154
170
 
155
- const res = core.render(
156
- <core.Output namePolicy={csharp.createCSharpNamePolicy()}>
157
- <csharp.Namespace name="TestCode">
158
- <csharp.SourceFile path="Test.cs">
159
- <csharp.EnumDeclaration
160
- public
161
- name="TestEnum"
162
- refkey={enumTypeRefkey}
163
- >
164
- <core.List comma hardline>
165
- <csharp.EnumMember name="One" />
166
- <csharp.EnumMember name="Two" />
167
- </core.List>
168
- </csharp.EnumDeclaration>
171
+ const res = render(
172
+ <Output namePolicy={createCSharpNamePolicy()}>
173
+ <Namespace name="TestCode">
174
+ <SourceFile path="Test.cs">
175
+ <EnumDeclaration public name="TestEnum" refkey={enumTypeRefkey}>
176
+ <List comma hardline>
177
+ <EnumMember name="One" />
178
+ <EnumMember name="Two" />
179
+ </List>
180
+ </EnumDeclaration>
169
181
  <hbr />
170
- <csharp.ClassDeclaration
171
- public
172
- name="TestInput"
173
- refkey={inputTypeRefkey}
174
- />
182
+ <ClassDeclaration public name="TestInput" refkey={inputTypeRefkey} />
175
183
  <hbr />
176
- <csharp.ClassDeclaration
184
+ <ClassDeclaration
177
185
  public
178
186
  name="TestResult"
179
187
  refkey={testResultTypeRefkey}
180
188
  />
181
189
  <hbr />
182
- <csharp.ClassDeclaration public name="TestClass">
190
+ <ClassDeclaration public name="TestClass">
183
191
  <Field private name="MemberOne" type={enumTypeRefkey} />
184
192
  <hbr />
185
- <csharp.Method
193
+ <Method
186
194
  public
187
195
  name="MethodOne"
188
196
  parameters={params}
189
197
  returns={testResultTypeRefkey}
190
198
  >
191
199
  return new {testResultTypeRefkey}();
192
- </csharp.Method>
193
- </csharp.ClassDeclaration>
194
- </csharp.SourceFile>
195
- </csharp.Namespace>
196
- </core.Output>,
200
+ </Method>
201
+ </ClassDeclaration>
202
+ </SourceFile>
203
+ </Namespace>
204
+ </Output>,
197
205
  );
198
206
 
199
207
  expect(findFile(res, "Test.cs").contents).toBe(coretest.d`
@@ -232,7 +240,7 @@ describe("with type parameters", () => {
232
240
  ];
233
241
 
234
242
  expect(
235
- <utils.TestNamespace>
243
+ <TestNamespace>
236
244
  <SourceFile path="Test.cs">
237
245
  <ClassDeclaration
238
246
  public
@@ -245,7 +253,7 @@ describe("with type parameters", () => {
245
253
  </List>
246
254
  </ClassDeclaration>
247
255
  </SourceFile>
248
- </utils.TestNamespace>,
256
+ </TestNamespace>,
249
257
  ).toRenderTo(`
250
258
  namespace TestCode
251
259
  {
@@ -271,7 +279,7 @@ describe("with type parameters", () => {
271
279
  ];
272
280
 
273
281
  expect(
274
- <utils.TestNamespace>
282
+ <TestNamespace>
275
283
  <ClassDeclaration
276
284
  public
277
285
  name="TestClass"
@@ -279,7 +287,7 @@ describe("with type parameters", () => {
279
287
  >
280
288
  // Body
281
289
  </ClassDeclaration>
282
- </utils.TestNamespace>,
290
+ </TestNamespace>,
283
291
  ).toRenderTo(`
284
292
  public class TestClass<T, U>
285
293
  where T : IFoo
@@ -293,25 +301,26 @@ describe("with type parameters", () => {
293
301
 
294
302
  it("declares class with invalid members", () => {
295
303
  const decl = (
296
- <csharp.ClassDeclaration public name="TestClass">
297
- <csharp.EnumMember name="One" />,<hbr />
298
- <csharp.EnumMember name="Two" />
299
- </csharp.ClassDeclaration>
304
+ <ClassDeclaration public name="TestClass">
305
+ <EnumMember name="One" />,<hbr />
306
+ <EnumMember name="Two" />
307
+ </ClassDeclaration>
300
308
  );
301
309
 
302
- expect(() => utils.toSourceText(decl)).toThrow(
310
+ expect(() => toSourceText(decl)).toThrow(
303
311
  "can't define an enum member outside of an enum-decl scope",
304
312
  );
305
313
  });
306
314
 
307
- it("declares class with constructor", () => {
308
- const res = utils.toSourceText(
309
- <csharp.ClassDeclaration public name="TestClass">
310
- <Constructor public />
311
- </csharp.ClassDeclaration>,
312
- );
315
+ describe("constructor", () => {
316
+ it("declares with constructor", () => {
317
+ const res = toSourceText(
318
+ <ClassDeclaration public name="TestClass">
319
+ <Constructor public />
320
+ </ClassDeclaration>,
321
+ );
313
322
 
314
- expect(res).toBe(coretest.d`
323
+ expect(res).toBe(coretest.d`
315
324
  namespace TestCode
316
325
  {
317
326
  public class TestClass
@@ -320,43 +329,43 @@ it("declares class with constructor", () => {
320
329
  }
321
330
  }
322
331
  `);
323
- });
332
+ });
324
333
 
325
- it("declares class with constructor params and assigns values to fields", () => {
326
- const thisNameRefkey = core.refkey();
327
- const thisSizeRefkey = core.refkey();
328
- const paramNameRefkey = core.refkey();
329
- const paramSizeRefkey = core.refkey();
334
+ it("declares with constructor params and assigns values to fields", () => {
335
+ const thisNameRefkey = refkey();
336
+ const thisSizeRefkey = refkey();
337
+ const paramNameRefkey = refkey();
338
+ const paramSizeRefkey = refkey();
330
339
 
331
- const ctorParams = [
332
- {
333
- name: "name",
334
- type: "string",
335
- refkey: paramNameRefkey,
336
- },
337
- {
338
- name: "size",
339
- type: "int",
340
- refkey: paramSizeRefkey,
341
- },
342
- ];
340
+ const ctorParams = [
341
+ {
342
+ name: "name",
343
+ type: "string",
344
+ refkey: paramNameRefkey,
345
+ },
346
+ {
347
+ name: "size",
348
+ type: "int",
349
+ refkey: paramSizeRefkey,
350
+ },
351
+ ];
343
352
 
344
- const res = utils.toSourceText(
345
- <csharp.ClassDeclaration public name="TestClass">
346
- <Field private name="name" type="string" refkey={thisNameRefkey} />
347
- <hbr />
348
- <Field private name="size" type="int" refkey={thisSizeRefkey} />
349
- <hbr />
350
- <Constructor public parameters={ctorParams}>
351
- {thisNameRefkey} = {paramNameRefkey};<hbr />
352
- {thisSizeRefkey} = {paramSizeRefkey};
353
- </Constructor>
354
- </csharp.ClassDeclaration>,
355
- );
353
+ const res = toSourceText(
354
+ <ClassDeclaration public name="TestClass">
355
+ <Field private name="name" type="string" refkey={thisNameRefkey} />
356
+ <hbr />
357
+ <Field private name="size" type="int" refkey={thisSizeRefkey} />
358
+ <hbr />
359
+ <Constructor public parameters={ctorParams}>
360
+ {thisNameRefkey} = {paramNameRefkey};<hbr />
361
+ {thisSizeRefkey} = {paramSizeRefkey};
362
+ </Constructor>
363
+ </ClassDeclaration>,
364
+ );
356
365
 
357
- // TODO: assignments to members should have this. prefix
358
- // e.g. this.name = name;
359
- expect(res).toBe(coretest.d`
366
+ // TODO: assignments to members should have this. prefix
367
+ // e.g. this.name = name;
368
+ expect(res).toBe(coretest.d`
360
369
  namespace TestCode
361
370
  {
362
371
  public class TestClass
@@ -371,13 +380,83 @@ it("declares class with constructor params and assigns values to fields", () =>
371
380
  }
372
381
  }
373
382
  `);
383
+ });
384
+
385
+ it("declares primary constructor with args", () => {
386
+ const paramNameRefkey = refkey();
387
+ const paramSizeRefkey = refkey();
388
+
389
+ const ctorParams = [
390
+ {
391
+ name: "name",
392
+ type: "string",
393
+ refkey: paramNameRefkey,
394
+ },
395
+ {
396
+ name: "size",
397
+ type: "int",
398
+ refkey: paramSizeRefkey,
399
+ },
400
+ ];
401
+
402
+ expect(
403
+ <Wrapper>
404
+ <ClassDeclaration
405
+ public
406
+ name="TestClass"
407
+ primaryConstructor={ctorParams}
408
+ >
409
+ <Property
410
+ name="PrettyName"
411
+ type="string"
412
+ get
413
+ initializer={code`$"{${paramNameRefkey}} {${paramSizeRefkey}}"`}
414
+ />
415
+ </ClassDeclaration>
416
+ </Wrapper>,
417
+ ).toRenderTo(`
418
+ namespace TestCode
419
+ {
420
+ public class TestClass(string name, int size)
421
+ {
422
+ string PrettyName { get; } = $"{name} {size}";
423
+ }
424
+ }
425
+ `);
426
+ });
427
+
428
+ it("primary constructor params conflict with method", () => {
429
+ const ctorParams = [{ name: "name", type: "string" }];
430
+
431
+ expect(
432
+ <Wrapper>
433
+ <NamePolicyContext.Provider value={createNamePolicy((x) => x)}>
434
+ <ClassDeclaration
435
+ public
436
+ name="TestClass"
437
+ primaryConstructor={ctorParams}
438
+ >
439
+ <Field name="name" type="string" />
440
+ </ClassDeclaration>
441
+ </NamePolicyContext.Provider>
442
+ </Wrapper>,
443
+ ).toRenderTo(`
444
+ namespace TestCode
445
+ {
446
+ public class TestClass(string name)
447
+ {
448
+ string name_2;
449
+ }
450
+ }
451
+ `);
452
+ });
374
453
  });
375
454
 
376
455
  it("specify doc comment", () => {
377
456
  expect(
378
- <utils.TestNamespace>
457
+ <TestNamespace>
379
458
  <ClassDeclaration name="Test" doc="This is a test" />
380
- </utils.TestNamespace>,
459
+ </TestNamespace>,
381
460
  ).toRenderTo(`
382
461
  /// This is a test
383
462
  class Test;
@@ -386,11 +465,11 @@ it("specify doc comment", () => {
386
465
 
387
466
  it("supports class member doc comments", () => {
388
467
  expect(
389
- <utils.TestNamespace>
468
+ <TestNamespace>
390
469
  <ClassDeclaration name="Test" doc="This is a test">
391
470
  <Field name="Member" public type="int" doc="This is a member" />
392
471
  </ClassDeclaration>
393
- </utils.TestNamespace>,
472
+ </TestNamespace>,
394
473
  ).toRenderTo(`
395
474
  /// This is a test
396
475
  class Test
@@ -403,9 +482,9 @@ it("supports class member doc comments", () => {
403
482
 
404
483
  it("specify attributes", () => {
405
484
  expect(
406
- <utils.TestNamespace>
485
+ <TestNamespace>
407
486
  <ClassDeclaration name="Test" attributes={[<Attribute name="Test" />]} />
408
- </utils.TestNamespace>,
487
+ </TestNamespace>,
409
488
  ).toRenderTo(`
410
489
  [Test]
411
490
  class Test;
@@ -1,20 +1,28 @@
1
- import * as core from "@alloy-js/core";
2
- import { join } from "@alloy-js/core";
1
+ import {
2
+ Block,
3
+ Children,
4
+ Declaration,
5
+ DeclarationProps,
6
+ join,
7
+ Name,
8
+ Refkey,
9
+ Scope,
10
+ } from "@alloy-js/core";
3
11
  import {
4
12
  AccessModifiers,
5
13
  computeModifiersPrefix,
6
14
  getAccessModifier,
7
15
  makeModifiers,
8
- } from "../modifiers.js";
9
- import { useCSharpNamePolicy } from "../name-policy.js";
10
- import { CSharpOutputSymbol } from "../symbols/csharp-output-symbol.js";
11
- import { CSharpMemberScope } from "../symbols/scopes.js";
12
- import { AttributeList, AttributesProp } from "./attributes/attributes.jsx";
13
- import { DocWhen } from "./doc/comment.jsx";
14
- import { Name } from "./Name.jsx";
15
- import { TypeParameterConstraints } from "./type-parameters/type-parameter-constraints.jsx";
16
- import { TypeParameterProps } from "./type-parameters/type-parameter.jsx";
17
- import { TypeParameters } from "./type-parameters/type-parameters.jsx";
16
+ } from "../../modifiers.js";
17
+ import { useCSharpNamePolicy } from "../../name-policy.js";
18
+ import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
19
+ import { CSharpMemberScope } from "../../symbols/scopes.js";
20
+ import { AttributeList, AttributesProp } from "../attributes/attributes.jsx";
21
+ import { DocWhen } from "../doc/comment.jsx";
22
+ import { ParameterProps, Parameters } from "../parameters/parameters.jsx";
23
+ import { TypeParameterConstraints } from "../type-parameters/type-parameter-constraints.jsx";
24
+ import { TypeParameterProps } from "../type-parameters/type-parameter.jsx";
25
+ import { TypeParameters } from "../type-parameters/type-parameters.jsx";
18
26
 
19
27
  export interface ClassModifiers {
20
28
  readonly abstract?: boolean;
@@ -32,13 +40,13 @@ const getClassModifiers = makeModifiers<ClassModifiers>([
32
40
 
33
41
  // properties for creating a class
34
42
  export interface ClassDeclarationProps
35
- extends Omit<core.DeclarationProps, "nameKind">,
43
+ extends Omit<DeclarationProps, "nameKind">,
36
44
  AccessModifiers,
37
45
  ClassModifiers {
38
46
  name: string;
39
47
  /** Doc comment */
40
- doc?: core.Children;
41
- refkey?: core.Refkey;
48
+ doc?: Children;
49
+ refkey?: Refkey;
42
50
 
43
51
  /**
44
52
  * Type parameters for the class
@@ -55,10 +63,10 @@ export interface ClassDeclarationProps
55
63
  typeParameters?: (string | TypeParameterProps)[];
56
64
 
57
65
  /** Base class that this class extends */
58
- baseType?: core.Children;
66
+ baseType?: Children;
59
67
 
60
68
  /** Interfaces this class implements */
61
- interfaceTypes?: core.Children[];
69
+ interfaceTypes?: Children[];
62
70
 
63
71
  /**
64
72
  * Define attributes to attach
@@ -77,6 +85,24 @@ export interface ClassDeclarationProps
77
85
  * ```
78
86
  */
79
87
  attributes?: AttributesProp;
88
+
89
+ /**
90
+ * Set the primary constructor parameters
91
+ * @example
92
+ * ```tsx
93
+ * <ClassDeclaration name="MyClass" primaryConstructor={[
94
+ * {name: "value", type: "int"}
95
+ * ]}>
96
+ * ```
97
+ * This will produce:
98
+ * ```csharp
99
+ * public class MyClass(int value)
100
+ * {
101
+ *
102
+ * }
103
+ * ```
104
+ */
105
+ primaryConstructor?: ParameterProps[];
80
106
  }
81
107
 
82
108
  /**
@@ -129,23 +155,28 @@ export function ClassDeclaration(props: ClassDeclarationProps) {
129
155
  getClassModifiers(props),
130
156
  ]);
131
157
  return (
132
- <core.Declaration symbol={thisClassSymbol}>
158
+ <Declaration symbol={thisClassSymbol}>
133
159
  <DocWhen doc={props.doc} />
134
160
  <AttributeList attributes={props.attributes} endline />
135
161
  {modifiers}class <Name />
136
162
  {props.typeParameters && (
137
163
  <TypeParameters parameters={props.typeParameters} />
138
164
  )}
165
+ {props.primaryConstructor && (
166
+ <Scope value={thisClassScope}>
167
+ <Parameters parameters={props.primaryConstructor} />
168
+ </Scope>
169
+ )}
139
170
  {base}
140
171
  {props.typeParameters && (
141
172
  <TypeParameterConstraints parameters={props.typeParameters} />
142
173
  )}
143
174
  {!props.children && ";"}
144
175
  {props.children && (
145
- <core.Block newline>
146
- <core.Scope value={thisClassScope}>{props.children}</core.Scope>
147
- </core.Block>
176
+ <Block newline>
177
+ <Scope value={thisClassScope}>{props.children}</Scope>
178
+ </Block>
148
179
  )}
149
- </core.Declaration>
180
+ </Declaration>
150
181
  );
151
182
  }
@@ -1,7 +1,7 @@
1
1
  import { refkey } from "@alloy-js/core";
2
2
  import { expect, it } from "vitest";
3
3
  import { TestNamespace } from "../../../test/utils.jsx";
4
- import { ClassDeclaration } from "../ClassDeclaration.jsx";
4
+ import { ClassDeclaration } from "../class/declaration.jsx";
5
5
  import { SourceFile } from "../SourceFile.jsx";
6
6
  import { Constructor } from "./constructor.jsx";
7
7