@sun-asterisk/sunlint 1.0.5

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 (192) hide show
  1. package/CHANGELOG.md +202 -0
  2. package/LICENSE +21 -0
  3. package/README.md +490 -0
  4. package/cli-legacy.js +355 -0
  5. package/cli.js +35 -0
  6. package/config/default.json +22 -0
  7. package/config/presets/beginner.json +36 -0
  8. package/config/presets/ci.json +46 -0
  9. package/config/presets/recommended.json +24 -0
  10. package/config/presets/strict.json +32 -0
  11. package/config/rules-registry.json +681 -0
  12. package/config/sunlint-schema.json +166 -0
  13. package/config/typescript/custom-rules-new.js +0 -0
  14. package/config/typescript/custom-rules.js +9 -0
  15. package/config/typescript/eslint.config.js +110 -0
  16. package/config/typescript/package-lock.json +1585 -0
  17. package/config/typescript/package.json +13 -0
  18. package/config/typescript/security-rules/index.js +90 -0
  19. package/config/typescript/security-rules/s005-no-origin-auth.js +95 -0
  20. package/config/typescript/security-rules/s006-activation-recovery-secret-not-plaintext.js +69 -0
  21. package/config/typescript/security-rules/s008-crypto-agility.js +62 -0
  22. package/config/typescript/security-rules/s009-no-insecure-crypto.js +103 -0
  23. package/config/typescript/security-rules/s010-no-insecure-random-in-sensitive-context.js +123 -0
  24. package/config/typescript/security-rules/s011-no-insecure-uuid.js +66 -0
  25. package/config/typescript/security-rules/s012-hardcode-secret.js +71 -0
  26. package/config/typescript/security-rules/s014-insecure-tls-version.js +50 -0
  27. package/config/typescript/security-rules/s015-insecure-tls-certificate.js +43 -0
  28. package/config/typescript/security-rules/s016-sensitive-query-parameter.js +59 -0
  29. package/config/typescript/security-rules/s017-no-sql-injection.js +193 -0
  30. package/config/typescript/security-rules/s018-positive-input-validation.js +56 -0
  31. package/config/typescript/security-rules/s019-no-raw-user-input-in-email.js +113 -0
  32. package/config/typescript/security-rules/s020-no-eval-dynamic-execution.js +89 -0
  33. package/config/typescript/security-rules/s022-output-encoding.js +78 -0
  34. package/config/typescript/security-rules/s023-no-json-injection.js +300 -0
  35. package/config/typescript/security-rules/s025-server-side-input-validation.js +217 -0
  36. package/config/typescript/security-rules/s026-json-schema-validation.js +68 -0
  37. package/config/typescript/security-rules/s027-no-hardcoded-secrets.js +80 -0
  38. package/config/typescript/security-rules/s029-require-csrf-protection.js +79 -0
  39. package/config/typescript/security-rules/s030-no-directory-browsing.js +78 -0
  40. package/config/typescript/security-rules/s033-require-samesite-cookie.js +80 -0
  41. package/config/typescript/security-rules/s034-require-host-cookie-prefix.js +77 -0
  42. package/config/typescript/security-rules/s035-cookie-specific-path.js +74 -0
  43. package/config/typescript/security-rules/s036-no-unsafe-file-include.js +68 -0
  44. package/config/typescript/security-rules/s037-require-anti-cache-headers.js +70 -0
  45. package/config/typescript/security-rules/s038-no-version-disclosure.js +74 -0
  46. package/config/typescript/security-rules/s039-no-session-token-in-url.js +63 -0
  47. package/config/typescript/security-rules/s041-require-session-invalidate-on-logout.js +211 -0
  48. package/config/typescript/security-rules/s042-require-periodic-reauthentication.js +294 -0
  49. package/config/typescript/security-rules/s043-terminate-sessions-on-password-change.js +254 -0
  50. package/config/typescript/security-rules/s044-require-full-session-for-sensitive-operations.js +292 -0
  51. package/config/typescript/security-rules/s045-anti-automation-controls.js +46 -0
  52. package/config/typescript/security-rules/s046-secure-notification-on-auth-change.js +44 -0
  53. package/config/typescript/security-rules/s048-password-credential-recovery.js +54 -0
  54. package/config/typescript/security-rules/s050-session-token-weak-hash.js +94 -0
  55. package/config/typescript/security-rules/s052-secure-random-authentication-code.js +66 -0
  56. package/config/typescript/security-rules/s054-verification-default-account.js +109 -0
  57. package/config/typescript/security-rules/s057-utc-logging.js +54 -0
  58. package/config/typescript/security-rules/s058-no-ssrf.js +73 -0
  59. package/config/typescript/test-s005-working.ts +22 -0
  60. package/config/typescript/tsconfig.json +29 -0
  61. package/core/ai-analyzer.js +169 -0
  62. package/core/analysis-orchestrator.js +705 -0
  63. package/core/cli-action-handler.js +230 -0
  64. package/core/cli-program.js +106 -0
  65. package/core/config-manager.js +396 -0
  66. package/core/config-merger.js +136 -0
  67. package/core/config-override-processor.js +74 -0
  68. package/core/config-preset-resolver.js +65 -0
  69. package/core/config-source-loader.js +152 -0
  70. package/core/config-validator.js +126 -0
  71. package/core/dependency-manager.js +105 -0
  72. package/core/eslint-engine-service.js +312 -0
  73. package/core/eslint-instance-manager.js +104 -0
  74. package/core/eslint-integration-service.js +363 -0
  75. package/core/git-utils.js +170 -0
  76. package/core/multi-rule-runner.js +239 -0
  77. package/core/output-service.js +250 -0
  78. package/core/report-generator.js +320 -0
  79. package/core/rule-mapping-service.js +309 -0
  80. package/core/rule-selection-service.js +121 -0
  81. package/core/sunlint-engine-service.js +23 -0
  82. package/core/typescript-analyzer.js +262 -0
  83. package/core/typescript-engine.js +313 -0
  84. package/docs/AI.md +163 -0
  85. package/docs/ARCHITECTURE.md +78 -0
  86. package/docs/CI-CD-GUIDE.md +315 -0
  87. package/docs/COMMAND-EXAMPLES.md +256 -0
  88. package/docs/DEBUG.md +86 -0
  89. package/docs/DISTRIBUTION.md +153 -0
  90. package/docs/ESLINT-INTEGRATION-STRATEGY.md +392 -0
  91. package/docs/ESLINT_INTEGRATION.md +238 -0
  92. package/docs/FOLDER_STRUCTURE.md +59 -0
  93. package/docs/HEURISTIC_VS_AI.md +113 -0
  94. package/docs/README.md +32 -0
  95. package/docs/RELEASE_GUIDE.md +230 -0
  96. package/docs/RULE-RESPONSIBILITY-MATRIX.md +204 -0
  97. package/eslint-integration/.eslintrc.js +98 -0
  98. package/eslint-integration/cli.js +35 -0
  99. package/eslint-integration/eslint-plugin-custom/c002-no-duplicate-code.js +204 -0
  100. package/eslint-integration/eslint-plugin-custom/c003-no-vague-abbreviations.js +246 -0
  101. package/eslint-integration/eslint-plugin-custom/c006-function-name-verb-noun.js +207 -0
  102. package/eslint-integration/eslint-plugin-custom/c010-limit-block-nesting.js +90 -0
  103. package/eslint-integration/eslint-plugin-custom/c013-no-dead-code.js +43 -0
  104. package/eslint-integration/eslint-plugin-custom/c014-abstract-dependency-preferred.js +38 -0
  105. package/eslint-integration/eslint-plugin-custom/c017-limit-constructor-logic.js +39 -0
  106. package/eslint-integration/eslint-plugin-custom/c018-no-generic-throw.js +335 -0
  107. package/eslint-integration/eslint-plugin-custom/c023-no-duplicate-variable-name-in-scope.js +142 -0
  108. package/eslint-integration/eslint-plugin-custom/c027-limit-function-nesting.js +50 -0
  109. package/eslint-integration/eslint-plugin-custom/c029-catch-block-logging.js +80 -0
  110. package/eslint-integration/eslint-plugin-custom/c030-use-custom-error-classes.js +294 -0
  111. package/eslint-integration/eslint-plugin-custom/c034-no-implicit-return.js +34 -0
  112. package/eslint-integration/eslint-plugin-custom/c035-no-empty-catch.js +32 -0
  113. package/eslint-integration/eslint-plugin-custom/c041-no-config-inline.js +64 -0
  114. package/eslint-integration/eslint-plugin-custom/c042-boolean-name-prefix.js +406 -0
  115. package/eslint-integration/eslint-plugin-custom/c043-no-console-or-print.js +300 -0
  116. package/eslint-integration/eslint-plugin-custom/c047-no-duplicate-retry-logic.js +239 -0
  117. package/eslint-integration/eslint-plugin-custom/c048-no-var-declaration.js +31 -0
  118. package/eslint-integration/eslint-plugin-custom/c076-one-assert-per-test.js +184 -0
  119. package/eslint-integration/eslint-plugin-custom/index.js +155 -0
  120. package/eslint-integration/eslint-plugin-custom/package.json +13 -0
  121. package/eslint-integration/eslint-plugin-custom/package.json.bak +9 -0
  122. package/eslint-integration/eslint-plugin-custom/s003-no-unvalidated-redirect.js +86 -0
  123. package/eslint-integration/eslint-plugin-custom/s005-no-origin-auth.js +95 -0
  124. package/eslint-integration/eslint-plugin-custom/s006-activation-recovery-secret-not-plaintext.js +69 -0
  125. package/eslint-integration/eslint-plugin-custom/s008-crypto-agility.js +62 -0
  126. package/eslint-integration/eslint-plugin-custom/s009-no-insecure-crypto.js +103 -0
  127. package/eslint-integration/eslint-plugin-custom/s010-no-insecure-random-in-sensitive-context.js +123 -0
  128. package/eslint-integration/eslint-plugin-custom/s011-no-insecure-uuid.js +66 -0
  129. package/eslint-integration/eslint-plugin-custom/s012-hardcode-secret.js +71 -0
  130. package/eslint-integration/eslint-plugin-custom/s014-insecure-tls-version.js +50 -0
  131. package/eslint-integration/eslint-plugin-custom/s015-insecure-tls-certificate.js +43 -0
  132. package/eslint-integration/eslint-plugin-custom/s016-sensitive-query-parameter.js +59 -0
  133. package/eslint-integration/eslint-plugin-custom/s017-no-sql-injection.js +193 -0
  134. package/eslint-integration/eslint-plugin-custom/s018-positive-input-validation.js +56 -0
  135. package/eslint-integration/eslint-plugin-custom/s019-no-raw-user-input-in-email.js +113 -0
  136. package/eslint-integration/eslint-plugin-custom/s020-no-eval-dynamic-execution.js +89 -0
  137. package/eslint-integration/eslint-plugin-custom/s022-output-encoding.js +78 -0
  138. package/eslint-integration/eslint-plugin-custom/s023-no-json-injection.js +300 -0
  139. package/eslint-integration/eslint-plugin-custom/s025-server-side-input-validation.js +217 -0
  140. package/eslint-integration/eslint-plugin-custom/s026-json-schema-validation.js +68 -0
  141. package/eslint-integration/eslint-plugin-custom/s027-no-hardcoded-secrets.js +80 -0
  142. package/eslint-integration/eslint-plugin-custom/s029-require-csrf-protection.js +79 -0
  143. package/eslint-integration/eslint-plugin-custom/s030-no-directory-browsing.js +78 -0
  144. package/eslint-integration/eslint-plugin-custom/s033-require-samesite-cookie.js +80 -0
  145. package/eslint-integration/eslint-plugin-custom/s034-require-host-cookie-prefix.js +77 -0
  146. package/eslint-integration/eslint-plugin-custom/s035-cookie-specific-path.js +74 -0
  147. package/eslint-integration/eslint-plugin-custom/s036-no-unsafe-file-include.js +68 -0
  148. package/eslint-integration/eslint-plugin-custom/s037-require-anti-cache-headers.js +70 -0
  149. package/eslint-integration/eslint-plugin-custom/s038-no-version-disclosure.js +74 -0
  150. package/eslint-integration/eslint-plugin-custom/s039-no-session-token-in-url.js +63 -0
  151. package/eslint-integration/eslint-plugin-custom/s041-require-session-invalidate-on-logout.js +211 -0
  152. package/eslint-integration/eslint-plugin-custom/s042-require-periodic-reauthentication.js +294 -0
  153. package/eslint-integration/eslint-plugin-custom/s043-terminate-sessions-on-password-change.js +254 -0
  154. package/eslint-integration/eslint-plugin-custom/s044-require-full-session-for-sensitive-operations.js +292 -0
  155. package/eslint-integration/eslint-plugin-custom/s045-anti-automation-controls.js +46 -0
  156. package/eslint-integration/eslint-plugin-custom/s046-secure-notification-on-auth-change.js +44 -0
  157. package/eslint-integration/eslint-plugin-custom/s047-secure-random-passwords.js +108 -0
  158. package/eslint-integration/eslint-plugin-custom/s048-password-credential-recovery.js +54 -0
  159. package/eslint-integration/eslint-plugin-custom/s050-session-token-weak-hash.js +94 -0
  160. package/eslint-integration/eslint-plugin-custom/s052-secure-random-authentication-code.js +66 -0
  161. package/eslint-integration/eslint-plugin-custom/s054-verification-default-account.js +109 -0
  162. package/eslint-integration/eslint-plugin-custom/s055-verification-rest-check-the-incoming-content-type.js +143 -0
  163. package/eslint-integration/eslint-plugin-custom/s057-utc-logging.js +54 -0
  164. package/eslint-integration/eslint-plugin-custom/s058-no-ssrf.js +73 -0
  165. package/eslint-integration/eslint-plugin-custom/t002-interface-prefix-i.js +42 -0
  166. package/eslint-integration/eslint-plugin-custom/t003-ts-ignore-reason.js +48 -0
  167. package/eslint-integration/eslint-plugin-custom/t004-interface-public-only.js +160 -0
  168. package/eslint-integration/eslint-plugin-custom/t007-no-fn-in-constructor.js +52 -0
  169. package/eslint-integration/eslint-plugin-custom/t011-no-real-time-dependency.js +175 -0
  170. package/eslint-integration/eslint-plugin-custom/t019-no-empty-type.js +95 -0
  171. package/eslint-integration/eslint-plugin-custom/t025-no-nested-union-tuple.js +48 -0
  172. package/eslint-integration/eslint-plugin-custom/t026-limit-nested-generics.js +377 -0
  173. package/eslint-integration/eslint.config.js +125 -0
  174. package/eslint-integration/eslint.config.simple.js +24 -0
  175. package/eslint-integration/node_modules/eslint-plugin-custom/package.json +0 -0
  176. package/eslint-integration/package.json +23 -0
  177. package/eslint-integration/sample.ts +53 -0
  178. package/eslint-integration/test-s003.js +5 -0
  179. package/eslint-integration/tsconfig.json +27 -0
  180. package/examples/.github/workflows/code-quality.yml +111 -0
  181. package/examples/.sunlint.json +42 -0
  182. package/examples/README.md +47 -0
  183. package/examples/package.json +33 -0
  184. package/package.json +100 -0
  185. package/rules/C006_function_naming/analyzer.js +338 -0
  186. package/rules/C006_function_naming/config.json +86 -0
  187. package/rules/C019_log_level_usage/analyzer.js +359 -0
  188. package/rules/C019_log_level_usage/config.json +121 -0
  189. package/rules/C029_catch_block_logging/analyzer.js +339 -0
  190. package/rules/C029_catch_block_logging/config.json +59 -0
  191. package/rules/C031_validation_separation/README.md +72 -0
  192. package/rules/C031_validation_separation/analyzer.js +186 -0
@@ -0,0 +1,204 @@
1
+ # Rule Responsibility Matrix
2
+
3
+ ## Overview
4
+ This document defines clear responsibilities between ESLint and SunLint to avoid duplication and maximize efficiency.
5
+
6
+ ## Current Rule Distribution
7
+
8
+ ### ESLint Custom Rules (29 rules)
9
+ **Primary Responsibilities:**
10
+ - ✅ Syntactic/structural checks
11
+ - ✅ IDE integration & fast feedback
12
+ - ✅ Standard coding conventions
13
+ - ✅ TypeScript-specific features
14
+
15
+ | Rule ID | Name | Type | Rationale |
16
+ |---------|------|------|-----------|
17
+ | C002 | no-duplicate-code | Structural | AST-based duplicate detection |
18
+ | C003 | no-vague-abbreviations | Naming | Simple naming convention |
19
+ | C006 | function-name-verb-noun | Naming | **ACTIVE** - Simple naming check |
20
+ | C008 | declare-variables-near-usage | Structural | Scope analysis |
21
+ | C010 | limit-block-nesting | Structural | Nesting depth check |
22
+ | C013 | no-dead-code | Structural | Dead code detection |
23
+ | C014 | abstract-dependency-preferred | Structural | DI pattern detection |
24
+ | C017 | limit-constructor-logic | Structural | Constructor complexity |
25
+ | C018 | no-generic-throw | Structural | Error handling pattern |
26
+ | C023 | no-duplicate-variable-name | Structural | Variable naming |
27
+ | C024 | no-hardcode-constants | Structural | Constant extraction |
28
+ | C027 | limit-function-nesting | Structural | Function nesting |
29
+ | C028 | no-silent-catch | Structural | **DEPRECATED** - Use SunLint C029 |
30
+ | C030 | use-custom-error-classes | Structural | Error class pattern |
31
+ | C034 | no-implicit-return | Structural | Return statement check |
32
+ | C035 | no-empty-catch | Structural | Empty catch detection |
33
+ | C037 | error-handler-log-input | Structural | Error logging pattern |
34
+ | C041 | no-config-inline | Structural | Configuration separation |
35
+ | C042 | boolean-name-prefix | Naming | Boolean naming convention |
36
+ | C043 | no-console-or-print | Structural | Console usage detection |
37
+ | C047 | no-duplicate-retry-logic | Structural | Retry pattern detection |
38
+ | C048 | no-var-declaration | Structural | Variable declaration |
39
+ | C076 | one-assert-per-test | Test | Test assertion pattern |
40
+ | T002 | interface-prefix-i | TypeScript | Interface naming |
41
+ | T003 | ts-ignore-reason | TypeScript | TypeScript ignore usage |
42
+ | T004 | interface-public-only | TypeScript | Interface structure |
43
+ | T007 | no-fn-in-constructor | TypeScript | Constructor pattern |
44
+ | T011 | no-real-time-dependency | Test | Test isolation |
45
+ | T019 | no-empty-type | TypeScript | Type definition |
46
+ | T025 | no-nested-union-tuple | TypeScript | Type complexity |
47
+ | T026 | limit-nested-generics | TypeScript | Generic complexity |
48
+
49
+ ### SunLint Rules (4 rules)
50
+ **Primary Responsibilities:**
51
+ - ✅ Complex semantic analysis
52
+ - ✅ Cross-file/project analysis
53
+ - ✅ Performance-critical batch processing
54
+ - ✅ Business rule logic
55
+
56
+ | Rule ID | Name | Type | Rationale |
57
+ |---------|------|------|-----------|
58
+ | C006 | function_naming | Naming | **DISABLED** - Use ESLint version |
59
+ | C019 | log_level_usage | Semantic | **ACTIVE** - Complex log context analysis |
60
+ | C029 | catch_block_logging | Semantic | **ACTIVE** - Enhanced error context analysis |
61
+ | C031 | validation_separation | Architectural | **ACTIVE** - Cross-function validation pattern |
62
+
63
+ ## Rule Overlap Resolution
64
+
65
+ ### ✅ Resolved Overlaps
66
+
67
+ #### C006 - Function Naming
68
+ - **Decision**: Use ESLint version
69
+ - **Rationale**: Simple naming check, better IDE integration
70
+ - **Action**: SunLint C006 disabled in config
71
+
72
+ #### C028/C029 - Catch Block Logging
73
+ - **Decision**: Use SunLint C029
74
+ - **Rationale**: More sophisticated error context analysis
75
+ - **Action**: ESLint C028 should be deprecated in favor of SunLint C029
76
+
77
+ ### 🔄 Planned Enhancements
78
+
79
+ #### C029 - Enhanced Catch Block Logging
80
+ Current SunLint C029 should be enhanced to fully replace ESLint C028:
81
+
82
+ **ESLint C028 capabilities:**
83
+ - Detects silent catch blocks
84
+ - Basic error logging requirements
85
+
86
+ **SunLint C029 enhancements needed:**
87
+ - All C028 functionality
88
+ - Context-aware error logging
89
+ - Stack trace preservation analysis
90
+ - Error correlation tracking
91
+
92
+ ## Integration Strategy
93
+
94
+ ### Phase 1: Current State (Implemented)
95
+ ```json
96
+ // .eslintrc.cjs - ESLint handles most rules
97
+ {
98
+ "rules": {
99
+ "custom/c006": "warn", // Active in ESLint
100
+ "custom/c029": "warn", // Will be deprecated
101
+ // ... other ESLint rules
102
+ }
103
+ }
104
+
105
+ // .sunlint.json - SunLint handles specialized rules
106
+ {
107
+ "rules": {
108
+ "C006": "off", // Disabled - use ESLint
109
+ "C019": true, // Active - unique to SunLint
110
+ "C029": "error", // Active - enhanced version
111
+ "C031": true // Active - unique to SunLint
112
+ }
113
+ }
114
+ ```
115
+
116
+ ### Phase 2: ESLint Adapter (Planned)
117
+ ```json
118
+ // .sunlint.json - Unified configuration
119
+ {
120
+ "rules": {
121
+ "C019": true,
122
+ "C029": true,
123
+ "C031": true,
124
+ // ESLint rules via adapter
125
+ "eslint:custom/c003": true,
126
+ "eslint:custom/c006": true,
127
+ "eslint:custom/c042": true
128
+ },
129
+ "eslintAdapter": {
130
+ "configPath": ".eslintrc.cjs",
131
+ "rules": ["custom/c003", "custom/c006", "custom/c042"]
132
+ }
133
+ }
134
+ ```
135
+
136
+ ## Migration Guidelines
137
+
138
+ ### Rules to Keep in ESLint
139
+ **Criteria:**
140
+ - Simple syntactic checks
141
+ - IDE integration critical
142
+ - TypeScript-specific features
143
+ - Standard conventions
144
+
145
+ **Examples:**
146
+ - C003 (Variable naming)
147
+ - C042 (Boolean naming)
148
+ - T002 (Interface prefix)
149
+ - T003 (TypeScript ignore)
150
+
151
+ ### Rules to Migrate to SunLint
152
+ **Criteria:**
153
+ - Complex semantic analysis
154
+ - Cross-file analysis needed
155
+ - Performance-critical
156
+ - Business rule logic
157
+
158
+ **Candidates:**
159
+ - C014 (Dependency Injection) - Cross-file analysis
160
+ - C034 (Data fetching separation) - Service layer analysis
161
+ - C040 (File execution order) - Project-level analysis
162
+
163
+ ### Rules to Enhance in SunLint
164
+ **Current:**
165
+ - C029 (Catch block logging) - Enhance to replace C028
166
+ - C031 (Validation separation) - Add cross-file validation
167
+
168
+ ## Testing Strategy
169
+
170
+ ### Rule Compatibility Testing
171
+ 1. **Overlap Testing**: Ensure no conflicting reports
172
+ 2. **Performance Testing**: Compare combined vs individual execution
173
+ 3. **Accuracy Testing**: Validate rule logic equivalence
174
+
175
+ ### Integration Testing
176
+ 1. **CI/CD Pipeline**: Test unified reporting
177
+ 2. **IDE Integration**: Verify ESLint feedback still works
178
+ 3. **Configuration**: Test rule enable/disable scenarios
179
+
180
+ ## Monitoring & Maintenance
181
+
182
+ ### Performance Metrics
183
+ - Combined analysis time
184
+ - Memory usage comparison
185
+ - CI/CD pipeline impact
186
+
187
+ ### Quality Metrics
188
+ - Rule coverage completeness
189
+ - False positive rates
190
+ - Developer satisfaction
191
+
192
+ ### Process Metrics
193
+ - Configuration complexity
194
+ - Maintenance overhead
195
+ - Team adoption rate
196
+
197
+ ## Decision Log
198
+
199
+ | Date | Decision | Rationale |
200
+ |------|----------|-----------|
201
+ | 2024-01-XX | Disable SunLint C006 | ESLint version sufficient, better IDE integration |
202
+ | 2024-01-XX | Keep SunLint C019 | Unique semantic analysis capability |
203
+ | 2024-01-XX | Enhance SunLint C029 | Replace ESLint C028 with better analysis |
204
+ | 2024-01-XX | Keep SunLint C031 | Unique architectural analysis |
@@ -0,0 +1,98 @@
1
+ // ESLint Legacy Configuration for SunLint (ESLint v8.x compatibility)
2
+ // Following Rule C005: Single responsibility - ESLint configuration
3
+ module.exports = {
4
+ env: {
5
+ es2022: true,
6
+ node: true,
7
+ browser: true
8
+ },
9
+
10
+ parser: '@typescript-eslint/parser',
11
+
12
+ parserOptions: {
13
+ ecmaVersion: 2022,
14
+ sourceType: 'module',
15
+ project: 'eslint-integration/tsconfig.json'
16
+ },
17
+
18
+ plugins: [
19
+ 'custom',
20
+ '@typescript-eslint'
21
+ ],
22
+
23
+ globals: {
24
+ console: 'readonly',
25
+ process: 'readonly',
26
+ eval: 'readonly'
27
+ },
28
+
29
+ rules: {
30
+ // Rule C019: No console.error for non-critical errors
31
+ 'no-console': ['warn', { allow: ['warn', 'log'] }],
32
+
33
+ // Code quality rules
34
+ 'no-unused-vars': 'warn',
35
+ 'prefer-const': 'warn',
36
+ 'no-var': 'error',
37
+ 'no-undef': 'warn',
38
+
39
+ // Rule C005: Single responsibility principle
40
+ 'max-lines-per-function': ['warn', { max: 50 }],
41
+ 'complexity': ['warn', { max: 10 }],
42
+
43
+ // Rule C014: Avoid direct new instantiation patterns
44
+ 'no-new': 'warn',
45
+
46
+ // Security and best practices
47
+ 'no-eval': 'error',
48
+ 'no-implied-eval': 'error',
49
+ 'no-new-func': 'error',
50
+ 'eqeqeq': 'error',
51
+ 'curly': 'error',
52
+
53
+ // Security rules from custom plugin (dynamic loading based on category)
54
+ 'custom/typescript_s003': 'off', // Will be enabled dynamically
55
+ 'custom/typescript_s005': 'off', // Will be enabled dynamically
56
+ 'custom/typescript_s006': 'off',
57
+ 'custom/typescript_s008': 'off',
58
+ 'custom/typescript_s009': 'off',
59
+ 'custom/typescript_s010': 'off',
60
+ 'custom/typescript_s011': 'off',
61
+ 'custom/typescript_s012': 'off',
62
+ 'custom/typescript_s014': 'off',
63
+ 'custom/typescript_s015': 'off',
64
+ 'custom/typescript_s016': 'off',
65
+ 'custom/typescript_s017': 'off',
66
+ 'custom/typescript_s018': 'off',
67
+ 'custom/typescript_s019': 'off',
68
+ 'custom/typescript_s020': 'off',
69
+ 'custom/typescript_s022': 'off',
70
+ 'custom/typescript_s023': 'off',
71
+ 'custom/typescript_s025': 'off',
72
+ 'custom/typescript_s026': 'off',
73
+ 'custom/typescript_s027': 'off',
74
+ 'custom/typescript_s029': 'off',
75
+ 'custom/typescript_s030': 'off',
76
+ 'custom/typescript_s033': 'off',
77
+ 'custom/typescript_s034': 'off',
78
+ 'custom/typescript_s035': 'off',
79
+ 'custom/typescript_s036': 'off',
80
+ 'custom/typescript_s037': 'off',
81
+ 'custom/typescript_s038': 'off',
82
+ 'custom/typescript_s039': 'off',
83
+ 'custom/typescript_s041': 'off',
84
+ 'custom/typescript_s042': 'off',
85
+ 'custom/typescript_s043': 'off',
86
+ 'custom/typescript_s044': 'off',
87
+ 'custom/typescript_s045': 'off',
88
+ 'custom/typescript_s046': 'off',
89
+ 'custom/typescript_s047': 'off',
90
+ 'custom/typescript_s048': 'off',
91
+ 'custom/typescript_s050': 'off',
92
+ 'custom/typescript_s052': 'off',
93
+ 'custom/typescript_s054': 'off',
94
+ 'custom/typescript_s055': 'off',
95
+ 'custom/typescript_s057': 'off',
96
+ 'custom/typescript_s058': 'off'
97
+ }
98
+ };
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SunLint CLI Entry Point
5
+ * Main CLI entry point with modular architecture
6
+ * Following Rule C005: Single responsibility - only handle CLI bootstrapping
7
+ * Following Rule C014: Dependency injection for services
8
+ */
9
+
10
+ const chalk = require('chalk');
11
+ const { createCliProgram } = require('./core/cli-program');
12
+ const CliActionHandler = require('./core/cli-action-handler');
13
+
14
+ // Create CLI program
15
+ const program = createCliProgram();
16
+
17
+ // Set up main action handler
18
+ program.action(async (options) => {
19
+ const actionHandler = new CliActionHandler(options);
20
+ await actionHandler.execute();
21
+ });
22
+
23
+ // Global error handling
24
+ process.on('unhandledRejection', (reason, promise) => {
25
+ console.error(chalk.red('Sun Lint - Unhandled Rejection:'), promise, chalk.red('reason:'), reason);
26
+ process.exit(1);
27
+ });
28
+
29
+ process.on('uncaughtException', (error) => {
30
+ console.error(chalk.red('Sun Lint - Uncaught Exception:'), error);
31
+ process.exit(1);
32
+ });
33
+
34
+ // Parse CLI arguments
35
+ program.parse();
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Custom ESLint rule for: C002 – Không để trùng lặp code > 10 dòng
3
+ * Rule ID: custom/c002
4
+ * Purpose: Detect duplicate code blocks longer than 10 lines to maintain DRY principle
5
+ */
6
+
7
+ module.exports = {
8
+ meta: {
9
+ type: "suggestion",
10
+ docs: {
11
+ description: "Detect duplicate code blocks longer than 10 lines",
12
+ recommended: false
13
+ },
14
+ schema: [
15
+ {
16
+ type: "object",
17
+ properties: {
18
+ minLines: {
19
+ type: "number",
20
+ minimum: 1,
21
+ default: 10
22
+ },
23
+ ignoreComments: {
24
+ type: "boolean",
25
+ default: true
26
+ },
27
+ ignoreWhitespace: {
28
+ type: "boolean",
29
+ default: true
30
+ }
31
+ },
32
+ additionalProperties: false
33
+ }
34
+ ],
35
+ messages: {
36
+ duplicateCode: "Duplicate code block found ({{lines}} lines). Consider extracting into a shared function or module."
37
+ }
38
+ },
39
+ create(context) {
40
+ const options = context.options[0] || {};
41
+ const minLines = options.minLines || 10;
42
+ const ignoreComments = options.ignoreComments !== false;
43
+ const ignoreWhitespace = options.ignoreWhitespace !== false;
44
+
45
+ const sourceCode = context.getSourceCode();
46
+ const codeBlocks = new Map();
47
+
48
+ function normalizeCode(text) {
49
+ let normalized = text;
50
+
51
+ if (ignoreWhitespace) {
52
+ // Remove extra whitespace and normalize spacing
53
+ normalized = normalized
54
+ .replace(/\s+/g, ' ')
55
+ .trim();
56
+ }
57
+
58
+ if (ignoreComments) {
59
+ // Remove single line comments
60
+ normalized = normalized.replace(/\/\/.*$/gm, '');
61
+ // Remove multi-line comments
62
+ normalized = normalized.replace(/\/\*[\s\S]*?\*\//g, '');
63
+ }
64
+
65
+ return normalized;
66
+ }
67
+
68
+ function getCodeLines(node) {
69
+ const startLine = node.loc.start.line;
70
+ const endLine = node.loc.end.line;
71
+ const lines = [];
72
+
73
+ for (let i = startLine; i <= endLine; i++) {
74
+ const line = sourceCode.lines[i - 1];
75
+ if (line !== undefined) {
76
+ lines.push(line);
77
+ }
78
+ }
79
+
80
+ return lines;
81
+ }
82
+
83
+ function analyzeNode(node) {
84
+ const lines = getCodeLines(node);
85
+
86
+ if (lines.length < minLines) {
87
+ return;
88
+ }
89
+
90
+ const codeText = lines.join('\n');
91
+ const normalizedCode = normalizeCode(codeText);
92
+
93
+ // Skip if normalized code is too short after cleaning
94
+ if (normalizedCode.length < 20) {
95
+ return;
96
+ }
97
+
98
+ const codeHash = normalizedCode;
99
+
100
+ if (codeBlocks.has(codeHash)) {
101
+ const existingNodes = codeBlocks.get(codeHash);
102
+
103
+ // Report duplicate for current node
104
+ context.report({
105
+ node,
106
+ messageId: "duplicateCode",
107
+ data: {
108
+ lines: lines.length
109
+ }
110
+ });
111
+
112
+ // Also report the first occurrence if not already reported
113
+ existingNodes.forEach(existingNode => {
114
+ if (!existingNode.reported) {
115
+ context.report({
116
+ node: existingNode.node,
117
+ messageId: "duplicateCode",
118
+ data: {
119
+ lines: existingNode.lines
120
+ }
121
+ });
122
+ existingNode.reported = true;
123
+ }
124
+ });
125
+
126
+ existingNodes.push({ node, lines: lines.length, reported: true });
127
+ } else {
128
+ codeBlocks.set(codeHash, [{ node, lines: lines.length, reported: false }]);
129
+ }
130
+ }
131
+
132
+ return {
133
+ // Check function declarations
134
+ FunctionDeclaration(node) {
135
+ if (node.body) {
136
+ analyzeNode(node.body);
137
+ }
138
+ },
139
+
140
+ // Check function expressions
141
+ FunctionExpression(node) {
142
+ if (node.body) {
143
+ analyzeNode(node.body);
144
+ }
145
+ },
146
+
147
+ // Check arrow functions
148
+ ArrowFunctionExpression(node) {
149
+ if (node.body && node.body.type === 'BlockStatement') {
150
+ analyzeNode(node.body);
151
+ }
152
+ },
153
+
154
+ // Check method definitions
155
+ MethodDefinition(node) {
156
+ if (node.value && node.value.body) {
157
+ analyzeNode(node.value.body);
158
+ }
159
+ },
160
+
161
+ // Check block statements (general code blocks)
162
+ BlockStatement(node) {
163
+ // Only analyze block statements that are not function bodies
164
+ const parent = node.parent;
165
+ if (parent &&
166
+ parent.type !== 'FunctionDeclaration' &&
167
+ parent.type !== 'FunctionExpression' &&
168
+ parent.type !== 'ArrowFunctionExpression' &&
169
+ parent.type !== 'MethodDefinition') {
170
+ analyzeNode(node);
171
+ }
172
+ },
173
+
174
+ // Check if/else statements
175
+ IfStatement(node) {
176
+ if (node.consequent && node.consequent.type === 'BlockStatement') {
177
+ analyzeNode(node.consequent);
178
+ }
179
+ if (node.alternate && node.alternate.type === 'BlockStatement') {
180
+ analyzeNode(node.alternate);
181
+ }
182
+ },
183
+
184
+ // Check loop bodies
185
+ ForStatement(node) {
186
+ if (node.body && node.body.type === 'BlockStatement') {
187
+ analyzeNode(node.body);
188
+ }
189
+ },
190
+
191
+ WhileStatement(node) {
192
+ if (node.body && node.body.type === 'BlockStatement') {
193
+ analyzeNode(node.body);
194
+ }
195
+ },
196
+
197
+ DoWhileStatement(node) {
198
+ if (node.body && node.body.type === 'BlockStatement') {
199
+ analyzeNode(node.body);
200
+ }
201
+ }
202
+ };
203
+ }
204
+ };