@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,393 @@
1
+ /**
2
+ * Language Analyzer Interface
3
+ * Defines the contract for all language-specific analyzers in SunLint
4
+ * Following Rule C014: Dependency injection - Plugin interface
5
+ * Following Rule C015: Use domain language - clear interface naming
6
+ *
7
+ * This interface enables multi-language support by allowing different
8
+ * analyzers (TypeScript, Dart, etc.) to be registered and used interchangeably.
9
+ */
10
+
11
+ /**
12
+ * @typedef {Object} AnalyzerConfig
13
+ * @property {string} projectPath - Root path of the project
14
+ * @property {string[]} [targetFiles] - Specific files to analyze
15
+ * @property {number} [maxFiles] - Maximum files to load for analysis
16
+ * @property {boolean} [verbose] - Enable verbose logging
17
+ * @property {Object} [compilerOptions] - Language-specific compiler options
18
+ */
19
+
20
+ /**
21
+ * @typedef {Object} Violation
22
+ * @property {string} ruleId - The rule ID that was violated
23
+ * @property {string} filePath - Absolute path to the file
24
+ * @property {number} line - Line number (1-based)
25
+ * @property {number} column - Column number (1-based)
26
+ * @property {string} message - Human-readable violation message
27
+ * @property {string} [severity] - 'error' | 'warning' | 'info'
28
+ * @property {string} [analysisMethod] - 'ast' | 'regex' | 'semantic'
29
+ * @property {number} [confidence] - Confidence score (0-100)
30
+ */
31
+
32
+ /**
33
+ * @typedef {Object} SymbolTable
34
+ * @property {string} filePath - Absolute path to the file
35
+ * @property {string} fileName - Base name of the file
36
+ * @property {Array} imports - Import declarations
37
+ * @property {Array} exports - Export declarations
38
+ * @property {Array} functions - Function declarations
39
+ * @property {Array} classes - Class declarations
40
+ * @property {Array} interfaces - Interface declarations
41
+ * @property {Array} variables - Variable declarations
42
+ * @property {Array} constants - Constant declarations
43
+ * @property {Array} functionCalls - Function call expressions
44
+ * @property {Array} methodCalls - Method call expressions
45
+ * @property {number} lastModified - Timestamp
46
+ * @property {number} analysisTime - Analysis duration in ms
47
+ */
48
+
49
+ /**
50
+ * ILanguageAnalyzer Interface
51
+ * All language analyzers must implement this interface
52
+ */
53
+ class ILanguageAnalyzer {
54
+ /**
55
+ * Constructor for Language Analyzer
56
+ * @param {string} name - Analyzer name (e.g., 'typescript', 'dart')
57
+ * @param {string[]} extensions - Supported file extensions (e.g., ['.ts', '.tsx'])
58
+ */
59
+ constructor(name, extensions = []) {
60
+ if (this.constructor === ILanguageAnalyzer) {
61
+ throw new Error('ILanguageAnalyzer is abstract and cannot be instantiated directly');
62
+ }
63
+
64
+ this.name = name;
65
+ this.extensions = extensions;
66
+ this.initialized = false;
67
+ this.stats = {
68
+ filesAnalyzed: 0,
69
+ cacheHits: 0,
70
+ cacheMisses: 0,
71
+ totalAnalysisTime: 0
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Initialize the language analyzer
77
+ * @param {AnalyzerConfig} config - Analyzer configuration
78
+ * @returns {Promise<boolean>} - True if initialization succeeded
79
+ */
80
+ async initialize(config) {
81
+ throw new Error(`Method initialize() must be implemented by ${this.constructor.name}`);
82
+ }
83
+
84
+ /**
85
+ * Analyze a single file and return violations
86
+ * @param {string} filePath - Absolute path to the file
87
+ * @param {Object[]} rules - Array of rule objects to apply
88
+ * @param {Object} [options] - Analysis options
89
+ * @returns {Promise<Violation[]>} - Array of violations found
90
+ */
91
+ async analyzeFile(filePath, rules, options = {}) {
92
+ throw new Error(`Method analyzeFile() must be implemented by ${this.constructor.name}`);
93
+ }
94
+
95
+ /**
96
+ * Analyze multiple files
97
+ * @param {string[]} files - Array of file paths
98
+ * @param {Object[]} rules - Array of rule objects to apply
99
+ * @param {Object} [options] - Analysis options
100
+ * @returns {Promise<Violation[]>} - Array of violations found
101
+ */
102
+ async analyzeFiles(files, rules, options = {}) {
103
+ const violations = [];
104
+
105
+ for (const file of files) {
106
+ if (this.supportsFile(file)) {
107
+ const fileViolations = await this.analyzeFile(file, rules, options);
108
+ violations.push(...fileViolations);
109
+ }
110
+ }
111
+
112
+ return violations;
113
+ }
114
+
115
+ /**
116
+ * Get the Symbol Table for a file
117
+ * Used by semantic rules for cross-file analysis
118
+ * @param {string} filePath - Absolute path to the file
119
+ * @returns {Promise<SymbolTable|null>} - Symbol table or null if not available
120
+ */
121
+ async getSymbolTable(filePath) {
122
+ throw new Error(`Method getSymbolTable() must be implemented by ${this.constructor.name}`);
123
+ }
124
+
125
+ /**
126
+ * Check if analyzer is ready for analysis
127
+ * @returns {boolean} - True if initialized and ready
128
+ */
129
+ isReady() {
130
+ return this.initialized;
131
+ }
132
+
133
+ /**
134
+ * Check if this analyzer supports a specific file
135
+ * @param {string} filePath - Path to the file
136
+ * @returns {boolean} - True if file is supported
137
+ */
138
+ supportsFile(filePath) {
139
+ const ext = require('path').extname(filePath).toLowerCase();
140
+ return this.extensions.includes(ext);
141
+ }
142
+
143
+ /**
144
+ * Check if this analyzer supports a specific file extension
145
+ * @param {string} extension - File extension (e.g., '.ts')
146
+ * @returns {boolean} - True if extension is supported
147
+ */
148
+ supportsExtension(extension) {
149
+ return this.extensions.includes(extension.toLowerCase());
150
+ }
151
+
152
+ /**
153
+ * Get analyzer metadata
154
+ * @returns {Object} - Analyzer metadata
155
+ */
156
+ getInfo() {
157
+ return {
158
+ name: this.name,
159
+ extensions: this.extensions,
160
+ initialized: this.initialized,
161
+ stats: { ...this.stats }
162
+ };
163
+ }
164
+
165
+ /**
166
+ * Get analysis statistics
167
+ * @returns {Object} - Statistics object
168
+ */
169
+ getStats() {
170
+ return { ...this.stats };
171
+ }
172
+
173
+ /**
174
+ * Reset statistics
175
+ */
176
+ resetStats() {
177
+ this.stats = {
178
+ filesAnalyzed: 0,
179
+ cacheHits: 0,
180
+ cacheMisses: 0,
181
+ totalAnalysisTime: 0
182
+ };
183
+ }
184
+
185
+ /**
186
+ * Cleanup resources
187
+ * Called when the analyzer is no longer needed
188
+ * @returns {Promise<void>}
189
+ */
190
+ async dispose() {
191
+ this.initialized = false;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Language Analyzer Registry
197
+ * Manages registration and lookup of language analyzers
198
+ */
199
+ class LanguageAnalyzerRegistry {
200
+ constructor() {
201
+ this.analyzers = new Map();
202
+ this.extensionMap = new Map(); // extension -> analyzer name
203
+ }
204
+
205
+ /**
206
+ * Register a language analyzer
207
+ * @param {ILanguageAnalyzer} analyzer - Analyzer instance
208
+ */
209
+ register(analyzer) {
210
+ if (!(analyzer instanceof ILanguageAnalyzer)) {
211
+ throw new Error('Analyzer must extend ILanguageAnalyzer');
212
+ }
213
+
214
+ this.analyzers.set(analyzer.name, analyzer);
215
+
216
+ // Map extensions to analyzer
217
+ for (const ext of analyzer.extensions) {
218
+ this.extensionMap.set(ext.toLowerCase(), analyzer.name);
219
+ }
220
+
221
+ // Silent registration - only log in verbose mode
222
+ }
223
+
224
+ /**
225
+ * Unregister a language analyzer
226
+ * @param {string} name - Analyzer name
227
+ */
228
+ unregister(name) {
229
+ const analyzer = this.analyzers.get(name);
230
+ if (analyzer) {
231
+ // Remove extension mappings
232
+ for (const ext of analyzer.extensions) {
233
+ if (this.extensionMap.get(ext) === name) {
234
+ this.extensionMap.delete(ext);
235
+ }
236
+ }
237
+ this.analyzers.delete(name);
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Get analyzer by name
243
+ * @param {string} name - Analyzer name
244
+ * @returns {ILanguageAnalyzer|null} - Analyzer instance or null
245
+ */
246
+ get(name) {
247
+ return this.analyzers.get(name) || null;
248
+ }
249
+
250
+ /**
251
+ * Get analyzer for a file
252
+ * @param {string} filePath - Path to the file
253
+ * @returns {ILanguageAnalyzer|null} - Analyzer instance or null
254
+ */
255
+ getForFile(filePath) {
256
+ const ext = require('path').extname(filePath).toLowerCase();
257
+ const analyzerName = this.extensionMap.get(ext);
258
+ return analyzerName ? this.analyzers.get(analyzerName) : null;
259
+ }
260
+
261
+ /**
262
+ * Get analyzer for an extension
263
+ * @param {string} extension - File extension
264
+ * @returns {ILanguageAnalyzer|null} - Analyzer instance or null
265
+ */
266
+ getForExtension(extension) {
267
+ const analyzerName = this.extensionMap.get(extension.toLowerCase());
268
+ return analyzerName ? this.analyzers.get(analyzerName) : null;
269
+ }
270
+
271
+ /**
272
+ * Get all registered analyzers
273
+ * @returns {ILanguageAnalyzer[]} - Array of analyzer instances
274
+ */
275
+ getAll() {
276
+ return Array.from(this.analyzers.values());
277
+ }
278
+
279
+ /**
280
+ * Get all registered analyzer names
281
+ * @returns {string[]} - Array of analyzer names
282
+ */
283
+ getNames() {
284
+ return Array.from(this.analyzers.keys());
285
+ }
286
+
287
+ /**
288
+ * Check if an analyzer is registered
289
+ * @param {string} name - Analyzer name
290
+ * @returns {boolean} - True if registered
291
+ */
292
+ has(name) {
293
+ return this.analyzers.has(name);
294
+ }
295
+
296
+ /**
297
+ * Check if a file is supported by any analyzer
298
+ * @param {string} filePath - Path to the file
299
+ * @returns {boolean} - True if supported
300
+ */
301
+ supportsFile(filePath) {
302
+ const ext = require('path').extname(filePath).toLowerCase();
303
+ return this.extensionMap.has(ext);
304
+ }
305
+
306
+ /**
307
+ * Get all supported extensions
308
+ * @returns {string[]} - Array of supported extensions
309
+ */
310
+ getSupportedExtensions() {
311
+ return Array.from(this.extensionMap.keys());
312
+ }
313
+
314
+ /**
315
+ * Initialize all registered analyzers
316
+ * @param {AnalyzerConfig} config - Configuration for all analyzers
317
+ * @returns {Promise<Map<string, boolean>>} - Map of analyzer name -> initialization success
318
+ */
319
+ async initializeAll(config) {
320
+ const results = new Map();
321
+
322
+ for (const [name, analyzer] of this.analyzers) {
323
+ try {
324
+ const success = await analyzer.initialize(config);
325
+ results.set(name, success);
326
+ } catch (error) {
327
+ console.error(`Failed to initialize ${name} analyzer:`, error.message);
328
+ results.set(name, false);
329
+ }
330
+ }
331
+
332
+ return results;
333
+ }
334
+
335
+ /**
336
+ * Dispose all registered analyzers
337
+ * @returns {Promise<void>}
338
+ */
339
+ async disposeAll() {
340
+ for (const analyzer of this.analyzers.values()) {
341
+ try {
342
+ await analyzer.dispose();
343
+ } catch (error) {
344
+ console.error(`Error disposing ${analyzer.name} analyzer:`, error.message);
345
+ }
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Get combined statistics from all analyzers
351
+ * @returns {Object} - Combined statistics
352
+ */
353
+ getCombinedStats() {
354
+ const combined = {
355
+ totalFilesAnalyzed: 0,
356
+ totalCacheHits: 0,
357
+ totalCacheMisses: 0,
358
+ totalAnalysisTime: 0,
359
+ byAnalyzer: {}
360
+ };
361
+
362
+ for (const [name, analyzer] of this.analyzers) {
363
+ const stats = analyzer.getStats();
364
+ combined.totalFilesAnalyzed += stats.filesAnalyzed;
365
+ combined.totalCacheHits += stats.cacheHits;
366
+ combined.totalCacheMisses += stats.cacheMisses;
367
+ combined.totalAnalysisTime += stats.totalAnalysisTime;
368
+ combined.byAnalyzer[name] = stats;
369
+ }
370
+
371
+ return combined;
372
+ }
373
+ }
374
+
375
+ // Singleton instance of the registry
376
+ let registryInstance = null;
377
+
378
+ /**
379
+ * Get the singleton registry instance
380
+ * @returns {LanguageAnalyzerRegistry}
381
+ */
382
+ function getRegistry() {
383
+ if (!registryInstance) {
384
+ registryInstance = new LanguageAnalyzerRegistry();
385
+ }
386
+ return registryInstance;
387
+ }
388
+
389
+ module.exports = {
390
+ ILanguageAnalyzer,
391
+ LanguageAnalyzerRegistry,
392
+ getRegistry
393
+ };
@@ -333,7 +333,7 @@ class OutputService {
333
333
 
334
334
  formatViolations(violations) {
335
335
  if (violations.length === 0) {
336
- return chalk.green(' No violations found!');
336
+ return ''; // Summary already shown by orchestrator
337
337
  }
338
338
 
339
339
  let output = '';
@@ -398,22 +398,23 @@ class OutputService {
398
398
  }
399
399
 
400
400
  generateSummary(violations, filesAnalyzed, metadata) {
401
- const duration = metadata.duration || 0;
401
+ // Summary is now minimal - main info shown by orchestrator
402
+ if (violations.length === 0) {
403
+ return ''; // Clean output when no issues
404
+ }
405
+
402
406
  const errorCount = violations.filter(v => v.severity === 'error').length;
403
407
  const warningCount = violations.filter(v => v.severity === 'warning').length;
404
408
 
405
- let summary = chalk.blue('\n📊 Sun Lint Summary:\n');
406
- summary += `Analysis completed in ${duration}ms\n`;
407
- summary += `Files: ${filesAnalyzed} | Total: ${violations.length}\n`;
408
-
409
- if (errorCount > 0) {
410
- summary += chalk.red(`Errors: ${errorCount} `);
411
- }
412
- if (warningCount > 0) {
413
- summary += chalk.yellow(`Warnings: ${warningCount} `);
414
- }
415
- if (violations.length === 0) {
416
- summary += chalk.green('All checks passed! ✅');
409
+ let summary = '\n';
410
+ if (errorCount > 0 || warningCount > 0) {
411
+ summary += chalk.gray(' ') + chalk.dim(`${filesAnalyzed} files · `);
412
+ if (errorCount > 0) {
413
+ summary += chalk.red(`${errorCount} errors `);
414
+ }
415
+ if (warningCount > 0) {
416
+ summary += chalk.yellow(`${warningCount} warnings`);
417
+ }
417
418
  }
418
419
 
419
420
  return summary;
@@ -2,6 +2,7 @@
2
2
  * Rule Selection Service
3
3
  * Following Rule C005: Single responsibility - only handle rule selection
4
4
  * REFACTORED: Now uses SunlintRuleAdapter instead of direct registry access
5
+ * UPDATED: Load rules from released-rules.json for consistency
5
6
  */
6
7
 
7
8
  const chalk = require('chalk');
@@ -15,6 +16,8 @@ class RuleSelectionService {
15
16
  this.ruleAdapter = SunlintRuleAdapter.getInstance();
16
17
  this.ruleMappingService = new RuleMappingService();
17
18
  this.initialized = false;
19
+ // Path works both in dev (from pages/) and npm package (from config/)
20
+ this.releasedRulesPath = path.join(__dirname, '../config/released-rules.json');
18
21
  }
19
22
 
20
23
  async initialize() {
@@ -24,55 +27,102 @@ class RuleSelectionService {
24
27
  }
25
28
  }
26
29
 
30
+ /**
31
+ * Load released rules from released-rules.json
32
+ * @param {string} [version] - Version to load (default: latest)
33
+ * @returns {Object} Object with Common, Security arrays
34
+ */
35
+ loadReleasedRules(version = null) {
36
+ try {
37
+ if (!fs.existsSync(this.releasedRulesPath)) {
38
+ return null;
39
+ }
40
+
41
+ const data = JSON.parse(fs.readFileSync(this.releasedRulesPath, 'utf8'));
42
+ const versions = data.versions || [];
43
+
44
+ if (versions.length === 0) {
45
+ return null;
46
+ }
47
+
48
+ // Get specified version or latest
49
+ const targetVersion = version
50
+ ? versions.find(v => v.version === version)
51
+ : versions[versions.length - 1]; // Latest version
52
+
53
+ if (!targetVersion) {
54
+ return null;
55
+ }
56
+
57
+ return targetVersion.rulesByCategory;
58
+ } catch (error) {
59
+ return null;
60
+ }
61
+ }
62
+
27
63
  async selectRules(config, options) {
28
64
  // Ensure adapter is initialized
29
65
  await this.initialize();
30
-
66
+
31
67
  const allRules = config.rules || {};
32
68
  let selectedRules = [];
33
69
 
70
+ // Try to load from released-rules.json first
71
+ const releasedRules = this.loadReleasedRules();
72
+
34
73
  // Determine rule selection strategy
35
74
  if (options.rule) {
36
75
  selectedRules = [options.rule];
37
76
  } else if (options.rules) {
38
77
  selectedRules = options.rules.split(',').map(r => r.trim());
39
78
  } else if (options.all) {
40
- // Handle --all shortcut (load from preset file)
41
- selectedRules = this.loadPresetRules('all');
42
-
43
- if (options.verbose) {
44
- console.log(chalk.blue(`📋 Selected ${selectedRules.length} rules from all preset file`));
79
+ // Load all rules from released-rules.json
80
+ if (releasedRules) {
81
+ selectedRules = [
82
+ ...(releasedRules.Common || []),
83
+ ...(releasedRules.Security || []),
84
+ ...(releasedRules.Frontend || []),
85
+ ...(releasedRules.Backend || []),
86
+ ...(releasedRules.Mobile || [])
87
+ ];
88
+ } else {
89
+ // Fallback to preset file
90
+ selectedRules = this.loadPresetRules('all');
45
91
  }
46
92
  } else if (options.quality) {
47
- // Handle --quality shortcut (load from preset file)
48
- selectedRules = this.loadPresetRules('quality');
49
-
50
- if (options.verbose) {
51
- console.log(chalk.blue(`📋 Selected ${selectedRules.length} quality rules from preset file`));
93
+ // Load Common rules from released-rules.json
94
+ if (releasedRules && releasedRules.Common) {
95
+ selectedRules = releasedRules.Common;
96
+ } else {
97
+ selectedRules = this.loadPresetRules('quality');
52
98
  }
53
99
  } else if (options.security) {
54
- // Handle --security shortcut (load from preset file)
55
- selectedRules = this.loadPresetRules('security');
56
-
57
- if (options.verbose) {
58
- console.log(chalk.blue(`📋 Selected ${selectedRules.length} security rules from preset file`));
100
+ // Load Security rules from released-rules.json
101
+ if (releasedRules && releasedRules.Security) {
102
+ selectedRules = releasedRules.Security;
103
+ } else {
104
+ selectedRules = this.loadPresetRules('security');
59
105
  }
60
106
  } else if (options.category) {
61
107
  // Handle --category shortcut (standardized approach)
62
108
  const categoryRules = this.ruleAdapter.getStandardCategoryRules(options.category);
63
109
  selectedRules = categoryRules.map(rule => rule.id);
64
-
65
- if (options.verbose) {
66
- console.log(chalk.blue(`📋 Selected ${selectedRules.length} ${options.category} rules from core files`));
67
- }
68
110
  } else {
69
- // Default: use config rules or minimal set
70
- selectedRules = Object.keys(allRules).filter(ruleId =>
71
- allRules[ruleId] !== 'off' && allRules[ruleId] !== false
72
- );
73
-
74
- if (selectedRules.length === 0) {
75
- selectedRules = ['C006', 'C019']; // Default minimal set
111
+ // Default: load all from released-rules.json
112
+ if (releasedRules) {
113
+ selectedRules = [
114
+ ...(releasedRules.Common || []),
115
+ ...(releasedRules.Security || [])
116
+ ];
117
+ } else {
118
+ // Fallback to config rules or minimal set
119
+ selectedRules = Object.keys(allRules).filter(ruleId =>
120
+ allRules[ruleId] !== 'off' && allRules[ruleId] !== false
121
+ );
122
+
123
+ if (selectedRules.length === 0) {
124
+ selectedRules = ['C006', 'C019']; // Default minimal set
125
+ }
76
126
  }
77
127
  }
78
128