lib/atp/processors/condition.rb in atp-0.2.0 vs lib/atp/processors/condition.rb in atp-0.2.1

- old
+ new

@@ -63,11 +63,13 @@ def on_boolean_condition(node) children = node.children.dup name = children.shift state = children.shift + remove_condition << node children = optimize_siblings(n(:temp, children)) + remove_condition.pop if condition_to_be_removed?(node) process_all(children) else node.updated(nil, [name, state] + process_all(children)) end @@ -77,11 +79,13 @@ alias_method :on_test_executed, :on_boolean_condition def on_condition(node) children = node.children.dup name = children.shift + remove_condition << node children = optimize_siblings(n(:temp, children)) + remove_condition.pop if condition_to_be_removed?(node) process_all(children) else node.updated(nil, [name] + process_all(children)) end @@ -98,11 +102,11 @@ end end end def condition_to_be_removed?(node) - remove_condition.last && equal_conditions?(remove_condition.last, node) + remove_condition.any? { |c| equal_conditions?(c, node) } end def equal_conditions?(node1, node2) if node1.type == node2.type if node1.type == :group || node1.type == :job @@ -116,15 +120,21 @@ def condition?(node) node.is_a?(ATP::AST::Node) && CONDITION_NODES.include?(node.type) end def on_flow(node) - node.updated(nil, optimize_siblings(node)) + # The extract_common_embedded_conditions method can probably do the whole job, + # but it might get a little complicated with regards to optimizing adjacent groups, + # so have left the original logic to have the first crack and deal with the groups + # for now. + nodes = optimize_siblings(node) + nodes = extract_common_embedded_conditions(nodes) + node.updated(nil, nodes) end def on_members(node) - node.updated(nil, optimize_siblings(node)) + node.updated(nil, extract_common_embedded_conditions(optimize_siblings(node))) end def optimize_siblings(top_node) children = [] unprocessed_children = [] @@ -162,9 +172,49 @@ children << process(node) end end end children.flatten + end + + def extract_common_embedded_conditions(nodes) + nodes = [nodes] unless nodes.is_a?(Array) + result = [] + cond_a = nil + test_a = nil + ConditionExtractor.new.run(nodes).each do |cond_b, test_b| + if cond_a + common = cond_a & cond_b + if common.empty? + result << combine(cond_a, extract_common_embedded_conditions(test_a)) + cond_a = cond_b + test_a = test_b + else + a = combine(cond_a - common, test_a) + b = combine(cond_b - common, test_b) + cond_a = common + test_a = [a, b].flatten + end + else + cond_a = cond_b + test_a = test_b + end + end + if nodes == [test_a] + nodes + else + result << combine(cond_a, extract_common_embedded_conditions(test_a)) + result.flatten + end + end + + def combine(conditions, node) + if conditions && !conditions.empty? + conditions.reverse_each do |n| + node = n.updated(nil, n.children + (node.is_a?(Array) ? node : [node])) + end + end + node end def remove_condition @remove_condition ||= [] end