UNPKG

@neurolint/cli

Version:

NeuroLint CLI - Deterministic code fixing for TypeScript, JavaScript, React, and Next.js with 8-layer architecture including Security Forensics, Next.js 16, React Compiler, and Turbopack support

119 lines (103 loc) 3.69 kB
/** * NeuroLint - Transformation Validator * Validates code transformations for safety and correctness * * Copyright (c) 2025 NeuroLint * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class TransformationValidator { constructor(options = {}) { this.strict = options.strict !== false; } validate(originalCode, transformedCode, filename) { // Basic validation - can be enhanced later if (!transformedCode || transformedCode.trim().length === 0) { return { valid: false, errors: ['Transformed code is empty'] }; } // Check for basic syntax issues (very simple check) const hasMatchingBraces = this.checkMatchingBraces(transformedCode); if (!hasMatchingBraces) { return { valid: false, errors: ['Mismatched braces in transformed code'] }; } return { valid: true, errors: [] }; } checkMatchingBraces(code) { const stack = []; const pairs = { '{': '}', '[': ']', '(': ')' }; for (const char of code) { if (char in pairs) { stack.push(pairs[char]); } else if (Object.values(pairs).includes(char)) { if (stack.pop() !== char) return false; } } return stack.length === 0; } validateFile(filePath, originalCode, transformedCode) { // Validate file transformation return this.validate(originalCode, transformedCode, filePath); } static validateCode(code, filename) { const validator = new TransformationValidator(); return validator.validate('', code, filename); } static async validateFile(filePath, originalCode, transformedCode) { const fs = require('fs').promises; const validator = new TransformationValidator(); // If only filePath is provided, read the file if (!originalCode && !transformedCode) { try { const code = await fs.readFile(filePath, 'utf8'); const result = validator.validate('', code, filePath); return { isValid: result.valid, error: result.errors.length > 0 ? result.errors.join(', ') : null, suggestion: result.errors.length > 0 ? 'Fix syntax errors in the file' : null }; } catch (error) { return { isValid: false, error: error.message, suggestion: 'Ensure the file exists and is readable' }; } } // Otherwise validate the transformation const result = validator.validate(originalCode, transformedCode, filePath); return { isValid: result.valid, error: result.errors.length > 0 ? result.errors.join(', ') : null, suggestion: result.errors.length > 0 ? 'Review the transformation' : null }; } static async validateTransformation(originalCode, transformedCode, filePath) { const validator = new TransformationValidator(); const result = validator.validate(originalCode, transformedCode, filePath); return { shouldRevert: !result.valid, reason: result.errors.length > 0 ? result.errors.join(', ') : null, valid: result.valid, errors: result.errors }; } } module.exports = TransformationValidator;