feat: SQL between/hostvar-key alignment, class-condition parsing, gcov merge across scenario runs

This commit is contained in:
hangshuo652
2026-08-09 17:43:00 +08:00
parent f331c8fa2a
commit 273a3f8211
31 changed files with 3789 additions and 272 deletions
+69 -2
View File
@@ -26,12 +26,36 @@ def build_branch_tree_fallback(proc_text, fields=None):
pass
# New parser generates O(N) paths (not O(2^N)), so no cap needed.
# Just use it directly when it works.
# When new parser succeeds, also try the old parser with short timeout.
# If old parser succeeds and has more IF nodes, use it (new parser may miss
# nested ifs inside PERFORM UNTIL/SECTION blocks).
old_tree, old_assigns = None, {}
if new_tree is not None:
old_fallback, old_fb_assigns = None, {}
try:
import threading
r, e, d = [None], [None], [False]
def run():
try:
r[0] = old_build(proc_text, fields)
except Exception as ex:
e[0] = ex
d[0] = True
t = threading.Thread(target=run, daemon=True)
t.start(); t.join(3.0)
if d[0] and not e[0] and r[0]:
old_fallback, old_fb_assigns = r[0]
except Exception as e:
pass
if old_fallback is not None:
old_with_cond = _count_brif_with_cond(old_fallback)
new_with_cond = _count_brif_with_cond(new_tree)
if old_with_cond > new_with_cond:
logger.info(f" Old parser: {old_with_cond} BrIf with cond_tree vs new parser {new_with_cond}, using old parser")
return old_fallback, old_fb_assigns
return new_tree, new_assigns
# 2. Old parser with 3s timeout (fallback only)
old_tree, old_assigns = None, {}
try:
import threading
r, e, d = [None], [None], [False]
@@ -174,6 +198,49 @@ def _count_br_nodes(node) -> int:
return count
def _count_brif(node):
"""Count BrIf nodes in a branch tree."""
from .models import BrIf, BrSeq, BrEval, BrPerform, BrSearch
count = 0
if isinstance(node, BrIf):
count += 1
if isinstance(node, BrSeq):
for c in node.children: count += _count_brif(c)
if isinstance(node, BrIf):
count += _count_brif(node.true_seq) + _count_brif(node.false_seq)
if isinstance(node, BrEval):
for _, s in node.when_list: count += _count_brif(s)
count += _count_brif(node.other_seq)
if isinstance(node, BrPerform):
count += _count_brif(node.body_seq)
if isinstance(node, BrSearch):
count += _count_brif(node.at_end_seq)
for _, s in node.when_list: count += _count_brif(s)
return count
def _count_brif_with_cond(node):
"""Count BrIf nodes that have cond_tree set."""
from .models import BrIf, BrSeq, BrEval, BrPerform, BrSearch
count = 0
if isinstance(node, BrIf):
if node.cond_tree is not None:
count += 1
if isinstance(node, BrSeq):
for c in node.children: count += _count_brif_with_cond(c)
if isinstance(node, BrIf):
count += _count_brif_with_cond(node.true_seq) + _count_brif_with_cond(node.false_seq)
if isinstance(node, BrEval):
for _, s in node.when_list: count += _count_brif_with_cond(s)
count += _count_brif_with_cond(node.other_seq)
if isinstance(node, BrPerform):
count += _count_brif_with_cond(node.body_seq)
if isinstance(node, BrSearch):
count += _count_brif_with_cond(node.at_end_seq)
for _, s in node.when_list: count += _count_brif_with_cond(s)
return count
def _assigns_list_to_dict(assigns_list: list) -> dict:
result = {}
for a in assigns_list: