GCC Code Coverage Report


Directory: ../
File: src/importcollector/ImportCollector.cpp
Date: 2025-02-09 04:23:07
Exec Total Coverage
Lines: 50 54 92.6%
Functions: 3 3 100.0%
Branches: 92 174 52.9%

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 <util/FileUtil.h>
10
11 namespace spice::compiler {
12
13 1015 std::any ImportCollector::visitEntry(EntryNode *node) {
14 // Visit all module attributes
15
2/2
✓ Branch 0 (9→4) taken 294 times.
✓ Branch 1 (9→10) taken 1015 times.
1309 for (ModAttrNode *attr : node->modAttrs)
16
1/2
✓ Branch 0 (5→6) taken 294 times.
✗ Branch 1 (5→21) not taken.
294 visit(attr);
17
18 // Visit all import defs
19
2/2
✓ Branch 0 (17→12) taken 476 times.
✓ Branch 1 (17→18) taken 1010 times.
1486 for (ImportDefNode *importDef : node->importDefs)
20
2/2
✓ Branch 0 (13→14) taken 471 times.
✓ Branch 1 (13→23) taken 5 times.
476 visit(importDef);
21
22
1/2
✓ Branch 0 (18→19) taken 1010 times.
✗ Branch 1 (18→25) not taken.
1010 return nullptr;
23 }
24
25 476 std::any ImportCollector::visitImportDef(ImportDefNode *node) {
26 476 const bool isStd = node->importPath.starts_with("std/");
27 476 const bool isBootstrap = node->importPath.starts_with("bootstrap/");
28
29 476 std::filesystem::path basePath;
30
2/2
✓ Branch 0 (5→6) taken 427 times.
✓ Branch 1 (5→27) taken 49 times.
476 if (isStd) { // Include source file from standard library
31 // Find std library
32
1/2
✓ Branch 0 (6→7) taken 427 times.
✗ Branch 1 (6→171) not taken.
427 const std::filesystem::path stdPath = FileUtil::getStdDir();
33
1/2
✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→17) taken 427 times.
427 if (stdPath.empty())
34 throw CompilerError(STD_NOT_FOUND, "Standard library could not be found. Check if the env var SPICE_STD_DIR exists");
35 // Format: /dir/to/path/file
36
3/6
✓ Branch 0 (18→19) taken 427 times.
✗ Branch 1 (18→166) not taken.
✓ Branch 2 (19→20) taken 427 times.
✗ Branch 3 (19→164) not taken.
✓ Branch 4 (20→21) taken 427 times.
✗ Branch 5 (20→162) not taken.
427 basePath = stdPath / node->importPath.substr(node->importPath.find("std/") + 4);
37
2/2
✓ Branch 0 (27→28) taken 18 times.
✓ Branch 1 (27→49) taken 31 times.
476 } else if (isBootstrap) { // Include source file from bootstrap library
38 // Find bootstrap library
39
1/2
✓ Branch 0 (28→29) taken 18 times.
✗ Branch 1 (28→190) not taken.
18 const std::filesystem::path bootstrapPath = FileUtil::getBootstrapDir();
40
1/2
✗ Branch 0 (30→31) not taken.
✓ Branch 1 (30→39) taken 18 times.
18 if (bootstrapPath.empty())
41 throw CompilerError(BOOTSTRAP_NOT_FOUND,
42 "Bootstrap compiler could not be found. Check if the env var SPICE_BOOTSTRAP_DIR exists");
43 // Format: /dir/to/path/file
44
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);
45 18 } else { // Include own source file
46 // Format: /dir/to/path/file
47
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;
48 }
49 476 basePath.make_preferred();
50
51 // Format: /dir/to/path/file.spice
52
1/2
✓ Branch 0 (58→59) taken 476 times.
✗ Branch 1 (58→282) not taken.
476 std::filesystem::path defaultPath = basePath;
53
5/10
✓ Branch 0 (59→60) taken 476 times.
✗ Branch 1 (59→206) not taken.
✓ Branch 2 (60→61) taken 476 times.
✗ Branch 3 (60→204) not taken.
✓ Branch 4 (61→62) taken 476 times.
✗ Branch 5 (61→202) not taken.
✓ Branch 6 (62→63) taken 476 times.
✗ Branch 7 (62→200) not taken.
✓ Branch 8 (63→64) taken 476 times.
✗ Branch 9 (63→198) not taken.
476 defaultPath.replace_filename(basePath.stem().string() + ".spice");
54 // Format: /dir/to/path/file_linux.spice
55
1/2
✓ Branch 0 (68→69) taken 476 times.
✗ Branch 1 (68→280) not taken.
476 std::filesystem::path osPath = basePath;
56
7/14
✓ Branch 0 (69→70) taken 476 times.
✗ Branch 1 (69→222) not taken.
✓ Branch 2 (70→71) taken 476 times.
✗ Branch 3 (70→220) not taken.
✓ Branch 4 (71→72) taken 476 times.
✗ Branch 5 (71→218) not taken.
✓ Branch 6 (72→73) taken 476 times.
✗ Branch 7 (72→216) not taken.
✓ Branch 8 (73→74) taken 476 times.
✗ Branch 9 (73→214) not taken.
✓ Branch 10 (74→75) taken 476 times.
✗ Branch 11 (74→212) not taken.
✓ Branch 12 (75→76) taken 476 times.
✗ Branch 13 (75→210) not taken.
476 osPath.replace_filename(basePath.stem().string() + "_" + cliOptions.targetOs + ".spice");
57 // Format: /dir/to/path/file_linux_x86_64.spice
58
1/2
✓ Branch 0 (82→83) taken 476 times.
✗ Branch 1 (82→278) not taken.
476 std::filesystem::path osArchPath = basePath;
59
9/18
✓ Branch 0 (83→84) taken 476 times.
✗ Branch 1 (83→244) not taken.
✓ Branch 2 (84→85) taken 476 times.
✗ Branch 3 (84→242) not taken.
✓ Branch 4 (85→86) taken 476 times.
✗ Branch 5 (85→240) not taken.
✓ Branch 6 (86→87) taken 476 times.
✗ Branch 7 (86→238) not taken.
✓ Branch 8 (87→88) taken 476 times.
✗ Branch 9 (87→236) not taken.
✓ Branch 10 (88→89) taken 476 times.
✗ Branch 11 (88→234) not taken.
✓ Branch 12 (89→90) taken 476 times.
✗ Branch 13 (89→232) not taken.
✓ Branch 14 (90→91) taken 476 times.
✗ Branch 15 (90→230) not taken.
✓ Branch 16 (91→92) taken 476 times.
✗ Branch 17 (91→228) not taken.
476 osArchPath.replace_filename(basePath.stem().string() + "_" + cliOptions.targetOs + "_" + cliOptions.targetArch + ".spice");
60
61 // Check which source file to import
62 476 std::filesystem::path importPath;
63
3/10
✓ Branch 0 (101→102) taken 476 times.
✗ Branch 1 (101→274) not taken.
✗ Branch 2 (102→103) not taken.
✓ Branch 3 (102→106) taken 476 times.
✗ Branch 4 (103→104) not taken.
✗ Branch 5 (103→274) not taken.
✗ Branch 6 (104→105) not taken.
✗ Branch 7 (104→106) not taken.
✗ Branch 8 (107→108) not taken.
✓ Branch 9 (107→109) taken 476 times.
476 if (exists(osArchPath) && !equivalent(sourceFile->filePath, osArchPath)) // file_os_arch.spice is first choice
64 importPath = osArchPath;
65
7/10
✓ Branch 0 (109→110) taken 476 times.
✗ Branch 1 (109→274) not taken.
✓ Branch 2 (110→111) taken 20 times.
✓ Branch 3 (110→114) taken 456 times.
✓ Branch 4 (111→112) taken 20 times.
✗ Branch 5 (111→274) not taken.
✓ Branch 6 (112→113) taken 20 times.
✗ Branch 7 (112→114) not taken.
✓ Branch 8 (115→116) taken 20 times.
✓ Branch 9 (115→117) taken 456 times.
476 else if (exists(osPath) && !equivalent(sourceFile->filePath, osPath)) // file_os.spice is second choice
66
1/2
✓ Branch 0 (116→127) taken 20 times.
✗ Branch 1 (116→274) not taken.
20 importPath = osPath;
67
3/4
✓ Branch 0 (117→118) taken 456 times.
✗ Branch 1 (117→274) not taken.
✓ Branch 2 (118→119) taken 454 times.
✓ Branch 3 (118→120) taken 2 times.
456 else if (exists(defaultPath)) // file.spice is third choice
68
1/2
✓ Branch 0 (119→127) taken 454 times.
✗ Branch 1 (119→274) not taken.
454 importPath = defaultPath;
69 else
70
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");
71
72 // Check if the import already exists
73
1/2
✓ Branch 0 (127→128) taken 474 times.
✗ Branch 1 (127→274) not taken.
474 SymbolTableEntry *importEntry = rootScope->lookupStrict(node->importName);
74
2/2
✓ Branch 0 (130→131) taken 2 times.
✓ Branch 1 (130→138) taken 472 times.
474 if (importEntry != nullptr)
75
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 + "'");
76
77 // Create symbol for import
78
1/2
✓ Branch 0 (138→139) taken 472 times.
✗ Branch 1 (138→274) not taken.
472 node->entry = rootScope->insert(node->importName, node);
79
80 // Create the imported source file
81
1/2
✓ Branch 0 (141→142) taken 472 times.
✗ Branch 1 (141→274) not taken.
472 const auto importedSourceFile = resourceManager.createSourceFile(sourceFile, node->importName, importPath, isStd);
82 // Register it as a dependency to the current source file
83
3/4
✓ Branch 0 (142→143) taken 472 times.
✗ Branch 1 (142→272) not taken.
✓ Branch 2 (143→144) taken 471 times.
✓ Branch 3 (143→270) taken 1 times.
473 sourceFile->addDependency(importedSourceFile, node, node->importName, importPath.generic_string());
84
85
1/2
✓ Branch 0 (145→146) taken 471 times.
✗ Branch 1 (145→273) not taken.
942 return nullptr;
86 496 }
87
88 294 std::any ImportCollector::visitModAttr(ModAttrNode *node) {
89 // !!! Only bool attributes allowed here, due to missing attribute value checks being executed in a later stage !!!
90
91 // core.compiler.keep-on-name-collision
92
4/6
✓ Branch 0 (4→5) taken 294 times.
✗ Branch 1 (4→35) not taken.
✓ Branch 2 (5→6) taken 294 times.
✗ Branch 3 (5→33) not taken.
✓ Branch 4 (8→9) taken 286 times.
✓ Branch 5 (8→16) taken 8 times.
882 if (node->attrLst->hasAttr(ATTR_CORE_COMPILER_KEEP_ON_NAME_COLLISION)) {
93
2/4
✓ Branch 0 (11→12) taken 286 times.
✗ Branch 1 (11→41) not taken.
✓ Branch 2 (12→13) taken 286 times.
✗ Branch 3 (12→39) not taken.
572 const bool keepOnCollision = node->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_KEEP_ON_NAME_COLLISION)->boolValue;
94 286 sourceFile->alwaysKeepSymbolsOnNameCollision = keepOnCollision;
95 }
96
97 // core.compiler.warnings.ignore
98
4/6
✓ Branch 0 (18→19) taken 294 times.
✗ Branch 1 (18→47) not taken.
✓ Branch 2 (19→20) taken 294 times.
✗ Branch 3 (19→45) not taken.
✓ Branch 4 (22→23) taken 2 times.
✓ Branch 5 (22→30) taken 292 times.
882 if (node->attrLst->hasAttr(ATTR_CORE_COMPILER_WARNINGS_IGNORE)) {
99
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;
100 2 sourceFile->ignoreWarnings = ignoreWarnings;
101 }
102
103
1/2
✓ Branch 0 (30→31) taken 294 times.
✗ Branch 1 (30→57) not taken.
294 return nullptr;
104 }
105
106 } // namespace spice::compiler
107