@sun-asterisk/sunlint 1.3.0 โ†’ 1.3.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.
Files changed (124) hide show
  1. package/CHANGELOG.md +115 -1
  2. package/CONTRIBUTING.md +249 -605
  3. package/README.md +3 -4
  4. package/config/ci-cd.json +54 -0
  5. package/config/development.json +56 -0
  6. package/config/large-project.json +143 -0
  7. package/config/presets/all.json +0 -1
  8. package/config/release.json +70 -0
  9. package/config/rule-analysis-strategies.js +38 -3
  10. package/config/rules/enhanced-rules-registry.json +474 -1179
  11. package/config/rules/rules-registry-generated.json +3 -3
  12. package/core/cli-action-handler.js +24 -30
  13. package/core/cli-program.js +11 -3
  14. package/core/config-merger.js +29 -2
  15. package/core/enhanced-rules-registry.js +3 -2
  16. package/core/semantic-engine.js +129 -19
  17. package/core/semantic-rule-base.js +4 -2
  18. package/core/unified-rule-registry.js +1 -1
  19. package/docs/COMMAND-EXAMPLES.md +134 -0
  20. package/docs/LARGE-PROJECT-GUIDE.md +324 -0
  21. package/engines/heuristic-engine.js +135 -16
  22. package/integrations/eslint/plugin/index.js +0 -2
  23. package/integrations/eslint/plugin/rules/common/c003-no-vague-abbreviations.js +59 -1
  24. package/integrations/eslint/plugin/rules/common/c006-function-name-verb-noun.js +26 -1
  25. package/integrations/eslint/plugin/rules/common/c030-use-custom-error-classes.js +54 -19
  26. package/origin-rules/common-en.md +19 -15
  27. package/package.json +1 -1
  28. package/rules/common/C002_no_duplicate_code/analyzer.js +334 -36
  29. package/rules/common/C003_no_vague_abbreviations/analyzer.js +220 -35
  30. package/rules/common/C006_function_naming/analyzer.js +29 -3
  31. package/rules/common/C010_limit_block_nesting/analyzer.js +181 -337
  32. package/rules/common/C010_limit_block_nesting/config.json +64 -0
  33. package/rules/common/C010_limit_block_nesting/regex-based-analyzer.js +379 -0
  34. package/rules/common/C010_limit_block_nesting/symbol-based-analyzer.js +231 -0
  35. package/rules/common/C013_no_dead_code/analyzer.js +75 -177
  36. package/rules/common/C013_no_dead_code/config.json +61 -0
  37. package/rules/common/C013_no_dead_code/regex-based-analyzer.js +345 -0
  38. package/rules/common/C013_no_dead_code/symbol-based-analyzer.js +640 -0
  39. package/rules/common/C014_dependency_injection/analyzer.js +48 -313
  40. package/rules/common/C014_dependency_injection/config.json +26 -0
  41. package/rules/common/C014_dependency_injection/symbol-based-analyzer.js +751 -0
  42. package/rules/common/C017_constructor_logic/analyzer.js +254 -17
  43. package/rules/common/C017_constructor_logic/semantic-analyzer.js +340 -0
  44. package/rules/common/C018_no_throw_generic_error/analyzer.js +232 -0
  45. package/rules/common/C018_no_throw_generic_error/config.json +50 -0
  46. package/rules/common/C018_no_throw_generic_error/regex-based-analyzer.js +387 -0
  47. package/rules/common/C018_no_throw_generic_error/symbol-based-analyzer.js +314 -0
  48. package/rules/common/C019_log_level_usage/analyzer.js +110 -317
  49. package/rules/common/C019_log_level_usage/pattern-analyzer.js +88 -0
  50. package/rules/common/C019_log_level_usage/system-log-analyzer.js +1267 -0
  51. package/rules/common/C023_no_duplicate_variable/analyzer.js +180 -0
  52. package/rules/common/C023_no_duplicate_variable/config.json +50 -0
  53. package/rules/common/C023_no_duplicate_variable/symbol-based-analyzer.js +158 -0
  54. package/rules/common/C024_no_scatter_hardcoded_constants/analyzer.js +180 -0
  55. package/rules/common/C024_no_scatter_hardcoded_constants/config.json +50 -0
  56. package/rules/common/C024_no_scatter_hardcoded_constants/symbol-based-analyzer.js +181 -0
  57. package/rules/common/C030_use_custom_error_classes/analyzer.js +200 -0
  58. package/rules/common/C033_separate_service_repository/README.md +78 -0
  59. package/rules/common/C033_separate_service_repository/analyzer.js +160 -0
  60. package/rules/common/C033_separate_service_repository/config.json +50 -0
  61. package/rules/common/C033_separate_service_repository/regex-based-analyzer.js +585 -0
  62. package/rules/common/C033_separate_service_repository/symbol-based-analyzer.js +368 -0
  63. package/rules/common/C035_error_logging_context/STRATEGY.md +99 -0
  64. package/rules/common/C035_error_logging_context/analyzer.js +232 -0
  65. package/rules/common/C035_error_logging_context/config.json +54 -0
  66. package/rules/common/C035_error_logging_context/regex-based-analyzer.js +299 -0
  67. package/rules/common/C035_error_logging_context/symbol-based-analyzer.js +454 -0
  68. package/rules/common/C040_centralized_validation/analyzer.js +165 -0
  69. package/rules/common/C040_centralized_validation/config.json +46 -0
  70. package/rules/common/C040_centralized_validation/regex-based-analyzer.js +243 -0
  71. package/rules/common/C040_centralized_validation/symbol-based-analyzer.js +416 -0
  72. package/rules/common/{C076_single_test_behavior โ†’ C072_single_test_behavior}/analyzer.js +6 -6
  73. package/rules/common/C076_explicit_function_types/README.md +30 -0
  74. package/rules/common/C076_explicit_function_types/analyzer.js +172 -0
  75. package/rules/common/C076_explicit_function_types/config.json +15 -0
  76. package/rules/common/C076_explicit_function_types/semantic-analyzer.js +341 -0
  77. package/rules/index.js +6 -1
  78. package/rules/parser/rule-parser.js +13 -2
  79. package/rules/security/S005_no_origin_auth/README.md +226 -0
  80. package/rules/security/S005_no_origin_auth/analyzer.js +184 -0
  81. package/rules/security/S005_no_origin_auth/ast-analyzer.js +406 -0
  82. package/rules/security/S005_no_origin_auth/config.json +85 -0
  83. package/rules/security/S006_no_plaintext_recovery_codes/README.md +139 -0
  84. package/rules/security/S006_no_plaintext_recovery_codes/analyzer.js +306 -0
  85. package/rules/security/S006_no_plaintext_recovery_codes/config.json +48 -0
  86. package/rules/security/S007_no_plaintext_otp/README.md +198 -0
  87. package/rules/security/S007_no_plaintext_otp/analyzer.js +406 -0
  88. package/rules/security/S007_no_plaintext_otp/config.json +79 -0
  89. package/rules/security/S007_no_plaintext_otp/semantic-analyzer.js +609 -0
  90. package/rules/security/S007_no_plaintext_otp/semantic-config.json +195 -0
  91. package/rules/security/S007_no_plaintext_otp/semantic-wrapper.js +280 -0
  92. package/rules/security/S009_no_insecure_encryption/README.md +158 -0
  93. package/rules/security/S009_no_insecure_encryption/analyzer.js +319 -0
  94. package/rules/security/S009_no_insecure_encryption/config.json +55 -0
  95. package/rules/security/S010_no_insecure_encryption/README.md +224 -0
  96. package/rules/security/S010_no_insecure_encryption/analyzer.js +493 -0
  97. package/rules/security/S010_no_insecure_encryption/config.json +48 -0
  98. package/rules/security/S016_no_sensitive_querystring/STRATEGY.md +149 -0
  99. package/rules/security/S016_no_sensitive_querystring/analyzer.js +276 -0
  100. package/rules/security/S016_no_sensitive_querystring/config.json +127 -0
  101. package/rules/security/S016_no_sensitive_querystring/regex-based-analyzer.js +258 -0
  102. package/rules/security/S016_no_sensitive_querystring/symbol-based-analyzer.js +495 -0
  103. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +180 -366
  104. package/rules/security/S027_no_hardcoded_secrets/categories.json +153 -0
  105. package/rules/security/S027_no_hardcoded_secrets/categorized-analyzer.js +250 -0
  106. package/rules/security/S048_no_current_password_in_reset/README.md +222 -0
  107. package/rules/security/S048_no_current_password_in_reset/analyzer.js +366 -0
  108. package/rules/security/S048_no_current_password_in_reset/config.json +48 -0
  109. package/rules/security/S055_content_type_validation/README.md +176 -0
  110. package/rules/security/S055_content_type_validation/analyzer.js +312 -0
  111. package/rules/security/S055_content_type_validation/config.json +48 -0
  112. package/rules/utils/rule-helpers.js +140 -1
  113. package/scripts/consolidate-config.js +116 -0
  114. package/scripts/prepare-release.sh +1 -1
  115. package/config/rules/rules-registry.json +0 -765
  116. package/docs/ESLINT-INTEGRATION-STRATEGY.md +0 -392
  117. package/docs/FUTURE_PACKAGES.md +0 -83
  118. package/docs/HEURISTIC_VS_AI.md +0 -113
  119. package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +0 -112
  120. package/docs/PRODUCTION_SIZE_IMPACT.md +0 -183
  121. package/docs/RELEASE_GUIDE.md +0 -230
  122. package/docs/STANDARDIZED-CATEGORY-FILTERING.md +0 -156
  123. package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +0 -254
  124. package/rules/common/C006_function_naming/smart-analyzer.js +0 -503
package/CONTRIBUTING.md CHANGED
@@ -1,698 +1,342 @@
1
- # Contributing to Sun Lint
1
+ # Contributing to SunLint - Rule Development Guide
2
2
 
3
- Thank you for your interest in contributing to Sun Lint! ๐ŸŒŸ
3
+ ## ๐ŸŽฏ Quick Start for Rule Development
4
4
 
5
- ## ๐Ÿš€ **Getting Started**
5
+ This guide focuses on developing new rules for SunLint. Based on practical experience from refactoring rules like C013, C035, we recommend a **symbol-based only** approach for maximum accuracy.
6
6
 
7
- ### **Prerequisites**
8
- - Node.js 16+
9
- - npm 8+
10
- - Git
7
+ ## ๐Ÿ“‹ Rule Development Steps
11
8
 
12
- ### **Setup Development Environment**
9
+ ### Step 1: Register Rule in Registry
13
10
 
14
- ```bash
15
- # Clone the repository
16
- git clone https://github.com/sun-engineering/sunlint.git
17
- cd sunlint
18
-
19
- # Install dependencies
20
- npm install
21
-
22
- # Run tests
23
- npm test
24
-
25
- # Try the CLI locally
26
- node cli.js --help
27
- ```
28
-
29
- ## ๐Ÿ“‹ **Coding Standards**
30
-
31
- When contributing to Sun Lint, please follow these coding rules:
32
-
33
- ### **Code Quality Rules**
34
- - **Rule C005** โ€“ Each function should do one thing only
35
- - **Rule C006** โ€“ Function names must be verb/verb-noun
36
- - **Rule C007** โ€“ Avoid comments that just describe the code
37
- - **Rule C012** โ€“ Separate Command and Query operations (CQS principle)
38
- - **Rule C014** โ€“ Use Dependency Injection instead of direct instantiation
39
- - **Rule C015** โ€“ Use domain language in class/function names
40
- - **Rule C019** โ€“ Don't use `error` log level for non-critical errors
41
- - **Rule C031** โ€“ Keep validation logic separate
42
- - **Rule C032** โ€“ Don't call external APIs in constructors or static blocks
43
- - **Rule C033** โ€“ Separate processing logic and data queries in service layer
44
- - **Rule C034** โ€“ Limit direct access to global state in domain logic
45
- - **Rule C035** โ€“ When handling errors, log complete relevant information
46
- - **Rule C037** โ€“ API handlers should return standard response objects (not raw strings)
47
- - **Rule C038** โ€“ Avoid logic depending on file/module loading order
48
- - **Rule C040** โ€“ Don't scatter validation logic across multiple classes
49
-
50
- ## ๐Ÿ”ง **Development Workflow**
11
+ Add your rule to `config/rules/enhanced-rules-registry.json`:
51
12
 
52
- ### **SunLint Architecture Overview**
53
-
54
- SunLint uses a **multi-engine architecture** with rule mapping system:
55
-
56
- - **Heuristic Engine**: Pattern-based analysis using AST (Abstract Syntax Tree)
57
- - **ESLint Engine**: JavaScript/TypeScript linting using ESLint rules
58
- - **OpenAI Engine**: AI-powered code analysis
59
-
60
- **Rule Configuration Files:**
61
- - `rules/` - Unified rule registry (auto-generated from origin-rules)
62
- - `config/eslint-rule-mapping.json` - ESLint engine rule mappings
63
- - `origin-rules/` - Original rule definitions (markdown format)
64
-
65
- ### **Adding a New Rule (Current Process)**
66
-
67
- #### **Step 1: Choose Rule Implementation Approach**
68
-
69
- **Option A: ESLint Engine Rule (Recommended for JS/TS)**
70
- For JavaScript/TypeScript rules that can use existing ESLint rules:
71
-
72
- 1. **Add to ESLint mapping**: Edit `config/eslint-rule-mapping.json`
73
13
  ```json
74
14
  {
75
- "C042": ["no-magic-numbers", "custom/no-hardcoded-values"]
76
- }
77
- ```
78
-
79
- 2. **Create custom ESLint rule** (if needed): `integrations/eslint/plugin/rules/no-hardcoded-values.js`
80
-
81
- **Option B: Heuristic Engine Rule (Universal)**
82
- For language-agnostic rules or complex pattern analysis:
83
-
84
- 1. **Create rule class**: `custom-rules/c042-no-hardcoded-config.js`
85
-
86
- #### **Step 2: Implement Rule Logic**
87
-
88
- **For ESLint Engine Rules:**
89
- ```javascript
90
- // integrations/eslint/plugin/rules/no-hardcoded-values.js
91
- module.exports = {
92
- meta: {
93
- type: 'problem',
94
- docs: { description: 'Detect hardcoded configuration values' },
95
- schema: []
96
- },
97
- create(context) {
98
- return {
99
- VariableDeclaration(node) {
100
- // Rule C005: Single responsibility - detect hardcoded values
101
- if (this.isHardcodedConfig(node)) {
102
- context.report({
103
- node,
104
- message: 'Avoid hardcoded configuration values'
105
- });
15
+ "rules": {
16
+ "C010": {
17
+ "name": "Limit Block Nesting",
18
+ "description": "Limit nested blocks (if/for/while/switch) to maximum 3 levels for readability",
19
+ "category": "complexity",
20
+ "severity": "warning",
21
+ "languages": ["typescript", "javascript", "dart", "kotlin"],
22
+ "analyzer": "./rules/common/C010_limit_block_nesting/analyzer.js",
23
+ "config": "./rules/common/C010_limit_block_nesting/config.json",
24
+ "version": "1.0.0",
25
+ "status": "stable",
26
+ "tags": ["complexity", "readability", "nesting", "maintainability"],
27
+ "strategy": {
28
+ "preferred": "ast",
29
+ "fallbacks": ["ast"],
30
+ "accuracy": {
31
+ "ast": 95
106
32
  }
33
+ },
34
+ "engineMappings": {
35
+ "eslint": ["complexity", "max-depth"]
107
36
  }
108
- };
109
- }
110
- };
111
- ```
112
-
113
- **For Heuristic Engine Rules:**
114
- ```javascript
115
- // custom-rules/c042-no-hardcoded-config.js
116
- const SemanticRuleBase = require('../core/semantic-rule-base');
117
-
118
- class NoHardcodedConfigRule extends SemanticRuleBase {
119
- constructor() {
120
- super('C042', 'No Hardcoded Configuration Values');
121
- }
122
-
123
- analyze(node, context) {
124
- // Rule C005: Single responsibility - focus only on hardcoded config detection
125
- if (this.isHardcodedConfigValue(node)) {
126
- return this.createViolation(node, 'Hardcoded configuration value detected');
127
37
  }
128
- return null;
129
- }
130
-
131
- isHardcodedConfigValue(node) {
132
- // Rule C031: Keep validation logic separate
133
- const configPatterns = /^(API_URL|DATABASE_URL|MAX_|MIN_|TIMEOUT|PORT)/;
134
- return node.type === 'VariableDeclaration' &&
135
- configPatterns.test(node.declarations[0]?.id?.name);
136
38
  }
137
39
  }
138
-
139
- module.exports = NoHardcodedConfigRule;
140
- ```
141
-
142
- #### **Step 3: Update Rule Registry**
143
-
144
- Add rule definition to origin rules:
145
- ```markdown
146
- <!-- origin-rules/common-en.md -->
147
- ## C042: No Hardcoded Configuration Values
148
-
149
- **Category**: Maintainability
150
- **Severity**: Warning
151
-
152
- **Description**: Avoid hardcoding configuration values in business logic
153
-
154
- **Examples**:
155
- โŒ Bad:
156
- ```javascript
157
- const API_URL = "https://api.example.com";
158
- const MAX_RETRIES = 5;
159
40
  ```
160
41
 
161
- โœ… Good:
162
- ```javascript
163
- const API_URL = process.env.API_URL;
164
- const MAX_RETRIES = parseInt(process.env.MAX_RETRIES || '3');
165
- ```
42
+ **Key Registry Fields:**
43
+ - `analyzer`: Path to main analyzer file
44
+ - `strategy.preferred`: Use "ast" for symbol-based analysis
45
+ - `strategy.fallbacks`: Recommend ["ast"] only for accuracy
46
+ - `strategy.accuracy`: Expected accuracy percentage
166
47
 
167
- #### **Step 4: Add Tests**
168
-
169
- ```javascript
170
- // test/rules/c042.test.js
171
- const { testRule } = require('../test-utils');
172
-
173
- describe('Rule C042: No Hardcoded Configuration Values', () => {
174
- testRule('C042', {
175
- valid: [
176
- 'const apiUrl = process.env.API_URL;',
177
- 'const config = loadConfig();'
178
- ],
179
- invalid: [
180
- 'const API_URL = "https://api.example.com";',
181
- 'const MAX_RETRIES = 5;'
182
- ]
183
- });
184
- });
185
- ```
186
-
187
- #### **Step 5: Test Your Rule**
48
+ ### Step 2: Create Rule Directory Structure
188
49
 
189
50
  ```bash
190
- # Test with specific engine
191
- node cli.js --rule=C042 --engine=eslint --input=test/fixtures
192
- node cli.js --rule=C042 --engine=heuristic --input=test/fixtures
51
+ mkdir -p rules/common/C010_limit_block_nesting
52
+ cd rules/common/C010_limit_block_nesting
193
53
 
194
- # Test rule behavior
195
- node cli.js --rule=C042 --input=test/fixtures --verbose
54
+ # Required files
55
+ touch analyzer.js # Main orchestrator
56
+ touch symbol-based-analyzer.js # Core analysis logic
57
+ touch config.json # Rule configuration
196
58
  ```
197
59
 
198
- ### **Engine-Specific Development**
199
-
200
- #### **Heuristic Engine Rules**
60
+ ### Step 3: Implement Main Analyzer (analyzer.js)
201
61
 
202
- For custom pattern-based analysis:
203
-
204
- 1. **Create Rule Class**:
205
62
  ```javascript
206
- // rules/custom/your-rule.js
207
- const HeuristicRuleBase = require('../../core/heuristic-rule-base');
208
-
209
- class YourCustomRule extends HeuristicRuleBase {
210
- constructor() {
211
- super('CXXX', 'Your Rule Name');
63
+ // rules/common/C010_limit_block_nesting/analyzer.js
64
+ const C010SymbolBasedAnalyzer = require('./symbol-based-analyzer.js');
65
+
66
+ class C010Analyzer {
67
+ constructor(semanticEngine = null) {
68
+ this.ruleId = 'C010';
69
+ this.ruleName = 'Limit Block Nesting';
70
+ this.description = 'Limit nested blocks to maximum 3 levels';
71
+ this.semanticEngine = semanticEngine;
72
+ this.verbose = false;
73
+
74
+ // Use symbol-based only for accuracy
75
+ this.symbolAnalyzer = new C010SymbolBasedAnalyzer(semanticEngine);
212
76
  }
213
77
 
214
- analyze(node, context) {
215
- // Your analysis logic
216
- // Return violation or null
217
- }
218
- }
219
- ```
220
-
221
- 2. **Add to Registry**:
222
- ```json
223
- {
224
- "CXXX": {
225
- "engineMappings": {
226
- "heuristic": {
227
- "implementation": "custom/your-rule",
228
- "supportedLanguages": ["typescript", "javascript"]
229
- }
78
+ async initialize(semanticEngine = null) {
79
+ if (semanticEngine) {
80
+ this.semanticEngine = semanticEngine;
230
81
  }
82
+ this.verbose = semanticEngine?.verbose || false;
83
+ await this.symbolAnalyzer.initialize(semanticEngine);
231
84
  }
232
- }
233
- ```
234
85
 
235
- #### **ESLint Engine Rules**
86
+ async analyzeFileBasic(filePath, options = {}) {
87
+ try {
88
+ // Check if symbol engine is ready
89
+ if (!this.semanticEngine?.isSymbolEngineReady?.() || !this.semanticEngine.project) {
90
+ throw new Error('Symbol engine not available');
91
+ }
236
92
 
237
- For JavaScript/TypeScript linting:
93
+ if (this.verbose) {
94
+ console.log(`[DEBUG] ๐ŸŽฏ C010: Using symbol-based analysis for ${filePath.split('/').pop()}`);
95
+ }
238
96
 
239
- 1. **Use Existing ESLint Rules**:
240
- ```json
241
- {
242
- "CXXX": {
243
- "engineMappings": {
244
- "eslint": {
245
- "rules": ["no-console", "prefer-const"],
246
- "config": {
247
- "no-console": ["error"],
248
- "prefer-const": ["warn"]
249
- }
97
+ const violations = await this.symbolAnalyzer.analyzeFileBasic(filePath, options);
98
+
99
+ if (this.verbose) {
100
+ console.log(`[DEBUG] ๐ŸŽฏ C010: Symbol-based analysis found ${violations.length} violations`);
250
101
  }
251
- }
252
- }
253
- }
254
- ```
255
102
 
256
- 2. **Create Custom ESLint Rule** (advanced):
257
- ```javascript
258
- // eslint-custom-rules/your-rule.js
259
- module.exports = {
260
- meta: {
261
- type: 'problem',
262
- docs: { description: 'Your rule description' }
263
- },
264
- create(context) {
265
- return {
266
- FunctionDeclaration(node) {
267
- // Your ESLint rule logic
103
+ return violations;
104
+ } catch (error) {
105
+ if (this.verbose) {
106
+ console.error(`[DEBUG] โŒ C010: Analysis failed: ${error.message}`);
268
107
  }
269
- };
108
+ throw new Error(`C010 analysis failed: ${error.message}`);
109
+ }
270
110
  }
271
- };
272
- ```
273
-
274
- #### **OpenAI Engine Rules**
275
111
 
276
- For AI-powered analysis:
277
-
278
- ```json
279
- {
280
- "CXXX": {
281
- "engineMappings": {
282
- "openai": {
283
- "prompt": "Analyze code for specific pattern or anti-pattern",
284
- "examples": [
285
- "// Bad example",
286
- "// Good example"
287
- ],
288
- "temperature": 0.1,
289
- "maxTokens": 500
112
+ async analyzeFiles(files, options = {}) {
113
+ const allViolations = [];
114
+ for (const filePath of files) {
115
+ try {
116
+ const violations = await this.analyzeFileBasic(filePath, options);
117
+ allViolations.push(...violations);
118
+ } catch (error) {
119
+ console.warn(`C010: Skipping ${filePath}: ${error.message}`);
290
120
  }
291
121
  }
122
+ return allViolations;
292
123
  }
293
124
  }
294
- ```
295
-
296
- ### **Adding a New Security Rule**
297
-
298
- Same process as above, just use `"category": "security"` in the rule definition.
299
-
300
- ### **Testing Your New Rule**
301
-
302
- ```bash
303
- # Test all engines with your new rule
304
- node cli.js --rule=C042 --input=test/fixtures --format=json
305
-
306
- # Test specific engine
307
- node cli.js --rule=C042 --engine=heuristic --input=test/fixtures
308
- node cli.js --rule=C042 --engine=eslint --input=test/fixtures
309
- node cli.js --rule=C042 --engine=openai --input=test/fixtures
310
125
 
311
- # Validate rule registry
312
- node validate-system.js
126
+ module.exports = C010Analyzer;
313
127
  ```
314
128
 
315
- ### **Rule Definition Schema**
129
+ ### Step 4: Implement Symbol-Based Analyzer
316
130
 
317
- Complete schema for rule definitions:
131
+ ```javascript
132
+ // rules/common/C010_limit_block_nesting/symbol-based-analyzer.js
133
+ const { SyntaxKind } = require('ts-morph');
134
+
135
+ class C010SymbolBasedAnalyzer {
136
+ constructor(semanticEngine = null) {
137
+ this.semanticEngine = semanticEngine;
138
+ this.maxNestingLevel = 3;
139
+ this.verbose = false;
140
+ }
318
141
 
319
- ```json
320
- {
321
- "CXXX": {
322
- "id": "CXXX", // Required: Rule ID
323
- "title": "Rule Title", // Required: Human-readable title
324
- "description": "Detailed description", // Required: Rule description
325
- "severity": "error|warning|info", // Required: Severity level
326
- "category": "quality|security|performance|maintainability", // Required
327
- "tags": ["tag1", "tag2"], // Optional: Tags for filtering
328
- "languages": ["typescript", "javascript"], // Optional: Supported languages
329
- "engineMappings": { // Required: Engine configurations
330
- "heuristic": {
331
- "implementation": "custom/rule-name",
332
- "supportedLanguages": ["typescript"],
333
- "astTargets": ["FunctionDeclaration"]
334
- },
335
- "eslint": {
336
- "rules": ["eslint-rule-name"],
337
- "config": { "rule-option": true }
338
- },
339
- "openai": {
340
- "prompt": "AI analysis prompt",
341
- "examples": ["code example"],
342
- "temperature": 0.1
343
- }
344
- },
345
- "analysisStrategy": { // Optional: Analysis metadata
346
- "type": "ast|regex|semantic",
347
- "patterns": ["pattern1"],
348
- "astTargets": ["NodeType"],
349
- "heuristics": ["detection-method"]
350
- },
351
- "metadata": { // Optional: Additional metadata
352
- "author": "Developer Name",
353
- "created": "2025-08-07",
354
- "updated": "2025-08-07",
355
- "version": "1.0.0"
142
+ async initialize(semanticEngine = null) {
143
+ if (semanticEngine) {
144
+ this.semanticEngine = semanticEngine;
356
145
  }
146
+ this.verbose = semanticEngine?.verbose || false;
357
147
  }
358
- }
359
- ```
360
-
361
- ### **Architecture Deep Dive**
362
-
363
- #### **Unified Rule Registry**
364
- - **Location**: `rules/` (auto-generated from origin-rules)
365
- - **Source**: `origin-rules/` (markdown files)
366
- - **ESLint Mappings**: `config/eslint-rule-mapping.json`
367
- - **Loader**: `core/unified-rule-registry.js`
368
148
 
369
- #### **Engine Architecture**
370
- ```
371
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
372
- โ”‚ SunLint CLI โ”‚
373
- โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
374
- โ”‚ Analysis Orchestrator โ”‚
375
- โ”‚ (Strict Engine Mode Support) โ”‚
376
- โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
377
- โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
378
- โ”‚ โ”‚ Heuristic โ”‚ ESLint โ”‚ OpenAI โ”‚ โ”‚
379
- โ”‚ โ”‚ Engine โ”‚ Engine โ”‚ Engine โ”‚ โ”‚
380
- โ”‚ โ”‚ (244 rules) โ”‚ (57 rules) โ”‚(256 all)โ”‚ โ”‚
381
- โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
382
- โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
383
- โ”‚ Rule Configuration โ”‚
384
- โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
385
- โ”‚ โ”‚ ESLint โ”‚ Unified Registry โ”‚ โ”‚
386
- โ”‚ โ”‚ Mappings โ”‚ (Generated Rules) โ”‚ โ”‚
387
- โ”‚ โ”‚ (.json) โ”‚ (origin-rules) โ”‚ โ”‚
388
- โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
389
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
390
- ```
149
+ async analyzeFileBasic(filePath, options = {}) {
150
+ const violations = [];
151
+
152
+ try {
153
+ const sourceFile = this.semanticEngine.project.getSourceFile(filePath);
154
+ if (!sourceFile) {
155
+ throw new Error(`Source file not found: ${filePath}`);
156
+ }
391
157
 
392
- #### **How Engines Load Rules**
393
- 1. **Initialization**: Each engine calls `getInstance()` from unified registry
394
- 2. **Rule Loading**: Registry loads rules from auto-generated `rules/` directory
395
- 3. **ESLint Mapping**: ESLint engine loads rule mappings from `config/eslint-rule-mapping.json`
396
- 4. **Engine Filtering**: Each engine filters rules based on their capabilities
397
- 5. **Analysis**: Engines analyze code using their specific rule implementations
158
+ if (this.verbose) {
159
+ console.log(`[DEBUG] ๐Ÿ” C010: Analyzing nesting in ${filePath.split('/').pop()}`);
160
+ }
398
161
 
399
- **Key Features:**
400
- - โœ… **Strict Engine Mode**: `--engine=eslint` only runs ESLint, skips unsupported rules
401
- - โœ… **Fallback Mode**: Auto-engine selection with fallback (ESLint โ†’ Heuristic โ†’ OpenAI)
402
- - โœ… **Rule Skipping**: Graceful handling of unsupported rules by specific engines
162
+ // Find nested blocks
163
+ const nestedBlocks = this.findNestedBlocks(sourceFile);
164
+
165
+ for (const block of nestedBlocks) {
166
+ if (block.nestingLevel > this.maxNestingLevel) {
167
+ violations.push({
168
+ ruleId: 'C010',
169
+ message: `Nested block exceeds maximum depth of ${this.maxNestingLevel} (current: ${block.nestingLevel}). Consider extracting to separate functions.`,
170
+ filePath: filePath,
171
+ line: block.line,
172
+ column: block.column,
173
+ severity: 'warning',
174
+ category: 'complexity'
175
+ });
176
+ }
177
+ }
403
178
 
404
- ## ๐Ÿงช **Testing**
179
+ if (this.verbose) {
180
+ console.log(`[DEBUG] ๐Ÿ” C010: Found ${violations.length} nesting violations`);
181
+ }
405
182
 
406
- ### **Run All Tests**
407
- ```bash
408
- npm test
409
- ```
183
+ return violations;
184
+ } catch (error) {
185
+ if (this.verbose) {
186
+ console.error(`[DEBUG] โŒ C010: Symbol analysis error: ${error.message}`);
187
+ }
188
+ throw error;
189
+ }
190
+ }
410
191
 
411
- ### **Test Rule Registry System**
412
- ```bash
413
- # Validate unified rule registry
414
- node validate-system.js
192
+ findNestedBlocks(sourceFile) {
193
+ const blocks = [];
194
+
195
+ function traverse(node, currentDepth = 0) {
196
+ // Check for block statements that increase nesting
197
+ if (this.isNestingNode(node)) {
198
+ currentDepth++;
199
+
200
+ const position = sourceFile.getLineAndColumnAtPos(node.getStart());
201
+ blocks.push({
202
+ node: node,
203
+ nestingLevel: currentDepth,
204
+ line: position.line,
205
+ column: position.column
206
+ });
207
+ }
415
208
 
416
- # Check rule loading for each engine
417
- npm run test:engines
418
- ```
209
+ // Traverse children
210
+ node.forEachChild(child => traverse.call(this, child, currentDepth));
211
+ }
419
212
 
420
- ### **Test Specific Rules**
421
- ```bash
422
- # Test specific rule with all engines
423
- node cli.js --rule=C042 --input=test/fixtures
213
+ traverse.call(this, sourceFile, 0);
214
+ return blocks;
215
+ }
424
216
 
425
- # Test with specific engine
426
- node cli.js --rule=C042 --engine=heuristic --input=test/fixtures
427
- node cli.js --rule=C042 --engine=eslint --input=test/fixtures
428
- node cli.js --rule=C042 --engine=openai --input=test/fixtures
217
+ isNestingNode(node) {
218
+ return [
219
+ SyntaxKind.IfStatement,
220
+ SyntaxKind.ForStatement,
221
+ SyntaxKind.ForInStatement,
222
+ SyntaxKind.ForOfStatement,
223
+ SyntaxKind.WhileStatement,
224
+ SyntaxKind.DoStatement,
225
+ SyntaxKind.SwitchStatement,
226
+ SyntaxKind.TryStatement,
227
+ SyntaxKind.CatchClause
228
+ ].includes(node.getKind());
229
+ }
230
+ }
429
231
 
430
- # Test multiple rules
431
- node cli.js --rule=C006,C019,C042 --input=test/fixtures
232
+ module.exports = C010SymbolBasedAnalyzer;
432
233
  ```
433
234
 
434
- ### **Test Rule Development**
435
- ```bash
436
- # Create test fixtures
437
- mkdir -p test/fixtures/c042
438
- echo 'const API_URL = "https://api.example.com";' > test/fixtures/c042/invalid.ts
439
- echo 'const apiUrl = process.env.API_URL;' > test/fixtures/c042/valid.ts
235
+ ### Step 5: Create Rule Configuration
440
236
 
441
- # Test your rule
442
- node cli.js --rule=C042 --input=test/fixtures/c042 --format=json
237
+ ```json
238
+ // rules/common/C010_limit_block_nesting/config.json
239
+ {
240
+ "maxNestingLevel": 3,
241
+ "excludePatterns": [
242
+ "**/*.test.js",
243
+ "**/*.spec.js"
244
+ ],
245
+ "includePatterns": [
246
+ "**/*.js",
247
+ "**/*.ts",
248
+ "**/*.jsx",
249
+ "**/*.tsx"
250
+ ]
251
+ }
443
252
  ```
444
253
 
445
- ### **Integration Testing**
446
- ```bash
447
- # Test all engines work together
448
- npm run test:integration
449
-
450
- # Test rule registry loading
451
- npm run test:registry
452
-
453
- # Performance testing
454
- npm run test:performance
455
- ```
254
+ ## ๐Ÿšจ Common Pitfalls & Solutions
456
255
 
457
- ## ๐Ÿ“Š **Code Review Process**
458
-
459
- 1. **Self-Review Checklist**
460
- - [ ] Follows all Sun Lint coding rules (C005, C006, etc.)
461
- - [ ] Rule C035: Error handling includes complete logging
462
- - [ ] Rule C037: API responses use standard format
463
- - [ ] Rule C040: Validation logic is centralized
464
- - [ ] Tests pass and cover edge cases
465
- - [ ] Documentation updated
466
-
467
- 2. **Submit Pull Request**
468
- - Clear title and description
469
- - Reference related issues
470
- - Include test results
471
- - Follow template
472
- - **NEW**: Validate rule registry with `node validate-system.js`
473
-
474
- 3. **Review Criteria**
475
- - Code quality (follows our own rules!)
476
- - Rule properly defined in `enhanced-rules-registry.json`
477
- - All engines can load the rule correctly
478
- - Test coverage for all supported engines
479
- - Documentation completeness
480
- - Performance impact
481
- - Backward compatibility
482
-
483
- ## ๐Ÿ“ **Documentation**
484
-
485
- ### **Update Documentation**
486
- When adding features:
487
- - Update `README.md`
488
- - Add rule to `enhanced-rules-registry.json` (this is your main documentation!)
489
- - Update configuration examples
490
- - Add usage examples
491
- - Update `RULE_MIGRATION_SUMMARY.md` if changing rule system
492
-
493
- ### **Rule Documentation Template**
494
-
495
- All rule documentation is now centralized in `enhanced-rules-registry.json`:
256
+ ### 1. Symbol Engine Not Ready
257
+ ```javascript
258
+ // โŒ Wrong - Will fail if symbol engine not ready
259
+ const violations = await this.symbolAnalyzer.analyzeFileBasic(filePath);
496
260
 
497
- ```json
498
- {
499
- "C042": {
500
- "title": "Clear, descriptive rule title",
501
- "description": "Detailed explanation of what the rule checks, why it matters, and how to fix violations. Follow Rule C015 (domain language) - use clear business terms.",
502
- "examples": {
503
- "invalid": [
504
- "// Bad example that violates the rule",
505
- "const API_URL = 'https://hardcoded-url.com';"
506
- ],
507
- "valid": [
508
- "// Good example that follows the rule",
509
- "const apiUrl = process.env.API_URL;"
510
- ]
511
- },
512
- "fixSuggestions": [
513
- "Move configuration to environment variables",
514
- "Use a configuration management system",
515
- "Extract constants to a separate config file"
516
- ],
517
- "relatedRules": ["C031", "C034"]
518
- }
261
+ // โœ… Correct - Check engine availability
262
+ if (!this.semanticEngine?.isSymbolEngineReady?.() || !this.semanticEngine.project) {
263
+ throw new Error('Symbol engine not available');
519
264
  }
520
265
  ```
521
266
 
522
- ### **Engine-Specific Documentation**
267
+ ### 2. Missing Source File Check
268
+ ```javascript
269
+ // โŒ Wrong - Will crash if file not found
270
+ const sourceFile = this.semanticEngine.project.getSourceFile(filePath);
523
271
 
524
- #### **Heuristic Engine Rules**
525
- Document custom analysis patterns:
526
- ```json
527
- {
528
- "analysisStrategy": {
529
- "type": "ast",
530
- "description": "Analyzes AST nodes for hardcoded configuration patterns",
531
- "astTargets": ["VariableDeclaration", "PropertyAssignment"],
532
- "patterns": ["literal-values-in-config-context"],
533
- "complexity": "O(n) where n is number of variable declarations"
534
- }
272
+ // โœ… Correct - Always check source file existence
273
+ const sourceFile = this.semanticEngine.project.getSourceFile(filePath);
274
+ if (!sourceFile) {
275
+ throw new Error(`Source file not found: ${filePath}`);
535
276
  }
536
277
  ```
537
278
 
538
- #### **ESLint Engine Rules**
539
- Document ESLint rule mappings:
540
- ```json
541
- {
542
- "engineMappings": {
543
- "eslint": {
544
- "rules": ["no-magic-numbers"],
545
- "rationale": "ESLint's no-magic-numbers rule catches hardcoded values",
546
- "limitations": "May have false positives for legitimate constants",
547
- "customConfig": {
548
- "no-magic-numbers": ["error", { "ignore": [0, 1, -1] }]
549
- }
550
- }
551
- }
279
+ ### 3. Improper Error Handling
280
+ ```javascript
281
+ // โŒ Wrong - Silent failures
282
+ try {
283
+ const violations = await this.analyzeFile(filePath);
284
+ } catch (error) {
285
+ return [];
552
286
  }
553
- ```
554
287
 
555
- #### **OpenAI Engine Rules**
556
- Document AI prompts and examples:
557
- ```json
558
- {
559
- "engineMappings": {
560
- "openai": {
561
- "prompt": "Identify hardcoded configuration values that should be externalized to environment variables or config files",
562
- "context": "Look for URLs, timeouts, limits, and other configuration that might change between environments",
563
- "examples": [
564
- "โŒ const API_URL = 'https://api.example.com';",
565
- "โœ… const API_URL = process.env.API_URL || 'https://default-api.com';"
566
- ]
567
- }
288
+ // โœ… Correct - Proper error propagation
289
+ try {
290
+ const violations = await this.analyzeFile(filePath);
291
+ return violations;
292
+ } catch (error) {
293
+ if (this.verbose) {
294
+ console.error(`Analysis failed: ${error.message}`);
568
295
  }
296
+ throw error;
569
297
  }
570
298
  ```
571
299
 
572
- ## ๐Ÿ› **Bug Reports**
573
-
574
- When reporting bugs:
575
- 1. Use clear, descriptive title
576
- 2. Include reproduction steps
577
- 3. Provide sample code
578
- 4. Include environment details
579
- 5. Include sunlint output
580
- 6. **NEW**: Run `node validate-system.js` and include output
300
+ ## ๐Ÿงช Testing Your Rule
581
301
 
582
- ## ๐Ÿ”ง **Troubleshooting**
583
-
584
- ### **Common Issues**
585
-
586
- #### **Rule Not Loading**
587
302
  ```bash
588
- # Check if rule exists in registry
589
- node -e "const registry = require('./core/unified-rule-registry'); registry.getInstance().initialize().then(() => console.log('Rule C042:', registry.getInstance().rules.has('C042')))"
303
+ # Test single file
304
+ node cli.js --input=test-file.js --rule=C010 --engine=heuristic --verbose
590
305
 
591
- # Validate registry syntax
592
- node validate-system.js
593
- ```
306
+ # Test project
307
+ node cli.js --input=src/ --rule=C010 --engine=heuristic --max-semantic-files=-1
594
308
 
595
- #### **Engine Not Finding Rule**
596
- ```bash
597
- # Check engine-specific mapping
598
- node -e "const registry = require('./core/unified-rule-registry'); registry.getInstance().initialize().then(r => { const rule = r.rules.get('C042'); console.log('ESLint mapping:', rule?.engineMappings?.eslint); })"
309
+ # Performance test
310
+ time node cli.js --input=large-project/ --rule=C010 --engine=heuristic
599
311
  ```
600
312
 
601
- #### **Rule Registry Errors**
602
- ```bash
603
- # Common issues:
604
- # 1. JSON syntax errors in enhanced-rules-registry.json
605
- # 2. Missing required fields (id, title, description, severity, category)
606
- # 3. Invalid engine mapping structure
313
+ ## ๐Ÿ“ Best Practices
607
314
 
608
- # Validate JSON syntax
609
- node -c config/enhanced-rules-registry.json
315
+ 1. **Use Symbol-Based Only**: More accurate than regex patterns
316
+ 2. **Always Check Engine State**: Verify semantic engine is ready
317
+ 3. **Handle Errors Gracefully**: Don't silently ignore failures
318
+ 4. **Add Debug Logging**: Use `this.verbose` for troubleshooting
319
+ 5. **Test on Real Projects**: Validate with large codebases
320
+ 6. **Document Accuracy**: Update strategy.accuracy in registry
610
321
 
611
- # Check required fields
612
- node validate-system.js
613
- ```
322
+ ## ๐Ÿ”ง Development Environment
614
323
 
615
- ### **Performance Issues**
616
324
  ```bash
617
- # Profile rule loading
618
- node --prof cli.js --rule=C042 --input=large-project/
619
-
620
- # Check memory usage
621
- node --inspect cli.js --rule=C042 --input=test/fixtures/
622
- ```
623
-
624
- ## ๐Ÿ’ก **Feature Requests**
625
-
626
- For new features:
627
- 1. Check existing issues first
628
- 2. Describe the use case
629
- 3. Provide examples
630
- 4. Consider implementation complexity
631
- 5. Think about backward compatibility
632
-
633
- ## ๐Ÿ“‹ **Quick Reference**
634
-
635
- ### **Essential Commands**
636
- ```bash
637
- # Add ESLint engine rule mapping
638
- vim config/eslint-rule-mapping.json
639
-
640
- # Create custom heuristic rule
641
- vim custom-rules/c042-rule-name.js
642
-
643
- # Add rule documentation
644
- vim origin-rules/common-en.md
645
-
646
- # Test new rule with specific engine
647
- node cli.js --rule=CXXX --engine=eslint --input=test/fixtures
648
- node cli.js --rule=CXXX --engine=heuristic --input=test/fixtures
649
-
650
- # Test strict engine mode (no fallback)
651
- node cli.js --rule=CXXX --engine=eslint --input=test/fixtures
325
+ # Setup
326
+ npm install
327
+ npm test
652
328
 
653
- # Test fallback mode (auto engine selection)
654
- node cli.js --rule=CXXX --input=test/fixtures
329
+ # Development workflow
330
+ node cli.js --input=examples/ --rule=YOUR_RULE --engine=heuristic --verbose
655
331
  ```
656
332
 
657
- ### **Key Files**
658
- - `config/eslint-rule-mapping.json` - **ESLint engine rule mappings**
659
- - `origin-rules/` - **Original rule definitions** (markdown format)
660
- - `rules/` - **Generated rule registry** (auto-generated)
661
- - `core/unified-rule-registry.js` - Rule registry loader
662
- - `engines/heuristic-engine.js` - Custom pattern analysis
663
- - `engines/eslint-engine.js` - JavaScript/TypeScript linting
664
- - `engines/openai-engine.js` - AI-powered analysis
665
- - `integrations/eslint/plugin/` - Custom ESLint rules
666
- - `custom-rules/` - Heuristic engine custom rules
667
-
668
- ### **Rule Development Checklist**
669
- - [ ] Choose appropriate engine (ESLint for JS/TS, Heuristic for universal)
670
- - [ ] Add ESLint mapping to `config/eslint-rule-mapping.json` (if using ESLint engine)
671
- - [ ] Create custom rule implementation (if needed)
672
- - [ ] Add rule definition to `origin-rules/` (markdown format)
673
- - [ ] Add test cases and examples
674
- - [ ] Test with `node cli.js --rule=CXXX --input=test/fixtures`
675
- - [ ] Test engine-specific behavior (`--engine=eslint`, `--engine=heuristic`)
676
- - [ ] Update documentation if needed
677
-
678
- ---
679
-
680
- **๐Ÿš€ Ready to contribute? Start by choosing your engine and editing the appropriate mapping file!**
681
-
682
- **For ESLint rules**: Edit `config/eslint-rule-mapping.json`
683
- **For Heuristic rules**: Create files in `custom-rules/`
684
- **For documentation**: Add to `origin-rules/` markdown files
685
-
686
- ## ๐Ÿค **Community**
687
-
688
- - **Discord**: [Sun Engineering Discord](https://discord.gg/sun-engineering)
689
- - **Issues**: [GitHub Issues](https://github.com/sun-engineering/sunlint/issues)
690
- - **Discussions**: [GitHub Discussions](https://github.com/sun-engineering/sunlint/discussions)
691
-
692
- ## ๐Ÿ“„ **License**
333
+ ## ๐Ÿ“š Advanced Topics
693
334
 
694
- By contributing, you agree that your contributions will be licensed under the MIT License.
335
+ - **AST Navigation**: Use ts-morph documentation for node traversal
336
+ - **Performance**: Symbol-based analysis is ~15s for 2000+ files
337
+ - **Multi-language**: Extend analyzers for Dart, Kotlin support
338
+ - **Custom Patterns**: Leverage SyntaxKind for specific constructs
695
339
 
696
340
  ---
697
341
 
698
- **Thank you for making Sun Lint better! โ˜€๏ธ**
342
+ This guide is based on real experience refactoring C013 and other rules. Focus on accuracy over speed - symbol-based analysis provides much better results than regex patterns.