@sun-asterisk/sunlint 1.2.2 → 1.3.1
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 +107 -1
- package/CONTRIBUTING.md +1654 -66
- package/README.md +19 -6
- package/config/ci-cd.json +54 -0
- package/config/development.json +56 -0
- 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/large-project.json +143 -0
- package/config/presets/all.json +0 -1
- package/config/release.json +70 -0
- package/config/rule-analysis-strategies.js +23 -4
- package/config/rules/S027-categories.json +122 -0
- package/config/rules/enhanced-rules-registry.json +2564 -0
- package/config/rules/rules-registry-generated.json +785 -837
- package/config/rules/rules-registry.json +13 -1
- 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 +53 -32
- package/core/cli-program.js +11 -3
- package/core/config-manager.js +111 -0
- package/core/config-merger.js +88 -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/enhanced-rules-registry.js +3 -3
- 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 +658 -0
- package/core/semantic-rule-base.js +433 -0
- package/core/unified-rule-registry.js +484 -0
- package/docs/COMMAND-EXAMPLES.md +134 -0
- package/docs/CONSTANTS-ARCHITECTURE.md +288 -0
- package/docs/LARGE-PROJECT-GUIDE.md +324 -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 +569 -78
- package/integrations/eslint/plugin/index.js +26 -28
- package/origin-rules/common-en.md +8 -8
- package/package.json +10 -6
- package/rules/common/C003_no_vague_abbreviations/analyzer.js +1 -1
- package/rules/common/C017_constructor_logic/analyzer.js +254 -17
- package/rules/common/C017_constructor_logic/semantic-analyzer.js +340 -0
- package/rules/common/C029_catch_block_logging/analyzer.js +17 -5
- package/rules/common/C033_separate_service_repository/README.md +78 -0
- package/rules/common/C033_separate_service_repository/analyzer.js +160 -0
- package/rules/common/C033_separate_service_repository/config.json +50 -0
- package/rules/common/C033_separate_service_repository/regex-based-analyzer.js +585 -0
- package/rules/common/C033_separate_service_repository/symbol-based-analyzer.js +368 -0
- package/rules/common/C035_error_logging_context/STRATEGY.md +99 -0
- package/rules/common/C035_error_logging_context/analyzer.js +230 -0
- package/rules/common/C035_error_logging_context/config.json +54 -0
- package/rules/common/C035_error_logging_context/regex-based-analyzer.js +299 -0
- package/rules/common/C035_error_logging_context/symbol-based-analyzer.js +454 -0
- package/rules/common/C040_centralized_validation/analyzer.js +165 -0
- package/rules/common/C040_centralized_validation/config.json +46 -0
- package/rules/common/C040_centralized_validation/regex-based-analyzer.js +243 -0
- package/rules/common/C040_centralized_validation/symbol-based-analyzer.js +416 -0
- 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/common/{C076_single_test_behavior → C072_single_test_behavior}/analyzer.js +6 -6
- package/rules/common/C076_explicit_function_types/README.md +30 -0
- package/rules/common/C076_explicit_function_types/analyzer.js +172 -0
- package/rules/common/C076_explicit_function_types/config.json +15 -0
- package/rules/common/C076_explicit_function_types/semantic-analyzer.js +341 -0
- package/rules/index.js +8 -0
- package/rules/parser/rule-parser.js +13 -2
- package/rules/security/S005_no_origin_auth/README.md +226 -0
- package/rules/security/S005_no_origin_auth/analyzer.js +184 -0
- package/rules/security/S005_no_origin_auth/ast-analyzer.js +406 -0
- package/rules/security/S005_no_origin_auth/config.json +85 -0
- package/rules/security/S006_no_plaintext_recovery_codes/README.md +139 -0
- package/rules/security/S006_no_plaintext_recovery_codes/analyzer.js +306 -0
- package/rules/security/S006_no_plaintext_recovery_codes/config.json +48 -0
- package/rules/security/S007_no_plaintext_otp/README.md +198 -0
- package/rules/security/S007_no_plaintext_otp/analyzer.js +406 -0
- package/rules/security/S007_no_plaintext_otp/config.json +79 -0
- package/rules/security/S007_no_plaintext_otp/semantic-analyzer.js +609 -0
- package/rules/security/S007_no_plaintext_otp/semantic-config.json +195 -0
- package/rules/security/S007_no_plaintext_otp/semantic-wrapper.js +280 -0
- package/rules/security/S027_no_hardcoded_secrets/analyzer.js +180 -366
- package/rules/security/S027_no_hardcoded_secrets/categories.json +153 -0
- package/rules/security/S027_no_hardcoded_secrets/categorized-analyzer.js +250 -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/prepare-release.sh +1 -1
- 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/docs/ESLINT-INTEGRATION-STRATEGY.md +0 -392
- package/docs/FUTURE_PACKAGES.md +0 -83
- package/docs/HEURISTIC_VS_AI.md +0 -113
- package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +0 -112
- package/docs/PRODUCTION_SIZE_IMPACT.md +0 -183
- package/docs/RELEASE_GUIDE.md +0 -230
- package/docs/STANDARDIZED-CATEGORY-FILTERING.md +0 -156
- package/engines/tree-sitter-parser.js +0 -0
- package/engines/universal-ast-engine.js +0 -0
- package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +0 -254
- 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
package/engines/eslint-engine.js
CHANGED
|
@@ -9,6 +9,7 @@ const AnalysisEngineInterface = require('../core/interfaces/analysis-engine.inte
|
|
|
9
9
|
const dependencyChecker = require('../core/dependency-checker');
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const path = require('path');
|
|
12
|
+
const { getInstance } = require('../core/unified-rule-registry');
|
|
12
13
|
|
|
13
14
|
class ESLintEngine extends AnalysisEngineInterface {
|
|
14
15
|
constructor() {
|
|
@@ -18,12 +19,16 @@ class ESLintEngine extends AnalysisEngineInterface {
|
|
|
18
19
|
this.configFiles = new Map();
|
|
19
20
|
this.ruleMapping = new Map();
|
|
20
21
|
|
|
22
|
+
// Unified rule registry
|
|
23
|
+
this.unifiedRegistry = getInstance();
|
|
24
|
+
|
|
21
25
|
// Load rule mapping immediately (synchronous)
|
|
22
26
|
try {
|
|
23
27
|
this.loadRuleMappingSync();
|
|
24
28
|
} catch (error) {
|
|
25
29
|
console.error('🚨 Constructor failed to load mapping:', error.message);
|
|
26
|
-
|
|
30
|
+
// Defer async mapping loading to when needed
|
|
31
|
+
this.mappingLoaded = false;
|
|
27
32
|
}
|
|
28
33
|
}
|
|
29
34
|
|
|
@@ -41,15 +46,27 @@ class ESLintEngine extends AnalysisEngineInterface {
|
|
|
41
46
|
for (const [sunlintRule, eslintRules] of Object.entries(mapping)) {
|
|
42
47
|
this.ruleMapping.set(sunlintRule, eslintRules);
|
|
43
48
|
}
|
|
49
|
+
this.mappingLoaded = true;
|
|
44
50
|
} else {
|
|
45
|
-
//
|
|
46
|
-
this.
|
|
47
|
-
console.warn('⚠️
|
|
51
|
+
// Mark as not loaded, will load from registry later
|
|
52
|
+
this.mappingLoaded = false;
|
|
53
|
+
console.warn('⚠️ Legacy ESLint mapping file not found, will load from unified registry');
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
} catch (error) {
|
|
51
57
|
console.warn('⚠️ [ESLintEngine] Failed to load ESLint rule mapping:', error.message);
|
|
52
|
-
this.
|
|
58
|
+
this.mappingLoaded = false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Ensure rule mapping is loaded (async)
|
|
64
|
+
*/
|
|
65
|
+
async ensureMappingLoaded() {
|
|
66
|
+
if (!this.mappingLoaded) {
|
|
67
|
+
console.log('📋 [ESLintEngine] Loading rule mapping from unified registry...');
|
|
68
|
+
await this.createDefaultRuleMapping();
|
|
69
|
+
this.mappingLoaded = true;
|
|
53
70
|
}
|
|
54
71
|
}
|
|
55
72
|
|
|
@@ -301,12 +318,14 @@ class ESLintEngine extends AnalysisEngineInterface {
|
|
|
301
318
|
const rules = this.extractRulesFromConfig(eslintConfig);
|
|
302
319
|
const needsReact = this.needsReactPlugins(rules);
|
|
303
320
|
const needsTypeScript = this.needsTypeScriptPlugins(rules);
|
|
321
|
+
const needsImport = this.needsImportPlugin(rules);
|
|
304
322
|
|
|
305
323
|
// Check plugin availability in target project
|
|
306
324
|
const hasReact = needsReact && this.isReactPluginAvailable(projectPath);
|
|
307
325
|
const hasReactHooks = needsReact && this.isReactHooksPluginAvailable(projectPath);
|
|
308
326
|
const hasTypeScript = needsTypeScript && this.isTypeScriptPluginAvailable(projectPath);
|
|
309
327
|
const hasTypeScriptParser = this.isTypeScriptParserAvailable(projectPath);
|
|
328
|
+
const hasImport = needsImport && this.isImportPluginAvailable(projectPath);
|
|
310
329
|
|
|
311
330
|
let pluginImports = '';
|
|
312
331
|
let pluginDefs = '{ "custom": customPlugin';
|
|
@@ -326,11 +345,16 @@ class ESLintEngine extends AnalysisEngineInterface {
|
|
|
326
345
|
pluginDefs += ', "@typescript-eslint": typescriptPlugin';
|
|
327
346
|
}
|
|
328
347
|
|
|
348
|
+
if (hasImport) {
|
|
349
|
+
pluginImports += `\nimport importPlugin from 'eslint-plugin-import';`;
|
|
350
|
+
pluginDefs += ', "import": importPlugin';
|
|
351
|
+
}
|
|
352
|
+
|
|
329
353
|
pluginDefs += ' }';
|
|
330
354
|
|
|
331
355
|
// Filter rules to only include those for available plugins
|
|
332
356
|
const filteredRules = {};
|
|
333
|
-
const skippedRules = { react: [], reactHooks: [], typescript: [] };
|
|
357
|
+
const skippedRules = { react: [], reactHooks: [], typescript: [], import: [] };
|
|
334
358
|
|
|
335
359
|
for (const [ruleKey, ruleConfig] of Object.entries(eslintConfig.rules || {})) {
|
|
336
360
|
if (ruleKey.startsWith('react/') && !hasReact) {
|
|
@@ -345,6 +369,10 @@ class ESLintEngine extends AnalysisEngineInterface {
|
|
|
345
369
|
skippedRules.typescript.push(ruleKey);
|
|
346
370
|
continue;
|
|
347
371
|
}
|
|
372
|
+
if (ruleKey.startsWith('import/') && !hasImport) {
|
|
373
|
+
skippedRules.import.push(ruleKey);
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
348
376
|
filteredRules[ruleKey] = ruleConfig;
|
|
349
377
|
}
|
|
350
378
|
|
|
@@ -358,6 +386,9 @@ class ESLintEngine extends AnalysisEngineInterface {
|
|
|
358
386
|
if (skippedRules.typescript.length > 0) {
|
|
359
387
|
console.warn(`⚠️ [ESLintEngine] Skipped ${skippedRules.typescript.length} TypeScript ESLint rules - plugin not available`);
|
|
360
388
|
}
|
|
389
|
+
if (skippedRules.import.length > 0) {
|
|
390
|
+
console.warn(`⚠️ [ESLintEngine] Skipped ${skippedRules.import.length} Import rules - plugin not available`);
|
|
391
|
+
}
|
|
361
392
|
|
|
362
393
|
// Use only SunLint analysis config (filteredRules) - do not merge with project rules
|
|
363
394
|
const mergedConfig = {
|
|
@@ -568,13 +599,18 @@ export default [
|
|
|
568
599
|
}
|
|
569
600
|
|
|
570
601
|
/**
|
|
571
|
-
* Create default rule mapping
|
|
602
|
+
* Create default rule mapping (DEPRECATED - use unified registry)
|
|
572
603
|
* Following Rule C006: Verb-noun naming
|
|
573
604
|
*/
|
|
574
|
-
createDefaultRuleMapping() {
|
|
575
|
-
console.log(
|
|
605
|
+
async createDefaultRuleMapping() {
|
|
606
|
+
console.log(`⚠️ [ESLintEngine] createDefaultRuleMapping() is DEPRECATED - using unified registry instead`);
|
|
607
|
+
|
|
608
|
+
// Use unified registry instead of hardcoded mappings
|
|
609
|
+
if (this.unifiedRegistry) {
|
|
610
|
+
return await this.loadMappingsFromRegistry();
|
|
611
|
+
}
|
|
576
612
|
|
|
577
|
-
//
|
|
613
|
+
// Legacy fallback mapping (will be removed)
|
|
578
614
|
const defaultMappings = {
|
|
579
615
|
'C005': ['max-statements-per-line', 'complexity'],
|
|
580
616
|
'C006': ['func-names', 'func-name-matching'],
|
|
@@ -599,6 +635,32 @@ export default [
|
|
|
599
635
|
console.warn('⚠️ Using default ESLint rule mapping');
|
|
600
636
|
}
|
|
601
637
|
|
|
638
|
+
/**
|
|
639
|
+
* Load rule mappings from unified registry
|
|
640
|
+
*/
|
|
641
|
+
async loadMappingsFromRegistry() {
|
|
642
|
+
if (!this.unifiedRegistry.initialized) {
|
|
643
|
+
await this.unifiedRegistry.initialize();
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const mappings = {};
|
|
647
|
+
for (const [ruleId, ruleDefinition] of this.unifiedRegistry.rules.entries()) {
|
|
648
|
+
if (ruleDefinition.engineMappings && ruleDefinition.engineMappings.eslint) {
|
|
649
|
+
mappings[ruleId] = ruleDefinition.engineMappings.eslint;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
console.log(`📋 [ESLintEngine] Loaded ${Object.keys(mappings).length} mappings from unified registry`);
|
|
654
|
+
|
|
655
|
+
// Clear existing mapping and set new ones
|
|
656
|
+
this.ruleMapping.clear();
|
|
657
|
+
for (const [sunlintRule, eslintRules] of Object.entries(mappings)) {
|
|
658
|
+
this.ruleMapping.set(sunlintRule, eslintRules);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
return mappings;
|
|
662
|
+
}
|
|
663
|
+
|
|
602
664
|
/**
|
|
603
665
|
* Detect project type from package.json and file patterns
|
|
604
666
|
* @param {string} projectPath - Project path
|
|
@@ -908,6 +970,20 @@ export default [
|
|
|
908
970
|
}
|
|
909
971
|
}
|
|
910
972
|
|
|
973
|
+
/**
|
|
974
|
+
* Check if Import plugin is available in project
|
|
975
|
+
* @param {string} projectPath - Project path to check
|
|
976
|
+
* @returns {boolean} True if Import plugin is available
|
|
977
|
+
*/
|
|
978
|
+
isImportPluginAvailable(projectPath) {
|
|
979
|
+
try {
|
|
980
|
+
require.resolve('eslint-plugin-import', { paths: [projectPath] });
|
|
981
|
+
return true;
|
|
982
|
+
} catch (error) {
|
|
983
|
+
return false;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
911
987
|
/**
|
|
912
988
|
* Load React ESLint plugin
|
|
913
989
|
* Following Rule C006: Verb-noun naming
|
|
@@ -1026,6 +1102,9 @@ export default [
|
|
|
1026
1102
|
throw new Error('ESLint engine not initialized');
|
|
1027
1103
|
}
|
|
1028
1104
|
|
|
1105
|
+
// Ensure rule mapping is loaded from unified registry
|
|
1106
|
+
await this.ensureMappingLoaded();
|
|
1107
|
+
|
|
1029
1108
|
const results = {
|
|
1030
1109
|
results: [],
|
|
1031
1110
|
filesAnalyzed: 0,
|
|
@@ -1296,6 +1375,18 @@ export default [
|
|
|
1296
1375
|
});
|
|
1297
1376
|
}
|
|
1298
1377
|
|
|
1378
|
+
/**
|
|
1379
|
+
* Check if rules need Import plugin
|
|
1380
|
+
*/
|
|
1381
|
+
needsImportPlugin(rules) {
|
|
1382
|
+
// Check if any rules use import/ prefix or specific rules that need import plugin
|
|
1383
|
+
return rules.some(ruleId => {
|
|
1384
|
+
const id = typeof ruleId === 'string' ? ruleId : ruleId.id || ruleId.name;
|
|
1385
|
+
return id && (id.includes('import/') ||
|
|
1386
|
+
['C038', 'C040'].includes(id)); // Rules that map to import plugin
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1299
1390
|
/**
|
|
1300
1391
|
* Build dynamic plugins based on rules being analyzed
|
|
1301
1392
|
* @param {Array} rules - Rules to analyze
|
|
@@ -1370,8 +1461,41 @@ export default [
|
|
|
1370
1461
|
continue;
|
|
1371
1462
|
}
|
|
1372
1463
|
|
|
1373
|
-
// For Common rules (C series),
|
|
1464
|
+
// For Common rules (C series), check mapping file first
|
|
1374
1465
|
if (rule.id.startsWith('C')) {
|
|
1466
|
+
const eslintRules = this.ruleMapping.get(rule.id);
|
|
1467
|
+
|
|
1468
|
+
if (eslintRules && Array.isArray(eslintRules)) {
|
|
1469
|
+
// Check if mapping contains custom rules
|
|
1470
|
+
const customRules = eslintRules.filter(r => r.startsWith('custom/'));
|
|
1471
|
+
const builtinRules = eslintRules.filter(r => !r.startsWith('custom/'));
|
|
1472
|
+
|
|
1473
|
+
// If mapping has custom rules, use them
|
|
1474
|
+
if (customRules.length > 0) {
|
|
1475
|
+
for (const customRule of customRules) {
|
|
1476
|
+
const ruleConfig = this.mapSeverity(rule.severity || 'warning');
|
|
1477
|
+
|
|
1478
|
+
// Add rule configuration for specific rules
|
|
1479
|
+
if (rule.id === 'C010') {
|
|
1480
|
+
config.rules[customRule] = [ruleConfig, { maxDepth: 3 }];
|
|
1481
|
+
} else {
|
|
1482
|
+
config.rules[customRule] = ruleConfig;
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
continue;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
// If mapping has only builtin rules, use them
|
|
1489
|
+
if (builtinRules.length > 0) {
|
|
1490
|
+
for (const eslintRule of builtinRules) {
|
|
1491
|
+
const severity = this.mapSeverity(rule.severity || 'warning');
|
|
1492
|
+
config.rules[eslintRule] = severity;
|
|
1493
|
+
}
|
|
1494
|
+
continue;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
// If no mapping found, fallback to auto-generated custom rule name
|
|
1375
1499
|
const customRuleName = `custom/${rule.id.toLowerCase()}`;
|
|
1376
1500
|
const ruleConfig = this.mapSeverity(rule.severity || 'warning');
|
|
1377
1501
|
|
|
@@ -1384,29 +1508,57 @@ export default [
|
|
|
1384
1508
|
continue;
|
|
1385
1509
|
}
|
|
1386
1510
|
|
|
1387
|
-
// For TypeScript rules (T series),
|
|
1511
|
+
// For TypeScript rules (T series), check mapping file first
|
|
1388
1512
|
if (rule.id.startsWith('T')) {
|
|
1513
|
+
const eslintRules = this.ruleMapping.get(rule.id);
|
|
1514
|
+
|
|
1515
|
+
if (eslintRules && Array.isArray(eslintRules)) {
|
|
1516
|
+
// Check if mapping contains custom rules
|
|
1517
|
+
const customRules = eslintRules.filter(r => r.startsWith('custom/'));
|
|
1518
|
+
const builtinRules = eslintRules.filter(r => !r.startsWith('custom/'));
|
|
1519
|
+
|
|
1520
|
+
// If mapping has custom rules, use them
|
|
1521
|
+
if (customRules.length > 0) {
|
|
1522
|
+
for (const customRule of customRules) {
|
|
1523
|
+
const ruleConfig = this.mapSeverity(rule.severity || 'warning');
|
|
1524
|
+
config.rules[customRule] = ruleConfig;
|
|
1525
|
+
}
|
|
1526
|
+
continue;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
// If mapping has only builtin rules, use them
|
|
1530
|
+
if (builtinRules.length > 0) {
|
|
1531
|
+
for (const eslintRule of builtinRules) {
|
|
1532
|
+
const severity = this.mapSeverity(rule.severity || 'warning');
|
|
1533
|
+
config.rules[eslintRule] = severity;
|
|
1534
|
+
}
|
|
1535
|
+
continue;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
// If no mapping found, fallback to auto-generated custom rule name
|
|
1389
1540
|
const customRuleName = `custom/${rule.id.toLowerCase()}`;
|
|
1390
1541
|
const ruleConfig = this.mapSeverity(rule.severity || 'warning');
|
|
1391
1542
|
config.rules[customRuleName] = ruleConfig;
|
|
1392
1543
|
continue;
|
|
1393
1544
|
}
|
|
1394
1545
|
|
|
1395
|
-
// For other rules, check mapping file
|
|
1546
|
+
// For other rules, check mapping file first
|
|
1396
1547
|
const eslintRules = this.ruleMapping.get(rule.id);
|
|
1397
1548
|
|
|
1398
1549
|
if (eslintRules && Array.isArray(eslintRules)) {
|
|
1550
|
+
// Use mapping file (for builtin ESLint rules)
|
|
1399
1551
|
for (const eslintRule of eslintRules) {
|
|
1400
|
-
// Set rule severity based on SunLint rule
|
|
1401
1552
|
const severity = this.mapSeverity(rule.severity || 'warning');
|
|
1402
1553
|
config.rules[eslintRule] = severity;
|
|
1403
1554
|
}
|
|
1404
|
-
|
|
1405
|
-
// Fallback - try as custom rule
|
|
1406
|
-
const customRuleName = `custom/${rule.id.toLowerCase()}`;
|
|
1407
|
-
const ruleConfig = this.mapSeverity(rule.severity || 'warning');
|
|
1408
|
-
config.rules[customRuleName] = ruleConfig;
|
|
1555
|
+
continue;
|
|
1409
1556
|
}
|
|
1557
|
+
|
|
1558
|
+
// Fallback - try as custom rule for any remaining rules
|
|
1559
|
+
const customRuleName = `custom/${rule.id.toLowerCase()}`;
|
|
1560
|
+
const ruleConfig = this.mapSeverity(rule.severity || 'warning');
|
|
1561
|
+
config.rules[customRuleName] = ruleConfig;
|
|
1410
1562
|
}
|
|
1411
1563
|
|
|
1412
1564
|
return config;
|