GCC Code Coverage Report


src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
30 / 30
100.0%
Branches:
-
-%
Functions:
9 / 9
100.0%

linter/lint-pass.spice
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 // Std imports
4 import "std/type/any";
5 import "std/data/vector";
6
7 // Own imports
8 import "@/compiler-pass";
9 import "@/ast/abstract-ast-visitor-intf";
10 import "@/ast/ast-nodes";
11 import "@/global/global-resource-manager";
12 import "@/source-file";
13 import "@/linter/lint-finding";
14 import "@/linter/rules/naming-convention-rule";
15 import "@/linter/rules/too-many-parameters-rule";
16 import "@/linter/rules/cyclomatic-complexity-rule";
17
18 /**
19 * Runs all built-in lint rules over a fully type-checked AST in a single read-only traversal.
20 *
21 * Modeled on PostTypeCheckingVerifier: each overridden visit method fans out to every rule interested in that
22 * node kind, so adding a new rule only requires adding its call to the matching visit method, never a new AST
23 * walk. Spice has no heap-allocated polymorphic collections, so the rules live in linter/rules/ as free functions that this
24 * pass dispatches to.
25 */
26 3 public type LintPass struct : IAbstractAstVisitor {
27 compose public CompilerPass compilerPass
28 public Vector<LintFinding> findings
29 }
30
31 /**
32 * Construct a lint pass for the given source file
33 *
34 * @param resourceManager Global resource manager
35 * @param sourceFile Source file, whose AST is linted
36 */
37 3 public p LintPass.ctor(GlobalResourceManager& resourceManager, SourceFile* sourceFile) {
38 3 this.compilerPass = CompilerPass(resourceManager, sourceFile);
39 3 }
40
41 /**
42 * Run all lint rules over the given AST and return the collected findings.
43 *
44 * @param ast Root node of the AST to lint
45 * @return Collected lint findings
46 */
47 3 public f<Vector<LintFinding>> LintPass.lint(ASTEntryNode* ast) {
48 3 this.visit(ast);
49 6 return this.findings;
50 3 }
51
52 // ========================================================== Lint rules =========================================================
53
54 7 public f<Any> LintPass.visitFctDef(ASTFctDefNode* node) {
55 7 checkNamingFctDef(node, this.findings);
56 7 checkParamCountFctDef(node, this.findings);
57 7 checkComplexityFctDef(node, this.findings);
58 7 return this.visitChildren(cast<ASTNode*>(node));
59 }
60
61 3 public f<Any> LintPass.visitProcDef(ASTProcDefNode* node) {
62 3 checkNamingProcDef(node, this.findings);
63 3 checkParamCountProcDef(node, this.findings);
64 3 checkComplexityProcDef(node, this.findings);
65 3 return this.visitChildren(cast<ASTNode*>(node));
66 }
67
68 2 public f<Any> LintPass.visitStructDef(ASTStructDefNode* node) {
69 2 checkNamingStructDef(node, this.findings);
70 2 return this.visitChildren(cast<ASTNode*>(node));
71 }
72
73 2 public f<Any> LintPass.visitInterfaceDef(ASTInterfaceDefNode* node) {
74 2 checkNamingInterfaceDef(node, this.findings);
75 2 return this.visitChildren(cast<ASTNode*>(node));
76 }
77
78 2 public f<Any> LintPass.visitUnionDef(ASTUnionDefNode* node) {
79 2 checkNamingUnionDef(node, this.findings);
80 2 return this.visitChildren(cast<ASTNode*>(node));
81 }
82
83 2 public f<Any> LintPass.visitGlobalVarDef(ASTGlobalVarDefNode* node) {
84 2 checkNamingGlobalVarDef(node, this.findings);
85 2 return this.visitChildren(cast<ASTNode*>(node));
86 }
87