@sun-asterisk/sunlint 1.2.1 → 1.2.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 (77) hide show
  1. package/config/rule-analysis-strategies.js +18 -2
  2. package/engines/eslint-engine.js +9 -11
  3. package/engines/heuristic-engine.js +55 -31
  4. package/package.json +2 -1
  5. package/rules/README.md +252 -0
  6. package/rules/common/C002_no_duplicate_code/analyzer.js +65 -0
  7. package/rules/common/C002_no_duplicate_code/config.json +23 -0
  8. package/rules/common/C003_no_vague_abbreviations/analyzer.js +418 -0
  9. package/rules/common/C003_no_vague_abbreviations/config.json +35 -0
  10. package/rules/common/C006_function_naming/analyzer.js +504 -0
  11. package/rules/common/C006_function_naming/config.json +86 -0
  12. package/rules/common/C006_function_naming/smart-analyzer.js +503 -0
  13. package/rules/common/C010_limit_block_nesting/analyzer.js +389 -0
  14. package/rules/common/C012_command_query_separation/analyzer.js +481 -0
  15. package/rules/common/C012_command_query_separation/ast-analyzer.js +495 -0
  16. package/rules/common/C013_no_dead_code/analyzer.js +206 -0
  17. package/rules/common/C014_dependency_injection/analyzer.js +338 -0
  18. package/rules/common/C017_constructor_logic/analyzer.js +314 -0
  19. package/rules/common/C019_log_level_usage/analyzer.js +362 -0
  20. package/rules/common/C019_log_level_usage/config.json +121 -0
  21. package/rules/common/C029_catch_block_logging/analyzer-backup.js +426 -0
  22. package/rules/common/C029_catch_block_logging/analyzer-fixed.js +130 -0
  23. package/rules/common/C029_catch_block_logging/analyzer-multi-tech.js +487 -0
  24. package/rules/common/C029_catch_block_logging/analyzer-simple.js +110 -0
  25. package/rules/common/C029_catch_block_logging/analyzer-smart-pipeline.js +755 -0
  26. package/rules/common/C029_catch_block_logging/analyzer.js +129 -0
  27. package/rules/common/C029_catch_block_logging/ast-analyzer-backup.js +441 -0
  28. package/rules/common/C029_catch_block_logging/ast-analyzer-new.js +127 -0
  29. package/rules/common/C029_catch_block_logging/ast-analyzer.js +133 -0
  30. package/rules/common/C029_catch_block_logging/cfg-analyzer.js +408 -0
  31. package/rules/common/C029_catch_block_logging/config.json +59 -0
  32. package/rules/common/C029_catch_block_logging/dataflow-analyzer.js +454 -0
  33. package/rules/common/C029_catch_block_logging/multi-language-ast-engine.js +700 -0
  34. package/rules/common/C029_catch_block_logging/pattern-learning-analyzer.js +568 -0
  35. package/rules/common/C029_catch_block_logging/semantic-analyzer.js +459 -0
  36. package/rules/common/C031_validation_separation/analyzer.js +186 -0
  37. package/rules/common/C041_no_sensitive_hardcode/analyzer.js +292 -0
  38. package/rules/common/C041_no_sensitive_hardcode/ast-analyzer.js +296 -0
  39. package/rules/common/C042_boolean_name_prefix/analyzer.js +300 -0
  40. package/rules/common/C043_no_console_or_print/analyzer.js +431 -0
  41. package/rules/common/C047_no_duplicate_retry_logic/analyzer.js +590 -0
  42. package/rules/common/C075_explicit_return_types/analyzer.js +103 -0
  43. package/rules/common/C076_single_test_behavior/analyzer.js +121 -0
  44. package/rules/docs/C002_no_duplicate_code.md +57 -0
  45. package/rules/docs/C031_validation_separation.md +72 -0
  46. package/rules/index.js +155 -0
  47. package/rules/migration/converter.js +385 -0
  48. package/rules/migration/mapping.json +164 -0
  49. package/rules/parser/constants.js +31 -0
  50. package/rules/parser/file-config.js +80 -0
  51. package/rules/parser/rule-parser-simple.js +305 -0
  52. package/rules/parser/rule-parser.js +527 -0
  53. package/rules/security/S015_insecure_tls_certificate/analyzer.js +150 -0
  54. package/rules/security/S015_insecure_tls_certificate/ast-analyzer.js +237 -0
  55. package/rules/security/S023_no_json_injection/analyzer.js +278 -0
  56. package/rules/security/S023_no_json_injection/ast-analyzer.js +359 -0
  57. package/rules/security/S026_json_schema_validation/analyzer.js +251 -0
  58. package/rules/security/S026_json_schema_validation/config.json +27 -0
  59. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +436 -0
  60. package/rules/security/S027_no_hardcoded_secrets/config.json +29 -0
  61. package/rules/security/S029_csrf_protection/analyzer.js +330 -0
  62. package/rules/tests/C002_no_duplicate_code.test.js +50 -0
  63. package/rules/universal/C010/generic.js +0 -0
  64. package/rules/universal/C010/tree-sitter-analyzer.js +0 -0
  65. package/rules/utils/ast-utils.js +191 -0
  66. package/rules/utils/base-analyzer.js +98 -0
  67. package/rules/utils/pattern-matchers.js +239 -0
  68. package/rules/utils/rule-helpers.js +264 -0
  69. package/rules/utils/severity-constants.js +93 -0
  70. package/scripts/generate_insights.js +188 -0
  71. package/scripts/merge-reports.js +0 -424
  72. package/scripts/test-scripts/README.md +0 -22
  73. package/scripts/test-scripts/test-c041-comparison.js +0 -114
  74. package/scripts/test-scripts/test-c041-eslint.js +0 -67
  75. package/scripts/test-scripts/test-eslint-rules.js +0 -146
  76. package/scripts/test-scripts/test-real-world.js +0 -44
  77. package/scripts/test-scripts/test-rules-on-real-projects.js +0 -86
@@ -0,0 +1,504 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const ts = require('typescript');
4
+
5
+ /**
6
+ * SMART C006 ANALYZER - INTELLIGENT FUNCTION NAMING ANALYSIS
7
+ *
8
+ * 🧠 5-TIER ANALYSIS APPROACH:
9
+ * 1. Context Analysis: File path, imports, class context
10
+ * 2. Semantic Analysis: Function body inspection for intent
11
+ * 3. Architectural Layer Detection: UI, Logic, Data, Utils
12
+ * 4. Natural Language Processing: Verb/noun classification
13
+ * 5. Confidence Scoring: Multi-factor violation assessment
14
+ */
15
+ class SmartC006Analyzer {
16
+ constructor() {
17
+ this.ruleId = 'C006';
18
+ this.ruleName = 'Smart Function Naming Convention';
19
+ this.description = 'Intelligent verb-noun naming pattern detection with context awareness';
20
+
21
+ // 🎯 CONFIDENCE THRESHOLDS
22
+ this.confidenceThresholds = {
23
+ HIGH: 0.8, // Clear violations
24
+ MEDIUM: 0.6, // Likely violations
25
+ LOW: 0.4 // Potential violations
26
+ };
27
+
28
+ // 🗂️ ARCHITECTURAL CONTEXT PATTERNS
29
+ this.architecturalLayers = {
30
+ UI: ['component', 'view', 'page', 'screen', 'modal', 'dialog'],
31
+ DATA: ['service', 'repository', 'dao', 'api', 'client', 'adapter'],
32
+ UTILS: ['util', 'helper', 'tool', 'lib', 'common'],
33
+ LOGIC: ['controller', 'handler', 'processor', 'manager', 'engine']
34
+ };
35
+
36
+ // 🎭 SEMANTIC INTENT PATTERNS
37
+ this.semanticPatterns = {
38
+ // Return patterns indicate getters
39
+ GETTER: [/return\s+[^;]+/, /=>\s*[^{]/, /\?\s*[^:]+:/],
40
+ // Assignment patterns indicate setters
41
+ SETTER: [/=\s*[^=]/, /\.push\(/, /\.set\(/],
42
+ // Conditional patterns indicate checkers
43
+ CHECKER: [/if\s*\(/, /\?\s*/, /return\s+(true|false)/],
44
+ // Side effect patterns indicate actions
45
+ ACTION: [/console\./, /fetch\(/, /\.send\(/, /\.post\(/]
46
+ };
47
+ }
48
+
49
+ async analyze(files, language, config) {
50
+ const violations = [];
51
+
52
+ if (config.verbose) {
53
+ console.log(`🔧 [DEBUG] Starting Smart C006 Analysis on ${files.length} files...`);
54
+ }
55
+
56
+ for (const filePath of files) {
57
+ try {
58
+ const fileContent = fs.readFileSync(filePath, 'utf8');
59
+ const fileViolations = await this.analyzeFile(filePath, fileContent, language, config);
60
+ violations.push(...fileViolations);
61
+ } catch (error) {
62
+ if (config.verbose) {
63
+ console.error(`⚠️ [DEBUG] Error analyzing file ${filePath}:`, error.message);
64
+ }
65
+ }
66
+ }
67
+
68
+ if (config.verbose) {
69
+ console.log(`🔧 [DEBUG] Smart C006 Analysis complete: ${violations.length} violations found`);
70
+ }
71
+
72
+ return violations;
73
+ }
74
+
75
+ async analyzeFile(filePath, content, language, config) {
76
+ if (language !== 'typescript' && language !== 'javascript') {
77
+ return []; // Focus on TS/JS for now
78
+ }
79
+
80
+ const violations = [];
81
+ const lines = content.split('\n');
82
+
83
+ // 🏗️ TIER 1: ARCHITECTURAL CONTEXT ANALYSIS
84
+ const architecturalContext = this.analyzeArchitecturalContext(filePath, content);
85
+
86
+ // Parse TypeScript/JavaScript code
87
+ const sourceFile = ts.createSourceFile(
88
+ filePath,
89
+ content,
90
+ ts.ScriptTarget.Latest,
91
+ true
92
+ );
93
+
94
+ const visit = (node) => {
95
+ // Analyze function declarations
96
+ if (ts.isFunctionDeclaration(node) && node.name && node.body) {
97
+ const analysis = this.smartAnalyzeFunctionName(
98
+ node.name.text,
99
+ node,
100
+ sourceFile,
101
+ architecturalContext,
102
+ content
103
+ );
104
+
105
+ if (analysis.isViolation && analysis.confidence >= this.confidenceThresholds.LOW) {
106
+ const namePosition = sourceFile.getLineAndCharacterOfPosition(node.name.getStart());
107
+ const line = namePosition.line + 1;
108
+ const column = namePosition.character + 1;
109
+ const lineText = lines[line - 1]?.trim() || '';
110
+
111
+ violations.push({
112
+ ruleId: this.ruleId,
113
+ file: filePath,
114
+ line,
115
+ column,
116
+ message: analysis.reason,
117
+ severity: this.getSeverityFromConfidence(analysis.confidence),
118
+ code: lineText,
119
+ type: analysis.type,
120
+ confidence: analysis.confidence,
121
+ suggestion: analysis.suggestion,
122
+ context: analysis.context
123
+ });
124
+ }
125
+ }
126
+
127
+ // Analyze method declarations
128
+ if (ts.isMethodDeclaration(node) && node.name) {
129
+ const analysis = this.smartAnalyzeFunctionName(
130
+ node.name.text,
131
+ node,
132
+ sourceFile,
133
+ architecturalContext,
134
+ content
135
+ );
136
+
137
+ if (analysis.isViolation && analysis.confidence >= this.confidenceThresholds.LOW) {
138
+ const namePosition = sourceFile.getLineAndCharacterOfPosition(node.name.getStart());
139
+ const line = namePosition.line + 1;
140
+ const column = namePosition.character + 1;
141
+ const lineText = lines[line - 1]?.trim() || '';
142
+
143
+ violations.push({
144
+ ruleId: this.ruleId,
145
+ file: filePath,
146
+ line,
147
+ column,
148
+ message: analysis.reason,
149
+ severity: this.getSeverityFromConfidence(analysis.confidence),
150
+ code: lineText,
151
+ type: analysis.type,
152
+ confidence: analysis.confidence,
153
+ suggestion: analysis.suggestion,
154
+ context: analysis.context
155
+ });
156
+ }
157
+ }
158
+
159
+ // Analyze arrow functions assigned to variables
160
+ if (ts.isVariableDeclaration(node) && node.name && ts.isIdentifier(node.name) &&
161
+ node.initializer && ts.isArrowFunction(node.initializer)) {
162
+ const analysis = this.smartAnalyzeFunctionName(
163
+ node.name.text,
164
+ node.initializer,
165
+ sourceFile,
166
+ architecturalContext,
167
+ content
168
+ );
169
+
170
+ if (analysis.isViolation && analysis.confidence >= this.confidenceThresholds.LOW) {
171
+ const namePosition = sourceFile.getLineAndCharacterOfPosition(node.name.getStart());
172
+ const line = namePosition.line + 1;
173
+ const column = namePosition.character + 1;
174
+ const lineText = lines[line - 1]?.trim() || '';
175
+
176
+ violations.push({
177
+ ruleId: this.ruleId,
178
+ file: filePath,
179
+ line,
180
+ column,
181
+ message: analysis.reason,
182
+ severity: this.getSeverityFromConfidence(analysis.confidence),
183
+ code: lineText,
184
+ type: analysis.type,
185
+ confidence: analysis.confidence,
186
+ suggestion: analysis.suggestion,
187
+ context: analysis.context
188
+ });
189
+ }
190
+ }
191
+
192
+ ts.forEachChild(node, visit);
193
+ };
194
+
195
+ visit(sourceFile);
196
+ return violations;
197
+ }
198
+
199
+ /**
200
+ * 🏗️ TIER 1: ARCHITECTURAL CONTEXT ANALYSIS
201
+ * Determines what type of file/module this is
202
+ */
203
+ analyzeArchitecturalContext(filePath, content) {
204
+ const fileName = path.basename(filePath, path.extname(filePath)).toLowerCase();
205
+ const fileDir = path.dirname(filePath).toLowerCase();
206
+
207
+ // Detect architectural layer
208
+ let layer = 'UNKNOWN';
209
+ for (const [layerName, patterns] of Object.entries(this.architecturalLayers)) {
210
+ if (patterns.some(pattern => fileName.includes(pattern) || fileDir.includes(pattern))) {
211
+ layer = layerName;
212
+ break;
213
+ }
214
+ }
215
+
216
+ // Analyze imports for additional context
217
+ const imports = this.extractImports(content);
218
+ const isReactComponent = imports.some(imp => imp.includes('react')) || content.includes('JSX.Element');
219
+ const isTestFile = fileName.includes('test') || fileName.includes('spec');
220
+
221
+ return {
222
+ layer,
223
+ isReactComponent,
224
+ isTestFile,
225
+ fileName,
226
+ imports
227
+ };
228
+ }
229
+
230
+ /**
231
+ * 🧠 TIER 2: SEMANTIC ANALYSIS
232
+ * Analyzes function body to understand intent
233
+ */
234
+ analyzeSemanticIntent(functionNode, sourceFile, content) {
235
+ if (!functionNode.body) return 'UNKNOWN';
236
+
237
+ const functionText = content.substring(
238
+ functionNode.body.getStart(),
239
+ functionNode.body.getEnd()
240
+ );
241
+
242
+ // Check for different semantic patterns
243
+ for (const [intent, patterns] of Object.entries(this.semanticPatterns)) {
244
+ if (patterns.some(pattern => pattern.test(functionText))) {
245
+ return intent;
246
+ }
247
+ }
248
+
249
+ return 'UNKNOWN';
250
+ }
251
+
252
+ /**
253
+ * 🎯 TIER 3: INTELLIGENT VERB DETECTION
254
+ * Uses multiple strategies to detect verbs
255
+ */
256
+ isVerbLikeName(functionName) {
257
+ // Strategy 1: Known verb prefixes (expanded beyond static list)
258
+ const verbPrefixes = [
259
+ 'get', 'set', 'is', 'has', 'can', 'should', 'will', 'does',
260
+ 'create', 'build', 'make', 'generate', 'construct', 'produce',
261
+ 'update', 'modify', 'change', 'edit', 'alter', 'transform',
262
+ 'delete', 'remove', 'destroy', 'clean', 'clear', 'reset',
263
+ 'load', 'save', 'fetch', 'retrieve', 'find', 'search', 'query',
264
+ 'validate', 'verify', 'check', 'confirm', 'ensure', 'test',
265
+ 'calculate', 'compute', 'process', 'handle', 'manage', 'execute',
266
+ 'send', 'receive', 'transmit', 'broadcast', 'emit', 'publish',
267
+ 'parse', 'format', 'convert', 'map', 'filter', 'sort', 'group',
268
+ 'connect', 'disconnect', 'open', 'close', 'start', 'stop', 'run',
269
+ 'show', 'hide', 'display', 'render', 'draw', 'paint', 'animate',
270
+ 'add', 'append', 'insert', 'push', 'pop', 'shift', 'splice',
271
+ 'count', 'measure', 'monitor', 'watch', 'track', 'observe',
272
+ 'refresh', 'restore', 'reload', 'retry', 'resume', 'redirect',
273
+ 'select', 'toggle', 'switch', 'enable', 'disable', 'activate',
274
+ 'expand', 'collapse', 'scroll', 'navigate', 'submit', 'cancel',
275
+ 'on', 'handle', 'trigger', 'fire', 'dispatch', 'invoke', 'call'
276
+ ];
277
+
278
+ // Strategy 2: Check if starts with known verb
279
+ const startsWithVerb = verbPrefixes.some(verb => {
280
+ const verbPattern = new RegExp(`^${verb}[A-Z]?`, 'i');
281
+ return verbPattern.test(functionName);
282
+ });
283
+
284
+ if (startsWithVerb) return true;
285
+
286
+ // Strategy 3: Common verb suffixes that indicate actions
287
+ const actionSuffixes = ['ize', 'ise', 'fy', 'ate', 'en'];
288
+ if (actionSuffixes.some(suffix => functionName.endsWith(suffix))) {
289
+ return true;
290
+ }
291
+
292
+ // Strategy 4: English verb patterns (basic NLP)
293
+ const verbPatterns = [
294
+ /^(re|un|pre|de|dis)[A-Z]/, // prefixed verbs: revalidate, unload, preprocess
295
+ /^[a-z]+ly[A-Z]/, // adverb-verb patterns: quicklyProcess
296
+ ];
297
+
298
+ return verbPatterns.some(pattern => pattern.test(functionName));
299
+ }
300
+
301
+ /**
302
+ * 🎭 TIER 4: CONTEXT-AWARE NAMING RULES
303
+ * Different rules for different contexts
304
+ */
305
+ getContextSpecificRules(architecturalContext, semanticIntent) {
306
+ const rules = {
307
+ allowedPatterns: [],
308
+ requiredPatterns: [],
309
+ suggestions: []
310
+ };
311
+
312
+ // React components have different naming conventions
313
+ if (architecturalContext.isReactComponent) {
314
+ rules.allowedPatterns.push(/^[A-Z][a-zA-Z]*$/); // PascalCase components
315
+ rules.allowedPatterns.push(/^use[A-Z][a-zA-Z]*$/); // React hooks
316
+ rules.allowedPatterns.push(/^handle[A-Z][a-zA-Z]*$/); // Event handlers
317
+ }
318
+
319
+ // Test files have different patterns
320
+ if (architecturalContext.isTestFile) {
321
+ rules.allowedPatterns.push(/^(test|it|describe|should|expect)[A-Z]?/);
322
+ }
323
+
324
+ // Data layer functions often have CRUD patterns
325
+ if (architecturalContext.layer === 'DATA') {
326
+ rules.suggestions.push('Consider CRUD verbs: create, read, update, delete');
327
+ }
328
+
329
+ // UI layer functions often have interaction verbs
330
+ if (architecturalContext.layer === 'UI') {
331
+ rules.suggestions.push('Consider UI verbs: show, hide, toggle, render, display');
332
+ }
333
+
334
+ return rules;
335
+ }
336
+
337
+ /**
338
+ * 🎯 TIER 5: COMPREHENSIVE SMART ANALYSIS
339
+ * Combines all tiers for intelligent assessment
340
+ */
341
+ smartAnalyzeFunctionName(functionName, functionNode, sourceFile, architecturalContext, content) {
342
+ // Skip special functions
343
+ if (this.isSpecialFunction(functionName, architecturalContext)) {
344
+ return { isViolation: false };
345
+ }
346
+
347
+ // Get semantic intent
348
+ const semanticIntent = this.analyzeSemanticIntent(functionNode, sourceFile, content);
349
+
350
+ // Get context-specific rules
351
+ const contextRules = this.getContextSpecificRules(architecturalContext, semanticIntent);
352
+
353
+ // Check if allowed by context-specific patterns
354
+ if (contextRules.allowedPatterns.some(pattern => pattern.test(functionName))) {
355
+ return { isViolation: false };
356
+ }
357
+
358
+ // Check if name follows verb-noun pattern
359
+ const isVerbLike = this.isVerbLikeName(functionName);
360
+
361
+ if (isVerbLike) {
362
+ return { isViolation: false };
363
+ }
364
+
365
+ // 🧮 CONFIDENCE CALCULATION
366
+ let confidence = 0.5; // Base confidence
367
+
368
+ // Boost confidence for clear noun-only patterns
369
+ if (/^[a-z]+$/.test(functionName)) {
370
+ confidence += 0.3; // Simple lowercase nouns: user, data
371
+ }
372
+
373
+ if (/^[a-z]+[A-Z][a-z]+$/.test(functionName)) {
374
+ confidence += 0.2; // Simple camelCase nouns: userData, userInfo
375
+ }
376
+
377
+ // Reduce confidence for complex names (might have hidden verbs)
378
+ if (functionName.length > 15) {
379
+ confidence -= 0.1;
380
+ }
381
+
382
+ // Reduce confidence for utils/helpers (more flexible naming)
383
+ if (architecturalContext.layer === 'UTILS') {
384
+ confidence -= 0.2;
385
+ }
386
+
387
+ // Reduce confidence for test files
388
+ if (architecturalContext.isTestFile) {
389
+ confidence -= 0.3;
390
+ }
391
+
392
+ // Cap confidence
393
+ confidence = Math.min(Math.max(confidence, 0.1), 1.0);
394
+
395
+ // 💬 INTELLIGENT MESSAGING
396
+ const context = {
397
+ layer: architecturalContext.layer,
398
+ intent: semanticIntent,
399
+ isReactComponent: architecturalContext.isReactComponent,
400
+ isTestFile: architecturalContext.isTestFile
401
+ };
402
+
403
+ let reason = `Function '${functionName}' should follow verb-noun naming pattern`;
404
+ let suggestion = this.generateSmartSuggestion(functionName, semanticIntent, architecturalContext);
405
+
406
+ if (architecturalContext.layer !== 'UNKNOWN') {
407
+ reason += ` (${architecturalContext.layer} layer)`;
408
+ }
409
+
410
+ return {
411
+ isViolation: true,
412
+ reason,
413
+ type: 'smart_naming_violation',
414
+ confidence,
415
+ suggestion,
416
+ context
417
+ };
418
+ }
419
+
420
+ /**
421
+ * 💡 SMART SUGGESTION GENERATOR
422
+ */
423
+ generateSmartSuggestion(functionName, semanticIntent, architecturalContext) {
424
+ const baseNoun = functionName.charAt(0).toUpperCase() + functionName.slice(1);
425
+
426
+ switch (semanticIntent) {
427
+ case 'GETTER':
428
+ return `get${baseNoun}()`;
429
+ case 'SETTER':
430
+ return `set${baseNoun}()`;
431
+ case 'CHECKER':
432
+ return `is${baseNoun}() or has${baseNoun}()`;
433
+ case 'ACTION':
434
+ return `process${baseNoun}() or handle${baseNoun}()`;
435
+ default:
436
+ if (architecturalContext.layer === 'DATA') {
437
+ return `fetch${baseNoun}() or create${baseNoun}()`;
438
+ }
439
+ if (architecturalContext.layer === 'UI') {
440
+ return `render${baseNoun}() or show${baseNoun}()`;
441
+ }
442
+ return `get${baseNoun}() or process${baseNoun}()`;
443
+ }
444
+ }
445
+
446
+ /**
447
+ * 🛡️ ENHANCED SPECIAL FUNCTION DETECTION
448
+ */
449
+ isSpecialFunction(name, architecturalContext) {
450
+ const specialFunctions = [
451
+ 'constructor', 'toString', 'valueOf', 'toJSON',
452
+ 'main', 'init', 'setup', 'teardown', 'build',
453
+ 'onCreate', 'onDestroy', 'onStart', 'onStop',
454
+ 'onPause', 'onResume', 'onSaveInstanceState',
455
+ 'equals', 'hashCode', 'compareTo', 'clone',
456
+ 'finalize', 'notify', 'notifyAll', 'wait'
457
+ ];
458
+
459
+ // Basic special function check
460
+ if (specialFunctions.includes(name) || name.startsWith('_') || name.startsWith('$')) {
461
+ return true;
462
+ }
463
+
464
+ // React component names (PascalCase)
465
+ if (architecturalContext.isReactComponent && /^[A-Z][a-zA-Z]*$/.test(name)) {
466
+ return true;
467
+ }
468
+
469
+ // React hooks
470
+ if (name.startsWith('use') && /^use[A-Z]/.test(name)) {
471
+ return true;
472
+ }
473
+
474
+ // Test function names
475
+ if (architecturalContext.isTestFile && /^(test|it|describe|should|expect)/.test(name)) {
476
+ return true;
477
+ }
478
+
479
+ return false;
480
+ }
481
+
482
+ /**
483
+ * 🎯 UTILITY METHODS
484
+ */
485
+ extractImports(content) {
486
+ const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
487
+ const imports = [];
488
+ let match;
489
+
490
+ while ((match = importRegex.exec(content)) !== null) {
491
+ imports.push(match[1]);
492
+ }
493
+
494
+ return imports;
495
+ }
496
+
497
+ getSeverityFromConfidence(confidence) {
498
+ if (confidence >= this.confidenceThresholds.HIGH) return 'warning';
499
+ if (confidence >= this.confidenceThresholds.MEDIUM) return 'info';
500
+ return 'hint';
501
+ }
502
+ }
503
+
504
+ module.exports = new SmartC006Analyzer();
@@ -0,0 +1,86 @@
1
+ {
2
+ "ruleId": "C006",
3
+ "name": "Function Naming Convention",
4
+ "description": "Tên hàm phải là động từ/verb-noun pattern",
5
+ "category": "naming",
6
+ "severity": "warning",
7
+ "languages": ["typescript", "dart", "kotlin"],
8
+ "version": "1.0.0",
9
+ "status": "activated",
10
+ "tags": ["naming", "convention", "readability"],
11
+ "config": {
12
+ "commonVerbs": [
13
+ "get", "set", "is", "has", "can", "should", "will",
14
+ "create", "build", "make", "generate", "construct",
15
+ "update", "modify", "change", "edit", "alter",
16
+ "delete", "remove", "destroy", "clean", "clear",
17
+ "load", "save", "fetch", "retrieve", "find", "search",
18
+ "validate", "verify", "check", "confirm", "ensure",
19
+ "calculate", "compute", "process", "handle", "manage",
20
+ "send", "receive", "transmit", "broadcast", "emit",
21
+ "parse", "format", "transform", "convert", "map",
22
+ "filter", "sort", "group", "merge", "split",
23
+ "connect", "disconnect", "open", "close", "start", "stop",
24
+ "show", "hide", "display", "render", "draw", "paint",
25
+ "add", "append", "insert", "push", "pop", "shift",
26
+ "test", "debug", "log", "trace", "monitor", "watch"
27
+ ],
28
+ "specialFunctions": [
29
+ "constructor", "toString", "valueOf", "toJSON",
30
+ "main", "init", "setup", "teardown", "build",
31
+ "onCreate", "onDestroy", "onStart", "onStop",
32
+ "onPause", "onResume", "onSaveInstanceState",
33
+ "equals", "hashCode", "compareTo", "clone",
34
+ "finalize", "notify", "notifyAll", "wait"
35
+ ],
36
+ "patterns": {
37
+ "camelCase": "^[a-z][a-zA-Z0-9]*$",
38
+ "verbNoun": "^(get|set|is|has|can|create|update|delete|load|save|find|validate|process|handle|calculate|send|receive|parse|format|transform|filter|sort|connect|show|hide|add|remove)[A-Z][a-zA-Z0-9]*$"
39
+ }
40
+ },
41
+ "examples": {
42
+ "violations": [
43
+ {
44
+ "language": "typescript",
45
+ "code": "function userData() { return user.data; }",
46
+ "reason": "Function name is a noun - should start with a verb like 'getUserData'"
47
+ },
48
+ {
49
+ "language": "typescript",
50
+ "code": "function calculation() { return x + y; }",
51
+ "reason": "Should use verb-noun pattern like 'calculateSum' or 'performCalculation'"
52
+ },
53
+ {
54
+ "language": "dart",
55
+ "code": "String userInfo() { return 'info'; }",
56
+ "reason": "Function name should start with verb like 'getUserInfo'"
57
+ }
58
+ ],
59
+ "valid": [
60
+ {
61
+ "language": "typescript",
62
+ "code": "function getUserData() { return user.data; }",
63
+ "reason": "Follows verb-noun pattern"
64
+ },
65
+ {
66
+ "language": "typescript",
67
+ "code": "function isValid() { return true; }",
68
+ "reason": "Starts with verb 'is'"
69
+ },
70
+ {
71
+ "language": "dart",
72
+ "code": "bool hasPermission() { return true; }",
73
+ "reason": "Starts with verb 'has'"
74
+ }
75
+ ]
76
+ },
77
+ "fixes": {
78
+ "autoFixable": false,
79
+ "suggestions": [
80
+ "Start function names with verbs (get, set, is, has, create, update, etc.)",
81
+ "Use verb-noun pattern for clarity (e.g., getUserData, validateInput)",
82
+ "Avoid noun-only function names",
83
+ "Use camelCase convention"
84
+ ]
85
+ }
86
+ }