Skip to content

Commit 440a57f

Browse files
tawsifkamalcodegen-bot
authored and
tkucar
committed
Tawsif fix asyncify promise return type (#348)
# Motivation - changed asyncify bug If the normal function already returns a promise, do not surround Promise<> type as async function collapses promises. - when a function is already returning a promise, making it async will not make it return <Promise<Promise<any>> - It will just stay Promise<any> as is Co-authored-by: codegen-bot <[email protected]>
1 parent e429498 commit 440a57f

File tree

2 files changed

+148
-1
lines changed

2 files changed

+148
-1
lines changed

src/codegen/sdk/typescript/function.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ def asyncify(self) -> None:
297297
if self.is_async:
298298
return
299299
self.add_keyword("async")
300-
if self.return_type:
300+
if self.return_type and self.return_type.name != "Promise":
301301
self.return_type.insert_before("Promise<", newline=False)
302302
self.return_type.insert_after(">", newline=False)
303303

tests/unit/codegen/sdk/typescript/function/test_function_async.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from codegen.sdk.codebase.factory.get_session import get_codebase_session
22
from codegen.sdk.enums import ProgrammingLanguage
3+
from codegen.sdk.typescript.placeholder.placeholder_return_type import TSReturnTypePlaceholder
34

45

56
def test_function_is_async_basic(tmpdir):
@@ -233,3 +234,149 @@ class MathOperations {
233234
}
234235
"""
235236
)
237+
238+
239+
def test_asyncify_wraps_non_promise_return_type(tmpdir) -> None:
240+
# ========= = [ BEFORE ] ==========
241+
# language=typescript
242+
BEFORE_CONTENT = """
243+
function getData(): string {
244+
return "hello";
245+
}
246+
"""
247+
# ========== [ AFTER ] ==========
248+
# language=typescript
249+
EXPECTED_CONTENT = """
250+
async function getData(): Promise<string> {
251+
return "hello";
252+
}
253+
"""
254+
255+
with get_codebase_session(
256+
tmpdir=tmpdir,
257+
programming_language=ProgrammingLanguage.TYPESCRIPT,
258+
files={"test.ts": BEFORE_CONTENT},
259+
) as codebase:
260+
file = codebase.get_file("test.ts")
261+
func = file.get_function("getData")
262+
263+
# Initial state should be non-async
264+
assert not func.is_async
265+
assert func.return_type.source == "string"
266+
267+
# After asyncify, should be async and return type wrapped in Promise
268+
func.asyncify()
269+
codebase.commit()
270+
271+
# Check file content directly instead of func.is_async
272+
assert file.content.strip() == EXPECTED_CONTENT.strip()
273+
274+
275+
def test_asyncify_already_promise_return_type(tmpdir) -> None:
276+
# ========== [ BEFORE ] ==========
277+
# language=typescript
278+
BEFORE_CONTENT = """
279+
function getData(): Promise<string> {
280+
return Promise.resolve("hello");
281+
}
282+
"""
283+
284+
# ========== [ AFTER ] ==========
285+
# language=typescript
286+
EXPECTED_CONTENT = """
287+
async function getData(): Promise<string> {
288+
return Promise.resolve("hello");
289+
}
290+
"""
291+
292+
with get_codebase_session(
293+
tmpdir=tmpdir,
294+
programming_language=ProgrammingLanguage.TYPESCRIPT,
295+
files={"test.ts": BEFORE_CONTENT},
296+
) as codebase:
297+
file = codebase.get_file("test.ts")
298+
func = file.get_function("getData")
299+
300+
# Initial state should be non-async but already have Promise return type
301+
assert not func.is_async
302+
assert func.return_type.source == "Promise<string>"
303+
304+
# After asyncify, should be async but return type should remain unchanged
305+
func.asyncify()
306+
codebase.commit()
307+
308+
# Check file content directly instead of func.is_async
309+
print(file.content)
310+
assert file.content.strip() == EXPECTED_CONTENT.strip()
311+
312+
313+
def test_asyncify_void_return_type(tmpdir) -> None:
314+
# ========== [ BEFORE ] ==========
315+
# language=typescript
316+
BEFORE_CONTENT = """
317+
function processData(): void {
318+
console.log("processing");
319+
}
320+
"""
321+
322+
# ========== [ AFTER ] ==========
323+
# language=typescript
324+
EXPECTED_CONTENT = """
325+
async function processData(): Promise<void> {
326+
console.log("processing");
327+
}
328+
"""
329+
330+
with get_codebase_session(
331+
tmpdir=tmpdir,
332+
programming_language=ProgrammingLanguage.TYPESCRIPT,
333+
files={"test.ts": BEFORE_CONTENT},
334+
) as codebase:
335+
file = codebase.get_file("test.ts")
336+
func = file.get_function("processData")
337+
338+
# Initial state should be non-async with void return type
339+
assert not func.is_async
340+
assert func.return_type.source == "void"
341+
342+
# After asyncify, should be async and return Promise<void>
343+
func.asyncify()
344+
codebase.commit()
345+
# Check file content directly instead of func.is_async
346+
assert file.content.strip() == EXPECTED_CONTENT.strip()
347+
348+
349+
def test_asyncify_no_return_type(tmpdir) -> None:
350+
# ========== [ BEFORE ] ==========
351+
# language=typescript
352+
BEFORE_CONTENT = """
353+
function processData() {
354+
console.log("processing");
355+
}
356+
"""
357+
358+
# ========== [ AFTER ] ==========
359+
# language=typescript
360+
EXPECTED_CONTENT = """
361+
async function processData() {
362+
console.log("processing");
363+
}
364+
"""
365+
366+
with get_codebase_session(
367+
tmpdir=tmpdir,
368+
programming_language=ProgrammingLanguage.TYPESCRIPT,
369+
files={"test.ts": BEFORE_CONTENT},
370+
) as codebase:
371+
file = codebase.get_file("test.ts")
372+
func = file.get_function("processData")
373+
374+
# Initial state should be non-async with no return type
375+
assert not func.is_async
376+
assert isinstance(func.return_type, TSReturnTypePlaceholder)
377+
378+
# After asyncify, should be async but no return type added
379+
func.asyncify()
380+
codebase.commit()
381+
# Check file content directly instead of func.is_async
382+
assert file.content.strip() == EXPECTED_CONTENT.strip()

0 commit comments

Comments
 (0)