@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.
- package/CHANGELOG.md +115 -1
- package/CONTRIBUTING.md +249 -605
- package/README.md +3 -4
- package/config/ci-cd.json +54 -0
- package/config/development.json +56 -0
- package/config/large-project.json +143 -0
- package/config/presets/all.json +0 -1
- package/config/release.json +70 -0
- package/config/rule-analysis-strategies.js +38 -3
- package/config/rules/enhanced-rules-registry.json +474 -1179
- package/config/rules/rules-registry-generated.json +3 -3
- package/core/cli-action-handler.js +24 -30
- package/core/cli-program.js +11 -3
- package/core/config-merger.js +29 -2
- package/core/enhanced-rules-registry.js +3 -2
- package/core/semantic-engine.js +129 -19
- package/core/semantic-rule-base.js +4 -2
- package/core/unified-rule-registry.js +1 -1
- package/docs/COMMAND-EXAMPLES.md +134 -0
- package/docs/LARGE-PROJECT-GUIDE.md +324 -0
- package/engines/heuristic-engine.js +135 -16
- package/integrations/eslint/plugin/index.js +0 -2
- package/integrations/eslint/plugin/rules/common/c003-no-vague-abbreviations.js +59 -1
- package/integrations/eslint/plugin/rules/common/c006-function-name-verb-noun.js +26 -1
- package/integrations/eslint/plugin/rules/common/c030-use-custom-error-classes.js +54 -19
- package/origin-rules/common-en.md +19 -15
- package/package.json +1 -1
- package/rules/common/C002_no_duplicate_code/analyzer.js +334 -36
- package/rules/common/C003_no_vague_abbreviations/analyzer.js +220 -35
- package/rules/common/C006_function_naming/analyzer.js +29 -3
- package/rules/common/C010_limit_block_nesting/analyzer.js +181 -337
- package/rules/common/C010_limit_block_nesting/config.json +64 -0
- package/rules/common/C010_limit_block_nesting/regex-based-analyzer.js +379 -0
- package/rules/common/C010_limit_block_nesting/symbol-based-analyzer.js +231 -0
- package/rules/common/C013_no_dead_code/analyzer.js +75 -177
- package/rules/common/C013_no_dead_code/config.json +61 -0
- package/rules/common/C013_no_dead_code/regex-based-analyzer.js +345 -0
- package/rules/common/C013_no_dead_code/symbol-based-analyzer.js +640 -0
- package/rules/common/C014_dependency_injection/analyzer.js +48 -313
- package/rules/common/C014_dependency_injection/config.json +26 -0
- package/rules/common/C014_dependency_injection/symbol-based-analyzer.js +751 -0
- package/rules/common/C017_constructor_logic/analyzer.js +254 -17
- package/rules/common/C017_constructor_logic/semantic-analyzer.js +340 -0
- package/rules/common/C018_no_throw_generic_error/analyzer.js +232 -0
- package/rules/common/C018_no_throw_generic_error/config.json +50 -0
- package/rules/common/C018_no_throw_generic_error/regex-based-analyzer.js +387 -0
- package/rules/common/C018_no_throw_generic_error/symbol-based-analyzer.js +314 -0
- package/rules/common/C019_log_level_usage/analyzer.js +110 -317
- package/rules/common/C019_log_level_usage/pattern-analyzer.js +88 -0
- package/rules/common/C019_log_level_usage/system-log-analyzer.js +1267 -0
- package/rules/common/C023_no_duplicate_variable/analyzer.js +180 -0
- package/rules/common/C023_no_duplicate_variable/config.json +50 -0
- package/rules/common/C023_no_duplicate_variable/symbol-based-analyzer.js +158 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/analyzer.js +180 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/config.json +50 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/symbol-based-analyzer.js +181 -0
- package/rules/common/C030_use_custom_error_classes/analyzer.js +200 -0
- package/rules/common/C033_separate_service_repository/README.md +78 -0
- package/rules/common/C033_separate_service_repository/analyzer.js +160 -0
- package/rules/common/C033_separate_service_repository/config.json +50 -0
- package/rules/common/C033_separate_service_repository/regex-based-analyzer.js +585 -0
- package/rules/common/C033_separate_service_repository/symbol-based-analyzer.js +368 -0
- package/rules/common/C035_error_logging_context/STRATEGY.md +99 -0
- package/rules/common/C035_error_logging_context/analyzer.js +232 -0
- package/rules/common/C035_error_logging_context/config.json +54 -0
- package/rules/common/C035_error_logging_context/regex-based-analyzer.js +299 -0
- package/rules/common/C035_error_logging_context/symbol-based-analyzer.js +454 -0
- package/rules/common/C040_centralized_validation/analyzer.js +165 -0
- package/rules/common/C040_centralized_validation/config.json +46 -0
- package/rules/common/C040_centralized_validation/regex-based-analyzer.js +243 -0
- package/rules/common/C040_centralized_validation/symbol-based-analyzer.js +416 -0
- package/rules/common/{C076_single_test_behavior → C072_single_test_behavior}/analyzer.js +6 -6
- package/rules/common/C076_explicit_function_types/README.md +30 -0
- package/rules/common/C076_explicit_function_types/analyzer.js +172 -0
- package/rules/common/C076_explicit_function_types/config.json +15 -0
- package/rules/common/C076_explicit_function_types/semantic-analyzer.js +341 -0
- package/rules/index.js +6 -1
- package/rules/parser/rule-parser.js +13 -2
- package/rules/security/S005_no_origin_auth/README.md +226 -0
- package/rules/security/S005_no_origin_auth/analyzer.js +184 -0
- package/rules/security/S005_no_origin_auth/ast-analyzer.js +406 -0
- package/rules/security/S005_no_origin_auth/config.json +85 -0
- package/rules/security/S006_no_plaintext_recovery_codes/README.md +139 -0
- package/rules/security/S006_no_plaintext_recovery_codes/analyzer.js +306 -0
- package/rules/security/S006_no_plaintext_recovery_codes/config.json +48 -0
- package/rules/security/S007_no_plaintext_otp/README.md +198 -0
- package/rules/security/S007_no_plaintext_otp/analyzer.js +406 -0
- package/rules/security/S007_no_plaintext_otp/config.json +79 -0
- package/rules/security/S007_no_plaintext_otp/semantic-analyzer.js +609 -0
- package/rules/security/S007_no_plaintext_otp/semantic-config.json +195 -0
- package/rules/security/S007_no_plaintext_otp/semantic-wrapper.js +280 -0
- package/rules/security/S009_no_insecure_encryption/README.md +158 -0
- package/rules/security/S009_no_insecure_encryption/analyzer.js +319 -0
- package/rules/security/S009_no_insecure_encryption/config.json +55 -0
- package/rules/security/S010_no_insecure_encryption/README.md +224 -0
- package/rules/security/S010_no_insecure_encryption/analyzer.js +493 -0
- package/rules/security/S010_no_insecure_encryption/config.json +48 -0
- package/rules/security/S016_no_sensitive_querystring/STRATEGY.md +149 -0
- package/rules/security/S016_no_sensitive_querystring/analyzer.js +276 -0
- package/rules/security/S016_no_sensitive_querystring/config.json +127 -0
- package/rules/security/S016_no_sensitive_querystring/regex-based-analyzer.js +258 -0
- package/rules/security/S016_no_sensitive_querystring/symbol-based-analyzer.js +495 -0
- package/rules/security/S027_no_hardcoded_secrets/analyzer.js +180 -366
- package/rules/security/S027_no_hardcoded_secrets/categories.json +153 -0
- package/rules/security/S027_no_hardcoded_secrets/categorized-analyzer.js +250 -0
- package/rules/security/S048_no_current_password_in_reset/README.md +222 -0
- package/rules/security/S048_no_current_password_in_reset/analyzer.js +366 -0
- package/rules/security/S048_no_current_password_in_reset/config.json +48 -0
- package/rules/security/S055_content_type_validation/README.md +176 -0
- package/rules/security/S055_content_type_validation/analyzer.js +312 -0
- package/rules/security/S055_content_type_validation/config.json +48 -0
- package/rules/utils/rule-helpers.js +140 -1
- package/scripts/consolidate-config.js +116 -0
- package/scripts/prepare-release.sh +1 -1
- package/config/rules/rules-registry.json +0 -765
- package/docs/ESLINT-INTEGRATION-STRATEGY.md +0 -392
- package/docs/FUTURE_PACKAGES.md +0 -83
- package/docs/HEURISTIC_VS_AI.md +0 -113
- package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +0 -112
- package/docs/PRODUCTION_SIZE_IMPACT.md +0 -183
- package/docs/RELEASE_GUIDE.md +0 -230
- package/docs/STANDARDIZED-CATEGORY-FILTERING.md +0 -156
- package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +0 -254
- package/rules/common/C006_function_naming/smart-analyzer.js +0 -503
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "C035_error_logging_context",
|
|
3
|
+
"name": "C035_error_logging_context",
|
|
4
|
+
"category": "architecture",
|
|
5
|
+
"description": "C035 - Khi xử lý lỗi, phải ghi log đầy đủ thông tin liên quan",
|
|
6
|
+
"severity": "warning",
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"semantic": {
|
|
9
|
+
"enabled": true,
|
|
10
|
+
"priority": "high",
|
|
11
|
+
"fallback": "heuristic"
|
|
12
|
+
},
|
|
13
|
+
"patterns": {
|
|
14
|
+
"include": [
|
|
15
|
+
"**/*.js",
|
|
16
|
+
"**/*.ts",
|
|
17
|
+
"**/*.jsx",
|
|
18
|
+
"**/*.tsx"
|
|
19
|
+
],
|
|
20
|
+
"exclude": [
|
|
21
|
+
"**/*.test.js",
|
|
22
|
+
"**/*.test.ts",
|
|
23
|
+
"**/*.spec.js",
|
|
24
|
+
"**/*.spec.ts",
|
|
25
|
+
"**/node_modules/**",
|
|
26
|
+
"**/dist/**",
|
|
27
|
+
"**/build/**"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"analysis": {
|
|
31
|
+
"approach": "symbol-based-primary",
|
|
32
|
+
"fallback": "regex-based",
|
|
33
|
+
"depth": 2,
|
|
34
|
+
"timeout": 5000
|
|
35
|
+
},
|
|
36
|
+
"validation": {
|
|
37
|
+
"requiredContext": [
|
|
38
|
+
"error_message",
|
|
39
|
+
"identifier",
|
|
40
|
+
"context"
|
|
41
|
+
],
|
|
42
|
+
"sensitivePatterns": [
|
|
43
|
+
"password", "passwd", "pwd",
|
|
44
|
+
"token", "jwt", "auth", "secret",
|
|
45
|
+
"key", "apikey", "privatekey",
|
|
46
|
+
"ssn", "credit", "card", "cvv"
|
|
47
|
+
],
|
|
48
|
+
"loggerPatterns": [
|
|
49
|
+
"console.log", "console.error", "console.warn",
|
|
50
|
+
"logger.log", "logger.error", "logger.warn", "logger.info",
|
|
51
|
+
"log.error", "log.warn", "log.info"
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C035 Regex-based Analyzer - Basic Error Logging Context Detection
|
|
3
|
+
* Purpose: Fallback pattern matching when symbol analysis fails
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class C035RegexBasedAnalyzer {
|
|
7
|
+
constructor(semanticEngine = null) {
|
|
8
|
+
this.ruleId = 'C035';
|
|
9
|
+
this.ruleName = 'Error Logging Context Analysis (Regex-Based)';
|
|
10
|
+
this.semanticEngine = semanticEngine;
|
|
11
|
+
this.verbose = false;
|
|
12
|
+
|
|
13
|
+
// Patterns for identifying catch blocks (supports TypeScript type annotations)
|
|
14
|
+
this.catchPattern = /catch\s*\(\s*(\w+)(?:\s*:\s*\w+(?:\s*\|\s*\w+)*)?\s*\)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/gs;
|
|
15
|
+
this.logPatterns = [
|
|
16
|
+
/console\.(log|error|warn|info)\s*\(/g,
|
|
17
|
+
/logger\.(log|error|warn|info|debug)\s*\(/g,
|
|
18
|
+
/log\.(error|warn|info|debug)\s*\(/g
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
// Sensitive data patterns
|
|
22
|
+
this.sensitivePatterns = [
|
|
23
|
+
/password|passwd|pwd/gi,
|
|
24
|
+
/token|jwt|auth|secret|key/gi,
|
|
25
|
+
/ssn|social|credit|card|cvv/gi
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
// String concatenation patterns (non-structured)
|
|
29
|
+
this.stringConcatPatterns = [
|
|
30
|
+
/\+\s*["'`]/g, // string concatenation
|
|
31
|
+
/["'`]\s*\+/g, // string concatenation
|
|
32
|
+
/\$\{.*\}/g // template literals (basic)
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async initialize(semanticEngine = null) {
|
|
37
|
+
if (semanticEngine) {
|
|
38
|
+
this.semanticEngine = semanticEngine;
|
|
39
|
+
}
|
|
40
|
+
this.verbose = semanticEngine?.verbose || false;
|
|
41
|
+
|
|
42
|
+
if (this.verbose) {
|
|
43
|
+
console.log(`🔧 [C035 Regex-Based] Analyzer initialized`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async analyzeFileBasic(filePath, options = {}) {
|
|
48
|
+
const fs = require('fs');
|
|
49
|
+
const path = require('path');
|
|
50
|
+
const violations = [];
|
|
51
|
+
|
|
52
|
+
if (this.verbose) {
|
|
53
|
+
console.log(`🔧 [C035 Regex] Starting analysis for: ${filePath}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
58
|
+
|
|
59
|
+
if (this.verbose) {
|
|
60
|
+
console.log(`🔧 [C035 Regex] File content length: ${content.length}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const lines = content.split('\n');
|
|
64
|
+
const catchBlocks = this.findCatchBlocks(content);
|
|
65
|
+
|
|
66
|
+
if (this.verbose) {
|
|
67
|
+
console.log(`🔧 [C035 Regex] Found ${catchBlocks.length} catch blocks`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (const block of catchBlocks) {
|
|
71
|
+
const blockViolations = this.analyzeCatchBlockContent(block, lines, filePath);
|
|
72
|
+
if (this.verbose && blockViolations.length > 0) {
|
|
73
|
+
console.log(`🔧 [C035 Regex] Block violations: ${blockViolations.length}`);
|
|
74
|
+
}
|
|
75
|
+
violations.push(...blockViolations);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (this.verbose) {
|
|
79
|
+
console.log(`🔧 [C035 Regex] Total violations found: ${violations.length}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return violations;
|
|
83
|
+
} catch (error) {
|
|
84
|
+
if (this.verbose) {
|
|
85
|
+
console.error(`🔧 [C035 Regex] Error analyzing ${filePath}:`, error);
|
|
86
|
+
}
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
} /**
|
|
90
|
+
* Find catch blocks in content using regex
|
|
91
|
+
*/
|
|
92
|
+
findCatchBlocks(content) {
|
|
93
|
+
const catchBlocks = [];
|
|
94
|
+
let match;
|
|
95
|
+
|
|
96
|
+
// Reset regex
|
|
97
|
+
this.catchPattern.lastIndex = 0;
|
|
98
|
+
|
|
99
|
+
while ((match = this.catchPattern.exec(content)) !== null) {
|
|
100
|
+
const fullMatch = match[0];
|
|
101
|
+
const errorVar = match[1];
|
|
102
|
+
const blockContent = match[2];
|
|
103
|
+
|
|
104
|
+
// Calculate line number
|
|
105
|
+
const beforeMatch = content.substring(0, match.index);
|
|
106
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
107
|
+
|
|
108
|
+
catchBlocks.push({
|
|
109
|
+
fullMatch,
|
|
110
|
+
errorVar,
|
|
111
|
+
blockContent,
|
|
112
|
+
lineNumber,
|
|
113
|
+
startIndex: match.index
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return catchBlocks;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Analyze catch block content for logging violations
|
|
122
|
+
*/
|
|
123
|
+
analyzeCatchBlockContent(catchBlock, lines, filePath) {
|
|
124
|
+
const violations = [];
|
|
125
|
+
const { blockContent, lineNumber, errorVar } = catchBlock;
|
|
126
|
+
|
|
127
|
+
// Find log calls in catch block
|
|
128
|
+
const logCalls = this.findLogCallsInContent(blockContent);
|
|
129
|
+
|
|
130
|
+
if (logCalls.length === 0) {
|
|
131
|
+
// No logging - C029's concern, not ours
|
|
132
|
+
return violations;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Analyze each log call
|
|
136
|
+
for (const logCall of logCalls) {
|
|
137
|
+
const logLineNumber = lineNumber + logCall.relativeLineNumber;
|
|
138
|
+
|
|
139
|
+
// Check for non-structured logging (string concatenation)
|
|
140
|
+
if (this.hasStringConcatenation(logCall.content)) {
|
|
141
|
+
violations.push({
|
|
142
|
+
ruleId: this.ruleId,
|
|
143
|
+
severity: 'warning',
|
|
144
|
+
message: 'Error logging should use structured format instead of string concatenation',
|
|
145
|
+
source: this.ruleId,
|
|
146
|
+
file: filePath,
|
|
147
|
+
line: logLineNumber,
|
|
148
|
+
column: logCall.column,
|
|
149
|
+
description: `[REGEX-FALLBACK] String concatenation detected in error logging. Use structured object format.`,
|
|
150
|
+
suggestion: 'Use logger.error("message", { error: e.message, context: {...} }) instead of string concatenation',
|
|
151
|
+
category: 'logging'
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Check for sensitive data
|
|
156
|
+
const sensitiveData = this.findSensitiveData(logCall.content);
|
|
157
|
+
if (sensitiveData.length > 0) {
|
|
158
|
+
violations.push({
|
|
159
|
+
ruleId: this.ruleId,
|
|
160
|
+
severity: 'error',
|
|
161
|
+
message: 'Error logging contains potentially sensitive data',
|
|
162
|
+
source: this.ruleId,
|
|
163
|
+
file: filePath,
|
|
164
|
+
line: logLineNumber,
|
|
165
|
+
column: logCall.column,
|
|
166
|
+
description: `[REGEX-FALLBACK] Sensitive patterns detected: ${sensitiveData.join(', ')}. Mask or exclude sensitive data.`,
|
|
167
|
+
suggestion: 'Mask sensitive data or exclude entirely from logs',
|
|
168
|
+
category: 'security'
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Basic context check (limited in regex mode)
|
|
173
|
+
if (!this.hasBasicContext(logCall.content, errorVar)) {
|
|
174
|
+
violations.push({
|
|
175
|
+
ruleId: this.ruleId,
|
|
176
|
+
severity: 'warning',
|
|
177
|
+
message: 'Error logging appears to miss important context information',
|
|
178
|
+
source: this.ruleId,
|
|
179
|
+
file: filePath,
|
|
180
|
+
line: logLineNumber,
|
|
181
|
+
column: logCall.column,
|
|
182
|
+
description: `[REGEX-FALLBACK] Basic context validation suggests missing error details or identifiers.`,
|
|
183
|
+
suggestion: 'Include error message, identifiers (requestId, userId), and operation context',
|
|
184
|
+
category: 'logging'
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return violations;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Find log calls within catch block content
|
|
194
|
+
*/
|
|
195
|
+
findLogCallsInContent(content) {
|
|
196
|
+
const logCalls = [];
|
|
197
|
+
const lines = content.split('\n');
|
|
198
|
+
|
|
199
|
+
for (let i = 0; i < lines.length; i++) {
|
|
200
|
+
const line = lines[i];
|
|
201
|
+
|
|
202
|
+
for (const pattern of this.logPatterns) {
|
|
203
|
+
pattern.lastIndex = 0; // Reset regex
|
|
204
|
+
const match = pattern.exec(line);
|
|
205
|
+
|
|
206
|
+
if (match) {
|
|
207
|
+
logCalls.push({
|
|
208
|
+
content: line.trim(),
|
|
209
|
+
relativeLineNumber: i,
|
|
210
|
+
column: match.index + 1,
|
|
211
|
+
method: match[1] || 'unknown'
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return logCalls;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Check if log call uses string concatenation
|
|
222
|
+
*/
|
|
223
|
+
hasStringConcatenation(content) {
|
|
224
|
+
return this.stringConcatPatterns.some(pattern => {
|
|
225
|
+
pattern.lastIndex = 0;
|
|
226
|
+
return pattern.test(content);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Find sensitive data patterns in content
|
|
232
|
+
*/
|
|
233
|
+
findSensitiveData(content) {
|
|
234
|
+
const found = [];
|
|
235
|
+
|
|
236
|
+
for (const pattern of this.sensitivePatterns) {
|
|
237
|
+
pattern.lastIndex = 0;
|
|
238
|
+
const matches = content.match(pattern);
|
|
239
|
+
if (matches) {
|
|
240
|
+
found.push(...matches.map(m => m.toLowerCase()));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return [...new Set(found)]; // Remove duplicates
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Basic context validation (limited in regex mode)
|
|
249
|
+
*/
|
|
250
|
+
hasBasicContext(content, errorVar) {
|
|
251
|
+
const lowerContent = content.toLowerCase();
|
|
252
|
+
|
|
253
|
+
// Check if error variable is used
|
|
254
|
+
const hasError = lowerContent.includes(errorVar.toLowerCase());
|
|
255
|
+
|
|
256
|
+
// Check for basic context indicators
|
|
257
|
+
const contextIndicators = ['id', 'request', 'user', 'operation', 'method'];
|
|
258
|
+
const hasContext = contextIndicators.some(indicator =>
|
|
259
|
+
lowerContent.includes(indicator)
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
return hasError && hasContext;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async analyze(files, language, options = {}) {
|
|
266
|
+
if (this.verbose) {
|
|
267
|
+
console.log(`🔧 [C035 Regex] analyze() called with ${files.length} files, language: ${language}`);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const violations = [];
|
|
271
|
+
|
|
272
|
+
for (const filePath of files) {
|
|
273
|
+
try {
|
|
274
|
+
if (this.verbose) {
|
|
275
|
+
console.log(`🔧 [C035 Regex] Processing file: ${filePath}`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const fileViolations = await this.analyzeFileBasic(filePath, options);
|
|
279
|
+
violations.push(...fileViolations);
|
|
280
|
+
|
|
281
|
+
if (this.verbose) {
|
|
282
|
+
console.log(`🔧 [C035 Regex] File ${filePath}: Found ${fileViolations.length} violations`);
|
|
283
|
+
}
|
|
284
|
+
} catch (error) {
|
|
285
|
+
if (this.verbose) {
|
|
286
|
+
console.warn(`❌ [C035 Regex] Analysis failed for ${filePath}:`, error.message);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (this.verbose) {
|
|
292
|
+
console.log(`🔧 [C035 Regex] Total violations found: ${violations.length}`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return violations;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
module.exports = C035RegexBasedAnalyzer;
|