native test framework
This commit is contained in:
+56
-22
@@ -26,6 +26,7 @@ State :: struct {
|
||||
c_options: cimport.Options,
|
||||
selected: target.Target,
|
||||
project_root: string,
|
||||
mode: ast.Compile_Mode,
|
||||
record_identities: [dynamic]string,
|
||||
record_types: [dynamic]types.Type,
|
||||
root_failed: bool,
|
||||
@@ -1130,7 +1131,42 @@ load_header :: proc(state: ^State, path: string, import_span: source.Span) -> as
|
||||
return pkg_id
|
||||
}
|
||||
|
||||
load_package :: proc(state: ^State, path: string, import_span: source.Span, is_root := false) -> ast.Package_Id {
|
||||
resolve_package_imports :: proc(state: ^State, pkg_id: ast.Package_Id) {
|
||||
if int(pkg_id) >= len(state.module.packages) {
|
||||
return
|
||||
}
|
||||
canonical := state.module.packages[pkg_id].path
|
||||
import_count := len(state.module.imports)
|
||||
for import_id in 0..<import_count {
|
||||
import_item := state.module.imports[import_id]
|
||||
if import_item.pkg != pkg_id || import_item.target != ast.INVALID_PACKAGE ||
|
||||
import_item.test_only && (state.mode != .Test || !state.module.packages[pkg_id].test) {
|
||||
continue
|
||||
}
|
||||
if filepath.is_abs(import_item.path) {
|
||||
state.module.imports[import_id].diagnostic = source.add(state.diagnostics, import_item.span, "absolute import paths are invalid")
|
||||
state.module.imports[import_id].valid = false
|
||||
state.module.imports[import_id].target = add_placeholder(state, import_item.path)
|
||||
continue
|
||||
}
|
||||
target_path, target_ok := resolve_import_path(state, canonical, import_item.path)
|
||||
target := load_header(state, target_path, import_item.span) if filepath.ext(import_item.path) == ".h" else
|
||||
load_package(state, target_path, import_item.span, include_tests=import_item.test_only)
|
||||
state.module.imports[import_id].target = target
|
||||
if !target_ok || target == ast.INVALID_PACKAGE || !state.module.packages[target].available {
|
||||
state.module.imports[import_id].valid = false
|
||||
}
|
||||
delete(target_path, state.allocator)
|
||||
}
|
||||
}
|
||||
|
||||
load_package :: proc(
|
||||
state: ^State,
|
||||
path: string,
|
||||
import_span: source.Span,
|
||||
is_root := false,
|
||||
include_tests := false,
|
||||
) -> ast.Package_Id {
|
||||
canonical, ok := filepath.abs(path, state.allocator)
|
||||
if !ok || !os.is_dir(path) {
|
||||
if is_root {
|
||||
@@ -1152,6 +1188,10 @@ load_package :: proc(state: ^State, path: string, import_span: source.Span, is_r
|
||||
return id
|
||||
}
|
||||
if existing := find_package(state, canonical); existing != ast.INVALID_PACKAGE {
|
||||
if include_tests && !state.module.packages[existing].test {
|
||||
state.module.packages[existing].test = true
|
||||
resolve_package_imports(state, existing)
|
||||
}
|
||||
delete(canonical, state.allocator)
|
||||
return existing
|
||||
}
|
||||
@@ -1161,6 +1201,7 @@ load_package :: proc(state: ^State, path: string, import_span: source.Span, is_r
|
||||
path=canonical,
|
||||
name=symbol.intern(state.symbols, filepath.base(canonical)),
|
||||
available=true,
|
||||
test=state.mode == .Test && is_root || include_tests,
|
||||
})
|
||||
files, files_ok := read_package_files(state, canonical)
|
||||
if !files_ok {
|
||||
@@ -1204,26 +1245,7 @@ load_package :: proc(state: ^State, path: string, import_span: source.Span, is_r
|
||||
}
|
||||
os.file_info_slice_delete(files, state.allocator)
|
||||
|
||||
import_count := len(state.module.imports)
|
||||
for import_id in 0..<import_count {
|
||||
import_item := state.module.imports[import_id]
|
||||
if import_item.pkg != pkg_id || import_item.target != ast.INVALID_PACKAGE {
|
||||
continue
|
||||
}
|
||||
if filepath.is_abs(import_item.path) {
|
||||
state.module.imports[import_id].diagnostic = source.add(state.diagnostics, import_item.span, "absolute import paths are invalid")
|
||||
state.module.imports[import_id].valid = false
|
||||
state.module.imports[import_id].target = add_placeholder(state, import_item.path)
|
||||
continue
|
||||
}
|
||||
target_path, target_ok := resolve_import_path(state, canonical, import_item.path)
|
||||
target := load_header(state, target_path, import_item.span) if filepath.ext(import_item.path) == ".h" else load_package(state, target_path, import_item.span)
|
||||
state.module.imports[import_id].target = target
|
||||
if !target_ok || target == ast.INVALID_PACKAGE || !state.module.packages[target].available {
|
||||
state.module.imports[import_id].valid = false
|
||||
}
|
||||
delete(target_path, state.allocator)
|
||||
}
|
||||
resolve_package_imports(state, pkg_id)
|
||||
return pkg_id
|
||||
}
|
||||
|
||||
@@ -1248,6 +1270,9 @@ declaration_conflicts :: proc(module: ^ast.Module, pkg: ast.Package_Id, file: as
|
||||
|
||||
validate_imports :: proc(state: ^State) {
|
||||
for import_item, import_id in state.module.imports {
|
||||
if import_item.test_only {
|
||||
continue
|
||||
}
|
||||
if !symbol.is_valid(import_item.alias) && import_item.target != ast.INVALID_PACKAGE {
|
||||
state.module.imports[import_id].alias = state.module.packages[import_item.target].name
|
||||
}
|
||||
@@ -1287,7 +1312,7 @@ validate_imports :: proc(state: ^State) {
|
||||
|
||||
find_type_import :: proc(module: ^ast.Module, file: ast.File_Id, alias: symbol.Id) -> ast.Import_Id {
|
||||
for import_item, index in module.imports {
|
||||
if import_item.file == file && import_item.alias == alias {
|
||||
if !import_item.test_only && import_item.file == file && import_item.alias == alias {
|
||||
return ast.import_id(index)
|
||||
}
|
||||
}
|
||||
@@ -1879,6 +1904,7 @@ load :: proc(
|
||||
c_options := cimport.Options{},
|
||||
selected := target.DEFAULT,
|
||||
project_root_path := "",
|
||||
mode := ast.Compile_Mode.Executable,
|
||||
) -> (ast.Module, bool) {
|
||||
module := ast.init_module(allocator)
|
||||
project_root_source := project_root_path if len(project_root_path) > 0 else root_path
|
||||
@@ -1896,6 +1922,7 @@ load :: proc(
|
||||
c_options=c_options,
|
||||
selected=selected,
|
||||
project_root=project_root,
|
||||
mode=mode,
|
||||
}
|
||||
state.record_identities.allocator = allocator
|
||||
state.record_types.allocator = allocator
|
||||
@@ -1911,6 +1938,13 @@ load :: proc(
|
||||
if root != ast.Package_Id(0) && root != ast.INVALID_PACKAGE {
|
||||
state.root_failed = true
|
||||
}
|
||||
if mode == .Test {
|
||||
testing_path, testing_error := filepath.join({project_root, "std", "testing"}, allocator)
|
||||
if testing_error == nil {
|
||||
_ = load_package(&state, testing_path, source.Span{})
|
||||
delete(testing_path, allocator)
|
||||
}
|
||||
}
|
||||
validate_imports(&state)
|
||||
validate_declaration_aliases(&state)
|
||||
resolve_enum_values(&state)
|
||||
|
||||
Reference in New Issue
Block a user