GCC Code Coverage Report


Directory: ../
File: src/importcollector/ImportCollector.cpp
Date: 2025-06-14 23:29:02
Exec Total Coverage
Lines: 51 54 94.4%
Functions: 3 3 100.0%
Branches: 97 174 55.7%

Line Branch Exec Source
1 // Copyright (c) 2021-2025 ChilliBits. All rights reserved.
2
3 #include "ImportCollector.h"
4
5 #include <SourceFile.h>
6 #include <ast/ASTNodes.h>
7 #include <ast/Attributes.h>
8 #include <exception/SemanticError.h>
9 #include <global/GlobalResourceManager.h>
10 #include <util/FileUtil.h>
11
12 namespace spice::compiler {
13
14 1059 std::any ImportCollector::visitEntry(EntryNode *node) {
15 // Visit all module attributes
16
2/2
✓ Branch 0 (9→4) taken 304 times.
✓ Branch 1 (9→10) taken 1059 times.
1363 for (ModAttrNode *attr : node->modAttrs)
17
1/2
✓ Branch 0 (5→6) taken 304 times.
✗ Branch 1 (5→21) not taken.
304 visit(attr);
18
19 // Visit all import defs
20
2/2
✓ Branch 0 (17→12) taken 526 times.
✓ Branch 1 (17→18) taken 1054 times.
1580 for (ImportDefNode *importDef : node->importDefs)
21
2/2
✓ Branch 0 (13→14) taken 521 times.
✓ Branch 1 (13→23) taken 5 times.
526 visit(importDef);
22
23
1/2
✓ Branch 0 (18→19) taken 1054 times.
✗ Branch 1 (18→25) not taken.
1054 return nullptr;
24 }
25
26 526 std::any ImportCollector::visitImportDef(ImportDefNode *node) {
27 526 const bool isStd = node->importPath.starts_with("std/");
28 526 const bool isBootstrap = node->importPath.starts_with("bootstrap/");
29
30 526 std::filesystem::path basePath;
31
2/2
✓ Branch 0 (5→6) taken 477 times.
✓ Branch 1 (5→27) taken 49 times.
526 if (isStd) { // Include source file from standard library
32 // Find std library
33
1/2
✓ Branch 0 (6→7) taken 477 times.
✗ Branch 1 (6→171) not taken.
477 const std::filesystem::path stdPath = FileUtil::getStdDir();
34
1/2
✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→17) taken 477 times.
477 if (stdPath.empty())
35 throw CompilerError(STD_NOT_FOUND, "Standard library could not be found. Check if the env var SPICE_STD_DIR exists");
36 // Format: /dir/to/path/file
37
3/6
✓ Branch 0 (18→19) taken 477 times.
✗ Branch 1 (18→166) not taken.
✓ Branch 2 (19→20) taken 477 times.
✗ Branch 3 (19→164) not taken.
✓ Branch 4 (20→21) taken 477 times.
✗ Branch 5 (20→162) not taken.
477 basePath = stdPath / node->importPath.substr(node->importPath.find("std/") + 4);
38
2/2
✓ Branch 0 (27→28) taken 18 times.
✓ Branch 1 (27→49) taken 31 times.
526 } else if (isBootstrap) { // Include source file from bootstrap library
39 // Find bootstrap library
40
1/2
✓ Branch 0 (28→29) taken 18 times.
✗ Branch 1 (28→190) not taken.
18 const std::filesystem::path bootstrapPath = FileUtil::getBootstrapDir();
41
1/2
✗ Branch 0 (30→31) not taken.
✓ Branch 1 (30→39) taken 18 times.
18 if (bootstrapPath.empty())
42 throw CompilerError(BOOTSTRAP_NOT_FOUND,
43 "Bootstrap compiler could not be found. Check if the env var SPICE_BOOTSTRAP_DIR exists");
44 // Format: /dir/to/path/file
45
3/6
✓ Branch 0 (40→41) taken 18 times.
✗ Branch 1 (40→185) not taken.
✓ Branch 2 (41→42) taken 18 times.
✗ Branch 3 (41→183) not taken.
✓ Branch 4 (42→43) taken 18 times.
✗ Branch 5 (42→181) not taken.
18 basePath = bootstrapPath / node->importPath.substr(node->importPath.find("bootstrap/") + 10);
46 18 } else { // Include own source file
47 // Format: /dir/to/path/file
48
3/6
✓ Branch 0 (49→50) taken 31 times.
✗ Branch 1 (49→196) not taken.
✓ Branch 2 (50→51) taken 31 times.
✗ Branch 3 (50→193) not taken.
✓ Branch 4 (51→52) taken 31 times.
✗ Branch 5 (51→191) not taken.
31 basePath = sourceFile->filePath.parent_path() / node->importPath;
49 }
50 526 basePath.make_preferred();
51
52 // Format: /dir/to/path/file.spice
53
1/2
✓ Branch 0 (58→59) taken 526 times.
✗ Branch 1 (58→282) not taken.
526 std::filesystem::path defaultPath = basePath;
54
5/10
✓ Branch 0 (59→60) taken 526 times.
✗ Branch 1 (59→206) not taken.
✓ Branch 2 (60→61) taken 526 times.
✗ Branch 3 (60→204) not taken.
✓ Branch 4 (61→62) taken 526 times.
✗ Branch 5 (61→202) not taken.
✓ Branch 6 (62→63) taken 526 times.
✗ Branch 7 (62→200) not taken.
✓ Branch 8 (63→64) taken 526 times.
✗ Branch 9 (63→198) not taken.
526 defaultPath.replace_filename(basePath.stem().string() + ".spice");
55 // Format: /dir/to/path/file_linux.spice
56
1/2
✓ Branch 0 (68→69) taken 526 times.
✗ Branch 1 (68→280) not taken.
526 std::filesystem::path osPath = basePath;
57
7/14
✓ Branch 0 (69→70) taken 526 times.
✗ Branch 1 (69→222) not taken.
✓ Branch 2 (70→71) taken 526 times.
✗ Branch 3 (70→220) not taken.
✓ Branch 4 (71→72) taken 526 times.
✗ Branch 5 (71→218) not taken.
✓ Branch 6 (72→73) taken 526 times.
✗ Branch 7 (72→216) not taken.
✓ Branch 8 (73→74) taken 526 times.
✗ Branch 9 (73→214) not taken.
✓ Branch 10 (74→75) taken 526 times.
✗ Branch 11 (74→212) not taken.
✓ Branch 12 (75→76) taken 526 times.
✗ Branch 13 (75→210) not taken.
526 osPath.replace_filename(basePath.stem().string() + "_" + cliOptions.targetOs + ".spice");
58 // Format: /dir/to/path/file_linux_x86_64.spice
59
1/2
✓ Branch 0 (82→83) taken 526 times.
✗ Branch 1 (82→278) not taken.
526 std::filesystem::path osArchPath = basePath;
60
9/18
✓ Branch 0 (83→84) taken 526 times.
✗ Branch 1 (83→244) not taken.
✓ Branch 2 (84→85) taken 526 times.
✗ Branch 3 (84→242) not taken.
✓ Branch 4 (85→86) taken 526 times.
✗ Branch 5 (85→240) not taken.
✓ Branch 6 (86→87) taken 526 times.
✗ Branch 7 (86→238) not taken.
✓ Branch 8 (87→88) taken 526 times.
✗ Branch 9 (87→236) not taken.
✓ Branch 10 (88→89) taken 526 times.
✗ Branch 11 (88→234) not taken.
✓ Branch 12 (89→90) taken 526 times.
✗ Branch 13 (89→232) not taken.
✓ Branch 14 (90→91) taken 526 times.
✗ Branch 15 (90→230) not taken.
✓ Branch 16 (91→92) taken 526 times.
✗ Branch 17 (91→228) not taken.
526 osArchPath.replace_filename(basePath.stem().string() + "_" + cliOptions.targetOs + "_" + cliOptions.targetArch + ".spice");
61
62 // Check which source file to import
63 526 std::filesystem::path importPath;
64
7/10
✓ Branch 0 (101→102) taken 526 times.
✗ Branch 1 (101→274) not taken.
✓ Branch 2 (102→103) taken 1 times.
✓ Branch 3 (102→106) taken 525 times.
✓ Branch 4 (103→104) taken 1 times.
✗ Branch 5 (103→274) not taken.
✓ Branch 6 (104→105) taken 1 times.
✗ Branch 7 (104→106) not taken.
✓ Branch 8 (107→108) taken 1 times.
✓ Branch 9 (107→109) taken 525 times.
526 if (exists(osArchPath) && !equivalent(sourceFile->filePath, osArchPath)) // file_os_arch.spice is first choice
65
1/2
✓ Branch 0 (108→127) taken 1 times.
✗ Branch 1 (108→274) not taken.
1 importPath = osArchPath;
66
7/10
✓ Branch 0 (109→110) taken 525 times.
✗ Branch 1 (109→274) not taken.
✓ Branch 2 (110→111) taken 21 times.
✓ Branch 3 (110→114) taken 504 times.
✓ Branch 4 (111→112) taken 21 times.
✗ Branch 5 (111→274) not taken.
✓ Branch 6 (112→113) taken 21 times.
✗ Branch 7 (112→114) not taken.
✓ Branch 8 (115→116) taken 21 times.
✓ Branch 9 (115→117) taken 504 times.
525 else if (exists(osPath) && !equivalent(sourceFile->filePath, osPath)) // file_os.spice is second choice
67
1/2
✓ Branch 0 (116→127) taken 21 times.
✗ Branch 1 (116→274) not taken.
21 importPath = osPath;
68
3/4
✓ Branch 0 (117→118) taken 504 times.
✗ Branch 1 (117→274) not taken.
✓ Branch 2 (118→119) taken 502 times.
✓ Branch 3 (118→120) taken 2 times.
504 else if (exists(defaultPath)) // file.spice is third choice
69
1/2
✓ Branch 0 (119→127) taken 502 times.
✗ Branch 1 (119→274) not taken.
502 importPath = defaultPath;
70 else
71
3/6
✓ Branch 0 (121→122) taken 2 times.
✗ Branch 1 (121→257) not taken.
✓ Branch 2 (122→123) taken 2 times.
✗ Branch 3 (122→255) not taken.
✓ Branch 4 (123→124) taken 2 times.
✗ Branch 5 (123→252) not taken.
2 throw SemanticError(node, IMPORTED_FILE_NOT_EXISTING, "The source file '" + node->importPath + ".spice' does not exist");
72
73 // Check if the import already exists
74
1/2
✓ Branch 0 (127→128) taken 524 times.
✗ Branch 1 (127→274) not taken.
524 SymbolTableEntry *importEntry = rootScope->lookupStrict(node->importName);
75
2/2
✓ Branch 0 (130→131) taken 2 times.
✓ Branch 1 (130→138) taken 522 times.
524 if (importEntry != nullptr)
76
3/6
✓ Branch 0 (132→133) taken 2 times.
✗ Branch 1 (132→266) not taken.
✓ Branch 2 (133→134) taken 2 times.
✗ Branch 3 (133→264) not taken.
✓ Branch 4 (134→135) taken 2 times.
✗ Branch 5 (134→261) not taken.
2 throw SemanticError(node, DUPLICATE_IMPORT_NAME, "Duplicate import '" + node->importName + "'");
77
78 // Create symbol for import
79
1/2
✓ Branch 0 (138→139) taken 522 times.
✗ Branch 1 (138→274) not taken.
522 node->entry = rootScope->insert(node->importName, node);
80
81 // Create the imported source file
82
1/2
✓ Branch 0 (141→142) taken 522 times.
✗ Branch 1 (141→274) not taken.
522 const auto importedSourceFile = resourceManager.createSourceFile(sourceFile, node->importName, importPath, isStd);
83 // Register it as a dependency to the current source file
84
3/4
✓ Branch 0 (142→143) taken 522 times.
✗ Branch 1 (142→272) not taken.
✓ Branch 2 (143→144) taken 521 times.
✓ Branch 3 (143→270) taken 1 times.
523 sourceFile->addDependency(importedSourceFile, node, node->importName, importPath.generic_string());
85
86
1/2
✓ Branch 0 (145→146) taken 521 times.
✗ Branch 1 (145→273) not taken.
1042 return nullptr;
87 546 }
88
89 304 std::any ImportCollector::visitModAttr(ModAttrNode *node) {
90 // !!! Only bool attributes allowed here, due to missing attribute value checks being executed in a later stage !!!
91
92 // core.compiler.keep-on-name-collision
93
4/6
✓ Branch 0 (4→5) taken 304 times.
✗ Branch 1 (4→35) not taken.
✓ Branch 2 (5→6) taken 304 times.
✗ Branch 3 (5→33) not taken.
✓ Branch 4 (8→9) taken 296 times.
✓ Branch 5 (8→16) taken 8 times.
912 if (node->attrLst->hasAttr(ATTR_CORE_COMPILER_KEEP_ON_NAME_COLLISION)) {
94
2/4
✓ Branch 0 (11→12) taken 296 times.
✗ Branch 1 (11→41) not taken.
✓ Branch 2 (12→13) taken 296 times.
✗ Branch 3 (12→39) not taken.
592 const bool keepOnCollision = node->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_KEEP_ON_NAME_COLLISION)->boolValue;
95 296 sourceFile->alwaysKeepSymbolsOnNameCollision = keepOnCollision;
96 }
97
98 // core.compiler.warnings.ignore
99
4/6
✓ Branch 0 (18→19) taken 304 times.
✗ Branch 1 (18→47) not taken.
✓ Branch 2 (19→20) taken 304 times.
✗ Branch 3 (19→45) not taken.
✓ Branch 4 (22→23) taken 2 times.
✓ Branch 5 (22→30) taken 302 times.
912 if (node->attrLst->hasAttr(ATTR_CORE_COMPILER_WARNINGS_IGNORE)) {
100
2/4
✓ Branch 0 (25→26) taken 2 times.
✗ Branch 1 (25→53) not taken.
✓ Branch 2 (26→27) taken 2 times.
✗ Branch 3 (26→51) not taken.
4 const bool ignoreWarnings = node->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_WARNINGS_IGNORE)->boolValue;
101 2 sourceFile->ignoreWarnings = ignoreWarnings;
102 }
103
104
1/2
✓ Branch 0 (30→31) taken 304 times.
✗ Branch 1 (30→57) not taken.
304 return nullptr;
105 }
106
107 } // namespace spice::compiler
108