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

Add support for Godot 4.2 typed for loop iterator variable, fixes #236 #241

Merged
merged 1 commit into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions gdtoolkit/common/ast.py
Scony marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def __init__(self, node: Tree, annotations: List[Annotation] = []):

self._load_sub_statements()

# pylint: disable=too-many-branches
def _load_sub_statements(self):
if self.kind == "class_def":
pass # TODO: implement
Expand All @@ -48,6 +49,8 @@ def _load_sub_statements(self):
self.sub_statements = [Statement(n) for n in self.lark_node.children[1:]]
elif self.kind == "for_stmt":
self.sub_statements = [Statement(n) for n in self.lark_node.children[2:]]
elif self.kind == "for_stmt_typed":
self.sub_statements = [Statement(n) for n in self.lark_node.children[3:]]
elif self.kind == "match_stmt":
for branch in self.lark_node.children:
self.sub_statements += [Statement(n) for n in branch.children[1:]]
Expand Down
8 changes: 8 additions & 0 deletions gdtoolkit/formatter/function_statement.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def format_func_statement(statement: Tree, context: Context) -> Outcome:
"if_stmt": _format_if_statement,
"while_stmt": partial(_format_branch, "while ", ":", 0),
"for_stmt": _format_for_statement,
"for_stmt_typed": _format_for_statement_typed,
"match_stmt": _format_match_statement,
"annotation": format_standalone_annotation,
# fake statements:
Expand Down Expand Up @@ -83,6 +84,13 @@ def _format_for_statement(statement: Tree, context: Context) -> Outcome:
return _format_branch(prefix, suffix, expr_position, statement, context)


def _format_for_statement_typed(statement: Tree, context: Context) -> Outcome:
prefix = f"for {statement.children[0].value}: {statement.children[1].value} in "
suffix = ":"
expr_position = 2
return _format_branch(prefix, suffix, expr_position, statement, context)


def _format_match_statement(statement: Tree, context: Context) -> Outcome:
prefix = "match "
suffix = ":"
Expand Down
8 changes: 8 additions & 0 deletions gdtoolkit/gd2py/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ def _convert_statement(statement: Tree, context: Context) -> List[str]:
)
]
+ _convert_block(s.children[2:], c.create_child_context(-1)),
"for_stmt_typed": lambda s, c: [
"{}for {} in {}:".format(
c.indent_string,
s.children[0].value,
_convert_expression_to_str(s.children[2]),
)
]
+ _convert_block(s.children[3:], c.create_child_context(-2)),
"match_stmt": _convert_match_statement,
"match_branch": partial(_convert_branch_with_expression, "elif"),
} # type: Dict[str, Callable]
Expand Down
3 changes: 2 additions & 1 deletion gdtoolkit/linter/name_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def lint(parse_tree: Tree, config: MappingProxyType) -> List[Problem]:
"enum_named",
"enum_element",
"for_stmt",
"for_stmt_typed",
"func_arg_regular",
"func_arg_inf",
"func_arg_typed",
Expand Down Expand Up @@ -93,7 +94,7 @@ def lint(parse_tree: Tree, config: MappingProxyType) -> List[Problem]:
partial(
_generic_name_check,
config["loop-variable-name"],
rule_name_tokens["for_stmt"],
rule_name_tokens["for_stmt"] + rule_name_tokens["for_stmt_typed"],
"loop-variable-name",
'Loop variable name "{}" is not valid',
),
Expand Down
3 changes: 3 additions & 0 deletions gdtoolkit/parser/gdscript.lark
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ _var_typed: "var" NAME ":" TYPE_HINT
class_var_typed: _var_typed [inline_property_body]
class_var_typed_assgnd: _var_typed "=" expr [inline_property_body]
class_var_inf: "var" NAME ":" "=" expr [inline_property_body]
_for_iterator_var_typed: NAME ":" TYPE_HINT
inline_property_body: ":" [property_delegate_set ["," property_delegate_get]]
| ":" [property_delegate_get ["," property_delegate_set]]
const_stmt: const_assigned
Expand Down Expand Up @@ -95,6 +96,7 @@ _simple_func_stmt: annotation* single_func_stmt (";" annotation* single_func_stm
?compound_func_stmt: if_stmt
| while_stmt
| for_stmt
| for_stmt_typed
| match_stmt
return_stmt: "return" [expr]
func_var_stmt: func_var_empty
Expand All @@ -117,6 +119,7 @@ elif_branch: "elif" expr ":" _func_suite
else_branch: "else" ":" _func_suite
while_stmt: "while" expr ":" _func_suite
for_stmt: "for" NAME "in" expr ":" _func_suite
for_stmt_typed: "for" _for_iterator_var_typed "in" expr ":" _func_suite
match_stmt: "match" expr ":" _match_body
_match_body: _NL _INDENT match_branch+ _DEDENT
match_branch: pattern ":" _func_suite
Expand Down
5 changes: 5 additions & 0 deletions tests/formatter/input-output-pairs/for_loop_typed.in.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class X:
func foo():
var a: Array[int] = [1]
for i:int in a:
print(a[i])
5 changes: 5 additions & 0 deletions tests/formatter/input-output-pairs/for_loop_typed.out.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class X:
func foo():
var a: Array[int] = [1]
for i: int in a:
print(a[i])
2 changes: 2 additions & 0 deletions tests/gd2py/input-output-pairs/func_level_statements.in.gd
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ func foo():
break
for i in 1:
continue
for j: int in 1:
continue
match 1:
1:
pass
Expand Down
2 changes: 2 additions & 0 deletions tests/gd2py/input-output-pairs/func_level_statements.out.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def foo():
break
for i in 1:
continue
for j in 1:
continue
if 1:
pass
elif 1:
Expand Down
24 changes: 24 additions & 0 deletions tests/linter/test_name_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,18 @@ def test_enum_element_name_nok(code):
for aaa_bbb in y:
pass
""",
"""func foo():
for _x: int in y:
pass
""",
"""func foo():
for xyz: int in y:
pass
""",
"""func foo():
for aaa_bbb: int in y:
pass
""",
])
def test_loop_variable_name_ok(code):
simple_ok_check(code)
Expand All @@ -211,6 +223,18 @@ def test_loop_variable_name_ok(code):
for X_X in y:
pass
""",
"""func foo():
for x_: int in y:
pass
""",
"""func foo():
for xX: int in y:
pass
""",
"""func foo():
for X_X: int in y:
pass
""",
])
def test_loop_variable_name_nok(code):
simple_nok_check(code, 'loop-variable-name')
Expand Down
6 changes: 6 additions & 0 deletions tests/valid-gd-scripts/typed_for_loop.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
extends Node

func _ready():
var a: Array[int] = [1]
for i: int in a:
print(a)
Loading