@sun-asterisk/sunlint 1.3.33 → 1.3.34

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 (450) hide show
  1. package/config/released-rules.json +62 -0
  2. package/config/rules/enhanced-rules-registry.json +2315 -1354
  3. package/core/adapters/dart-analyzer.js +658 -0
  4. package/core/adapters/index.js +102 -0
  5. package/core/adapters/sunlint-rule-adapter.js +0 -2
  6. package/core/adapters/typescript-analyzer.js +277 -0
  7. package/core/analysis-orchestrator.js +168 -40
  8. package/core/cli-action-handler.js +6 -19
  9. package/core/config-merger.js +24 -14
  10. package/core/constants/defaults.js +1 -2
  11. package/core/github-annotate-service.js +141 -89
  12. package/core/github-step-summary-generator.js +8 -8
  13. package/core/interfaces/language-analyzer.interface.js +393 -0
  14. package/core/output-service.js +15 -14
  15. package/core/rule-selection-service.js +77 -27
  16. package/core/semantic-engine-manager.js +375 -0
  17. package/core/semantic-engine.js +4 -57
  18. package/core/unified-rule-registry.js +52 -11
  19. package/docs/DART_RULE_EXECUTION_FLOW.md +745 -0
  20. package/docs/DART_SUPPORT_IMPLEMENTATION.md +245 -0
  21. package/docs/SUNLINT_ARCHITECTURE.md +692 -0
  22. package/docs/skills/CREATE_DART_RULE.md +909 -0
  23. package/engines/eslint-engine.js +2 -8
  24. package/engines/heuristic-engine.js +234 -38
  25. package/package.json +1 -1
  26. package/rules/common/C002_no_duplicate_code/config.json +12 -20
  27. package/rules/common/C002_no_duplicate_code/dart/analyzer.js +53 -0
  28. package/rules/common/C002_no_duplicate_code/index.js +93 -0
  29. package/rules/common/C003_no_vague_abbreviations/config.json +1 -1
  30. package/rules/common/C003_no_vague_abbreviations/dart/analyzer.js +54 -0
  31. package/rules/common/C003_no_vague_abbreviations/index.js +93 -0
  32. package/rules/common/C006_function_naming/dart/analyzer.js +40 -0
  33. package/rules/common/C006_function_naming/index.js +86 -0
  34. package/rules/common/C008_variable_declaration_locality/dart/analyzer.js +32 -0
  35. package/rules/common/C008_variable_declaration_locality/index.js +86 -0
  36. package/rules/common/C010_limit_block_nesting/dart/analyzer.js +32 -0
  37. package/rules/common/C010_limit_block_nesting/index.js +86 -0
  38. package/rules/common/C012_command_query_separation/config.json +61 -0
  39. package/rules/common/C012_command_query_separation/dart/analyzer.js +32 -0
  40. package/rules/common/C012_command_query_separation/index.js +86 -0
  41. package/rules/common/C013_no_dead_code/dart/analyzer.js +32 -0
  42. package/rules/common/C013_no_dead_code/index.js +86 -0
  43. package/rules/common/C014_dependency_injection/dart/analyzer.js +32 -0
  44. package/rules/common/C014_dependency_injection/index.js +86 -0
  45. package/rules/common/C017_constructor_logic/dart/analyzer.js +32 -0
  46. package/rules/common/C017_constructor_logic/index.js +86 -0
  47. package/rules/common/C018_no_throw_generic_error/dart/analyzer.js +32 -0
  48. package/rules/common/C018_no_throw_generic_error/index.js +86 -0
  49. package/rules/common/C019_log_level_usage/dart/analyzer.js +32 -0
  50. package/rules/common/C019_log_level_usage/index.js +86 -0
  51. package/rules/common/C019_log_level_usage/{ts-morph-analyzer.js → typescript/ts-morph-analyzer.js} +0 -1
  52. package/rules/common/C020_unused_imports/dart/analyzer.js +32 -0
  53. package/rules/common/C020_unused_imports/index.js +86 -0
  54. package/rules/common/C020_unused_imports/{ts-morph-analyzer.js → typescript/ts-morph-analyzer.js} +0 -1
  55. package/rules/common/C021_import_organization/config.json +29 -9
  56. package/rules/common/C021_import_organization/dart/analyzer.js +40 -0
  57. package/rules/common/C021_import_organization/index.js +83 -0
  58. package/rules/common/C021_import_organization/{ts-morph-analyzer.js → typescript/ts-morph-analyzer.js} +0 -1
  59. package/rules/common/C023_no_duplicate_variable/config.json +7 -2
  60. package/rules/common/C023_no_duplicate_variable/dart/analyzer.js +40 -0
  61. package/rules/common/C023_no_duplicate_variable/index.js +83 -0
  62. package/rules/common/C024_no_scatter_hardcoded_constants/config.json +7 -2
  63. package/rules/common/C024_no_scatter_hardcoded_constants/dart/analyzer.js +40 -0
  64. package/rules/common/C024_no_scatter_hardcoded_constants/index.js +83 -0
  65. package/rules/common/C024_no_scatter_hardcoded_constants/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -1
  66. package/rules/common/C029_catch_block_logging/config.json +15 -5
  67. package/rules/common/C029_catch_block_logging/dart/analyzer.js +40 -0
  68. package/rules/common/C029_catch_block_logging/index.js +83 -0
  69. package/rules/common/C030_use_custom_error_classes/config.json +28 -0
  70. package/rules/common/C030_use_custom_error_classes/dart/analyzer.js +40 -0
  71. package/rules/common/C030_use_custom_error_classes/index.js +83 -0
  72. package/rules/common/C031_validation_separation/config.json +28 -0
  73. package/rules/common/C031_validation_separation/dart/analyzer.js +40 -0
  74. package/rules/common/C031_validation_separation/index.js +83 -0
  75. package/rules/common/C033_separate_service_repository/config.json +8 -3
  76. package/rules/common/C033_separate_service_repository/dart/analyzer.js +40 -0
  77. package/rules/common/C033_separate_service_repository/index.js +83 -0
  78. package/rules/common/C035_error_logging_context/config.json +34 -12
  79. package/rules/common/C035_error_logging_context/dart/analyzer.js +40 -0
  80. package/rules/common/C035_error_logging_context/index.js +83 -0
  81. package/rules/common/C040_centralized_validation/config.json +37 -8
  82. package/rules/common/C040_centralized_validation/dart/analyzer.js +40 -0
  83. package/rules/common/C040_centralized_validation/index.js +83 -0
  84. package/rules/common/C041_no_sensitive_hardcode/config.json +7 -2
  85. package/rules/common/C041_no_sensitive_hardcode/dart/analyzer.js +40 -0
  86. package/rules/common/C041_no_sensitive_hardcode/index.js +83 -0
  87. package/rules/common/C042_boolean_name_prefix/config.json +28 -0
  88. package/rules/common/C042_boolean_name_prefix/dart/analyzer.js +40 -0
  89. package/rules/common/C042_boolean_name_prefix/index.js +83 -0
  90. package/rules/common/C043_no_console_or_print/config.json +28 -0
  91. package/rules/common/C043_no_console_or_print/dart/analyzer.js +40 -0
  92. package/rules/common/C043_no_console_or_print/index.js +83 -0
  93. package/rules/common/C047_no_duplicate_retry_logic/config.json +28 -0
  94. package/rules/common/C047_no_duplicate_retry_logic/dart/analyzer.js +40 -0
  95. package/rules/common/C047_no_duplicate_retry_logic/index.js +83 -0
  96. package/rules/common/C048_no_bypass_architectural_layers/config.json +7 -2
  97. package/rules/common/C048_no_bypass_architectural_layers/dart/analyzer.js +40 -0
  98. package/rules/common/C048_no_bypass_architectural_layers/index.js +83 -0
  99. package/rules/common/C052_parsing_or_data_transformation/config.json +7 -2
  100. package/rules/common/C052_parsing_or_data_transformation/dart/analyzer.js +40 -0
  101. package/rules/common/C052_parsing_or_data_transformation/index.js +83 -0
  102. package/rules/common/C060_no_override_superclass/config.json +7 -2
  103. package/rules/common/C060_no_override_superclass/dart/analyzer.js +40 -0
  104. package/rules/common/C060_no_override_superclass/index.js +83 -0
  105. package/rules/common/C065_one_behavior_per_test/config.json +187 -28
  106. package/rules/common/C065_one_behavior_per_test/dart/analyzer.js +40 -0
  107. package/rules/common/C065_one_behavior_per_test/index.js +83 -0
  108. package/rules/common/C067_no_hardcoded_config/config.json +18 -4
  109. package/rules/common/C067_no_hardcoded_config/dart/analyzer.js +40 -0
  110. package/rules/common/C067_no_hardcoded_config/index.js +83 -0
  111. package/rules/common/C070_no_real_time_tests/config.json +41 -12
  112. package/rules/common/C070_no_real_time_tests/dart/analyzer.js +40 -0
  113. package/rules/common/C070_no_real_time_tests/index.js +83 -0
  114. package/rules/common/C072_single_test_behavior/config.json +28 -0
  115. package/rules/common/C072_single_test_behavior/dart/analyzer.js +40 -0
  116. package/rules/common/C072_single_test_behavior/index.js +83 -0
  117. package/rules/common/C073_validate_required_config_on_startup/config.json +93 -18
  118. package/rules/common/C073_validate_required_config_on_startup/dart/analyzer.js +40 -0
  119. package/rules/common/C073_validate_required_config_on_startup/index.js +83 -0
  120. package/rules/common/C073_validate_required_config_on_startup/{analyzer.js → typescript/analyzer.js} +0 -1
  121. package/rules/common/C075_explicit_return_types/config.json +28 -0
  122. package/rules/common/C075_explicit_return_types/dart/analyzer.js +40 -0
  123. package/rules/common/C075_explicit_return_types/index.js +83 -0
  124. package/rules/common/C076_explicit_function_types/config.json +18 -4
  125. package/rules/common/C076_explicit_function_types/dart/analyzer.js +40 -0
  126. package/rules/common/C076_explicit_function_types/index.js +83 -0
  127. package/rules/index.js +26 -6
  128. package/rules/security/S003_open_redirect_protection/config.json +11 -53
  129. package/rules/security/S003_open_redirect_protection/dart/analyzer.js +43 -0
  130. package/rules/security/S003_open_redirect_protection/index.js +94 -0
  131. package/rules/security/S003_open_redirect_protection/typescript/analyzer.js +105 -0
  132. package/rules/security/S003_open_redirect_protection/{symbol-based-analyzer.js → typescript/semantic-analyzer.js} +1 -1
  133. package/rules/security/S004_sensitive_data_logging/config.json +1 -1
  134. package/rules/security/S004_sensitive_data_logging/dart/analyzer.js +58 -0
  135. package/rules/security/S004_sensitive_data_logging/index.js +93 -0
  136. package/rules/security/S005_no_origin_auth/dart/analyzer.js +30 -0
  137. package/rules/security/S005_no_origin_auth/index.js +83 -0
  138. package/rules/security/S005_no_origin_auth/{analyzer.js → typescript/analyzer.js} +1 -0
  139. package/rules/security/S006_no_plaintext_recovery_codes/dart/analyzer.js +30 -0
  140. package/rules/security/S006_no_plaintext_recovery_codes/index.js +83 -0
  141. package/rules/security/S007_no_plaintext_otp/dart/analyzer.js +30 -0
  142. package/rules/security/S007_no_plaintext_otp/index.js +83 -0
  143. package/rules/security/S009_no_insecure_encryption/dart/analyzer.js +30 -0
  144. package/rules/security/S009_no_insecure_encryption/index.js +83 -0
  145. package/rules/security/S010_no_insecure_encryption/dart/analyzer.js +30 -0
  146. package/rules/security/S010_no_insecure_encryption/index.js +83 -0
  147. package/rules/security/S011_secure_guid_generation/dart/analyzer.js +30 -0
  148. package/rules/security/S011_secure_guid_generation/index.js +83 -0
  149. package/rules/security/S012_hardcoded_secrets/dart/analyzer.js +30 -0
  150. package/rules/security/S012_hardcoded_secrets/index.js +83 -0
  151. package/rules/security/S012_hardcoded_secrets/typescript/config.json +75 -0
  152. package/rules/security/S013_tls_enforcement/dart/analyzer.js +30 -0
  153. package/rules/security/S013_tls_enforcement/index.js +83 -0
  154. package/rules/security/S014_tls_version_enforcement/dart/analyzer.js +30 -0
  155. package/rules/security/S014_tls_version_enforcement/index.js +83 -0
  156. package/rules/security/S015_insecure_tls_certificate/config.json +41 -0
  157. package/rules/security/S015_insecure_tls_certificate/dart/analyzer.js +19 -0
  158. package/rules/security/S015_insecure_tls_certificate/index.js +83 -0
  159. package/rules/security/S016_no_sensitive_querystring/dart/analyzer.js +30 -0
  160. package/rules/security/S016_no_sensitive_querystring/index.js +83 -0
  161. package/rules/security/S017_use_parameterized_queries/dart/analyzer.js +30 -0
  162. package/rules/security/S017_use_parameterized_queries/index.js +83 -0
  163. package/rules/security/S019_smtp_injection_protection/dart/analyzer.js +30 -0
  164. package/rules/security/S019_smtp_injection_protection/index.js +83 -0
  165. package/rules/security/S020_no_eval_dynamic_code/dart/analyzer.js +30 -0
  166. package/rules/security/S020_no_eval_dynamic_code/index.js +83 -0
  167. package/rules/security/S022_escape_output_context/dart/analyzer.js +30 -0
  168. package/rules/security/S022_escape_output_context/index.js +83 -0
  169. package/rules/security/S023_no_json_injection/dart/analyzer.js +30 -0
  170. package/rules/security/S023_no_json_injection/index.js +83 -0
  171. package/rules/security/S024_xpath_xxe_protection/dart/analyzer.js +30 -0
  172. package/rules/security/S024_xpath_xxe_protection/index.js +83 -0
  173. package/rules/security/S025_server_side_validation/dart/analyzer.js +30 -0
  174. package/rules/security/S025_server_side_validation/index.js +83 -0
  175. package/rules/security/S026_json_schema_validation/dart/analyzer.js +30 -0
  176. package/rules/security/S026_json_schema_validation/index.js +83 -0
  177. package/rules/security/S027_no_hardcoded_secrets/dart/analyzer.js +30 -0
  178. package/rules/security/S027_no_hardcoded_secrets/index.js +83 -0
  179. package/rules/security/S028_file_upload_size_limits/dart/analyzer.js +30 -0
  180. package/rules/security/S028_file_upload_size_limits/index.js +83 -0
  181. package/rules/security/S029_csrf_protection/dart/analyzer.js +30 -0
  182. package/rules/security/S029_csrf_protection/index.js +83 -0
  183. package/rules/security/S030_directory_browsing_protection/dart/analyzer.js +30 -0
  184. package/rules/security/S030_directory_browsing_protection/index.js +83 -0
  185. package/rules/security/S031_secure_session_cookies/dart/analyzer.js +30 -0
  186. package/rules/security/S031_secure_session_cookies/index.js +83 -0
  187. package/rules/security/S032_httponly_session_cookies/dart/analyzer.js +30 -0
  188. package/rules/security/S032_httponly_session_cookies/index.js +83 -0
  189. package/rules/security/S033_samesite_session_cookies/dart/analyzer.js +30 -0
  190. package/rules/security/S033_samesite_session_cookies/index.js +83 -0
  191. package/rules/security/S034_host_prefix_session_cookies/dart/analyzer.js +30 -0
  192. package/rules/security/S034_host_prefix_session_cookies/index.js +83 -0
  193. package/rules/security/S035_path_session_cookies/dart/analyzer.js +30 -0
  194. package/rules/security/S035_path_session_cookies/index.js +83 -0
  195. package/rules/security/S036_lfi_rfi_protection/dart/analyzer.js +30 -0
  196. package/rules/security/S036_lfi_rfi_protection/index.js +83 -0
  197. package/rules/security/S037_cache_headers/dart/analyzer.js +30 -0
  198. package/rules/security/S037_cache_headers/index.js +83 -0
  199. package/rules/security/S038_no_version_headers/dart/analyzer.js +30 -0
  200. package/rules/security/S038_no_version_headers/index.js +83 -0
  201. package/rules/security/S039_no_session_tokens_in_url/dart/analyzer.js +30 -0
  202. package/rules/security/S039_no_session_tokens_in_url/index.js +83 -0
  203. package/rules/security/S040_session_fixation_protection/dart/analyzer.js +30 -0
  204. package/rules/security/S040_session_fixation_protection/index.js +83 -0
  205. package/rules/security/S041_session_token_invalidation/dart/analyzer.js +30 -0
  206. package/rules/security/S041_session_token_invalidation/index.js +83 -0
  207. package/rules/security/S042_require_re_authentication_for_long_lived/dart/analyzer.js +30 -0
  208. package/rules/security/S042_require_re_authentication_for_long_lived/index.js +83 -0
  209. package/rules/security/S043_password_changes_invalidate_all_sessions/dart/analyzer.js +30 -0
  210. package/rules/security/S043_password_changes_invalidate_all_sessions/index.js +83 -0
  211. package/rules/security/S044_re_authentication_required/dart/analyzer.js +30 -0
  212. package/rules/security/S044_re_authentication_required/index.js +83 -0
  213. package/rules/security/S045_brute_force_protection/dart/analyzer.js +30 -0
  214. package/rules/security/S045_brute_force_protection/index.js +83 -0
  215. package/rules/security/S048_no_current_password_in_reset/dart/analyzer.js +30 -0
  216. package/rules/security/S048_no_current_password_in_reset/index.js +83 -0
  217. package/rules/security/S049_short_validity_tokens/dart/analyzer.js +30 -0
  218. package/rules/security/S049_short_validity_tokens/index.js +83 -0
  219. package/rules/security/S049_short_validity_tokens/typescript/config.json +124 -0
  220. package/rules/security/S051_password_length_policy/dart/analyzer.js +30 -0
  221. package/rules/security/S051_password_length_policy/index.js +83 -0
  222. package/rules/security/S051_password_length_policy/typescript/config.json +83 -0
  223. package/rules/security/S052_weak_otp_entropy/dart/analyzer.js +30 -0
  224. package/rules/security/S052_weak_otp_entropy/index.js +83 -0
  225. package/rules/security/S052_weak_otp_entropy/typescript/config.json +57 -0
  226. package/rules/security/S054_no_default_accounts/dart/analyzer.js +30 -0
  227. package/rules/security/S054_no_default_accounts/index.js +83 -0
  228. package/rules/security/S054_no_default_accounts/typescript/config.json +101 -0
  229. package/rules/security/S055_content_type_validation/dart/analyzer.js +30 -0
  230. package/rules/security/S055_content_type_validation/index.js +83 -0
  231. package/rules/security/S056_log_injection_protection/dart/analyzer.js +30 -0
  232. package/rules/security/S056_log_injection_protection/index.js +83 -0
  233. package/rules/security/S057_utc_logging/dart/analyzer.js +30 -0
  234. package/rules/security/S057_utc_logging/index.js +83 -0
  235. package/rules/security/S057_utc_logging/typescript/config.json +105 -0
  236. package/rules/security/S058_no_ssrf/dart/analyzer.js +30 -0
  237. package/rules/security/S058_no_ssrf/index.js +83 -0
  238. package/rules/security/S058_no_ssrf/{analyzer.js → typescript/analyzer.js} +0 -1
  239. package/rules/security/S058_no_ssrf/typescript/config.json +125 -0
  240. package/scripts/build-release.sh +12 -0
  241. package/rules/common/C002_no_duplicate_code/test-cases/api-handlers.ts +0 -64
  242. package/rules/common/C002_no_duplicate_code/test-cases/data-processor.ts +0 -46
  243. package/rules/common/C002_no_duplicate_code/test-cases/good-example.tsx +0 -40
  244. package/rules/common/C002_no_duplicate_code/test-cases/product-service.ts +0 -57
  245. package/rules/common/C002_no_duplicate_code/test-cases/user-service.ts +0 -49
  246. package/rules/common/C067_no_hardcoded_config/symbol-based-analyzer.js.backup +0 -3853
  247. package/rules/security/S003_open_redirect_protection/analyzer.js +0 -135
  248. /package/rules/common/C002_no_duplicate_code/{analyzer.js → typescript/analyzer.js} +0 -0
  249. /package/rules/common/C003_no_vague_abbreviations/{analyzer.js → typescript/analyzer.js} +0 -0
  250. /package/rules/common/C006_function_naming/{analyzer.js → typescript/analyzer.js} +0 -0
  251. /package/rules/common/{C008 → C008_variable_declaration_locality}/config.json +0 -0
  252. /package/rules/common/{C008 → C008_variable_declaration_locality/typescript}/analyzer.js +0 -0
  253. /package/rules/common/{C008 → C008_variable_declaration_locality/typescript}/ts-morph-analyzer.js +0 -0
  254. /package/rules/common/C010_limit_block_nesting/{analyzer.js → typescript/analyzer.js} +0 -0
  255. /package/rules/common/C010_limit_block_nesting/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  256. /package/rules/common/C010_limit_block_nesting/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  257. /package/rules/common/C012_command_query_separation/{analyzer.js → typescript/analyzer.js} +0 -0
  258. /package/rules/common/C012_command_query_separation/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
  259. /package/rules/common/C013_no_dead_code/{analyzer.js → typescript/analyzer.js} +0 -0
  260. /package/rules/common/C013_no_dead_code/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  261. /package/rules/common/C013_no_dead_code/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  262. /package/rules/common/C014_dependency_injection/{analyzer.js → typescript/analyzer.js} +0 -0
  263. /package/rules/common/C014_dependency_injection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  264. /package/rules/common/C017_constructor_logic/{analyzer.js → typescript/analyzer.js} +0 -0
  265. /package/rules/common/C017_constructor_logic/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  266. /package/rules/common/C018_no_throw_generic_error/{analyzer.js → typescript/analyzer.js} +0 -0
  267. /package/rules/common/C018_no_throw_generic_error/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  268. /package/rules/common/C018_no_throw_generic_error/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  269. /package/rules/common/C019_log_level_usage/{analyzer.js → typescript/analyzer.js} +0 -0
  270. /package/rules/common/C019_log_level_usage/{pattern-analyzer.js → typescript/pattern-analyzer.js} +0 -0
  271. /package/rules/common/C019_log_level_usage/{system-log-analyzer.js → typescript/system-log-analyzer.js} +0 -0
  272. /package/rules/common/C020_unused_imports/{analyzer.js → typescript/analyzer.js} +0 -0
  273. /package/rules/common/C021_import_organization/{analyzer.js → typescript/analyzer.js} +0 -0
  274. /package/rules/common/C023_no_duplicate_variable/{analyzer.js → typescript/analyzer.js} +0 -0
  275. /package/rules/common/C023_no_duplicate_variable/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  276. /package/rules/common/C024_no_scatter_hardcoded_constants/{analyzer.js → typescript/analyzer.js} +0 -0
  277. /package/rules/common/C029_catch_block_logging/{analyzer.js → typescript/analyzer.js} +0 -0
  278. /package/rules/common/C030_use_custom_error_classes/{analyzer.js → typescript/analyzer.js} +0 -0
  279. /package/rules/common/C031_validation_separation/{analyzer.js → typescript/analyzer.js} +0 -0
  280. /package/rules/common/C033_separate_service_repository/{README.md → typescript/README.md} +0 -0
  281. /package/rules/common/C033_separate_service_repository/{analyzer.js → typescript/analyzer.js} +0 -0
  282. /package/rules/common/C033_separate_service_repository/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  283. /package/rules/common/C033_separate_service_repository/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  284. /package/rules/common/C035_error_logging_context/{STRATEGY.md → typescript/STRATEGY.md} +0 -0
  285. /package/rules/common/C035_error_logging_context/{analyzer.js → typescript/analyzer.js} +0 -0
  286. /package/rules/common/C035_error_logging_context/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  287. /package/rules/common/C035_error_logging_context/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  288. /package/rules/common/C040_centralized_validation/{analyzer.js → typescript/analyzer.js} +0 -0
  289. /package/rules/common/C040_centralized_validation/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  290. /package/rules/common/C040_centralized_validation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  291. /package/rules/common/C041_no_sensitive_hardcode/{analyzer.js → typescript/analyzer.js} +0 -0
  292. /package/rules/common/C041_no_sensitive_hardcode/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  293. /package/rules/common/C042_boolean_name_prefix/{analyzer.js → typescript/analyzer.js} +0 -0
  294. /package/rules/common/C043_no_console_or_print/{analyzer.js → typescript/analyzer.js} +0 -0
  295. /package/rules/common/C047_no_duplicate_retry_logic/{analyzer.js → typescript/analyzer.js} +0 -0
  296. /package/rules/common/C047_no_duplicate_retry_logic/{c047-semantic-rule.js → typescript/c047-semantic-rule.js} +0 -0
  297. /package/rules/common/C047_no_duplicate_retry_logic/{symbol-analyzer-enhanced.js → typescript/symbol-analyzer-enhanced.js} +0 -0
  298. /package/rules/common/C047_no_duplicate_retry_logic/{symbol-config.json → typescript/symbol-config.json} +0 -0
  299. /package/rules/common/C048_no_bypass_architectural_layers/{analyzer.js → typescript/analyzer.js} +0 -0
  300. /package/rules/common/C048_no_bypass_architectural_layers/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  301. /package/rules/common/C052_parsing_or_data_transformation/{analyzer.js → typescript/analyzer.js} +0 -0
  302. /package/rules/common/C052_parsing_or_data_transformation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  303. /package/rules/common/C060_no_override_superclass/{analyzer.js → typescript/analyzer.js} +0 -0
  304. /package/rules/common/C060_no_override_superclass/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  305. /package/rules/common/C065_one_behavior_per_test/{analyzer.js → typescript/analyzer.js} +0 -0
  306. /package/rules/common/C067_no_hardcoded_config/{analyzer.js → typescript/analyzer.js} +0 -0
  307. /package/rules/common/C067_no_hardcoded_config/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  308. /package/rules/common/C070_no_real_time_tests/{analyzer.js → typescript/analyzer.js} +0 -0
  309. /package/rules/common/C070_no_real_time_tests/{regex-analyzer.js → typescript/regex-analyzer.js} +0 -0
  310. /package/rules/common/C072_single_test_behavior/{analyzer.js → typescript/analyzer.js} +0 -0
  311. /package/rules/common/C073_validate_required_config_on_startup/{README.md → typescript/README.md} +0 -0
  312. /package/rules/common/C073_validate_required_config_on_startup/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  313. /package/rules/common/C075_explicit_return_types/{analyzer.js → typescript/analyzer.js} +0 -0
  314. /package/rules/common/C076_explicit_function_types/{README.md → typescript/README.md} +0 -0
  315. /package/rules/common/C076_explicit_function_types/{analyzer.js → typescript/analyzer.js} +0 -0
  316. /package/rules/common/C076_explicit_function_types/{semantic-analyzer.js → typescript/semantic-analyzer.js} +0 -0
  317. /package/rules/security/S003_open_redirect_protection/{README.md → typescript/README.md} +0 -0
  318. /package/rules/security/S004_sensitive_data_logging/{analyzer.js → typescript/analyzer.js} +0 -0
  319. /package/rules/security/S004_sensitive_data_logging/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  320. /package/rules/security/S005_no_origin_auth/{README.md → typescript/README.md} +0 -0
  321. /package/rules/security/S005_no_origin_auth/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
  322. /package/rules/security/S005_no_origin_auth/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  323. /package/rules/security/S006_no_plaintext_recovery_codes/{README.md → typescript/README.md} +0 -0
  324. /package/rules/security/S006_no_plaintext_recovery_codes/{analyzer.js → typescript/analyzer.js} +0 -0
  325. /package/rules/security/S006_no_plaintext_recovery_codes/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  326. /package/rules/security/S007_no_plaintext_otp/{README.md → typescript/README.md} +0 -0
  327. /package/rules/security/S007_no_plaintext_otp/{analyzer.js → typescript/analyzer.js} +0 -0
  328. /package/rules/security/S007_no_plaintext_otp/{semantic-analyzer.js → typescript/semantic-analyzer.js} +0 -0
  329. /package/rules/security/S007_no_plaintext_otp/{semantic-config.json → typescript/semantic-config.json} +0 -0
  330. /package/rules/security/S007_no_plaintext_otp/{semantic-wrapper.js → typescript/semantic-wrapper.js} +0 -0
  331. /package/rules/security/S009_no_insecure_encryption/{README.md → typescript/README.md} +0 -0
  332. /package/rules/security/S009_no_insecure_encryption/{analyzer.js → typescript/analyzer.js} +0 -0
  333. /package/rules/security/S010_no_insecure_encryption/{README.md → typescript/README.md} +0 -0
  334. /package/rules/security/S010_no_insecure_encryption/{analyzer.js → typescript/analyzer.js} +0 -0
  335. /package/rules/security/S011_secure_guid_generation/{README.md → typescript/README.md} +0 -0
  336. /package/rules/security/S011_secure_guid_generation/{analyzer.js → typescript/analyzer.js} +0 -0
  337. /package/rules/security/S011_secure_guid_generation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  338. /package/rules/security/S012_hardcoded_secrets/{analyzer.js → typescript/analyzer.js} +0 -0
  339. /package/rules/security/S012_hardcoded_secrets/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  340. /package/rules/security/S013_tls_enforcement/{README.md → typescript/README.md} +0 -0
  341. /package/rules/security/S013_tls_enforcement/{analyzer.js → typescript/analyzer.js} +0 -0
  342. /package/rules/security/S013_tls_enforcement/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  343. /package/rules/security/S014_tls_version_enforcement/{README.md → typescript/README.md} +0 -0
  344. /package/rules/security/S014_tls_version_enforcement/{analyzer.js → typescript/analyzer.js} +0 -0
  345. /package/rules/security/S014_tls_version_enforcement/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  346. /package/rules/security/S015_insecure_tls_certificate/{analyzer.js → typescript/analyzer.js} +0 -0
  347. /package/rules/security/S015_insecure_tls_certificate/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
  348. /package/rules/security/S016_no_sensitive_querystring/{analyzer.js → typescript/analyzer.js} +0 -0
  349. /package/rules/security/S016_no_sensitive_querystring/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  350. /package/rules/security/S016_no_sensitive_querystring/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  351. /package/rules/security/S017_use_parameterized_queries/{README.md → typescript/README.md} +0 -0
  352. /package/rules/security/S017_use_parameterized_queries/{analyzer.js → typescript/analyzer.js} +0 -0
  353. /package/rules/security/S017_use_parameterized_queries/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  354. /package/rules/security/S019_smtp_injection_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  355. /package/rules/security/S019_smtp_injection_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  356. /package/rules/security/S020_no_eval_dynamic_code/{README.md → typescript/README.md} +0 -0
  357. /package/rules/security/S020_no_eval_dynamic_code/{analyzer.js → typescript/analyzer.js} +0 -0
  358. /package/rules/security/S020_no_eval_dynamic_code/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  359. /package/rules/security/S022_escape_output_context/{README.md → typescript/README.md} +0 -0
  360. /package/rules/security/S022_escape_output_context/{analyzer.js → typescript/analyzer.js} +0 -0
  361. /package/rules/security/S023_no_json_injection/{analyzer.js → typescript/analyzer.js} +0 -0
  362. /package/rules/security/S023_no_json_injection/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
  363. /package/rules/security/S024_xpath_xxe_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  364. /package/rules/security/S024_xpath_xxe_protection/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  365. /package/rules/security/S024_xpath_xxe_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  366. /package/rules/security/S025_server_side_validation/{README.md → typescript/README.md} +0 -0
  367. /package/rules/security/S025_server_side_validation/{analyzer.js → typescript/analyzer.js} +0 -0
  368. /package/rules/security/S025_server_side_validation/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  369. /package/rules/security/S025_server_side_validation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  370. /package/rules/security/S026_json_schema_validation/{analyzer.js → typescript/analyzer.js} +0 -0
  371. /package/rules/security/S027_no_hardcoded_secrets/{analyzer.js → typescript/analyzer.js} +0 -0
  372. /package/rules/security/S027_no_hardcoded_secrets/{categories.json → typescript/categories.json} +0 -0
  373. /package/rules/security/S027_no_hardcoded_secrets/{categorized-analyzer.js → typescript/categorized-analyzer.js} +0 -0
  374. /package/rules/security/S028_file_upload_size_limits/{README.md → typescript/README.md} +0 -0
  375. /package/rules/security/S028_file_upload_size_limits/{analyzer.js → typescript/analyzer.js} +0 -0
  376. /package/rules/security/S028_file_upload_size_limits/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  377. /package/rules/security/S029_csrf_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  378. /package/rules/security/S030_directory_browsing_protection/{README.md → typescript/README.md} +0 -0
  379. /package/rules/security/S030_directory_browsing_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  380. /package/rules/security/S030_directory_browsing_protection/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  381. /package/rules/security/S030_directory_browsing_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  382. /package/rules/security/S031_secure_session_cookies/{README.md → typescript/README.md} +0 -0
  383. /package/rules/security/S031_secure_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
  384. /package/rules/security/S031_secure_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  385. /package/rules/security/S032_httponly_session_cookies/{FRAMEWORK_SUPPORT.md → typescript/FRAMEWORK_SUPPORT.md} +0 -0
  386. /package/rules/security/S032_httponly_session_cookies/{README.md → typescript/README.md} +0 -0
  387. /package/rules/security/S032_httponly_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
  388. /package/rules/security/S032_httponly_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  389. /package/rules/security/S032_httponly_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  390. /package/rules/security/S033_samesite_session_cookies/{README.md → typescript/README.md} +0 -0
  391. /package/rules/security/S033_samesite_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
  392. /package/rules/security/S033_samesite_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  393. /package/rules/security/S033_samesite_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  394. /package/rules/security/S034_host_prefix_session_cookies/{README.md → typescript/README.md} +0 -0
  395. /package/rules/security/S034_host_prefix_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
  396. /package/rules/security/S034_host_prefix_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  397. /package/rules/security/S034_host_prefix_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  398. /package/rules/security/S035_path_session_cookies/{README.md → typescript/README.md} +0 -0
  399. /package/rules/security/S035_path_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
  400. /package/rules/security/S035_path_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  401. /package/rules/security/S035_path_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  402. /package/rules/security/S036_lfi_rfi_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  403. /package/rules/security/S037_cache_headers/{README.md → typescript/README.md} +0 -0
  404. /package/rules/security/S037_cache_headers/{analyzer.js → typescript/analyzer.js} +0 -0
  405. /package/rules/security/S037_cache_headers/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  406. /package/rules/security/S037_cache_headers/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  407. /package/rules/security/S038_no_version_headers/{README.md → typescript/README.md} +0 -0
  408. /package/rules/security/S038_no_version_headers/{analyzer.js → typescript/analyzer.js} +0 -0
  409. /package/rules/security/S038_no_version_headers/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  410. /package/rules/security/S038_no_version_headers/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  411. /package/rules/security/S039_no_session_tokens_in_url/{README.md → typescript/README.md} +0 -0
  412. /package/rules/security/S039_no_session_tokens_in_url/{analyzer.js → typescript/analyzer.js} +0 -0
  413. /package/rules/security/S039_no_session_tokens_in_url/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  414. /package/rules/security/S039_no_session_tokens_in_url/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  415. /package/rules/security/S040_session_fixation_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  416. /package/rules/security/S041_session_token_invalidation/{README.md → typescript/README.md} +0 -0
  417. /package/rules/security/S041_session_token_invalidation/{analyzer.js → typescript/analyzer.js} +0 -0
  418. /package/rules/security/S041_session_token_invalidation/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  419. /package/rules/security/S041_session_token_invalidation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  420. /package/rules/security/S042_require_re_authentication_for_long_lived/{README.md → typescript/README.md} +0 -0
  421. /package/rules/security/S042_require_re_authentication_for_long_lived/{analyzer.js → typescript/analyzer.js} +0 -0
  422. /package/rules/security/S042_require_re_authentication_for_long_lived/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  423. /package/rules/security/S043_password_changes_invalidate_all_sessions/{README.md → typescript/README.md} +0 -0
  424. /package/rules/security/S043_password_changes_invalidate_all_sessions/{analyzer.js → typescript/analyzer.js} +0 -0
  425. /package/rules/security/S043_password_changes_invalidate_all_sessions/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  426. /package/rules/security/S044_re_authentication_required/{README.md → typescript/README.md} +0 -0
  427. /package/rules/security/S044_re_authentication_required/{analyzer.js → typescript/analyzer.js} +0 -0
  428. /package/rules/security/S044_re_authentication_required/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  429. /package/rules/security/S044_re_authentication_required/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  430. /package/rules/security/S045_brute_force_protection/{README.md → typescript/README.md} +0 -0
  431. /package/rules/security/S045_brute_force_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  432. /package/rules/security/S045_brute_force_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  433. /package/rules/security/S048_no_current_password_in_reset/{README.md → typescript/README.md} +0 -0
  434. /package/rules/security/S048_no_current_password_in_reset/{analyzer.js → typescript/analyzer.js} +0 -0
  435. /package/rules/security/S049_short_validity_tokens/{analyzer.js → typescript/analyzer.js} +0 -0
  436. /package/rules/security/S049_short_validity_tokens/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  437. /package/rules/security/S049_short_validity_tokens/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  438. /package/rules/security/S051_password_length_policy/{analyzer.js → typescript/analyzer.js} +0 -0
  439. /package/rules/security/S052_weak_otp_entropy/{analyzer.js → typescript/analyzer.js} +0 -0
  440. /package/rules/security/S054_no_default_accounts/{README.md → typescript/README.md} +0 -0
  441. /package/rules/security/S054_no_default_accounts/{analyzer.js → typescript/analyzer.js} +0 -0
  442. /package/rules/security/S055_content_type_validation/{README.md → typescript/README.md} +0 -0
  443. /package/rules/security/S055_content_type_validation/{analyzer.js → typescript/analyzer.js} +0 -0
  444. /package/rules/security/S055_content_type_validation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  445. /package/rules/security/S056_log_injection_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  446. /package/rules/security/S056_log_injection_protection/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  447. /package/rules/security/S056_log_injection_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  448. /package/rules/security/S057_utc_logging/{README.md → typescript/README.md} +0 -0
  449. /package/rules/security/S057_utc_logging/{analyzer.js → typescript/analyzer.js} +0 -0
  450. /package/rules/security/S058_no_ssrf/{README.md → typescript/README.md} +0 -0
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Language Analyzer Adapters - Registration Module
3
+ * Automatically registers all available language analyzers
4
+ *
5
+ * Following Rule C005: Single responsibility - analyzer registration
6
+ */
7
+
8
+ const { getRegistry } = require('../interfaces/language-analyzer.interface');
9
+ const TypeScriptAnalyzer = require('./typescript-analyzer');
10
+ const DartAnalyzer = require('./dart-analyzer');
11
+
12
+ /**
13
+ * Register all built-in language analyzers
14
+ * @param {Object} [options] - Options
15
+ * @param {boolean} [options.verbose] - Enable verbose logging
16
+ * @returns {LanguageAnalyzerRegistry} - The registry with registered analyzers
17
+ */
18
+ function registerBuiltInAnalyzers(options = {}) {
19
+ const registry = getRegistry();
20
+ const { verbose = false } = options;
21
+
22
+ // Register TypeScript/JavaScript analyzer
23
+ if (!registry.has('typescript')) {
24
+ const tsAnalyzer = new TypeScriptAnalyzer();
25
+ registry.register(tsAnalyzer);
26
+ if (verbose) {
27
+ console.log(`📝 Registered TypeScript/JavaScript analyzer`);
28
+ }
29
+ }
30
+
31
+ // Register Dart analyzer
32
+ if (!registry.has('dart')) {
33
+ const dartAnalyzer = new DartAnalyzer();
34
+ registry.register(dartAnalyzer);
35
+ if (verbose) {
36
+ console.log(`📝 Registered Dart analyzer`);
37
+ }
38
+ }
39
+
40
+ return registry;
41
+ }
42
+
43
+ /**
44
+ * Get supported languages info
45
+ * @returns {Object[]} - Array of language info objects
46
+ */
47
+ function getSupportedLanguages() {
48
+ return [
49
+ {
50
+ name: 'typescript',
51
+ displayName: 'TypeScript',
52
+ extensions: ['.ts', '.tsx', '.mts', '.cts'],
53
+ analyzerClass: TypeScriptAnalyzer
54
+ },
55
+ {
56
+ name: 'javascript',
57
+ displayName: 'JavaScript',
58
+ extensions: ['.js', '.jsx', '.mjs', '.cjs'],
59
+ analyzerClass: TypeScriptAnalyzer // Shares analyzer with TypeScript
60
+ },
61
+ {
62
+ name: 'dart',
63
+ displayName: 'Dart',
64
+ extensions: ['.dart'],
65
+ analyzerClass: DartAnalyzer
66
+ }
67
+ ];
68
+ }
69
+
70
+ /**
71
+ * Get analyzer class for a language
72
+ * @param {string} language - Language name
73
+ * @returns {Class|null} - Analyzer class or null
74
+ */
75
+ function getAnalyzerClass(language) {
76
+ const langLower = language.toLowerCase();
77
+
78
+ switch (langLower) {
79
+ case 'typescript':
80
+ case 'javascript':
81
+ case 'ts':
82
+ case 'js':
83
+ return TypeScriptAnalyzer;
84
+ case 'dart':
85
+ return DartAnalyzer;
86
+ default:
87
+ return null;
88
+ }
89
+ }
90
+
91
+ module.exports = {
92
+ // Registration
93
+ registerBuiltInAnalyzers,
94
+
95
+ // Analyzer classes
96
+ TypeScriptAnalyzer,
97
+ DartAnalyzer,
98
+
99
+ // Utilities
100
+ getSupportedLanguages,
101
+ getAnalyzerClass
102
+ };
@@ -55,7 +55,6 @@ class SunlintRuleAdapter {
55
55
  }
56
56
 
57
57
  this.isInitialized = true;
58
- console.log(`✅ SunlintRuleAdapter initialized with ${this.getAllRuleIds().length} rules`);
59
58
  return true;
60
59
 
61
60
  } catch (error) {
@@ -74,7 +73,6 @@ class SunlintRuleAdapter {
74
73
  if (fs.existsSync(registryPath)) {
75
74
  const registryData = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
76
75
  this.registryCache = registryData.rules || {};
77
- console.log(`📊 Loaded ${Object.keys(this.registryCache).length} rules from registry`);
78
76
  return true;
79
77
  }
80
78
 
@@ -0,0 +1,277 @@
1
+ /**
2
+ * TypeScript/JavaScript Analyzer
3
+ * Implements ILanguageAnalyzer for TypeScript and JavaScript files
4
+ * Wraps the existing SemanticEngine (ts-morph) functionality
5
+ *
6
+ * Following Rule C005: Single responsibility - TypeScript/JS analysis only
7
+ * Following Rule C014: Dependency injection - implements ILanguageAnalyzer
8
+ */
9
+
10
+ const path = require('path');
11
+ const { ILanguageAnalyzer } = require('../interfaces/language-analyzer.interface');
12
+ const SemanticEngine = require('../semantic-engine');
13
+
14
+ class TypeScriptAnalyzer extends ILanguageAnalyzer {
15
+ /**
16
+ * Create a TypeScript/JavaScript analyzer
17
+ */
18
+ constructor() {
19
+ super('typescript', ['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts', '.mjs', '.cjs']);
20
+
21
+ // The underlying ts-morph based engine
22
+ this.semanticEngine = null;
23
+ this.projectPath = null;
24
+
25
+ // Cache for quick lookups
26
+ this.fileCache = new Map();
27
+ }
28
+
29
+ /**
30
+ * Initialize the TypeScript analyzer
31
+ * @param {Object} config - Configuration
32
+ * @param {string} config.projectPath - Project root path
33
+ * @param {string[]} [config.targetFiles] - Specific files to analyze
34
+ * @param {number} [config.maxSemanticFiles] - Max files to load
35
+ * @param {boolean} [config.verbose] - Enable verbose logging
36
+ * @returns {Promise<boolean>} - True if initialization succeeded
37
+ */
38
+ async initialize(config) {
39
+ try {
40
+ const {
41
+ projectPath = process.cwd(),
42
+ targetFiles = null,
43
+ maxSemanticFiles,
44
+ verbose = false,
45
+ compilerOptions = {}
46
+ } = config;
47
+
48
+ this.projectPath = projectPath;
49
+ this.verbose = verbose;
50
+
51
+ // Filter only TypeScript/JavaScript files from targetFiles
52
+ const tsFiles = targetFiles
53
+ ? targetFiles.filter(f => this.supportsFile(f))
54
+ : null;
55
+
56
+ if (verbose) {
57
+ console.log(`🔷 TypeScriptAnalyzer: Initializing for ${projectPath}`);
58
+ if (tsFiles) {
59
+ console.log(` 📄 Target files: ${tsFiles.length} TypeScript/JavaScript files`);
60
+ }
61
+ }
62
+
63
+ // Create and initialize the underlying semantic engine
64
+ this.semanticEngine = new SemanticEngine({
65
+ maxSemanticFiles,
66
+ verbose,
67
+ compilerOptions: {
68
+ target: 99, // Latest
69
+ allowJs: true,
70
+ checkJs: false,
71
+ skipLibCheck: true,
72
+ skipDefaultLibCheck: true,
73
+ ...compilerOptions
74
+ },
75
+ enableCaching: true
76
+ });
77
+
78
+ // Initialize with filtered files
79
+ const success = await this.semanticEngine.initialize(projectPath, tsFiles);
80
+
81
+ if (success) {
82
+ this.initialized = true;
83
+ if (verbose) {
84
+ console.log(`✅ TypeScriptAnalyzer initialized successfully`);
85
+ }
86
+ } else {
87
+ if (verbose) {
88
+ console.warn(`⚠️ TypeScriptAnalyzer: ts-morph initialization failed, using fallback mode`);
89
+ }
90
+ // Still mark as initialized for fallback regex-based analysis
91
+ this.initialized = true;
92
+ }
93
+
94
+ return true;
95
+ } catch (error) {
96
+ console.error(`❌ TypeScriptAnalyzer initialization failed:`, error.message);
97
+ // Initialize anyway for fallback mode
98
+ this.initialized = true;
99
+ return false;
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Analyze a single file
105
+ * @param {string} filePath - Path to the file
106
+ * @param {Object[]} rules - Rules to apply
107
+ * @param {Object} [options] - Analysis options
108
+ * @returns {Promise<Object[]>} - Array of violations
109
+ */
110
+ async analyzeFile(filePath, rules, options = {}) {
111
+ if (!this.initialized) {
112
+ console.warn(`⚠️ TypeScriptAnalyzer not initialized`);
113
+ return [];
114
+ }
115
+
116
+ if (!this.supportsFile(filePath)) {
117
+ return [];
118
+ }
119
+
120
+ const violations = [];
121
+ const startTime = Date.now();
122
+
123
+ try {
124
+ // Get symbol table for this file
125
+ const symbolTable = await this.getSymbolTable(filePath);
126
+
127
+ // Process each rule
128
+ for (const rule of rules) {
129
+ // Skip rules not applicable to TypeScript/JavaScript
130
+ if (rule.languages && !this.isRuleApplicable(rule)) {
131
+ continue;
132
+ }
133
+
134
+ // Semantic rules use the symbol table
135
+ if (rule.analyzeWithSymbolTable && symbolTable) {
136
+ try {
137
+ const ruleViolations = await rule.analyzeWithSymbolTable(symbolTable, {
138
+ filePath,
139
+ ...options
140
+ });
141
+ violations.push(...(ruleViolations || []));
142
+ } catch (error) {
143
+ if (this.verbose) {
144
+ console.warn(`⚠️ Rule ${rule.ruleId} failed on ${path.basename(filePath)}:`, error.message);
145
+ }
146
+ }
147
+ }
148
+ }
149
+
150
+ this.stats.filesAnalyzed++;
151
+ this.stats.totalAnalysisTime += Date.now() - startTime;
152
+
153
+ } catch (error) {
154
+ console.error(`❌ Error analyzing ${filePath}:`, error.message);
155
+ }
156
+
157
+ return violations;
158
+ }
159
+
160
+ /**
161
+ * Get the Symbol Table for a file
162
+ * @param {string} filePath - Absolute path to the file
163
+ * @returns {Promise<Object|null>} - Symbol table or null
164
+ */
165
+ async getSymbolTable(filePath) {
166
+ if (!this.semanticEngine || !this.semanticEngine.isSymbolEngineReady()) {
167
+ return null;
168
+ }
169
+
170
+ // Check cache
171
+ const absolutePath = path.resolve(filePath);
172
+ if (this.fileCache.has(absolutePath)) {
173
+ this.stats.cacheHits++;
174
+ return this.fileCache.get(absolutePath);
175
+ }
176
+
177
+ try {
178
+ this.stats.cacheMisses++;
179
+ const symbolTable = await this.semanticEngine.getSymbolTable(absolutePath);
180
+
181
+ // Cache the result
182
+ if (symbolTable) {
183
+ this.fileCache.set(absolutePath, symbolTable);
184
+ }
185
+
186
+ return symbolTable;
187
+ } catch (error) {
188
+ if (this.verbose) {
189
+ console.warn(`⚠️ Failed to get symbol table for ${path.basename(filePath)}:`, error.message);
190
+ }
191
+ return null;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Check if a rule is applicable to TypeScript/JavaScript
197
+ * @param {Object} rule - Rule definition
198
+ * @returns {boolean} - True if applicable
199
+ */
200
+ isRuleApplicable(rule) {
201
+ if (!rule.languages || rule.languages.length === 0) {
202
+ return true; // No language restriction
203
+ }
204
+
205
+ const applicableLanguages = ['typescript', 'javascript', 'all'];
206
+ return rule.languages.some(lang => applicableLanguages.includes(lang.toLowerCase()));
207
+ }
208
+
209
+ /**
210
+ * Get the underlying semantic engine
211
+ * For backward compatibility with existing code
212
+ * @returns {SemanticEngine|null}
213
+ */
214
+ getSemanticEngine() {
215
+ return this.semanticEngine;
216
+ }
217
+
218
+ /**
219
+ * Check if Symbol Table is ready
220
+ * For backward compatibility
221
+ * @returns {boolean}
222
+ */
223
+ isSymbolEngineReady() {
224
+ return this.semanticEngine?.isSymbolEngineReady() || false;
225
+ }
226
+
227
+ /**
228
+ * Get ts-morph project
229
+ * For advanced use cases
230
+ * @returns {Project|null}
231
+ */
232
+ getProject() {
233
+ return this.semanticEngine?.project || null;
234
+ }
235
+
236
+ /**
237
+ * Get source file from ts-morph
238
+ * @param {string} filePath - Path to the file
239
+ * @returns {SourceFile|null}
240
+ */
241
+ getSourceFile(filePath) {
242
+ const project = this.getProject();
243
+ if (!project) return null;
244
+
245
+ const absolutePath = path.resolve(filePath);
246
+ return project.getSourceFile(absolutePath) || null;
247
+ }
248
+
249
+ /**
250
+ * Clear the file cache
251
+ */
252
+ clearCache() {
253
+ this.fileCache.clear();
254
+ }
255
+
256
+ /**
257
+ * Cleanup resources
258
+ * @returns {Promise<void>}
259
+ */
260
+ async dispose() {
261
+ if (this.semanticEngine) {
262
+ await this.semanticEngine.cleanup();
263
+ this.semanticEngine = null;
264
+ }
265
+
266
+ this.fileCache.clear();
267
+ this.initialized = false;
268
+
269
+ if (this.verbose) {
270
+ console.log(`🧹 TypeScriptAnalyzer disposed`);
271
+ console.log(` 📊 Files analyzed: ${this.stats.filesAnalyzed}`);
272
+ console.log(` 🎯 Cache hits: ${this.stats.cacheHits}`);
273
+ }
274
+ }
275
+ }
276
+
277
+ module.exports = TypeScriptAnalyzer;
@@ -185,13 +185,30 @@ class AnalysisOrchestrator {
185
185
  );
186
186
 
187
187
  if (!options.quiet) {
188
- console.log(chalk.cyan(`🔍 Analyzing ${optimizedRules.length} rules on ${optimizedFiles.length} files...`));
189
- if (performanceMetrics.filteredFiles > 0) {
190
- console.log(chalk.gray(` 📦 Filtered ${performanceMetrics.filteredFiles} files for performance`));
191
- }
192
- if (performanceMetrics.ruleBatches > 1) {
193
- console.log(chalk.gray(` 🔄 Using ${performanceMetrics.ruleBatches} rule batches`));
188
+ // Group rules by category
189
+ const rulesByCategory = this.groupRulesByCategory(optimizedRules);
190
+ const categoryBreakdown = Object.entries(rulesByCategory)
191
+ .map(([cat, rules]) => `${cat}:${rules.length}`)
192
+ .join(' · ');
193
+
194
+ // Professional startup display
195
+ console.log();
196
+ console.log(chalk.cyan(` ➜ Rules `) + chalk.white(`${optimizedRules.length}`) + chalk.gray(` (${categoryBreakdown})`));
197
+ console.log(chalk.cyan(` ➜ Files `) + chalk.white(`${optimizedFiles.length}`) + chalk.gray(` targeted`));
198
+
199
+ // Display rules by category with truncation
200
+ for (const [category, rules] of Object.entries(rulesByCategory)) {
201
+ const ruleIds = rules.map(r => r.id || r).sort();
202
+ const displayRules = ruleIds.length > 8
203
+ ? ruleIds.slice(0, 8).join(', ') + chalk.gray(` +${ruleIds.length - 8} more`)
204
+ : ruleIds.join(', ');
205
+ console.log(chalk.cyan(` ➜ ${category} `) + chalk.gray(displayRules));
194
206
  }
207
+
208
+ // Separator before progress
209
+ console.log();
210
+ console.log(chalk.gray(' ─────────────────────────────────────────────────────────────'));
211
+ console.log();
195
212
  }
196
213
 
197
214
  // Group rules by their preferred engines
@@ -206,21 +223,28 @@ class AnalysisOrchestrator {
206
223
  totalBatches += ruleBatches.length;
207
224
  }
208
225
 
209
- if (!options.quiet) {
210
- console.log(chalk.cyan(`🚀 Running analysis across ${engineGroups.size} engines (${totalBatches} batches total)...`));
211
- }
212
-
213
226
  // Run analysis on each engine with batching
214
227
  const results = [];
215
228
  let completedBatches = 0;
229
+ let totalViolationsFound = 0;
230
+ const startTime = Date.now();
231
+ let currentEngineName = null;
216
232
 
217
233
  for (const [engineName, rules] of engineGroups) {
218
234
  const engine = this.engines.get(engineName);
219
235
  if (!engine) {
220
- console.warn(chalk.yellow(`⚠️ Engine ${engineName} not found, skipping ${rules.length} rules`));
221
236
  continue;
222
237
  }
223
238
 
239
+ // Display engine header when switching to new engine
240
+ if (!options.quiet && engineName !== currentEngineName) {
241
+ currentEngineName = engineName;
242
+ const engineLabel = this.getEngineDisplayName(engineName);
243
+ const engineRulesCount = rules.length;
244
+ console.log();
245
+ console.log(chalk.cyan(` ⚙ ${engineLabel}`) + chalk.gray(` · ${engineRulesCount} rules · ${optimizedFiles.length} files`));
246
+ }
247
+
224
248
  // Get pre-calculated batches
225
249
  const ruleBatches = engineBatchInfo.get(engineName);
226
250
 
@@ -228,13 +252,15 @@ class AnalysisOrchestrator {
228
252
  const batch = ruleBatches[i];
229
253
  const batchNumber = i + 1;
230
254
  const overallProgress = Math.round((completedBatches / totalBatches) * 100);
255
+ const batchStartTime = Date.now();
231
256
 
257
+ // Log batch start - multi-line format for easier debugging
232
258
  if (!options.quiet) {
233
- if (ruleBatches.length > 1) {
234
- console.log(chalk.blue(`⚙️ [${overallProgress}%] ${engineName} - Batch ${batchNumber}/${ruleBatches.length}: ${batch.length} rules (${optimizedFiles.length} files)`));
235
- } else {
236
- console.log(chalk.blue(`⚙️ [${overallProgress}%] Running ${batch.length} rules on ${engineName} engine (${optimizedFiles.length} files)...`));
237
- }
259
+ const batchLabel = `Batch ${completedBatches + 1}/${totalBatches}`;
260
+ console.log();
261
+ console.log(chalk.gray(` ┌─ ${batchLabel} `) + chalk.dim(`(${overallProgress}%)`));
262
+ // Display each rule on separate line
263
+ this.displayBatchRulesMultiLine(batch);
238
264
  }
239
265
 
240
266
  try {
@@ -253,33 +279,45 @@ class AnalysisOrchestrator {
253
279
  ...engineResult
254
280
  });
255
281
 
282
+ const batchViolations = this.countViolations(engineResult);
256
283
  completedBatches++;
257
- const newProgress = Math.round((completedBatches / totalBatches) * 100);
284
+ totalViolationsFound += batchViolations;
285
+ const batchDuration = ((Date.now() - batchStartTime) / 1000).toFixed(2);
258
286
 
287
+ // Log batch result
259
288
  if (!options.quiet) {
260
- const violationCount = this.countViolations(engineResult);
261
- console.log(chalk.green(`✅ [${newProgress}%] ${engineName} batch ${batchNumber}/${ruleBatches.length}: ${violationCount} violations found`));
289
+ if (batchViolations > 0) {
290
+ console.log(chalk.gray(` └─ `) + chalk.yellow(`⚠ ${batchViolations} issues`) + chalk.gray(` · ${batchDuration}s`));
291
+ } else {
292
+ console.log(chalk.gray(` └─ `) + chalk.green(`✓ passed`) + chalk.gray(` · ${batchDuration}s`));
293
+ }
262
294
  }
295
+
263
296
  } catch (error) {
264
- // Enhanced error recovery with batch context
265
- const errorInfo = this.performanceOptimizer.handleAnalysisError(error, {
266
- engine: engineName,
267
- batch: batchNumber,
268
- rules: batch.map(r => r.id),
269
- files: optimizedFiles.length
270
- });
271
-
272
- console.error(chalk.red(`❌ Engine ${engineName} batch ${batchNumber} failed:`), errorInfo.message);
273
-
274
- if (errorInfo.shouldRetry && !options.noRetry) {
275
- console.log(chalk.yellow(`🔄 Retrying with reduced batch size...`));
276
- // Split batch and retry - implement recursive retry logic here
297
+ completedBatches++;
298
+ const batchDuration = ((Date.now() - batchStartTime) / 1000).toFixed(2);
299
+ if (!options.quiet) {
300
+ console.log(chalk.gray(` └─ `) + chalk.red(`✗ Error: ${error.message}`) + chalk.gray(` · ${batchDuration}s`));
277
301
  }
278
- // Continue with other batches instead of failing completely
279
302
  }
280
303
  }
281
304
  }
282
305
 
306
+ // Show final result
307
+ if (!options.quiet) {
308
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
309
+ console.log();
310
+ console.log(chalk.gray(' ─────────────────────────────────────────────────────────────'));
311
+ console.log();
312
+
313
+ if (totalViolationsFound === 0) {
314
+ console.log(' ' + chalk.green('✓ All checks passed') + chalk.gray(` · ${elapsed}s`));
315
+ } else {
316
+ console.log(' ' + chalk.yellow(`⚠ ${totalViolationsFound} issues`) + chalk.gray(` · ${elapsed}s`));
317
+ }
318
+ console.log();
319
+ }
320
+
283
321
  // Merge results and add performance metrics
284
322
  const mergedResults = this.mergeEngineResults(results, options, optimizedFiles.length);
285
323
  mergedResults.performance = performanceMetrics;
@@ -340,12 +378,6 @@ class AnalysisOrchestrator {
340
378
  groups.get(selectedEngine).push(rule);
341
379
  }
342
380
 
343
- // Report skipped rules if any
344
- if (skippedRules.length > 0) {
345
- const skippedRuleIds = skippedRules.map(r => r.id).join(', ');
346
- console.warn(`⚠️ [Orchestrator] Skipped ${skippedRules.length} rules not supported by requested engine: ${skippedRuleIds}`);
347
- }
348
-
349
381
  if (config.verbose) {
350
382
  console.log(`📋 [Orchestrator] Final groups:`, Array.from(groups.entries()).map(([k, v]) => [k, v.length]));
351
383
  }
@@ -610,6 +642,103 @@ class AnalysisOrchestrator {
610
642
  return mergedResults;
611
643
  }
612
644
 
645
+ /**
646
+ * Create a visual progress bar
647
+ * @param {number} percent - Progress percentage (0-100)
648
+ * @returns {string} Progress bar string
649
+ */
650
+ createProgressBar(percent) {
651
+ const width = 20;
652
+ const filled = Math.round((percent / 100) * width);
653
+ const empty = width - filled;
654
+ return '[' + '█'.repeat(filled) + '░'.repeat(empty) + ']';
655
+ }
656
+
657
+ /**
658
+ * Get human-readable display name for an engine
659
+ * Following Rule C006: Verb-noun naming
660
+ * @param {string} engineName - Engine identifier
661
+ * @returns {string} Display name for the engine
662
+ */
663
+ getEngineDisplayName(engineName) {
664
+ const displayNames = {
665
+ 'heuristic': 'Heuristic Engine',
666
+ 'eslint': 'ESLint Engine',
667
+ 'openai': 'AI Engine',
668
+ 'ai': 'AI Engine',
669
+ 'typescript': 'TypeScript Engine',
670
+ 'semantic': 'Semantic Engine'
671
+ };
672
+ return displayNames[engineName] || `${engineName.charAt(0).toUpperCase()}${engineName.slice(1)} Engine`;
673
+ }
674
+
675
+ /**
676
+ * Format batch rules display with IDs and names
677
+ * Following Rule C006: Verb-noun naming
678
+ * @param {Object[]} batch - Array of rule objects
679
+ * @returns {string} Formatted rules display string
680
+ */
681
+ formatBatchRulesDisplay(batch) {
682
+ const maxLength = 60;
683
+ const ruleDisplays = batch.map(rule => {
684
+ const id = rule.id || rule;
685
+ const name = rule.name || rule.title;
686
+ if (name) {
687
+ // Truncate long rule names
688
+ const shortName = name.length > 25 ? name.substring(0, 25) + '…' : name;
689
+ return `${id}: ${shortName}`;
690
+ }
691
+ return id;
692
+ });
693
+
694
+ // Join and truncate if too long
695
+ const fullDisplay = ruleDisplays.join(' │ ');
696
+ if (fullDisplay.length > maxLength) {
697
+ return fullDisplay.substring(0, maxLength) + '…';
698
+ }
699
+ return fullDisplay;
700
+ }
701
+
702
+ /**
703
+ * Display batch rules in multi-line format for easier debugging
704
+ * Following Rule C006: Verb-noun naming
705
+ * @param {Object[]} batch - Array of rule objects
706
+ */
707
+ displayBatchRulesMultiLine(batch) {
708
+ for (let i = 0; i < batch.length; i++) {
709
+ const rule = batch[i];
710
+ const id = rule.id || rule;
711
+ const name = rule.name || rule.title || '';
712
+ const isLast = i === batch.length - 1;
713
+ const prefix = isLast ? ' │ └─' : ' │ ├─';
714
+
715
+ if (name) {
716
+ console.log(chalk.gray(prefix) + ' ' + chalk.cyan(id) + chalk.gray(': ') + chalk.white(name));
717
+ } else {
718
+ console.log(chalk.gray(prefix) + ' ' + chalk.cyan(id));
719
+ }
720
+ }
721
+ }
722
+
723
+ /**
724
+ * Group rules by category prefix (C, S, T, R, etc.)
725
+ * Following Rule C006: Verb-noun naming
726
+ * @param {Object[]} rules - Rules to group
727
+ * @returns {Object} Object with category arrays
728
+ */
729
+ groupRulesByCategory(rules) {
730
+ const groups = {};
731
+ for (const rule of rules) {
732
+ const ruleId = rule.id || rule;
733
+ const category = ruleId.charAt(0); // Get first character (C, S, T, R, etc.)
734
+ if (!groups[category]) {
735
+ groups[category] = [];
736
+ }
737
+ groups[category].push(rule);
738
+ }
739
+ return groups;
740
+ }
741
+
613
742
  /**
614
743
  * Count violations in engine results
615
744
  * Following Rule C006: Verb-noun naming
@@ -690,7 +819,6 @@ class AnalysisOrchestrator {
690
819
  }
691
820
 
692
821
  this.initialized = false;
693
- console.log(chalk.blue('🧹 Engine cleanup completed'));
694
822
  }
695
823
  }
696
824