veryl-formatter 0.20.0

A modern hardware description language
Documentation
use crate::Formatter;
use veryl_analyzer::{Analyzer, Context};
use veryl_metadata::Metadata;
use veryl_parser::Parser;

#[track_caller]
fn format(metadata: &Metadata, code: &str) -> String {
    let parser = Parser::parse(&code, &"").unwrap();
    let analyzer = Analyzer::new(metadata);
    let mut context = Context::default();

    analyzer.analyze_pass1(&"prj", &parser.veryl);
    Analyzer::analyze_post_pass1();
    analyzer.analyze_pass2(&"prj", &parser.veryl, &mut context, None);

    let mut formatter = Formatter::new(metadata);
    formatter.format(&parser.veryl, code);
    formatter.as_str().to_string()
}

#[test]
fn empty_body_with_comment() {
    let code = r#"module ModuleA {
    /* */
}
"#;
    let expect = r#"module ModuleA {
    /* */
}
"#;

    let metadata = Metadata::create_default("prj").unwrap();

    let ret = format(&metadata, &code);
    assert_eq!(ret, expect);

    let code = r#"module ModuleA {
    /* foo */
    /* bar */
}
"#;
    let expect = r#"module ModuleA {
    /* foo */
    /* bar */
}
"#;

    let metadata = Metadata::create_default("prj").unwrap();

    let ret = format(&metadata, &code);
    assert_eq!(ret, expect);

    let code = r#"module ModuleA {
    /* foo */
    // bar
}
"#;
    let expect = r#"module ModuleA {
    /* foo */
    // bar
}
"#;

    let metadata = Metadata::create_default("prj").unwrap();

    let ret = format(&metadata, &code);
    assert_eq!(ret, expect);
}

#[test]
fn empty_list() {
    let code = r#"module ModuleA #(

) (

) {

}
module ModuleB {
  inst u: ModuleA #(

    ) (

    );

    function Func (

    ) {

    }

    always_comb {
        Func(

        );
    }
}
"#;

    let expect = r#"module ModuleA #() () {}
module ModuleB {
    inst u: ModuleA ;

    function Func () {}

    always_comb {
        Func();
    }
}
"#;

    let metadata = Metadata::create_default("prj").unwrap();

    let ret = format(&metadata, &code);

    println!("ret\n{}\nexp\n{}", ret, expect);
    assert_eq!(ret, expect);
}

#[test]
fn skip_formatting() {
    let code = r#"#[fmt(skip)]
module ModuleA {
    let _a: logic = 0;
}

#[fmt(skip)]
interface InterfaceA {
    var a: logic;

    modport mp {
        a: input
    }
}

#[fmt(skip)]
package PackageA {
    const A: u32 = 0;

    function FuncA(
        a: input u32,
        b: input u32
    ) -> u32 {
        return a + b;
    }
}
"#;

    let mut metadata = Metadata::create_default("prj").unwrap();

    metadata.format.indent_width = 2;

    let ret = format(&metadata, &code);

    println!("ret\n{}\nexp\n{}", ret, code);
    assert_eq!(ret, code);

    let code = r#"#[fmt(skip)]
module ModuleA () {
    /* this comment line is important */
}
#[fmt(skip)]
module ModuleB () {
    // this comment line is important
}
"#;

    let mut metadata = Metadata::create_default("prj").unwrap();

    metadata.format.indent_width = 2;

    let ret = format(&metadata, &code);

    println!("ret\n{}\nexp\n{}", ret, code);
    assert_eq!(ret, code);
}

#[test]
fn no_panic_if_expression_when_vertical_align_off() {
    let code = r#"module ModuleA {
    let a: logic = 1;
    let _b: logic = if a == 1 ? 1 : if a == 2 ? 0 : 1;
}
"#;

    let mut metadata = Metadata::create_default("prj").unwrap();
    metadata.format.vertical_align = false;

    let ret = format(&metadata, code);
    assert!(!ret.is_empty());
}

#[test]
fn const_above_let_alignment() {
    let code = r#"module TopModule {
    const _c: u32 = 0;
    let _a: logic = 0;
    let _abcd: logic = 0;
}
"#;

    let expect = r#"module TopModule {
    const _c   : u32   = 0;
    let   _a   : logic = 0;
    let   _abcd: logic = 0;
}
"#;

    let metadata = Metadata::create_default("prj").unwrap();

    let ret = format(&metadata, code);
    assert_eq!(ret, expect);
}

#[test]
fn format_generic_list() {
    let metadata = Metadata::create_default("prj").unwrap();

    let code = r#"module ModuleA::<A : a_type, AA: u32,> {}
"#;

    let expect = r#"module ModuleA::<A: a_type, AA: u32> {}
"#;

    let ret = format(&metadata, &code);
    assert_eq!(ret, expect);

    let code = r#"module ModuleA::<
    A: a_type,
    AA: u32
> {}
"#;

    let expect = r#"module ModuleA::<
    A : a_type,
    AA: u32   ,
> {}
"#;

    let ret = format(&metadata, &code);
    assert_eq!(ret, expect);

    let code = r#"alias module ModuleA = ModuleB::<8, 16,>;
"#;

    let expect = r#"alias module ModuleA = ModuleB::<8, 16>;
"#;

    let ret = format(&metadata, &code);
    assert_eq!(ret, expect);

    let code = r#"alias module ModuleB = ModuleC::<
    8,
    16
>;
"#;

    let expect = r#"alias module ModuleB = ModuleC::<
    8 ,
    16,
>;
"#;

    let ret = format(&metadata, &code);
    assert_eq!(ret, expect);
}