@alloy-js/csharp 0.18.0-dev.9 → 0.18.0
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/CHANGELOG.md +31 -0
- package/dist/src/components/ClassDeclaration.d.ts +39 -2
- package/dist/src/components/ClassDeclaration.d.ts.map +1 -1
- package/dist/src/components/ClassDeclaration.js +35 -34
- package/dist/src/components/ClassMethod.d.ts +33 -1
- package/dist/src/components/ClassMethod.d.ts.map +1 -1
- package/dist/src/components/ClassMethod.js +22 -7
- package/dist/src/components/SourceFile.d.ts.map +1 -1
- package/dist/src/components/SourceFile.js +1 -0
- package/dist/src/components/attributes/attributes.d.ts +39 -0
- package/dist/src/components/attributes/attributes.d.ts.map +1 -0
- package/dist/src/components/attributes/attributes.js +62 -0
- package/dist/src/components/attributes/attributes.test.d.ts +2 -0
- package/dist/src/components/attributes/attributes.test.d.ts.map +1 -0
- package/dist/src/components/attributes/attributes.test.js +75 -0
- package/dist/src/components/index.d.ts +7 -1
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +8 -2
- package/dist/src/components/interface/declaration.d.ts +32 -1
- package/dist/src/components/interface/declaration.d.ts.map +1 -1
- package/dist/src/components/interface/declaration.js +18 -25
- package/dist/src/components/interface/declaration.test.js +102 -0
- package/dist/src/components/interface/method.d.ts +33 -1
- package/dist/src/components/interface/method.d.ts.map +1 -1
- package/dist/src/components/interface/method.js +22 -7
- package/dist/src/components/interface/method.test.js +169 -0
- package/dist/src/components/interface/property.d.ts +36 -1
- package/dist/src/components/interface/property.d.ts.map +1 -1
- package/dist/src/components/interface/property.js +18 -4
- package/dist/src/components/interface/property.test.js +24 -0
- package/dist/src/components/parameters/parameters.d.ts +19 -0
- package/dist/src/components/parameters/parameters.d.ts.map +1 -0
- package/dist/src/components/parameters/parameters.js +43 -0
- package/dist/src/components/property/property.d.ts +80 -0
- package/dist/src/components/property/property.d.ts.map +1 -0
- package/dist/src/components/property/property.js +76 -0
- package/dist/src/components/property/property.test.d.ts +2 -0
- package/dist/src/components/property/property.test.d.ts.map +1 -0
- package/dist/src/components/property/property.test.js +242 -0
- package/dist/src/components/record/declaration.d.ts +35 -0
- package/dist/src/components/record/declaration.d.ts.map +1 -0
- package/dist/src/components/record/declaration.js +90 -0
- package/dist/src/components/record/declaration.test.d.ts +2 -0
- package/dist/src/components/record/declaration.test.d.ts.map +1 -0
- package/dist/src/components/record/declaration.test.js +94 -0
- package/dist/src/components/type-parameters/type-parameter-constraints.d.ts +8 -0
- package/dist/src/components/type-parameters/type-parameter-constraints.d.ts.map +1 -0
- package/dist/src/components/type-parameters/type-parameter-constraints.js +44 -0
- package/dist/src/components/type-parameters/type-parameter-constraints.test.d.ts +2 -0
- package/dist/src/components/type-parameters/type-parameter-constraints.test.d.ts.map +1 -0
- package/dist/src/components/type-parameters/type-parameter-constraints.test.js +67 -0
- package/dist/src/components/type-parameters/type-parameter.d.ts +20 -0
- package/dist/src/components/type-parameters/type-parameter.d.ts.map +1 -0
- package/dist/src/components/type-parameters/type-parameter.js +22 -0
- package/dist/src/components/type-parameters/type-parameters.d.ts +17 -0
- package/dist/src/components/type-parameters/type-parameters.d.ts.map +1 -0
- package/dist/src/components/type-parameters/type-parameters.js +54 -0
- package/dist/src/components/type-parameters/type-parameters.test.d.ts +2 -0
- package/dist/src/components/type-parameters/type-parameters.test.d.ts.map +1 -0
- package/dist/src/components/type-parameters/type-parameters.test.js +48 -0
- package/dist/src/components/var/declaration.d.ts +35 -0
- package/dist/src/components/var/declaration.d.ts.map +1 -0
- package/dist/src/components/var/declaration.js +40 -0
- package/dist/src/components/var/declaration.test.d.ts +2 -0
- package/dist/src/components/var/declaration.test.d.ts.map +1 -0
- package/dist/src/components/var/declaration.test.js +73 -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.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} +161 -33
- package/dist/test/project-directory.test.d.ts +2 -0
- package/dist/test/project-directory.test.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/src/components/ClassDeclaration.tsx +65 -33
- package/src/components/ClassMethod.tsx +46 -4
- package/src/components/SourceFile.tsx +1 -0
- package/src/components/attributes/attributes.test.tsx +61 -0
- package/src/components/attributes/attributes.tsx +100 -0
- package/src/components/index.ts +7 -1
- package/src/components/interface/declaration.test.tsx +102 -0
- package/src/components/interface/declaration.tsx +43 -27
- package/src/components/interface/method.test.tsx +173 -0
- package/src/components/interface/method.tsx +45 -5
- package/src/components/interface/property.test.tsx +21 -0
- package/src/components/interface/property.tsx +43 -6
- package/src/components/parameters/parameters.tsx +74 -0
- package/src/components/property/property.test.tsx +209 -0
- package/src/components/property/property.tsx +172 -0
- package/src/components/record/declaration.test.tsx +73 -0
- package/src/components/record/declaration.tsx +109 -0
- package/src/components/type-parameters/type-parameter-constraints.test.tsx +93 -0
- package/src/components/type-parameters/type-parameter-constraints.tsx +46 -0
- package/src/components/type-parameters/type-parameter.tsx +35 -0
- package/src/components/type-parameters/type-parameters.test.tsx +46 -0
- package/src/components/type-parameters/type-parameters.tsx +63 -0
- package/src/components/var/declaration.test.tsx +59 -0
- package/src/components/var/declaration.tsx +47 -0
- package/src/name-policy.ts +3 -0
- package/temp/api.json +4722 -2384
- package/test/{class.test.tsx → class-declaration.test.tsx} +144 -26
- package/dist/src/components/Parameters.d.ts +0 -13
- package/dist/src/components/Parameters.d.ts.map +0 -1
- package/dist/src/components/Parameters.js +0 -34
- 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
- package/src/components/Parameters.tsx +0 -51
- /package/dist/test/{projectdirectory.test.js → project-directory.test.js} +0 -0
- /package/test/{projectdirectory.test.tsx → project-directory.test.tsx} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as core from "@alloy-js/core";
|
|
2
|
+
import { join } from "@alloy-js/core";
|
|
2
3
|
import {
|
|
3
4
|
AccessModifiers,
|
|
4
5
|
computeModifiersPrefix,
|
|
@@ -8,9 +9,13 @@ import {
|
|
|
8
9
|
import { CSharpElements, useCSharpNamePolicy } from "../name-policy.js";
|
|
9
10
|
import { CSharpOutputSymbol } from "../symbols/csharp-output-symbol.js";
|
|
10
11
|
import { CSharpMemberScope, useCSharpScope } from "../symbols/scopes.js";
|
|
11
|
-
import {
|
|
12
|
-
import { ParameterProps, Parameters } from "./Parameters.jsx";
|
|
12
|
+
import { AttributeList, AttributesProp } from "./attributes/attributes.jsx";
|
|
13
13
|
import { DocWhen } from "./doc/comment.jsx";
|
|
14
|
+
import { Name } from "./Name.jsx";
|
|
15
|
+
import { ParameterProps, Parameters } from "./parameters/parameters.jsx";
|
|
16
|
+
import { TypeParameterConstraints } from "./type-parameters/type-parameter-constraints.jsx";
|
|
17
|
+
import { TypeParameterProps } from "./type-parameters/type-parameter.jsx";
|
|
18
|
+
import { TypeParameters } from "./type-parameters/type-parameters.jsx";
|
|
14
19
|
|
|
15
20
|
export interface ClassModifiers {
|
|
16
21
|
readonly abstract?: boolean;
|
|
@@ -35,7 +40,44 @@ export interface ClassDeclarationProps
|
|
|
35
40
|
/** Doc comment */
|
|
36
41
|
doc?: core.Children;
|
|
37
42
|
refkey?: core.Refkey;
|
|
38
|
-
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Type parameters for the class
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```tsx
|
|
49
|
+
* <ClassDeclaration name="MyClass" typeParameters={["T"]} />
|
|
50
|
+
* ```
|
|
51
|
+
* This will produce:
|
|
52
|
+
* ```csharp
|
|
53
|
+
* public class MyClass<T>
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
typeParameters?: (string | TypeParameterProps)[];
|
|
57
|
+
|
|
58
|
+
/** Base class that this class extends */
|
|
59
|
+
baseType?: core.Children;
|
|
60
|
+
|
|
61
|
+
/** Interfaces this class implements */
|
|
62
|
+
interfaceTypes?: core.Children[];
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Define attributes to attach
|
|
66
|
+
* @example
|
|
67
|
+
* ```tsx
|
|
68
|
+
* <ClassDeclaration name="MyClass" attributes={[
|
|
69
|
+
* <Attribute name="Test" />
|
|
70
|
+
* <Attribute name="Test2" args={["arg1", "arg2"]} />
|
|
71
|
+
* ]}>
|
|
72
|
+
* ```
|
|
73
|
+
* This will produce:
|
|
74
|
+
* ```csharp
|
|
75
|
+
* [Test]
|
|
76
|
+
* [Test2("arg1", "arg2")]
|
|
77
|
+
* public class MyClass
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
attributes?: AttributesProp;
|
|
39
81
|
}
|
|
40
82
|
|
|
41
83
|
/**
|
|
@@ -77,31 +119,12 @@ export function ClassDeclaration(props: ClassDeclarationProps) {
|
|
|
77
119
|
owner: thisClassSymbol,
|
|
78
120
|
});
|
|
79
121
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
);
|
|
87
|
-
// create a symbol for each type param so its
|
|
88
|
-
// refkey resolves to the type param's name
|
|
89
|
-
new CSharpOutputSymbol(entry[0], {
|
|
90
|
-
scope: thisClassScope,
|
|
91
|
-
refkeys: entry[1],
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
typeParams = (
|
|
95
|
-
<group>
|
|
96
|
-
{"<"}
|
|
97
|
-
<core.For each={typeParamNames} comma line>
|
|
98
|
-
{(name) => name}
|
|
99
|
-
</core.For>
|
|
100
|
-
{">"}
|
|
101
|
-
</group>
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
122
|
+
const bases = [
|
|
123
|
+
...(props.baseType ? [props.baseType] : []),
|
|
124
|
+
...(props.interfaceTypes || []),
|
|
125
|
+
];
|
|
126
|
+
const base =
|
|
127
|
+
bases.length > 0 ? <> : {join(bases, { joiner: ", " })}</> : null;
|
|
105
128
|
const modifiers = computeModifiersPrefix([
|
|
106
129
|
getAccessModifier(props),
|
|
107
130
|
getClassModifiers(props),
|
|
@@ -109,8 +132,15 @@ export function ClassDeclaration(props: ClassDeclarationProps) {
|
|
|
109
132
|
return (
|
|
110
133
|
<core.Declaration symbol={thisClassSymbol}>
|
|
111
134
|
<DocWhen doc={props.doc} />
|
|
135
|
+
<AttributeList attributes={props.attributes} endline />
|
|
112
136
|
{modifiers}class <Name />
|
|
113
|
-
{
|
|
137
|
+
{props.typeParameters && (
|
|
138
|
+
<TypeParameters parameters={props.typeParameters} />
|
|
139
|
+
)}
|
|
140
|
+
{base}
|
|
141
|
+
{props.typeParameters && (
|
|
142
|
+
<TypeParameterConstraints parameters={props.typeParameters} />
|
|
143
|
+
)}
|
|
114
144
|
{!props.children && ";"}
|
|
115
145
|
{props.children && (
|
|
116
146
|
<core.Block newline>
|
|
@@ -151,15 +181,14 @@ export function ClassConstructor(props: ClassConstructorProps) {
|
|
|
151
181
|
|
|
152
182
|
const modifiers = computeModifiersPrefix([getAccessModifier(props)]);
|
|
153
183
|
|
|
154
|
-
const params =
|
|
155
|
-
props.parameters ? <Parameters parameters={props.parameters} /> : "";
|
|
156
|
-
|
|
157
184
|
// note that scope wraps the ctor decl so that the params get the correct scope
|
|
158
185
|
return (
|
|
159
186
|
<core.Declaration symbol={ctorSymbol}>
|
|
160
187
|
<core.Scope value={ctorDeclScope}>
|
|
161
188
|
{modifiers}
|
|
162
|
-
<Name />
|
|
189
|
+
<Name />
|
|
190
|
+
<Parameters parameters={props.parameters} />
|
|
191
|
+
<core.Block newline>{props.children}</core.Block>
|
|
163
192
|
</core.Scope>
|
|
164
193
|
</core.Declaration>
|
|
165
194
|
);
|
|
@@ -170,6 +199,8 @@ export interface ClassMemberProps extends AccessModifiers {
|
|
|
170
199
|
name: string;
|
|
171
200
|
type: core.Children;
|
|
172
201
|
refkey?: core.Refkey;
|
|
202
|
+
/** Doc comment */
|
|
203
|
+
doc?: core.Children;
|
|
173
204
|
}
|
|
174
205
|
|
|
175
206
|
// a C# class member (i.e. a field within a class like "private int count")
|
|
@@ -194,6 +225,7 @@ export function ClassMember(props: ClassMemberProps) {
|
|
|
194
225
|
const modifiers = computeModifiersPrefix([getAccessModifier(props)]);
|
|
195
226
|
return (
|
|
196
227
|
<core.Declaration symbol={memberSymbol}>
|
|
228
|
+
<DocWhen doc={props.doc} />
|
|
197
229
|
{modifiers}
|
|
198
230
|
{props.type} <Name />
|
|
199
231
|
</core.Declaration>
|
|
@@ -16,8 +16,12 @@ import {
|
|
|
16
16
|
import { useCSharpNamePolicy } from "../name-policy.js";
|
|
17
17
|
import { CSharpOutputSymbol } from "../symbols/csharp-output-symbol.js";
|
|
18
18
|
import { CSharpMemberScope, useCSharpScope } from "../symbols/scopes.js";
|
|
19
|
-
import {
|
|
19
|
+
import { AttributeList, AttributesProp } from "./attributes/attributes.jsx";
|
|
20
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";
|
|
21
25
|
|
|
22
26
|
/** Method modifiers. Can only be one. */
|
|
23
27
|
export interface ClassMethodModifiers {
|
|
@@ -51,6 +55,38 @@ export interface ClassMethodProps
|
|
|
51
55
|
|
|
52
56
|
/** Doc comment */
|
|
53
57
|
doc?: Children;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Type parameters for the method
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <InterfaceMethod name="Test" typeParameters={["T"]} />
|
|
65
|
+
* ```
|
|
66
|
+
* This will produce:
|
|
67
|
+
* ```csharp
|
|
68
|
+
* public void Test<T>()
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
typeParameters?: (TypeParameterProps | string)[];
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Define attributes to attach
|
|
75
|
+
* @example
|
|
76
|
+
* ```tsx
|
|
77
|
+
* <ClassMethod name="MyMethod" attributes={[
|
|
78
|
+
* <Attribute name="Test" />
|
|
79
|
+
* <Attribute name="Test2" args={["arg1", "arg2"]} />
|
|
80
|
+
* ]} />
|
|
81
|
+
* ```
|
|
82
|
+
* This will produce:
|
|
83
|
+
* ```csharp
|
|
84
|
+
* [Test]
|
|
85
|
+
* [Test2("arg1", "arg2")]
|
|
86
|
+
* public void MyMethod() { }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
attributes?: AttributesProp;
|
|
54
90
|
}
|
|
55
91
|
|
|
56
92
|
// a C# class method
|
|
@@ -71,8 +107,6 @@ export function ClassMethod(props: ClassMethodProps) {
|
|
|
71
107
|
owner: methodSymbol,
|
|
72
108
|
});
|
|
73
109
|
|
|
74
|
-
const params =
|
|
75
|
-
props.parameters ? <Parameters parameters={props.parameters} /> : "";
|
|
76
110
|
const returns = props.returns ?? (props.async ? "Task" : "void");
|
|
77
111
|
|
|
78
112
|
const modifiers = computeModifiersPrefix([
|
|
@@ -85,8 +119,16 @@ export function ClassMethod(props: ClassMethodProps) {
|
|
|
85
119
|
<MemberDeclaration symbol={methodSymbol}>
|
|
86
120
|
<Scope value={methodScope}>
|
|
87
121
|
<DocWhen doc={props.doc} />
|
|
122
|
+
<AttributeList attributes={props.attributes} endline />
|
|
88
123
|
{modifiers}
|
|
89
|
-
{returns} {name}
|
|
124
|
+
{returns} {name}
|
|
125
|
+
{props.typeParameters && (
|
|
126
|
+
<TypeParameters parameters={props.typeParameters} />
|
|
127
|
+
)}
|
|
128
|
+
<Parameters parameters={props.parameters} />
|
|
129
|
+
{props.typeParameters && (
|
|
130
|
+
<TypeParameterConstraints parameters={props.typeParameters} />
|
|
131
|
+
)}
|
|
90
132
|
{props.abstract ? ";" : <Block newline>{props.children}</Block>}
|
|
91
133
|
</Scope>
|
|
92
134
|
</MemberDeclaration>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { expect, it } from "vitest";
|
|
2
|
+
import { Attribute, AttributeList } from "./attributes.jsx";
|
|
3
|
+
|
|
4
|
+
it("define attribute", () => {
|
|
5
|
+
expect(<Attribute name="Test" />).toRenderTo(`
|
|
6
|
+
[Test]
|
|
7
|
+
`);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("define attribute with single arg", () => {
|
|
11
|
+
expect(<Attribute name="Test" args={[`"abc"`]} />).toRenderTo(`
|
|
12
|
+
[Test("abc")]
|
|
13
|
+
`);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("define attribute with multiple arg", () => {
|
|
17
|
+
expect(<Attribute name="Test" args={[`"abc"`, `"def"`]} />).toRenderTo(`
|
|
18
|
+
[Test("abc", "def")]
|
|
19
|
+
`);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("define attribute list with Attribute components", () => {
|
|
23
|
+
expect(
|
|
24
|
+
<AttributeList
|
|
25
|
+
attributes={[<Attribute name="TestA" />, <Attribute name="TestB" />]}
|
|
26
|
+
/>,
|
|
27
|
+
).toRenderTo(`
|
|
28
|
+
[TestA]
|
|
29
|
+
[TestB]
|
|
30
|
+
`);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("define attribute list with attribute names", () => {
|
|
34
|
+
expect(<AttributeList attributes={["TestA", "TestB"]} />).toRenderTo(`
|
|
35
|
+
[TestA]
|
|
36
|
+
[TestB]
|
|
37
|
+
`);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("define attribute list with attribute props", () => {
|
|
41
|
+
expect(
|
|
42
|
+
<AttributeList
|
|
43
|
+
attributes={[{ name: "TestA" }, { name: "TestB", args: [`"test"`] }]}
|
|
44
|
+
/>,
|
|
45
|
+
).toRenderTo(`
|
|
46
|
+
[TestA]
|
|
47
|
+
[TestB("test")]
|
|
48
|
+
`);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("define attribute list with children", () => {
|
|
52
|
+
expect(
|
|
53
|
+
<AttributeList>
|
|
54
|
+
<Attribute name="TestA" />
|
|
55
|
+
<Attribute name="TestB" />
|
|
56
|
+
</AttributeList>,
|
|
57
|
+
).toRenderTo(`
|
|
58
|
+
[TestA]
|
|
59
|
+
[TestB]
|
|
60
|
+
`);
|
|
61
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Children,
|
|
3
|
+
findKeyedChildren,
|
|
4
|
+
For,
|
|
5
|
+
Indent,
|
|
6
|
+
taggedComponent,
|
|
7
|
+
} from "@alloy-js/core";
|
|
8
|
+
|
|
9
|
+
export interface AttributeItem {
|
|
10
|
+
name: string;
|
|
11
|
+
args?: string[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type AttributesProp = Array<string | AttributeProps | Children>;
|
|
15
|
+
|
|
16
|
+
export interface AttributeListProps {
|
|
17
|
+
/** If the attribute list should finish with a hard line if there is any attribute */
|
|
18
|
+
endline?: boolean;
|
|
19
|
+
attributes?: AttributesProp;
|
|
20
|
+
children?: Children[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Render each attributes in a new line.
|
|
25
|
+
*/
|
|
26
|
+
export function AttributeList(props: AttributeListProps) {
|
|
27
|
+
const attributes =
|
|
28
|
+
props.attributes ??
|
|
29
|
+
(props.children && findKeyedChildren(props.children, Attribute.tag));
|
|
30
|
+
|
|
31
|
+
if (!attributes) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
<For each={attributes} line>
|
|
38
|
+
{(arg) => renderAttribute(arg)}
|
|
39
|
+
</For>
|
|
40
|
+
{props.endline && attributes.length > 0 && <hbr />}
|
|
41
|
+
</>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function renderAttribute(attr: string | AttributeProps | Children): Children {
|
|
46
|
+
if (typeof attr === "string") {
|
|
47
|
+
return <Attribute name={attr} />;
|
|
48
|
+
} else if (typeof attr === "object" && attr && "name" in attr) {
|
|
49
|
+
return <Attribute {...attr} />;
|
|
50
|
+
} else {
|
|
51
|
+
return attr;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface AttributeProps {
|
|
56
|
+
/** Attribute name */
|
|
57
|
+
name: Children;
|
|
58
|
+
|
|
59
|
+
/** Argument */
|
|
60
|
+
args?: Children[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const AttributeTag = Symbol("AttributeTag");
|
|
64
|
+
/**
|
|
65
|
+
* Render a csharp attribute.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* <Attribute name="Test" /><hbr/>
|
|
70
|
+
* <Attribute name="Test" args={["arg1", "arg2"]} />
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* will render:
|
|
74
|
+
* ```csharp
|
|
75
|
+
* [Test]
|
|
76
|
+
* [Test("arg1", "arg2")]
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export const Attribute = taggedComponent(
|
|
80
|
+
AttributeTag,
|
|
81
|
+
(props: AttributeProps) => {
|
|
82
|
+
return (
|
|
83
|
+
<group>
|
|
84
|
+
[{props.name}
|
|
85
|
+
{props.args && props.args.length > 0 && (
|
|
86
|
+
<>
|
|
87
|
+
(
|
|
88
|
+
<Indent softline>
|
|
89
|
+
<For each={props.args ?? []} comma line>
|
|
90
|
+
{(arg) => arg}
|
|
91
|
+
</For>
|
|
92
|
+
</Indent>
|
|
93
|
+
)
|
|
94
|
+
</>
|
|
95
|
+
)}
|
|
96
|
+
]
|
|
97
|
+
</group>
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
);
|
package/src/components/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from "./attributes/attributes.jsx";
|
|
1
2
|
export * from "./ClassDeclaration.jsx";
|
|
2
3
|
export * from "./ClassMethod.jsx";
|
|
3
4
|
export * from "./Declaration.js";
|
|
@@ -6,10 +7,15 @@ export * from "./doc/from-markdown.jsx";
|
|
|
6
7
|
export * from "./EnumDeclaration.jsx";
|
|
7
8
|
export * from "./interface/declaration.js";
|
|
8
9
|
export * from "./interface/method.js";
|
|
10
|
+
export * from "./interface/property.js";
|
|
9
11
|
export * from "./Name.js";
|
|
10
12
|
export * from "./Namespace.js";
|
|
11
|
-
export * from "./
|
|
13
|
+
export * from "./parameters/parameters.jsx";
|
|
12
14
|
export * from "./ProjectDirectory.js";
|
|
15
|
+
export * from "./property/property.jsx";
|
|
16
|
+
export * from "./record/declaration.js";
|
|
13
17
|
export * from "./Reference.js";
|
|
14
18
|
export * from "./SourceFile.js";
|
|
19
|
+
export type { TypeParameterProps } from "./type-parameters/type-parameter.jsx";
|
|
15
20
|
export * from "./UsingDirective.js";
|
|
21
|
+
export * from "./var/declaration.jsx";
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { List, refkey } from "@alloy-js/core";
|
|
1
2
|
import { describe, expect, it } from "vitest";
|
|
2
3
|
import { TestNamespace } from "../../../test/utils.jsx";
|
|
4
|
+
import { Attribute } from "../attributes/attributes.jsx";
|
|
5
|
+
import { SourceFile } from "../SourceFile.jsx";
|
|
6
|
+
import { TypeParameterProps } from "../type-parameters/type-parameter.jsx";
|
|
3
7
|
import { InterfaceDeclaration } from "./declaration.jsx";
|
|
8
|
+
import { InterfaceProperty } from "./property.jsx";
|
|
4
9
|
|
|
5
10
|
it("declares class with no members", () => {
|
|
6
11
|
expect(
|
|
@@ -54,3 +59,100 @@ it("specify doc comment", () => {
|
|
|
54
59
|
interface TestInterface;
|
|
55
60
|
`);
|
|
56
61
|
});
|
|
62
|
+
|
|
63
|
+
describe("with type parameters", () => {
|
|
64
|
+
it("reference parameters", () => {
|
|
65
|
+
const typeParameters: TypeParameterProps[] = [
|
|
66
|
+
{
|
|
67
|
+
name: "T",
|
|
68
|
+
refkey: refkey(),
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "U",
|
|
72
|
+
refkey: refkey(),
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
expect(
|
|
77
|
+
<TestNamespace>
|
|
78
|
+
<SourceFile path="Test.cs">
|
|
79
|
+
<InterfaceDeclaration
|
|
80
|
+
public
|
|
81
|
+
name="Test"
|
|
82
|
+
typeParameters={typeParameters}
|
|
83
|
+
>
|
|
84
|
+
<List>
|
|
85
|
+
<InterfaceProperty
|
|
86
|
+
name="PropA"
|
|
87
|
+
type={typeParameters[0].refkey}
|
|
88
|
+
get
|
|
89
|
+
set
|
|
90
|
+
/>
|
|
91
|
+
<InterfaceProperty
|
|
92
|
+
name="PropB"
|
|
93
|
+
type={typeParameters[1].refkey}
|
|
94
|
+
get
|
|
95
|
+
set
|
|
96
|
+
/>
|
|
97
|
+
</List>
|
|
98
|
+
</InterfaceDeclaration>
|
|
99
|
+
</SourceFile>
|
|
100
|
+
</TestNamespace>,
|
|
101
|
+
).toRenderTo(`
|
|
102
|
+
namespace TestCode
|
|
103
|
+
{
|
|
104
|
+
public interface Test<T, U>
|
|
105
|
+
{
|
|
106
|
+
T PropA { get; set; }
|
|
107
|
+
U PropB { get; set; }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
`);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("defines with constraints", () => {
|
|
114
|
+
const typeParameters: TypeParameterProps[] = [
|
|
115
|
+
{
|
|
116
|
+
name: "T",
|
|
117
|
+
constraints: "IFoo",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "U",
|
|
121
|
+
constraints: "IBar",
|
|
122
|
+
},
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
expect(
|
|
126
|
+
<TestNamespace>
|
|
127
|
+
<InterfaceDeclaration
|
|
128
|
+
public
|
|
129
|
+
name="Test"
|
|
130
|
+
typeParameters={typeParameters}
|
|
131
|
+
>
|
|
132
|
+
// Body
|
|
133
|
+
</InterfaceDeclaration>
|
|
134
|
+
</TestNamespace>,
|
|
135
|
+
).toRenderTo(`
|
|
136
|
+
public interface Test<T, U>
|
|
137
|
+
where T : IFoo
|
|
138
|
+
where U : IBar
|
|
139
|
+
{
|
|
140
|
+
// Body
|
|
141
|
+
}
|
|
142
|
+
`);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("specify attributes", () => {
|
|
147
|
+
expect(
|
|
148
|
+
<TestNamespace>
|
|
149
|
+
<InterfaceDeclaration
|
|
150
|
+
name="Test"
|
|
151
|
+
attributes={[<Attribute name="Test" />]}
|
|
152
|
+
/>
|
|
153
|
+
</TestNamespace>,
|
|
154
|
+
).toRenderTo(`
|
|
155
|
+
[Test]
|
|
156
|
+
interface Test;
|
|
157
|
+
`);
|
|
158
|
+
});
|
|
@@ -8,8 +8,12 @@ import {
|
|
|
8
8
|
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
9
9
|
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
10
10
|
import { CSharpMemberScope } from "../../symbols/scopes.js";
|
|
11
|
+
import { AttributeList, AttributesProp } from "../attributes/attributes.jsx";
|
|
11
12
|
import { DocWhen } from "../doc/comment.jsx";
|
|
12
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";
|
|
13
17
|
|
|
14
18
|
export interface InterfaceModifiers {
|
|
15
19
|
readonly partial?: boolean;
|
|
@@ -27,7 +31,38 @@ export interface InterfaceDeclarationProps
|
|
|
27
31
|
/** Doc comment */
|
|
28
32
|
doc?: core.Children;
|
|
29
33
|
refkey?: core.Refkey;
|
|
30
|
-
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Type parameters for the interface
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```tsx
|
|
40
|
+
* <InterfaceDeclaration name="IList" typeParameters={["T"]} />
|
|
41
|
+
* ```
|
|
42
|
+
* This will produce:
|
|
43
|
+
* ```csharp
|
|
44
|
+
* public interface IList<T>
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
typeParameters?: (TypeParameterProps | string)[];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Define attributes to attach
|
|
51
|
+
* @example
|
|
52
|
+
* ```tsx
|
|
53
|
+
* <InterfaceDeclaration name="MyInterface" attributes={[
|
|
54
|
+
* <Attribute name="Test" />
|
|
55
|
+
* <Attribute name="Test2" args={["arg1", "arg2"]} />
|
|
56
|
+
* ]} />
|
|
57
|
+
* ```
|
|
58
|
+
* This will produce:
|
|
59
|
+
* ```csharp
|
|
60
|
+
* [Test]
|
|
61
|
+
* [Test2("arg1", "arg2")]
|
|
62
|
+
* public interface MyInterface
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
attributes?: AttributesProp;
|
|
31
66
|
}
|
|
32
67
|
|
|
33
68
|
/**
|
|
@@ -65,31 +100,6 @@ export function InterfaceDeclaration(props: InterfaceDeclarationProps) {
|
|
|
65
100
|
owner: thisInterfaceSymbol,
|
|
66
101
|
});
|
|
67
102
|
|
|
68
|
-
let typeParams: core.Children;
|
|
69
|
-
if (props.typeParameters) {
|
|
70
|
-
const typeParamNames = new Array<string>();
|
|
71
|
-
for (const entry of Object.entries(props.typeParameters)) {
|
|
72
|
-
typeParamNames.push(
|
|
73
|
-
useCSharpNamePolicy().getName(entry[0], "type-parameter"),
|
|
74
|
-
);
|
|
75
|
-
// create a symbol for each type param so its
|
|
76
|
-
// refkey resolves to the type param's name
|
|
77
|
-
new CSharpOutputSymbol(entry[0], {
|
|
78
|
-
scope: thisInterfaceScope,
|
|
79
|
-
refkeys: entry[1],
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
typeParams = (
|
|
83
|
-
<group>
|
|
84
|
-
{"<"}
|
|
85
|
-
<core.For each={typeParamNames} comma line>
|
|
86
|
-
{(name) => name}
|
|
87
|
-
</core.For>
|
|
88
|
-
{">"}
|
|
89
|
-
</group>
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
103
|
const modifiers = computeModifiersPrefix([
|
|
94
104
|
getAccessModifier(props),
|
|
95
105
|
getInterfaceModifiers(props),
|
|
@@ -97,8 +107,14 @@ export function InterfaceDeclaration(props: InterfaceDeclarationProps) {
|
|
|
97
107
|
return (
|
|
98
108
|
<core.Declaration symbol={thisInterfaceSymbol}>
|
|
99
109
|
<DocWhen doc={props.doc} />
|
|
110
|
+
<AttributeList attributes={props.attributes} endline />
|
|
100
111
|
{modifiers}interface <Name />
|
|
101
|
-
{
|
|
112
|
+
{props.typeParameters && (
|
|
113
|
+
<TypeParameters parameters={props.typeParameters} />
|
|
114
|
+
)}
|
|
115
|
+
{props.typeParameters && (
|
|
116
|
+
<TypeParameterConstraints parameters={props.typeParameters} />
|
|
117
|
+
)}
|
|
102
118
|
{props.children ?
|
|
103
119
|
<core.Block newline>
|
|
104
120
|
<core.Scope value={thisInterfaceScope}>{props.children}</core.Scope>
|