@alloy-js/csharp 0.17.0 → 0.18.0-dev.11
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 +57 -0
- package/dist/src/components/ClassDeclaration.d.ts.map +1 -0
- package/dist/src/components/{Class.js → ClassDeclaration.js} +42 -53
- package/dist/src/components/ClassMethod.d.ts +25 -0
- package/dist/src/components/ClassMethod.d.ts.map +1 -0
- package/dist/src/components/ClassMethod.js +60 -0
- package/dist/src/components/EnumDeclaration.d.ts +34 -0
- package/dist/src/components/EnumDeclaration.d.ts.map +1 -0
- package/dist/src/components/{Enum.js → EnumDeclaration.js} +25 -5
- package/dist/src/components/class/property.d.ts +55 -0
- package/dist/src/components/class/property.d.ts.map +1 -0
- package/dist/src/components/class/property.js +67 -0
- package/dist/src/components/class/property.test.d.ts +2 -0
- package/dist/src/components/class/property.test.d.ts.map +1 -0
- package/dist/src/components/class/property.test.js +201 -0
- package/dist/src/components/doc/comment.d.ts +70 -0
- package/dist/src/components/doc/comment.d.ts.map +1 -0
- package/dist/src/components/doc/comment.js +88 -0
- package/dist/src/components/doc/comment.test.d.ts +2 -0
- package/dist/src/components/doc/comment.test.d.ts.map +1 -0
- package/dist/src/components/doc/comment.test.js +348 -0
- package/dist/src/components/doc/from-markdown.d.ts +6 -0
- package/dist/src/components/doc/from-markdown.d.ts.map +1 -0
- package/dist/src/components/doc/from-markdown.js +58 -0
- package/dist/src/components/doc/from-markdown.test.d.ts +2 -0
- package/dist/src/components/doc/from-markdown.test.d.ts.map +1 -0
- package/dist/src/components/doc/from-markdown.test.js +83 -0
- package/dist/src/components/index.d.ts +9 -2
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +9 -2
- package/dist/src/components/interface/declaration.d.ts +34 -0
- package/dist/src/components/interface/declaration.d.ts.map +1 -0
- package/dist/src/components/interface/declaration.js +90 -0
- package/dist/src/components/interface/declaration.test.d.ts +2 -0
- package/dist/src/components/interface/declaration.test.d.ts.map +1 -0
- package/dist/src/components/interface/declaration.test.js +69 -0
- package/dist/src/components/interface/method.d.ts +18 -0
- package/dist/src/components/interface/method.d.ts.map +1 -0
- package/dist/src/components/interface/method.js +59 -0
- package/dist/src/components/interface/method.test.d.ts +2 -0
- package/dist/src/components/interface/method.test.d.ts.map +1 -0
- package/dist/src/components/interface/method.test.js +131 -0
- package/dist/src/components/interface/property.d.ts +38 -0
- package/dist/src/components/interface/property.d.ts.map +1 -0
- package/dist/src/components/interface/property.js +67 -0
- package/dist/src/components/interface/property.test.d.ts +2 -0
- package/dist/src/components/interface/property.test.d.ts.map +1 -0
- package/dist/src/components/interface/property.test.js +165 -0
- package/dist/src/components/stc/index.d.ts +2 -2
- package/dist/src/components/stc/index.d.ts.map +1 -1
- package/dist/src/components/stc/index.js +2 -2
- package/dist/src/modifiers.d.ts +13 -4
- package/dist/src/modifiers.d.ts.map +1 -1
- package/dist/src/modifiers.js +13 -27
- 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.d.ts +2 -0
- package/dist/test/class-declaration.test.d.ts.map +1 -0
- package/dist/test/{class.test.js → class-declaration.test.js} +123 -73
- package/dist/test/class-method.test.d.ts +2 -0
- package/dist/test/class-method.test.d.ts.map +1 -0
- package/dist/test/class-method.test.js +161 -0
- package/dist/test/enum.test.js +12 -12
- package/dist/test/namespace.test.js +8 -8
- package/dist/test/project-directory.test.d.ts +2 -0
- package/dist/test/project-directory.test.d.ts.map +1 -0
- package/dist/test/{projectdirectory.test.js → project-directory.test.js} +8 -8
- package/dist/test/sourcefile.test.js +4 -4
- package/dist/test/using.test.js +9 -9
- package/dist/test/utils.d.ts +3 -0
- package/dist/test/utils.d.ts.map +1 -1
- package/dist/test/utils.js +15 -0
- 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/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/src/components/{Class.tsx → ClassDeclaration.tsx} +68 -66
- package/src/components/ClassMethod.tsx +94 -0
- package/src/components/{Enum.tsx → EnumDeclaration.tsx} +30 -6
- package/src/components/class/property.test.tsx +180 -0
- package/src/components/class/property.tsx +135 -0
- package/src/components/doc/comment.test.tsx +337 -0
- package/src/components/doc/comment.tsx +152 -0
- package/src/components/doc/from-markdown.test.tsx +103 -0
- package/src/components/doc/from-markdown.tsx +58 -0
- package/src/components/index.ts +9 -2
- package/src/components/interface/declaration.test.tsx +56 -0
- package/src/components/interface/declaration.tsx +109 -0
- package/src/components/interface/method.test.tsx +120 -0
- package/src/components/interface/method.tsx +82 -0
- package/src/components/interface/property.test.tsx +144 -0
- package/src/components/interface/property.tsx +107 -0
- package/src/components/stc/index.ts +2 -2
- package/src/modifiers.ts +32 -37
- package/src/name-policy.ts +2 -0
- package/temp/api.json +4419 -567
- package/test/{class.test.tsx → class-declaration.test.tsx} +103 -99
- package/test/class-method.test.tsx +147 -0
- package/test/enum.test.tsx +11 -11
- package/test/namespace.test.tsx +4 -4
- package/test/{projectdirectory.test.tsx → project-directory.test.tsx} +4 -4
- package/test/sourcefile.test.tsx +2 -2
- package/test/using.test.tsx +9 -9
- package/test/utils.tsx +9 -0
- package/test/vitest.setup.ts +1 -0
- package/tsconfig.json +2 -1
- package/vitest.config.ts +3 -0
- package/dist/src/components/Class.d.ts +0 -36
- package/dist/src/components/Class.d.ts.map +0 -1
- package/dist/src/components/Enum.d.ts +0 -15
- package/dist/src/components/Enum.d.ts.map +0 -1
- package/dist/test/class.test.d.ts +0 -2
- package/dist/test/class.test.d.ts.map +0 -1
- package/dist/test/projectdirectory.test.d.ts +0 -2
- package/dist/test/projectdirectory.test.d.ts.map +0 -1
|
@@ -1,26 +1,68 @@
|
|
|
1
1
|
import * as core from "@alloy-js/core";
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
AccessModifiers,
|
|
4
|
+
computeModifiersPrefix,
|
|
4
5
|
getAccessModifier,
|
|
5
|
-
|
|
6
|
-
MethodModifier,
|
|
6
|
+
makeModifiers,
|
|
7
7
|
} from "../modifiers.js";
|
|
8
8
|
import { CSharpElements, useCSharpNamePolicy } from "../name-policy.js";
|
|
9
9
|
import { CSharpOutputSymbol } from "../symbols/csharp-output-symbol.js";
|
|
10
10
|
import { CSharpMemberScope, useCSharpScope } from "../symbols/scopes.js";
|
|
11
|
-
import { Name } from "./Name.
|
|
12
|
-
import { ParameterProps, Parameters } from "./Parameters.
|
|
11
|
+
import { Name } from "./Name.jsx";
|
|
12
|
+
import { ParameterProps, Parameters } from "./Parameters.jsx";
|
|
13
|
+
import { DocWhen } from "./doc/comment.jsx";
|
|
14
|
+
|
|
15
|
+
export interface ClassModifiers {
|
|
16
|
+
readonly abstract?: boolean;
|
|
17
|
+
readonly partial?: boolean;
|
|
18
|
+
readonly sealed?: boolean;
|
|
19
|
+
readonly static?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const getClassModifiers = makeModifiers<ClassModifiers>([
|
|
23
|
+
"abstract",
|
|
24
|
+
"partial",
|
|
25
|
+
"sealed",
|
|
26
|
+
"static",
|
|
27
|
+
]);
|
|
13
28
|
|
|
14
29
|
// properties for creating a class
|
|
15
|
-
export interface
|
|
30
|
+
export interface ClassDeclarationProps
|
|
31
|
+
extends Omit<core.DeclarationProps, "nameKind">,
|
|
32
|
+
AccessModifiers,
|
|
33
|
+
ClassModifiers {
|
|
16
34
|
name: string;
|
|
35
|
+
/** Doc comment */
|
|
36
|
+
doc?: core.Children;
|
|
17
37
|
refkey?: core.Refkey;
|
|
18
|
-
accessModifier?: AccessModifier;
|
|
19
38
|
typeParameters?: Record<string, core.Refkey>;
|
|
20
39
|
}
|
|
21
40
|
|
|
22
|
-
|
|
23
|
-
|
|
41
|
+
/**
|
|
42
|
+
* CSharp class declaration.
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* <ClassDeclaration public name="MyClass">
|
|
46
|
+
* <ClassMember public name="MyField" type="int" />
|
|
47
|
+
* <ClassConstructor>
|
|
48
|
+
* <Parameter name="value" type="int" />
|
|
49
|
+
* this.MyField = value;
|
|
50
|
+
* </ClassConstructor>
|
|
51
|
+
* </ClassDeclaration>
|
|
52
|
+
* ```
|
|
53
|
+
* This will produce:
|
|
54
|
+
* ```csharp
|
|
55
|
+
* public class MyClass
|
|
56
|
+
* {
|
|
57
|
+
* public int MyField;
|
|
58
|
+
* public MyClass(int value)
|
|
59
|
+
* {
|
|
60
|
+
* this.MyField = value;
|
|
61
|
+
* }
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export function ClassDeclaration(props: ClassDeclarationProps) {
|
|
24
66
|
const name = useCSharpNamePolicy().getName(props.name!, "class");
|
|
25
67
|
|
|
26
68
|
const thisClassSymbol = new CSharpOutputSymbol(name, {
|
|
@@ -60,9 +102,14 @@ export function Class(props: ClassProps) {
|
|
|
60
102
|
);
|
|
61
103
|
}
|
|
62
104
|
|
|
105
|
+
const modifiers = computeModifiersPrefix([
|
|
106
|
+
getAccessModifier(props),
|
|
107
|
+
getClassModifiers(props),
|
|
108
|
+
]);
|
|
63
109
|
return (
|
|
64
110
|
<core.Declaration symbol={thisClassSymbol}>
|
|
65
|
-
{
|
|
111
|
+
<DocWhen doc={props.doc} />
|
|
112
|
+
{modifiers}class <Name />
|
|
66
113
|
{typeParams}
|
|
67
114
|
{!props.children && ";"}
|
|
68
115
|
{props.children && (
|
|
@@ -74,8 +121,7 @@ export function Class(props: ClassProps) {
|
|
|
74
121
|
);
|
|
75
122
|
}
|
|
76
123
|
|
|
77
|
-
export interface ClassConstructorProps {
|
|
78
|
-
accessModifier?: AccessModifier;
|
|
124
|
+
export interface ClassConstructorProps extends AccessModifiers {
|
|
79
125
|
parameters?: Array<ParameterProps>;
|
|
80
126
|
refkey?: core.Refkey;
|
|
81
127
|
symbol?: core.OutputSymbol;
|
|
@@ -103,7 +149,8 @@ export function ClassConstructor(props: ClassConstructorProps) {
|
|
|
103
149
|
owner: ctorSymbol,
|
|
104
150
|
});
|
|
105
151
|
|
|
106
|
-
const
|
|
152
|
+
const modifiers = computeModifiersPrefix([getAccessModifier(props)]);
|
|
153
|
+
|
|
107
154
|
const params =
|
|
108
155
|
props.parameters ? <Parameters parameters={props.parameters} /> : "";
|
|
109
156
|
|
|
@@ -111,7 +158,7 @@ export function ClassConstructor(props: ClassConstructorProps) {
|
|
|
111
158
|
return (
|
|
112
159
|
<core.Declaration symbol={ctorSymbol}>
|
|
113
160
|
<core.Scope value={ctorDeclScope}>
|
|
114
|
-
{
|
|
161
|
+
{modifiers}
|
|
115
162
|
<Name />({params})<core.Block newline>{props.children}</core.Block>
|
|
116
163
|
</core.Scope>
|
|
117
164
|
</core.Declaration>
|
|
@@ -119,17 +166,18 @@ export function ClassConstructor(props: ClassConstructorProps) {
|
|
|
119
166
|
}
|
|
120
167
|
|
|
121
168
|
// properties for creating a class member
|
|
122
|
-
export interface ClassMemberProps {
|
|
169
|
+
export interface ClassMemberProps extends AccessModifiers {
|
|
123
170
|
name: string;
|
|
124
171
|
type: core.Children;
|
|
125
|
-
accessModifier?: AccessModifier;
|
|
126
172
|
refkey?: core.Refkey;
|
|
173
|
+
/** Doc comment */
|
|
174
|
+
doc?: core.Children;
|
|
127
175
|
}
|
|
128
176
|
|
|
129
177
|
// a C# class member (i.e. a field within a class like "private int count")
|
|
130
178
|
export function ClassMember(props: ClassMemberProps) {
|
|
131
179
|
let nameElement: CSharpElements = "class-member-private";
|
|
132
|
-
if (props.
|
|
180
|
+
if (props.public) {
|
|
133
181
|
nameElement = "class-member-public";
|
|
134
182
|
}
|
|
135
183
|
const name = useCSharpNamePolicy().getName(props.name, nameElement);
|
|
@@ -145,58 +193,12 @@ export function ClassMember(props: ClassMemberProps) {
|
|
|
145
193
|
refkeys: props.refkey ?? core.refkey(props.name),
|
|
146
194
|
});
|
|
147
195
|
|
|
196
|
+
const modifiers = computeModifiersPrefix([getAccessModifier(props)]);
|
|
148
197
|
return (
|
|
149
198
|
<core.Declaration symbol={memberSymbol}>
|
|
150
|
-
{
|
|
199
|
+
<DocWhen doc={props.doc} />
|
|
200
|
+
{modifiers}
|
|
151
201
|
{props.type} <Name />
|
|
152
202
|
</core.Declaration>
|
|
153
203
|
);
|
|
154
204
|
}
|
|
155
|
-
|
|
156
|
-
// properties for creating a method
|
|
157
|
-
export interface ClassMethodProps {
|
|
158
|
-
name: string;
|
|
159
|
-
refkey?: core.Refkey;
|
|
160
|
-
children?: core.Children;
|
|
161
|
-
accessModifier?: AccessModifier;
|
|
162
|
-
methodModifier?: MethodModifier;
|
|
163
|
-
parameters?: Array<ParameterProps>;
|
|
164
|
-
returns?: core.Children;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// a C# class method
|
|
168
|
-
export function ClassMethod(props: ClassMethodProps) {
|
|
169
|
-
const name = useCSharpNamePolicy().getName(props.name!, "class-method");
|
|
170
|
-
const scope = useCSharpScope();
|
|
171
|
-
if (scope.kind !== "member" || scope.name !== "class-decl") {
|
|
172
|
-
throw new Error("can't define a class method outside of a class scope");
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const methodSymbol = new CSharpOutputSymbol(name, {
|
|
176
|
-
scope,
|
|
177
|
-
refkeys: props.refkey ?? core.refkey(props.name),
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// scope for method declaration
|
|
181
|
-
const methodScope = new CSharpMemberScope("method-decl", {
|
|
182
|
-
owner: methodSymbol,
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
const accessModifier = getAccessModifier(props.accessModifier);
|
|
186
|
-
const methodModifier = getMethodModifier(props.methodModifier);
|
|
187
|
-
const params =
|
|
188
|
-
props.parameters ? <Parameters parameters={props.parameters} /> : "";
|
|
189
|
-
const returns = props.returns ?? "void";
|
|
190
|
-
|
|
191
|
-
// note that scope wraps the method decl so that the params get the correct scope
|
|
192
|
-
return (
|
|
193
|
-
<core.Declaration symbol={methodSymbol}>
|
|
194
|
-
<core.Scope value={methodScope}>
|
|
195
|
-
{accessModifier}
|
|
196
|
-
{methodModifier}
|
|
197
|
-
{returns} <Name />({params})
|
|
198
|
-
<core.Block newline>{props.children}</core.Block>
|
|
199
|
-
</core.Scope>
|
|
200
|
-
</core.Declaration>
|
|
201
|
-
);
|
|
202
|
-
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Block,
|
|
3
|
+
Children,
|
|
4
|
+
MemberDeclaration,
|
|
5
|
+
refkey,
|
|
6
|
+
Refkey,
|
|
7
|
+
Scope,
|
|
8
|
+
} from "@alloy-js/core";
|
|
9
|
+
import {
|
|
10
|
+
AccessModifiers,
|
|
11
|
+
computeModifiersPrefix,
|
|
12
|
+
getAccessModifier,
|
|
13
|
+
getAsyncModifier,
|
|
14
|
+
makeModifiers,
|
|
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 { ParameterProps, Parameters } from "./Parameters.jsx";
|
|
20
|
+
import { DocWhen } from "./doc/comment.jsx";
|
|
21
|
+
|
|
22
|
+
/** Method modifiers. Can only be one. */
|
|
23
|
+
export interface ClassMethodModifiers {
|
|
24
|
+
readonly abstract?: boolean;
|
|
25
|
+
readonly sealed?: boolean;
|
|
26
|
+
readonly static?: boolean;
|
|
27
|
+
readonly virtual?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const getMethodModifier = makeModifiers<ClassMethodModifiers>([
|
|
31
|
+
"abstract",
|
|
32
|
+
"sealed",
|
|
33
|
+
"static",
|
|
34
|
+
"virtual",
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
// properties for creating a method
|
|
38
|
+
export interface ClassMethodProps
|
|
39
|
+
extends AccessModifiers,
|
|
40
|
+
ClassMethodModifiers {
|
|
41
|
+
name: string;
|
|
42
|
+
refkey?: Refkey;
|
|
43
|
+
children?: Children;
|
|
44
|
+
parameters?: Array<ParameterProps>;
|
|
45
|
+
returns?: Children;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* If true, the method will be declared as an async method.
|
|
49
|
+
*/
|
|
50
|
+
async?: boolean;
|
|
51
|
+
|
|
52
|
+
/** Doc comment */
|
|
53
|
+
doc?: Children;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// a C# class method
|
|
57
|
+
export function ClassMethod(props: ClassMethodProps) {
|
|
58
|
+
const name = useCSharpNamePolicy().getName(props.name, "class-method");
|
|
59
|
+
const scope = useCSharpScope();
|
|
60
|
+
if (scope.kind !== "member" || scope.name !== "class-decl") {
|
|
61
|
+
throw new Error("can't define a class method outside of a class scope");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const methodSymbol = new CSharpOutputSymbol(name, {
|
|
65
|
+
scope,
|
|
66
|
+
refkeys: props.refkey ?? refkey(props.name),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// scope for method declaration
|
|
70
|
+
const methodScope = new CSharpMemberScope("method-decl", {
|
|
71
|
+
owner: methodSymbol,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const params =
|
|
75
|
+
props.parameters ? <Parameters parameters={props.parameters} /> : "";
|
|
76
|
+
const returns = props.returns ?? (props.async ? "Task" : "void");
|
|
77
|
+
|
|
78
|
+
const modifiers = computeModifiersPrefix([
|
|
79
|
+
getAccessModifier(props),
|
|
80
|
+
getMethodModifier(props),
|
|
81
|
+
getAsyncModifier(props.async),
|
|
82
|
+
]);
|
|
83
|
+
// note that scope wraps the method decl so that the params get the correct scope
|
|
84
|
+
return (
|
|
85
|
+
<MemberDeclaration symbol={methodSymbol}>
|
|
86
|
+
<Scope value={methodScope}>
|
|
87
|
+
<DocWhen doc={props.doc} />
|
|
88
|
+
{modifiers}
|
|
89
|
+
{returns} {name}({params})
|
|
90
|
+
{props.abstract ? ";" : <Block newline>{props.children}</Block>}
|
|
91
|
+
</Scope>
|
|
92
|
+
</MemberDeclaration>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
@@ -1,20 +1,42 @@
|
|
|
1
1
|
import * as core from "@alloy-js/core";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AccessModifiers,
|
|
4
|
+
computeModifiersPrefix,
|
|
5
|
+
getAccessModifier,
|
|
6
|
+
} from "../modifiers.js";
|
|
3
7
|
import { useCSharpNamePolicy } from "../name-policy.js";
|
|
4
8
|
import { CSharpOutputSymbol } from "../symbols/csharp-output-symbol.js";
|
|
5
9
|
import { CSharpMemberScope, useCSharpScope } from "../symbols/scopes.js";
|
|
6
10
|
import { Name } from "./Name.jsx";
|
|
7
11
|
|
|
8
12
|
// properties for creating an enum
|
|
9
|
-
export interface
|
|
13
|
+
export interface EnumDeclarationProps extends AccessModifiers {
|
|
10
14
|
name: string;
|
|
11
15
|
refkey?: core.Refkey;
|
|
12
16
|
children?: core.Children;
|
|
13
|
-
accessModifier?: AccessModifier;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
/**
|
|
20
|
+
* A C# enum declaration
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* <EnumDeclaration public name="Color">
|
|
24
|
+
* <EnumMember name="Red" />
|
|
25
|
+
* <EnumMember name="Green" />
|
|
26
|
+
* <EnumMember name="Blue" />
|
|
27
|
+
* </EnumDeclaration>
|
|
28
|
+
* ```
|
|
29
|
+
* This will produce:
|
|
30
|
+
* ```csharp
|
|
31
|
+
* public enum Color
|
|
32
|
+
* {
|
|
33
|
+
* Red,
|
|
34
|
+
* Green,
|
|
35
|
+
* Blue
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function EnumDeclaration(props: EnumDeclarationProps) {
|
|
18
40
|
const name = useCSharpNamePolicy().getName(props.name!, "enum");
|
|
19
41
|
const scope = useCSharpScope();
|
|
20
42
|
|
|
@@ -32,10 +54,12 @@ export function Enum(props: EnumProps) {
|
|
|
32
54
|
owner: thisEnumSymbol,
|
|
33
55
|
});
|
|
34
56
|
|
|
57
|
+
const modifiers = computeModifiersPrefix([getAccessModifier(props)]);
|
|
58
|
+
|
|
35
59
|
if (thisEnumScope.owner)
|
|
36
60
|
return (
|
|
37
61
|
<core.Declaration symbol={thisEnumSymbol}>
|
|
38
|
-
{
|
|
62
|
+
{modifiers}enum <Name />
|
|
39
63
|
{!props.children && ";"}
|
|
40
64
|
{props.children && (
|
|
41
65
|
<core.Scope value={thisEnumScope}>
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { Children } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { TestNamespace } from "../../../test/utils.jsx";
|
|
4
|
+
import { ClassDeclaration } from "../ClassDeclaration.jsx";
|
|
5
|
+
import { ClassProperty } from "./property.jsx";
|
|
6
|
+
|
|
7
|
+
const Wrapper = (props: { children: Children }) => (
|
|
8
|
+
<TestNamespace>
|
|
9
|
+
<ClassDeclaration public name="TestClass">
|
|
10
|
+
{props.children}
|
|
11
|
+
</ClassDeclaration>
|
|
12
|
+
</TestNamespace>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
describe("modifiers", () => {
|
|
16
|
+
describe("access modifiers", () => {
|
|
17
|
+
it.each(["public", "private", "protected", "internal"] as const)(
|
|
18
|
+
"%s",
|
|
19
|
+
(accessModifier) => {
|
|
20
|
+
expect(
|
|
21
|
+
<Wrapper>
|
|
22
|
+
<ClassProperty
|
|
23
|
+
{...{ [accessModifier]: true }}
|
|
24
|
+
name="TestProp"
|
|
25
|
+
type="string"
|
|
26
|
+
get
|
|
27
|
+
/>
|
|
28
|
+
</Wrapper>,
|
|
29
|
+
).toRenderTo(`
|
|
30
|
+
public class TestClass
|
|
31
|
+
{
|
|
32
|
+
${accessModifier} string TestProp { get; }
|
|
33
|
+
}
|
|
34
|
+
`);
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe("property modifiers", () => {
|
|
40
|
+
it.each([
|
|
41
|
+
"new",
|
|
42
|
+
"static",
|
|
43
|
+
"virtual",
|
|
44
|
+
"sealed",
|
|
45
|
+
"override",
|
|
46
|
+
"abstract",
|
|
47
|
+
"extern",
|
|
48
|
+
"readonly",
|
|
49
|
+
] as const)("%s", (methodModifier) => {
|
|
50
|
+
expect(
|
|
51
|
+
<Wrapper>
|
|
52
|
+
<ClassProperty
|
|
53
|
+
{...{ [methodModifier]: true }}
|
|
54
|
+
name="TestProp"
|
|
55
|
+
type="string"
|
|
56
|
+
get
|
|
57
|
+
/>
|
|
58
|
+
</Wrapper>,
|
|
59
|
+
).toRenderTo(`
|
|
60
|
+
public class TestClass
|
|
61
|
+
{
|
|
62
|
+
${methodModifier} string TestProp { get; }
|
|
63
|
+
}
|
|
64
|
+
`);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("combine modifiers", () => {
|
|
69
|
+
expect(
|
|
70
|
+
<Wrapper>
|
|
71
|
+
<ClassProperty public new name="TestProp" type="string" get />
|
|
72
|
+
</Wrapper>,
|
|
73
|
+
).toRenderTo(`
|
|
74
|
+
public class TestClass
|
|
75
|
+
{
|
|
76
|
+
public new string TestProp { get; }
|
|
77
|
+
}
|
|
78
|
+
`);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("applies PascalCase naming policy", () => {
|
|
83
|
+
expect(
|
|
84
|
+
<Wrapper>
|
|
85
|
+
<ClassProperty name="test_prop" type="string" get />
|
|
86
|
+
</Wrapper>,
|
|
87
|
+
).toRenderTo(`
|
|
88
|
+
public class TestClass
|
|
89
|
+
{
|
|
90
|
+
string TestProp { get; }
|
|
91
|
+
}
|
|
92
|
+
`);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("has getter only", () => {
|
|
96
|
+
expect(
|
|
97
|
+
<Wrapper>
|
|
98
|
+
<ClassProperty name="TestProp" type="string" get />
|
|
99
|
+
</Wrapper>,
|
|
100
|
+
).toRenderTo(`
|
|
101
|
+
public class TestClass
|
|
102
|
+
{
|
|
103
|
+
string TestProp { get; }
|
|
104
|
+
}
|
|
105
|
+
`);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("has setter only", () => {
|
|
109
|
+
expect(
|
|
110
|
+
<Wrapper>
|
|
111
|
+
<ClassProperty name="TestProp" type="string" set />
|
|
112
|
+
</Wrapper>,
|
|
113
|
+
).toRenderTo(`
|
|
114
|
+
public class TestClass
|
|
115
|
+
{
|
|
116
|
+
string TestProp { set; }
|
|
117
|
+
}
|
|
118
|
+
`);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("has getter and setter", () => {
|
|
122
|
+
expect(
|
|
123
|
+
<Wrapper>
|
|
124
|
+
<ClassProperty name="TestProp" type="string" get set />
|
|
125
|
+
</Wrapper>,
|
|
126
|
+
).toRenderTo(`
|
|
127
|
+
public class TestClass
|
|
128
|
+
{
|
|
129
|
+
string TestProp { get; set; }
|
|
130
|
+
}
|
|
131
|
+
`);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("specify doc comment", () => {
|
|
135
|
+
expect(
|
|
136
|
+
<TestNamespace>
|
|
137
|
+
<ClassDeclaration name="Test">
|
|
138
|
+
<ClassProperty
|
|
139
|
+
name="Method"
|
|
140
|
+
type="string"
|
|
141
|
+
get
|
|
142
|
+
set
|
|
143
|
+
doc="This is a test"
|
|
144
|
+
/>
|
|
145
|
+
</ClassDeclaration>
|
|
146
|
+
</TestNamespace>,
|
|
147
|
+
).toRenderTo(`
|
|
148
|
+
class Test
|
|
149
|
+
{
|
|
150
|
+
/// This is a test
|
|
151
|
+
string Method { get; set; }
|
|
152
|
+
}
|
|
153
|
+
`);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("specify nullable property", () => {
|
|
157
|
+
expect(
|
|
158
|
+
<Wrapper>
|
|
159
|
+
<ClassProperty name="TestProp" type="string" nullable get set />
|
|
160
|
+
</Wrapper>,
|
|
161
|
+
).toRenderTo(`
|
|
162
|
+
public class TestClass
|
|
163
|
+
{
|
|
164
|
+
string? TestProp { get; set; }
|
|
165
|
+
}
|
|
166
|
+
`);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("specify initializer", () => {
|
|
170
|
+
expect(
|
|
171
|
+
<Wrapper>
|
|
172
|
+
<ClassProperty name="TestProp" type="string" get set init={`"abc"`} />
|
|
173
|
+
</Wrapper>,
|
|
174
|
+
).toRenderTo(`
|
|
175
|
+
public class TestClass
|
|
176
|
+
{
|
|
177
|
+
string TestProp { get; set; } = "abc";
|
|
178
|
+
}
|
|
179
|
+
`);
|
|
180
|
+
});
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Block,
|
|
3
|
+
Children,
|
|
4
|
+
code,
|
|
5
|
+
List,
|
|
6
|
+
MemberDeclaration,
|
|
7
|
+
refkey,
|
|
8
|
+
Refkey,
|
|
9
|
+
Scope,
|
|
10
|
+
} from "@alloy-js/core";
|
|
11
|
+
import {
|
|
12
|
+
AccessModifiers,
|
|
13
|
+
computeModifiersPrefix,
|
|
14
|
+
getAccessModifier,
|
|
15
|
+
makeModifiers,
|
|
16
|
+
} from "../../modifiers.js";
|
|
17
|
+
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
18
|
+
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
19
|
+
import { CSharpMemberScope, useCSharpScope } from "../../symbols/scopes.js";
|
|
20
|
+
import { DocWhen } from "../doc/comment.jsx";
|
|
21
|
+
|
|
22
|
+
/** Method modifiers. Can only be one. */
|
|
23
|
+
export interface ClassPropertyModifiers {
|
|
24
|
+
readonly new?: boolean;
|
|
25
|
+
readonly static?: boolean;
|
|
26
|
+
readonly virtual?: boolean;
|
|
27
|
+
readonly sealed?: boolean;
|
|
28
|
+
readonly override?: boolean;
|
|
29
|
+
readonly abstract?: boolean;
|
|
30
|
+
readonly extern?: boolean;
|
|
31
|
+
readonly readonly?: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const getModifiers = makeModifiers<ClassPropertyModifiers>([
|
|
35
|
+
"new",
|
|
36
|
+
"static",
|
|
37
|
+
"virtual",
|
|
38
|
+
"sealed",
|
|
39
|
+
"override",
|
|
40
|
+
"abstract",
|
|
41
|
+
"extern",
|
|
42
|
+
"readonly",
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
/** Properties for {@link ClassProperty} component */
|
|
46
|
+
export interface ClassPropertyProps
|
|
47
|
+
extends AccessModifiers,
|
|
48
|
+
ClassPropertyModifiers {
|
|
49
|
+
name: string;
|
|
50
|
+
refkey?: Refkey;
|
|
51
|
+
|
|
52
|
+
/** Property type */
|
|
53
|
+
type: Children;
|
|
54
|
+
|
|
55
|
+
/** If property should have a getter */
|
|
56
|
+
get?: boolean;
|
|
57
|
+
|
|
58
|
+
/** If property should have a setter */
|
|
59
|
+
set?: boolean;
|
|
60
|
+
|
|
61
|
+
/** Doc comment */
|
|
62
|
+
doc?: Children;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Property initializer
|
|
66
|
+
* @example `<ClassProperty name="My" get set nullable />`
|
|
67
|
+
*
|
|
68
|
+
* ```cs
|
|
69
|
+
* int? My { get; set; };
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
nullable?: boolean;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Property initializer
|
|
76
|
+
* @example `<ClassProperty name="My" get set init={42} />`
|
|
77
|
+
*
|
|
78
|
+
* ```cs
|
|
79
|
+
* int My { get; set; } = 42;
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
init?: Children;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Render a C# class property.
|
|
87
|
+
*
|
|
88
|
+
* @example `<ClassProperty public name="My" get set />`
|
|
89
|
+
*
|
|
90
|
+
* ```cs
|
|
91
|
+
* public int My { get; set; };
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export function ClassProperty(props: ClassPropertyProps) {
|
|
95
|
+
const name = useCSharpNamePolicy().getName(props.name, "class-property");
|
|
96
|
+
const scope = useCSharpScope();
|
|
97
|
+
if (scope.kind !== "member" || scope.name !== "class-decl") {
|
|
98
|
+
throw new Error(
|
|
99
|
+
"can't define an interface method outside of an interface scope",
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const propertySymbol = new CSharpOutputSymbol(name, {
|
|
104
|
+
scope,
|
|
105
|
+
refkeys: props.refkey ?? refkey(props.name),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// scope for property declaration
|
|
109
|
+
const propertyScope = new CSharpMemberScope("property-decl", {
|
|
110
|
+
owner: propertySymbol,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const modifiers = computeModifiersPrefix([
|
|
114
|
+
getAccessModifier(props),
|
|
115
|
+
getModifiers(props),
|
|
116
|
+
]);
|
|
117
|
+
// note that scope wraps the method decl so that the params get the correct scope
|
|
118
|
+
return (
|
|
119
|
+
<MemberDeclaration symbol={propertySymbol}>
|
|
120
|
+
<Scope value={propertyScope}>
|
|
121
|
+
<DocWhen doc={props.doc} />
|
|
122
|
+
{modifiers}
|
|
123
|
+
{props.type}
|
|
124
|
+
{props.nullable && "?"} {name}{" "}
|
|
125
|
+
<Block newline inline>
|
|
126
|
+
<List joiner=" ">
|
|
127
|
+
{props.get && "get;"}
|
|
128
|
+
{props.set && "set;"}
|
|
129
|
+
</List>
|
|
130
|
+
</Block>
|
|
131
|
+
{props.init && code` = ${props.init};`}
|
|
132
|
+
</Scope>
|
|
133
|
+
</MemberDeclaration>
|
|
134
|
+
);
|
|
135
|
+
}
|