@sun-asterisk/sunlint 1.2.1 → 1.2.2
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/config/rule-analysis-strategies.js +18 -2
- package/engines/eslint-engine.js +9 -11
- package/engines/heuristic-engine.js +55 -31
- package/package.json +2 -1
- package/rules/README.md +252 -0
- package/rules/common/C002_no_duplicate_code/analyzer.js +65 -0
- package/rules/common/C002_no_duplicate_code/config.json +23 -0
- package/rules/common/C003_no_vague_abbreviations/analyzer.js +418 -0
- package/rules/common/C003_no_vague_abbreviations/config.json +35 -0
- package/rules/common/C006_function_naming/analyzer.js +504 -0
- package/rules/common/C006_function_naming/config.json +86 -0
- package/rules/common/C006_function_naming/smart-analyzer.js +503 -0
- package/rules/common/C010_limit_block_nesting/analyzer.js +389 -0
- package/rules/common/C012_command_query_separation/analyzer.js +481 -0
- package/rules/common/C012_command_query_separation/ast-analyzer.js +495 -0
- package/rules/common/C013_no_dead_code/analyzer.js +206 -0
- package/rules/common/C014_dependency_injection/analyzer.js +338 -0
- package/rules/common/C017_constructor_logic/analyzer.js +314 -0
- package/rules/common/C019_log_level_usage/analyzer.js +362 -0
- package/rules/common/C019_log_level_usage/config.json +121 -0
- package/rules/common/C029_catch_block_logging/analyzer-backup.js +426 -0
- package/rules/common/C029_catch_block_logging/analyzer-fixed.js +130 -0
- package/rules/common/C029_catch_block_logging/analyzer-multi-tech.js +487 -0
- package/rules/common/C029_catch_block_logging/analyzer-simple.js +110 -0
- package/rules/common/C029_catch_block_logging/analyzer-smart-pipeline.js +755 -0
- package/rules/common/C029_catch_block_logging/analyzer.js +129 -0
- package/rules/common/C029_catch_block_logging/ast-analyzer-backup.js +441 -0
- package/rules/common/C029_catch_block_logging/ast-analyzer-new.js +127 -0
- package/rules/common/C029_catch_block_logging/ast-analyzer.js +133 -0
- package/rules/common/C029_catch_block_logging/cfg-analyzer.js +408 -0
- package/rules/common/C029_catch_block_logging/config.json +59 -0
- package/rules/common/C029_catch_block_logging/dataflow-analyzer.js +454 -0
- package/rules/common/C029_catch_block_logging/multi-language-ast-engine.js +700 -0
- package/rules/common/C029_catch_block_logging/pattern-learning-analyzer.js +568 -0
- package/rules/common/C029_catch_block_logging/semantic-analyzer.js +459 -0
- package/rules/common/C031_validation_separation/analyzer.js +186 -0
- package/rules/common/C041_no_sensitive_hardcode/analyzer.js +292 -0
- package/rules/common/C041_no_sensitive_hardcode/ast-analyzer.js +296 -0
- package/rules/common/C042_boolean_name_prefix/analyzer.js +300 -0
- package/rules/common/C043_no_console_or_print/analyzer.js +431 -0
- package/rules/common/C047_no_duplicate_retry_logic/analyzer.js +590 -0
- package/rules/common/C075_explicit_return_types/analyzer.js +103 -0
- package/rules/common/C076_single_test_behavior/analyzer.js +121 -0
- package/rules/docs/C002_no_duplicate_code.md +57 -0
- package/rules/docs/C031_validation_separation.md +72 -0
- package/rules/index.js +155 -0
- package/rules/migration/converter.js +385 -0
- package/rules/migration/mapping.json +164 -0
- package/rules/parser/constants.js +31 -0
- package/rules/parser/file-config.js +80 -0
- package/rules/parser/rule-parser-simple.js +305 -0
- package/rules/parser/rule-parser.js +527 -0
- package/rules/security/S015_insecure_tls_certificate/analyzer.js +150 -0
- package/rules/security/S015_insecure_tls_certificate/ast-analyzer.js +237 -0
- package/rules/security/S023_no_json_injection/analyzer.js +278 -0
- package/rules/security/S023_no_json_injection/ast-analyzer.js +359 -0
- package/rules/security/S026_json_schema_validation/analyzer.js +251 -0
- package/rules/security/S026_json_schema_validation/config.json +27 -0
- package/rules/security/S027_no_hardcoded_secrets/analyzer.js +436 -0
- package/rules/security/S027_no_hardcoded_secrets/config.json +29 -0
- package/rules/security/S029_csrf_protection/analyzer.js +330 -0
- package/rules/tests/C002_no_duplicate_code.test.js +50 -0
- package/rules/universal/C010/generic.js +0 -0
- package/rules/universal/C010/tree-sitter-analyzer.js +0 -0
- package/rules/utils/ast-utils.js +191 -0
- package/rules/utils/base-analyzer.js +98 -0
- package/rules/utils/pattern-matchers.js +239 -0
- package/rules/utils/rule-helpers.js +264 -0
- package/rules/utils/severity-constants.js +93 -0
- package/scripts/generate_insights.js +188 -0
- package/scripts/merge-reports.js +0 -424
- package/scripts/test-scripts/README.md +0 -22
- package/scripts/test-scripts/test-c041-comparison.js +0 -114
- package/scripts/test-scripts/test-c041-eslint.js +0 -67
- package/scripts/test-scripts/test-eslint-rules.js +0 -146
- package/scripts/test-scripts/test-real-world.js +0 -44
- package/scripts/test-scripts/test-rules-on-real-projects.js +0 -86
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESLint to Heuristic Migration Converter
|
|
3
|
+
* Automated tool for migrating ESLint rules to heuristic engine
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const mapping = require('./mapping.json');
|
|
9
|
+
|
|
10
|
+
class MigrationConverter {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.mapping = mapping;
|
|
13
|
+
this.rulesDir = path.join(__dirname, '..');
|
|
14
|
+
this.eslintRulesDir = path.join(__dirname, '../../integrations/eslint/plugin/rules');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get migration info for a specific rule
|
|
19
|
+
* @param {string} ruleId - Rule ID (e.g., 'C006', 'S001')
|
|
20
|
+
* @returns {Object|null} Migration info
|
|
21
|
+
*/
|
|
22
|
+
getMigrationInfo(ruleId) {
|
|
23
|
+
return this.mapping.migrations.find(m =>
|
|
24
|
+
m.heuristic_rule.startsWith(ruleId)
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create heuristic rule directory structure
|
|
30
|
+
* @param {string} category - Rule category
|
|
31
|
+
* @param {string} ruleId - Rule ID
|
|
32
|
+
* @returns {string} Created directory path
|
|
33
|
+
*/
|
|
34
|
+
createRuleStructure(category, ruleId) {
|
|
35
|
+
const ruleDir = path.join(this.rulesDir, category, ruleId);
|
|
36
|
+
|
|
37
|
+
if (!fs.existsSync(ruleDir)) {
|
|
38
|
+
fs.mkdirSync(ruleDir, { recursive: true });
|
|
39
|
+
console.log(`✅ Created rule directory: ${ruleDir}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Create rule files if they don't exist
|
|
43
|
+
const files = ['analyzer.js', 'config.json', 'test.js', 'README.md'];
|
|
44
|
+
files.forEach(file => {
|
|
45
|
+
const filePath = path.join(ruleDir, file);
|
|
46
|
+
if (!fs.existsSync(filePath)) {
|
|
47
|
+
this.createRuleFile(filePath, file, ruleId, category);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return ruleDir;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create individual rule file with template content
|
|
56
|
+
* @param {string} filePath - File path to create
|
|
57
|
+
* @param {string} fileName - File name
|
|
58
|
+
* @param {string} ruleId - Rule ID
|
|
59
|
+
* @param {string} category - Rule category
|
|
60
|
+
*/
|
|
61
|
+
createRuleFile(filePath, fileName, ruleId, category) {
|
|
62
|
+
let content = '';
|
|
63
|
+
|
|
64
|
+
switch (fileName) {
|
|
65
|
+
case 'analyzer.js':
|
|
66
|
+
content = this.generateAnalyzerTemplate(ruleId, category);
|
|
67
|
+
break;
|
|
68
|
+
case 'config.json':
|
|
69
|
+
content = this.generateConfigTemplate(ruleId, category);
|
|
70
|
+
break;
|
|
71
|
+
case 'test.js':
|
|
72
|
+
content = this.generateTestTemplate(ruleId, category);
|
|
73
|
+
break;
|
|
74
|
+
case 'README.md':
|
|
75
|
+
content = this.generateReadmeTemplate(ruleId, category);
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
fs.writeFileSync(filePath, content);
|
|
80
|
+
console.log(`✅ Created: ${filePath}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Generate analyzer template
|
|
85
|
+
*/
|
|
86
|
+
generateAnalyzerTemplate(ruleId, category) {
|
|
87
|
+
return `/**
|
|
88
|
+
* ${ruleId} - Heuristic Rule Analyzer
|
|
89
|
+
* Category: ${category}
|
|
90
|
+
*
|
|
91
|
+
* TODO: Migrate logic from ESLint rule
|
|
92
|
+
* ESLint rule: integrations/eslint/plugin/rules/${category}/${ruleId.toLowerCase().replace('_', '-')}.js
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
const { PatternMatcher } = require('../common/pattern-matchers');
|
|
96
|
+
const { RuleHelper } = require('../common/rule-helpers');
|
|
97
|
+
|
|
98
|
+
class ${ruleId}Analyzer {
|
|
99
|
+
constructor(config = {}) {
|
|
100
|
+
this.config = config;
|
|
101
|
+
this.patternMatcher = new PatternMatcher();
|
|
102
|
+
this.helper = new RuleHelper();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Analyze code content for rule violations
|
|
107
|
+
* @param {string} content - File content
|
|
108
|
+
* @param {string} filePath - File path
|
|
109
|
+
* @param {Object} context - Analysis context
|
|
110
|
+
* @returns {Array} Array of violations
|
|
111
|
+
*/
|
|
112
|
+
analyze(content, filePath, context = {}) {
|
|
113
|
+
const violations = [];
|
|
114
|
+
|
|
115
|
+
// TODO: Implement heuristic analysis logic
|
|
116
|
+
// This should replicate the ESLint rule behavior using pattern matching
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
// Example pattern-based analysis
|
|
120
|
+
// const patterns = this.getViolationPatterns();
|
|
121
|
+
// const matches = this.patternMatcher.findMatches(content, patterns);
|
|
122
|
+
//
|
|
123
|
+
// matches.forEach(match => {
|
|
124
|
+
// violations.push(this.helper.createViolation({
|
|
125
|
+
// ruleId: '${ruleId}',
|
|
126
|
+
// message: 'Rule violation detected',
|
|
127
|
+
// line: match.line,
|
|
128
|
+
// column: match.column,
|
|
129
|
+
// severity: 'error'
|
|
130
|
+
// }));
|
|
131
|
+
// });
|
|
132
|
+
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.warn(\`Error analyzing \${filePath} with ${ruleId}:\`, error.message);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return violations;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get violation patterns for this rule
|
|
142
|
+
* @returns {Array} Array of patterns to match
|
|
143
|
+
*/
|
|
144
|
+
getViolationPatterns() {
|
|
145
|
+
// TODO: Define patterns based on ESLint rule logic
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
module.exports = ${ruleId}Analyzer;
|
|
151
|
+
`;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Generate config template
|
|
156
|
+
*/
|
|
157
|
+
generateConfigTemplate(ruleId, category) {
|
|
158
|
+
const migration = this.getMigrationInfo(ruleId);
|
|
159
|
+
return JSON.stringify({
|
|
160
|
+
"id": ruleId,
|
|
161
|
+
"name": migration ? migration.heuristic_rule : ruleId,
|
|
162
|
+
"category": category,
|
|
163
|
+
"description": `${ruleId} heuristic rule - migrated from ESLint`,
|
|
164
|
+
"severity": "error",
|
|
165
|
+
"enabled": true,
|
|
166
|
+
"migration": {
|
|
167
|
+
"from_eslint": migration ? migration.eslint_rule : "unknown",
|
|
168
|
+
"compatibility": migration ? migration.compatibility : "pending",
|
|
169
|
+
"status": migration ? migration.status : "pending"
|
|
170
|
+
},
|
|
171
|
+
"patterns": {
|
|
172
|
+
"include": ["**/*.js", "**/*.ts"],
|
|
173
|
+
"exclude": ["**/*.test.*", "**/*.spec.*"]
|
|
174
|
+
}
|
|
175
|
+
}, null, 2);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Generate test template
|
|
180
|
+
*/
|
|
181
|
+
generateTestTemplate(ruleId, category) {
|
|
182
|
+
return `/**
|
|
183
|
+
* ${ruleId} - Rule Tests
|
|
184
|
+
* Tests for heuristic rule analyzer
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
const ${ruleId}Analyzer = require('./analyzer');
|
|
188
|
+
|
|
189
|
+
describe('${ruleId} Heuristic Rule', () => {
|
|
190
|
+
let analyzer;
|
|
191
|
+
|
|
192
|
+
beforeEach(() => {
|
|
193
|
+
analyzer = new ${ruleId}Analyzer();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe('Valid Code', () => {
|
|
197
|
+
test('should not report violations for valid code', () => {
|
|
198
|
+
const code = \`
|
|
199
|
+
// TODO: Add valid code examples
|
|
200
|
+
\`;
|
|
201
|
+
|
|
202
|
+
const violations = analyzer.analyze(code, 'test.js');
|
|
203
|
+
expect(violations).toHaveLength(0);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe('Invalid Code', () => {
|
|
208
|
+
test('should report violations for invalid code', () => {
|
|
209
|
+
const code = \`
|
|
210
|
+
// TODO: Add invalid code examples
|
|
211
|
+
\`;
|
|
212
|
+
|
|
213
|
+
const violations = analyzer.analyze(code, 'test.js');
|
|
214
|
+
expect(violations.length).toBeGreaterThan(0);
|
|
215
|
+
expect(violations[0].ruleId).toBe('${ruleId}');
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('Edge Cases', () => {
|
|
220
|
+
test('should handle empty code', () => {
|
|
221
|
+
const violations = analyzer.analyze('', 'test.js');
|
|
222
|
+
expect(violations).toHaveLength(0);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test('should handle syntax errors gracefully', () => {
|
|
226
|
+
const code = 'invalid javascript syntax {{{';
|
|
227
|
+
const violations = analyzer.analyze(code, 'test.js');
|
|
228
|
+
expect(Array.isArray(violations)).toBe(true);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
`;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Generate README template
|
|
237
|
+
*/
|
|
238
|
+
generateReadmeTemplate(ruleId, category) {
|
|
239
|
+
const migration = this.getMigrationInfo(ruleId);
|
|
240
|
+
return `# ${ruleId} - ${category.toUpperCase()} Rule
|
|
241
|
+
|
|
242
|
+
## 📋 Overview
|
|
243
|
+
|
|
244
|
+
**Rule ID**: \`${ruleId}\`
|
|
245
|
+
**Category**: ${category}
|
|
246
|
+
**Severity**: Error
|
|
247
|
+
**Status**: ${migration ? migration.status : 'Pending Migration'}
|
|
248
|
+
|
|
249
|
+
## 🎯 Description
|
|
250
|
+
|
|
251
|
+
TODO: Add rule description after migration from ESLint.
|
|
252
|
+
|
|
253
|
+
${migration ? `
|
|
254
|
+
## 🔄 Migration Info
|
|
255
|
+
|
|
256
|
+
**ESLint Rule**: \`${migration.eslint_rule}\`
|
|
257
|
+
**Compatibility**: ${migration.compatibility}
|
|
258
|
+
**Priority**: ${migration.priority}
|
|
259
|
+
` : ''}
|
|
260
|
+
|
|
261
|
+
## ✅ Valid Code Examples
|
|
262
|
+
|
|
263
|
+
\`\`\`javascript
|
|
264
|
+
// TODO: Add valid code examples
|
|
265
|
+
\`\`\`
|
|
266
|
+
|
|
267
|
+
## ❌ Invalid Code Examples
|
|
268
|
+
|
|
269
|
+
\`\`\`javascript
|
|
270
|
+
// TODO: Add invalid code examples that should trigger violations
|
|
271
|
+
\`\`\`
|
|
272
|
+
|
|
273
|
+
## ⚙️ Configuration
|
|
274
|
+
|
|
275
|
+
\`\`\`json
|
|
276
|
+
{
|
|
277
|
+
"rules": {
|
|
278
|
+
"${ruleId}": "error"
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
\`\`\`
|
|
282
|
+
|
|
283
|
+
## 🧪 Testing
|
|
284
|
+
|
|
285
|
+
\`\`\`bash
|
|
286
|
+
# Run rule-specific tests
|
|
287
|
+
npm test -- ${ruleId.toLowerCase()}
|
|
288
|
+
|
|
289
|
+
# Test with SunLint CLI
|
|
290
|
+
sunlint --rules=${ruleId} --input=examples/
|
|
291
|
+
\`\`\`
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
**Migration Status**: ${migration ? migration.status : 'Pending'}
|
|
296
|
+
**Last Updated**: ${new Date().toISOString().split('T')[0]}
|
|
297
|
+
`;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Migrate a specific rule
|
|
302
|
+
* @param {string} ruleId - Rule ID to migrate
|
|
303
|
+
* @returns {boolean} Success status
|
|
304
|
+
*/
|
|
305
|
+
async migrateRule(ruleId) {
|
|
306
|
+
const migration = this.getMigrationInfo(ruleId);
|
|
307
|
+
|
|
308
|
+
if (!migration) {
|
|
309
|
+
console.error(`❌ No migration mapping found for rule: ${ruleId}`);
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (migration.status === 'completed') {
|
|
314
|
+
console.log(`✅ Rule ${ruleId} already migrated`);
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
console.log(`🔄 Migrating rule: ${ruleId}`);
|
|
319
|
+
console.log(` ESLint: ${migration.eslint_rule}`);
|
|
320
|
+
console.log(` Category: ${migration.category}`);
|
|
321
|
+
console.log(` Compatibility: ${migration.compatibility}`);
|
|
322
|
+
|
|
323
|
+
try {
|
|
324
|
+
// Create heuristic rule structure
|
|
325
|
+
this.createRuleStructure(migration.category, migration.heuristic_rule);
|
|
326
|
+
|
|
327
|
+
console.log(`✅ Migration template created for ${ruleId}`);
|
|
328
|
+
console.log(`📝 Next steps:`);
|
|
329
|
+
console.log(` 1. Implement analyzer logic in rules/${migration.category}/${migration.heuristic_rule}/analyzer.js`);
|
|
330
|
+
console.log(` 2. Add test cases in rules/${migration.category}/${migration.heuristic_rule}/test.js`);
|
|
331
|
+
console.log(` 3. Update rule documentation`);
|
|
332
|
+
console.log(` 4. Test against ESLint rule behavior`);
|
|
333
|
+
|
|
334
|
+
return true;
|
|
335
|
+
|
|
336
|
+
} catch (error) {
|
|
337
|
+
console.error(`❌ Migration failed for ${ruleId}:`, error.message);
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Show migration statistics
|
|
344
|
+
*/
|
|
345
|
+
showStats() {
|
|
346
|
+
const stats = this.mapping.migration_stats;
|
|
347
|
+
console.log('📊 Migration Statistics:');
|
|
348
|
+
console.log(` Total Rules: ${stats.total_rules}`);
|
|
349
|
+
console.log(` Completed: ${stats.completed}`);
|
|
350
|
+
console.log(` Pending: ${stats.pending}`);
|
|
351
|
+
console.log('');
|
|
352
|
+
console.log('📋 By Category:');
|
|
353
|
+
Object.entries(stats.by_category).forEach(([category, data]) => {
|
|
354
|
+
console.log(` ${category}: ${data.completed}/${data.total} completed`);
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// CLI usage
|
|
360
|
+
if (require.main === module) {
|
|
361
|
+
const converter = new MigrationConverter();
|
|
362
|
+
const args = process.argv.slice(2);
|
|
363
|
+
|
|
364
|
+
if (args.includes('--stats')) {
|
|
365
|
+
converter.showStats();
|
|
366
|
+
} else if (args.includes('--rule')) {
|
|
367
|
+
const ruleIndex = args.indexOf('--rule');
|
|
368
|
+
const ruleId = args[ruleIndex + 1];
|
|
369
|
+
if (ruleId) {
|
|
370
|
+
converter.migrateRule(ruleId);
|
|
371
|
+
} else {
|
|
372
|
+
console.error('❌ Please specify a rule ID with --rule');
|
|
373
|
+
}
|
|
374
|
+
} else {
|
|
375
|
+
console.log('🚀 SunLint Migration Converter');
|
|
376
|
+
console.log('');
|
|
377
|
+
console.log('Usage:');
|
|
378
|
+
console.log(' node converter.js --stats # Show migration statistics');
|
|
379
|
+
console.log(' node converter.js --rule C006 # Migrate specific rule');
|
|
380
|
+
console.log('');
|
|
381
|
+
converter.showStats();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
module.exports = MigrationConverter;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_description": "ESLint to Heuristic Migration Mapping - Maps ESLint plugin rules to heuristic engine equivalents",
|
|
3
|
+
"migrations": [
|
|
4
|
+
{
|
|
5
|
+
"eslint_rule": "c006-function-name-verb-noun",
|
|
6
|
+
"heuristic_rule": "C006_function_naming",
|
|
7
|
+
"category": "coding",
|
|
8
|
+
"compatibility": "full",
|
|
9
|
+
"priority": "high",
|
|
10
|
+
"status": "completed",
|
|
11
|
+
"notes": "Direct mapping - heuristic version already exists"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"eslint_rule": "c019-log-level-usage",
|
|
15
|
+
"heuristic_rule": "C019_log_level_usage",
|
|
16
|
+
"category": "coding",
|
|
17
|
+
"compatibility": "full",
|
|
18
|
+
"priority": "high",
|
|
19
|
+
"status": "completed",
|
|
20
|
+
"notes": "Direct mapping - heuristic version already exists"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"eslint_rule": "c029-catch-block-logging",
|
|
24
|
+
"heuristic_rule": "C029_catch_block_logging",
|
|
25
|
+
"category": "coding",
|
|
26
|
+
"compatibility": "full",
|
|
27
|
+
"priority": "high",
|
|
28
|
+
"status": "completed",
|
|
29
|
+
"notes": "Direct mapping - heuristic version already exists"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"eslint_rule": "c031-validation-separation",
|
|
33
|
+
"heuristic_rule": "C031_validation_separation",
|
|
34
|
+
"category": "coding",
|
|
35
|
+
"compatibility": "full",
|
|
36
|
+
"priority": "high",
|
|
37
|
+
"status": "completed",
|
|
38
|
+
"notes": "Direct mapping - heuristic version already exists"
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
{
|
|
42
|
+
"eslint_rule": "c002-no-duplicate-code",
|
|
43
|
+
"heuristic_rule": "C002_no_duplicate_code",
|
|
44
|
+
"category": "coding",
|
|
45
|
+
"compatibility": "partial",
|
|
46
|
+
"priority": "medium",
|
|
47
|
+
"status": "pending",
|
|
48
|
+
"notes": "Requires AST pattern matching for code duplication"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"eslint_rule": "c003-no-vague-abbreviations",
|
|
52
|
+
"heuristic_rule": "C003_no_vague_abbreviations",
|
|
53
|
+
"category": "coding",
|
|
54
|
+
"compatibility": "full",
|
|
55
|
+
"priority": "low",
|
|
56
|
+
"status": "pending",
|
|
57
|
+
"notes": "String pattern matching for variable names"
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
{
|
|
61
|
+
"eslint_rule": "s001-fail-securely",
|
|
62
|
+
"heuristic_rule": "S001_fail_securely",
|
|
63
|
+
"category": "security",
|
|
64
|
+
"compatibility": "partial",
|
|
65
|
+
"priority": "critical",
|
|
66
|
+
"status": "pending",
|
|
67
|
+
"notes": "Complex logic analysis required for security patterns"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"eslint_rule": "s003-no-unvalidated-redirect",
|
|
71
|
+
"heuristic_rule": "S003_no_unvalidated_redirect",
|
|
72
|
+
"category": "security",
|
|
73
|
+
"compatibility": "full",
|
|
74
|
+
"priority": "critical",
|
|
75
|
+
"status": "pending",
|
|
76
|
+
"notes": "Pattern matching for redirect vulnerabilities"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"eslint_rule": "s012-hardcode-secret",
|
|
80
|
+
"heuristic_rule": "S012_hardcode_secret",
|
|
81
|
+
"category": "security",
|
|
82
|
+
"compatibility": "full",
|
|
83
|
+
"priority": "critical",
|
|
84
|
+
"status": "pending",
|
|
85
|
+
"notes": "String pattern matching for hardcoded secrets"
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
{
|
|
89
|
+
"eslint_rule": "t002-interface-prefix-i",
|
|
90
|
+
"heuristic_rule": "T002_interface_prefix_i",
|
|
91
|
+
"category": "typescript",
|
|
92
|
+
"compatibility": "full",
|
|
93
|
+
"priority": "medium",
|
|
94
|
+
"status": "pending",
|
|
95
|
+
"notes": "TypeScript interface naming conventions"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"eslint_rule": "t003-ts-ignore-reason",
|
|
99
|
+
"heuristic_rule": "T003_ts_ignore_reason",
|
|
100
|
+
"category": "typescript",
|
|
101
|
+
"compatibility": "full",
|
|
102
|
+
"priority": "medium",
|
|
103
|
+
"status": "pending",
|
|
104
|
+
"notes": "TypeScript comment analysis for @ts-ignore"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
|
|
108
|
+
"migration_stats": {
|
|
109
|
+
"total_rules": 81,
|
|
110
|
+
"completed": 4,
|
|
111
|
+
"pending": 77,
|
|
112
|
+
"by_category": {
|
|
113
|
+
"coding": {
|
|
114
|
+
"total": 22,
|
|
115
|
+
"completed": 4,
|
|
116
|
+
"pending": 18
|
|
117
|
+
},
|
|
118
|
+
"security": {
|
|
119
|
+
"total": 49,
|
|
120
|
+
"completed": 0,
|
|
121
|
+
"pending": 49
|
|
122
|
+
},
|
|
123
|
+
"typescript": {
|
|
124
|
+
"total": 10,
|
|
125
|
+
"completed": 0,
|
|
126
|
+
"pending": 10
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"by_priority": {
|
|
130
|
+
"critical": 3,
|
|
131
|
+
"high": 4,
|
|
132
|
+
"medium": 12,
|
|
133
|
+
"low": 62
|
|
134
|
+
},
|
|
135
|
+
"by_compatibility": {
|
|
136
|
+
"full": 65,
|
|
137
|
+
"partial": 16,
|
|
138
|
+
"complex": 0
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
"migration_phases": {
|
|
143
|
+
"phase_1": {
|
|
144
|
+
"name": "Critical Security Rules",
|
|
145
|
+
"rules": ["S001", "S003", "S012"],
|
|
146
|
+
"timeline": "Immediate post-ESLint deprecation"
|
|
147
|
+
},
|
|
148
|
+
"phase_2": {
|
|
149
|
+
"name": "High Priority Coding Rules",
|
|
150
|
+
"rules": ["C002", "C010", "C014", "C018"],
|
|
151
|
+
"timeline": "Within 1 month"
|
|
152
|
+
},
|
|
153
|
+
"phase_3": {
|
|
154
|
+
"name": "TypeScript Rules",
|
|
155
|
+
"rules": ["T002", "T003", "T004", "T007"],
|
|
156
|
+
"timeline": "Within 2 months"
|
|
157
|
+
},
|
|
158
|
+
"phase_4": {
|
|
159
|
+
"name": "Remaining Rules",
|
|
160
|
+
"rules": "All remaining 70 rules",
|
|
161
|
+
"timeline": "Within 6 months"
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Keywords for parsing markdown files
|
|
2
|
+
const KEYWORDS = {
|
|
3
|
+
OBJECTIVE: ["**Mục tiêu**:", "**Objective**:"],
|
|
4
|
+
DETAILS: ["**Chi tiết**:", "**Details**:"],
|
|
5
|
+
APPLIES_TO: ["**Áp dụng**:", "**Applies to**:"],
|
|
6
|
+
TOOLS: ["**Tool**:", "**Tools**:", "**Công cụ**:"],
|
|
7
|
+
PRINCIPLES: ["**Principles**:", "**Nguyên tắc**:"],
|
|
8
|
+
VERSION: ["**Version**:", "**Phiên bản**:"],
|
|
9
|
+
STATUS: ["**Status**:", "**Trạng thái**:"],
|
|
10
|
+
SEVERITY: ["**Severity**:", "**Mức độ**:"],
|
|
11
|
+
GOOD_EXAMPLE: ["**Ví dụ đúng**:", "**Good example**:", "**Correct example**:"],
|
|
12
|
+
BAD_EXAMPLE: ["**Ví dụ sai**:", "**Bad example**:", "**Incorrect example**:"],
|
|
13
|
+
CONFIG: [
|
|
14
|
+
"**Config**:",
|
|
15
|
+
"**Configuration**:",
|
|
16
|
+
"**Cấu hình**:",
|
|
17
|
+
"**ESLint Config**:",
|
|
18
|
+
"**TSConfig**:",
|
|
19
|
+
"**SonarQube Config**:",
|
|
20
|
+
"**Detekt Config**:",
|
|
21
|
+
"**PMD Config**:",
|
|
22
|
+
"**Prettier Config**:",
|
|
23
|
+
"**Ktlint Config**:",
|
|
24
|
+
"**Pre-commit Hook**:",
|
|
25
|
+
"**CI Check Script**:",
|
|
26
|
+
],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = {
|
|
30
|
+
KEYWORDS,
|
|
31
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// File configuration mapping for different rule files
|
|
2
|
+
const FILE_CONFIG = {
|
|
3
|
+
"common.md": {
|
|
4
|
+
category: "Common",
|
|
5
|
+
language: "All",
|
|
6
|
+
framework: "All",
|
|
7
|
+
},
|
|
8
|
+
"java.md": {
|
|
9
|
+
category: "Backend",
|
|
10
|
+
language: "Java",
|
|
11
|
+
framework: "Spring Boot",
|
|
12
|
+
},
|
|
13
|
+
"kotlin.md": {
|
|
14
|
+
category: "Backend",
|
|
15
|
+
language: "Kotlin",
|
|
16
|
+
framework: "Spring Boot",
|
|
17
|
+
},
|
|
18
|
+
"php.md": {
|
|
19
|
+
category: "Backend",
|
|
20
|
+
language: "PHP",
|
|
21
|
+
framework: "Laravel",
|
|
22
|
+
},
|
|
23
|
+
"python.md": {
|
|
24
|
+
category: "Backend",
|
|
25
|
+
language: "Python",
|
|
26
|
+
framework: "Django",
|
|
27
|
+
},
|
|
28
|
+
"ruby.md": {
|
|
29
|
+
category: "Backend",
|
|
30
|
+
language: "Ruby",
|
|
31
|
+
framework: "Rails",
|
|
32
|
+
},
|
|
33
|
+
"typescript.md": {
|
|
34
|
+
category: "Frontend",
|
|
35
|
+
language: "TypeScript",
|
|
36
|
+
framework: "React",
|
|
37
|
+
},
|
|
38
|
+
"security.md": {
|
|
39
|
+
category: "Security",
|
|
40
|
+
language: "All",
|
|
41
|
+
framework: "All",
|
|
42
|
+
},
|
|
43
|
+
"typescript-be.md": {
|
|
44
|
+
category: "Backend",
|
|
45
|
+
language: "TypeScript",
|
|
46
|
+
framework: "NestJS",
|
|
47
|
+
},
|
|
48
|
+
"kotlin-mobile.md": {
|
|
49
|
+
category: "Mobile",
|
|
50
|
+
language: "Kotlin",
|
|
51
|
+
framework: "Android SDK",
|
|
52
|
+
},
|
|
53
|
+
"java-mobile.md": {
|
|
54
|
+
category: "Mobile",
|
|
55
|
+
language: "Java",
|
|
56
|
+
framework: "Android SDK",
|
|
57
|
+
},
|
|
58
|
+
"swift.md": {
|
|
59
|
+
category: "Mobile",
|
|
60
|
+
language: "Swift",
|
|
61
|
+
framework: "UIKit",
|
|
62
|
+
},
|
|
63
|
+
"dart.md": {
|
|
64
|
+
category: "Mobile",
|
|
65
|
+
language: "Dart",
|
|
66
|
+
framework: "Flutter",
|
|
67
|
+
},
|
|
68
|
+
"reactjs.md": {
|
|
69
|
+
category: "Frontend",
|
|
70
|
+
language: "JavaScript",
|
|
71
|
+
framework: "React",
|
|
72
|
+
},
|
|
73
|
+
"javascript.md": {
|
|
74
|
+
category: "Backend",
|
|
75
|
+
language: "JavaScript",
|
|
76
|
+
framework: "Node.js",
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = { FILE_CONFIG }
|