@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
93 lines • 3.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AstConfigObjectAnalyzer = void 0;
const HardcodedValue_1 = require("../../domain/value-objects/HardcodedValue");
const rules_1 = require("../../shared/constants/rules");
const ast_node_types_1 = require("../../shared/constants/ast-node-types");
const defaults_1 = require("../constants/defaults");
/**
* AST-based analyzer for detecting configuration objects with hardcoded values
*
* Detects objects that contain multiple hardcoded values that should be
* extracted to a configuration file.
*
* Example:
* const config = { timeout: 5000, retries: 3, url: "http://..." }
*/
class AstConfigObjectAnalyzer {
contextChecker;
MIN_HARDCODED_VALUES = 2;
constructor(contextChecker) {
this.contextChecker = contextChecker;
}
/**
* Analyzes an object expression and returns a violation if it contains many hardcoded values
*/
analyze(node, lines) {
if (node.type !== "object") {
return null;
}
if (this.contextChecker.isInExportedConstant(node)) {
return null;
}
if (this.contextChecker.isInTypeContext(node)) {
return null;
}
const hardcodedCount = this.countHardcodedValues(node);
if (hardcodedCount < this.MIN_HARDCODED_VALUES) {
return null;
}
return this.createViolation(node, hardcodedCount, lines);
}
/**
* Counts hardcoded values in an object
*/
countHardcodedValues(objectNode) {
let count = 0;
for (const child of objectNode.children) {
if (child.type === "pair") {
const value = child.childForFieldName("value");
if (value && this.isHardcodedValue(value)) {
count++;
}
}
}
return count;
}
/**
* Checks if a node is a hardcoded value
*/
isHardcodedValue(node) {
if (node.type === "number") {
const value = parseInt(node.text, 10);
return !defaults_1.ALLOWED_NUMBERS.has(value) && value >= 100;
}
if (node.type === "string") {
const stringFragment = node.children.find((c) => c.type === ast_node_types_1.AST_STRING_TYPES.STRING_FRAGMENT);
return stringFragment !== undefined && stringFragment.text.length > 3;
}
return false;
}
/**
* Creates a HardcodedValue violation for a config object
*/
createViolation(node, hardcodedCount, lines) {
const lineNumber = node.startPosition.row + 1;
const column = node.startPosition.column;
const context = lines[node.startPosition.row]?.trim() ?? "";
const objectPreview = this.getObjectPreview(node);
return HardcodedValue_1.HardcodedValue.create(`Configuration object with ${String(hardcodedCount)} hardcoded values: ${objectPreview}`, rules_1.HARDCODE_TYPES.MAGIC_CONFIG, lineNumber, column, context);
}
/**
* Gets a preview of the object for the violation message
*/
getObjectPreview(node) {
const text = node.text;
if (text.length <= 50) {
return text;
}
return `${text.substring(0, 47)}...`;
}
}
exports.AstConfigObjectAnalyzer = AstConfigObjectAnalyzer;
//# sourceMappingURL=AstConfigObjectAnalyzer.js.map