in src/models/source_code_unit.rs [199:261]
fn propagate(
&mut self, replace_range: Range, rule: InstantiatedRule, rules_store: &mut RuleStore,
parser: &mut Parser,
) {
let mut current_replace_range = replace_range;
let mut current_rule = rule.name();
let mut next_rules_stack: VecDeque<(CGPattern, InstantiatedRule)> = VecDeque::new();
// Perform the parent edits, while queueing the Method and Class level edits.
// let file_level_scope_names = [METHOD, CLASS];
loop {
debug!("Current Rule: {current_rule}");
// Get all the (next) rules that could be after applying the current rule (`rule`).
let next_rules_by_scope = self
.piranha_arguments
.rule_graph()
.get_next(¤t_rule, self.substitutions());
debug!(
"\n{}",
&next_rules_by_scope
.iter()
.map(|(k, v)| {
let rules = v.iter().map(|f| f.name()).join(", ");
format!("Next Rules:\n- Scope {k} \n- Rules {rules}").blue()
})
.join("\n")
);
// Adds rules of scope != ["Parent", "Global"] to the stack
self.add_rules_to_stack(
&next_rules_by_scope,
current_replace_range,
rules_store,
&mut next_rules_stack,
);
// Add Global rules as seed rules
for r in &next_rules_by_scope[GLOBAL] {
rules_store.add_to_global_rules(r);
}
// Process the parent
// Find the rules to be applied in the "Parent" scope that match any parent (context) of the changed node in the previous edit
if let Some(edit) =
self.get_edit_for_ancestors(¤t_replace_range, rules_store, &next_rules_by_scope)
{
self.rewrites_mut().push(edit.clone());
// Apply the matched rule to the parent
let applied_edit = self.apply_edit(&edit, parser);
current_replace_range = get_replace_range(applied_edit);
current_rule = edit.matched_rule().to_string();
// Add the (tag, code_snippet) mapping to substitution table.
self.substitutions.extend(edit.p_match().matches().clone());
} else {
break;
}
}
// Apply the next rules from the stack
for (sq, rle) in &next_rules_stack {
self.apply_rule(rle.clone(), rules_store, parser, &Some(sq.clone()));
}
}