UNPKG

superaugment

Version:

Enterprise-grade MCP server with world-class C++ analysis, robust error handling, and production-ready architecture for VS Code Augment

429 lines (417 loc) 20.8 kB
/** * Enhanced C++ Analysis Tool with Professional AST Support * * Provides enterprise-grade C++ code analysis using Tree-sitter AST parsing, * comprehensive semantic analysis, CUDA support, and professional-grade * performance, memory, and security analysis. */ import { z } from 'zod'; import { extname } from 'path'; import { BaseTool } from '../BaseTool.js'; import { ConfigManager } from '../../config/ConfigManager.js'; import { FileSystemManager } from '../../utils/FileSystemManager.js'; import { EnhancedCppAnalyzer } from '../../analyzers/EnhancedCppAnalyzer.js'; import { AnalysisError, ErrorCode, } from '../../errors/ErrorTypes.js'; import { logger } from '../../utils/logger.js'; /** * Enhanced C++ analysis options schema */ const EnhancedCppAnalysisSchema = z.object({ path: z.string().describe('Path to C++ file or directory to analyze'), cppStandard: z.enum(['cpp11', 'cpp14', 'cpp17', 'cpp20', 'cpp23']).default('cpp17').describe('C++ standard to use for analysis'), // Analysis scope options includeHeaders: z.boolean().default(true).describe('Include header file analysis'), analyzeDependencies: z.boolean().default(true).describe('Analyze include dependencies and build dependency graph'), detectCircularDeps: z.boolean().default(true).describe('Detect circular dependencies'), // Feature analysis options modernCppAnalysis: z.boolean().default(true).describe('Analyze modern C++ features usage'), performanceAnalysis: z.boolean().default(true).describe('Perform comprehensive performance analysis'), memoryAnalysis: z.boolean().default(true).describe('Analyze memory management patterns'), securityAnalysis: z.boolean().default(true).describe('Perform security vulnerability analysis'), // Specialized analysis cudaAnalysis: z.boolean().default(false).describe('Enable CUDA/GPU code analysis'), templateAnalysis: z.boolean().default(true).describe('Analyze template usage and instantiation'), // Output options includeMetrics: z.boolean().default(true).describe('Include detailed code metrics'), includeRecommendations: z.boolean().default(true).describe('Include improvement recommendations'), verboseOutput: z.boolean().default(false).describe('Include verbose analysis details'), // Quality thresholds complexityThreshold: z.number().min(1).max(50).default(10).describe('Cyclomatic complexity threshold for warnings'), maintainabilityThreshold: z.number().min(0).max(100).default(70).describe('Maintainability index threshold'), // Custom rules customRules: z.array(z.string()).default([]).describe('Custom analysis rules to apply'), excludePatterns: z.array(z.string()).default([]).describe('File patterns to exclude from analysis'), }); /** * Enhanced C++ Analysis Tool */ export class EnhancedCppAnalysisTool extends BaseTool { name = 'analyze_cpp_enhanced'; description = 'Professional-grade C++ code analysis with AST parsing, CUDA support, and comprehensive quality metrics'; inputSchema = EnhancedCppAnalysisSchema; fileSystemManager; enhancedAnalyzer; constructor(configManager) { super(configManager); this.fileSystemManager = new FileSystemManager(); this.enhancedAnalyzer = new EnhancedCppAnalyzer(); } /** * Execute enhanced C++ analysis */ async executeInternal(args, context) { try { logger.info('Starting enhanced C++ analysis', { args, context: context.requestId }); // Validate and parse arguments const validatedArgs = EnhancedCppAnalysisSchema.parse(args); // Find C++ files to analyze const cppFiles = await this.findCppFiles(validatedArgs.path, validatedArgs.excludePatterns); if (cppFiles.length === 0) { return this.createResponse('⚠️ No C++ files found to analyze.\n\nPlease check the path and ensure it contains .cpp, .cxx, .cc, .h, .hpp, or .hxx files.', [], { filesFound: 0, analysisSkipped: true }); } // Perform analysis on each file const analysisResults = []; const analysisOptions = { cppStandard: validatedArgs.cppStandard, includeCuda: validatedArgs.cudaAnalysis, includePerformance: validatedArgs.performanceAnalysis, includeMemory: validatedArgs.memoryAnalysis, includeSecurity: validatedArgs.securityAnalysis, }; for (const file of cppFiles) { try { logger.debug(`Analyzing file: ${file}`); const result = await this.enhancedAnalyzer.analyzeFile(file, analysisOptions); analysisResults.push(result); } catch (error) { logger.warn(`Failed to analyze file ${file}`, { error }); // Continue with other files } } // Generate comprehensive report const report = this.generateComprehensiveReport(analysisResults, validatedArgs); // Format response based on verbosity const responseText = validatedArgs.verboseOutput ? this.formatVerboseResponse(report, analysisResults, validatedArgs) : this.formatStandardResponse(report, validatedArgs); return this.createResponse(responseText, [], { filesAnalyzed: analysisResults.length, overallScore: report.summary.overallScore, grade: report.summary.grade, analysisTime: Date.now() - context.startTime.getTime(), }); } catch (error) { if (error instanceof AnalysisError) { return this.createErrorResponse(error, true); } throw new AnalysisError(`Enhanced C++ analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`, ErrorCode.ANALYSIS_FAILED, { additionalInfo: { args, context: context.requestId } }, error instanceof Error ? error : undefined); } } /** * Find C++ files to analyze */ async findCppFiles(path, excludePatterns) { const cppExtensions = ['.cpp', '.cxx', '.cc', '.c', '.h', '.hpp', '.hxx', '.cu', '.cuh']; try { const exists = await this.fileSystemManager.fileExists(path); if (!exists) { return []; } // Check if it's a file try { const stats = await this.fileSystemManager.getFileStats(path); if (stats && cppExtensions.includes(extname(path).toLowerCase())) { return [path]; } } catch { // Might be a directory, continue to directory handling } // Try to handle as directory try { const patterns = cppExtensions.map(ext => `**/*${ext}`); const files = await this.fileSystemManager.readFiles(patterns, path); return files .filter(file => !this.shouldExcludeFile(file.path, excludePatterns)) .map(file => file.path); } catch (error) { logger.error(`Failed to read directory ${path}`, { error }); return []; } } catch (error) { logger.error(`Failed to find C++ files in ${path}`, { error }); return []; } } /** * Check if file should be excluded based on patterns */ shouldExcludeFile(filePath, excludePatterns) { return excludePatterns.some(pattern => { const regex = new RegExp(pattern.replace(/\*/g, '.*')); return regex.test(filePath); }); } /** * Generate comprehensive analysis report */ generateComprehensiveReport(results, options) { if (results.length === 0) { return this.createEmptyReport(); } // Aggregate metrics from all files const totalLines = results.reduce((sum, r) => sum + r.metrics.totalLines, 0); const totalCodeLines = results.reduce((sum, r) => sum + r.metrics.codeLines, 0); const totalCommentLines = results.reduce((sum, r) => sum + r.metrics.commentLines, 0); const totalBlankLines = results.reduce((sum, r) => sum + r.metrics.blankLines, 0); // Calculate average scores const avgMaintainability = results.reduce((sum, r) => sum + r.metrics.complexity.maintainabilityIndex, 0) / results.length; const avgModernCppScore = results.reduce((sum, r) => sum + r.modernCpp.score, 0) / results.length; const avgPerformanceScore = results.reduce((sum, r) => sum + r.performance.score, 0) / results.length; const avgMemoryScore = results.reduce((sum, r) => sum + r.memory.score, 0) / results.length; const avgSecurityScore = results.reduce((sum, r) => sum + r.security.score, 0) / results.length; // Calculate overall score const overallScore = Math.round((avgMaintainability + avgModernCppScore + avgPerformanceScore + avgMemoryScore + avgSecurityScore) / 5); const grade = this.calculateGrade(overallScore); // Aggregate structural information const totalNamespaces = results.reduce((sum, r) => sum + r.structure.namespaces.length, 0); const totalClasses = results.reduce((sum, r) => sum + r.structure.classes.length, 0); const totalFunctions = results.reduce((sum, r) => sum + r.structure.functions.length, 0); const totalTemplates = results.reduce((sum, r) => sum + r.structure.templates.length, 0); // Calculate complexity metrics const complexities = results.flatMap(r => r.structure.functions.map(f => f.complexity)); const avgComplexity = complexities.length > 0 ? complexities.reduce((sum, c) => sum + c, 0) / complexities.length : 0; const maxComplexity = complexities.length > 0 ? Math.max(...complexities) : 0; return { summary: { filesAnalyzed: results.length, totalLines, codeLines: totalCodeLines, commentLines: totalCommentLines, blankLines: totalBlankLines, overallScore, grade, }, structure: { namespaces: totalNamespaces, classes: totalClasses, functions: totalFunctions, templates: totalTemplates, complexity: { average: Math.round(avgComplexity * 100) / 100, maximum: maxComplexity, distribution: this.calculateComplexityDistribution(complexities), }, }, quality: { maintainabilityIndex: Math.round(avgMaintainability), codeSmells: this.countCodeSmells(results), technicalDebt: this.estimateTechnicalDebt(results), recommendations: this.generateQualityRecommendations(results, options), }, modernCpp: { score: Math.round(avgModernCppScore), featuresUsed: results.reduce((sum, r) => sum + r.modernCpp.featuresUsed.filter(f => f.used).length, 0), featuresAvailable: results.reduce((sum, r) => sum + r.modernCpp.featuresUsed.length, 0), recommendations: this.aggregateRecommendations(results.map(r => r.modernCpp.recommendations)), }, performance: { score: Math.round(avgPerformanceScore), hotspots: results.reduce((sum, r) => sum + r.performance.hotspots.length, 0), optimizations: this.aggregateRecommendations(results.map(r => r.performance.optimizations.map(o => o.description))), }, memory: { score: Math.round(avgMemoryScore), issues: results.reduce((sum, r) => sum + r.memory.issues.length, 0), smartPointerUsage: results.reduce((sum, r) => sum + r.memory.smartPointerUsage.uniquePtr + r.memory.smartPointerUsage.sharedPtr, 0), raii: Math.round(results.reduce((sum, r) => sum + r.memory.raii.score, 0) / results.length), }, security: { score: Math.round(avgSecurityScore), vulnerabilities: results.reduce((sum, r) => sum + r.security.vulnerabilities.length, 0), criticalIssues: results.reduce((sum, r) => sum + r.security.vulnerabilities.filter(v => v.severity === 'critical').length, 0), }, dependencies: { totalIncludes: results.reduce((sum, r) => sum + r.dependencies.systemIncludes.length + r.dependencies.userIncludes.length, 0), circularDependencies: results.reduce((sum, r) => sum + r.dependencies.circularDependencies.length, 0), dependencyDepth: Math.max(...results.map(r => Math.max(...r.dependencies.dependencyGraph.map(d => d.depth), 0))), }, }; } /** * Calculate grade based on overall score */ calculateGrade(score) { if (score >= 90) return 'A+'; if (score >= 85) return 'A'; if (score >= 80) return 'A-'; if (score >= 75) return 'B+'; if (score >= 70) return 'B'; if (score >= 65) return 'B-'; if (score >= 60) return 'C+'; if (score >= 55) return 'C'; if (score >= 50) return 'C-'; if (score >= 45) return 'D+'; if (score >= 40) return 'D'; return 'F'; } /** * Create empty report for no results */ createEmptyReport() { return { summary: { filesAnalyzed: 0, totalLines: 0, codeLines: 0, commentLines: 0, blankLines: 0, overallScore: 0, grade: 'N/A' }, structure: { namespaces: 0, classes: 0, functions: 0, templates: 0, complexity: { average: 0, maximum: 0, distribution: {} } }, quality: { maintainabilityIndex: 0, codeSmells: 0, technicalDebt: 'Unknown', recommendations: [] }, modernCpp: { score: 0, featuresUsed: 0, featuresAvailable: 0, recommendations: [] }, performance: { score: 0, hotspots: 0, optimizations: [] }, memory: { score: 0, issues: 0, smartPointerUsage: 0, raii: 0 }, security: { score: 0, vulnerabilities: 0, criticalIssues: 0 }, dependencies: { totalIncludes: 0, circularDependencies: 0, dependencyDepth: 0 }, }; } // Helper methods for report generation calculateComplexityDistribution(complexities) { const distribution = { 'Low (1-5)': 0, 'Medium (6-10)': 0, 'High (11-20)': 0, 'Very High (21+)': 0, }; complexities.forEach(complexity => { if (complexity <= 5) distribution['Low (1-5)'] = (distribution['Low (1-5)'] || 0) + 1; else if (complexity <= 10) distribution['Medium (6-10)'] = (distribution['Medium (6-10)'] || 0) + 1; else if (complexity <= 20) distribution['High (11-20)'] = (distribution['High (11-20)'] || 0) + 1; else distribution['Very High (21+)'] = (distribution['Very High (21+)'] || 0) + 1; }); return distribution; } countCodeSmells(results) { // Count various code smells across all results return results.reduce((sum, r) => { return sum + (r.memory?.issues?.length || 0) + (r.security?.vulnerabilities?.length || 0) + (r.performance?.hotspots?.length || 0); }, 0); } estimateTechnicalDebt(results) { const totalIssues = this.countCodeSmells(results); const totalLines = results.reduce((sum, r) => sum + r.metrics.codeLines, 0); if (totalLines === 0) return 'Unknown'; const debtRatio = totalIssues / totalLines * 1000; // Issues per 1000 lines if (debtRatio < 5) return 'Low'; if (debtRatio < 15) return 'Medium'; if (debtRatio < 30) return 'High'; return 'Very High'; } generateQualityRecommendations(results, options) { const recommendations = []; // Add recommendations based on analysis results const avgComplexity = results.reduce((sum, r) => { const complexities = r.structure.functions.map(f => f.complexity); return sum + (complexities.length > 0 ? complexities.reduce((s, c) => s + c, 0) / complexities.length : 0); }, 0) / results.length; if (avgComplexity > options.complexityThreshold) { recommendations.push(`Consider refactoring functions with high cyclomatic complexity (average: ${avgComplexity.toFixed(1)})`); } const avgMaintainability = results.reduce((sum, r) => sum + r.metrics.complexity.maintainabilityIndex, 0) / results.length; if (avgMaintainability < options.maintainabilityThreshold) { recommendations.push(`Improve maintainability index (current: ${avgMaintainability.toFixed(1)}, target: ${options.maintainabilityThreshold})`); } return recommendations; } aggregateRecommendations(recommendationArrays) { const uniqueRecommendations = new Set(); recommendationArrays.forEach(recommendations => { recommendations.forEach(rec => uniqueRecommendations.add(rec)); }); return Array.from(uniqueRecommendations); } /** * Format standard response */ formatStandardResponse(report, options) { return `# 🔍 Enhanced C++ Analysis Report ## 📊 Summary - **Files Analyzed**: ${report.summary.filesAnalyzed} - **Total Lines**: ${report.summary.totalLines.toLocaleString()} (${report.summary.codeLines.toLocaleString()} code, ${report.summary.commentLines.toLocaleString()} comments) - **Overall Score**: ${report.summary.overallScore}/100 (Grade: ${report.summary.grade}) - **C++ Standard**: ${options.cppStandard} ## 🏗️ Code Structure - **Namespaces**: ${report.structure.namespaces} - **Classes**: ${report.structure.classes} - **Functions**: ${report.structure.functions} - **Templates**: ${report.structure.templates} - **Average Complexity**: ${report.structure.complexity.average} - **Maximum Complexity**: ${report.structure.complexity.maximum} ## 📈 Quality Metrics - **Maintainability Index**: ${report.quality.maintainabilityIndex}/100 - **Code Smells**: ${report.quality.codeSmells} - **Technical Debt**: ${report.quality.technicalDebt} ## 🚀 Modern C++ (${options.cppStandard}) - **Score**: ${report.modernCpp.score}/100 - **Features Used**: ${report.modernCpp.featuresUsed}/${report.modernCpp.featuresAvailable} ## ⚡ Performance Analysis - **Score**: ${report.performance.score}/100 - **Hotspots Found**: ${report.performance.hotspots} ## 🧠 Memory Management - **Score**: ${report.memory.score}/100 - **Memory Issues**: ${report.memory.issues} - **Smart Pointer Usage**: ${report.memory.smartPointerUsage} - **RAII Score**: ${report.memory.raii}/100 ## 🛡️ Security Analysis - **Score**: ${report.security.score}/100 - **Vulnerabilities**: ${report.security.vulnerabilities} - **Critical Issues**: ${report.security.criticalIssues} ## 📦 Dependencies - **Total Includes**: ${report.dependencies.totalIncludes} - **Circular Dependencies**: ${report.dependencies.circularDependencies} - **Max Dependency Depth**: ${report.dependencies.dependencyDepth} ${report.quality.recommendations.length > 0 ? ` ## 💡 Recommendations ${report.quality.recommendations.map(rec => `- ${rec}`).join('\n')} ` : ''} ${report.modernCpp.recommendations.length > 0 ? ` ## 🔧 Modern C++ Improvements ${report.modernCpp.recommendations.slice(0, 5).map(rec => `- ${rec}`).join('\n')} ` : ''} ${report.performance.optimizations.length > 0 ? ` ## ⚡ Performance Optimizations ${report.performance.optimizations.slice(0, 5).map(opt => `- ${opt}`).join('\n')} ` : ''} --- *Analysis completed using Enhanced C++ Analyzer with Tree-sitter AST parsing*`; } /** * Format verbose response (placeholder) */ formatVerboseResponse(report, _results, options) { // This would include detailed per-file analysis, full recommendation lists, etc. return this.formatStandardResponse(report, options) + '\n\n*Verbose output not yet implemented*'; } } //# sourceMappingURL=EnhancedCppAnalysisTool.js.map