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
})
}
#[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, .. }
));
});
}
#[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, ...
"#,
);
}
#[test]
fn parse_const_function() {
parse_const_ok("const function f() return 42 end");
}
#[test]
fn parse_const_function_with_attr() {
parse_const_ok(
r#"
@deprecated
const function f() return 42 end
"#,
);
}
#[test]
fn parse_local_const() {
parse_const_ok("local const");
}
#[test]
fn parse_const_call() {
parse_const_ok(
r#"
local const = function(t) return t end
const { a = "a" }
"#,
);
}
#[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
"#,
);
}
#[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");
}
}
#[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");
}
}
#[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");
}