@sun-asterisk/sunlint 1.3.47 → 1.3.49

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 (185) hide show
  1. package/config/rules/rules-registry-generated.json +1717 -282
  2. package/core/architecture-integration.js +57 -15
  3. package/core/cli-action-handler.js +51 -36
  4. package/core/config-manager.js +6 -0
  5. package/core/config-merger.js +33 -0
  6. package/core/config-validator.js +37 -2
  7. package/core/file-targeting-service.js +148 -15
  8. package/core/init-command.js +118 -70
  9. package/core/output-service.js +12 -3
  10. package/core/project-detector.js +517 -0
  11. package/core/scoring-service.js +12 -6
  12. package/core/summary-report-service.js +9 -4
  13. package/core/tui-select.js +245 -0
  14. package/engines/arch-detect/rules/layered/l001-presentation-layer.js +7 -15
  15. package/engines/arch-detect/rules/layered/l002-business-layer.js +7 -15
  16. package/engines/arch-detect/rules/layered/l003-data-layer.js +7 -15
  17. package/engines/arch-detect/rules/layered/l004-model-layer.js +7 -15
  18. package/engines/arch-detect/rules/layered/l005-layer-separation.js +22 -2
  19. package/engines/arch-detect/rules/layered/l006-dependency-direction.js +8 -5
  20. package/engines/arch-detect/rules/modular/m005-no-deep-imports.js +67 -29
  21. package/engines/arch-detect/rules/presentation/pr001-view-layer.js +16 -9
  22. package/engines/arch-detect/rules/presentation/pr006-router-layer.js +33 -8
  23. package/engines/arch-detect/rules/presentation/pr007-interactor-layer.js +35 -6
  24. package/engines/arch-detect/rules/project-scanner/ps003-framework-detection.js +56 -10
  25. package/engines/impact/cli.js +54 -39
  26. package/engines/impact/config/default-config.js +105 -5
  27. package/engines/impact/core/impact-analyzer.js +12 -15
  28. package/engines/impact/core/utils/gitignore-parser.js +123 -0
  29. package/engines/impact/core/utils/method-call-graph.js +272 -87
  30. package/origin-rules/dart-en.md +1 -1
  31. package/origin-rules/go-en.md +231 -0
  32. package/origin-rules/php-en.md +107 -0
  33. package/origin-rules/python-en.md +113 -0
  34. package/origin-rules/ruby-en.md +607 -0
  35. package/package.json +1 -1
  36. package/scripts/copy-arch-detect.js +5 -1
  37. package/scripts/copy-impact-analyzer.js +5 -1
  38. package/scripts/generate-rules-registry.js +30 -14
  39. package/skill-assets/sunlint-code-quality/SKILL.md +3 -2
  40. package/skill-assets/sunlint-code-quality/rules/dart/C006-verb-noun-functions.md +45 -0
  41. package/skill-assets/sunlint-code-quality/rules/dart/C013-no-dead-code.md +53 -0
  42. package/skill-assets/sunlint-code-quality/rules/dart/C014-dependency-injection.md +92 -0
  43. package/skill-assets/sunlint-code-quality/rules/dart/C017-no-constructor-logic.md +62 -0
  44. package/skill-assets/sunlint-code-quality/rules/dart/C018-generic-errors.md +57 -0
  45. package/skill-assets/sunlint-code-quality/rules/dart/C019-error-log-level.md +50 -0
  46. package/skill-assets/sunlint-code-quality/rules/dart/C020-no-unused-imports.md +46 -0
  47. package/skill-assets/sunlint-code-quality/rules/dart/C022-no-unused-variables.md +50 -0
  48. package/skill-assets/sunlint-code-quality/rules/dart/C023-no-duplicate-names.md +56 -0
  49. package/skill-assets/sunlint-code-quality/rules/dart/C024-centralize-constants.md +75 -0
  50. package/skill-assets/sunlint-code-quality/rules/dart/C029-catch-log-root-cause.md +53 -0
  51. package/skill-assets/sunlint-code-quality/rules/dart/C030-custom-error-classes.md +86 -0
  52. package/skill-assets/sunlint-code-quality/rules/dart/C033-separate-data-access.md +90 -0
  53. package/skill-assets/sunlint-code-quality/rules/dart/C035-error-context-logging.md +62 -0
  54. package/skill-assets/sunlint-code-quality/rules/dart/C041-no-hardcoded-secrets.md +75 -0
  55. package/skill-assets/sunlint-code-quality/rules/dart/C042-boolean-naming.md +73 -0
  56. package/skill-assets/sunlint-code-quality/rules/dart/C052-widget-parsing.md +84 -0
  57. package/skill-assets/sunlint-code-quality/rules/dart/C060-superclass-logic.md +91 -0
  58. package/skill-assets/sunlint-code-quality/rules/dart/C067-no-hardcoded-config.md +108 -0
  59. package/skill-assets/sunlint-code-quality/rules/go/G001-explicit-error-handling.md +53 -0
  60. package/skill-assets/sunlint-code-quality/rules/go/G002-context-first-argument.md +44 -0
  61. package/skill-assets/sunlint-code-quality/rules/go/G003-receiver-consistency.md +38 -0
  62. package/skill-assets/sunlint-code-quality/rules/go/G004-avoid-panic.md +49 -0
  63. package/skill-assets/sunlint-code-quality/rules/go/G005-goroutine-leak-prevention.md +49 -0
  64. package/skill-assets/sunlint-code-quality/rules/go/G006-interface-consumer-definition.md +45 -0
  65. package/skill-assets/sunlint-code-quality/rules/go/GN001-gin-binding-validation.md +57 -0
  66. package/skill-assets/sunlint-code-quality/rules/go/GN002-gin-error-response.md +48 -0
  67. package/skill-assets/sunlint-code-quality/rules/go/GN003-graceful-shutdown.md +57 -0
  68. package/skill-assets/sunlint-code-quality/rules/go/GN004-gin-route-logical-grouping.md +54 -0
  69. package/skill-assets/sunlint-code-quality/rules/go-gin/AGENTS.md +149 -0
  70. package/skill-assets/sunlint-code-quality/rules/go-gin/GN001-abort-after-response.md +75 -0
  71. package/skill-assets/sunlint-code-quality/rules/go-gin/GN002-request-context.md +64 -0
  72. package/skill-assets/sunlint-code-quality/rules/go-gin/GN003-bind-error-handling.md +70 -0
  73. package/skill-assets/sunlint-code-quality/rules/go-gin/GN004-dependency-injection.md +78 -0
  74. package/skill-assets/sunlint-code-quality/rules/go-gin/GN005-route-groups-middleware.md +71 -0
  75. package/skill-assets/sunlint-code-quality/rules/go-gin/GN006-http-status-codes.md +91 -0
  76. package/skill-assets/sunlint-code-quality/rules/go-gin/GN007-release-mode.md +64 -0
  77. package/skill-assets/sunlint-code-quality/rules/go-gin/GN008-struct-validation-tags.md +90 -0
  78. package/skill-assets/sunlint-code-quality/rules/go-gin/GN009-recovery-middleware.md +68 -0
  79. package/skill-assets/sunlint-code-quality/rules/go-gin/GN010-context-scope.md +68 -0
  80. package/skill-assets/sunlint-code-quality/rules/go-gin/GN011-middleware-concerns.md +92 -0
  81. package/skill-assets/sunlint-code-quality/rules/go-gin/GN012-no-log-sensitive.md +84 -0
  82. package/skill-assets/sunlint-code-quality/rules/java/J001-try-with-resources.md +86 -0
  83. package/skill-assets/sunlint-code-quality/rules/java/J002-equals-and-hashcode.md +88 -0
  84. package/skill-assets/sunlint-code-quality/rules/java/J003-string-comparison.md +72 -0
  85. package/skill-assets/sunlint-code-quality/rules/java/J004-use-java-time.md +91 -0
  86. package/skill-assets/sunlint-code-quality/rules/java/J005-no-print-stack-trace.md +80 -0
  87. package/skill-assets/sunlint-code-quality/rules/java/J006-no-system-println.md +89 -0
  88. package/skill-assets/sunlint-code-quality/rules/java/J007-proper-logger.md +91 -0
  89. package/skill-assets/sunlint-code-quality/rules/java/J008-thread-safe-singleton.md +119 -0
  90. package/skill-assets/sunlint-code-quality/rules/java/J009-utility-class-constructor.md +82 -0
  91. package/skill-assets/sunlint-code-quality/rules/java/J010-preserve-stack-trace.md +119 -0
  92. package/skill-assets/sunlint-code-quality/rules/java/J011-null-safe-compare.md +88 -0
  93. package/skill-assets/sunlint-code-quality/rules/java/J012-use-enum-collections.md +104 -0
  94. package/skill-assets/sunlint-code-quality/rules/java/J013-return-empty-not-null.md +102 -0
  95. package/skill-assets/sunlint-code-quality/rules/java/J014-hardcoded-crypto-key.md +108 -0
  96. package/skill-assets/sunlint-code-quality/rules/java/J015-optional-instead-of-null.md +109 -0
  97. package/skill-assets/sunlint-code-quality/rules/php-laravel/AGENTS.md +124 -0
  98. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV001-form-request-validation.md +64 -0
  99. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV002-eager-load-no-n-plus-1.md +58 -0
  100. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV003-config-not-env.md +54 -0
  101. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV004-fillable-mass-assignment.md +51 -0
  102. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV005-policies-gates-authorization.md +71 -0
  103. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV006-queue-heavy-tasks.md +68 -0
  104. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV007-hash-passwords.md +51 -0
  105. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV008-route-model-binding.md +67 -0
  106. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV009-api-resources.md +72 -0
  107. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV010-chunk-large-datasets.md +58 -0
  108. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV011-db-transactions.md +73 -0
  109. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV012-service-layer.md +78 -0
  110. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV013-testing-factories.md +75 -0
  111. package/skill-assets/sunlint-code-quality/rules/php-laravel/LV014-service-container.md +61 -0
  112. package/skill-assets/sunlint-code-quality/rules/python/P001-mutable-default-argument.md +55 -0
  113. package/skill-assets/sunlint-code-quality/rules/python/P002-specify-file-encoding.md +45 -0
  114. package/skill-assets/sunlint-code-quality/rules/python/P003-context-manager-for-resources.md +54 -0
  115. package/skill-assets/sunlint-code-quality/rules/python/P004-no-bare-except.md +65 -0
  116. package/skill-assets/sunlint-code-quality/rules/python/P005-use-isinstance.md +60 -0
  117. package/skill-assets/sunlint-code-quality/rules/python/P006-timezone-aware-datetime.md +58 -0
  118. package/skill-assets/sunlint-code-quality/rules/python/P007-use-pathlib.md +62 -0
  119. package/skill-assets/sunlint-code-quality/rules/python/P008-no-wildcard-import.md +52 -0
  120. package/skill-assets/sunlint-code-quality/rules/python/P009-logging-lazy-format.md +50 -0
  121. package/skill-assets/sunlint-code-quality/rules/python/P010-exception-chaining.md +57 -0
  122. package/skill-assets/sunlint-code-quality/rules/python/P011-subprocess-check.md +59 -0
  123. package/skill-assets/sunlint-code-quality/rules/python/P012-requests-timeout.md +70 -0
  124. package/skill-assets/sunlint-code-quality/rules/python/P013-no-global-statement.md +73 -0
  125. package/skill-assets/sunlint-code-quality/rules/python/P014-no-modify-collection-while-iterating.md +66 -0
  126. package/skill-assets/sunlint-code-quality/rules/python/P015-prefer-fstrings.md +61 -0
  127. package/skill-assets/sunlint-code-quality/rules/ruby-rails/AGENTS.md +121 -0
  128. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR001-strong-parameters.md +55 -0
  129. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR002-eager-load-includes.md +51 -0
  130. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR003-service-objects.md +99 -0
  131. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR004-active-job-background.md +67 -0
  132. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR005-pagination.md +53 -0
  133. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR006-find-each-batches.md +53 -0
  134. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR007-http-status-codes.md +76 -0
  135. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR008-before-action-auth.md +77 -0
  136. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR009-rails-credentials.md +61 -0
  137. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR010-scopes.md +57 -0
  138. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR011-counter-cache.md +59 -0
  139. package/skill-assets/sunlint-code-quality/rules/ruby-rails/RR012-render-json-status.md +42 -0
  140. package/skill-assets/sunlint-code-quality/rules/swift/C006-verb-noun-functions.md +37 -0
  141. package/skill-assets/sunlint-code-quality/rules/swift/C013-no-dead-code.md +55 -0
  142. package/skill-assets/sunlint-code-quality/rules/swift/C014-dependency-injection.md +69 -0
  143. package/skill-assets/sunlint-code-quality/rules/swift/C017-no-constructor-logic.md +66 -0
  144. package/skill-assets/sunlint-code-quality/rules/swift/C018-generic-errors.md +64 -0
  145. package/skill-assets/sunlint-code-quality/rules/swift/C019-error-log-level.md +64 -0
  146. package/skill-assets/sunlint-code-quality/rules/swift/C020-no-unused-imports.md +47 -0
  147. package/skill-assets/sunlint-code-quality/rules/swift/C022-no-unused-variables.md +46 -0
  148. package/skill-assets/sunlint-code-quality/rules/swift/C023-no-duplicate-names.md +55 -0
  149. package/skill-assets/sunlint-code-quality/rules/swift/C024-centralize-constants.md +68 -0
  150. package/skill-assets/sunlint-code-quality/rules/swift/C029-catch-log-root-cause.md +69 -0
  151. package/skill-assets/sunlint-code-quality/rules/swift/C030-custom-error-classes.md +77 -0
  152. package/skill-assets/sunlint-code-quality/rules/swift/C033-separate-data-access.md +89 -0
  153. package/skill-assets/sunlint-code-quality/rules/swift/C035-error-context-logging.md +66 -0
  154. package/skill-assets/sunlint-code-quality/rules/swift/C041-no-hardcoded-secrets.md +65 -0
  155. package/skill-assets/sunlint-code-quality/rules/swift/C042-boolean-naming.md +60 -0
  156. package/skill-assets/sunlint-code-quality/rules/swift/C052-controller-parsing.md +67 -0
  157. package/skill-assets/sunlint-code-quality/rules/swift/C060-superclass-logic.md +95 -0
  158. package/skill-assets/sunlint-code-quality/rules/swift/C067-no-hardcoded-config.md +80 -0
  159. package/skill-assets/sunlint-code-quality/rules/swift/S003-sql-injection.md +65 -0
  160. package/skill-assets/sunlint-code-quality/rules/swift/S004-no-log-credentials.md +67 -0
  161. package/skill-assets/sunlint-code-quality/rules/swift/S005-server-authorization.md +73 -0
  162. package/skill-assets/sunlint-code-quality/rules/swift/S006-default-credentials.md +76 -0
  163. package/skill-assets/sunlint-code-quality/rules/swift/S007-output-encoding.md +96 -0
  164. package/skill-assets/sunlint-code-quality/rules/swift/S009-approved-crypto.md +86 -0
  165. package/skill-assets/sunlint-code-quality/rules/swift/S010-csprng.md +71 -0
  166. package/skill-assets/sunlint-code-quality/rules/swift/S011-insecure-deserialization.md +74 -0
  167. package/skill-assets/sunlint-code-quality/rules/swift/S012-secrets-management.md +81 -0
  168. package/skill-assets/sunlint-code-quality/rules/swift/S013-tls-connections.md +67 -0
  169. package/skill-assets/sunlint-code-quality/rules/swift/S017-parameterized-queries.md +86 -0
  170. package/skill-assets/sunlint-code-quality/rules/swift/S019-session-management.md +131 -0
  171. package/skill-assets/sunlint-code-quality/rules/swift/S020-kvc-injection.md +91 -0
  172. package/skill-assets/sunlint-code-quality/rules/swift/S025-input-validation.md +125 -0
  173. package/skill-assets/sunlint-code-quality/rules/swift/S029-brute-force-protection.md +120 -0
  174. package/skill-assets/sunlint-code-quality/rules/swift/S036-path-traversal.md +102 -0
  175. package/skill-assets/sunlint-code-quality/rules/swift/S039-tls-certificate-validation.md +109 -0
  176. package/skill-assets/sunlint-code-quality/rules/swift/S041-logout-invalidation.md +103 -0
  177. package/skill-assets/sunlint-code-quality/rules/swift/S043-password-hashing.md +116 -0
  178. package/skill-assets/sunlint-code-quality/rules/swift/S044-critical-changes-reauth.md +145 -0
  179. package/skill-assets/sunlint-code-quality/rules/swift/S045-debug-info-exposure.md +116 -0
  180. package/skill-assets/sunlint-code-quality/rules/swift/S046-unvalidated-redirect.md +140 -0
  181. package/skill-assets/sunlint-code-quality/rules/swift/S051-token-expiry.md +134 -0
  182. package/skill-assets/sunlint-code-quality/rules/swift/S053-jwt-validation.md +139 -0
  183. package/skill-assets/sunlint-code-quality/rules/swift/S059-background-snapshot-protection.md +113 -0
  184. package/skill-assets/sunlint-code-quality/rules/swift/S060-data-protection-api.md +106 -0
  185. package/skill-assets/sunlint-code-quality/rules/swift/S061-jailbreak-detection.md +132 -0
@@ -16,29 +16,45 @@ try {
16
16
  const parser = new SimpleRuleParser();
17
17
  const originRulesDir = path.join(__dirname, '..', 'origin-rules');
18
18
  const targetPath = path.join(__dirname, '..', 'config', 'rules', 'rules-registry-generated.json');
19
-
19
+
20
20
  console.log(`Source: ${originRulesDir}`);
21
21
  console.log(`Target: ${targetPath}`);
22
-
22
+
23
23
  // Parse all rules from origin-rules
24
24
  const allRules = parser.parseAllRules(originRulesDir);
25
-
25
+
26
26
  if (allRules.length === 0) {
27
27
  console.error('❌ No rules found in origin-rules directory');
28
28
  process.exit(1);
29
29
  }
30
-
30
+
31
31
  // Convert to registry format
32
32
  const registry = {
33
33
  rules: {}
34
34
  };
35
-
35
+
36
36
  allRules.forEach(rule => {
37
37
  if (rule.id) {
38
+ let category = rule.category || 'Common';
39
+ const id = rule.id;
40
+
41
+ // Smart category detection based on prefix
42
+ if (id.startsWith('S')) {
43
+ category = 'Security';
44
+ } else if (id.startsWith('C')) {
45
+ category = 'Common';
46
+ } else if (['RB', 'G', 'GN', 'J', 'PY', 'P'].some(p => id.startsWith(p))) {
47
+ category = 'Backend';
48
+ } else if (['T', 'R'].some(p => id.startsWith(p))) {
49
+ category = 'Frontend';
50
+ } else if (['K', 'SW', 'D'].some(p => id.startsWith(p))) {
51
+ category = 'Mobile';
52
+ }
53
+
38
54
  registry.rules[rule.id] = {
39
55
  name: rule.title || `${rule.id} Rule`,
40
56
  description: rule.description || 'No description available',
41
- category: rule.category || 'quality',
57
+ category: category,
42
58
  severity: rule.severity || 'major',
43
59
  languages: rule.language ? [rule.language] : ['All languages'],
44
60
  version: rule.version || '1.0.0',
@@ -50,37 +66,37 @@ try {
50
66
  };
51
67
  }
52
68
  });
53
-
69
+
54
70
  // Ensure target directory exists
55
71
  const targetDir = path.dirname(targetPath);
56
72
  if (!fs.existsSync(targetDir)) {
57
73
  fs.mkdirSync(targetDir, { recursive: true });
58
74
  }
59
-
75
+
60
76
  // Write registry file
61
77
  fs.writeFileSync(targetPath, JSON.stringify(registry, null, 2), 'utf8');
62
-
78
+
63
79
  const rulesCount = Object.keys(registry.rules).length;
64
80
  const fileSize = (fs.statSync(targetPath).size / 1024).toFixed(1);
65
-
81
+
66
82
  console.log(`✅ Generated registry with ${rulesCount} rules`);
67
83
  console.log(`📁 File: ${targetPath} (${fileSize} KB)`);
68
84
  console.log('');
69
85
  console.log('📊 Rules by category:');
70
-
86
+
71
87
  // Stats by category
72
88
  const categories = {};
73
89
  Object.values(registry.rules).forEach(rule => {
74
90
  const cat = rule.category || 'unknown';
75
91
  categories[cat] = (categories[cat] || 0) + 1;
76
92
  });
77
-
93
+
78
94
  Object.entries(categories)
79
- .sort(([,a], [,b]) => b - a)
95
+ .sort(([, a], [, b]) => b - a)
80
96
  .forEach(([category, count]) => {
81
97
  console.log(` ${category}: ${count} rules`);
82
98
  });
83
-
99
+
84
100
  } catch (error) {
85
101
  console.error('❌ Error generating registry:', error.message);
86
102
  console.error(error.stack);
@@ -9,7 +9,7 @@ metadata:
9
9
 
10
10
  # SunLint Code Quality & Security Standards
11
11
 
12
- Comprehensive code quality and security optimization guide for all projects, maintained by Sun* Engineering Excellence team. Contains **65 rules** across **6 priority categories**, organized by impact to guide automated code review and generation.
12
+ Comprehensive code quality and security optimization guide for all projects, maintained by Sun* Engineering Excellence team. Contains **75 rules** across **7 priority categories**, organized by impact to guide automated code review and generation.
13
13
 
14
14
  ## When to Apply
15
15
 
@@ -31,6 +31,7 @@ Reference these guidelines when:
31
31
  | 4 | Security - Cryptography & TLS | **HIGH** | 8 | `S0xx` |
32
32
  | 5 | Security - Data Protection | **HIGH** | 10 | `S0xx` |
33
33
  | 6 | Security - Logging & Monitoring | **MEDIUM** | 6 | `S0xx` |
34
+ | 7 | Language Specific (Go/Gin) | **CRITICAL/HIGH** | 10 | `Gxx`/`GNxx` |
34
35
 
35
36
  ---
36
37
 
@@ -173,4 +174,4 @@ For the complete guide with all rules expanded: `AGENTS.md`
173
174
 
174
175
  ---
175
176
 
176
- **Last Updated**: January 2026 | **Version**: 2.3 | **Maintainer**: Sun* Engineering Excellence
177
+ **Last Updated**: February 2026 | **Version**: 2.4.1 | **Maintainer**: Sun* Engineering Excellence
@@ -0,0 +1,45 @@
1
+ ---
2
+ title: Function Names Verb-Noun
3
+ impact: LOW
4
+ impactDescription: makes code self-documenting
5
+ tags: naming, functions, readability, conventions, quality
6
+ ---
7
+
8
+ ## Function Names Verb-Noun
9
+
10
+ Functions do things. Action verbs make purpose clear.
11
+
12
+ **Incorrect (vague names):**
13
+
14
+ ```dart
15
+ User user() { } // Noun only
16
+ void userData() { } // Noun only
17
+ void doSomething() { } // Vague
18
+ void handleStuff() { } // Vague
19
+ void manager() { } // Noun only
20
+ ```
21
+
22
+ **Correct (action verbs):**
23
+
24
+ ```dart
25
+ Future<User> getUser() async { }
26
+ void createUserAccount() { }
27
+ bool validateEmailFormat(String email) { }
28
+ double calculateTotalPrice(List<Item> items) { }
29
+ Future<void> sendConfirmationEmail(String email) async { }
30
+ String convertCurrencyToVnd(double amount) { }
31
+ ```
32
+
33
+ **Verb categories:**
34
+
35
+ | Category | Verbs |
36
+ |----------|-------|
37
+ | Retrieval | `get`, `fetch`, `find`, `load`, `query` |
38
+ | Creation | `create`, `build`, `make`, `generate` |
39
+ | Modification | `set`, `update`, `modify`, `change` |
40
+ | Deletion | `delete`, `remove`, `destroy`, `clear` |
41
+ | Validation | `validate`, `verify`, `check`, `ensure` |
42
+ | Computation | `calculate`, `compute`, `parse`, `format` |
43
+ | Boolean | `is`, `has`, `can`, `should`, `will` |
44
+
45
+ **Tools:** PR review, dart_analyzer
@@ -0,0 +1,53 @@
1
+ ---
2
+ title: Do Not Use Dead Code
3
+ impact: LOW
4
+ impactDescription: reduces codebase noise and app size
5
+ tags: dead-code, cleanup, maintenance, quality
6
+ ---
7
+
8
+ ## Do Not Use Dead Code
9
+
10
+ Dead code confuses readers and increases app size. Git history preserves deleted code.
11
+
12
+ **Incorrect (keeping dead code):**
13
+
14
+ ```dart
15
+ void processOrder(Order order) {
16
+ // Old implementation - keeping for reference
17
+ // final total = order.items.fold(0.0, (sum, item) {
18
+ // return sum + item.price * item.quantity;
19
+ // });
20
+
21
+ final total = calculateTotal(order);
22
+ return total;
23
+ }
24
+
25
+ // Unused function - someone might need it later
26
+ double legacyCalculation(List<Item> items) {
27
+ return items.length * 10.0;
28
+ }
29
+
30
+ import 'package:app/utils/unused_helper.dart'; // Never used
31
+ ```
32
+
33
+ **Correct (clean code):**
34
+
35
+ ```dart
36
+ void processOrder(Order order) {
37
+ final total = calculateTotal(order);
38
+ return total;
39
+ }
40
+
41
+ // Delete unused functions - git history preserves them
42
+ // Delete commented code - git history preserves it
43
+ // Remove unused imports
44
+ ```
45
+
46
+ **Types of dead code:**
47
+ - Commented-out code blocks
48
+ - Unused functions/classes/mixins
49
+ - Unused imports
50
+ - Unreachable code (after `return`/`throw`)
51
+ - Unused variables and parameters
52
+
53
+ **Tools:** dart analyze, `unused_import` lint rule, Code Review
@@ -0,0 +1,92 @@
1
+ ---
2
+ title: Use Dependency Injection
3
+ impact: HIGH
4
+ impactDescription: enables testability and loose coupling
5
+ tags: dependency-injection, testing, coupling, architecture, quality
6
+ ---
7
+
8
+ ## Use Dependency Injection
9
+
10
+ Direct instantiation creates tight coupling, making testing difficult and changes risky. DI enables mockability, replaceability, and testability.
11
+
12
+ **Incorrect (hardcoded dependencies):**
13
+
14
+ ```dart
15
+ class OrderService {
16
+ final _db = DatabaseHelper(); // Hardcoded dependency
17
+ final _mailer = EmailService(); // Hardcoded dependency
18
+
19
+ Future<Order> createOrder(OrderData data) async {
20
+ final order = await _db.insert('orders', data.toMap());
21
+ await _mailer.send(data.email, 'Order created');
22
+ return order;
23
+ }
24
+ }
25
+ ```
26
+
27
+ **Correct (injected dependencies):**
28
+
29
+ ```dart
30
+ abstract class IDatabase {
31
+ Future<Map<String, dynamic>> insert(String table, Map<String, dynamic> data);
32
+ }
33
+
34
+ abstract class IMailer {
35
+ Future<void> send(String to, String message);
36
+ }
37
+
38
+ class OrderService {
39
+ OrderService({
40
+ required IDatabase db,
41
+ required IMailer mailer,
42
+ }) : _db = db,
43
+ _mailer = mailer;
44
+
45
+ final IDatabase _db;
46
+ final IMailer _mailer;
47
+
48
+ Future<Order> createOrder(OrderData data) async {
49
+ final order = await _db.insert('orders', data.toMap());
50
+ await _mailer.send(data.email, 'Order created');
51
+ return order;
52
+ }
53
+ }
54
+
55
+ // Usage - production
56
+ final service = OrderService(
57
+ db: SqliteDatabase(path: dbPath),
58
+ mailer: SmtpMailer(host: smtpHost),
59
+ );
60
+
61
+ // Usage - testing
62
+ final service = OrderService(
63
+ db: MockDatabase(),
64
+ mailer: MockMailer(),
65
+ );
66
+ ```
67
+
68
+ **With get_it or injectable:**
69
+
70
+ ```dart
71
+ // Using get_it
72
+ @injectable
73
+ class OrderService {
74
+ OrderService(this._db, this._mailer);
75
+
76
+ final IDatabase _db;
77
+ final IMailer _mailer;
78
+ }
79
+
80
+ // Register
81
+ GetIt.instance.registerFactory<OrderService>(
82
+ () => OrderService(GetIt.instance(), GetIt.instance()),
83
+ );
84
+ ```
85
+
86
+ **Benefits:**
87
+ - Easy mocking for unit tests
88
+ - Swappable implementations
89
+ - Clear dependencies visible in constructor
90
+ - Supports interface-based design
91
+
92
+ **Tools:** get_it, injectable, mockito, mocktail
@@ -0,0 +1,62 @@
1
+ ---
2
+ title: No Business Logic In Constructors
3
+ impact: HIGH
4
+ impactDescription: ensures predictable object initialization
5
+ tags: constructor, initialization, side-effects, patterns, quality
6
+ ---
7
+
8
+ ## No Business Logic In Constructors
9
+
10
+ Constructors should only initialize state. Side effects in constructors are unexpected and make testing difficult.
11
+
12
+ **Incorrect (logic in constructor):**
13
+
14
+ ```dart
15
+ class UserRepository {
16
+ UserRepository(String configPath) {
17
+ // BAD: File I/O in constructor
18
+ final file = File(configPath).readAsStringSync();
19
+ final config = jsonDecode(file) as Map<String, dynamic>;
20
+
21
+ // BAD: Network call in constructor
22
+ _client = HttpClient()..open('GET', config['apiUrl'] as String, 80, '/init');
23
+
24
+ // BAD: Mutation side-effects
25
+ _cache.clear();
26
+
27
+ // BAD: Logging with side effects
28
+ print('UserRepository initialized');
29
+ }
30
+ }
31
+ ```
32
+
33
+ **Correct (factory method for async / complex init):**
34
+
35
+ ```dart
36
+ class UserRepository {
37
+ UserRepository({
38
+ required HttpClient client,
39
+ required AppConfig config,
40
+ }) : _client = client, // Only assignments
41
+ _config = config;
42
+
43
+ final HttpClient _client;
44
+ final AppConfig _config;
45
+
46
+ // Factory method for complex initialization
47
+ static Future<UserRepository> create(String configPath) async {
48
+ final file = await File(configPath).readAsString();
49
+ final config = AppConfig.fromJson(jsonDecode(file) as Map<String, dynamic>);
50
+
51
+ final client = HttpClient();
52
+ await client.initialize(config.apiUrl);
53
+
54
+ return UserRepository(client: client, config: config);
55
+ }
56
+ }
57
+
58
+ // Usage
59
+ final repo = await UserRepository.create('./config.json');
60
+ ```
61
+
62
+ **Tools:** Code Review, dart_analyzer
@@ -0,0 +1,57 @@
1
+ ---
2
+ title: Do Not Throw Generic Errors
3
+ impact: HIGH
4
+ impactDescription: enables proper error handling and monitoring
5
+ tags: error-handling, exceptions, custom-errors, debugging, quality
6
+ ---
7
+
8
+ ## Do Not Throw Generic Errors
9
+
10
+ Generic errors lack context needed for debugging. They make it impossible to distinguish between error types for proper handling.
11
+
12
+ **Incorrect (generic errors):**
13
+
14
+ ```dart
15
+ if (user == null) {
16
+ throw Exception('error');
17
+ }
18
+
19
+ if (!isValid) {
20
+ throw Exception();
21
+ }
22
+
23
+ if (response.statusCode != 200) {
24
+ throw Exception('Failed');
25
+ }
26
+ ```
27
+
28
+ **Correct (specific custom exceptions):**
29
+
30
+ ```dart
31
+ if (user == null) {
32
+ throw UserNotFoundException('User with ID $userId not found');
33
+ }
34
+
35
+ if (!isValid) {
36
+ throw ValidationException(
37
+ field: 'email',
38
+ message: 'Email format is invalid',
39
+ value: email,
40
+ );
41
+ }
42
+
43
+ if (response.statusCode != 200) {
44
+ throw ApiException(
45
+ statusCode: response.statusCode,
46
+ message: 'API request failed',
47
+ endpoint: '/users/$userId',
48
+ );
49
+ }
50
+ ```
51
+
52
+ Custom exceptions should include:
53
+ - Descriptive message with context
54
+ - Relevant data for debugging
55
+ - Error code for programmatic handling
56
+
57
+ **Tools:** Code Review, dart_analyzer
@@ -0,0 +1,50 @@
1
+ ---
2
+ title: Do Not Use Error Log For Non-critical
3
+ impact: HIGH
4
+ impactDescription: prevents alert fatigue and log noise
5
+ tags: logging, log-levels, error, observability, quality
6
+ ---
7
+
8
+ ## Do Not Use Error Log For Non-critical
9
+
10
+ Incorrect log levels cause alert fatigue and hide real issues. When everything is an "error", nothing is.
11
+
12
+ **Incorrect (overusing error level):**
13
+
14
+ ```dart
15
+ // NOT an error - expected business case
16
+ logger.e('User entered wrong password');
17
+
18
+ // NOT an error - validation failure
19
+ logger.e('Email format invalid');
20
+
21
+ // NOT an error - retry in progress
22
+ logger.e('Retry attempt 2 of 5');
23
+ ```
24
+
25
+ **Correct (appropriate log levels):**
26
+
27
+ ```dart
28
+ // WARN - recoverable, may need attention
29
+ logger.w('Payment retry attempt', error: {'attempt': 2, 'maxAttempts': 5});
30
+
31
+ // INFO - normal business events
32
+ logger.i('Login failed - invalid password', {'userId': userId, 'attempts': 3});
33
+
34
+ // DEBUG - detailed troubleshooting
35
+ logger.d('Validation failed', error: {'field': 'email'});
36
+
37
+ // ERROR - only for actual system / unrecoverable failures
38
+ logger.e('Database connection lost', error: e, stackTrace: st);
39
+ ```
40
+
41
+ **Log Level Guide (using `logger` package):**
42
+
43
+ | Method | Level | Use For |
44
+ |--------|-------|---------|
45
+ | `logger.e()` | ERROR | System failures, crashes, unrecoverable |
46
+ | `logger.w()` | WARN | Potential issues, degraded performance |
47
+ | `logger.i()` | INFO | Business events, state changes |
48
+ | `logger.d()` | DEBUG | Detailed troubleshooting |
49
+
50
+ **Tools:** logger package, Code Review
@@ -0,0 +1,46 @@
1
+ ---
2
+ title: Do Not Import Unused Modules
3
+ impact: LOW
4
+ impactDescription: reduces app size and improves clarity
5
+ tags: imports, cleanup, bundle-size, quality
6
+ ---
7
+
8
+ ## Do Not Import Unused Modules
9
+
10
+ Unused imports add noise and may increase app size.
11
+
12
+ **Incorrect (unused imports):**
13
+
14
+ ```dart
15
+ import 'package:app/models/user.dart';
16
+ import 'package:app/models/order.dart'; // Never used
17
+ import 'package:app/utils/date_utils.dart'; // Never used
18
+ import 'package:intl/intl.dart'; // Never used
19
+
20
+ // Only User is actually used
21
+ User getUser(String id) {
22
+ return userRepository.findById(id);
23
+ }
24
+ ```
25
+
26
+ **Correct (only needed imports):**
27
+
28
+ ```dart
29
+ import 'package:app/models/user.dart';
30
+
31
+ User getUser(String id) {
32
+ return userRepository.findById(id);
33
+ }
34
+ ```
35
+
36
+ **Enable via analysis_options.yaml:**
37
+
38
+ ```yaml
39
+ # analysis_options.yaml
40
+ linter:
41
+ rules:
42
+ - unused_import
43
+ - avoid_unused_constructor_parameters
44
+ ```
45
+
46
+ **Tools:** dart analyze, IDE auto-organize imports (Cmd/Ctrl+Shift+O)
@@ -0,0 +1,50 @@
1
+ ---
2
+ title: Do Not Leave Unused Variables
3
+ impact: LOW
4
+ impactDescription: reduces code noise and potential bugs
5
+ tags: variables, cleanup, quality
6
+ ---
7
+
8
+ ## Do Not Leave Unused Variables
9
+
10
+ Unused variables suggest incomplete refactoring or bugs.
11
+
12
+ **Incorrect (unused variables):**
13
+
14
+ ```dart
15
+ void processOrder(Order order) {
16
+ final user = order.user; // Never used
17
+ final total = order.total; // Never used
18
+ final items = order.items;
19
+
20
+ return items.map((i) => i.name).toList();
21
+ }
22
+ ```
23
+
24
+ **Correct (only needed variables):**
25
+
26
+ ```dart
27
+ void processOrder(Order order) {
28
+ return order.items.map((i) => i.name).toList();
29
+ }
30
+
31
+ // If destructuring/pattern matching, prefix with _ for intentionally ignored
32
+ void handleEvent(Map<String, dynamic> event) {
33
+ final type = event['type'] as String;
34
+ final _ = event['payload']; // Intentionally ignored
35
+ print('Event: $type');
36
+ }
37
+ ```
38
+
39
+ **Enable via analysis_options.yaml:**
40
+
41
+ ```yaml
42
+ # analysis_options.yaml
43
+ linter:
44
+ rules:
45
+ - unused_local_variable
46
+ - unused_element
47
+ - avoid_unused_constructor_parameters
48
+ ```
49
+
50
+ **Tools:** dart analyze, `unused_local_variable` lint rule
@@ -0,0 +1,56 @@
1
+ ---
2
+ title: No Duplicate Variable Names In Scope
3
+ impact: HIGH
4
+ impactDescription: prevents shadowing bugs
5
+ tags: variables, shadowing, scope, quality
6
+ ---
7
+
8
+ ## No Duplicate Variable Names In Scope
9
+
10
+ Variable shadowing causes subtle bugs where inner variables hide outer ones.
11
+
12
+ **Incorrect (shadowed variables):**
13
+
14
+ ```dart
15
+ final user = getCurrentUser();
16
+
17
+ void processOrder(Order order) {
18
+ final user = order.user; // Shadows outer user!
19
+
20
+ // Which user is this?
21
+ print(user.name);
22
+ }
23
+
24
+ // Same name in nested scope
25
+ for (final item in items) {
26
+ final item = transform(item); // Shadows loop variable!
27
+ }
28
+ ```
29
+
30
+ **Correct (unique names):**
31
+
32
+ ```dart
33
+ final currentUser = getCurrentUser();
34
+
35
+ void processOrder(Order order) {
36
+ final orderUser = order.user; // Clear distinction
37
+
38
+ print(orderUser.name);
39
+ }
40
+
41
+ // Different names in nested scope
42
+ for (final item in items) {
43
+ final transformedItem = transform(item);
44
+ }
45
+ ```
46
+
47
+ **Enable via analysis_options.yaml:**
48
+
49
+ ```yaml
50
+ # analysis_options.yaml
51
+ linter:
52
+ rules:
53
+ - no_leading_underscores_for_local_identifiers
54
+ ```
55
+
56
+ **Tools:** dart analyze, Code Review