luau-syntax 0.732.0

Luau lexer, parser, AST, CST, and source utilities
Documentation
use super::super::common::*;
use luau_common::flags;

fn with_parse_const_ok<R>(source: &str, f: impl for<'ast> FnOnce(ParseResult<'ast>) -> R) -> R {
    let _export = flags::LuauExportValueSyntax.scoped(true);
    with_parse(source, ParseOptions::default(), |result| f(result.unwrap()))
}

fn parse_const_ok(source: &str) {
    with_parse_const_ok(source, |_| {})
}

fn parse_const_errors(source: &str) -> Vec<ParseError> {
    let _export = flags::LuauExportValueSyntax.scoped(true);
    with_parse(source, ParseOptions::default(), |result| {
        result.unwrap().metadata.errors
    })
}

// Parser.test.cpp: parse_const
#[test]
fn parse_const() {
    with_parse_const_ok("const f = 42", |result| {
        let [statement] = statement_kinds(result.root.as_slice()).exact();
        let local = statement.as_local().expect("expected const local");
        assert_eq!(local.bindings.len(), 1);
        assert_eq!(local.bindings[0].name, "f");
        assert!(local.bindings[0].is_const);
        assert_eq!(local.values.len(), 1);
        assert!(matches!(
            local.values[0].kind(),
            ExpressionKind::Number { value: 42.0, .. }
        ));
    });
}
// Parser.test.cpp: parse_const_multi_initialize
#[test]
fn parse_const_multi_initialize() {
    parse_const_ok(
        r#"
const a, b = 42, 32
const a, b, c = 42, f()
const a, b, c = 42, ...
"#,
    );
}
// Parser.test.cpp: parse_const_function
#[test]
fn parse_const_function() {
    parse_const_ok("const function f() return 42 end");
}
// Parser.test.cpp: parse_const_function_with_attr
#[test]
fn parse_const_function_with_attr() {
    parse_const_ok(
        r#"
@deprecated
const function f() return 42 end
"#,
    );
}
// Parser.test.cpp: parse_local_const
#[test]
fn parse_local_const() {
    parse_const_ok("local const");
}
// Parser.test.cpp: parse_const_call
#[test]
fn parse_const_call() {
    parse_const_ok(
        r#"
local const = function(t) return t end
const { a = "a" }
"#,
    );
}
// Parser.test.cpp: const_shadow
#[test]
fn const_shadow() {
    parse_const_ok(
        r#"
const a = 42
const a = 43

do
    const a = 44
    do
        local a = 44.1
        do
            const a = 44.2
        end
        a = 44.3
    end
end

function f()
    const a = 45
    local a = 46
    return function(x) a = x end
end
"#,
    );
}
// Parser.test.cpp: error_const_not_initialized
#[test]
fn error_const_not_initialized() {
    for source in [
        "const c",
        "const a, b = nil",
        "const a, b, c = f(), 42",
        "const a, b, c = ..., 42",
    ] {
        parse_const_errors(source).assert_first_message("Missing initializer in const declaration");
    }
}

// Parser.test.cpp: error_const_reassignment
#[test]
fn error_const_reassignment() {
    for source in [
        "const a = 42; a = 43",
        "local b; const a = 42; a, b = 43",
        "local b; const a = 42; b, a = 43",
        "local b; const a = 42; b, a = ...",
        "const a = 42; function a() end",
    ] {
        parse_const_errors(source)
            .assert_first_message("Variable 'a' is constant and may not be reassigned");
    }
}
// Parser.test.cpp: error_const_function_reassignment
#[test]
fn error_const_function_reassignment() {
    parse_const_errors("const function a() return 42 end; a = 43")
        .assert_first_message("Variable 'a' is constant and may not be reassigned");
}