Skip to content

Commit 942980f

Browse files
committed
Current version of AST does not always parse all nodes
1 parent 6cf363e commit 942980f

File tree

5 files changed

+389
-11
lines changed

5 files changed

+389
-11
lines changed

code_diff/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ def difference(source, target, lang = "guess", **kwargs):
1818
# Concretize Diff
1919
source_ast, target_ast = diff_search(source_ast, target_ast)
2020

21+
if source_ast is None:
22+
raise ValueError("Source and Target AST are identical.")
23+
2124
return ASTDiff(config, source_ast, target_ast)
2225

2326

@@ -79,6 +82,10 @@ def statement_diff(self):
7982
return ASTDiff(self.config, source_stmt, target_stmt)
8083

8184
def sstub_pattern(self):
85+
if (parent_statement(self.config.statement_types, self.source_ast) is None
86+
or parent_statement(self.config.statement_types, self.target_ast) is None):
87+
return SStubPattern.NO_STMT
88+
8289
if not self.is_single_statement:
8390
return SStubPattern.MULTI_STMT
8491

code_diff/ast.py

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,17 @@ def __init__(self, create_node_fn):
9898
self.child_count = defaultdict(int)
9999

100100
def _create_node(self, ast_node, text = None):
101+
102+
if ast_node.type == "comment": return # We ignore comments
103+
101104
node_key = _node_key(ast_node)
102105
children = [self.node_index[_node_key(c)] for c in ast_node.children
103106
if _node_key(c) in self.node_index]
104107

105108
position = (ast_node.start_point, ast_node.end_point)
106109
current_node = self.create_node_fn(ast_node.type, children, text = text, position = position)
110+
current_node.backend = ast_node
111+
107112
self.node_index[node_key] = current_node
108113

109114
# Add parent if ready
@@ -119,21 +124,51 @@ def _create_node(self, ast_node, text = None):
119124
self.root_node = current_node
120125

121126

127+
def _open_node(self, node):
128+
node_key = _node_key(node)
129+
if node_key in self.node_index: return False
130+
131+
opened = False
132+
for c in node.children:
133+
opened = opened or self._open_node(c)
134+
135+
if not opened:
136+
self.waitlist.append(node)
137+
return True
138+
139+
return False
140+
141+
def _open_root_if_not_complete(self, base_node):
142+
143+
root = base_node
144+
while root.parent is not None:
145+
root = root.parent
146+
147+
for c in root.children:
148+
self._open_node(c)
149+
122150
def __call__(self, tokens):
123151

124152
token_nodes = ((t.text, t.ast_node) for t in tokens if hasattr(t, "ast_node"))
125153
for token_text, token_ast in token_nodes:
126154
self._create_node(token_ast, text = token_text)
127155

128-
while len(self.waitlist) > 0:
129-
self._create_node(self.waitlist.pop(0))
130-
156+
while self.root_node is None:
157+
while len(self.waitlist) > 0:
158+
current_node = self.waitlist.pop(0)
159+
self._create_node(current_node)
160+
161+
self._open_root_if_not_complete(current_node)
162+
163+
print(self.root_node.sexp())
164+
131165
return self.root_node
132166

133167

134168

135169
# Interface ----------------------------------------------------------------
136170

171+
137172
def parse_ast(source_code, lang = "guess", **kwargs):
138173

139174
# Parse AST

code_diff/gumtree/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ def __init__(self, operations):
3838
super().__init__(operations)
3939

4040
def __repr__(self):
41-
return serialize_script(self)
41+
return serialize_script(self, indent = 2)

code_diff/gumtree/ops.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def _serialize_node(new_node_index, node):
5454
return _serialize_ast_node(node)
5555

5656

57-
def serialize_script(edit_script):
57+
def serialize_script(edit_script, indent = 0):
5858

5959
sedit_script = []
6060
new_node_index = {}
@@ -77,15 +77,19 @@ def serialize_script(edit_script):
7777
else: # Leaf node
7878
new_node_str = "%s:%s" % new_node
7979

80-
sedit_script.append("%s(%s, %s, %d)" % (operation_name, target_node_str, new_node_str, operation.position))
80+
sedit_script.append("%s(%s, %s, %d)" % (operation_name, new_node_str, target_node_str, operation.position))
8181

8282
elif operation_name == "Move":
8383

8484
new_node_str = _serialize_node(new_node_index, operation.node)
8585

86-
sedit_script.append("%s(%s, %s, %d)" % (operation_name, target_node_str, new_node_str, operation.position))
86+
sedit_script.append("%s(%s, %s, %d)" % (operation_name, new_node_str, target_node_str, operation.position))
8787

8888
elif operation_name == "Delete":
8989
sedit_script.append("%s(%s)" % (operation_name, target_node_str))
9090

91-
return json.dumps(sedit_script, indent=2)
91+
if indent > 0:
92+
sedit_script = [" "*indent + e for e in sedit_script]
93+
return "[\n%s\n]" % (",\n").join(sedit_script)
94+
95+
return "[%s]" % ", ".join(sedit_script)

0 commit comments

Comments
 (0)