UNPKG

@samiyev/guardian

Version:

Research-backed code quality guardian for AI-assisted development. Detects hardcodes, secrets, circular deps, framework leaks, entity exposure, and 9 architecture violations. Enforces Clean Architecture/DDD principles. Works with GitHub Copilot, Cursor, W

90 lines 3.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AstTreeTraverser = void 0; const HardcodedValue_1 = require("../../domain/value-objects/HardcodedValue"); /** * AST tree traverser for detecting hardcoded values * * Walks through the Abstract Syntax Tree and uses analyzers * to detect hardcoded numbers, strings, booleans, and configuration objects. * Also tracks value usage to identify "almost constants" - values used 2+ times. */ class AstTreeTraverser { numberAnalyzer; stringAnalyzer; booleanAnalyzer; configObjectAnalyzer; constructor(numberAnalyzer, stringAnalyzer, booleanAnalyzer, configObjectAnalyzer) { this.numberAnalyzer = numberAnalyzer; this.stringAnalyzer = stringAnalyzer; this.booleanAnalyzer = booleanAnalyzer; this.configObjectAnalyzer = configObjectAnalyzer; } /** * Traverses the AST tree and collects hardcoded values */ traverse(tree, sourceCode) { const results = []; const lines = sourceCode.split("\n"); const cursor = tree.walk(); this.visit(cursor, lines, results); this.markAlmostConstants(results); return results; } /** * Marks values that appear multiple times in the same file */ markAlmostConstants(results) { const valueUsage = new Map(); for (const result of results) { const key = `${result.type}:${String(result.value)}`; valueUsage.set(key, (valueUsage.get(key) || 0) + 1); } for (let i = 0; i < results.length; i++) { const result = results[i]; const key = `${result.type}:${String(result.value)}`; const count = valueUsage.get(key) || 0; if (count >= 2 && !result.withinFileUsageCount) { results[i] = HardcodedValue_1.HardcodedValue.create(result.value, result.type, result.line, result.column, result.context, result.valueType, result.duplicateLocations, count); } } } /** * Recursively visits AST nodes */ visit(cursor, lines, results) { const node = cursor.currentNode; if (node.type === "object") { const violation = this.configObjectAnalyzer.analyze(node, lines); if (violation) { results.push(violation); } } else if (node.type === "number") { const violation = this.numberAnalyzer.analyze(node, lines); if (violation) { results.push(violation); } } else if (node.type === "string") { const violation = this.stringAnalyzer.analyze(node, lines); if (violation) { results.push(violation); } } else if (node.type === "true" || node.type === "false") { const violation = this.booleanAnalyzer.analyze(node, lines); if (violation) { results.push(violation); } } if (cursor.gotoFirstChild()) { do { this.visit(cursor, lines, results); } while (cursor.gotoNextSibling()); cursor.gotoParent(); } } } exports.AstTreeTraverser = AstTreeTraverser; //# sourceMappingURL=AstTreeTraverser.js.map