Repository: alloy-framework/alloy
Pull request #22 (2024-09-12 22:50:19)

Add support for class generic type params
Fixed some formatting to make prettier happy.

pkg-pr-new[bot]: 
[Open in Stackblitz](https://pkg.pr.new/template/f606ebaf-65f9-4f29-abd7-3f3c657d8566)


<details><summary><b>@alloy-js/babel-plugin-alloy</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/babel-plugin-alloy@22
```

</p></details>
      
    

<details><summary><b>babel-preset-alloy</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/babel-preset-alloy@22
```

</p></details>
      
    

<details><summary><b>@alloy-js/babel-plugin-jsx-dom-expressions</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/babel-plugin-jsx-dom-expressions@22
```

</p></details>
      
    

<details><summary><b>@alloy-js/csharp</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/csharp@22
```

</p></details>
      
    

<details><summary><b>@alloy-js/core</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/core@22
```

</p></details>
      
    

<details><summary><b>@alloy-js/java</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/java@22
```

</p></details>
      
    

<details><summary><b>@alloy-js/prettier-plugin-alloy</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/prettier-plugin-alloy@22
```

</p></details>
      
    

<details><summary><b>@alloy-js/typescript</b></summary><p>

```
pnpm add https://pkg.pr.new/alloy-framework/alloy/@alloy-js/typescript@22
```

</p></details>
      
    

_commit: <a href="https://github.com/alloy-framework/alloy/runs/30081217722"><code>c51ce31</code></a>_


Patch:
diff --git a/packages/csharp/src/components/Class.tsx b/packages/csharp/src/components/Class.tsx
index 40420e9..847f7e7 100644
--- a/packages/csharp/src/components/Class.tsx
+++ b/packages/csharp/src/components/Class.tsx
@@ -14,6 +14,7 @@ import { Parameters } from "./Parameters.jsx";
 // properties for creating a class
 export interface ClassProps extends Omit<core.DeclarationProps, "nameKind"> {
   accessModifier?: AccessModifier;
+  typeParameters?: Record<string, core.Refkey>;
 }
 
 // a C# class declaration
@@ -38,8 +39,24 @@ export function Class(props: ClassProps) {
     "class",
   );
 
+  let typeParams: string | undefined;
+  if (props.typeParameters) {
+    const typeParamNames = new Array<string>();
+    for (const entry of Object.entries(props.typeParameters)) {
+      typeParamNames.push(entry[0]);
+      // create a symbol for each type param so its
+      // refkey resolves to the type param's name
+      scope.binder.createSymbol<CSharpOutputSymbol>({
+        name: entry[0],
+        scope: thisClassScope,
+        refkey: entry[1],
+      });
+    }
+    typeParams = `<${typeParamNames.join(", ")}>`;
+  }
+
   return <core.Declaration symbol={thisClassSymbol}>
-      {getAccessModifier(props.accessModifier)}class <Name />{!props.children && ";"}{props.children &&
+      {getAccessModifier(props.accessModifier)}class <Name />{typeParams}{!props.children && ";"}{props.children &&
         <>
           {"\n{"}
             <core.Scope value={thisClassScope}>


Test patch:
diff --git a/packages/csharp/test/class.test.tsx b/packages/csharp/test/class.test.tsx
index d712599..e8f11a1 100644
--- a/packages/csharp/test/class.test.tsx
+++ b/packages/csharp/test/class.test.tsx
@@ -129,6 +129,31 @@ it("uses refkeys for members, params, and return type", () => {
   `);
 });
 
+it("declares class with generic parameters", () => {
+  const typeParameters = {
+    T: core.refkey(),
+    U: core.refkey(),
+  };
+
+  const res = utils.toSourceText(
+    <csharp.Class accessModifier='public' name="TestClass" typeParameters={typeParameters}>
+      <csharp.ClassMember accessModifier="public" name="MemberOne" type={typeParameters.T} />
+      <csharp.ClassMember accessModifier="private" name="MemberTwo" type={typeParameters.U} />
+    </csharp.Class>,
+  );
+
+  expect(res).toBe(coretest.d`
+    namespace TestCode
+    {
+      public class TestClass<T, U>
+      {
+        public T memberOne;
+        private U memberTwo;
+      }
+    }
+  `);
+});
+
 it("declares class with invalid members", () => {
   const decl =
     <csharp.Class accessModifier='public' name="TestClass">
diff --git a/packages/csharp/test/projectdirectory.test.tsx b/packages/csharp/test/projectdirectory.test.tsx
index 527614a..ef8517e 100644
--- a/packages/csharp/test/projectdirectory.test.tsx
+++ b/packages/csharp/test/projectdirectory.test.tsx
@@ -22,7 +22,9 @@ it("defines a project directory file with multiple source files", () => {
   const projDir = res.contents[0] as core.OutputDirectory;
 
   expect(projDir.path).equals("~/projects/TestProject");
-  expect(projDir.contents[0].path).equals("~/projects/TestProject/TestProject.csproj");
+  expect(projDir.contents[0].path).equals(
+    "~/projects/TestProject/TestProject.csproj",
+  );
   expect(projDir.contents[0].contents).toBe(coretest.d`
     <Project Sdk="Microsoft.NET.Sdk">
       <PropertyGroup>