Skip to content

Commit 3c149bf

Browse files
committed
Update AST Injection
1 parent 2a36301 commit 3c149bf

File tree

1 file changed

+50
-29
lines changed

1 file changed

+50
-29
lines changed

cppython/plugins/conan/builder.py

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ def _create_requires_assignment(self) -> cst.Assign:
2121
"""Create a `requires` assignment statement."""
2222
return cst.Assign(
2323
targets=[cst.AssignTarget(cst.Name('requires'))],
24-
value=cst.List([cst.Element(cst.SimpleString(f'"{dep.requires()}"')) for dep in self.dependencies]),
24+
value=cst.List([
25+
cst.Element(cst.SimpleString(f'"{dependency.requires()}"')) for dependency in self.dependencies
26+
]),
2527
)
2628

2729
def leave_ClassDef(self, original_node: cst.ClassDef, updated_node: cst.ClassDef) -> cst.BaseStatement:
@@ -46,51 +48,70 @@ def _is_conanfile_class(class_node: cst.ClassDef) -> bool:
4648
4749
Returns: True if the class inherits from ConanFile, False otherwise.
4850
"""
49-
return any(
50-
(isinstance(base, cst.Name) and base.value == 'ConanFile')
51-
or (isinstance(base, cst.Attribute) and base.attr.value == 'ConanFile')
52-
for base in class_node.bases
53-
)
51+
return any((isinstance(base.value, cst.Name) and base.value.value == 'ConanFile') for base in class_node.bases)
5452

5553
def _update_requires(self, updated_node: cst.ClassDef) -> cst.ClassDef:
56-
"""Update or add the 'requires' attribute in the class definition.
54+
"""Update or add a 'requires' assignment in a ConanFile class definition."""
55+
# Check if 'requires' is already defined
56+
for body_statement_line in updated_node.body.body:
57+
if not isinstance(body_statement_line, cst.SimpleStatementLine):
58+
continue
59+
60+
assignment_statement = body_statement_line.body[0]
61+
if not isinstance(assignment_statement, cst.Assign):
62+
continue
63+
64+
for target in assignment_statement.targets:
65+
if not isinstance(target.target, cst.Name) or target.target.value != 'requires':
66+
continue
67+
68+
return self._replace_requires(updated_node, body_statement_line, assignment_statement)
69+
70+
# Find the last attribute assignment before methods
71+
last_attribute = None
72+
for body_statement_line in updated_node.body.body:
73+
if not isinstance(body_statement_line, cst.SimpleStatementLine):
74+
break
75+
assignment_statement = body_statement_line.body[0]
76+
if not isinstance(assignment_statement, cst.Assign):
77+
break
78+
last_attribute = body_statement_line
79+
80+
# Construct a new statement for the 'requires' attribute
81+
new_statement = cst.SimpleStatementLine(
82+
body=[self._create_requires_assignment()],
83+
)
5784

58-
Args:
59-
updated_node: The class definition to update.
85+
# Insert the new statement after the last attribute assignment
86+
if last_attribute is not None:
87+
new_body = list(updated_node.body.body)
88+
index = new_body.index(last_attribute)
89+
new_body.insert(index + 1, new_statement)
90+
else:
91+
new_body = [new_statement] + list(updated_node.body.body)
6092

61-
Returns: The updated class definition.
62-
"""
63-
for body_item in updated_node.body.body:
64-
if isinstance(body_item, cst.SimpleStatementLine):
65-
stmt = body_item.body[0]
66-
if isinstance(stmt, cst.Assign):
67-
for target in stmt.targets:
68-
if isinstance(target.target, cst.Name) and target.target.value == 'requires':
69-
return self._replace_requires(updated_node, body_item, stmt)
70-
71-
new_stmt = self._create_requires_assignment()
72-
return updated_node.with_changes(
73-
body=updated_node.body.with_changes(body=[new_stmt] + list(updated_node.body.body))
74-
)
93+
return updated_node.with_changes(body=updated_node.body.with_changes(body=new_body))
7594

7695
def _replace_requires(
77-
self, updated_node: cst.ClassDef, body_item: cst.SimpleStatementLine, stmt: cst.Assign
96+
self, updated_node: cst.ClassDef, body_statement_line: cst.SimpleStatementLine, assignment_statement: cst.Assign
7897
) -> cst.ClassDef:
7998
"""Replace the existing 'requires' assignment with a new one.
8099
81100
Args:
82101
updated_node (cst.ClassDef): The class definition to update.
83-
body_item (cst.SimpleStatementLine): The body item containing the assignment.
84-
stmt (cst.Assign): The existing assignment statement.
102+
body_statement_line (cst.SimpleStatementLine): The body item containing the assignment.
103+
assignment_statement (cst.Assign): The existing assignment statement.
85104
86105
Returns:
87106
cst.ClassDef: The updated class definition.
88107
"""
89-
new_value = cst.List([cst.Element(cst.SimpleString(f'"{dep.requires()}"')) for dep in self.dependencies])
90-
new_stmt = stmt.with_changes(value=new_value)
108+
new_value = cst.List([
109+
cst.Element(cst.SimpleString(f'"{dependency.requires()}"')) for dependency in self.dependencies
110+
])
111+
new_assignment = assignment_statement.with_changes(value=new_value)
91112
return updated_node.with_changes(
92113
body=updated_node.body.with_changes(
93-
body=[new_stmt if item is body_item else item for item in updated_node.body.body]
114+
body=[new_assignment if item is body_statement_line else item for item in updated_node.body.body]
94115
)
95116
)
96117

0 commit comments

Comments
 (0)