(self, ast_patch:ASTPatch, ast_ctx:ASTContext)
| 124 | return relpos |
| 125 | |
| 126 | def apply_patch(self, ast_patch:ASTPatch, ast_ctx:ASTContext) -> bool: |
| 127 | # restart from root, if user modified AST in scheme callback |
| 128 | # assuming that user only gives us scheme patch, when it actually happened |
| 129 | if ast_patch.ptype is ast_patch.PatchType.SCHEME_MODIFIED: |
| 130 | self.restart_iteration() |
| 131 | return True |
| 132 | |
| 133 | # sanity check, None is only for scheme callbacks |
| 134 | assert ast_patch.item is not None |
| 135 | |
| 136 | # if iteration ended, then cant decide about reiteration |
| 137 | # just do the patch |
| 138 | if len(self.path) == 0: |
| 139 | print("[!] WARNING: patching AST, that already finished iteration") |
| 140 | return ast_patch.do_patch(ast_ctx) |
| 141 | |
| 142 | item_path = self.get_item_path(ast_patch.item) |
| 143 | if len(item_path) == 0: |
| 144 | print("[!] WARNING: patching AST with items, that dont match") |
| 145 | rv = ast_patch.do_patch(ast_ctx) |
| 146 | self.restart_iteration() |
| 147 | return rv |
| 148 | |
| 149 | if not ast_patch.do_patch(ast_ctx): |
| 150 | return False |
| 151 | |
| 152 | # if context is changed, then reiterate from scratch |
| 153 | if ast_ctx.is_modified: |
| 154 | ast_ctx.rebuild() |
| 155 | ast_ctx.is_modified = False |
| 156 | self.restart_iteration() |
| 157 | return True |
| 158 | |
| 159 | relpos = self.get_relative_position(item_path, ast_ctx) |
| 160 | # if item is yet to be iterated, then nothing needs to change |
| 161 | if relpos is RelativePosition.AHEAD: |
| 162 | return True |
| 163 | |
| 164 | # otherwise current/parent/behind is modified/removed |
| 165 | # that means that it is already iterated over |
| 166 | # thus reiteration (aka rebuilding self.path) is needed |
| 167 | |
| 168 | # if instruction is removed |
| 169 | if ast_patch.new_item is None: |
| 170 | # popping deleted instruction |
| 171 | item_path.pop() |
| 172 | |
| 173 | # higher than deleted instruction comes its parent block |
| 174 | parent_block, child_idx = item_path[-1] |
| 175 | |
| 176 | children = get_children(parent_block)[child_idx] |
| 177 | |
| 178 | # if removed instr is not last, then traverse next |
| 179 | if len(children) != child_idx: |
| 180 | child = children[child_idx] |
| 181 | item_path += build_path(child) |
| 182 | |
| 183 | # if removed instr is last, then next goes iteration over its |
no test coverage detected