@alloy-js/csharp 0.19.0-dev.1 → 0.19.0-dev.4
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/components/ClassDeclaration.d.ts +0 -8
- package/dist/src/components/ClassDeclaration.d.ts.map +1 -1
- package/dist/src/components/ClassDeclaration.js +0 -43
- package/dist/src/components/constructor/constructor.d.ts +17 -0
- package/dist/src/components/constructor/constructor.d.ts.map +1 -0
- package/dist/src/components/constructor/constructor.js +47 -0
- package/dist/src/components/constructor/constructor.test.d.ts +2 -0
- package/dist/src/components/constructor/constructor.test.d.ts.map +1 -0
- package/dist/src/components/constructor/constructor.test.js +54 -0
- package/dist/src/components/index.d.ts +3 -1
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +3 -1
- package/dist/src/components/{ClassMethod.d.ts → method/method.d.ts} +22 -8
- package/dist/src/components/method/method.d.ts.map +1 -0
- package/dist/src/components/{ClassMethod.js → method/method.js} +13 -13
- package/dist/src/components/method/method.test.d.ts +2 -0
- package/dist/src/components/method/method.test.d.ts.map +1 -0
- package/dist/{test/class-method.test.js → src/components/method/method.test.js} +33 -10
- package/dist/src/components/property/property.d.ts.map +1 -1
- package/dist/src/components/property/property.js +1 -1
- package/dist/src/components/stc/index.d.ts +3 -2
- package/dist/src/components/stc/index.d.ts.map +1 -1
- package/dist/src/components/stc/index.js +4 -3
- package/dist/src/components/struct/declaration.d.ts +68 -0
- package/dist/src/components/struct/declaration.d.ts.map +1 -0
- package/dist/src/components/struct/declaration.js +78 -0
- package/dist/src/components/struct/declaration.test.d.ts +2 -0
- package/dist/src/components/struct/declaration.test.d.ts.map +1 -0
- package/dist/src/components/struct/declaration.test.js +211 -0
- package/dist/src/name-policy.d.ts +1 -1
- package/dist/src/name-policy.d.ts.map +1 -1
- package/dist/src/name-policy.js +1 -0
- package/dist/test/class-declaration.test.js +6 -5
- package/dist/test/using.test.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/components/ClassDeclaration.tsx +0 -44
- package/src/components/constructor/constructor.test.tsx +41 -0
- package/src/components/constructor/constructor.tsx +67 -0
- package/src/components/index.ts +3 -1
- package/{test/class-method.test.tsx → src/components/method/method.test.tsx} +28 -15
- package/src/components/{ClassMethod.tsx → method/method.tsx} +44 -19
- package/src/components/property/property.tsx +3 -1
- package/src/components/stc/index.ts +3 -2
- package/src/components/struct/declaration.test.tsx +169 -0
- package/src/components/struct/declaration.tsx +129 -0
- package/src/name-policy.ts +2 -0
- package/temp/api.json +3544 -3163
- package/test/class-declaration.test.tsx +8 -7
- package/test/using.test.tsx +1 -1
- package/dist/src/components/ClassMethod.d.ts.map +0 -1
- package/dist/test/class-method.test.d.ts +0 -2
- package/dist/test/class-method.test.d.ts.map +0 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { refkey } from "@alloy-js/core";
|
|
2
|
+
import { expect, it } from "vitest";
|
|
3
|
+
import { TestNamespace } from "../../../test/utils.jsx";
|
|
4
|
+
import { ClassDeclaration } from "../ClassDeclaration.jsx";
|
|
5
|
+
import { SourceFile } from "../SourceFile.jsx";
|
|
6
|
+
import { Constructor } from "./constructor.jsx";
|
|
7
|
+
|
|
8
|
+
it("reference constructor parameters in body", () => {
|
|
9
|
+
const paramNameRefkey = refkey();
|
|
10
|
+
const paramSizeRefkey = refkey();
|
|
11
|
+
|
|
12
|
+
const ctorParams = [
|
|
13
|
+
{ name: "name", type: "string", refkey: paramNameRefkey },
|
|
14
|
+
{ name: "size", type: "int", refkey: paramSizeRefkey },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
expect(
|
|
18
|
+
<TestNamespace>
|
|
19
|
+
<SourceFile path="Test.cs">
|
|
20
|
+
<ClassDeclaration public name="TestClass">
|
|
21
|
+
<Constructor public parameters={ctorParams}>
|
|
22
|
+
{paramNameRefkey};<hbr />
|
|
23
|
+
{paramSizeRefkey};
|
|
24
|
+
</Constructor>
|
|
25
|
+
</ClassDeclaration>
|
|
26
|
+
</SourceFile>
|
|
27
|
+
</TestNamespace>,
|
|
28
|
+
).toRenderTo(`
|
|
29
|
+
namespace TestCode
|
|
30
|
+
{
|
|
31
|
+
public class TestClass
|
|
32
|
+
{
|
|
33
|
+
public TestClass(string name, int size)
|
|
34
|
+
{
|
|
35
|
+
name;
|
|
36
|
+
size;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`);
|
|
41
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Block,
|
|
3
|
+
Declaration,
|
|
4
|
+
Name,
|
|
5
|
+
Refkey,
|
|
6
|
+
refkey,
|
|
7
|
+
Scope,
|
|
8
|
+
} from "@alloy-js/core";
|
|
9
|
+
import { Children } from "@alloy-js/core/jsx-runtime";
|
|
10
|
+
import {
|
|
11
|
+
AccessModifiers,
|
|
12
|
+
computeModifiersPrefix,
|
|
13
|
+
getAccessModifier,
|
|
14
|
+
} from "../../modifiers.js";
|
|
15
|
+
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
16
|
+
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
17
|
+
import { CSharpMemberScope, useCSharpScope } from "../../symbols/scopes.js";
|
|
18
|
+
import { ParameterProps, Parameters } from "../parameters/parameters.jsx";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Properties for {@link Constructor} component.
|
|
22
|
+
*/
|
|
23
|
+
export interface ConstructorProps extends AccessModifiers {
|
|
24
|
+
/** Constructor parameters */
|
|
25
|
+
parameters?: ParameterProps[];
|
|
26
|
+
|
|
27
|
+
/** Refkey */
|
|
28
|
+
refkey?: Refkey;
|
|
29
|
+
|
|
30
|
+
/** Constructor body */
|
|
31
|
+
children?: Children;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function Constructor(props: ConstructorProps) {
|
|
35
|
+
const scope = useCSharpScope();
|
|
36
|
+
if (
|
|
37
|
+
scope.kind !== "member" ||
|
|
38
|
+
(scope.name !== "class-decl" && scope.name !== "struct-decl")
|
|
39
|
+
) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
"can't define a class method outside of a class or struct scope",
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const name = useCSharpNamePolicy().getName(scope.owner!.name, "class-method");
|
|
46
|
+
const ctorSymbol = new CSharpOutputSymbol(name, {
|
|
47
|
+
scope,
|
|
48
|
+
refkeys: props.refkey ?? refkey(name),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const ctorDeclScope = new CSharpMemberScope("constructor-decl", {
|
|
52
|
+
owner: ctorSymbol,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const modifiers = computeModifiersPrefix([getAccessModifier(props)]);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<Declaration symbol={ctorSymbol}>
|
|
59
|
+
<Scope value={ctorDeclScope}>
|
|
60
|
+
{modifiers}
|
|
61
|
+
<Name />
|
|
62
|
+
<Parameters parameters={props.parameters} />
|
|
63
|
+
<Block newline>{props.children}</Block>
|
|
64
|
+
</Scope>
|
|
65
|
+
</Declaration>
|
|
66
|
+
);
|
|
67
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./attributes/attributes.jsx";
|
|
2
2
|
export * from "./ClassDeclaration.jsx";
|
|
3
|
-
export * from "./
|
|
3
|
+
export * from "./constructor/constructor.jsx";
|
|
4
4
|
export * from "./Declaration.js";
|
|
5
5
|
export * from "./doc/comment.jsx";
|
|
6
6
|
export * from "./doc/from-markdown.jsx";
|
|
@@ -8,6 +8,7 @@ export * from "./EnumDeclaration.jsx";
|
|
|
8
8
|
export * from "./interface/declaration.js";
|
|
9
9
|
export * from "./interface/method.js";
|
|
10
10
|
export * from "./interface/property.js";
|
|
11
|
+
export * from "./method/method.jsx";
|
|
11
12
|
export * from "./Name.js";
|
|
12
13
|
export * from "./Namespace.js";
|
|
13
14
|
export * from "./parameters/parameters.jsx";
|
|
@@ -16,6 +17,7 @@ export * from "./property/property.jsx";
|
|
|
16
17
|
export * from "./record/declaration.js";
|
|
17
18
|
export * from "./Reference.js";
|
|
18
19
|
export * from "./SourceFile.js";
|
|
20
|
+
export * from "./struct/declaration.jsx";
|
|
19
21
|
export type { TypeParameterProps } from "./type-parameters/type-parameter.jsx";
|
|
20
22
|
export * from "./UsingDirective.js";
|
|
21
23
|
export * from "./var/declaration.jsx";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Children } from "@alloy-js/core/jsx-runtime";
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { TestNamespace } from "../../../test/utils.jsx";
|
|
4
|
+
import { ClassDeclaration, Method } from "../../index.js";
|
|
5
5
|
|
|
6
6
|
const Wrapper = (props: { children: Children }) => (
|
|
7
7
|
<TestNamespace>
|
|
@@ -18,7 +18,7 @@ describe("modifiers", () => {
|
|
|
18
18
|
(accessModifier) => {
|
|
19
19
|
expect(
|
|
20
20
|
<Wrapper>
|
|
21
|
-
<
|
|
21
|
+
<Method {...{ [accessModifier]: true }} name="MethodOne" />
|
|
22
22
|
</Wrapper>,
|
|
23
23
|
).toRenderTo(`
|
|
24
24
|
public class TestClass
|
|
@@ -36,7 +36,7 @@ describe("modifiers", () => {
|
|
|
36
36
|
(methodModifier) => {
|
|
37
37
|
expect(
|
|
38
38
|
<Wrapper>
|
|
39
|
-
<
|
|
39
|
+
<Method {...{ [methodModifier]: true }} name="MethodOne" />
|
|
40
40
|
</Wrapper>,
|
|
41
41
|
).toRenderTo(`
|
|
42
42
|
public class TestClass
|
|
@@ -50,7 +50,7 @@ describe("modifiers", () => {
|
|
|
50
50
|
it("abstract exclude body", () => {
|
|
51
51
|
expect(
|
|
52
52
|
<Wrapper>
|
|
53
|
-
<
|
|
53
|
+
<Method abstract name="MethodOne" />
|
|
54
54
|
</Wrapper>,
|
|
55
55
|
).toRenderTo(`
|
|
56
56
|
public class TestClass
|
|
@@ -64,7 +64,7 @@ describe("modifiers", () => {
|
|
|
64
64
|
it("mark method async", () => {
|
|
65
65
|
expect(
|
|
66
66
|
<Wrapper>
|
|
67
|
-
<
|
|
67
|
+
<Method async name="MethodOne" />
|
|
68
68
|
</Wrapper>,
|
|
69
69
|
).toRenderTo(`
|
|
70
70
|
public class TestClass
|
|
@@ -77,7 +77,7 @@ describe("modifiers", () => {
|
|
|
77
77
|
it("combine modifiers", () => {
|
|
78
78
|
expect(
|
|
79
79
|
<Wrapper>
|
|
80
|
-
<
|
|
80
|
+
<Method async returns="Task" public abstract name="MethodOne" />
|
|
81
81
|
</Wrapper>,
|
|
82
82
|
).toRenderTo(`
|
|
83
83
|
public class TestClass
|
|
@@ -91,7 +91,7 @@ describe("modifiers", () => {
|
|
|
91
91
|
it("applies PascalCase naming policy", () => {
|
|
92
92
|
expect(
|
|
93
93
|
<Wrapper>
|
|
94
|
-
<
|
|
94
|
+
<Method name="method_one" />
|
|
95
95
|
</Wrapper>,
|
|
96
96
|
).toRenderTo(`
|
|
97
97
|
public class TestClass
|
|
@@ -113,12 +113,7 @@ it("defines params and return type", () => {
|
|
|
113
113
|
];
|
|
114
114
|
const res = (
|
|
115
115
|
<Wrapper>
|
|
116
|
-
<
|
|
117
|
-
public
|
|
118
|
-
name="MethodOne"
|
|
119
|
-
parameters={params}
|
|
120
|
-
returns="string"
|
|
121
|
-
/>
|
|
116
|
+
<Method public name="MethodOne" parameters={params} returns="string" />
|
|
122
117
|
</Wrapper>
|
|
123
118
|
);
|
|
124
119
|
|
|
@@ -134,7 +129,7 @@ it("specify doc comment", () => {
|
|
|
134
129
|
expect(
|
|
135
130
|
<TestNamespace>
|
|
136
131
|
<ClassDeclaration name="Test">
|
|
137
|
-
<
|
|
132
|
+
<Method name="Method" doc="This is a test" />
|
|
138
133
|
</ClassDeclaration>
|
|
139
134
|
</TestNamespace>,
|
|
140
135
|
).toRenderTo(`
|
|
@@ -145,3 +140,21 @@ it("specify doc comment", () => {
|
|
|
145
140
|
}
|
|
146
141
|
`);
|
|
147
142
|
});
|
|
143
|
+
|
|
144
|
+
it("use expression body form", () => {
|
|
145
|
+
expect(
|
|
146
|
+
<TestNamespace>
|
|
147
|
+
<ClassDeclaration name="Test">
|
|
148
|
+
<Method name="Method" doc="This is a test" expression>
|
|
149
|
+
this.MyProperty.Value;
|
|
150
|
+
</Method>
|
|
151
|
+
</ClassDeclaration>
|
|
152
|
+
</TestNamespace>,
|
|
153
|
+
).toRenderTo(`
|
|
154
|
+
class Test
|
|
155
|
+
{
|
|
156
|
+
/// This is a test
|
|
157
|
+
void Method() => this.MyProperty.Value;
|
|
158
|
+
}
|
|
159
|
+
`);
|
|
160
|
+
});
|
|
@@ -12,26 +12,26 @@ import {
|
|
|
12
12
|
getAccessModifier,
|
|
13
13
|
getAsyncModifier,
|
|
14
14
|
makeModifiers,
|
|
15
|
-
} from "
|
|
16
|
-
import { useCSharpNamePolicy } from "
|
|
17
|
-
import { CSharpOutputSymbol } from "
|
|
18
|
-
import { CSharpMemberScope, useCSharpScope } from "
|
|
19
|
-
import { AttributeList, AttributesProp } from "
|
|
20
|
-
import { DocWhen } from "
|
|
21
|
-
import { ParameterProps, Parameters } from "
|
|
22
|
-
import { TypeParameterConstraints } from "
|
|
23
|
-
import { TypeParameterProps } from "
|
|
24
|
-
import { TypeParameters } from "
|
|
15
|
+
} from "../../modifiers.js";
|
|
16
|
+
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
17
|
+
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
18
|
+
import { CSharpMemberScope, useCSharpScope } from "../../symbols/scopes.js";
|
|
19
|
+
import { AttributeList, AttributesProp } from "../attributes/attributes.jsx";
|
|
20
|
+
import { DocWhen } from "../doc/comment.jsx";
|
|
21
|
+
import { ParameterProps, Parameters } from "../parameters/parameters.jsx";
|
|
22
|
+
import { TypeParameterConstraints } from "../type-parameters/type-parameter-constraints.jsx";
|
|
23
|
+
import { TypeParameterProps } from "../type-parameters/type-parameter.jsx";
|
|
24
|
+
import { TypeParameters } from "../type-parameters/type-parameters.jsx";
|
|
25
25
|
|
|
26
26
|
/** Method modifiers. Can only be one. */
|
|
27
|
-
export interface
|
|
27
|
+
export interface MethodModifiers {
|
|
28
28
|
readonly abstract?: boolean;
|
|
29
29
|
readonly sealed?: boolean;
|
|
30
30
|
readonly static?: boolean;
|
|
31
31
|
readonly virtual?: boolean;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const getMethodModifier = makeModifiers<
|
|
34
|
+
const getMethodModifier = makeModifiers<MethodModifiers>([
|
|
35
35
|
"abstract",
|
|
36
36
|
"sealed",
|
|
37
37
|
"static",
|
|
@@ -39,9 +39,7 @@ const getMethodModifier = makeModifiers<ClassMethodModifiers>([
|
|
|
39
39
|
]);
|
|
40
40
|
|
|
41
41
|
// properties for creating a method
|
|
42
|
-
export interface
|
|
43
|
-
extends AccessModifiers,
|
|
44
|
-
ClassMethodModifiers {
|
|
42
|
+
export interface MethodProps extends AccessModifiers, MethodModifiers {
|
|
45
43
|
name: string;
|
|
46
44
|
refkey?: Refkey;
|
|
47
45
|
children?: Children;
|
|
@@ -87,14 +85,34 @@ export interface ClassMethodProps
|
|
|
87
85
|
* ```
|
|
88
86
|
*/
|
|
89
87
|
attributes?: AttributesProp;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Use expression syntax for the method.
|
|
91
|
+
* @example
|
|
92
|
+
* ```tsx
|
|
93
|
+
* <ClassMethod name="MyMethod" lambda>
|
|
94
|
+
* this.MyProperty.Value;
|
|
95
|
+
* </ClassMethod>
|
|
96
|
+
* ```
|
|
97
|
+
* This will produce:
|
|
98
|
+
* ```csharp
|
|
99
|
+
* public void MyMethod() => this.MyProperty.Value;
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
expression?: boolean;
|
|
90
103
|
}
|
|
91
104
|
|
|
92
105
|
// a C# class method
|
|
93
|
-
export function
|
|
106
|
+
export function Method(props: MethodProps) {
|
|
94
107
|
const name = useCSharpNamePolicy().getName(props.name, "class-method");
|
|
95
108
|
const scope = useCSharpScope();
|
|
96
|
-
if (
|
|
97
|
-
|
|
109
|
+
if (
|
|
110
|
+
scope.kind !== "member" ||
|
|
111
|
+
(scope.name !== "class-decl" && scope.name !== "struct-decl")
|
|
112
|
+
) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
"can't define a class method outside of a class or struct scope",
|
|
115
|
+
);
|
|
98
116
|
}
|
|
99
117
|
|
|
100
118
|
const methodSymbol = new CSharpOutputSymbol(name, {
|
|
@@ -129,7 +147,14 @@ export function ClassMethod(props: ClassMethodProps) {
|
|
|
129
147
|
{props.typeParameters && (
|
|
130
148
|
<TypeParameterConstraints parameters={props.typeParameters} />
|
|
131
149
|
)}
|
|
132
|
-
{props.abstract ?
|
|
150
|
+
{props.abstract ?
|
|
151
|
+
";"
|
|
152
|
+
: props.expression ?
|
|
153
|
+
<>
|
|
154
|
+
{" => "}
|
|
155
|
+
{props.children}
|
|
156
|
+
</>
|
|
157
|
+
: <Block newline>{props.children}</Block>}
|
|
133
158
|
</Scope>
|
|
134
159
|
</MemberDeclaration>
|
|
135
160
|
);
|
|
@@ -122,7 +122,9 @@ export function Property(props: PropertyProps) {
|
|
|
122
122
|
const scope = useCSharpScope();
|
|
123
123
|
if (
|
|
124
124
|
scope.kind !== "member" ||
|
|
125
|
-
(scope.name !== "class-decl" &&
|
|
125
|
+
(scope.name !== "class-decl" &&
|
|
126
|
+
scope.name !== "record-decl" &&
|
|
127
|
+
scope.name !== "struct-decl")
|
|
126
128
|
) {
|
|
127
129
|
throw new Error(
|
|
128
130
|
"can't define an interface method outside of an interface scope",
|
|
@@ -2,12 +2,13 @@ import * as core from "@alloy-js/core";
|
|
|
2
2
|
import * as base from "../index.js";
|
|
3
3
|
|
|
4
4
|
export const ClassDeclaration = core.stc(base.ClassDeclaration);
|
|
5
|
-
export const
|
|
5
|
+
export const Constructor = core.stc(base.Constructor);
|
|
6
6
|
export const ClassMember = core.stc(base.ClassMember);
|
|
7
|
-
export const ClassMethod = core.stc(base.
|
|
7
|
+
export const ClassMethod = core.stc(base.Method);
|
|
8
8
|
export const EnumDeclaration = core.stc(base.EnumDeclaration);
|
|
9
9
|
export const EnumMember = core.stc(base.EnumMember);
|
|
10
10
|
export const Parameter = core.stc(base.Parameter);
|
|
11
11
|
export const Parameters = core.stc(base.Parameters);
|
|
12
12
|
export const ProjectDirectory = core.stc(base.ProjectDirectory);
|
|
13
13
|
export const UsingDirective = core.stc(base.UsingDirective);
|
|
14
|
+
export const StructDeclaration = core.stc(base.StructDeclaration);
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { List, refkey } from "@alloy-js/core";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { TestNamespace } from "../../../test/utils.jsx";
|
|
4
|
+
import { Attribute } from "../attributes/attributes.jsx";
|
|
5
|
+
import { Constructor } from "../constructor/constructor.jsx";
|
|
6
|
+
import { Method } from "../method/method.jsx";
|
|
7
|
+
import { Property } from "../property/property.jsx";
|
|
8
|
+
import { SourceFile } from "../SourceFile.jsx";
|
|
9
|
+
import { TypeParameterProps } from "../type-parameters/type-parameter.jsx";
|
|
10
|
+
import { StructDeclaration } from "./declaration.jsx";
|
|
11
|
+
|
|
12
|
+
it("declares struct with no members", () => {
|
|
13
|
+
expect(
|
|
14
|
+
<TestNamespace>
|
|
15
|
+
<StructDeclaration name="Test" />
|
|
16
|
+
</TestNamespace>,
|
|
17
|
+
).toRenderTo(`
|
|
18
|
+
struct Test;
|
|
19
|
+
`);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe("modifiers", () => {
|
|
23
|
+
it.each(["public", "private", "internal"])("%s", (mod) => {
|
|
24
|
+
expect(
|
|
25
|
+
<TestNamespace>
|
|
26
|
+
<StructDeclaration {...{ [mod]: true }} name="Test" />
|
|
27
|
+
</TestNamespace>,
|
|
28
|
+
).toRenderTo(`
|
|
29
|
+
${mod} struct Test;
|
|
30
|
+
`);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it.each(["partial"])("%s", (mod) => {
|
|
34
|
+
expect(
|
|
35
|
+
<TestNamespace>
|
|
36
|
+
<StructDeclaration {...{ [mod]: true }} name="Test" />
|
|
37
|
+
</TestNamespace>,
|
|
38
|
+
).toRenderTo(`
|
|
39
|
+
${mod} struct Test;
|
|
40
|
+
`);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("combines modifiers", () => {
|
|
44
|
+
expect(
|
|
45
|
+
<TestNamespace>
|
|
46
|
+
<StructDeclaration public partial name="Test" />
|
|
47
|
+
</TestNamespace>,
|
|
48
|
+
).toRenderTo(`
|
|
49
|
+
public partial struct Test;
|
|
50
|
+
`);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("specify doc comment", () => {
|
|
55
|
+
expect(
|
|
56
|
+
<TestNamespace>
|
|
57
|
+
<StructDeclaration name="Test" doc="This is a test" />
|
|
58
|
+
</TestNamespace>,
|
|
59
|
+
).toRenderTo(`
|
|
60
|
+
/// This is a test
|
|
61
|
+
struct Test;
|
|
62
|
+
`);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe("with type parameters", () => {
|
|
66
|
+
it("reference parameters", () => {
|
|
67
|
+
const typeParameters: TypeParameterProps[] = [
|
|
68
|
+
{
|
|
69
|
+
name: "T",
|
|
70
|
+
refkey: refkey(),
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "U",
|
|
74
|
+
refkey: refkey(),
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
expect(
|
|
79
|
+
<TestNamespace>
|
|
80
|
+
<SourceFile path="Test.cs">
|
|
81
|
+
<StructDeclaration public name="Test" typeParameters={typeParameters}>
|
|
82
|
+
<List>
|
|
83
|
+
<Property name="PropA" type={typeParameters[0].refkey} get set />
|
|
84
|
+
<Property name="PropB" type={typeParameters[1].refkey} get set />
|
|
85
|
+
</List>
|
|
86
|
+
</StructDeclaration>
|
|
87
|
+
</SourceFile>
|
|
88
|
+
</TestNamespace>,
|
|
89
|
+
).toRenderTo(`
|
|
90
|
+
namespace TestCode
|
|
91
|
+
{
|
|
92
|
+
public struct Test<T, U>
|
|
93
|
+
{
|
|
94
|
+
T PropA { get; set; }
|
|
95
|
+
U PropB { get; set; }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
`);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("defines with constraints", () => {
|
|
102
|
+
const typeParameters: TypeParameterProps[] = [
|
|
103
|
+
{
|
|
104
|
+
name: "T",
|
|
105
|
+
constraints: "IFoo",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "U",
|
|
109
|
+
constraints: "IBar",
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
expect(
|
|
114
|
+
<TestNamespace>
|
|
115
|
+
<StructDeclaration public name="Test" typeParameters={typeParameters}>
|
|
116
|
+
// Body
|
|
117
|
+
</StructDeclaration>
|
|
118
|
+
</TestNamespace>,
|
|
119
|
+
).toRenderTo(`
|
|
120
|
+
public struct Test<T, U>
|
|
121
|
+
where T : IFoo
|
|
122
|
+
where U : IBar
|
|
123
|
+
{
|
|
124
|
+
// Body
|
|
125
|
+
}
|
|
126
|
+
`);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("specify attributes", () => {
|
|
131
|
+
expect(
|
|
132
|
+
<TestNamespace>
|
|
133
|
+
<StructDeclaration name="Test" attributes={[<Attribute name="Test" />]} />
|
|
134
|
+
</TestNamespace>,
|
|
135
|
+
).toRenderTo(`
|
|
136
|
+
[Test]
|
|
137
|
+
struct Test;
|
|
138
|
+
`);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("define methods", () => {
|
|
142
|
+
expect(
|
|
143
|
+
<TestNamespace>
|
|
144
|
+
<StructDeclaration name="Test">
|
|
145
|
+
<Method name="MethodOne" />
|
|
146
|
+
</StructDeclaration>
|
|
147
|
+
</TestNamespace>,
|
|
148
|
+
).toRenderTo(`
|
|
149
|
+
struct Test
|
|
150
|
+
{
|
|
151
|
+
void MethodOne() {}
|
|
152
|
+
}
|
|
153
|
+
`);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("define constructor", () => {
|
|
157
|
+
expect(
|
|
158
|
+
<TestNamespace>
|
|
159
|
+
<StructDeclaration name="Test">
|
|
160
|
+
<Constructor public />
|
|
161
|
+
</StructDeclaration>
|
|
162
|
+
</TestNamespace>,
|
|
163
|
+
).toRenderTo(`
|
|
164
|
+
struct Test
|
|
165
|
+
{
|
|
166
|
+
public Test() {}
|
|
167
|
+
}
|
|
168
|
+
`);
|
|
169
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import * as core from "@alloy-js/core";
|
|
2
|
+
import {
|
|
3
|
+
AccessModifiers,
|
|
4
|
+
computeModifiersPrefix,
|
|
5
|
+
getAccessModifier,
|
|
6
|
+
makeModifiers,
|
|
7
|
+
} from "../../modifiers.js";
|
|
8
|
+
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
9
|
+
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
10
|
+
import { CSharpMemberScope } from "../../symbols/scopes.js";
|
|
11
|
+
import { AttributeList, AttributesProp } from "../attributes/attributes.jsx";
|
|
12
|
+
import { DocWhen } from "../doc/comment.jsx";
|
|
13
|
+
import { Name } from "../Name.jsx";
|
|
14
|
+
import { TypeParameterConstraints } from "../type-parameters/type-parameter-constraints.jsx";
|
|
15
|
+
import { TypeParameterProps } from "../type-parameters/type-parameter.jsx";
|
|
16
|
+
import { TypeParameters } from "../type-parameters/type-parameters.jsx";
|
|
17
|
+
|
|
18
|
+
export interface StructModifiers {
|
|
19
|
+
readonly new?: boolean;
|
|
20
|
+
readonly readonly?: boolean;
|
|
21
|
+
readonly ref?: boolean;
|
|
22
|
+
readonly partial?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const getStructModifiers = makeModifiers<StructModifiers>([
|
|
26
|
+
"new",
|
|
27
|
+
"readonly",
|
|
28
|
+
"ref",
|
|
29
|
+
"partial",
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
// properties for creating a class
|
|
33
|
+
export interface StructDeclarationProps
|
|
34
|
+
extends Omit<core.DeclarationProps, "nameKind">,
|
|
35
|
+
AccessModifiers,
|
|
36
|
+
StructModifiers {
|
|
37
|
+
name: string;
|
|
38
|
+
|
|
39
|
+
/** Doc comment */
|
|
40
|
+
doc?: core.Children;
|
|
41
|
+
refkey?: core.Refkey;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Type parameters for the struct
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* <StructDeclaration name="IList" typeParameters={["T"]} />
|
|
49
|
+
* ```
|
|
50
|
+
* This will produce:
|
|
51
|
+
* ```csharp
|
|
52
|
+
* public struct IList<T>
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
typeParameters?: (TypeParameterProps | string)[];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Define attributes to attach
|
|
59
|
+
* @example
|
|
60
|
+
* ```tsx
|
|
61
|
+
* <StructDeclaration name="MyStruct" attributes={[
|
|
62
|
+
* <Attribute name="Test" />
|
|
63
|
+
* <Attribute name="Test2" args={["arg1", "arg2"]} />
|
|
64
|
+
* ]} />
|
|
65
|
+
* ```
|
|
66
|
+
* This will produce:
|
|
67
|
+
* ```csharp
|
|
68
|
+
* [Test]
|
|
69
|
+
* [Test2("arg1", "arg2")]
|
|
70
|
+
* public struct MyStruct
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
attributes?: AttributesProp;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* CSharp struct declaration.
|
|
78
|
+
* @example
|
|
79
|
+
* ```tsx
|
|
80
|
+
* <StructDeclaration public name="IMyStruct">
|
|
81
|
+
* <StructMember public name="MyProperty" type="int" />
|
|
82
|
+
* <StructMethod public name="MyMethod" returnType="void">
|
|
83
|
+
* <Parameter name="value" type="int" />
|
|
84
|
+
* </StructMethod>
|
|
85
|
+
* </StructDeclaration>
|
|
86
|
+
* ```
|
|
87
|
+
* This will produce:
|
|
88
|
+
* ```csharp
|
|
89
|
+
* public struct MyIface
|
|
90
|
+
* {
|
|
91
|
+
* public int MyProperty { get; set; }
|
|
92
|
+
* public void MyMethod(int value);
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export function StructDeclaration(props: StructDeclarationProps) {
|
|
97
|
+
const name = useCSharpNamePolicy().getName(props.name!, "struct");
|
|
98
|
+
|
|
99
|
+
const thisStructSymbol = new CSharpOutputSymbol(name, {
|
|
100
|
+
refkeys: props.refkey,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const thisStructScope = new CSharpMemberScope("struct-decl", {
|
|
104
|
+
owner: thisStructSymbol,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const modifiers = computeModifiersPrefix([
|
|
108
|
+
getAccessModifier(props),
|
|
109
|
+
getStructModifiers(props),
|
|
110
|
+
]);
|
|
111
|
+
return (
|
|
112
|
+
<core.Declaration symbol={thisStructSymbol}>
|
|
113
|
+
<DocWhen doc={props.doc} />
|
|
114
|
+
<AttributeList attributes={props.attributes} endline />
|
|
115
|
+
{modifiers}struct <Name />
|
|
116
|
+
{props.typeParameters && (
|
|
117
|
+
<TypeParameters parameters={props.typeParameters} />
|
|
118
|
+
)}
|
|
119
|
+
{props.typeParameters && (
|
|
120
|
+
<TypeParameterConstraints parameters={props.typeParameters} />
|
|
121
|
+
)}
|
|
122
|
+
{props.children ?
|
|
123
|
+
<core.Block newline>
|
|
124
|
+
<core.Scope value={thisStructScope}>{props.children}</core.Scope>
|
|
125
|
+
</core.Block>
|
|
126
|
+
: ";"}
|
|
127
|
+
</core.Declaration>
|
|
128
|
+
);
|
|
129
|
+
}
|
package/src/name-policy.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type CSharpElements =
|
|
|
6
6
|
| "class"
|
|
7
7
|
| "constant"
|
|
8
8
|
| "variable"
|
|
9
|
+
| "struct"
|
|
9
10
|
| "enum"
|
|
10
11
|
| "enum-member"
|
|
11
12
|
| "function"
|
|
@@ -23,6 +24,7 @@ export function createCSharpNamePolicy(): core.NamePolicy<CSharpElements> {
|
|
|
23
24
|
return core.createNamePolicy((name, element) => {
|
|
24
25
|
switch (element) {
|
|
25
26
|
case "class":
|
|
27
|
+
case "struct":
|
|
26
28
|
case "enum":
|
|
27
29
|
case "enum-member":
|
|
28
30
|
case "interface":
|