UNPKG

@sun-asterisk/sunlint

Version:

☀️ SunLint - Multi-language static analysis tool for code quality and security | Sun* Engineering Standards

693 lines (620 loc) 40.7 kB
# SunLint Architecture Documentation ## Table of Contents 1. [Overview](#overview) 2. [Folder Structure](#folder-structure) 3. [Core Components](#core-components) 4. [Execution Flow](#execution-flow) 5. [Engine Architecture](#engine-architecture) 6. [Rule System](#rule-system) 7. [Data Flow Diagrams](#data-flow-diagrams) --- ## Overview SunLint một static code analyzer đa ngôn ngữ, được thiết kế với kiến trúc plugin-based để dễ dàng mở rộng. ``` ┌─────────────────────────────────────────────────────────────────┐ SunLint CLI "sunlint --security --input=src" └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ Analysis Orchestrator - Route files to appropriate engines - Merge results from multiple engines - Handle batching and performance └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────┼─────────────────────┐ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ESLint Engine │Heuristic Engine│ OpenAI Engine (JS/TS only) (All languages)│ (AI-powered) └───────────────┘ └───────────────┘ └───────────────┘ ``` --- ## Folder Structure ``` sunlint/ ├── cli.js # Entry point ├── core/ # Core modules ├── cli-program.js # CLI definition (commander.js) ├── cli-action-handler.js # Main action handler ├── config-manager.js # Configuration management ├── config-merger.js # Merge configs (CLI + file) ├── config-validator.js # Validate config ├── config-preset-resolver.js # Resolve presets ├── config-source-loader.js # Load config files ├── config-override-processor.js# Process overrides ├── analysis-orchestrator.js # ⭐ Main orchestrator ├── rule-selection-service.js # Select rules to run ├── file-targeting-service.js # Find files to analyze ├── performance-optimizer.js # Optimize analysis ├── auto-performance-manager.js # Auto-tune performance ├── semantic-engine.js # ts-morph Symbol Table ├── semantic-rule-base.js # Base class for semantic rules ├── output-service.js # Format & output results ├── report-generator.js # Generate reports ├── scoring-service.js # Calculate scores ├── summary-report-service.js # Summary reports ├── upload-service.js # Upload to API ├── html-report-generator.js # HTML reports ├── github-annotate-service.js # GitHub PR annotations ├── github-step-summary-generator.js ├── unified-rule-registry.js # Rule registry ├── enhanced-rules-registry.js # Enhanced registry ├── rule-mapping-service.js # Map rules to engines ├── git-utils.js # Git operations ├── dependency-checker.js # Check dependencies ├── dependency-manager.js # Manage dependencies ├── smart-installer.js # Auto-install deps ├── plugin-manager.js # Plugin management ├── adapters/ └── sunlint-rule-adapter.js # Adapt rules to engines ├── interfaces/ ├── analysis-engine.interface.js # Engine interface └── rule-plugin.interface.js # Rule interface ├── ast-modules/ ├── index.js # AST module registry ├── base-parser.js # Base parser class └── parsers/ ├── javascript-parser.js ├── typescript-parser.js ├── eslint-js-parser.js └── eslint-ts-parser.js └── constants/ ├── index.js ├── categories.js ├── engines.js ├── rules.js └── defaults.js ├── engines/ # Analysis engines ├── eslint-engine.js # ESLint-based analysis ├── heuristic-engine.js # Pattern/regex + ts-morph ├── openai-engine.js # AI-powered analysis └── engine-factory.js # Engine factory ├── config/ ├── presets/ # Rule presets ├── all.json ├── quality.json └── security.json ├── engines/ └── engines.json # Engine configuration ├── rules/ # Rule definitions └── integrations/ └── eslint/ # ESLint configs ├── integrations/ └── eslint/ ├── plugin/ ├── index.js # ESLint plugin entry └── rules/ ├── security/ # Security rules ├── typescript/ # TS-specific rules └── common/ # Common rules └── configs/ ├── custom-rules/ # Custom rule examples ├── test/ ├── unit/ ├── integration/ └── fixtures/ ├── examples/ └── docs/ ``` --- ## Core Components ### 1. CLI Entry (`cli.js`) ```javascript // Entry point - minimal bootstrapping const program = createCliProgram(); program.action(async (options) => { const actionHandler = new CliActionHandler(options); await actionHandler.execute(); }); program.parse(); ``` ### 2. CLI Action Handler (`core/cli-action-handler.js`) Orchestrates the entire analysis flow: ```javascript class CliActionHandler { async execute() { // 1. Load configuration const config = await this.loadConfiguration(); // 2. Validate input this.validateInput(config); // 3. Select rules to run const rulesToRun = await this.ruleSelectionService.selectRules(config, this.options); // 4. Apply file targeting const targetingResult = await this.applyFileTargeting(config); // 5. Run analysis const results = await this.runModernAnalysis(rulesToRun, targetingResult.files, config); // 6. Output results await this.outputService.outputResults(results, this.options, metadata); } } ``` ### 3. Analysis Orchestrator (`core/analysis-orchestrator.js`) Routes rules to appropriate engines: ```javascript class AnalysisOrchestrator { async analyze(files, rules, options) { // 1. Group rules by engine preference const engineGroups = this.groupRulesByEngine(rules, config); // 2. Run each engine for (const [engineName, engineRules] of engineGroups) { const engine = this.engines.get(engineName); const result = await engine.analyze(files, engineRules, options); results.push(result); } // 3. Merge results return this.mergeEngineResults(results); } } ``` ### 4. Semantic Engine (`core/semantic-engine.js`) Provides ts-morph Symbol Table for advanced analysis: ```javascript class SemanticEngine { async initialize(projectPath, targetFiles) { // Initialize ts-morph project this.project = new Project({ compilerOptions: { ... }, skipFileDependencyResolution: true, skipLoadingLibFiles: true, }); // Load target files into Symbol Table for (const file of targetFiles) { this.project.addSourceFileAtPath(file); } } // Provides cross-file analysis capabilities getSymbolsInFile(filePath) { ... } findReferences(symbol) { ... } getTypeInfo(node) { ... } } ``` --- ## Execution Flow ### Complete Flow Diagram ``` ┌─────────────────────────────────────────────────────────────────────────────┐ USER INPUT $ sunlint --security --input=src --format=summary └─────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────────┐ 1. CLI PROGRAM (cli-program.js) - Parse arguments with commander.js - Extract options: {security: true, input: 'src', format: 'summary'} └─────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────────┐ 2. CLI ACTION HANDLER (cli-action-handler.js) - Main orchestration entry point └─────────────────────────────────────────────────────────────────────────────┘ ┌───────────────┼───────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ Config Rule File Manager Selection Targeting Service Service └─────────────┘ └─────────────┘ └─────────────┘ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ Load config Load preset Find files files security.json│ in src/ Merge CLI 57 rules 500 files └─────────────┘ └─────────────┘ └─────────────┘ └───────────────┼───────────────┘ ┌─────────────────────────────────────────────────────────────────────────────┐ 3. ANALYSIS ORCHESTRATOR (analysis-orchestrator.js) - Initialize engines - Group rules by engine - Batch rules for performance └─────────────────────────────────────────────────────────────────────────────┘ ┌───────────────┴───────────────┐ ┌───────────────────────┐ ┌───────────────────────┐ ESLint Engine Heuristic Engine (eslint-engine.js) (heuristic-engine.js)│ Rules: S001, S002... Rules: S003, S004... (7 ESLint rules) (50 heuristic rules) └───────────────────────┘ └───────────────────────┘ ┌───────────────────────┐ ┌───────────────────────┐ ESLint Core Semantic Engine - Parse with ESLint (ts-morph) - Run custom rules - Symbol Table - AST analysis - Pattern matching └───────────────────────┘ └───────────────────────┘ ┌───────────────────────┐ ┌───────────────────────┐ Violations: Violations: [{file, line, msg}] [{file, line, msg}] └───────────────────────┘ └───────────────────────┘ └───────────────┬───────────────┘ ┌─────────────────────────────────────────────────────────────────────────────┐ 4. MERGE RESULTS - Combine violations from all engines - Calculate statistics - Generate summary └─────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────────┐ 5. OUTPUT SERVICE (output-service.js) - Format results (eslint/json/summary/table) - Write to file if --output specified - Upload to API if --upload-report - GitHub annotations if --github-annotate └─────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────────┐ 6. CONSOLE OUTPUT 📊 Sun Lint Summary: Analysis completed in 10762ms Files: 237 | Total: 58 Errors: 55 Warnings: 3 └─────────────────────────────────────────────────────────────────────────────┘ ``` --- ## Engine Architecture ### Engine Interface ```javascript // core/interfaces/analysis-engine.interface.js class AnalysisEngineInterface { constructor(id, version, supportedLanguages) { this.id = id; // 'eslint', 'heuristic', 'openai' this.version = version; // '4.0' this.supportedLanguages = supportedLanguages; // ['typescript', 'javascript'] } async initialize(config) { } async analyze(files, rules, options) { } isRuleSupported(ruleId) { } getSupportedRules() { } cleanup() { } } ``` ### Engine Comparison | Engine | Languages | Approach | Speed | Accuracy | |--------|-----------|----------|-------|----------| | **ESLint** | JS/TS only | AST + ESLint rules | Fast | High | | **Heuristic** | All | ts-morph + Regex | Medium | Medium-High | | **OpenAI** | All | AI analysis | Slow | Variable | ### Heuristic Engine Detail ``` ┌─────────────────────────────────────────────────────────────────┐ HEURISTIC ENGINE └─────────────────────────────────────────────────────────────────┘ ┌───────────────┼───────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ Semantic AST Pattern Analysis Analysis Matching (ts-morph) (tree-sitter)│ (Regex) └─────────────┘ └─────────────┘ └─────────────┘ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ Symbol Table│ Parse tree Text search Type info Node types Line/column Cross-file Visitors Fast scan └─────────────┘ └─────────────┘ └─────────────┘ └───────────────┼───────────────┘ ┌─────────────────┐ Violations └─────────────────┘ ``` --- ## Rule System ### Rule Definition Structure ```json // config/presets/security.json { "name": "@sun/sunlint/security", "rules": { "S001": "error", "S002": "error", "S003": "warn", ... } } ``` ### Rule Selection Flow ``` ┌─────────────────────────────────────────────────────────────────┐ CLI Options --rule, --rules, --all, --quality, --security, --category └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ RULE SELECTION SERVICE (rule-selection-service.js) └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────┼─────────────────────┐ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ --rule C019 --security (no option) Single rule Load preset Use config [C019] security.json file rules 57 rules └───────────────┘ └───────────────┘ └───────────────┘ └─────────────────────┼─────────────────────┘ ┌─────────────────┐ Rules to Run [{id, name,...}] └─────────────────┘ ``` ### Rule to Engine Mapping ``` ┌─────────────────────────────────────────────────────────────────┐ Rules to Analyze: [S001, S003, S005, S017, S022, ...] └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ ORCHESTRATOR: groupRulesByEngine() For each rule: 1. Check rule.analyzer field 2. Check config.requestedEngine (--engine option) 3. Check engine.isRuleSupported(ruleId) 4. Fallback to 'heuristic' └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────┴─────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐ ESLint Engine Heuristic Engine Rules: Rules: - S001 (custom) - S003 - S002 (custom) - S004 - S009 (custom) - S005 - S017 (custom) - S006 ... - S012 (7 ESLint rules) ... (50 heuristic rules) └───────────────────────┘ └───────────────────────┘ ``` --- ## Data Flow Diagrams ### Config Loading Flow ``` ┌─────────────────────────────────────────────────────────────────┐ CONFIG LOADING ORDER (Lower Higher Priority) └─────────────────────────────────────────────────────────────────┘ 1. Built-in Defaults (config-manager.js defaultConfig) 2. Environment Variables (SUNLINT_RULES, SUNLINT_AI_ENABLED) 3. Global Config (~/.sunlint.json) 4. Project Config (sunlint.config.json, .sunlint.json) 5. CLI Options (--rule, --security, --format, etc.) ⚠️ Note: --all/--security/--quality OVERRIDE config rules ┌─────────────────────────────┐ Final Merged Config └─────────────────────────────┘ ``` ### File Analysis Flow ``` ┌─────────────────────────────────────────────────────────────────┐ Input: --input=src (directory) └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ FILE TARGETING SERVICE 1. Resolve path: src /full/path/to/src 2. Discover files recursively 3. Apply include patterns: ['**/*.ts', '**/*.js'] 4. Apply exclude patterns: ['node_modules/**', 'dist/**'] 5. Filter by language if specified └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ Target Files: [ '/path/src/index.ts', '/path/src/utils/helper.ts', '/path/src/components/Button.tsx', ... ] Total: 500 files └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ SEMANTIC ENGINE (ts-morph) 1. Create ts-morph Project 2. Load files into Symbol Table (max 1000 by default) 3. Build AST for each file 4. Cache for reuse across rules └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ FOR EACH FILE: 1. Get file content 2. Get AST from ts-morph (if available) 3. FOR EACH RULE: - Run rule analyzer - Collect violations 4. Aggregate file violations └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ All Violations: [ { ruleId: 'S022', file: '/path/src/utils/helper.ts', line: 42, column: 10, message: 'XSS vulnerability detected', severity: 'error' }, ... ] └─────────────────────────────────────────────────────────────────┘ ``` ### Output Generation Flow ``` ┌─────────────────────────────────────────────────────────────────┐ Analysis Results (violations array) └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ OUTPUT SERVICE 1. Calculate statistics 2. Group by file/rule 3. Format based on --format option └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────┼─────────────────────┐ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ --format= --format= --format= eslint json summary ESLint-style Raw JSON Summary output output table └───────────────┘ └───────────────┘ └───────────────┘ └─────────────────────┼─────────────────────┘ ┌─────────────────────┴─────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐ Console Output File Output (default) (--output=report.json)│ └───────────────────────┘ └───────────────────────┘ (optional) ┌─────────────────────┴─────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐ Upload to API GitHub Annotations (--upload-report) (--github-annotate) └───────────────────────┘ └───────────────────────┘ ``` --- ## Key Integration Points for Dart Support Để thêm Dart support, cần tích hợp tại các điểm sau: ### 1. File Targeting Service ```javascript // core/file-targeting-service.js this.supportedLanguages = ['typescript', 'javascript', 'dart', ...]; // Đã sẵn 'dart' trong list ``` ### 2. Engine Configuration ```json // config/engines/engines.json "heuristic": { "supportedLanguages": ["typescript", "javascript", "dart", ...], // Đã sẵn 'dart' trong list } ``` ### 3. Semantic Engine ```javascript // core/semantic-engine.js // Hiện tại chỉ hỗ trợ ts/js // CẦN THÊM: Dart analyzer subprocess ``` ### 4. New Dart Analyzer Adapter ```javascript // core/adapters/dart-analyzer.ts (MỚI) class DartAnalyzer implements ILanguageAnalyzer { // Spawn Dart binary subprocess // JSON-RPC communication } ``` --- ## Summary SunLint sử dụng kiến trúc **Plugin-Based Engine** với: 1. **CLI Layer**: Parse arguments, bootstrap 2. **Orchestrator Layer**: Route rules to engines, merge results 3. **Engine Layer**: Actual analysis (ESLint, Heuristic, OpenAI) 4. **Output Layer**: Format and output results Để thêm ngôn ngữ mới (như Dart): - Core đã sẵn sàng (multi-language support) - Cần thêm analyzer adapter cho ngôn ngữ đó - Cần định nghĩa rules cho ngôn ngữ đó