@sun-asterisk/sunlint 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -1
- package/CONTRIBUTING.md +533 -70
- package/README.md +16 -2
- package/config/engines/engines-enhanced.json +86 -0
- package/config/engines/semantic-config.json +114 -0
- package/config/eslint-rule-mapping.json +50 -38
- package/config/rules/enhanced-rules-registry.json +2503 -0
- package/config/rules/rules-registry-generated.json +785 -837
- package/core/adapters/sunlint-rule-adapter.js +25 -30
- package/core/analysis-orchestrator.js +42 -2
- package/core/categories.js +52 -0
- package/core/category-constants.js +39 -0
- package/core/cli-action-handler.js +32 -5
- package/core/config-manager.js +111 -0
- package/core/config-merger.js +61 -0
- package/core/constants/categories.js +168 -0
- package/core/constants/defaults.js +165 -0
- package/core/constants/engines.js +185 -0
- package/core/constants/index.js +30 -0
- package/core/constants/rules.js +215 -0
- package/core/file-targeting-service.js +128 -7
- package/core/interfaces/rule-plugin.interface.js +207 -0
- package/core/plugin-manager.js +448 -0
- package/core/rule-selection-service.js +42 -15
- package/core/semantic-engine.js +560 -0
- package/core/semantic-rule-base.js +433 -0
- package/core/unified-rule-registry.js +484 -0
- package/docs/CONSTANTS-ARCHITECTURE.md +288 -0
- package/engines/core/base-engine.js +249 -0
- package/engines/engine-factory.js +275 -0
- package/engines/eslint-engine.js +171 -19
- package/engines/heuristic-engine.js +511 -78
- package/integrations/eslint/plugin/index.js +27 -27
- package/package.json +10 -6
- package/rules/common/C003_no_vague_abbreviations/analyzer.js +1 -1
- package/rules/common/C029_catch_block_logging/analyzer.js +17 -5
- package/rules/common/C047_no_duplicate_retry_logic/c047-semantic-rule.js +278 -0
- package/rules/common/C047_no_duplicate_retry_logic/symbol-analyzer-enhanced.js +968 -0
- package/rules/common/C047_no_duplicate_retry_logic/symbol-config.json +71 -0
- package/rules/index.js +7 -0
- package/scripts/category-manager.js +150 -0
- package/scripts/generate-rules-registry.js +88 -0
- package/scripts/migrate-rule-registry.js +157 -0
- package/scripts/validate-system.js +48 -0
- package/.sunlint.json +0 -35
- package/config/README.md +0 -88
- package/config/engines/eslint-rule-mapping.json +0 -74
- package/config/schemas/sunlint-schema.json +0 -0
- package/config/testing/test-s005-working.ts +0 -22
- package/core/multi-rule-runner.js +0 -0
- package/engines/tree-sitter-parser.js +0 -0
- package/engines/universal-ast-engine.js +0 -0
- package/rules/common/C029_catch_block_logging/analyzer-backup.js +0 -426
- package/rules/common/C029_catch_block_logging/analyzer-fixed.js +0 -130
- package/rules/common/C029_catch_block_logging/analyzer-multi-tech.js +0 -487
- package/rules/common/C029_catch_block_logging/analyzer-simple.js +0 -110
- package/rules/common/C029_catch_block_logging/ast-analyzer-backup.js +0 -441
- package/rules/common/C029_catch_block_logging/ast-analyzer-new.js +0 -127
- package/rules/common/C029_catch_block_logging/ast-analyzer.js +0 -133
- package/rules/common/C029_catch_block_logging/cfg-analyzer.js +0 -408
- package/rules/common/C029_catch_block_logging/dataflow-analyzer.js +0 -454
- package/rules/common/C029_catch_block_logging/multi-language-ast-engine.js +0 -700
- package/rules/common/C029_catch_block_logging/pattern-learning-analyzer.js +0 -568
- package/rules/common/C029_catch_block_logging/semantic-analyzer.js +0 -459
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# SunLint Constants Architecture
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
SunLint now uses a centralized constants sub-package located at `core/constants/` to manage all constants and configuration values. This improves code organization, maintainability, and extensibility.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
core/
|
|
11
|
+
constants/
|
|
12
|
+
categories.js # Category-principle mappings and functions
|
|
13
|
+
defaults.js # Default configurations and values
|
|
14
|
+
engines.js # Engine capabilities and configurations
|
|
15
|
+
rules.js # Rule-related constants and utilities
|
|
16
|
+
index.js # Barrel export for all constants
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Migration Guide
|
|
20
|
+
|
|
21
|
+
### Before (Old approach)
|
|
22
|
+
```javascript
|
|
23
|
+
// Scattered constants across multiple files
|
|
24
|
+
const { getValidCategories } = require('./core/category-constants');
|
|
25
|
+
const defaultRules = ['C006', 'C019']; // Hardcoded in various files
|
|
26
|
+
const SUPPORTED_ENGINES = { /* scattered */ };
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### After (New centralized approach)
|
|
30
|
+
```javascript
|
|
31
|
+
// Option 1: Import specific module
|
|
32
|
+
const { getValidCategories } = require('./core/constants/categories');
|
|
33
|
+
const { getDefaultRuleSet } = require('./core/constants/defaults');
|
|
34
|
+
const { SUPPORTED_ENGINES } = require('./core/constants/engines');
|
|
35
|
+
|
|
36
|
+
// Option 2: Import from barrel export
|
|
37
|
+
const {
|
|
38
|
+
getValidCategories,
|
|
39
|
+
getDefaultRuleSet,
|
|
40
|
+
SUPPORTED_ENGINES
|
|
41
|
+
} = require('./core/constants');
|
|
42
|
+
|
|
43
|
+
// Option 3: Import entire module
|
|
44
|
+
const constants = require('./core/constants');
|
|
45
|
+
const categories = constants.getValidCategories();
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Modules
|
|
49
|
+
|
|
50
|
+
### 1. Categories (`core/constants/categories.js`)
|
|
51
|
+
|
|
52
|
+
**Purpose**: Category-principle mappings, validation, and normalization.
|
|
53
|
+
|
|
54
|
+
**Key Exports**:
|
|
55
|
+
```javascript
|
|
56
|
+
// Constants
|
|
57
|
+
SUNLINT_PRINCIPLES // Object with all principle constants
|
|
58
|
+
CATEGORY_PRINCIPLE_MAP // Category to principle mapping
|
|
59
|
+
CATEGORY_DESCRIPTIONS // Human-readable descriptions
|
|
60
|
+
|
|
61
|
+
// Functions
|
|
62
|
+
getValidCategories() // Get all valid categories
|
|
63
|
+
getCategoryPrinciples(category) // Get principles for category
|
|
64
|
+
isValidCategory(category) // Validate category
|
|
65
|
+
normalizeCategory(category) // Normalize and validate
|
|
66
|
+
getCategoryStats() // Get statistics
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Example Usage**:
|
|
70
|
+
```javascript
|
|
71
|
+
const { getValidCategories, normalizeCategory } = require('./core/constants/categories');
|
|
72
|
+
|
|
73
|
+
const validCategories = getValidCategories();
|
|
74
|
+
// ['security', 'quality', 'performance', ...]
|
|
75
|
+
|
|
76
|
+
const normalized = normalizeCategory('QUALITY');
|
|
77
|
+
// 'quality'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2. Defaults (`core/constants/defaults.js`)
|
|
81
|
+
|
|
82
|
+
**Purpose**: Default configurations, rule sets, and standard values.
|
|
83
|
+
|
|
84
|
+
**Key Exports**:
|
|
85
|
+
```javascript
|
|
86
|
+
// Constants
|
|
87
|
+
DEFAULT_RULE_SETS // Predefined rule sets (MINIMAL, ESSENTIAL, etc.)
|
|
88
|
+
DEFAULT_CONFIG // Default configuration object
|
|
89
|
+
DEFAULT_SEVERITIES // Severity levels
|
|
90
|
+
DEFAULT_TIMEOUTS // Timeout configurations
|
|
91
|
+
DEFAULT_LIMITS // File size and processing limits
|
|
92
|
+
|
|
93
|
+
// Functions
|
|
94
|
+
getDefaultRuleSet(name) // Get predefined rule set
|
|
95
|
+
getDefaultConfig(overrides) // Get configuration with overrides
|
|
96
|
+
getLanguageExtensions(lang) // Get file extensions for language
|
|
97
|
+
isFileSizeValid(size) // Check file size limits
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Example Usage**:
|
|
101
|
+
```javascript
|
|
102
|
+
const { getDefaultRuleSet, getDefaultConfig } = require('./core/constants/defaults');
|
|
103
|
+
|
|
104
|
+
const essentialRules = getDefaultRuleSet('ESSENTIAL');
|
|
105
|
+
// ['C001', 'C002', 'C003', ...]
|
|
106
|
+
|
|
107
|
+
const config = getDefaultConfig({ verbose: true });
|
|
108
|
+
// { verbose: true, useRegistry: true, ... }
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 3. Engines (`core/constants/engines.js`)
|
|
112
|
+
|
|
113
|
+
**Purpose**: Engine capabilities, configurations, and language support.
|
|
114
|
+
|
|
115
|
+
**Key Exports**:
|
|
116
|
+
```javascript
|
|
117
|
+
// Constants
|
|
118
|
+
SUPPORTED_ENGINES // Object with all supported engines
|
|
119
|
+
ENGINE_CAPABILITIES // Engine features and language support
|
|
120
|
+
ENGINE_MODES // Execution modes (sequential, parallel, etc.)
|
|
121
|
+
ENGINE_PERFORMANCE // Performance characteristics
|
|
122
|
+
|
|
123
|
+
// Functions
|
|
124
|
+
getEngineLanguages(engine) // Get supported languages
|
|
125
|
+
getEnginesForLanguage(language) // Get engines for language
|
|
126
|
+
getRecommendedEngine(language) // Get best engine for language
|
|
127
|
+
isLanguageSupported(engine, lang) // Check support
|
|
128
|
+
getEnginePerformance(engine) // Get performance info
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Example Usage**:
|
|
132
|
+
```javascript
|
|
133
|
+
const { getEnginesForLanguage, getRecommendedEngine } = require('./core/constants/engines');
|
|
134
|
+
|
|
135
|
+
const jsEngines = getEnginesForLanguage('javascript');
|
|
136
|
+
// [{ name: 'heuristic', priority: 1, features: [...] }, ...]
|
|
137
|
+
|
|
138
|
+
const recommended = getRecommendedEngine('typescript');
|
|
139
|
+
// 'heuristic'
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 4. Rules (`core/constants/rules.js`)
|
|
143
|
+
|
|
144
|
+
**Purpose**: Rule-related constants, metadata, and utilities.
|
|
145
|
+
|
|
146
|
+
**Key Exports**:
|
|
147
|
+
```javascript
|
|
148
|
+
// Constants
|
|
149
|
+
RULE_SEVERITIES // Severity levels (ERROR, WARNING, etc.)
|
|
150
|
+
RULE_STATUS // Execution status values
|
|
151
|
+
RULE_TYPES // Analysis types (HEURISTIC, AST, etc.)
|
|
152
|
+
RULE_SCOPES // Operation scopes (FILE, PROJECT, etc.)
|
|
153
|
+
RULE_LANGUAGE_PATTERNS // Regex patterns for rule IDs
|
|
154
|
+
RULE_TIMEOUTS // Timeout values by rule type
|
|
155
|
+
|
|
156
|
+
// Functions
|
|
157
|
+
getLanguageFromRuleId(ruleId) // Extract language from rule ID
|
|
158
|
+
isValidRuleId(ruleId) // Validate rule ID format
|
|
159
|
+
getRuleTimeout(type) // Get timeout for rule type
|
|
160
|
+
getDefaultRuleMetadata(overrides) // Get rule metadata template
|
|
161
|
+
isValidSeverity(severity) // Validate severity level
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Example Usage**:
|
|
165
|
+
```javascript
|
|
166
|
+
const { getLanguageFromRuleId, isValidRuleId } = require('./core/constants/rules');
|
|
167
|
+
|
|
168
|
+
const language = getLanguageFromRuleId('C001');
|
|
169
|
+
// 'common'
|
|
170
|
+
|
|
171
|
+
const isValid = isValidRuleId('CUSTOM_RULE');
|
|
172
|
+
// true
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Backward Compatibility
|
|
176
|
+
|
|
177
|
+
The following files are maintained for backward compatibility but are deprecated:
|
|
178
|
+
|
|
179
|
+
- `core/category-constants.js` - Proxies to `core/constants/categories.js`
|
|
180
|
+
- `core/categories.js` - Proxies to `core/constants/categories.js`
|
|
181
|
+
|
|
182
|
+
**Migration Path**:
|
|
183
|
+
1. Update imports to use `core/constants/*` directly
|
|
184
|
+
2. Replace deprecated file imports gradually
|
|
185
|
+
3. Legacy files will be removed in future versions
|
|
186
|
+
|
|
187
|
+
## Benefits
|
|
188
|
+
|
|
189
|
+
### 1. **Better Organization**
|
|
190
|
+
- Related constants grouped together
|
|
191
|
+
- Clear separation of concerns
|
|
192
|
+
- Easier to locate and modify constants
|
|
193
|
+
|
|
194
|
+
### 2. **Improved Maintainability**
|
|
195
|
+
- Single source of truth for each type of constant
|
|
196
|
+
- Centralized documentation and examples
|
|
197
|
+
- Easier to add new constants or modify existing ones
|
|
198
|
+
|
|
199
|
+
### 3. **Enhanced Extensibility**
|
|
200
|
+
- Modular structure supports new constant types
|
|
201
|
+
- Barrel export provides flexible import options
|
|
202
|
+
- Framework for adding new engines, rules, categories
|
|
203
|
+
|
|
204
|
+
### 4. **Developer Experience**
|
|
205
|
+
- Clearer imports with specific module names
|
|
206
|
+
- Better IDE support and autocomplete
|
|
207
|
+
- Self-documenting code structure
|
|
208
|
+
|
|
209
|
+
## Best Practices
|
|
210
|
+
|
|
211
|
+
### 1. **Import Strategy**
|
|
212
|
+
```javascript
|
|
213
|
+
// ✅ Good: Import specific functions
|
|
214
|
+
const { getValidCategories, normalizeCategory } = require('./core/constants/categories');
|
|
215
|
+
|
|
216
|
+
// ✅ Good: Import from barrel for multiple modules
|
|
217
|
+
const { getValidCategories, getDefaultRuleSet } = require('./core/constants');
|
|
218
|
+
|
|
219
|
+
// ❌ Avoid: Importing entire modules unnecessarily
|
|
220
|
+
const allConstants = require('./core/constants');
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### 2. **Adding New Constants**
|
|
224
|
+
```javascript
|
|
225
|
+
// Add to appropriate module (e.g., categories.js)
|
|
226
|
+
const NEW_CATEGORY_FEATURE = 'new-feature';
|
|
227
|
+
|
|
228
|
+
// Export in module
|
|
229
|
+
module.exports = {
|
|
230
|
+
NEW_CATEGORY_FEATURE,
|
|
231
|
+
// ... other exports
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// Update barrel export (index.js) if needed
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### 3. **Extending Functionality**
|
|
238
|
+
```javascript
|
|
239
|
+
// Add utility functions to appropriate modules
|
|
240
|
+
function getAdvancedCategoryInfo(category) {
|
|
241
|
+
// Implementation
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Export with other functions
|
|
245
|
+
module.exports = {
|
|
246
|
+
// ... existing exports
|
|
247
|
+
getAdvancedCategoryInfo
|
|
248
|
+
};
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Testing
|
|
252
|
+
|
|
253
|
+
Each constants module includes comprehensive tests:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
# Test entire constants structure
|
|
257
|
+
node test-constants-structure.js
|
|
258
|
+
|
|
259
|
+
# Test backward compatibility
|
|
260
|
+
node test-centralized-categories.js
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Future Enhancements
|
|
264
|
+
|
|
265
|
+
### Planned Features
|
|
266
|
+
1. **Dynamic Configuration Loading** - Load constants from external files
|
|
267
|
+
2. **Environment-specific Constants** - Different values for dev/prod
|
|
268
|
+
3. **Validation Schemas** - JSON Schema validation for all constants
|
|
269
|
+
4. **Hot Reloading** - Update constants without restarting
|
|
270
|
+
|
|
271
|
+
### Extension Points
|
|
272
|
+
- Add new constant modules (e.g., `integrations.js`, `plugins.js`)
|
|
273
|
+
- Extend barrel export for new modules
|
|
274
|
+
- Add validation functions for new constant types
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Quick Reference
|
|
279
|
+
|
|
280
|
+
| Module | Purpose | Key Functions |
|
|
281
|
+
|--------|---------|---------------|
|
|
282
|
+
| `categories.js` | Category management | `getValidCategories()`, `normalizeCategory()` |
|
|
283
|
+
| `defaults.js` | Default values | `getDefaultConfig()`, `getDefaultRuleSet()` |
|
|
284
|
+
| `engines.js` | Engine configuration | `getEnginesForLanguage()`, `getRecommendedEngine()` |
|
|
285
|
+
| `rules.js` | Rule utilities | `getLanguageFromRuleId()`, `isValidRuleId()` |
|
|
286
|
+
| `index.js` | Barrel export | All functions from all modules |
|
|
287
|
+
|
|
288
|
+
For detailed API documentation, see the JSDoc comments in each module file.
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Engine Abstract Class
|
|
3
|
+
* Following Rule C005: Single responsibility - Base engine functionality
|
|
4
|
+
* Following Rule C014: Dependency injection - Plugin architecture
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const EventEmitter = require('events');
|
|
8
|
+
|
|
9
|
+
class BaseEngine extends EventEmitter {
|
|
10
|
+
constructor(name, version, supportedLanguages = []) {
|
|
11
|
+
super();
|
|
12
|
+
this.name = name;
|
|
13
|
+
this.version = version;
|
|
14
|
+
this.supportedLanguages = supportedLanguages;
|
|
15
|
+
this.initialized = false;
|
|
16
|
+
this.verbose = false;
|
|
17
|
+
this.ruleRegistry = new Map();
|
|
18
|
+
this.pluginManager = null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Set plugin manager for this engine
|
|
23
|
+
* @param {PluginManager} pluginManager - Plugin manager instance
|
|
24
|
+
*/
|
|
25
|
+
setPluginManager(pluginManager) {
|
|
26
|
+
this.pluginManager = pluginManager;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Abstract method - must be implemented by subclasses
|
|
31
|
+
*/
|
|
32
|
+
async initialize(config) {
|
|
33
|
+
this.verbose = config.verbose || false;
|
|
34
|
+
|
|
35
|
+
// Load rules from plugin manager if available
|
|
36
|
+
if (this.pluginManager) {
|
|
37
|
+
const engineRules = await this.pluginManager.loadRulesForEngine(this.name, config);
|
|
38
|
+
this.ruleRegistry = engineRules;
|
|
39
|
+
|
|
40
|
+
if (this.verbose) {
|
|
41
|
+
console.log(`🔧 [${this.name}] Loaded ${engineRules.size} rules from Plugin Manager`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.initialized = true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Abstract method - must be implemented by subclasses
|
|
50
|
+
*/
|
|
51
|
+
async analyze(files, rules, options) {
|
|
52
|
+
throw new Error('analyze() must be implemented by subclass');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Analyze files with a specific rule plugin
|
|
57
|
+
* @param {string} ruleId - Rule identifier
|
|
58
|
+
* @param {Array} files - Files to analyze
|
|
59
|
+
* @param {string} language - Programming language
|
|
60
|
+
* @param {Object} options - Analysis options
|
|
61
|
+
* @returns {Array} Array of violations
|
|
62
|
+
*/
|
|
63
|
+
async analyzeWithRule(ruleId, files, language, options = {}) {
|
|
64
|
+
const ruleInfo = this.ruleRegistry.get(ruleId);
|
|
65
|
+
|
|
66
|
+
if (!ruleInfo) {
|
|
67
|
+
if (this.verbose) {
|
|
68
|
+
console.warn(`⚠️ [${this.name}] Rule ${ruleId} not found`);
|
|
69
|
+
}
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
const violations = await ruleInfo.plugin.analyze(files, language, {
|
|
75
|
+
...options,
|
|
76
|
+
engine: this.name,
|
|
77
|
+
metadata: ruleInfo.metadata
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Ensure violations have correct rule ID
|
|
81
|
+
return violations.map(violation => ({
|
|
82
|
+
...violation,
|
|
83
|
+
ruleId: ruleId,
|
|
84
|
+
engine: this.name,
|
|
85
|
+
pluginType: ruleInfo.type
|
|
86
|
+
}));
|
|
87
|
+
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (this.verbose) {
|
|
90
|
+
console.error(`❌ [${this.name}] Error analyzing with rule ${ruleId}: ${error.message}`);
|
|
91
|
+
}
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Check if a rule is supported by this engine
|
|
98
|
+
* @param {string} ruleId - Rule ID to check
|
|
99
|
+
* @returns {boolean} True if rule is supported
|
|
100
|
+
*/
|
|
101
|
+
isRuleSupported(ruleId) {
|
|
102
|
+
return this.ruleRegistry.has(ruleId);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Get engine information
|
|
107
|
+
* @returns {Object} Engine metadata
|
|
108
|
+
*/
|
|
109
|
+
getEngineInfo() {
|
|
110
|
+
return {
|
|
111
|
+
name: this.name,
|
|
112
|
+
version: this.version,
|
|
113
|
+
supportedLanguages: this.supportedLanguages,
|
|
114
|
+
initialized: this.initialized,
|
|
115
|
+
rulesLoaded: this.ruleRegistry.size
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Register a rule with the engine
|
|
121
|
+
* @param {string} ruleId - Rule identifier
|
|
122
|
+
* @param {Object} ruleInfo - Rule information and analyzer
|
|
123
|
+
*/
|
|
124
|
+
registerRule(ruleId, ruleInfo) {
|
|
125
|
+
this.ruleRegistry.set(ruleId, ruleInfo);
|
|
126
|
+
this.emit('ruleRegistered', { ruleId, engine: this.name });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Unregister a rule from the engine
|
|
131
|
+
* @param {string} ruleId - Rule identifier
|
|
132
|
+
*/
|
|
133
|
+
unregisterRule(ruleId) {
|
|
134
|
+
const removed = this.ruleRegistry.delete(ruleId);
|
|
135
|
+
if (removed) {
|
|
136
|
+
this.emit('ruleUnregistered', { ruleId, engine: this.name });
|
|
137
|
+
}
|
|
138
|
+
return removed;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Get all registered rules
|
|
143
|
+
* @returns {string[]} Array of rule IDs
|
|
144
|
+
*/
|
|
145
|
+
getRegisteredRules() {
|
|
146
|
+
return Array.from(this.ruleRegistry.keys());
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Set plugin manager
|
|
151
|
+
* @param {Object} pluginManager - Plugin manager instance
|
|
152
|
+
*/
|
|
153
|
+
setPluginManager(pluginManager) {
|
|
154
|
+
this.pluginManager = pluginManager;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Load rules using plugin manager
|
|
159
|
+
* @param {Object} config - Configuration options
|
|
160
|
+
*/
|
|
161
|
+
async loadRules(config = {}) {
|
|
162
|
+
if (!this.pluginManager) {
|
|
163
|
+
throw new Error('Plugin manager not set');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const rules = await this.pluginManager.loadRulesForEngine(this.name, config);
|
|
167
|
+
|
|
168
|
+
for (const [ruleId, ruleInfo] of rules) {
|
|
169
|
+
this.registerRule(ruleId, ruleInfo);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (this.verbose) {
|
|
173
|
+
console.log(`📚 [${this.name}] Loaded ${rules.size} rules`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Cleanup engine resources
|
|
179
|
+
*/
|
|
180
|
+
async cleanup() {
|
|
181
|
+
this.ruleRegistry.clear();
|
|
182
|
+
this.initialized = false;
|
|
183
|
+
this.emit('cleanup', { engine: this.name });
|
|
184
|
+
|
|
185
|
+
if (this.verbose) {
|
|
186
|
+
console.log(`🔧 [${this.name}] Engine cleanup completed`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Group files by programming language
|
|
192
|
+
* @param {string[]} files - Files to group
|
|
193
|
+
* @returns {Object} Files grouped by language
|
|
194
|
+
*/
|
|
195
|
+
groupFilesByLanguage(files) {
|
|
196
|
+
const groups = {};
|
|
197
|
+
|
|
198
|
+
for (const file of files) {
|
|
199
|
+
const language = this.detectLanguage(file);
|
|
200
|
+
if (!groups[language]) {
|
|
201
|
+
groups[language] = [];
|
|
202
|
+
}
|
|
203
|
+
groups[language].push(file);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return groups;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Detect programming language from file extension
|
|
211
|
+
* @param {string} filePath - File path
|
|
212
|
+
* @returns {string} Detected language
|
|
213
|
+
*/
|
|
214
|
+
detectLanguage(filePath) {
|
|
215
|
+
const path = require('path');
|
|
216
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
217
|
+
|
|
218
|
+
const languageMap = {
|
|
219
|
+
'.ts': 'typescript',
|
|
220
|
+
'.tsx': 'typescript',
|
|
221
|
+
'.js': 'javascript',
|
|
222
|
+
'.jsx': 'javascript',
|
|
223
|
+
'.dart': 'dart',
|
|
224
|
+
'.swift': 'swift',
|
|
225
|
+
'.kt': 'kotlin',
|
|
226
|
+
'.kts': 'kotlin',
|
|
227
|
+
'.java': 'java',
|
|
228
|
+
'.py': 'python',
|
|
229
|
+
'.go': 'go',
|
|
230
|
+
'.rs': 'rust',
|
|
231
|
+
'.php': 'php',
|
|
232
|
+
'.rb': 'ruby'
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
return languageMap[ext] || 'unknown';
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Check if language is supported
|
|
240
|
+
* @param {string} language - Language to check
|
|
241
|
+
* @returns {boolean} True if supported
|
|
242
|
+
*/
|
|
243
|
+
isLanguageSupported(language) {
|
|
244
|
+
return this.supportedLanguages.includes(language) ||
|
|
245
|
+
this.supportedLanguages.includes('all');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
module.exports = BaseEngine;
|