@sun-asterisk/sunlint 1.3.0 → 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.
Files changed (73) hide show
  1. package/CHANGELOG.md +68 -1
  2. package/CONTRIBUTING.md +1179 -54
  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 +23 -4
  10. package/config/rules/S027-categories.json +122 -0
  11. package/config/rules/enhanced-rules-registry.json +136 -75
  12. package/config/rules/rules-registry-generated.json +2 -2
  13. package/config/rules/rules-registry.json +13 -1
  14. package/core/cli-action-handler.js +24 -30
  15. package/core/cli-program.js +11 -3
  16. package/core/config-merger.js +29 -2
  17. package/core/enhanced-rules-registry.js +3 -3
  18. package/core/semantic-engine.js +117 -19
  19. package/core/unified-rule-registry.js +1 -1
  20. package/docs/COMMAND-EXAMPLES.md +134 -0
  21. package/docs/LARGE-PROJECT-GUIDE.md +324 -0
  22. package/engines/heuristic-engine.js +71 -13
  23. package/integrations/eslint/plugin/index.js +0 -2
  24. package/origin-rules/common-en.md +8 -8
  25. package/package.json +1 -1
  26. package/rules/common/C017_constructor_logic/analyzer.js +254 -17
  27. package/rules/common/C017_constructor_logic/semantic-analyzer.js +340 -0
  28. package/rules/common/C033_separate_service_repository/README.md +78 -0
  29. package/rules/common/C033_separate_service_repository/analyzer.js +160 -0
  30. package/rules/common/C033_separate_service_repository/config.json +50 -0
  31. package/rules/common/C033_separate_service_repository/regex-based-analyzer.js +585 -0
  32. package/rules/common/C033_separate_service_repository/symbol-based-analyzer.js +368 -0
  33. package/rules/common/C035_error_logging_context/STRATEGY.md +99 -0
  34. package/rules/common/C035_error_logging_context/analyzer.js +230 -0
  35. package/rules/common/C035_error_logging_context/config.json +54 -0
  36. package/rules/common/C035_error_logging_context/regex-based-analyzer.js +299 -0
  37. package/rules/common/C035_error_logging_context/symbol-based-analyzer.js +454 -0
  38. package/rules/common/C040_centralized_validation/analyzer.js +165 -0
  39. package/rules/common/C040_centralized_validation/config.json +46 -0
  40. package/rules/common/C040_centralized_validation/regex-based-analyzer.js +243 -0
  41. package/rules/common/C040_centralized_validation/symbol-based-analyzer.js +416 -0
  42. package/rules/common/{C076_single_test_behavior → C072_single_test_behavior}/analyzer.js +6 -6
  43. package/rules/common/C076_explicit_function_types/README.md +30 -0
  44. package/rules/common/C076_explicit_function_types/analyzer.js +172 -0
  45. package/rules/common/C076_explicit_function_types/config.json +15 -0
  46. package/rules/common/C076_explicit_function_types/semantic-analyzer.js +341 -0
  47. package/rules/index.js +1 -0
  48. package/rules/parser/rule-parser.js +13 -2
  49. package/rules/security/S005_no_origin_auth/README.md +226 -0
  50. package/rules/security/S005_no_origin_auth/analyzer.js +184 -0
  51. package/rules/security/S005_no_origin_auth/ast-analyzer.js +406 -0
  52. package/rules/security/S005_no_origin_auth/config.json +85 -0
  53. package/rules/security/S006_no_plaintext_recovery_codes/README.md +139 -0
  54. package/rules/security/S006_no_plaintext_recovery_codes/analyzer.js +306 -0
  55. package/rules/security/S006_no_plaintext_recovery_codes/config.json +48 -0
  56. package/rules/security/S007_no_plaintext_otp/README.md +198 -0
  57. package/rules/security/S007_no_plaintext_otp/analyzer.js +406 -0
  58. package/rules/security/S007_no_plaintext_otp/config.json +79 -0
  59. package/rules/security/S007_no_plaintext_otp/semantic-analyzer.js +609 -0
  60. package/rules/security/S007_no_plaintext_otp/semantic-config.json +195 -0
  61. package/rules/security/S007_no_plaintext_otp/semantic-wrapper.js +280 -0
  62. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +180 -366
  63. package/rules/security/S027_no_hardcoded_secrets/categories.json +153 -0
  64. package/rules/security/S027_no_hardcoded_secrets/categorized-analyzer.js +250 -0
  65. package/scripts/prepare-release.sh +1 -1
  66. package/docs/ESLINT-INTEGRATION-STRATEGY.md +0 -392
  67. package/docs/FUTURE_PACKAGES.md +0 -83
  68. package/docs/HEURISTIC_VS_AI.md +0 -113
  69. package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +0 -112
  70. package/docs/PRODUCTION_SIZE_IMPACT.md +0 -183
  71. package/docs/RELEASE_GUIDE.md +0 -230
  72. package/docs/STANDARDIZED-CATEGORY-FILTERING.md +0 -156
  73. package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +0 -254
package/CONTRIBUTING.md CHANGED
@@ -62,92 +62,652 @@ SunLint uses a **multi-engine architecture** with rule mapping system:
62
62
  - `config/eslint-rule-mapping.json` - ESLint engine rule mappings
63
63
  - `origin-rules/` - Original rule definitions (markdown format)
64
64
 
65
- ### **Adding a New Rule (Current Process)**
65
+ ### **Adding a New Rule (Modern Approach - 2025)**
66
66
 
67
- #### **Step 1: Choose Rule Implementation Approach**
67
+ #### **Step 1: Choose Rule Implementation Strategy**
68
68
 
69
- **Option A: ESLint Engine Rule (Recommended for JS/TS)**
70
- For JavaScript/TypeScript rules that can use existing ESLint rules:
69
+ **Modern Approach: Hybrid Symbol + Regex Analysis (Recommended)**
70
+ Following the successful C035 pattern, implement rules with both symbol-based and regex-based analyzers for maximum accuracy and fallback coverage.
71
71
 
72
- 1. **Add to ESLint mapping**: Edit `config/eslint-rule-mapping.json`
73
- ```json
74
- {
75
- "C042": ["no-magic-numbers", "custom/no-hardcoded-values"]
72
+ #### **Step 2: Create Rule Directory Structure**
73
+
74
+ ```bash
75
+ # Create rule directory
76
+ mkdir -p rules/common/C042_no_hardcoded_config
77
+
78
+ # Create required files
79
+ touch rules/common/C042_no_hardcoded_config/analyzer.js
80
+ touch rules/common/C042_no_hardcoded_config/symbol-based-analyzer.js
81
+ touch rules/common/C042_no_hardcoded_config/regex-based-analyzer.js
82
+ touch rules/common/C042_no_hardcoded_config/config.json
83
+ touch rules/common/C042_no_hardcoded_config/STRATEGY.md
84
+ ```
85
+
86
+ #### **Step 3: Implement Main Analyzer (Hybrid Orchestrator)**
87
+
88
+ ```javascript
89
+ // rules/common/C042_no_hardcoded_config/analyzer.js
90
+ const C042SymbolBasedAnalyzer = require('./symbol-based-analyzer.js');
91
+ const C042RegexBasedAnalyzer = require('./regex-based-analyzer.js');
92
+
93
+ class C042Analyzer {
94
+ constructor(semanticEngine = null) {
95
+ this.ruleId = 'C042';
96
+ this.ruleName = 'No Hardcoded Configuration Values';
97
+ this.description = 'Avoid hardcoding configuration values in business logic';
98
+ this.semanticEngine = semanticEngine;
99
+ this.verbose = false;
100
+
101
+ // Configuration
102
+ this.config = {
103
+ useSymbolBased: true, // Primary approach
104
+ fallbackToRegex: true, // Only when symbol fails completely
105
+ symbolBasedOnly: false // Can be set to true for pure mode
106
+ };
107
+
108
+ // Initialize both analyzers
109
+ this.symbolAnalyzer = new C042SymbolBasedAnalyzer(semanticEngine);
110
+ this.regexAnalyzer = new C042RegexBasedAnalyzer(semanticEngine);
111
+ }
112
+
113
+ async initialize(semanticEngine = null) {
114
+ if (semanticEngine) {
115
+ this.semanticEngine = semanticEngine;
116
+ }
117
+ this.verbose = semanticEngine?.verbose || false;
118
+
119
+ // Initialize both analyzers
120
+ await this.symbolAnalyzer.initialize(semanticEngine);
121
+ await this.regexAnalyzer.initialize(semanticEngine);
122
+
123
+ if (this.verbose) {
124
+ console.log(`🔧 [C042 Hybrid] Analyzer initialized`);
125
+ }
126
+ }
127
+
128
+ async analyzeFileBasic(filePath, options = {}) {
129
+ try {
130
+ // Try symbol-based analysis first
131
+ if (this.semanticEngine?.isSymbolEngineReady?.() &&
132
+ this.semanticEngine.project) {
133
+
134
+ if (this.verbose) {
135
+ console.log(`🔍 [C042] Using symbol-based analysis for ${filePath}`);
136
+ }
137
+
138
+ const violations = await this.symbolAnalyzer.analyzeFileBasic(filePath, options);
139
+ return violations;
140
+ }
141
+ } catch (error) {
142
+ if (this.verbose) {
143
+ console.warn(`⚠️ [C042] Symbol analysis failed: ${error.message}`);
144
+ }
145
+ }
146
+
147
+ // Fallback to regex-based analysis
148
+ if (this.verbose) {
149
+ console.log(`🔄 [C042] Using regex-based analysis (fallback) for ${filePath}`);
150
+ }
151
+
152
+ return await this.regexAnalyzer.analyzeFileBasic(filePath, options);
153
+ }
154
+
155
+ async analyze(files, language, options = {}) {
156
+ const violations = [];
157
+
158
+ for (const filePath of files) {
159
+ try {
160
+ const fileViolations = await this.analyzeFileBasic(filePath, options);
161
+ violations.push(...fileViolations);
162
+ } catch (error) {
163
+ if (this.verbose) {
164
+ console.warn(`❌ [C042] Analysis failed for ${filePath}:`, error.message);
165
+ }
166
+ }
167
+ }
168
+
169
+ return violations;
170
+ }
76
171
  }
172
+
173
+ module.exports = C042Analyzer;
77
174
  ```
78
175
 
79
- 2. **Create custom ESLint rule** (if needed): `integrations/eslint/plugin/rules/no-hardcoded-values.js`
176
+ #### **Step 4: Implement Symbol-Based Analyzer (Primary)**
177
+
178
+ ```javascript
179
+ // rules/common/C042_no_hardcoded_config/symbol-based-analyzer.js
180
+ class C042SymbolBasedAnalyzer {
181
+ constructor(semanticEngine = null) {
182
+ this.ruleId = 'C042';
183
+ this.ruleName = 'No Hardcoded Configuration Values (Symbol-Based)';
184
+ this.semanticEngine = semanticEngine;
185
+ this.verbose = false;
186
+
187
+ // Configuration patterns to detect
188
+ this.configPatterns = [
189
+ /^API_/i, /^DATABASE_/i, /^DB_/i,
190
+ /^MAX_/i, /^MIN_/i, /^LIMIT_/i,
191
+ /^TIMEOUT/i, /^PORT$/i, /^HOST$/i,
192
+ /^SECRET/i, /^KEY$/i, /^TOKEN/i
193
+ ];
194
+ }
195
+
196
+ async initialize(semanticEngine = null) {
197
+ if (semanticEngine) {
198
+ this.semanticEngine = semanticEngine;
199
+ }
200
+ this.verbose = semanticEngine?.verbose || false;
201
+
202
+ if (this.verbose) {
203
+ console.log(`🔧 [C042 Symbol-Based] Analyzer initialized`);
204
+ }
205
+ }
206
+
207
+ async analyzeFileBasic(filePath, options = {}) {
208
+ const violations = [];
209
+
210
+ if (!this.semanticEngine?.project) {
211
+ return violations;
212
+ }
80
213
 
81
- **Option B: Heuristic Engine Rule (Universal)**
82
- For language-agnostic rules or complex pattern analysis:
214
+ try {
215
+ const sourceFile = this.semanticEngine.project.getSourceFileByFilePath(filePath);
216
+ if (!sourceFile) {
217
+ return violations;
218
+ }
83
219
 
84
- 1. **Create rule class**: `custom-rules/c042-no-hardcoded-config.js`
220
+ // Analyze variable declarations
221
+ const variableDeclarations = sourceFile.getVariableDeclarations();
222
+ for (const declaration of variableDeclarations) {
223
+ const violation = this.analyzeVariableDeclaration(declaration, filePath);
224
+ if (violation) {
225
+ violations.push(violation);
226
+ }
227
+ }
85
228
 
86
- #### **Step 2: Implement Rule Logic**
229
+ return violations;
230
+ } catch (error) {
231
+ if (this.verbose) {
232
+ console.warn(`⚠️ [C042 Symbol-Based] Analysis failed for ${filePath}:`, error.message);
233
+ }
234
+ return violations;
235
+ }
236
+ }
237
+
238
+ analyzeVariableDeclaration(declaration, filePath) {
239
+ const name = declaration.getName();
240
+ const initializer = declaration.getInitializer();
241
+
242
+ // Check if variable name suggests configuration
243
+ if (!this.isConfigVariable(name)) {
244
+ return null;
245
+ }
246
+
247
+ // Check if value is hardcoded
248
+ if (this.isHardcodedValue(initializer)) {
249
+ const startLineNumber = declaration.getStartLineNumber();
250
+
251
+ return {
252
+ ruleId: this.ruleId,
253
+ severity: 'warning',
254
+ message: `Configuration variable '${name}' should not be hardcoded`,
255
+ source: this.ruleId,
256
+ file: filePath,
257
+ line: startLineNumber,
258
+ column: declaration.getStart() - declaration.getStartLinePos() + 1,
259
+ description: `Symbol-based analysis detected hardcoded configuration value. Use environment variables or config files.`,
260
+ suggestion: `Use process.env.${name} or load from configuration file`,
261
+ category: 'maintainability'
262
+ };
263
+ }
264
+
265
+ return null;
266
+ }
267
+
268
+ isConfigVariable(name) {
269
+ return this.configPatterns.some(pattern => pattern.test(name));
270
+ }
271
+
272
+ isHardcodedValue(initializer) {
273
+ if (!initializer) return false;
274
+
275
+ // Check for literal values (strings, numbers)
276
+ if (initializer.getKind() === ts.SyntaxKind.StringLiteral ||
277
+ initializer.getKind() === ts.SyntaxKind.NumericLiteral) {
278
+ return true;
279
+ }
280
+
281
+ // Check for property access to process.env
282
+ if (initializer.getText().includes('process.env')) {
283
+ return false;
284
+ }
285
+
286
+ return false;
287
+ }
288
+ }
289
+
290
+ module.exports = C042SymbolBasedAnalyzer;
291
+ ```
292
+
293
+ #### **Step 5: Implement Regex-Based Analyzer (Fallback)**
87
294
 
88
- **For ESLint Engine Rules:**
89
295
  ```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'
296
+ // rules/common/C042_no_hardcoded_config/regex-based-analyzer.js
297
+ class C042RegexBasedAnalyzer {
298
+ constructor(semanticEngine = null) {
299
+ this.ruleId = 'C042';
300
+ this.ruleName = 'No Hardcoded Configuration Values (Regex-Based)';
301
+ this.semanticEngine = semanticEngine;
302
+ this.verbose = false;
303
+
304
+ // Patterns for hardcoded config detection
305
+ this.hardcodedPatterns = [
306
+ /const\s+(API_\w+|DATABASE_\w+|DB_\w+)\s*=\s*["'][^"']+["']/gi,
307
+ /const\s+(MAX_\w+|MIN_\w+|LIMIT_\w+)\s*=\s*\d+/gi,
308
+ /const\s+(TIMEOUT|PORT|HOST)\s*=\s*["']\w+["']|\d+/gi
309
+ ];
310
+ }
311
+
312
+ async initialize(semanticEngine = null) {
313
+ if (semanticEngine) {
314
+ this.semanticEngine = semanticEngine;
315
+ }
316
+ this.verbose = semanticEngine?.verbose || false;
317
+
318
+ if (this.verbose) {
319
+ console.log(`🔧 [C042 Regex-Based] Analyzer initialized`);
320
+ }
321
+ }
322
+
323
+ async analyzeFileBasic(filePath, options = {}) {
324
+ const fs = require('fs');
325
+ const violations = [];
326
+
327
+ if (!fs.existsSync(filePath)) {
328
+ return violations;
329
+ }
330
+
331
+ const content = fs.readFileSync(filePath, 'utf8');
332
+ const lines = content.split('\n');
333
+
334
+ for (let i = 0; i < lines.length; i++) {
335
+ const line = lines[i];
336
+
337
+ for (const pattern of this.hardcodedPatterns) {
338
+ pattern.lastIndex = 0; // Reset regex
339
+ let match;
340
+
341
+ while ((match = pattern.exec(line)) !== null) {
342
+ // Skip if using process.env
343
+ if (line.includes('process.env')) {
344
+ continue;
345
+ }
346
+
347
+ violations.push({
348
+ ruleId: this.ruleId,
349
+ severity: 'warning',
350
+ message: `Configuration variable '${match[1]}' should not be hardcoded`,
351
+ source: this.ruleId,
352
+ file: filePath,
353
+ line: i + 1,
354
+ column: match.index + 1,
355
+ description: `[REGEX-FALLBACK] Hardcoded configuration detected. Use environment variables or config files.`,
356
+ suggestion: `Use process.env.${match[1]} or load from configuration file`,
357
+ category: 'maintainability'
105
358
  });
106
359
  }
107
360
  }
108
- };
361
+ }
362
+
363
+ return violations;
109
364
  }
110
- };
365
+
366
+ async analyze(files, language, options = {}) {
367
+ const violations = [];
368
+
369
+ for (const filePath of files) {
370
+ try {
371
+ const fileViolations = await this.analyzeFileBasic(filePath, options);
372
+ violations.push(...fileViolations);
373
+ } catch (error) {
374
+ if (this.verbose) {
375
+ console.warn(`❌ [C042 Regex] Analysis failed for ${filePath}:`, error.message);
376
+ }
377
+ }
378
+ }
379
+
380
+ return violations;
381
+ }
382
+ }
383
+
384
+ module.exports = C042RegexBasedAnalyzer;
111
385
  ```
112
386
 
113
- **For Heuristic Engine Rules:**
387
+ #### **Step 6: Create Rule Configuration**
388
+
389
+ ```json
390
+ // rules/common/C042_no_hardcoded_config/config.json
391
+ {
392
+ "ruleId": "C042",
393
+ "name": "No Hardcoded Configuration Values",
394
+ "description": "Avoid hardcoding configuration values in business logic",
395
+ "category": "maintainability",
396
+ "severity": "warning",
397
+ "languages": ["typescript", "javascript"],
398
+ "version": "1.0.0",
399
+ "tags": ["configuration", "maintainability", "environment"],
400
+ "patterns": {
401
+ "configVariables": [
402
+ "API_", "DATABASE_", "DB_", "MAX_", "MIN_", "LIMIT_",
403
+ "TIMEOUT", "PORT", "HOST", "SECRET", "KEY", "TOKEN"
404
+ ],
405
+ "excludePatterns": [
406
+ "process.env", "config.", "getConfig(", "loadConfig("
407
+ ]
408
+ },
409
+ "examples": {
410
+ "bad": [
411
+ "const API_URL = 'https://api.example.com';",
412
+ "const MAX_RETRIES = 5;",
413
+ "const DATABASE_PASSWORD = 'secret123';"
414
+ ],
415
+ "good": [
416
+ "const API_URL = process.env.API_URL;",
417
+ "const MAX_RETRIES = parseInt(process.env.MAX_RETRIES || '3');",
418
+ "const config = loadConfigFromFile();"
419
+ ]
420
+ }
421
+ }
422
+ ```
423
+
424
+ #### **Step 7: Document Analysis Strategy**
425
+
426
+ ```markdown
427
+ <!-- rules/common/C042_no_hardcoded_config/STRATEGY.md -->
428
+ # C042 Analysis Strategy: No Hardcoded Configuration Values
429
+
430
+ ## Overview
431
+ Hybrid approach using symbol-based analysis as primary with regex fallback.
432
+
433
+ ## Symbol-Based Analysis (Primary)
434
+ - Uses ts-morph AST to analyze variable declarations
435
+ - Detects configuration variable patterns by name
436
+ - Checks initializer values for hardcoded literals
437
+ - Excludes process.env and config function calls
438
+
439
+ ## Regex-Based Analysis (Fallback)
440
+ - Pattern matching for common hardcoded config scenarios
441
+ - Simpler but broader detection
442
+ - Used when symbol analysis unavailable
443
+
444
+ ## Strategy Selection
445
+ 1. **Symbol-based**: When ts-morph project available (95% accuracy)
446
+ 2. **Regex-fallback**: When symbol analysis fails (80% accuracy)
447
+
448
+ ## Testing Approach
449
+ Test both analyzers independently and verify hybrid orchestration.
450
+ ```
451
+
452
+ ---
453
+
454
+ ## 🆕 **Modern Rule Implementation Guide (2025)**
455
+
456
+ Based on the successful C035 implementation, here's the **current recommended approach** for adding new rules:
457
+
458
+ ### **Critical Success Patterns**
459
+
460
+ #### **✅ 1. Constructor Pattern (REQUIRED)**
114
461
  ```javascript
115
- // custom-rules/c042-no-hardcoded-config.js
116
- const SemanticRuleBase = require('../core/semantic-rule-base');
462
+ // ✅ CORRECT - Works with semantic engine injection
463
+ class C042Analyzer {
464
+ constructor(options = {}) {
465
+ this.semanticEngine = options.semanticEngine || null;
466
+ this.verbose = options.verbose || false;
467
+ // ...
468
+ }
469
+ }
117
470
 
118
- class NoHardcodedConfigRule extends SemanticRuleBase {
119
- constructor() {
120
- super('C042', 'No Hardcoded Configuration Values');
471
+ // WRONG - Causes semantic engine injection failure
472
+ class C042Analyzer {
473
+ constructor(semanticEngine = null) {
474
+ this.semanticEngine = semanticEngine;
475
+ // ...
121
476
  }
477
+ }
478
+ ```
122
479
 
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');
480
+ #### **✅ 2. Registry Configuration (REQUIRED)**
481
+
482
+ **Enhanced Rules Registry** (`config/rules/enhanced-rules-registry.json`):
483
+ ```json
484
+ {
485
+ "C042": {
486
+ "name": "No Hardcoded Configuration Values",
487
+ "description": "Avoid hardcoding configuration values in business logic",
488
+ "category": "maintainability",
489
+ "severity": "warning",
490
+ "languages": ["typescript", "javascript", "dart", "kotlin"],
491
+ "analyzer": "./rules/common/C042_no_hardcoded_config/analyzer.js",
492
+ "config": "./rules/common/C042_no_hardcoded_config/config.json",
493
+ "version": "1.0.0",
494
+ "status": "stable",
495
+ "tags": ["configuration", "hardcoding", "maintainability"],
496
+ "engineMappings": {
497
+ "eslint": ["no-magic-numbers", "@typescript-eslint/no-magic-numbers"]
127
498
  }
128
- return null;
499
+ }
500
+ }
501
+ ```
502
+
503
+ **Rule Analysis Strategies** (`config/rule-analysis-strategies.js`):
504
+ ```javascript
505
+ module.exports = {
506
+ hybridOptimal: {
507
+ 'C042': {
508
+ reason: 'Configuration detection requires symbol resolution + pattern matching',
509
+ methods: ['semantic', 'regex'],
510
+ strategy: 'semantic-primary-regex-fallback',
511
+ accuracy: { semantic: 90, regex: 75, combined: 95 }
512
+ }
513
+ }
514
+ }
515
+ ```
516
+
517
+ #### **✅ 3. Hybrid Architecture Template**
518
+
519
+ **Main Analyzer** (`analyzer.js`):
520
+ ```javascript
521
+ const C042SymbolBasedAnalyzer = require('./symbol-based-analyzer.js');
522
+ const C042RegexBasedAnalyzer = require('./regex-based-analyzer.js');
523
+
524
+ class C042Analyzer {
525
+ constructor(options = {}) {
526
+ if (process.env.SUNLINT_DEBUG) {
527
+ console.log(`🔧 [C042] Constructor called with options:`, !!options);
528
+ }
529
+
530
+ this.ruleId = 'C042';
531
+ this.semanticEngine = options.semanticEngine || null;
532
+ this.verbose = options.verbose || false;
533
+
534
+ // Initialize analyzers with THIS.semanticEngine
535
+ this.symbolAnalyzer = new C042SymbolBasedAnalyzer(this.semanticEngine);
536
+ this.regexAnalyzer = new C042RegexBasedAnalyzer(this.semanticEngine);
537
+
538
+ this.config = {
539
+ useSymbolBased: true,
540
+ fallbackToRegex: true,
541
+ symbolBasedOnly: false
542
+ };
129
543
  }
130
544
 
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);
545
+ async analyze(files, language = 'javascript', options = {}) {
546
+ const allViolations = [];
547
+
548
+ for (const filePath of files) {
549
+ const violations = await this.analyzeFile(filePath, options);
550
+ allViolations.push(...violations);
551
+ }
552
+
553
+ return allViolations;
554
+ }
555
+
556
+ async analyzeFile(filePath, options = {}) {
557
+ // 1. Try Symbol-based analysis first (primary)
558
+ if (this.config.useSymbolBased &&
559
+ this.semanticEngine?.project &&
560
+ this.semanticEngine?.initialized) {
561
+ try {
562
+ const sourceFile = this.semanticEngine.project.getSourceFile(filePath);
563
+ if (sourceFile) {
564
+ const violations = await this.symbolAnalyzer.analyzeFileWithSymbols(filePath, options);
565
+ violations.forEach(v => v.analysisStrategy = 'symbol-based');
566
+ return violations;
567
+ }
568
+ } catch (error) {
569
+ console.warn(`⚠️ [C042] Symbol analysis failed: ${error.message}`);
570
+ }
571
+ }
572
+
573
+ // 2. Fallback to regex-based analysis
574
+ if (this.config.fallbackToRegex) {
575
+ const violations = await this.regexAnalyzer.analyzeFileBasic(filePath, options);
576
+ violations.forEach(v => v.analysisStrategy = 'regex-based');
577
+ return violations;
578
+ }
579
+
580
+ return [];
136
581
  }
137
582
  }
138
583
 
139
- module.exports = NoHardcodedConfigRule;
584
+ module.exports = C042Analyzer;
585
+ ```
586
+
587
+ #### **✅ 4. Testing & Validation**
588
+
589
+ **Debug Output Verification**:
590
+ ```bash
591
+ SUNLINT_DEBUG=true node cli.js --input test-files/c042-test.js --rules C042 --engine=heuristic --debug
140
592
  ```
141
593
 
142
- #### **Step 3: Update Rule Registry**
594
+ **Expected Output**:
595
+ ```
596
+ 🔧 [HeuristicEngine] Rule C042: semantic (approach: hybrid-combined)
597
+ 🔧 [C042] Constructor called with options: true
598
+ 🔧 [C042] Options type: object [ 'verbose', 'semanticEngine' ]
599
+ 🔧 [C042] Trying symbol-based analysis...
600
+ ✅ [C042] Symbol-based analysis: X violations
601
+ ```
602
+
603
+ #### **✅ 5. Common Pitfalls & Solutions**
604
+
605
+ | ❌ Problem | ✅ Solution |
606
+ |------------|-------------|
607
+ | `constructor(semanticEngine)` | `constructor(options = {})` |
608
+ | Missing from `rule-analysis-strategies.js` | Add to `hybridOptimal` section |
609
+ | `ast (approach: ast-primary)` output | Ensure rule in strategies config |
610
+ | `this.semanticEngine?.project: false` | Check engine injection & initialization |
611
+ | No debug output from constructor | Verify constructor signature |
612
+
613
+ #### **✅ 6. Validation Checklist**
614
+
615
+ Before submitting a new rule:
616
+
617
+ - [ ] Constructor uses `options = {}` pattern
618
+ - [ ] Rule registered in `enhanced-rules-registry.json`
619
+ - [ ] Strategy defined in `rule-analysis-strategies.js` `hybridOptimal`
620
+ - [ ] Symbol-based analyzer implemented with ts-morph
621
+ - [ ] Regex-based analyzer implemented with pattern matching
622
+ - [ ] Debug output shows `semantic (approach: hybrid-combined)`
623
+ - [ ] Test cases detect expected violations accurately
624
+ - [ ] No modifications to engine core files (registry-driven only)
625
+ - [ ] Performance acceptable for large codebases
626
+
627
+ ---
628
+
629
+ ## 📚 **Legacy Implementation Examples**
630
+
631
+ The following examples show older patterns for reference, but **use the Modern Guide above** for new rules:
632
+
633
+ #### **Step 7: Document Analysis Strategy**
143
634
 
144
- Add rule definition to origin rules:
145
635
  ```markdown
146
- <!-- origin-rules/common-en.md -->
147
- ## C042: No Hardcoded Configuration Values
636
+ <!-- rules/common/C042_no_hardcoded_config/STRATEGY.md -->
637
+ # C042 Analysis Strategy: No Hardcoded Configuration Values
148
638
 
149
- **Category**: Maintainability
150
- **Severity**: Warning
639
+ ## Overview
640
+ Hybrid approach using symbol-based analysis as primary with regex fallback.
641
+
642
+ ## Symbol-Based Analysis (Primary)
643
+ - Uses ts-morph AST to analyze variable declarations
644
+ - Detects configuration variable patterns by name
645
+ - Checks initializer values for hardcoded literals
646
+ - Excludes process.env and config function calls
647
+
648
+ ## Regex-Based Analysis (Fallback)
649
+ - Pattern matching for common hardcoded config scenarios
650
+ - Simpler but broader detection
651
+ - Used when symbol analysis unavailable
652
+
653
+ ## Strategy Selection
654
+ 1. **Symbol-based**: When ts-morph project available (95% accuracy)
655
+ 2. **Regex-fallback**: When symbol analysis fails (80% accuracy)
656
+
657
+ ## Testing Approach
658
+ Test both analyzers independently and verify hybrid orchestration.
659
+ ```
660
+
661
+ #### **Step 8: Register Rule in Rules Registry**
662
+
663
+ ```json
664
+ // config/rules/rules-registry.json
665
+ {
666
+ "rules": {
667
+ "C042": {
668
+ "name": "No Hardcoded Configuration Values",
669
+ "description": "Avoid hardcoding configuration values in business logic",
670
+ "category": "maintainability",
671
+ "severity": "warning",
672
+ "languages": ["typescript", "javascript"],
673
+ "analyzer": "./rules/common/C042_no_hardcoded_config/analyzer.js",
674
+ "config": "./rules/common/C042_no_hardcoded_config/config.json",
675
+ "version": "1.0.0",
676
+ "status": "experimental",
677
+ "tags": ["configuration", "maintainability", "environment"]
678
+ }
679
+ }
680
+ }
681
+ ```
682
+
683
+ #### **Step 9: Add to Enhanced Rules Registry**
684
+
685
+ ```javascript
686
+ // core/enhanced-rules-registry.js
687
+ loadEnginePreferences(options = {}) {
688
+ const preferences = {
689
+ // ... existing rules ...
690
+ 'C042': ['heuristic', 'openai'], // Symbol + regex hybrid
691
+ // ... rest of rules ...
692
+ };
693
+ }
694
+ ```
695
+
696
+ #### **Step 10: Add to Analysis Strategies**
697
+
698
+ ```javascript
699
+ // config/rule-analysis-strategies.js
700
+ module.exports = {
701
+ astPreferred: {
702
+ // ... existing rules ...
703
+ 'C042': {
704
+ reason: 'Configuration detection requires precise symbol analysis for variable declarations',
705
+ methods: ['ast', 'regex'],
706
+ accuracy: { ast: 95, regex: 80 }
707
+ }
708
+ }
709
+ };
710
+ ```
151
711
 
152
712
  **Description**: Avoid hardcoding configuration values in business logic
153
713
 
@@ -683,6 +1243,571 @@ node cli.js --rule=CXXX --input=test/fixtures
683
1243
  **For Heuristic rules**: Create files in `custom-rules/`
684
1244
  **For documentation**: Add to `origin-rules/` markdown files
685
1245
 
1246
+ ---
1247
+
1248
+ ## 🔬 **Modern Rule Development Guide (2024)**
1249
+
1250
+ *This section provides a comprehensive, step-by-step guide for implementing new rules using the modern hybrid architecture pattern (symbol-based + regex fallback), based on the successful C035 implementation.*
1251
+
1252
+ ### **Quick Start: Creating a New Rule**
1253
+
1254
+ #### **Step 1: Create Rule Directory Structure**
1255
+
1256
+ ```bash
1257
+ # Example: Creating C042 (No Hardcoded Configuration Values)
1258
+ mkdir -p rules/common/C042_no_hardcoded_config
1259
+ cd rules/common/C042_no_hardcoded_config
1260
+ ```
1261
+
1262
+ #### **Step 2: Implement Main Analyzer (Hybrid Orchestrator)**
1263
+
1264
+ ```javascript
1265
+ // analyzer.js - Main hybrid orchestrator
1266
+ const SymbolBasedAnalyzer = require('./symbol-based-analyzer');
1267
+ const RegexBasedAnalyzer = require('./regex-based-analyzer');
1268
+
1269
+ class C042NoHardcodedConfigAnalyzer {
1270
+ constructor(verbose = false) {
1271
+ this.verbose = verbose;
1272
+ this.symbolAnalyzer = new SymbolBasedAnalyzer(verbose);
1273
+ this.regexAnalyzer = new RegexBasedAnalyzer(verbose);
1274
+ }
1275
+
1276
+ async analyzeFileBasic(filePath, options = {}) {
1277
+ if (this.verbose) {
1278
+ console.log(`🔍 [C042] Analyzing file: ${filePath}`);
1279
+ }
1280
+
1281
+ try {
1282
+ // Primary: Symbol-based analysis
1283
+ const violations = await this.symbolAnalyzer.analyzeFileBasic(filePath, options);
1284
+
1285
+ if (this.verbose) {
1286
+ console.log(`✅ [C042] Symbol-based analysis completed. Found ${violations.length} violations.`);
1287
+ }
1288
+
1289
+ return violations;
1290
+ } catch (error) {
1291
+ if (this.verbose) {
1292
+ console.warn(`⚠️ [C042] Symbol analysis failed: ${error.message}`);
1293
+ console.log(`🔄 [C042] Falling back to regex analysis...`);
1294
+ }
1295
+
1296
+ // Fallback: Regex-based analysis
1297
+ try {
1298
+ const violations = await this.regexAnalyzer.analyzeFileBasic(filePath, options);
1299
+
1300
+ if (this.verbose) {
1301
+ console.log(`✅ [C042] Regex-fallback analysis completed. Found ${violations.length} violations.`);
1302
+ }
1303
+
1304
+ return violations;
1305
+ } catch (fallbackError) {
1306
+ if (this.verbose) {
1307
+ console.error(`❌ [C042] Both symbol and regex analysis failed: ${fallbackError.message}`);
1308
+ }
1309
+ return [];
1310
+ }
1311
+ }
1312
+ }
1313
+ }
1314
+
1315
+ module.exports = C042NoHardcodedConfigAnalyzer;
1316
+ ```
1317
+
1318
+ #### **Step 3: Implement Symbol-Based Analyzer (Primary)**
1319
+
1320
+ ```javascript
1321
+ // symbol-based-analyzer.js - High-accuracy AST analysis
1322
+ const { Project } = require('ts-morph');
1323
+
1324
+ class C042SymbolBasedAnalyzer {
1325
+ constructor(verbose = false) {
1326
+ this.verbose = verbose;
1327
+ this.project = new Project({
1328
+ useInMemoryFileSystem: true,
1329
+ compilerOptions: {
1330
+ allowJs: true,
1331
+ checkJs: false,
1332
+ },
1333
+ });
1334
+ }
1335
+
1336
+ async analyzeFileBasic(filePath, options = {}) {
1337
+ const violations = [];
1338
+
1339
+ try {
1340
+ const sourceFile = this.project.addSourceFileAtPath(filePath);
1341
+
1342
+ // Analyze variable declarations
1343
+ sourceFile.getVariableDeclarations().forEach(declaration => {
1344
+ const initializer = declaration.getInitializer();
1345
+ if (initializer && this.isHardcodedConfig(initializer, declaration.getName())) {
1346
+ violations.push({
1347
+ line: declaration.getStartLineNumber(),
1348
+ column: declaration.getStart() - declaration.getStartLinePos() + 1,
1349
+ message: `Hardcoded configuration value detected in variable '${declaration.getName()}'`,
1350
+ severity: 'warning',
1351
+ rule: 'C042'
1352
+ });
1353
+ }
1354
+ });
1355
+
1356
+ // Analyze property assignments
1357
+ sourceFile.getDescendantsOfKind(ts.SyntaxKind.PropertyAssignment).forEach(prop => {
1358
+ const value = prop.getInitializer();
1359
+ if (value && this.isHardcodedConfig(value, prop.getName())) {
1360
+ violations.push({
1361
+ line: prop.getStartLineNumber(),
1362
+ column: prop.getStart() - prop.getStartLinePos() + 1,
1363
+ message: `Hardcoded configuration value in property '${prop.getName()}'`,
1364
+ severity: 'warning',
1365
+ rule: 'C042'
1366
+ });
1367
+ }
1368
+ });
1369
+
1370
+ this.project.removeSourceFile(sourceFile);
1371
+ return violations;
1372
+ } catch (error) {
1373
+ throw new Error(`Symbol analysis failed: ${error.message}`);
1374
+ }
1375
+ }
1376
+
1377
+ isHardcodedConfig(node, name) {
1378
+ // Check if the value looks like configuration
1379
+ const configPatterns = [
1380
+ /url/i, /host/i, /port/i, /timeout/i, /secret/i,
1381
+ /api[_-]?key/i, /password/i, /connection/i, /endpoint/i
1382
+ ];
1383
+
1384
+ const nameMatches = configPatterns.some(pattern => pattern.test(name));
1385
+
1386
+ if (!nameMatches) return false;
1387
+
1388
+ // Check if value is hardcoded (string/number literal)
1389
+ return node.getKind() === ts.SyntaxKind.StringLiteral ||
1390
+ node.getKind() === ts.SyntaxKind.NumericLiteral;
1391
+ }
1392
+ }
1393
+
1394
+ module.exports = C042SymbolBasedAnalyzer;
1395
+ ```
1396
+
1397
+ #### **Step 4: Implement Regex-Based Analyzer (Fallback)**
1398
+
1399
+ ```javascript
1400
+ // regex-based-analyzer.js - Broad coverage pattern matching
1401
+ const fs = require('fs');
1402
+
1403
+ class C042RegexBasedAnalyzer {
1404
+ constructor(verbose = false) {
1405
+ this.verbose = verbose;
1406
+
1407
+ // Configuration-related patterns
1408
+ this.configPatterns = [
1409
+ /(?:const|let|var)\s+(\w*(?:url|host|port|timeout|secret|key|password|connection|endpoint)\w*)\s*=\s*['"`]([^'"`]+)['"`]/gi,
1410
+ /(\w*(?:url|host|port|timeout|secret|key|password|connection|endpoint)\w*)\s*:\s*['"`]([^'"`]+)['"`]/gi,
1411
+ /(\w*(?:url|host|port|timeout|secret|key|password|connection|endpoint)\w*)\s*=\s*(\d+)/gi
1412
+ ];
1413
+ }
1414
+
1415
+ async analyzeFileBasic(filePath, options = {}) {
1416
+ const violations = [];
1417
+
1418
+ try {
1419
+ const content = fs.readFileSync(filePath, 'utf8');
1420
+ const lines = content.split('\n');
1421
+
1422
+ this.configPatterns.forEach(pattern => {
1423
+ lines.forEach((line, index) => {
1424
+ let match;
1425
+ while ((match = pattern.exec(line)) !== null) {
1426
+ const variableName = match[1];
1427
+ const value = match[2];
1428
+
1429
+ if (this.isLikelyHardcodedConfig(variableName, value)) {
1430
+ violations.push({
1431
+ line: index + 1,
1432
+ column: match.index + 1,
1433
+ message: `Potential hardcoded configuration: '${variableName}' = '${value}'`,
1434
+ severity: 'warning',
1435
+ rule: 'C042'
1436
+ });
1437
+ }
1438
+ }
1439
+ pattern.lastIndex = 0; // Reset regex
1440
+ });
1441
+ });
1442
+
1443
+ return violations;
1444
+ } catch (error) {
1445
+ throw new Error(`Regex analysis failed: ${error.message}`);
1446
+ }
1447
+ }
1448
+
1449
+ isLikelyHardcodedConfig(name, value) {
1450
+ // Skip obvious non-config values
1451
+ const skipPatterns = [
1452
+ /^(true|false|null|undefined)$/i,
1453
+ /^process\.env\./i,
1454
+ /^require\(/i,
1455
+ /^\w+\(/i // Function calls
1456
+ ];
1457
+
1458
+ return !skipPatterns.some(pattern => pattern.test(value));
1459
+ }
1460
+ }
1461
+
1462
+ module.exports = C042RegexBasedAnalyzer;
1463
+ ```
1464
+
1465
+ #### **Step 5: Create Rule Configuration**
1466
+
1467
+ ```json
1468
+ // config.json - Rule metadata and examples
1469
+ {
1470
+ "id": "C042",
1471
+ "name": "No Hardcoded Configuration Values",
1472
+ "category": "Maintainability",
1473
+ "severity": "warning",
1474
+ "description": "Detects hardcoded configuration values that should use environment variables or config files",
1475
+ "rationale": "Hardcoded configuration makes applications less flexible and harder to deploy across different environments",
1476
+ "examples": {
1477
+ "bad": [
1478
+ "const API_URL = 'https://api.example.com';",
1479
+ "const DB_HOST = 'localhost';",
1480
+ "const MAX_CONNECTIONS = 100;",
1481
+ "config: { port: 3000, host: 'localhost' }"
1482
+ ],
1483
+ "good": [
1484
+ "const API_URL = process.env.API_URL;",
1485
+ "const DB_HOST = process.env.DB_HOST || 'localhost';",
1486
+ "const config = loadConfigFromFile();",
1487
+ "const PORT = parseInt(process.env.PORT || '3000');"
1488
+ ]
1489
+ },
1490
+ "tags": ["configuration", "deployment", "security", "maintainability"],
1491
+ "accuracy": {
1492
+ "symbol_based": "high",
1493
+ "regex_based": "medium"
1494
+ },
1495
+ "performance": {
1496
+ "symbol_based": "medium",
1497
+ "regex_based": "fast"
1498
+ }
1499
+ }
1500
+ ```
1501
+
1502
+ #### **Step 6: Document Analysis Strategy**
1503
+
1504
+ ```markdown
1505
+ <!-- STRATEGY.md - Analysis approach documentation -->
1506
+ # C042: No Hardcoded Configuration Values - Analysis Strategy
1507
+
1508
+ ## Overview
1509
+ This rule detects hardcoded configuration values using a hybrid approach combining symbol-based AST analysis with regex-based pattern matching.
1510
+
1511
+ ## Analysis Approaches
1512
+
1513
+ ### Symbol-Based Analysis (Primary)
1514
+ - **Tool**: ts-morph AST parser
1515
+ - **Accuracy**: High (95%+)
1516
+ - **Coverage**: Variable declarations, property assignments
1517
+ - **Strengths**:
1518
+ - Understands code context
1519
+ - Low false positives
1520
+ - Handles complex expressions
1521
+ - **Limitations**:
1522
+ - Requires valid syntax
1523
+ - Slower performance
1524
+
1525
+ ### Regex-Based Analysis (Fallback)
1526
+ - **Tool**: Regular expressions
1527
+ - **Accuracy**: Medium (80%+)
1528
+ - **Coverage**: String/number patterns in config-like names
1529
+ - **Strengths**:
1530
+ - Fast execution
1531
+ - Works with any file
1532
+ - Broad pattern coverage
1533
+ - **Limitations**:
1534
+ - Higher false positives
1535
+ - Limited context understanding
1536
+
1537
+ ## Detection Patterns
1538
+
1539
+ ### Configuration Indicators
1540
+ - Variable/property names containing: url, host, port, timeout, secret, key, password, connection, endpoint
1541
+ - Literal string/number values
1542
+ - Assignment patterns
1543
+
1544
+ ### Exclusions
1545
+ - Environment variable references (process.env.*)
1546
+ - Function calls
1547
+ - Boolean/null literals
1548
+ - Computed values
1549
+
1550
+ ## Testing Strategy
1551
+ - Unit tests for each analyzer
1552
+ - Integration tests for hybrid orchestration
1553
+ - Real-world project validation
1554
+ - Performance benchmarking
1555
+ ```
1556
+
1557
+ #### **Step 7: Add to Rules Registry**
1558
+
1559
+ ```json
1560
+ // config/rules/rules-registry.json - Add rule definition
1561
+ {
1562
+ "C042": {
1563
+ "id": "C042",
1564
+ "name": "No Hardcoded Configuration Values",
1565
+ "category": "Maintainability",
1566
+ "severity": "warning",
1567
+ "description": "Detects hardcoded configuration values that should use environment variables or config files",
1568
+ "engine": "heuristic",
1569
+ "analyzerPath": "rules/common/C042_no_hardcoded_config/analyzer.js",
1570
+ "configPath": "rules/common/C042_no_hardcoded_config/config.json",
1571
+ "enabled": true,
1572
+ "languages": ["javascript", "typescript"],
1573
+ "tags": ["configuration", "deployment", "security"]
1574
+ }
1575
+ }
1576
+ ```
1577
+
1578
+ #### **Step 8: Register with Enhanced Rules Registry**
1579
+
1580
+ ```javascript
1581
+ // core/enhanced-rules-registry.js - Add engine preferences
1582
+ const enginePreferences = {
1583
+ // ... existing rules
1584
+ 'C042': ['heuristic'], // Add your rule here
1585
+ };
1586
+ ```
1587
+
1588
+ #### **Step 9: Add to Analysis Strategies**
1589
+
1590
+ ```javascript
1591
+ // config/rule-analysis-strategies.js - Add to AST preferred rules
1592
+ const strategies = {
1593
+ astPreferred: [
1594
+ // ... existing rules
1595
+ 'C042', // Add your rule here
1596
+ ],
1597
+ regexOnly: [
1598
+ // Rules that only use regex
1599
+ ],
1600
+ hybridOnly: [
1601
+ // Rules requiring both approaches
1602
+ ]
1603
+ };
1604
+ ```
1605
+
1606
+ #### **Step 10: Create Test Script for Direct Testing**
1607
+
1608
+ ```javascript
1609
+ // test-c042-direct.js - Direct analyzer testing
1610
+ const C042Analyzer = require('./rules/common/C042_no_hardcoded_config/analyzer');
1611
+
1612
+ async function testC042() {
1613
+ const analyzer = new C042Analyzer(true); // Enable verbose mode
1614
+
1615
+ try {
1616
+ const violations = await analyzer.analyzeFileBasic('test-files/c042-test.js');
1617
+ console.log(`\n📊 C042 Analysis Results:`);
1618
+ console.log(` Found ${violations.length} violations`);
1619
+
1620
+ violations.forEach((violation, index) => {
1621
+ console.log(` ${index + 1}. Line ${violation.line}: ${violation.message}`);
1622
+ });
1623
+ } catch (error) {
1624
+ console.error('❌ C042 test failed:', error.message);
1625
+ }
1626
+ }
1627
+
1628
+ testC042();
1629
+ ```
1630
+
1631
+ #### **Step 11: Create Test File**
1632
+
1633
+ ```javascript
1634
+ // test-files/c042-test.js
1635
+ /**
1636
+ * Test file for C042 No Hardcoded Configuration Values rule
1637
+ * Contains various configuration patterns to validate analyzer
1638
+ */
1639
+
1640
+ // Good Examples: Using environment variables
1641
+ const API_URL = process.env.API_URL;
1642
+ const MAX_RETRIES = parseInt(process.env.MAX_RETRIES || '3');
1643
+ const config = loadConfigFromFile();
1644
+
1645
+ // Bad Examples: Hardcoded values (should trigger violations)
1646
+ const DATABASE_URL = 'mongodb://localhost:27017/myapp';
1647
+ const API_SECRET = 'sk-1234567890abcdef';
1648
+ const MAX_CONNECTIONS = 100;
1649
+ const TIMEOUT_MS = 5000;
1650
+
1651
+ // Edge Cases
1652
+ const DEBUG_MODE = true; // Should not trigger (not config pattern)
1653
+ const DEFAULT_CONFIG = { // Should trigger for nested hardcoded values
1654
+ port: 3000,
1655
+ host: 'localhost'
1656
+ };
1657
+
1658
+ module.exports = {
1659
+ goodConfig,
1660
+ badConfig
1661
+ };
1662
+ ```
1663
+
1664
+ #### **Step 12: Test Your Rule**
1665
+
1666
+ ```bash
1667
+ # Test the new rule
1668
+ node cli.js --rule=C042 --input=test-files/c042-test.js --verbose --engine=heuristic
1669
+
1670
+ # Expected output: Should detect 4-5 violations for hardcoded config values
1671
+
1672
+ # Test rule in real projects
1673
+ node cli.js --rule=C042 --input=src --engine=heuristic
1674
+
1675
+ # Test with different engines
1676
+ node cli.js --rule=C042 --input=test-files/c042-test.js --engine=openai
1677
+ ```
1678
+
1679
+ #### **Step 13: Validate Integration**
1680
+
1681
+ ```bash
1682
+ # Check rule is loaded
1683
+ node cli.js --rule=C042 --input=test-files/c042-test.js --verbose | grep "Loaded.*rule: C042"
1684
+
1685
+ # Verify both analyzers work
1686
+ node cli.js --rule=C042 --input=test-files/c042-test.js --verbose | grep -E "(Symbol-based|Regex-fallback)"
1687
+
1688
+ # Check for violations
1689
+ node cli.js --rule=C042 --input=test-files/c042-test.js --format=json | jq '.results[].violations | length'
1690
+ ```
1691
+
1692
+ ### **Modern Rule Development Best Practices**
1693
+
1694
+ #### **Architecture Patterns**
1695
+
1696
+ 1. **Hybrid Symbol + Regex Approach** (Recommended)
1697
+ - Primary: Symbol-based analysis (high accuracy)
1698
+ - Fallback: Regex-based analysis (broad coverage)
1699
+ - Example: C035, C033
1700
+
1701
+ 2. **Symbol-Only Approach**
1702
+ - For complex AST analysis requiring deep context
1703
+ - Higher accuracy but limited fallback
1704
+ - Example: Advanced OOP rules
1705
+
1706
+ 3. **Regex-Only Approach**
1707
+ - For simple pattern matching
1708
+ - Fast but lower accuracy
1709
+ - Example: Basic naming conventions
1710
+
1711
+ #### **Code Quality Standards for Rules**
1712
+
1713
+ - **Rule C005**: Each analyzer should have single responsibility
1714
+ - **Rule C006**: Method names should be verb-noun (e.g., `analyzeVariableDeclaration`)
1715
+ - **Rule C031**: Keep validation logic separate from detection logic
1716
+ - **Rule C035**: Log detailed information for debugging (verbose mode)
1717
+
1718
+ #### **File Structure Standards**
1719
+
1720
+ ```
1721
+ rules/common/C042_rule_name/
1722
+ ├── analyzer.js # Main hybrid orchestrator
1723
+ ├── symbol-based-analyzer.js # Primary AST analysis
1724
+ ├── regex-based-analyzer.js # Fallback pattern matching
1725
+ ├── config.json # Rule configuration
1726
+ ├── STRATEGY.md # Analysis approach documentation
1727
+ └── README.md # Rule documentation (optional)
1728
+ ```
1729
+
1730
+ #### **Error Handling Standards**
1731
+
1732
+ ```javascript
1733
+ // Always include proper error handling
1734
+ try {
1735
+ const violations = await this.symbolAnalyzer.analyzeFileBasic(filePath, options);
1736
+ return violations;
1737
+ } catch (error) {
1738
+ if (this.verbose) {
1739
+ console.warn(`⚠️ [C042] Symbol analysis failed: ${error.message}`);
1740
+ }
1741
+ // Graceful fallback to regex analysis
1742
+ }
1743
+ ```
1744
+
1745
+ #### **Testing Standards**
1746
+
1747
+ 1. **Unit Tests**: Test each analyzer independently
1748
+ 2. **Integration Tests**: Test hybrid orchestration
1749
+ 3. **Real Project Tests**: Validate on actual codebases
1750
+ 4. **Performance Tests**: Ensure reasonable execution time
1751
+
1752
+ #### **Documentation Standards**
1753
+
1754
+ - **STRATEGY.md**: Document analysis approach and accuracy
1755
+ - **config.json**: Include examples of good/bad patterns
1756
+ - **CONTRIBUTING.md**: Update with new patterns learned
1757
+ - **Inline comments**: Explain complex detection logic
1758
+
1759
+ ### **Rule Development Checklist**
1760
+
1761
+ - [ ] Created rule directory structure
1762
+ - [ ] Implemented main analyzer (hybrid orchestrator)
1763
+ - [ ] Implemented symbol-based analyzer (primary)
1764
+ - [ ] Implemented regex-based analyzer (fallback)
1765
+ - [ ] Created rule configuration (config.json)
1766
+ - [ ] Documented analysis strategy (STRATEGY.md)
1767
+ - [ ] Added to rules registry
1768
+ - [ ] Added to enhanced rules registry
1769
+ - [ ] Added to analysis strategies
1770
+ - [ ] Created test file
1771
+ - [ ] Tested rule individually
1772
+ - [ ] Tested rule integration
1773
+ - [ ] Validated on real projects
1774
+ - [ ] Updated documentation
1775
+
1776
+ ### **Common Issues and Solutions**
1777
+
1778
+ #### **Issue: Rule not loaded**
1779
+ ```bash
1780
+ # Check if rule exists in registry
1781
+ node cli.js --rule=C042 --input=test-files --verbose | grep "No compatible analyzer found for C042"
1782
+
1783
+ # Solution: Add rule to config/rules/rules-registry.json
1784
+ ```
1785
+
1786
+ #### **Issue: Symbol analysis fails**
1787
+ ```bash
1788
+ # Check semantic engine availability
1789
+ node cli.js --rule=C042 --input=test-files --verbose | grep "Symbol analysis failed"
1790
+
1791
+ # Solution: Ensure proper error handling and regex fallback
1792
+ ```
1793
+
1794
+ #### **Issue: No violations detected**
1795
+ ```bash
1796
+ # Test analyzers independently
1797
+ node test-c042-direct.js
1798
+
1799
+ # Check file patterns match expectations
1800
+ ```
1801
+
1802
+ #### **Issue: Too many false positives**
1803
+ ```bash
1804
+ # Refine detection patterns
1805
+ # Add exclusion rules
1806
+ # Test on diverse codebases
1807
+ ```
1808
+
1809
+ ---
1810
+
686
1811
  ## 🤝 **Community**
687
1812
 
688
1813
  - **Discord**: [Sun Engineering Discord](https://discord.gg/sun-engineering)