brokk-bifrost-cpp 0.14.2

C++ language knowledge for brokk-bifrost: declarations and macro-sentinel recovery, include-graph visibility, out-of-line member identity reconciliation, and usage-graph resolution
Documentation
//! Shared fixture and AST assertions for the pinned C++ grammar boundary tests.
use tree_sitter::{Node, Tree};

pub(crate) const SOURCE: &str = concat!(
    "// \u{3bb}: UTF-8 before every recovery span\n",
    "void fragment() { Widget(value); }\n",
    "struct Widget {\n",
    " CPPCHECKLIB static std::string toString(Yield yield);\n",
    " API ns::Widget(Value value) : item(value) {}\n",
    " MSC_WARNING(suppress : 26495) CONSTEXPR Widget(grow_fun grow) noexcept : size_(size), grow_(grow) {}\n",
    "};\n",
    "void ranges() {\n",
    " for (auto [key, value] : pairs) {}\n",
    " for (auto &same : same) {}\n",
    " for (auto *ptr : pointers) {}\n",
    " for (auto item [[maybe_unused]] : items) {}\n",
    " for (auto &\u{3bb} : values) {}\n",
    "}\n",
    "int numeric[] = {{1, -2}, {+3, 4}};\n",
    "int comment[] = {1, /* data */ 2};\n",
    "int names[] = {value};\n",
    "int calls[] = {make()};\n",
    "int broken[] = {1, @};\n",
    "int missing[] = {1 2};\n",
    "int spaced[] = {- 2, + 3};\n",
    "int missing_token[] = {call(1};\n",
);

pub(crate) fn tree(source: &str) -> Tree {
    crate::clones::cpp_clone_parser()
        .parse(source, None)
        .unwrap()
}

pub(crate) fn nodes(root: Node<'_>) -> Vec<Node<'_>> {
    let mut result = Vec::new();
    let mut stack = vec![root];
    while let Some(node) = stack.pop() {
        result.push(node);
        let mut cursor = node.walk();
        let children: Vec<_> = node.children(&mut cursor).collect();
        stack.extend(children.into_iter().rev());
    }
    result
}

pub(crate) fn at<'tree>(
    root: Node<'tree>,
    kind: &str,
    span: std::ops::Range<usize>,
) -> Node<'tree> {
    let found: Vec<_> = nodes(root)
        .into_iter()
        .filter(|node| node.kind() == kind && node.byte_range() == span)
        .collect();
    assert_eq!(found.len(), 1, "{kind} at {span:?}: {found:?}");
    found[0]
}

pub(crate) fn field(node: Node<'_>, name: &str, kind: &str, span: std::ops::Range<usize>) {
    let child = node.child_by_field_name(name).expect(name);
    assert_eq!((child.kind(), child.byte_range()), (kind, span));
}