@sun-asterisk/sunlint 1.1.7 → 1.2.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/.sunlint.json +1 -1
- package/CHANGELOG.md +83 -0
- package/README.md +66 -4
- package/config/presets/all.json +125 -0
- package/config/presets/beginner.json +16 -8
- package/config/presets/ci.json +12 -4
- package/config/presets/maintainability.json +38 -0
- package/config/presets/performance.json +32 -0
- package/config/presets/quality.json +103 -0
- package/config/presets/recommended.json +36 -12
- package/config/presets/security.json +88 -0
- package/config/presets/strict.json +15 -5
- package/config/rules/rules-registry-generated.json +6312 -0
- package/config/rules-summary.json +1941 -0
- package/core/adapters/sunlint-rule-adapter.js +452 -0
- package/core/analysis-orchestrator.js +4 -4
- package/core/config-manager.js +28 -5
- package/core/rule-selection-service.js +52 -55
- package/docs/CONFIGURATION.md +111 -3
- package/docs/LANGUAGE-SPECIFIC-RULES.md +308 -0
- package/docs/README.md +3 -0
- package/docs/STANDARDIZED-CATEGORY-FILTERING.md +156 -0
- package/engines/eslint-engine.js +92 -2
- package/engines/heuristic-engine.js +8 -31
- package/origin-rules/common-en.md +1320 -0
- package/origin-rules/dart-en.md +289 -0
- package/origin-rules/java-en.md +60 -0
- package/origin-rules/kotlin-mobile-en.md +453 -0
- package/origin-rules/reactjs-en.md +102 -0
- package/origin-rules/security-en.md +1055 -0
- package/origin-rules/swift-en.md +449 -0
- package/origin-rules/typescript-en.md +136 -0
- package/package.json +6 -5
- package/scripts/copy-rules.js +86 -0
- package/rules/README.md +0 -252
- package/rules/common/C002_no_duplicate_code/analyzer.js +0 -65
- package/rules/common/C002_no_duplicate_code/config.json +0 -23
- package/rules/common/C003_no_vague_abbreviations/analyzer.js +0 -418
- package/rules/common/C003_no_vague_abbreviations/config.json +0 -35
- package/rules/common/C006_function_naming/analyzer.js +0 -349
- package/rules/common/C006_function_naming/config.json +0 -86
- package/rules/common/C010_limit_block_nesting/analyzer.js +0 -389
- package/rules/common/C013_no_dead_code/analyzer.js +0 -206
- package/rules/common/C014_dependency_injection/analyzer.js +0 -338
- package/rules/common/C017_constructor_logic/analyzer.js +0 -314
- package/rules/common/C019_log_level_usage/analyzer.js +0 -362
- package/rules/common/C019_log_level_usage/config.json +0 -121
- package/rules/common/C029_catch_block_logging/analyzer.js +0 -373
- package/rules/common/C029_catch_block_logging/config.json +0 -59
- package/rules/common/C031_validation_separation/analyzer.js +0 -186
- package/rules/common/C041_no_sensitive_hardcode/analyzer.js +0 -292
- package/rules/common/C042_boolean_name_prefix/analyzer.js +0 -300
- package/rules/common/C043_no_console_or_print/analyzer.js +0 -304
- package/rules/common/C047_no_duplicate_retry_logic/analyzer.js +0 -351
- package/rules/common/C075_explicit_return_types/analyzer.js +0 -103
- package/rules/common/C076_single_test_behavior/analyzer.js +0 -121
- package/rules/docs/C002_no_duplicate_code.md +0 -57
- package/rules/docs/C031_validation_separation.md +0 -72
- package/rules/index.js +0 -149
- package/rules/migration/converter.js +0 -385
- package/rules/migration/mapping.json +0 -164
- package/rules/security/S026_json_schema_validation/analyzer.js +0 -251
- package/rules/security/S026_json_schema_validation/config.json +0 -27
- package/rules/security/S027_no_hardcoded_secrets/analyzer.js +0 -263
- package/rules/security/S027_no_hardcoded_secrets/config.json +0 -29
- package/rules/security/S029_csrf_protection/analyzer.js +0 -264
- package/rules/tests/C002_no_duplicate_code.test.js +0 -50
- package/rules/universal/C010/generic.js +0 -0
- package/rules/universal/C010/tree-sitter-analyzer.js +0 -0
- package/rules/utils/ast-utils.js +0 -191
- package/rules/utils/base-analyzer.js +0 -98
- package/rules/utils/pattern-matchers.js +0 -239
- package/rules/utils/rule-helpers.js +0 -264
- package/rules/utils/severity-constants.js +0 -93
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Rule Selection Service
|
|
3
3
|
* Following Rule C005: Single responsibility - only handle rule selection
|
|
4
|
+
* REFACTORED: Now uses SunlintRuleAdapter instead of direct registry access
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
const chalk = require('chalk');
|
|
7
8
|
const RuleMappingService = require('./rule-mapping-service');
|
|
9
|
+
const SunlintRuleAdapter = require('./adapters/sunlint-rule-adapter');
|
|
8
10
|
|
|
9
11
|
class RuleSelectionService {
|
|
10
12
|
constructor() {
|
|
11
|
-
this.
|
|
13
|
+
this.ruleAdapter = SunlintRuleAdapter.getInstance();
|
|
12
14
|
this.ruleMappingService = new RuleMappingService();
|
|
15
|
+
this.initialized = false;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
|
-
async
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
this.
|
|
19
|
-
} catch (error) {
|
|
20
|
-
console.log(chalk.yellow('⚠️ Rules registry not found, using minimal rule set'));
|
|
21
|
-
this.rulesRegistry = this.getMinimalRuleSet();
|
|
18
|
+
async initialize() {
|
|
19
|
+
if (!this.initialized) {
|
|
20
|
+
await this.ruleAdapter.initialize();
|
|
21
|
+
this.initialized = true;
|
|
22
22
|
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async selectRules(config, options) {
|
|
26
|
+
// Ensure adapter is initialized
|
|
27
|
+
await this.initialize();
|
|
23
28
|
|
|
24
29
|
const allRules = config.rules || {};
|
|
25
30
|
let selectedRules = [];
|
|
@@ -30,27 +35,40 @@ class RuleSelectionService {
|
|
|
30
35
|
} else if (options.rules) {
|
|
31
36
|
selectedRules = options.rules.split(',').map(r => r.trim());
|
|
32
37
|
} else if (options.all) {
|
|
33
|
-
// For --all, use all supported rules from
|
|
34
|
-
const
|
|
38
|
+
// For --all, use all supported rules from adapter
|
|
39
|
+
const adapterRules = this.ruleAdapter.getAllRuleIds();
|
|
35
40
|
const eslintSupportedRules = this.ruleMappingService.getSupportedSunLintRules();
|
|
36
41
|
|
|
37
42
|
// Combine and deduplicate
|
|
38
|
-
selectedRules = [...new Set([...
|
|
43
|
+
selectedRules = [...new Set([...adapterRules, ...eslintSupportedRules])];
|
|
39
44
|
|
|
40
45
|
if (options.verbose) {
|
|
41
|
-
console.log(chalk.blue(`📋 Found ${selectedRules.length} total rules (${
|
|
46
|
+
console.log(chalk.blue(`📋 Found ${selectedRules.length} total rules (${adapterRules.length} adapter + ${eslintSupportedRules.length} ESLint)`));
|
|
42
47
|
}
|
|
43
48
|
} else if (options.quality) {
|
|
44
|
-
// Handle --quality shortcut
|
|
45
|
-
const categoryRules = this.
|
|
46
|
-
selectedRules = categoryRules;
|
|
49
|
+
// Handle --quality shortcut (standardized approach)
|
|
50
|
+
const categoryRules = this.ruleAdapter.getStandardCategoryRules('quality');
|
|
51
|
+
selectedRules = categoryRules.map(rule => rule.id);
|
|
52
|
+
|
|
53
|
+
if (options.verbose) {
|
|
54
|
+
console.log(chalk.blue(`📋 Selected ${selectedRules.length} quality rules from core files`));
|
|
55
|
+
}
|
|
47
56
|
} else if (options.security) {
|
|
48
|
-
// Handle --security shortcut
|
|
49
|
-
const categoryRules = this.
|
|
50
|
-
selectedRules = categoryRules;
|
|
57
|
+
// Handle --security shortcut (standardized approach)
|
|
58
|
+
const categoryRules = this.ruleAdapter.getStandardCategoryRules('security');
|
|
59
|
+
selectedRules = categoryRules.map(rule => rule.id);
|
|
60
|
+
|
|
61
|
+
if (options.verbose) {
|
|
62
|
+
console.log(chalk.blue(`📋 Selected ${selectedRules.length} security rules from core files`));
|
|
63
|
+
}
|
|
51
64
|
} else if (options.category) {
|
|
52
|
-
|
|
53
|
-
|
|
65
|
+
// Handle --category shortcut (standardized approach)
|
|
66
|
+
const categoryRules = this.ruleAdapter.getStandardCategoryRules(options.category);
|
|
67
|
+
selectedRules = categoryRules.map(rule => rule.id);
|
|
68
|
+
|
|
69
|
+
if (options.verbose) {
|
|
70
|
+
console.log(chalk.blue(`📋 Selected ${selectedRules.length} ${options.category} rules from core files`));
|
|
71
|
+
}
|
|
54
72
|
} else {
|
|
55
73
|
// Default: use config rules or minimal set
|
|
56
74
|
selectedRules = Object.keys(allRules).filter(ruleId =>
|
|
@@ -63,12 +81,15 @@ class RuleSelectionService {
|
|
|
63
81
|
}
|
|
64
82
|
|
|
65
83
|
// Convert to rule objects
|
|
66
|
-
return selectedRules.map(ruleId =>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
84
|
+
return selectedRules.map(ruleId => {
|
|
85
|
+
const adapterRule = this.ruleAdapter.getRuleById(ruleId);
|
|
86
|
+
return {
|
|
87
|
+
id: ruleId,
|
|
88
|
+
name: this.getRuleName(ruleId),
|
|
89
|
+
severity: 'warning',
|
|
90
|
+
...(adapterRule || {})
|
|
91
|
+
};
|
|
92
|
+
}).filter(rule => rule.id);
|
|
72
93
|
}
|
|
73
94
|
|
|
74
95
|
getMinimalRuleSet() {
|
|
@@ -91,38 +112,14 @@ class RuleSelectionService {
|
|
|
91
112
|
}
|
|
92
113
|
|
|
93
114
|
getRulesByCategory(category) {
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
return this.rulesRegistry.categories[category].rules;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Fallback to hardcoded mapping
|
|
100
|
-
const categoryMap = {
|
|
101
|
-
'quality': [
|
|
102
|
-
'C002', 'C003', 'C006', 'C010', 'C013', 'C014', 'C017', 'C018', 'C019',
|
|
103
|
-
'C023', 'C027', 'C029', 'C030', 'C031', 'C034', 'C035', 'C041', 'C042',
|
|
104
|
-
'C043', 'C047', 'C048', 'C076', 'T002', 'T003', 'T004', 'T007', 'T011',
|
|
105
|
-
'T019', 'T025', 'T026'
|
|
106
|
-
],
|
|
107
|
-
'security': ['S001', 'S002', 'S003', 'S005', 'S006', 'S007', 'S008', 'S009', 'S010', 'S011', 'S012', 'S013', 'S014', 'S015', 'S016', 'S017', 'S018', 'S019', 'S020', 'S022', 'S023', 'S025', 'S026', 'S027', 'S029', 'S030', 'S033', 'S034', 'S035', 'S036', 'S037', 'S038', 'S039', 'S041', 'S042', 'S043', 'S044', 'S045', 'S046', 'S047', 'S048', 'S050', 'S052', 'S054', 'S055', 'S057', 'S058'],
|
|
108
|
-
'naming': ['C006'],
|
|
109
|
-
'logging': ['C019', 'S057'],
|
|
110
|
-
'validation': ['C031', 'S018', 'S025', 'S026']
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
return categoryMap[category] || [];
|
|
115
|
+
// Use adapter to get rules by category
|
|
116
|
+
return this.ruleAdapter.getRulesByCategory(category).map(rule => rule.id);
|
|
114
117
|
}
|
|
115
118
|
|
|
116
119
|
getRuleName(ruleId) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
'C002': 'No Duplicate Code',
|
|
121
|
-
'C003': 'No Vague Abbreviations',
|
|
122
|
-
'C029': 'Catch Block Logging'
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
return ruleNames[ruleId] || `Rule ${ruleId}`;
|
|
120
|
+
// Use adapter to get rule name
|
|
121
|
+
const rule = this.ruleAdapter.getRuleById(ruleId);
|
|
122
|
+
return rule ? rule.name : `Rule ${ruleId}`;
|
|
126
123
|
}
|
|
127
124
|
}
|
|
128
125
|
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
This document provides a comprehensive guide to all SunLint configuration options.
|
|
4
4
|
|
|
5
|
+
## 🏗️ Architecture Overview
|
|
6
|
+
|
|
7
|
+
SunLint uses a **unified adapter pattern** for rule management, ensuring consistency between CLI and VSCode extension:
|
|
8
|
+
|
|
9
|
+
### Rule Access Architecture
|
|
10
|
+
```
|
|
11
|
+
CLI Tools → SunlintRuleAdapter → Rule Sources (Registry + Origin Rules)
|
|
12
|
+
↓ ↓
|
|
13
|
+
VSCode Extension → RuleReaderService → Rule Sources (Registry + Origin Rules)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Key Benefits
|
|
17
|
+
- **Unified Rule Model**: Both CLI and extension use the same rule access pattern
|
|
18
|
+
- **No Direct Parser Access**: All rule queries go through adapter layer
|
|
19
|
+
- **AI Context Consistency**: OpenAI integration gets correct context from origin-rules
|
|
20
|
+
- **Extensible**: Easy to add new rule sources or engines
|
|
21
|
+
|
|
22
|
+
### Rule Sources Priority
|
|
23
|
+
1. **Primary**: `config/rules/rules-registry-generated.json` (auto-generated from origin-rules)
|
|
24
|
+
2. **Fallback**: `origin-rules/*.md` files (direct markdown parsing)
|
|
25
|
+
3. **Cache**: Memory cache for performance optimization
|
|
26
|
+
|
|
5
27
|
## 📋 Quick Start
|
|
6
28
|
|
|
7
29
|
Create `.sunlint.json` in your project root:
|
|
@@ -248,9 +270,38 @@ Below is the full configuration schema with all available options and their desc
|
|
|
248
270
|
- `@sun/sunlint/ci` - Optimized for CI/CD environments
|
|
249
271
|
|
|
250
272
|
### Engine Selection
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
273
|
+
|
|
274
|
+
SunLint supports multiple analysis engines with automatic rule compatibility detection:
|
|
275
|
+
|
|
276
|
+
- `heuristic` - SunLint's native pattern-based analysis engine (default)
|
|
277
|
+
- **Coverage**: 244/256 rules (95.3%)
|
|
278
|
+
- **Performance**: Fast, low memory usage
|
|
279
|
+
- **Languages**: All supported languages
|
|
280
|
+
- **Best for**: General analysis, CI/CD pipelines
|
|
281
|
+
|
|
282
|
+
- `eslint` - ESLint-based analysis with automatic rule mapping
|
|
283
|
+
- **Coverage**: 17/256 rules (6.6%)
|
|
284
|
+
- **Performance**: Moderate, requires ESLint dependencies
|
|
285
|
+
- **Languages**: JavaScript, TypeScript, JSX, TSX
|
|
286
|
+
- **Best for**: Projects already using ESLint
|
|
287
|
+
|
|
288
|
+
- `ai` - AI-powered analysis using OpenAI/LLMs
|
|
289
|
+
- **Coverage**: 256/256 rules (100%)
|
|
290
|
+
- **Performance**: Slower, requires API access
|
|
291
|
+
- **Languages**: All supported languages
|
|
292
|
+
- **Best for**: Complex context analysis, legacy code review
|
|
293
|
+
|
|
294
|
+
### Engine Architecture
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
Analysis Orchestrator
|
|
298
|
+
├── SunlintRuleAdapter (unified rule access)
|
|
299
|
+
├── Heuristic Engine (pattern matching)
|
|
300
|
+
├── ESLint Engine (integration layer)
|
|
301
|
+
└── AI Engine (LLM integration)
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Auto-Engine Selection**: SunLint automatically selects the best engine for each rule based on compatibility and performance.
|
|
254
305
|
|
|
255
306
|
## 🎯 Common Configuration Examples
|
|
256
307
|
|
|
@@ -412,3 +463,60 @@ Engine preferences:
|
|
|
412
463
|
- **R*** rules: ESLint → Heuristic → AI
|
|
413
464
|
- **C*** rules: Heuristic → ESLint → AI
|
|
414
465
|
- **T*** rules: ESLint → Heuristic → AI
|
|
466
|
+
|
|
467
|
+
## 🚀 Performance & Architecture Benefits
|
|
468
|
+
|
|
469
|
+
### Adapter Pattern Benefits
|
|
470
|
+
- **Unified Rule Access**: Both CLI and VSCode extension use the same adapter layer
|
|
471
|
+
- **No Model Duplication**: Single rule model across all tools
|
|
472
|
+
- **Memory Efficiency**: Singleton pattern prevents duplicate instances
|
|
473
|
+
- **Fast Queries**: 0.07ms average per rule query with caching
|
|
474
|
+
|
|
475
|
+
### Rule Loading Performance
|
|
476
|
+
- **Registry Loading**: 256 rules in ~10ms
|
|
477
|
+
- **Memory Cache**: Rules cached after first load
|
|
478
|
+
- **Fallback Support**: Automatic fallback to origin-rules if registry unavailable
|
|
479
|
+
|
|
480
|
+
### Engine Performance Comparison
|
|
481
|
+
| Engine | Rules Coverage | Speed | Memory | Best Use Case |
|
|
482
|
+
|--------|---------------|-------|---------|--------------|
|
|
483
|
+
| Heuristic | 244/256 (95.3%) | Fast | Low | CI/CD, general analysis |
|
|
484
|
+
| ESLint | 17/256 (6.6%) | Moderate | Medium | Existing ESLint projects |
|
|
485
|
+
| AI | 256/256 (100%) | Slow | High | Complex analysis, legacy code |
|
|
486
|
+
|
|
487
|
+
### Architecture Validation
|
|
488
|
+
```bash
|
|
489
|
+
# Test adapter performance and coverage
|
|
490
|
+
npx sunlint --test-adapter
|
|
491
|
+
|
|
492
|
+
# Show engine compatibility for specific rules
|
|
493
|
+
npx sunlint --show-engines --rules=C010,R001,S005
|
|
494
|
+
|
|
495
|
+
# Verbose mode shows adapter and engine selection
|
|
496
|
+
npx sunlint --verbose --rules=C010,C020 --input=src
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
## 🔧 Development & Debugging
|
|
500
|
+
|
|
501
|
+
### Internal Architecture Access
|
|
502
|
+
For development and debugging, SunLint exposes internal adapter methods:
|
|
503
|
+
|
|
504
|
+
```javascript
|
|
505
|
+
// Access the rule adapter (for extensions or custom tools)
|
|
506
|
+
const SunlintRuleAdapter = require('@sun/sunlint/core/adapters/sunlint-rule-adapter');
|
|
507
|
+
|
|
508
|
+
const adapter = SunlintRuleAdapter.getInstance();
|
|
509
|
+
await adapter.initialize();
|
|
510
|
+
|
|
511
|
+
// Get all rules with metadata
|
|
512
|
+
const allRules = adapter.getAllRules();
|
|
513
|
+
|
|
514
|
+
// Generate AI context for specific rules
|
|
515
|
+
const aiContext = adapter.generateAIContext(['C010', 'C020']);
|
|
516
|
+
|
|
517
|
+
// Check engine compatibility
|
|
518
|
+
const heuristicRules = adapter.getRulesByEngine('heuristic');
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### VSCode Extension Integration
|
|
522
|
+
The SunLint VSCode extension uses the same adapter pattern via `RuleReaderService`, ensuring complete consistency between CLI and editor experience.
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# Language-Specific Rules Configuration Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
This guide explains how to configure language-specific rules in SunLint projects. Language-specific rules are **opt-in** and must be explicitly enabled via project configuration.
|
|
5
|
+
|
|
6
|
+
## Core vs Language-Specific Rules
|
|
7
|
+
|
|
8
|
+
### Core Rules (Always Available)
|
|
9
|
+
- **Files**: `common-en.md`, `security-en.md`
|
|
10
|
+
- **Count**: 135 rules
|
|
11
|
+
- **Usage**: Included in category commands (`--security`, `--quality`)
|
|
12
|
+
- **Scope**: Universal rules applicable to all languages
|
|
13
|
+
|
|
14
|
+
### Language-Specific Rules (Opt-In)
|
|
15
|
+
- **Files**: `typescript-en.md`, `reactjs-en.md`, `java-en.md`, etc.
|
|
16
|
+
- **Count**: 121 rules
|
|
17
|
+
- **Usage**: Must be enabled via project config
|
|
18
|
+
- **Scope**: Rules specific to particular languages/frameworks
|
|
19
|
+
|
|
20
|
+
## Configuration Methods
|
|
21
|
+
|
|
22
|
+
### 1. Project Configuration (.sunlint.json)
|
|
23
|
+
|
|
24
|
+
Create or edit `.sunlint.json` in your project root:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"rules": [
|
|
29
|
+
"TS001",
|
|
30
|
+
"TS002",
|
|
31
|
+
"REACT001"
|
|
32
|
+
],
|
|
33
|
+
"presets": ["typescript", "reactjs"],
|
|
34
|
+
"categories": ["security", "quality"]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 2. Package.json Configuration
|
|
39
|
+
|
|
40
|
+
Add sunlint config to your `package.json`:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"sunlint": {
|
|
45
|
+
"rules": ["TS001", "TS002"],
|
|
46
|
+
"presets": ["typescript"],
|
|
47
|
+
"categories": ["security"]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 3. CLI Rule Selection
|
|
53
|
+
|
|
54
|
+
Use CLI flags for one-time rule selection:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Specific language rules
|
|
58
|
+
sunlint --rules="TS001,TS002,REACT001"
|
|
59
|
+
|
|
60
|
+
# Mix core categories with specific rules
|
|
61
|
+
sunlint --security --rules="TS001,TS002"
|
|
62
|
+
|
|
63
|
+
# Use presets
|
|
64
|
+
sunlint --preset=typescript
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Available Language-Specific Rules
|
|
68
|
+
|
|
69
|
+
### TypeScript Rules (typescript-en.md)
|
|
70
|
+
```bash
|
|
71
|
+
# Example TypeScript-specific rules
|
|
72
|
+
TS001 - TypeScript strict mode enforcement
|
|
73
|
+
TS002 - Type assertion guidelines
|
|
74
|
+
TS003 - Interface vs type usage
|
|
75
|
+
# ... more TypeScript rules
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### React Rules (reactjs-en.md)
|
|
79
|
+
```bash
|
|
80
|
+
# Example React-specific rules
|
|
81
|
+
REACT001 - Component prop validation
|
|
82
|
+
REACT002 - State mutation prevention
|
|
83
|
+
REACT003 - Effect dependency handling
|
|
84
|
+
# ... more React rules
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Java Rules (java-en.md)
|
|
88
|
+
```bash
|
|
89
|
+
# Example Java-specific rules
|
|
90
|
+
JAVA001 - Exception handling patterns
|
|
91
|
+
JAVA002 - Thread safety guidelines
|
|
92
|
+
JAVA003 - Memory management best practices
|
|
93
|
+
# ... more Java rules
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Configuration Examples
|
|
97
|
+
|
|
98
|
+
### TypeScript Project
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"presets": ["typescript"],
|
|
102
|
+
"categories": ["security", "quality"],
|
|
103
|
+
"rules": [
|
|
104
|
+
"TS001",
|
|
105
|
+
"TS005",
|
|
106
|
+
"TS010"
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### React + TypeScript Project
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"presets": ["typescript", "reactjs"],
|
|
115
|
+
"categories": ["security"],
|
|
116
|
+
"rules": [
|
|
117
|
+
"TS001",
|
|
118
|
+
"REACT001",
|
|
119
|
+
"REACT005"
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Multi-Language Project
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"presets": ["typescript", "java"],
|
|
128
|
+
"categories": ["security", "quality"],
|
|
129
|
+
"rules": [
|
|
130
|
+
"TS001",
|
|
131
|
+
"JAVA001",
|
|
132
|
+
"JAVA010"
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Rule Priority System
|
|
138
|
+
|
|
139
|
+
SunLint follows this priority order:
|
|
140
|
+
|
|
141
|
+
1. **CLI `--rule`** (highest priority)
|
|
142
|
+
2. **CLI `--rules`**
|
|
143
|
+
3. **CLI `--category`** (core rules only)
|
|
144
|
+
4. **Project config file** (lowest priority)
|
|
145
|
+
|
|
146
|
+
### Example Priority Resolution
|
|
147
|
+
```bash
|
|
148
|
+
# Command: sunlint --security --rules="TS001,TS002" --rule="CUSTOM001"
|
|
149
|
+
# Result: Only CUSTOM001 is used (--rule overrides everything)
|
|
150
|
+
|
|
151
|
+
# Command: sunlint --security --rules="TS001,TS002"
|
|
152
|
+
# Result: TS001, TS002 are used (--rules overrides --security)
|
|
153
|
+
|
|
154
|
+
# Command: sunlint --security
|
|
155
|
+
# Result: 60 core security rules are used
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Preset Configurations
|
|
159
|
+
|
|
160
|
+
Presets provide curated rule collections for specific languages:
|
|
161
|
+
|
|
162
|
+
### Creating Custom Presets
|
|
163
|
+
```json
|
|
164
|
+
// config/presets/my-typescript-preset.json
|
|
165
|
+
{
|
|
166
|
+
"rules": [
|
|
167
|
+
"TS001", "TS002", "TS005",
|
|
168
|
+
"S001", "S010", "S020",
|
|
169
|
+
"C001", "C005", "C010"
|
|
170
|
+
],
|
|
171
|
+
"description": "Custom TypeScript preset with security focus"
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Using Presets
|
|
176
|
+
```bash
|
|
177
|
+
# CLI usage
|
|
178
|
+
sunlint --preset=my-typescript-preset
|
|
179
|
+
|
|
180
|
+
# Project config usage
|
|
181
|
+
{
|
|
182
|
+
"presets": ["my-typescript-preset"]
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Best Practices
|
|
187
|
+
|
|
188
|
+
### 1. Start with Core Categories
|
|
189
|
+
Begin with core categories, then add language-specific rules:
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"categories": ["security", "quality"],
|
|
193
|
+
"rules": ["TS001", "TS002"]
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 2. Use Presets for Common Configurations
|
|
198
|
+
Create and reuse presets for consistent team configurations:
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"presets": ["team-typescript", "security-strict"]
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### 3. Gradual Rule Adoption
|
|
206
|
+
Add language-specific rules incrementally:
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"categories": ["security"],
|
|
210
|
+
"rules": [
|
|
211
|
+
// Week 1: Start with essential rules
|
|
212
|
+
"TS001",
|
|
213
|
+
|
|
214
|
+
// Week 2: Add more specific rules
|
|
215
|
+
"TS002", "TS005",
|
|
216
|
+
|
|
217
|
+
// Week 3: Add advanced rules
|
|
218
|
+
"TS010", "TS015"
|
|
219
|
+
]
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### 4. Document Team Standards
|
|
224
|
+
Create team-specific documentation:
|
|
225
|
+
```json
|
|
226
|
+
{
|
|
227
|
+
"presets": ["team-standard"],
|
|
228
|
+
"description": "Our team's agreed-upon rule set",
|
|
229
|
+
"rules": ["TS001", "TS002", "REACT001"]
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Troubleshooting
|
|
234
|
+
|
|
235
|
+
### Common Issues
|
|
236
|
+
|
|
237
|
+
#### 1. Language Rules Not Applied
|
|
238
|
+
**Problem**: Language-specific rules don't appear in results
|
|
239
|
+
**Solution**: Check that rules are in project config, not just CLI categories
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# This only uses core rules
|
|
243
|
+
sunlint --security
|
|
244
|
+
|
|
245
|
+
# This includes language-specific rules
|
|
246
|
+
sunlint --security --rules="TS001,TS002"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### 2. Rule Conflicts
|
|
250
|
+
**Problem**: Different tools report different rule counts
|
|
251
|
+
**Solution**: Verify same configuration is used everywhere
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
// Ensure consistent config across tools
|
|
255
|
+
{
|
|
256
|
+
"presets": ["typescript"],
|
|
257
|
+
"categories": ["security"]
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
#### 3. Missing Rules
|
|
262
|
+
**Problem**: Expected rules don't appear
|
|
263
|
+
**Solution**: Check rule priority and configuration merge
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# Debug with verbose output
|
|
267
|
+
sunlint --verbose --security
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Migration from Legacy Configuration
|
|
271
|
+
|
|
272
|
+
### Old Approach (Deprecated)
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"includeLanguageRules": true,
|
|
276
|
+
"language": "typescript"
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### New Approach (Recommended)
|
|
281
|
+
```json
|
|
282
|
+
{
|
|
283
|
+
"presets": ["typescript"],
|
|
284
|
+
"categories": ["security", "quality"]
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Validation
|
|
289
|
+
|
|
290
|
+
Test your configuration:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# Verify rule selection
|
|
294
|
+
sunlint --input=src --verbose
|
|
295
|
+
|
|
296
|
+
# Test specific configuration
|
|
297
|
+
sunlint --config=.sunlint.json --verbose
|
|
298
|
+
|
|
299
|
+
# Validate rule counts
|
|
300
|
+
node test-category-filtering.js
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Related Documentation
|
|
304
|
+
|
|
305
|
+
- [Standardized Category Filtering](./STANDARDIZED-CATEGORY-FILTERING.md)
|
|
306
|
+
- [Configuration Guide](./CONFIGURATION.md)
|
|
307
|
+
- [Preset System](./PRESETS.md)
|
|
308
|
+
- [CLI Commands](./COMMAND-EXAMPLES.md)
|
package/docs/README.md
CHANGED
|
@@ -28,5 +28,8 @@
|
|
|
28
28
|
|
|
29
29
|
## Configuration
|
|
30
30
|
|
|
31
|
+
- **[Configuration Guide](CONFIGURATION.md)** - Complete configuration reference
|
|
32
|
+
- **[Standardized Category Filtering](STANDARDIZED-CATEGORY-FILTERING.md)** - Core vs language-specific rules
|
|
33
|
+
- **[Language-Specific Rules](LANGUAGE-SPECIFIC-RULES.md)** - How to configure language-specific rules
|
|
31
34
|
- **[.sunlint-simple.json](../.sunlint-simple.json)** - Simple configuration example
|
|
32
35
|
- **[sunlint.config.json](../sunlint.config.json)** - Full configuration with all features
|