@alloy-js/csharp 0.1.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.
Files changed (125) hide show
  1. package/LICENSE.txt +7 -0
  2. package/api-extractor.json +4 -0
  3. package/babel.config.cjs +4 -0
  4. package/dist/src/components/Class.d.ts +33 -0
  5. package/dist/src/components/Class.d.ts.map +1 -0
  6. package/dist/src/components/Class.js +170 -0
  7. package/dist/src/components/Class.js.map +1 -0
  8. package/dist/src/components/Declaration.d.ts +8 -0
  9. package/dist/src/components/Declaration.d.ts.map +1 -0
  10. package/dist/src/components/Declaration.js +18 -0
  11. package/dist/src/components/Declaration.js.map +1 -0
  12. package/dist/src/components/Enum.d.ts +13 -0
  13. package/dist/src/components/Enum.d.ts.map +1 -0
  14. package/dist/src/components/Enum.js +65 -0
  15. package/dist/src/components/Enum.js.map +1 -0
  16. package/dist/src/components/Name.d.ts +2 -0
  17. package/dist/src/components/Name.d.ts.map +1 -0
  18. package/dist/src/components/Name.js +12 -0
  19. package/dist/src/components/Name.js.map +1 -0
  20. package/dist/src/components/Namespace.d.ts +11 -0
  21. package/dist/src/components/Namespace.d.ts.map +1 -0
  22. package/dist/src/components/Namespace.js +35 -0
  23. package/dist/src/components/Namespace.js.map +1 -0
  24. package/dist/src/components/Parameters.d.ts +13 -0
  25. package/dist/src/components/Parameters.d.ts.map +1 -0
  26. package/dist/src/components/Parameters.js +34 -0
  27. package/dist/src/components/Parameters.js.map +1 -0
  28. package/dist/src/components/ProjectDirectory.d.ts +12 -0
  29. package/dist/src/components/ProjectDirectory.d.ts.map +1 -0
  30. package/dist/src/components/ProjectDirectory.js +48 -0
  31. package/dist/src/components/ProjectDirectory.js.map +1 -0
  32. package/dist/src/components/Reference.d.ts +6 -0
  33. package/dist/src/components/Reference.d.ts.map +1 -0
  34. package/dist/src/components/Reference.js +9 -0
  35. package/dist/src/components/Reference.js.map +1 -0
  36. package/dist/src/components/SourceFile.d.ts +12 -0
  37. package/dist/src/components/SourceFile.d.ts.map +1 -0
  38. package/dist/src/components/SourceFile.js +72 -0
  39. package/dist/src/components/SourceFile.js.map +1 -0
  40. package/dist/src/components/UsingDirective.d.ts +5 -0
  41. package/dist/src/components/UsingDirective.d.ts.map +1 -0
  42. package/dist/src/components/UsingDirective.js +13 -0
  43. package/dist/src/components/UsingDirective.js.map +1 -0
  44. package/dist/src/components/index.d.ts +11 -0
  45. package/dist/src/components/index.d.ts.map +1 -0
  46. package/dist/src/components/index.js +11 -0
  47. package/dist/src/components/index.js.map +1 -0
  48. package/dist/src/components/stc/index.d.ts +43 -0
  49. package/dist/src/components/stc/index.d.ts.map +1 -0
  50. package/dist/src/components/stc/index.js +13 -0
  51. package/dist/src/components/stc/index.js.map +1 -0
  52. package/dist/src/index.d.ts +5 -0
  53. package/dist/src/index.d.ts.map +1 -0
  54. package/dist/src/index.js +5 -0
  55. package/dist/src/index.js.map +1 -0
  56. package/dist/src/modifiers.d.ts +5 -0
  57. package/dist/src/modifiers.d.ts.map +1 -0
  58. package/dist/src/modifiers.js +35 -0
  59. package/dist/src/modifiers.js.map +1 -0
  60. package/dist/src/name-policy.d.ts +5 -0
  61. package/dist/src/name-policy.d.ts.map +1 -0
  62. package/dist/src/name-policy.js +30 -0
  63. package/dist/src/name-policy.js.map +1 -0
  64. package/dist/src/symbols/csharp-output-symbol.d.ts +7 -0
  65. package/dist/src/symbols/csharp-output-symbol.d.ts.map +1 -0
  66. package/dist/src/symbols/csharp-output-symbol.js +20 -0
  67. package/dist/src/symbols/csharp-output-symbol.js.map +1 -0
  68. package/dist/src/symbols/index.d.ts +4 -0
  69. package/dist/src/symbols/index.d.ts.map +1 -0
  70. package/dist/src/symbols/index.js +4 -0
  71. package/dist/src/symbols/index.js.map +1 -0
  72. package/dist/src/symbols/reference.d.ts +3 -0
  73. package/dist/src/symbols/reference.d.ts.map +1 -0
  74. package/dist/src/symbols/reference.js +55 -0
  75. package/dist/src/symbols/reference.js.map +1 -0
  76. package/dist/src/symbols/scopes.d.ts +16 -0
  77. package/dist/src/symbols/scopes.d.ts.map +1 -0
  78. package/dist/src/symbols/scopes.js +37 -0
  79. package/dist/src/symbols/scopes.js.map +1 -0
  80. package/dist/test/class.test.d.ts +2 -0
  81. package/dist/test/class.test.d.ts.map +1 -0
  82. package/dist/test/enum.test.d.ts +2 -0
  83. package/dist/test/enum.test.d.ts.map +1 -0
  84. package/dist/test/namespace.test.d.ts +2 -0
  85. package/dist/test/namespace.test.d.ts.map +1 -0
  86. package/dist/test/projectdirectory.test.d.ts +2 -0
  87. package/dist/test/projectdirectory.test.d.ts.map +1 -0
  88. package/dist/test/sourcefile.test.d.ts +2 -0
  89. package/dist/test/sourcefile.test.d.ts.map +1 -0
  90. package/dist/test/using.test.d.ts +2 -0
  91. package/dist/test/using.test.d.ts.map +1 -0
  92. package/dist/test/utils.d.ts +6 -0
  93. package/dist/test/utils.d.ts.map +1 -0
  94. package/dist/tsconfig.tsbuildinfo +1 -0
  95. package/package.json +51 -0
  96. package/src/components/Class.tsx +210 -0
  97. package/src/components/Declaration.tsx +17 -0
  98. package/src/components/Enum.tsx +74 -0
  99. package/src/components/Name.tsx +11 -0
  100. package/src/components/Namespace.tsx +39 -0
  101. package/src/components/Parameters.tsx +52 -0
  102. package/src/components/ProjectDirectory.tsx +54 -0
  103. package/src/components/Reference.tsx +13 -0
  104. package/src/components/SourceFile.tsx +69 -0
  105. package/src/components/UsingDirective.tsx +19 -0
  106. package/src/components/index.ts +10 -0
  107. package/src/components/stc/index.ts +13 -0
  108. package/src/index.ts +4 -0
  109. package/src/modifiers.ts +45 -0
  110. package/src/name-policy.ts +41 -0
  111. package/src/symbols/csharp-output-symbol.ts +26 -0
  112. package/src/symbols/index.ts +3 -0
  113. package/src/symbols/reference.ts +65 -0
  114. package/src/symbols/scopes.ts +60 -0
  115. package/temp/api.json +3474 -0
  116. package/test/class.test.tsx +249 -0
  117. package/test/enum.test.tsx +147 -0
  118. package/test/namespace.test.tsx +59 -0
  119. package/test/projectdirectory.test.tsx +106 -0
  120. package/test/sourcefile.test.tsx +46 -0
  121. package/test/using.test.tsx +97 -0
  122. package/test/utils.tsx +69 -0
  123. package/tsconfig.json +11 -0
  124. package/tsdoc-metadata.json +11 -0
  125. package/vitest.config.ts +18 -0
@@ -0,0 +1,210 @@
1
+ import * as core from "@alloy-js/core";
2
+ import {
3
+ AccessModifier,
4
+ getAccessModifier,
5
+ getMethodModifier,
6
+ MethodModifier,
7
+ } from "../modifiers.js";
8
+ import { CSharpElements, useCSharpNamePolicy } from "../name-policy.js";
9
+ import { CSharpOutputSymbol } from "../symbols/csharp-output-symbol.js";
10
+ import { createCSharpMemberScope, useCSharpScope } from "../symbols/scopes.js";
11
+ import { Name } from "./Name.js";
12
+ import { ParameterProps, Parameters } from "./Parameters.js";
13
+
14
+ // properties for creating a class
15
+ export interface ClassProps extends Omit<core.DeclarationProps, "nameKind"> {
16
+ name: string;
17
+ accessModifier?: AccessModifier;
18
+ typeParameters?: Record<string, core.Refkey>;
19
+ }
20
+
21
+ // a C# class declaration
22
+ export function Class(props: ClassProps) {
23
+ const name = useCSharpNamePolicy().getName(props.name!, "class");
24
+ const scope = useCSharpScope();
25
+
26
+ const thisClassSymbol = scope.binder.createSymbol<CSharpOutputSymbol>({
27
+ name: name,
28
+ scope,
29
+ refkey: props.refkey ?? core.refkey(props.name),
30
+ });
31
+
32
+ // this creates a new scope for the class definition.
33
+ // members will automatically "inherit" this scope so
34
+ // that refkeys to them will produce the fully-qualified
35
+ // name e.g. Foo.Bar.
36
+ const thisClassScope = createCSharpMemberScope(
37
+ scope.binder,
38
+ scope,
39
+ thisClassSymbol,
40
+ "class-decl",
41
+ );
42
+
43
+ let typeParams: string | undefined;
44
+ if (props.typeParameters) {
45
+ const typeParamNames = new Array<string>();
46
+ for (const entry of Object.entries(props.typeParameters)) {
47
+ typeParamNames.push(
48
+ useCSharpNamePolicy().getName(entry[0], "type-parameter"),
49
+ );
50
+ // create a symbol for each type param so its
51
+ // refkey resolves to the type param's name
52
+ scope.binder.createSymbol<CSharpOutputSymbol>({
53
+ name: entry[0],
54
+ scope: thisClassScope,
55
+ refkey: entry[1],
56
+ });
57
+ }
58
+ typeParams = `<${typeParamNames.join(", ")}>`;
59
+ }
60
+
61
+ return <core.Declaration symbol={thisClassSymbol}>
62
+ {getAccessModifier(props.accessModifier)}class <Name />{typeParams}{!props.children && ";"}{props.children &&
63
+ <>
64
+ {"\n{"}
65
+ <core.Scope value={thisClassScope}>
66
+ {props.children}
67
+ </core.Scope>
68
+ {"}"}
69
+ </>
70
+ }
71
+ </core.Declaration>;
72
+ }
73
+
74
+ export interface ClassConstructorProps {
75
+ accessModifier?: AccessModifier;
76
+ parameters?: Array<ParameterProps>;
77
+ refkey?: core.Refkey;
78
+ symbol?: core.OutputSymbol;
79
+ children?: core.Children;
80
+ }
81
+
82
+ // a C# class constructor
83
+ export function ClassConstructor(props: ClassConstructorProps) {
84
+ const scope = useCSharpScope();
85
+ if (scope.kind !== "member" || scope.name !== "class-decl") {
86
+ throw new Error(
87
+ "can't define a class constructor outside of a class-decl scope",
88
+ );
89
+ }
90
+
91
+ // fetch the class name from the scope
92
+ const name = useCSharpNamePolicy().getName(scope.owner.name, "class-method");
93
+ const ctorSymbol = scope.binder.createSymbol<CSharpOutputSymbol>({
94
+ name: name,
95
+ scope,
96
+ refkey: props.refkey ?? core.refkey(name),
97
+ });
98
+
99
+ // scope for ctor declaration
100
+ const ctorDeclScope = createCSharpMemberScope(
101
+ scope.binder,
102
+ scope,
103
+ ctorSymbol,
104
+ "constructor-decl",
105
+ );
106
+
107
+ const accessModifier = getAccessModifier(props.accessModifier);
108
+ const params = props.parameters ?
109
+ <Parameters parameters={props.parameters} />
110
+ : "";
111
+
112
+ // note that scope wraps the ctor decl so that the params get the correct scope
113
+ return <core.Declaration symbol={ctorSymbol}>
114
+ <core.Scope value={ctorDeclScope}>
115
+ {accessModifier}<Name />({params}){!props.children && " {}"}{props.children &&
116
+ <>
117
+ {"\n{"}
118
+ {props.children}
119
+ {"}"}
120
+ </>
121
+ }
122
+ </core.Scope>
123
+ </core.Declaration>;
124
+ }
125
+
126
+ // properties for creating a class member
127
+ export interface ClassMemberProps {
128
+ name: string;
129
+ type: core.Children;
130
+ accessModifier?: AccessModifier;
131
+ refkey?: core.Refkey;
132
+ }
133
+
134
+ // a C# class member (i.e. a field within a class like "private int count")
135
+ export function ClassMember(props: ClassMemberProps) {
136
+ let nameElement: CSharpElements = "class-member-private";
137
+ if (props.accessModifier === "public") {
138
+ nameElement = "class-member-public";
139
+ }
140
+ const name = useCSharpNamePolicy().getName(props.name, nameElement);
141
+ const scope = useCSharpScope();
142
+ if (scope.kind !== "member" || scope.name !== "class-decl") {
143
+ throw new Error(
144
+ "can't define a class member outside of a class-decl scope",
145
+ );
146
+ }
147
+
148
+ const memberSymbol = scope.binder.createSymbol<CSharpOutputSymbol>({
149
+ name: name,
150
+ scope,
151
+ refkey: props.refkey ?? core.refkey(props.name),
152
+ });
153
+
154
+ return <core.Declaration symbol={memberSymbol}>
155
+ {getAccessModifier(props.accessModifier)}{props.type} <Name />;
156
+ </core.Declaration>;
157
+ }
158
+
159
+ // properties for creating a method
160
+ export interface ClassMethodProps
161
+ extends Omit<core.DeclarationProps, "nameKind"> {
162
+ name: string;
163
+ accessModifier?: AccessModifier;
164
+ methodModifier?: MethodModifier;
165
+ parameters?: Array<ParameterProps>;
166
+ returns?: core.Children;
167
+ }
168
+
169
+ // a C# class method
170
+ export function ClassMethod(props: ClassMethodProps) {
171
+ const name = useCSharpNamePolicy().getName(props.name!, "class-method");
172
+ const scope = useCSharpScope();
173
+ if (scope.kind !== "member" || scope.name !== "class-decl") {
174
+ throw new Error("can't define a class method outside of a class scope");
175
+ }
176
+
177
+ const methodSymbol = scope.binder.createSymbol<CSharpOutputSymbol>({
178
+ name: name,
179
+ scope,
180
+ refkey: props.refkey ?? core.refkey(props.name),
181
+ });
182
+
183
+ // scope for method declaration
184
+ const methodScope = createCSharpMemberScope(
185
+ scope.binder,
186
+ scope,
187
+ methodSymbol,
188
+ "method-decl",
189
+ );
190
+
191
+ const accessModifier = getAccessModifier(props.accessModifier);
192
+ const methodModifier = getMethodModifier(props.methodModifier);
193
+ const params = props.parameters ?
194
+ <Parameters parameters={props.parameters} />
195
+ : "";
196
+ const returns = props.returns ?? "void";
197
+
198
+ // note that scope wraps the method decl so that the params get the correct scope
199
+ return <core.Declaration symbol={methodSymbol}>
200
+ <core.Scope value={methodScope}>
201
+ {accessModifier}{methodModifier}{returns} <Name />({params}){!props.children && " {}"}{props.children &&
202
+ <>
203
+ {"\n{"}
204
+ {props.children}
205
+ {"}"}
206
+ </>
207
+ }
208
+ </core.Scope>
209
+ </core.Declaration>;
210
+ }
@@ -0,0 +1,17 @@
1
+ import * as core from "@alloy-js/core";
2
+ import { createCSharpSymbol } from "../symbols/csharp-output-symbol.js";
3
+
4
+ // properties for creating a declaration
5
+ export interface DeclarationProps {
6
+ name: string;
7
+ refkey?: core.Refkey;
8
+ children?: core.Children;
9
+ }
10
+
11
+ // declares a symbol in the program (class, enum, interface etc)
12
+ export function Declaration(props: DeclarationProps) {
13
+ const sym = createCSharpSymbol(props);
14
+ return <core.Declaration symbol={sym}>
15
+ {props.children}
16
+ </core.Declaration>;
17
+ }
@@ -0,0 +1,74 @@
1
+ import * as core from "@alloy-js/core";
2
+ import { AccessModifier, getAccessModifier } from "../modifiers.js";
3
+ import { useCSharpNamePolicy } from "../name-policy.js";
4
+ import { CSharpOutputSymbol } from "../symbols/csharp-output-symbol.js";
5
+ import { createCSharpMemberScope, useCSharpScope } from "../symbols/scopes.js";
6
+ import { Name } from "./Name.jsx";
7
+
8
+ // properties for creating an enum
9
+ export interface EnumProps extends Omit<core.DeclarationProps, "nameKind"> {
10
+ name: string;
11
+ accessModifier?: AccessModifier;
12
+ }
13
+
14
+ // a C# enum declaration
15
+ export function Enum(props: EnumProps) {
16
+ const name = useCSharpNamePolicy().getName(props.name!, "enum");
17
+ const scope = useCSharpScope();
18
+
19
+ const thisEnumSymbol = scope.binder.createSymbol<CSharpOutputSymbol>({
20
+ name: name,
21
+ scope,
22
+ refkey: props.refkey ?? core.refkey(props.name),
23
+ });
24
+
25
+ // this creates a new scope for the enum definition.
26
+ // members will automatically "inherit" this scope so
27
+ // that refkeys to them will produce the fully-qualified
28
+ // name e.g. Foo.Bar.
29
+ const thisEnumScope = createCSharpMemberScope(
30
+ scope.binder,
31
+ scope,
32
+ thisEnumSymbol,
33
+ "enum-decl",
34
+ );
35
+
36
+ return <core.Declaration symbol={thisEnumSymbol}>
37
+ {getAccessModifier(props.accessModifier)}enum <Name />{!props.children && ";"}{props.children &&
38
+ <>
39
+ {"\n{"}
40
+ <core.Scope value={thisEnumScope}>
41
+ {props.children}
42
+ </core.Scope>
43
+ {"}"}
44
+ </>
45
+ }
46
+ </core.Declaration>;
47
+ }
48
+
49
+ // properties for creating a C# enum member
50
+ export interface EnumMemberProps {
51
+ name: string;
52
+ refkey?: core.Refkey;
53
+ }
54
+
55
+ // a member within a C# enum
56
+ export function EnumMember(props: EnumMemberProps) {
57
+ const scope = useCSharpScope();
58
+ if (scope.kind === "member" && scope.name !== "enum-decl") {
59
+ throw new Error(
60
+ "can't define an enum member outside of an enum-decl scope",
61
+ );
62
+ }
63
+
64
+ const name = useCSharpNamePolicy().getName(props.name, "enum-member");
65
+ const thisEnumValueSymbol = scope.binder.createSymbol<CSharpOutputSymbol>({
66
+ name: name,
67
+ scope,
68
+ refkey: props.refkey ?? core.refkey(props.name),
69
+ });
70
+
71
+ return <core.Declaration symbol={thisEnumValueSymbol}>
72
+ <Name />
73
+ </core.Declaration>;
74
+ }
@@ -0,0 +1,11 @@
1
+ import * as core from "@alloy-js/core";
2
+
3
+ // the name within the current declaration
4
+ export function Name() {
5
+ const declSymbol = core.useContext(core.DeclarationContext);
6
+ if (!declSymbol) {
7
+ throw new Error("missing declaration context");
8
+ }
9
+
10
+ return <>{declSymbol.name}</>;
11
+ }
@@ -0,0 +1,39 @@
1
+ import * as core from "@alloy-js/core";
2
+ import { createCSharpNamespaceScope } from "../symbols/scopes.js";
3
+
4
+ // contains the info for the current namespace
5
+ export interface NamespaceContext {
6
+ name: string;
7
+ }
8
+
9
+ const NamespaceContext = core.createContext<NamespaceContext>();
10
+
11
+ // returns the current namespace
12
+ export function useNamespace(): NamespaceContext | undefined {
13
+ return core.useContext(NamespaceContext) as NamespaceContext;
14
+ }
15
+
16
+ // properties for creating a C# namespace
17
+ export interface NamespaceProps {
18
+ name: string;
19
+ children?: core.Children;
20
+ }
21
+
22
+ // a C# namespace. contains one or more source files
23
+ export function Namespace(props: NamespaceProps) {
24
+ const scope = createCSharpNamespaceScope(
25
+ core.useBinder(),
26
+ core.useScope(),
27
+ props.name,
28
+ );
29
+
30
+ const namespaceCtx: NamespaceContext = {
31
+ name: props.name,
32
+ };
33
+
34
+ return <NamespaceContext.Provider value={namespaceCtx}>
35
+ <core.Scope value={scope}>
36
+ {props.children}
37
+ </core.Scope>
38
+ </NamespaceContext.Provider>;
39
+ }
@@ -0,0 +1,52 @@
1
+ import * as core from "@alloy-js/core";
2
+ import { useCSharpNamePolicy } from "../name-policy.js";
3
+ import { CSharpOutputSymbol } from "../symbols/csharp-output-symbol.js";
4
+ import { useCSharpScope } from "../symbols/scopes.js";
5
+ import { Name } from "./Name.js";
6
+
7
+ export interface ParameterProps {
8
+ name: string;
9
+ type: core.Children;
10
+ refkey?: core.Refkey;
11
+ symbol?: core.OutputSymbol;
12
+ }
13
+
14
+ // a constructor/method parameter
15
+ export function Parameter(props: ParameterProps) {
16
+ const name = useCSharpNamePolicy().getName(props.name, "parameter");
17
+ const scope = useCSharpScope();
18
+ if (
19
+ scope.kind !== "member" ||
20
+ (scope.name !== "constructor-decl" && scope.name !== "method-decl")
21
+ ) {
22
+ throw new Error(
23
+ "can't define a parameter outside of a constructor-decl or method-decl scope",
24
+ );
25
+ }
26
+
27
+ const memberSymbol = scope.binder.createSymbol<CSharpOutputSymbol>({
28
+ name: name,
29
+ scope,
30
+ refkey: props.refkey ?? core.refkey(props.name),
31
+ });
32
+
33
+ return <core.Declaration symbol={memberSymbol}>
34
+ {props.type} <Name />
35
+ </core.Declaration>;
36
+ }
37
+
38
+ export interface ParametersProps {
39
+ // param name and type
40
+ parameters: Array<ParameterProps>;
41
+ }
42
+
43
+ // a collection of parameters
44
+ export function Parameters(props: ParametersProps): Array<core.Child | string> {
45
+ return core.mapJoin(
46
+ props.parameters,
47
+ (param) => {
48
+ return <Parameter {...param} />;
49
+ },
50
+ { joiner: ", " },
51
+ );
52
+ }
@@ -0,0 +1,54 @@
1
+ import * as core from "@alloy-js/core";
2
+ import { join } from "pathe";
3
+
4
+ // properties for creating the project directory
5
+ export interface ProjectDirectoryProps {
6
+ // the name of the project directory
7
+ name: string;
8
+
9
+ // the semver of the project
10
+ version: string;
11
+
12
+ // project description
13
+ description: string;
14
+
15
+ // parent path where the project directory will be created
16
+ path: string;
17
+
18
+ // directory name for source files. defaults to "src"
19
+ srcDir?: string;
20
+
21
+ // the .NET TFM for this project. defaults to net8.0
22
+ targetFrameworkMoniker?: string;
23
+
24
+ // child components of the project
25
+ children?: core.Children;
26
+ }
27
+
28
+ // the top-level C# project directory. includes a csproj file
29
+ export function ProjectDirectory(props: ProjectDirectoryProps) {
30
+ if (!props.srcDir) {
31
+ props.srcDir = "src";
32
+ }
33
+
34
+ if (!props.targetFrameworkMoniker) {
35
+ props.targetFrameworkMoniker = "net8.0";
36
+ }
37
+
38
+ return <core.SourceDirectory path={join(props.path, props.name)}>
39
+ <core.SourceFile path={props.name+".csproj"} filetype="xml">
40
+ {core.code`
41
+ <Project Sdk="Microsoft.NET.Sdk">
42
+ <PropertyGroup>
43
+ <Version>${props.version}</Version>
44
+ <Description>${props.description}</Description>
45
+ <TargetFramework>${props.targetFrameworkMoniker}</TargetFramework>
46
+ </PropertyGroup>
47
+ </Project>
48
+ `}
49
+ </core.SourceFile>
50
+ <core.SourceDirectory path={props.srcDir}>
51
+ {props.children}
52
+ </core.SourceDirectory>
53
+ </core.SourceDirectory>;
54
+ }
@@ -0,0 +1,13 @@
1
+ import * as core from "@alloy-js/core";
2
+ import { ref } from "../symbols/reference.js";
3
+
4
+ export interface ReferenceProps {
5
+ refkey: core.Refkey;
6
+ }
7
+
8
+ // used to resolve refkey references within source files
9
+ export function Reference({ refkey }: ReferenceProps) {
10
+ const reference = ref(refkey);
11
+
12
+ return <>{reference}</>;
13
+ }
@@ -0,0 +1,69 @@
1
+ import * as core from "@alloy-js/core";
2
+ import { useNamespace } from "./Namespace.jsx";
3
+ import { Reference } from "./Reference.jsx";
4
+ import { UsingDirective } from "./UsingDirective.jsx";
5
+
6
+ // contains the info for the current source file
7
+ export interface SourceFileContext {
8
+ // adds a namespace to the array of using statements
9
+ addUsing(namespace: string): void;
10
+ }
11
+
12
+ const SourceFileContext = core.createContext<SourceFileContext>();
13
+
14
+ // returns the current source file
15
+ export function useSourceFile(): SourceFileContext | undefined {
16
+ return core.useContext(SourceFileContext) as SourceFileContext;
17
+ }
18
+
19
+ // properties fro creating a C# source file
20
+ export interface SourceFileProps {
21
+ path: string;
22
+ using?: Array<string>;
23
+ children?: core.Children;
24
+ }
25
+
26
+ // a C# source file. exists within the context of a namespace
27
+ // contains using statements and declarations
28
+ export function SourceFile(props: SourceFileProps) {
29
+ const namespaceCtx = useNamespace();
30
+
31
+ if (!namespaceCtx) {
32
+ throw new Error("SourceFile must be declared inside a namespace");
33
+ }
34
+
35
+ const using: Array<string> = core.reactive(new Array<string>());
36
+ if (props.using) {
37
+ using.push(...props.using);
38
+ }
39
+
40
+ // adds the specified namespace to the array of using statements.
41
+ // called via SourceFileContext.addUsing when resolving refkeys.
42
+ function addUsing(namespace: string): void {
43
+ if (!using.includes(namespace)) {
44
+ using.push(namespace);
45
+ }
46
+ }
47
+
48
+ const sourceFileCtx: SourceFileContext = {
49
+ addUsing,
50
+ };
51
+
52
+ return <core.SourceFile path={props.path} filetype="cs" reference={Reference}>
53
+ <SourceFileContext.Provider value={sourceFileCtx}>
54
+ <core.Scope name={props.path} kind="source-file">
55
+ {using.length > 0 ? (
56
+ <>
57
+ <UsingDirective namespaces={using} />{"\n"}
58
+ </>
59
+ ) : undefined}namespace {namespaceCtx.name}{!props.children && " {}"}{props.children &&
60
+ <>
61
+ {"\n{"}
62
+ {props.children}
63
+ {"}"}
64
+ </>
65
+ }
66
+ </core.Scope>
67
+ </SourceFileContext.Provider>
68
+ </core.SourceFile>;
69
+ }
@@ -0,0 +1,19 @@
1
+ import * as core from "@alloy-js/core";
2
+
3
+ export interface UsingDirectiveProps {
4
+ namespaces: Array<string>;
5
+ }
6
+
7
+ // one ore more C# using directives
8
+ export function UsingDirective(props: UsingDirectiveProps) {
9
+ // we need core.memo here so that the contents are in a reactive context.
10
+ // the values for namespaces are reactive thus we need to observe any changes.
11
+ return core.memo(() => {
12
+ props.namespaces.sort();
13
+ return core
14
+ .mapJoin(props.namespaces, (namespace) => {
15
+ return `using ${namespace};`;
16
+ })
17
+ .join("");
18
+ });
19
+ }
@@ -0,0 +1,10 @@
1
+ export * from "./Class.js";
2
+ export * from "./Declaration.js";
3
+ export * from "./Enum.js";
4
+ export * from "./Name.js";
5
+ export * from "./Namespace.js";
6
+ export * from "./Parameters.js";
7
+ export * from "./ProjectDirectory.js";
8
+ export * from "./Reference.js";
9
+ export * from "./SourceFile.js";
10
+ export * from "./UsingDirective.js";
@@ -0,0 +1,13 @@
1
+ import * as core from "@alloy-js/core";
2
+ import * as base from "../index.js";
3
+
4
+ export const Class = core.stc(base.Class);
5
+ export const ClassConstructor = core.stc(base.ClassConstructor);
6
+ export const ClassMember = core.stc(base.ClassMember);
7
+ export const ClassMethod = core.stc(base.ClassMethod);
8
+ export const Enum = core.stc(base.Enum);
9
+ export const EnumMember = core.stc(base.EnumMember);
10
+ export const Parameter = core.stc(base.Parameter);
11
+ export const Parameters = core.stc(base.Parameters);
12
+ export const ProjectDirectory = core.stc(base.ProjectDirectory);
13
+ export const UsingDirective = core.stc(base.UsingDirective);
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./components/index.js";
2
+ export * from "./modifiers.js";
3
+ export * from "./name-policy.js";
4
+ export * from "./symbols/index.js";
@@ -0,0 +1,45 @@
1
+ // the possible C# access modifiers
2
+ // https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers
3
+ export type AccessModifier =
4
+ | "public"
5
+ | "protected"
6
+ | "private"
7
+ | "internal"
8
+ | "protected-internal"
9
+ | "private-protected"
10
+ | "file";
11
+
12
+ // maps the above access modifier value to its C# syntax.
13
+ // note that the C# keyword includes a trailing space
14
+ const accessModifierLookup: Record<AccessModifier, string> = {
15
+ public: "public ",
16
+ protected: "protected ",
17
+ private: "private ",
18
+ internal: "internal ",
19
+ "protected-internal": "protected internal ",
20
+ "private-protected": "private protected ",
21
+ file: "file ",
22
+ };
23
+
24
+ // returns the C# syntax for the specified access modifier.
25
+ // if no access modifier is specified, the empty string is returned.
26
+ export function getAccessModifier(accessModifier?: AccessModifier): string {
27
+ return accessModifier ? accessModifierLookup[accessModifier] : "";
28
+ }
29
+
30
+ export type MethodModifier = "abstract" | "sealed" | "static" | "virtual";
31
+
32
+ // maps the above method modifier value to its C# syntax.
33
+ // note that the C# keyword includes a trailing space
34
+ const methodModifierLookup: Record<MethodModifier, string> = {
35
+ abstract: "abstract ",
36
+ sealed: "sealed ",
37
+ static: "static ",
38
+ virtual: "virtual ",
39
+ };
40
+
41
+ // returns the C# syntax for the specified method modifier.
42
+ // if no method modifier is specified, the empty string is returned.
43
+ export function getMethodModifier(methodModifier?: MethodModifier): string {
44
+ return methodModifier ? methodModifierLookup[methodModifier] : "";
45
+ }
@@ -0,0 +1,41 @@
1
+ import * as core from "@alloy-js/core";
2
+ import * as changecase from "change-case";
3
+
4
+ // the context in which the name policy should be applied
5
+ export type CSharpElements =
6
+ | "class"
7
+ | "constant"
8
+ | "enum"
9
+ | "enum-member"
10
+ | "function"
11
+ | "interface"
12
+ | "class-member-private"
13
+ | "class-member-public"
14
+ | "class-method"
15
+ | "parameter"
16
+ | "type-parameter";
17
+
18
+ // creates the C# naming policy
19
+ export function createCSharpNamePolicy(): core.NamePolicy<CSharpElements> {
20
+ return core.createNamePolicy((name, element) => {
21
+ switch (element) {
22
+ case "class":
23
+ case "enum":
24
+ case "enum-member":
25
+ case "interface":
26
+ case "class-member-public":
27
+ case "class-method":
28
+ case "type-parameter":
29
+ return changecase.pascalCase(name);
30
+ case "constant":
31
+ return changecase.constantCase(name);
32
+ default:
33
+ return changecase.camelCase(name);
34
+ }
35
+ });
36
+ }
37
+
38
+ // gets the active C# naming policy
39
+ export function useCSharpNamePolicy(): core.NamePolicy<CSharpElements> {
40
+ return core.useNamePolicy();
41
+ }