file-local / package-local decls
This commit is contained in:
+40
-8
@@ -3251,6 +3251,7 @@ inferred_error_channels_reject_unstable_or_untyped_contracts :: proc(t: ^testing
|
||||
Case :: struct {
|
||||
source: string,
|
||||
message: string,
|
||||
absent: string,
|
||||
}
|
||||
cases := [?]Case{
|
||||
{
|
||||
@@ -3259,7 +3260,7 @@ fail func() void ! Error { return .failed }
|
||||
visible func() void! { try fail() }
|
||||
main func() void {}
|
||||
`,
|
||||
message="inferred error channels are only allowed on hidden functions and root main",
|
||||
message="inferred error channels are only allowed on local functions and root main",
|
||||
},
|
||||
{
|
||||
source=`Error :: enum { failed }
|
||||
@@ -3281,6 +3282,20 @@ main func() void { empty() catch |_| {} }
|
||||
`,
|
||||
message="could not infer a named error channel for 'empty'",
|
||||
},
|
||||
{
|
||||
source=`Error :: enum { failed }
|
||||
fail func() void ! Error { return .failed }
|
||||
value func() i32 { return 1 }
|
||||
main func() void! {
|
||||
fail() catch |_| {
|
||||
return
|
||||
}
|
||||
_ = try value()
|
||||
}
|
||||
`,
|
||||
message="could not infer a named error channel for 'main'",
|
||||
absent="non-void function must return a value",
|
||||
},
|
||||
}
|
||||
for test_case in cases {
|
||||
source_file := source.Source{path="test.bro", text=test_case.source}
|
||||
@@ -3291,10 +3306,14 @@ main func() void { empty() catch |_| {} }
|
||||
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
|
||||
|
||||
found := false
|
||||
unexpected := false
|
||||
for diagnostic in diagnostics.items {
|
||||
found = found || strings.contains(diagnostic.message, test_case.message)
|
||||
unexpected = unexpected ||
|
||||
len(test_case.absent) > 0 && strings.contains(diagnostic.message, test_case.absent)
|
||||
}
|
||||
testing.expect(t, found)
|
||||
testing.expect(t, !unexpected)
|
||||
|
||||
hir.destroy_module(&hir_module)
|
||||
ast.destroy_module(&ast_module)
|
||||
@@ -10345,14 +10364,18 @@ imports_are_file_local :: proc(t: ^testing.T) {
|
||||
}
|
||||
|
||||
@(test)
|
||||
hide_is_rejected_outside_named_top_level_declarations :: proc(t: ^testing.T) {
|
||||
visibility_modifiers_are_rejected_outside_named_top_level_declarations :: proc(t: ^testing.T) {
|
||||
cases := [?]string{
|
||||
`hide import "../dep"`,
|
||||
`hide dep :: import "../dep"`,
|
||||
`hide(file) dep :: import "../dep"`,
|
||||
`hide func() void {}`,
|
||||
`main func(hide value i32) void {}`,
|
||||
`Box :: struct { hide i32 }`,
|
||||
`main func() void { hide value i32 := 1 }`,
|
||||
`hide() value :: 1`,
|
||||
`hide(module) value :: 1`,
|
||||
`hide("file") value :: 1`,
|
||||
`hide(file value :: 1`,
|
||||
}
|
||||
for text in cases {
|
||||
source_file := source.Source{path="test.bro", text=text}
|
||||
@@ -10370,17 +10393,17 @@ hide_is_rejected_outside_named_top_level_declarations :: proc(t: ^testing.T) {
|
||||
}
|
||||
|
||||
@(test)
|
||||
hide_declarations_are_package_hidden :: proc(t: ^testing.T) {
|
||||
output := "/tmp/brolang-test-hidden-declarations"
|
||||
local_declarations_resolve_at_their_declared_scope :: proc(t: ^testing.T) {
|
||||
output := "/tmp/brolang-test-local-declarations"
|
||||
defer _ = os.remove(output)
|
||||
status := compiler_core.compile_package("examples/packages/hidden_valid/app", output)
|
||||
testing.expect_value(t, status, 0)
|
||||
state := run_executable(output)
|
||||
testing.expect_value(t, state.exit_code, 9)
|
||||
testing.expect_value(t, state.exit_code, 15)
|
||||
}
|
||||
|
||||
@(test)
|
||||
package_hidden_declarations_resolve_locally_but_not_through_imports :: proc(t: ^testing.T) {
|
||||
package_and_file_local_visibility_is_enforced :: proc(t: ^testing.T) {
|
||||
sources := source.init_store()
|
||||
defer source.destroy_store(&sources)
|
||||
diagnostics := source.init_store_diagnostics(&sources)
|
||||
@@ -10398,18 +10421,27 @@ package_hidden_declarations_resolve_locally_but_not_through_imports :: proc(t: ^
|
||||
found_sibling_type := false
|
||||
found_import := false
|
||||
found_collision := false
|
||||
found_file_sibling := false
|
||||
found_file_sibling_value := false
|
||||
found_file_sibling_type := false
|
||||
for diagnostic in diagnostics.items {
|
||||
found_sibling = found_sibling || strings.contains(diagnostic.message, "unknown symbol 'sibling'")
|
||||
found_sibling_value = found_sibling_value || strings.contains(diagnostic.message, "unknown symbol 'sibling_value'")
|
||||
found_sibling_type = found_sibling_type || strings.contains(diagnostic.message, "unknown or opaque record type 'Sibling'")
|
||||
found_import = found_import || strings.contains(diagnostic.message, "package 'dep' has no member 'secret'")
|
||||
found_collision = found_collision || strings.contains(diagnostic.message, "duplicate function 'collision'")
|
||||
found_file_sibling = found_file_sibling || strings.contains(diagnostic.message, "unknown symbol 'file_sibling'")
|
||||
found_file_sibling_value = found_file_sibling_value || strings.contains(diagnostic.message, "unknown symbol 'file_sibling_value'")
|
||||
found_file_sibling_type = found_file_sibling_type || strings.contains(diagnostic.message, "unknown or opaque record type 'File_Sibling'")
|
||||
}
|
||||
testing.expect(t, !found_sibling)
|
||||
testing.expect(t, !found_sibling_value)
|
||||
testing.expect(t, !found_sibling_type)
|
||||
testing.expect(t, found_import)
|
||||
testing.expect(t, found_collision)
|
||||
testing.expect(t, found_file_sibling)
|
||||
testing.expect(t, found_file_sibling_value)
|
||||
testing.expect(t, found_file_sibling_type)
|
||||
}
|
||||
|
||||
@(test)
|
||||
@@ -10704,7 +10736,7 @@ main func() void {}
|
||||
testing.expect(t, loaded)
|
||||
wants := []string{
|
||||
"has no member 'missing'",
|
||||
"is package-hidden",
|
||||
"is not public",
|
||||
"unknown symbol 'nope'",
|
||||
"unavailable imported package 'gone'",
|
||||
"package member 'dep.ambiguous' is ambiguous",
|
||||
|
||||
Reference in New Issue
Block a user