Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CG-10705: API to remove async from functions #936

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 27 additions & 21 deletions src/codegen/sdk/core/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
from codegen.sdk.core.statements.return_statement import ReturnStatement
from codegen.sdk.core.symbol import Symbol


TDecorator = TypeVar("TDecorator", bound="Decorator", default=Decorator)
TCodeBlock = TypeVar("TCodeBlock", bound="CodeBlock", default=CodeBlock)
TParameter = TypeVar("TParameter", bound="Parameter", default=Parameter)
Expand All @@ -41,7 +40,7 @@


@apidoc
class Function(

Check failure on line 43 in src/codegen/sdk/core/function.py

View workflow job for this annotation

GitHub Actions / mypy

error: Cannot determine type of "code_block" in base class "Symbol" [misc]
SupportsGenerics[TType],
HasBlock[TCodeBlock, TDecorator],
Callable[TParameter, TType],
Expand Down Expand Up @@ -126,7 +125,7 @@
Returns:
bool: True if the function is a constructor method of a class, False otherwise.
"""
return self.is_method and self.name == self.parent_class.constructor_keyword

Check failure on line 128 in src/codegen/sdk/core/function.py

View workflow job for this annotation

GitHub Actions / mypy

error: Item "None" of "Any | None" has no attribute "constructor_keyword" [union-attr]

@property
def is_async(self) -> bool:
Expand All @@ -146,35 +145,15 @@

for symbol in self.valid_symbol_names:
if symbol.name == name and (start_byte is None or (symbol.start_byte if isinstance(symbol, Class | Function) else symbol.end_byte) <= start_byte):
yield symbol

Check failure on line 148 in src/codegen/sdk/core/function.py

View workflow job for this annotation

GitHub Actions / mypy

error: Incompatible types in "yield" (actual type "Importable[Any]", expected type "Symbol[Any, Any] | Import[Any] | WildcardImport[Any]") [misc]
return
yield from super().resolve_name(name, start_byte, strict=strict)

@cached_property
@noapidoc
def valid_symbol_names(self) -> list[Importable]:
return sort_editables(self.parameters.symbols + self.descendant_symbols, reverse=True)

Check failure on line 155 in src/codegen/sdk/core/function.py

View workflow job for this annotation

GitHub Actions / mypy

error: Item "list[TParameter]" of "SymbolGroup[TParameter, Function[TDecorator, TCodeBlock, TParameter, TType]] | list[TParameter]" has no attribute "symbols" [union-attr]

Check failure on line 155 in src/codegen/sdk/core/function.py

View workflow job for this annotation

GitHub Actions / mypy

error: No overload variant of "__add__" of "list" matches argument type "Sequence[Importable[Any]]" [operator]

# Faster implementation which uses more memory
# @noapidoc
# @reader
# def resolve_name(self, name: str, start_byte: int | None = None) -> Symbol | Import | WildcardImport | None:
# if symbols := self.valid_symbol_names.get(name, None):
# for symbol in symbols:
# from codegen.sdk.core.class_definition import Class
#
# if (symbol.start_byte if isinstance(symbol, Class | Function) else symbol.end_byte) <= start_byte:
# return symbol
# return super().resolve_name(name, start_byte)
#
# @cached_property
# @noapidoc
# def valid_symbol_names(self) -> dict[str, list[Importable]]:
# ret = defaultdict(list)
# for elem in sort_editables(self.parameters.symbols + self.descendant_symbols, reverse=True):
# ret[elem.name].append(elem)
# return ret
#
###########################################################################################################
# PROPERTIES
###########################################################################################################
Expand Down Expand Up @@ -207,7 +186,7 @@
Returns:
list[ReturnStatement]: A list of all return statements found within the function's body.
"""
return self.code_block.get_statements(statement_type=StatementType.RETURN_STATEMENT)

Check failure on line 189 in src/codegen/sdk/core/function.py

View workflow job for this annotation

GitHub Actions / mypy

error: Cannot determine type of "code_block" [has-type]

@property
@reader
Expand All @@ -219,7 +198,7 @@
Returns:
list[Self]: A list of Function objects representing nested functions within this function's body, sorted by position in the file.
"""
functions = [m.symbol for m in self.code_block.symbol_statements if isinstance(m.symbol, self.__class__)]

Check failure on line 201 in src/codegen/sdk/core/function.py

View workflow job for this annotation

GitHub Actions / mypy

error: Cannot determine type of "code_block" [has-type]
return functions

####################################################################################################################
Expand Down Expand Up @@ -262,6 +241,33 @@

self.add_keyword("async")

@writer
def remove_async(self) -> None:
"""Removes the async keyword from a function.

Converts an asynchronous function to be synchronous by removing the 'async' keyword from its definition.
This method has no effect if the function is not asynchronous.

Returns:
None

Note:
This method has no effect if the function is not asynchronous.
"""
if not self.is_async:
return

# Find the async keyword node
for node in self.children_by_field_types(self.ctx.node_classes.keywords):
if node == "async":
# Remove the async keyword and any following whitespace
node_source = node.source
if node_source.endswith(" "):
node.edit("")
else:
node.edit("", newline=False)

Check failure on line 268 in src/codegen/sdk/core/function.py

View workflow job for this annotation

GitHub Actions / mypy

error: Unexpected keyword argument "newline" for "edit" of "Editable" [call-arg]
return

@writer
def rename_local_variable(self, old_var_name: str, new_var_name: str, fuzzy_match: bool = False) -> None:
"""Renames a local variable and all its usages within a function body.
Expand All @@ -276,7 +282,7 @@
Returns:
None: The method modifies the AST in place.
"""
matches = self.code_block.get_assignments(old_var_name, fuzzy=fuzzy_match, parameters=False)

Check failure on line 285 in src/codegen/sdk/core/function.py

View workflow job for this annotation

GitHub Actions / mypy

error: Cannot determine type of "code_block" [has-type]
for match in matches:
new_name = new_var_name
if fuzzy_match:
Expand All @@ -302,7 +308,7 @@
if index == 0:
return self.prepend_statements(lines)

statements = self.code_block.statements

Check failure on line 311 in src/codegen/sdk/core/function.py

View workflow job for this annotation

GitHub Actions / mypy

error: Cannot determine type of "code_block" [has-type]
if index >= len(statements):
msg = f"Index {index} out of range for function {self.name}"
raise ValueError(msg)
Expand Down
Loading