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 |