mun_hir 0.4.0

Provides high-level intermediate representation of Mun code
Documentation
use crate::with_fixture::WithFixture;
use crate::{
    item_tree::Fields,
    item_tree::{ItemTree, ModItem},
    mock::MockDatabase,
    DefDatabase,
};
use std::{fmt, fmt::Write, sync::Arc};

fn item_tree(text: &str) -> Arc<ItemTree> {
    let (db, file_id) = MockDatabase::with_single_file(text);
    db.item_tree(file_id)
}

fn print_item_tree(text: &str) -> Result<String, fmt::Error> {
    let tree = item_tree(text);
    let mut out = String::new();
    writeln!(&mut out, "top-level items:")?;
    for item in tree.top_level_items() {
        format_mod_item(&mut out, &tree, *item)?;
        writeln!(&mut out)?;
    }

    Ok(out)
}

fn format_mod_item(out: &mut String, tree: &ItemTree, item: ModItem) -> fmt::Result {
    let mut children = String::new();
    match item {
        ModItem::Function(item) => {
            write!(out, "{:?}", tree[item])?;
        }
        ModItem::Struct(item) => {
            write!(out, "{:?}", tree[item])?;
            match &tree[item].fields {
                Fields::Record(a) | Fields::Tuple(a) => {
                    for field in a.clone() {
                        writeln!(children, "{:?}", tree[field])?;
                    }
                }
                _ => {}
            };
        }
        ModItem::TypeAlias(item) => {
            write!(out, "{:?}", tree[item])?;
        }
        ModItem::Import(item) => {
            write!(out, "{:?}", tree[item])?;
        }
    }

    for line in children.lines() {
        write!(out, "\n> {}", line)?;
    }

    Ok(())
}

#[test]
fn top_level_items() {
    insta::assert_snapshot!(print_item_tree(
        r#"
    fn foo(a:i32, b:u8, c:String) -> i32 {}
    pub fn bar(a:i32, b:u8, c:String) ->  {}
    pub(super) fn bar(a:i32, b:u8, c:String) ->  {}
    pub(package) fn baz(a:i32, b:, c:String) ->  {}
    extern fn eval(a:String) -> bool;

    struct Foo {
        a: i32,
        b: u8,
        c: String,
    }
    struct Foo2 {
        a: i32,
        b: ,
        c: String,
    }
    struct Bar (i32, u32, String)
    struct Baz;

    type FooBar = Foo;
    type FooBar = package::Foo;
    "#
    )
    .unwrap());
}