Repository: alloy-framework/alloy
Pull request #14 (2024-08-28 18:58:58)

Support async function declarations
Adds an `async` prop to function declaration and handles the return type to be wrapped by a Promise

pkg-pr-new[bot]: 
_commit: <a href="https://github.com/alloy-framework/alloy/runs/29385597283"><code>11bb8bb</code></a>_


<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@14
```

</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@14
```

</p></details>
      
    

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

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

</p></details>
      
    

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

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

</p></details>
      
    

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

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

</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@14
```

</p></details>
      
    

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

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

</p></details>
      
    

[Open in Stackblitz](https://pkg.pr.new/template/993cb507-90b3-44ae-80b0-64d4ba798e25)


Patch:
diff --git a/packages/typescript/src/components/FunctionDeclaration.tsx b/packages/typescript/src/components/FunctionDeclaration.tsx
index 17f6ea3..a7c170f 100644
--- a/packages/typescript/src/components/FunctionDeclaration.tsx
+++ b/packages/typescript/src/components/FunctionDeclaration.tsx
@@ -28,6 +28,7 @@ function isParameterDescriptor(
 }
 export interface FunctionDeclarationProps
   extends Omit<DeclarationProps, "nameKind"> {
+  async?: boolean;
   parameters?: Record<string, Children | ParameterDescriptor>;
   returnType?: string;
   children?: Children;
@@ -41,7 +42,8 @@ export function FunctionDeclaration(props: FunctionDeclarationProps) {
   const parametersChild = findKeyedChild(children, functionParametersTag);
   const bodyChild = findKeyedChild(children, functionBodyTag);
   const filteredChildren = findUnkeyedChildren(children);
-  const sReturnType = props.returnType ? <>: {props.returnType}</> : undefined;
+  const returnType = getReturnType(props.returnType, { async: props.async });
+  const sReturnType = returnType ? <>: {returnType}</> : undefined;
 
   const sParams =
     parametersChild ?? <FunctionDeclaration.Parameters parameters={props.parameters} />;
@@ -49,8 +51,10 @@ export function FunctionDeclaration(props: FunctionDeclarationProps) {
   let sBody =
     bodyChild ?? <FunctionDeclaration.Body>{filteredChildren}</FunctionDeclaration.Body>;
 
+  const asyncKwd = props.async ? "async " : "";
+
   return <Declaration {...props} nameKind="function">
-      function <Name /><Scope name={props.name} kind="function">
+      {asyncKwd}function <Name /><Scope name={props.name} kind="function">
         ({sParams}){sReturnType} {"{"}
           {sBody}
         {"}"}
@@ -58,6 +62,14 @@ export function FunctionDeclaration(props: FunctionDeclarationProps) {
     </Declaration>;
 }
 
+function getReturnType(
+  returnType: string | undefined,
+  options: { async?: boolean } = { async: false },
+) {
+  if (returnType) {
+    return options.async ? `Promise<${returnType}>` : returnType;
+  }
+}
 export interface FunctionParametersProps {
   parameters?: Record<string, Children | ParameterDescriptor>;
   children?: Children;


Test patch:
diff --git a/packages/typescript/test/function-declaration.test.tsx b/packages/typescript/test/function-declaration.test.tsx
index 5807979..e16be73 100644
--- a/packages/typescript/test/function-declaration.test.tsx
+++ b/packages/typescript/test/function-declaration.test.tsx
@@ -38,6 +38,26 @@ it("can be a default export", () => {
     `);
 });
 
+it("can be an async function", () => {
+  expect(toSourceText(<FunctionDeclaration async export name="foo" />)).toBe(d`
+    export async function foo() {
+      
+    }
+  `);
+});
+
+it("can be an async function with returnType", () => {
+  expect(
+    toSourceText(
+      <FunctionDeclaration async export name="foo" returnType="Foo"/>,
+    ),
+  ).toBe(d`
+    export async function foo(): Promise<Foo> {
+      
+    }
+  `);
+});
+
 it("supports parameters by element", () => {
   const decl =
     <FunctionDeclaration name="foo">