@sun-asterisk/sunlint 1.2.2 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +107 -1
  2. package/CONTRIBUTING.md +1654 -66
  3. package/README.md +19 -6
  4. package/config/ci-cd.json +54 -0
  5. package/config/development.json +56 -0
  6. package/config/engines/engines-enhanced.json +86 -0
  7. package/config/engines/semantic-config.json +114 -0
  8. package/config/eslint-rule-mapping.json +50 -38
  9. package/config/large-project.json +143 -0
  10. package/config/presets/all.json +0 -1
  11. package/config/release.json +70 -0
  12. package/config/rule-analysis-strategies.js +23 -4
  13. package/config/rules/S027-categories.json +122 -0
  14. package/config/rules/enhanced-rules-registry.json +2564 -0
  15. package/config/rules/rules-registry-generated.json +785 -837
  16. package/config/rules/rules-registry.json +13 -1
  17. package/core/adapters/sunlint-rule-adapter.js +25 -30
  18. package/core/analysis-orchestrator.js +42 -2
  19. package/core/categories.js +52 -0
  20. package/core/category-constants.js +39 -0
  21. package/core/cli-action-handler.js +53 -32
  22. package/core/cli-program.js +11 -3
  23. package/core/config-manager.js +111 -0
  24. package/core/config-merger.js +88 -0
  25. package/core/constants/categories.js +168 -0
  26. package/core/constants/defaults.js +165 -0
  27. package/core/constants/engines.js +185 -0
  28. package/core/constants/index.js +30 -0
  29. package/core/constants/rules.js +215 -0
  30. package/core/enhanced-rules-registry.js +3 -3
  31. package/core/file-targeting-service.js +128 -7
  32. package/core/interfaces/rule-plugin.interface.js +207 -0
  33. package/core/plugin-manager.js +448 -0
  34. package/core/rule-selection-service.js +42 -15
  35. package/core/semantic-engine.js +658 -0
  36. package/core/semantic-rule-base.js +433 -0
  37. package/core/unified-rule-registry.js +484 -0
  38. package/docs/COMMAND-EXAMPLES.md +134 -0
  39. package/docs/CONSTANTS-ARCHITECTURE.md +288 -0
  40. package/docs/LARGE-PROJECT-GUIDE.md +324 -0
  41. package/engines/core/base-engine.js +249 -0
  42. package/engines/engine-factory.js +275 -0
  43. package/engines/eslint-engine.js +171 -19
  44. package/engines/heuristic-engine.js +569 -78
  45. package/integrations/eslint/plugin/index.js +26 -28
  46. package/origin-rules/common-en.md +8 -8
  47. package/package.json +10 -6
  48. package/rules/common/C003_no_vague_abbreviations/analyzer.js +1 -1
  49. package/rules/common/C017_constructor_logic/analyzer.js +254 -17
  50. package/rules/common/C017_constructor_logic/semantic-analyzer.js +340 -0
  51. package/rules/common/C029_catch_block_logging/analyzer.js +17 -5
  52. package/rules/common/C033_separate_service_repository/README.md +78 -0
  53. package/rules/common/C033_separate_service_repository/analyzer.js +160 -0
  54. package/rules/common/C033_separate_service_repository/config.json +50 -0
  55. package/rules/common/C033_separate_service_repository/regex-based-analyzer.js +585 -0
  56. package/rules/common/C033_separate_service_repository/symbol-based-analyzer.js +368 -0
  57. package/rules/common/C035_error_logging_context/STRATEGY.md +99 -0
  58. package/rules/common/C035_error_logging_context/analyzer.js +230 -0
  59. package/rules/common/C035_error_logging_context/config.json +54 -0
  60. package/rules/common/C035_error_logging_context/regex-based-analyzer.js +299 -0
  61. package/rules/common/C035_error_logging_context/symbol-based-analyzer.js +454 -0
  62. package/rules/common/C040_centralized_validation/analyzer.js +165 -0
  63. package/rules/common/C040_centralized_validation/config.json +46 -0
  64. package/rules/common/C040_centralized_validation/regex-based-analyzer.js +243 -0
  65. package/rules/common/C040_centralized_validation/symbol-based-analyzer.js +416 -0
  66. package/rules/common/C047_no_duplicate_retry_logic/c047-semantic-rule.js +278 -0
  67. package/rules/common/C047_no_duplicate_retry_logic/symbol-analyzer-enhanced.js +968 -0
  68. package/rules/common/C047_no_duplicate_retry_logic/symbol-config.json +71 -0
  69. package/rules/common/{C076_single_test_behavior → C072_single_test_behavior}/analyzer.js +6 -6
  70. package/rules/common/C076_explicit_function_types/README.md +30 -0
  71. package/rules/common/C076_explicit_function_types/analyzer.js +172 -0
  72. package/rules/common/C076_explicit_function_types/config.json +15 -0
  73. package/rules/common/C076_explicit_function_types/semantic-analyzer.js +341 -0
  74. package/rules/index.js +8 -0
  75. package/rules/parser/rule-parser.js +13 -2
  76. package/rules/security/S005_no_origin_auth/README.md +226 -0
  77. package/rules/security/S005_no_origin_auth/analyzer.js +184 -0
  78. package/rules/security/S005_no_origin_auth/ast-analyzer.js +406 -0
  79. package/rules/security/S005_no_origin_auth/config.json +85 -0
  80. package/rules/security/S006_no_plaintext_recovery_codes/README.md +139 -0
  81. package/rules/security/S006_no_plaintext_recovery_codes/analyzer.js +306 -0
  82. package/rules/security/S006_no_plaintext_recovery_codes/config.json +48 -0
  83. package/rules/security/S007_no_plaintext_otp/README.md +198 -0
  84. package/rules/security/S007_no_plaintext_otp/analyzer.js +406 -0
  85. package/rules/security/S007_no_plaintext_otp/config.json +79 -0
  86. package/rules/security/S007_no_plaintext_otp/semantic-analyzer.js +609 -0
  87. package/rules/security/S007_no_plaintext_otp/semantic-config.json +195 -0
  88. package/rules/security/S007_no_plaintext_otp/semantic-wrapper.js +280 -0
  89. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +180 -366
  90. package/rules/security/S027_no_hardcoded_secrets/categories.json +153 -0
  91. package/rules/security/S027_no_hardcoded_secrets/categorized-analyzer.js +250 -0
  92. package/scripts/category-manager.js +150 -0
  93. package/scripts/generate-rules-registry.js +88 -0
  94. package/scripts/migrate-rule-registry.js +157 -0
  95. package/scripts/prepare-release.sh +1 -1
  96. package/scripts/validate-system.js +48 -0
  97. package/.sunlint.json +0 -35
  98. package/config/README.md +0 -88
  99. package/config/engines/eslint-rule-mapping.json +0 -74
  100. package/config/schemas/sunlint-schema.json +0 -0
  101. package/config/testing/test-s005-working.ts +0 -22
  102. package/core/multi-rule-runner.js +0 -0
  103. package/docs/ESLINT-INTEGRATION-STRATEGY.md +0 -392
  104. package/docs/FUTURE_PACKAGES.md +0 -83
  105. package/docs/HEURISTIC_VS_AI.md +0 -113
  106. package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +0 -112
  107. package/docs/PRODUCTION_SIZE_IMPACT.md +0 -183
  108. package/docs/RELEASE_GUIDE.md +0 -230
  109. package/docs/STANDARDIZED-CATEGORY-FILTERING.md +0 -156
  110. package/engines/tree-sitter-parser.js +0 -0
  111. package/engines/universal-ast-engine.js +0 -0
  112. package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +0 -254
  113. package/rules/common/C029_catch_block_logging/analyzer-backup.js +0 -426
  114. package/rules/common/C029_catch_block_logging/analyzer-fixed.js +0 -130
  115. package/rules/common/C029_catch_block_logging/analyzer-multi-tech.js +0 -487
  116. package/rules/common/C029_catch_block_logging/analyzer-simple.js +0 -110
  117. package/rules/common/C029_catch_block_logging/ast-analyzer-backup.js +0 -441
  118. package/rules/common/C029_catch_block_logging/ast-analyzer-new.js +0 -127
  119. package/rules/common/C029_catch_block_logging/ast-analyzer.js +0 -133
  120. package/rules/common/C029_catch_block_logging/cfg-analyzer.js +0 -408
  121. package/rules/common/C029_catch_block_logging/dataflow-analyzer.js +0 -454
  122. package/rules/common/C029_catch_block_logging/multi-language-ast-engine.js +0 -700
  123. package/rules/common/C029_catch_block_logging/pattern-learning-analyzer.js +0 -568
  124. package/rules/common/C029_catch_block_logging/semantic-analyzer.js +0 -459
@@ -1,459 +0,0 @@
1
- /**
2
- * C029 Semantic Analyzer
3
- *
4
- * Uses semantic analysis to understand the meaning and intent of error handling code
5
- * Goes beyond syntax to understand developer intent and code semantics
6
- *
7
- * Technology Showcase: Understanding code intent, not just structure
8
- */
9
-
10
- class C029SemanticAnalyzer {
11
- constructor() {
12
- this.ruleId = 'C029';
13
- this.ruleName = 'Semantic Intent-Based Catch Analysis';
14
- this.description = 'Understands developer intent in error handling through semantic analysis';
15
-
16
- // Semantic patterns for different error handling intents
17
- this.semanticPatterns = {
18
- // Intent: Ignore errors intentionally
19
- intentionalIgnore: [
20
- /catch\s*\(\s*[_][\w]*\s*\)/, // catch(_), catch(_ignored)
21
- /\/\/\s*(ignore|suppress|intentional)/i,
22
- /\/\*\s*(ignore|suppress|intentional)/i,
23
- /catch\s*\([^)]*ignored[^)]*\)/i
24
- ],
25
-
26
- // Intent: Log and continue
27
- logAndContinue: [
28
- /console\.(log|error|warn)/,
29
- /logger\.(log|error|warn)/,
30
- /log\.(error|warn|info)/
31
- ],
32
-
33
- // Intent: Transform and rethrow
34
- transformAndRethrow: [
35
- /throw\s+new\s+\w+Error/,
36
- /throw\s+.*Error\(/,
37
- /rethrow/i
38
- ],
39
-
40
- // Intent: Handle gracefully
41
- gracefulHandling: [
42
- /return\s+.*default/i,
43
- /return\s+.*fallback/i,
44
- /return\s+null/,
45
- /return\s+undefined/,
46
- /return\s+\[\]/,
47
- /return\s+\{\}/
48
- ],
49
-
50
- // Intent: Notify external systems
51
- externalNotification: [
52
- /notify/i,
53
- /alert/i,
54
- /report/i,
55
- /track/i,
56
- /analytics/i,
57
- /monitoring/i,
58
- /sentry/i,
59
- /bugsnag/i
60
- ],
61
-
62
- // Intent: Test verification
63
- testVerification: [
64
- /expect\(/,
65
- /assert\(/,
66
- /should\./,
67
- /toBe\(/,
68
- /toEqual\(/,
69
- /toThrow\(/
70
- ],
71
-
72
- // Intent: State management
73
- stateManagement: [
74
- /setState/,
75
- /dispatch/,
76
- /commit/,
77
- /rejectWithValue/,
78
- /setError/,
79
- /setLoading/
80
- ]
81
- };
82
- }
83
-
84
- async analyze(files, language, options = {}) {
85
- const violations = [];
86
- console.log(`🧠 C029 Semantic: Analyzing ${files.length} files with semantic understanding...`);
87
-
88
- for (const filePath of files) {
89
- try {
90
- const content = require('fs').readFileSync(filePath, 'utf8');
91
- const semanticViolations = await this.analyzeSemanticIntent(content, filePath, language);
92
- violations.push(...semanticViolations);
93
-
94
- } catch (error) {
95
- console.warn(`C029 Semantic skipping ${filePath}: ${error.message}`);
96
- }
97
- }
98
-
99
- return violations;
100
- }
101
-
102
- /**
103
- * Analyze semantic intent of error handling
104
- */
105
- async analyzeSemanticIntent(content, filePath, language) {
106
- const violations = [];
107
- const isTestFile = this.isTestFile(filePath);
108
-
109
- // Find all catch blocks with context
110
- const catchBlocks = this.extractCatchBlocksWithContext(content);
111
-
112
- for (const catchBlock of catchBlocks) {
113
- const semanticAnalysis = this.analyzeBlockSemantic(catchBlock, isTestFile, content);
114
-
115
- if (semanticAnalysis.isViolation) {
116
- violations.push({
117
- ruleId: this.ruleId,
118
- file: filePath,
119
- line: catchBlock.lineNumber,
120
- column: 1,
121
- message: semanticAnalysis.message,
122
- severity: semanticAnalysis.severity,
123
- code: catchBlock.code,
124
- type: semanticAnalysis.type,
125
- confidence: semanticAnalysis.confidence,
126
- suggestion: semanticAnalysis.suggestion,
127
- semanticIntent: semanticAnalysis.intent,
128
- contextAnalysis: semanticAnalysis.context
129
- });
130
- }
131
- }
132
-
133
- return violations;
134
- }
135
-
136
- /**
137
- * Extract catch blocks with surrounding context for semantic analysis
138
- */
139
- extractCatchBlocksWithContext(content) {
140
- const catchBlocks = [];
141
- const lines = content.split('\n');
142
-
143
- for (let i = 0; i < lines.length; i++) {
144
- const line = lines[i];
145
-
146
- if (this.isCatchBlockStart(line)) {
147
- const catchBlock = this.extractFullCatchBlock(lines, i);
148
-
149
- // Add surrounding context for semantic analysis
150
- const context = this.extractSurroundingContext(lines, i, catchBlock.endLine);
151
-
152
- catchBlocks.push({
153
- ...catchBlock,
154
- lineNumber: i + 1,
155
- context
156
- });
157
- }
158
- }
159
-
160
- return catchBlocks;
161
- }
162
-
163
- /**
164
- * Analyze semantic intent of a catch block
165
- */
166
- analyzeBlockSemantic(catchBlock, isTestFile, fullContent) {
167
- const blockContent = catchBlock.content;
168
- const blockCode = catchBlock.code;
169
- const context = catchBlock.context;
170
-
171
- // 1. Detect semantic intent
172
- const intent = this.detectSemanticIntent(blockContent, context, isTestFile);
173
-
174
- // 2. Validate intent appropriateness
175
- const validation = this.validateSemanticIntent(intent, catchBlock, isTestFile, fullContent);
176
-
177
- if (validation.isValid) {
178
- return { isViolation: false, intent, context: validation };
179
- }
180
-
181
- // 3. Generate semantic-aware violation
182
- return {
183
- isViolation: true,
184
- type: validation.violationType,
185
- message: validation.message,
186
- severity: validation.severity,
187
- confidence: validation.confidence,
188
- suggestion: validation.suggestion,
189
- intent,
190
- context: validation
191
- };
192
- }
193
-
194
- /**
195
- * Detect the semantic intent of error handling
196
- */
197
- detectSemanticIntent(blockContent, context, isTestFile) {
198
- const intents = [];
199
-
200
- // Check each semantic pattern category
201
- for (const [intentType, patterns] of Object.entries(this.semanticPatterns)) {
202
- for (const pattern of patterns) {
203
- if (pattern.test(blockContent) || pattern.test(context.before) || pattern.test(context.after)) {
204
- intents.push({
205
- type: intentType,
206
- confidence: this.calculateIntentConfidence(intentType, blockContent, context, isTestFile)
207
- });
208
- }
209
- }
210
- }
211
-
212
- // Handle empty catch blocks
213
- if (this.isEmpty(blockContent)) {
214
- intents.push({
215
- type: 'silentIgnore',
216
- confidence: 0.95
217
- });
218
- }
219
-
220
- // Handle unknown intent
221
- if (intents.length === 0) {
222
- intents.push({
223
- type: 'unknown',
224
- confidence: 0.1
225
- });
226
- }
227
-
228
- // Return primary intent (highest confidence)
229
- return intents.sort((a, b) => b.confidence - a.confidence)[0];
230
- }
231
-
232
- /**
233
- * Validate if the detected intent is appropriate for the context
234
- */
235
- validateSemanticIntent(intent, catchBlock, isTestFile, fullContent) {
236
- const intentType = intent.type;
237
- const confidence = intent.confidence;
238
-
239
- switch (intentType) {
240
- case 'intentionalIgnore':
241
- return this.validateIntentionalIgnore(catchBlock, confidence);
242
-
243
- case 'logAndContinue':
244
- return this.validateLogAndContinue(catchBlock, confidence);
245
-
246
- case 'transformAndRethrow':
247
- return this.validateTransformAndRethrow(catchBlock, confidence);
248
-
249
- case 'gracefulHandling':
250
- return this.validateGracefulHandling(catchBlock, confidence);
251
-
252
- case 'externalNotification':
253
- return this.validateExternalNotification(catchBlock, confidence);
254
-
255
- case 'testVerification':
256
- return this.validateTestVerification(catchBlock, isTestFile, confidence);
257
-
258
- case 'stateManagement':
259
- return this.validateStateManagement(catchBlock, confidence);
260
-
261
- case 'silentIgnore':
262
- return this.validateSilentIgnore(catchBlock, isTestFile, confidence);
263
-
264
- default:
265
- return this.validateUnknownIntent(catchBlock, confidence);
266
- }
267
- }
268
-
269
- /**
270
- * Validate intentional ignore patterns
271
- */
272
- validateIntentionalIgnore(catchBlock, confidence) {
273
- // Intentional ignore is usually acceptable if properly documented
274
- const hasDocumentation = this.hasProperDocumentation(catchBlock);
275
-
276
- if (hasDocumentation) {
277
- return { isValid: true, reason: 'documented_ignore' };
278
- }
279
-
280
- return {
281
- isValid: false,
282
- violationType: 'undocumented_ignore',
283
- message: 'Intentional error ignore should be documented with reason',
284
- severity: 'warning',
285
- confidence: confidence * 0.8,
286
- suggestion: 'Add comment explaining why error is intentionally ignored'
287
- };
288
- }
289
-
290
- /**
291
- * Validate log and continue patterns
292
- */
293
- validateLogAndContinue(catchBlock, confidence) {
294
- // Check if logging actually includes error information
295
- const hasErrorInfo = this.loggingIncludesErrorInfo(catchBlock);
296
-
297
- if (hasErrorInfo) {
298
- return { isValid: true, reason: 'proper_logging' };
299
- }
300
-
301
- return {
302
- isValid: false,
303
- violationType: 'incomplete_logging',
304
- message: 'Error logging should include error details (message, stack, context)',
305
- severity: 'warning',
306
- confidence: confidence * 0.9,
307
- suggestion: 'Include error.message, error.stack, or relevant error properties in logging'
308
- };
309
- }
310
-
311
- /**
312
- * Validate silent ignore (empty catch)
313
- */
314
- validateSilentIgnore(catchBlock, isTestFile, confidence) {
315
- // Silent ignore is usually problematic except in specific contexts
316
- if (isTestFile && this.isExpectedErrorInTest(catchBlock)) {
317
- return { isValid: true, reason: 'expected_test_error' };
318
- }
319
-
320
- return {
321
- isValid: false,
322
- violationType: 'silent_error_suppression',
323
- message: 'Silent error suppression hides bugs and makes debugging difficult',
324
- severity: 'error',
325
- confidence: confidence,
326
- suggestion: 'Add error logging, rethrowing, or explicit ignore with documentation'
327
- };
328
- }
329
-
330
- /**
331
- * Calculate confidence score for intent detection
332
- */
333
- calculateIntentConfidence(intentType, blockContent, context, isTestFile) {
334
- let confidence = 0.5; // Base confidence
335
-
336
- // Adjust based on pattern strength
337
- const patternCount = this.countMatchingPatterns(intentType, blockContent);
338
- confidence += Math.min(patternCount * 0.2, 0.4);
339
-
340
- // Adjust based on context
341
- if (isTestFile && intentType === 'testVerification') {
342
- confidence += 0.3;
343
- }
344
-
345
- // Adjust based on code quality indicators
346
- if (this.hasGoodNaming(blockContent)) {
347
- confidence += 0.1;
348
- }
349
-
350
- if (this.hasDocumentation(context)) {
351
- confidence += 0.1;
352
- }
353
-
354
- return Math.min(confidence, 1.0);
355
- }
356
-
357
- // Helper methods (simplified implementations)
358
-
359
- isCatchBlockStart(line) {
360
- return line.trim().includes('catch (') || line.trim().includes('catch(');
361
- }
362
-
363
- extractFullCatchBlock(lines, startIndex) {
364
- // Simplified catch block extraction
365
- return {
366
- content: 'catch block content',
367
- code: lines[startIndex],
368
- endLine: startIndex + 5
369
- };
370
- }
371
-
372
- extractSurroundingContext(lines, startLine, endLine) {
373
- const before = lines.slice(Math.max(0, startLine - 3), startLine).join('\n');
374
- const after = lines.slice(endLine + 1, Math.min(lines.length, endLine + 4)).join('\n');
375
-
376
- return { before, after };
377
- }
378
-
379
- isEmpty(content) {
380
- return content.trim().replace(/[{}]/g, '').trim().length === 0;
381
- }
382
-
383
- hasProperDocumentation(catchBlock) {
384
- const content = catchBlock.content + (catchBlock.context?.before || '');
385
- return /\/\/|\/\*/.test(content);
386
- }
387
-
388
- loggingIncludesErrorInfo(catchBlock) {
389
- const content = catchBlock.content;
390
- return /error\.(message|stack|name)/.test(content) || /\$\{error\}/.test(content);
391
- }
392
-
393
- isExpectedErrorInTest(catchBlock) {
394
- const context = catchBlock.context || {};
395
- return /expect.*toThrow|assertThrows|shouldThrow/.test(context.before + context.after);
396
- }
397
-
398
- countMatchingPatterns(intentType, content) {
399
- const patterns = this.semanticPatterns[intentType] || [];
400
- return patterns.filter(pattern => pattern.test(content)).length;
401
- }
402
-
403
- hasGoodNaming(content) {
404
- return /\b(error|err|exception|ex)\b/.test(content);
405
- }
406
-
407
- hasDocumentation(context) {
408
- return /\/\/|\/\*/.test((context?.before || '') + (context?.after || ''));
409
- }
410
-
411
- isTestFile(filePath) {
412
- const testPatterns = ['__tests__', '.test.', '.spec.', '/test/', '/tests/'];
413
- return testPatterns.some(pattern => filePath.includes(pattern));
414
- }
415
-
416
- // Placeholder validation methods
417
- validateTransformAndRethrow(catchBlock, confidence) {
418
- return { isValid: true, reason: 'proper_transform' };
419
- }
420
-
421
- validateGracefulHandling(catchBlock, confidence) {
422
- return { isValid: true, reason: 'graceful_handling' };
423
- }
424
-
425
- validateExternalNotification(catchBlock, confidence) {
426
- return { isValid: true, reason: 'external_notification' };
427
- }
428
-
429
- validateTestVerification(catchBlock, isTestFile, confidence) {
430
- if (!isTestFile) {
431
- return {
432
- isValid: false,
433
- violationType: 'test_code_in_production',
434
- message: 'Test-style error handling found in production code',
435
- severity: 'warning',
436
- confidence: confidence * 0.9,
437
- suggestion: 'Use proper error handling instead of test assertions'
438
- };
439
- }
440
- return { isValid: true, reason: 'valid_test_verification' };
441
- }
442
-
443
- validateStateManagement(catchBlock, confidence) {
444
- return { isValid: true, reason: 'state_management' };
445
- }
446
-
447
- validateUnknownIntent(catchBlock, confidence) {
448
- return {
449
- isValid: false,
450
- violationType: 'unclear_error_handling_intent',
451
- message: 'Error handling intent is unclear - consider explicit error handling',
452
- severity: 'info',
453
- confidence: confidence,
454
- suggestion: 'Make error handling intent clear through logging, rethrowing, or documentation'
455
- };
456
- }
457
- }
458
-
459
- module.exports = new C029SemanticAnalyzer();