@sun-asterisk/sunlint 1.3.32 → 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 (456) hide show
  1. package/README.md +47 -0
  2. package/config/released-rules.json +62 -0
  3. package/config/rules/enhanced-rules-registry.json +2315 -1354
  4. package/core/adapters/dart-analyzer.js +658 -0
  5. package/core/adapters/index.js +102 -0
  6. package/core/adapters/sunlint-rule-adapter.js +0 -2
  7. package/core/adapters/typescript-analyzer.js +277 -0
  8. package/core/analysis-orchestrator.js +168 -40
  9. package/core/architecture-integration.js +220 -0
  10. package/core/cli-action-handler.js +72 -24
  11. package/core/cli-program.js +13 -1
  12. package/core/config-merger.js +24 -14
  13. package/core/constants/defaults.js +1 -2
  14. package/core/github-annotate-service.js +141 -89
  15. package/core/github-step-summary-generator.js +8 -8
  16. package/core/interfaces/language-analyzer.interface.js +393 -0
  17. package/core/output-service.js +102 -38
  18. package/core/rule-selection-service.js +77 -27
  19. package/core/scoring-service.js +65 -20
  20. package/core/semantic-engine-manager.js +375 -0
  21. package/core/semantic-engine.js +4 -57
  22. package/core/unified-rule-registry.js +52 -11
  23. package/core/upload-service.js +43 -9
  24. package/docs/DART_RULE_EXECUTION_FLOW.md +745 -0
  25. package/docs/DART_SUPPORT_IMPLEMENTATION.md +245 -0
  26. package/docs/SUNLINT_ARCHITECTURE.md +692 -0
  27. package/docs/skills/CREATE_DART_RULE.md +909 -0
  28. package/engines/eslint-engine.js +2 -8
  29. package/engines/heuristic-engine.js +234 -38
  30. package/package.json +6 -5
  31. package/rules/common/C002_no_duplicate_code/config.json +12 -20
  32. package/rules/common/C002_no_duplicate_code/dart/analyzer.js +53 -0
  33. package/rules/common/C002_no_duplicate_code/index.js +93 -0
  34. package/rules/common/C003_no_vague_abbreviations/config.json +1 -1
  35. package/rules/common/C003_no_vague_abbreviations/dart/analyzer.js +54 -0
  36. package/rules/common/C003_no_vague_abbreviations/index.js +93 -0
  37. package/rules/common/C006_function_naming/dart/analyzer.js +40 -0
  38. package/rules/common/C006_function_naming/index.js +86 -0
  39. package/rules/common/C008_variable_declaration_locality/dart/analyzer.js +32 -0
  40. package/rules/common/C008_variable_declaration_locality/index.js +86 -0
  41. package/rules/common/C010_limit_block_nesting/dart/analyzer.js +32 -0
  42. package/rules/common/C010_limit_block_nesting/index.js +86 -0
  43. package/rules/common/C012_command_query_separation/config.json +61 -0
  44. package/rules/common/C012_command_query_separation/dart/analyzer.js +32 -0
  45. package/rules/common/C012_command_query_separation/index.js +86 -0
  46. package/rules/common/C013_no_dead_code/dart/analyzer.js +32 -0
  47. package/rules/common/C013_no_dead_code/index.js +86 -0
  48. package/rules/common/C014_dependency_injection/dart/analyzer.js +32 -0
  49. package/rules/common/C014_dependency_injection/index.js +86 -0
  50. package/rules/common/C017_constructor_logic/dart/analyzer.js +32 -0
  51. package/rules/common/C017_constructor_logic/index.js +86 -0
  52. package/rules/common/C018_no_throw_generic_error/dart/analyzer.js +32 -0
  53. package/rules/common/C018_no_throw_generic_error/index.js +86 -0
  54. package/rules/common/C019_log_level_usage/dart/analyzer.js +32 -0
  55. package/rules/common/C019_log_level_usage/index.js +86 -0
  56. package/rules/common/C019_log_level_usage/{ts-morph-analyzer.js → typescript/ts-morph-analyzer.js} +0 -1
  57. package/rules/common/C020_unused_imports/dart/analyzer.js +32 -0
  58. package/rules/common/C020_unused_imports/index.js +86 -0
  59. package/rules/common/C020_unused_imports/{ts-morph-analyzer.js → typescript/ts-morph-analyzer.js} +0 -1
  60. package/rules/common/C021_import_organization/config.json +29 -9
  61. package/rules/common/C021_import_organization/dart/analyzer.js +40 -0
  62. package/rules/common/C021_import_organization/index.js +83 -0
  63. package/rules/common/C021_import_organization/{ts-morph-analyzer.js → typescript/ts-morph-analyzer.js} +0 -1
  64. package/rules/common/C023_no_duplicate_variable/config.json +7 -2
  65. package/rules/common/C023_no_duplicate_variable/dart/analyzer.js +40 -0
  66. package/rules/common/C023_no_duplicate_variable/index.js +83 -0
  67. package/rules/common/C024_no_scatter_hardcoded_constants/config.json +7 -2
  68. package/rules/common/C024_no_scatter_hardcoded_constants/dart/analyzer.js +40 -0
  69. package/rules/common/C024_no_scatter_hardcoded_constants/index.js +83 -0
  70. package/rules/common/C024_no_scatter_hardcoded_constants/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +19 -1
  71. package/rules/common/C029_catch_block_logging/config.json +15 -5
  72. package/rules/common/C029_catch_block_logging/dart/analyzer.js +40 -0
  73. package/rules/common/C029_catch_block_logging/index.js +83 -0
  74. package/rules/common/C030_use_custom_error_classes/config.json +28 -0
  75. package/rules/common/C030_use_custom_error_classes/dart/analyzer.js +40 -0
  76. package/rules/common/C030_use_custom_error_classes/index.js +83 -0
  77. package/rules/common/C031_validation_separation/config.json +28 -0
  78. package/rules/common/C031_validation_separation/dart/analyzer.js +40 -0
  79. package/rules/common/C031_validation_separation/index.js +83 -0
  80. package/rules/common/C033_separate_service_repository/config.json +8 -3
  81. package/rules/common/C033_separate_service_repository/dart/analyzer.js +40 -0
  82. package/rules/common/C033_separate_service_repository/index.js +83 -0
  83. package/rules/common/C035_error_logging_context/config.json +34 -12
  84. package/rules/common/C035_error_logging_context/dart/analyzer.js +40 -0
  85. package/rules/common/C035_error_logging_context/index.js +83 -0
  86. package/rules/common/C040_centralized_validation/config.json +37 -8
  87. package/rules/common/C040_centralized_validation/dart/analyzer.js +40 -0
  88. package/rules/common/C040_centralized_validation/index.js +83 -0
  89. package/rules/common/C041_no_sensitive_hardcode/config.json +7 -2
  90. package/rules/common/C041_no_sensitive_hardcode/dart/analyzer.js +40 -0
  91. package/rules/common/C041_no_sensitive_hardcode/index.js +83 -0
  92. package/rules/common/C042_boolean_name_prefix/config.json +28 -0
  93. package/rules/common/C042_boolean_name_prefix/dart/analyzer.js +40 -0
  94. package/rules/common/C042_boolean_name_prefix/index.js +83 -0
  95. package/rules/common/C043_no_console_or_print/config.json +28 -0
  96. package/rules/common/C043_no_console_or_print/dart/analyzer.js +40 -0
  97. package/rules/common/C043_no_console_or_print/index.js +83 -0
  98. package/rules/common/C047_no_duplicate_retry_logic/config.json +28 -0
  99. package/rules/common/C047_no_duplicate_retry_logic/dart/analyzer.js +40 -0
  100. package/rules/common/C047_no_duplicate_retry_logic/index.js +83 -0
  101. package/rules/common/C048_no_bypass_architectural_layers/config.json +7 -2
  102. package/rules/common/C048_no_bypass_architectural_layers/dart/analyzer.js +40 -0
  103. package/rules/common/C048_no_bypass_architectural_layers/index.js +83 -0
  104. package/rules/common/C052_parsing_or_data_transformation/config.json +7 -2
  105. package/rules/common/C052_parsing_or_data_transformation/dart/analyzer.js +40 -0
  106. package/rules/common/C052_parsing_or_data_transformation/index.js +83 -0
  107. package/rules/common/C060_no_override_superclass/config.json +7 -2
  108. package/rules/common/C060_no_override_superclass/dart/analyzer.js +40 -0
  109. package/rules/common/C060_no_override_superclass/index.js +83 -0
  110. package/rules/common/C065_one_behavior_per_test/config.json +187 -28
  111. package/rules/common/C065_one_behavior_per_test/dart/analyzer.js +40 -0
  112. package/rules/common/C065_one_behavior_per_test/index.js +83 -0
  113. package/rules/common/C067_no_hardcoded_config/config.json +18 -4
  114. package/rules/common/C067_no_hardcoded_config/dart/analyzer.js +40 -0
  115. package/rules/common/C067_no_hardcoded_config/index.js +83 -0
  116. package/rules/common/C070_no_real_time_tests/config.json +41 -12
  117. package/rules/common/C070_no_real_time_tests/dart/analyzer.js +40 -0
  118. package/rules/common/C070_no_real_time_tests/index.js +83 -0
  119. package/rules/common/C072_single_test_behavior/config.json +28 -0
  120. package/rules/common/C072_single_test_behavior/dart/analyzer.js +40 -0
  121. package/rules/common/C072_single_test_behavior/index.js +83 -0
  122. package/rules/common/C073_validate_required_config_on_startup/config.json +93 -18
  123. package/rules/common/C073_validate_required_config_on_startup/dart/analyzer.js +40 -0
  124. package/rules/common/C073_validate_required_config_on_startup/index.js +83 -0
  125. package/rules/common/C073_validate_required_config_on_startup/{analyzer.js → typescript/analyzer.js} +0 -1
  126. package/rules/common/C075_explicit_return_types/config.json +28 -0
  127. package/rules/common/C075_explicit_return_types/dart/analyzer.js +40 -0
  128. package/rules/common/C075_explicit_return_types/index.js +83 -0
  129. package/rules/common/C076_explicit_function_types/config.json +18 -4
  130. package/rules/common/C076_explicit_function_types/dart/analyzer.js +40 -0
  131. package/rules/common/C076_explicit_function_types/index.js +83 -0
  132. package/rules/index.js +26 -6
  133. package/rules/security/S003_open_redirect_protection/config.json +11 -53
  134. package/rules/security/S003_open_redirect_protection/dart/analyzer.js +43 -0
  135. package/rules/security/S003_open_redirect_protection/index.js +94 -0
  136. package/rules/security/S003_open_redirect_protection/typescript/analyzer.js +105 -0
  137. package/rules/security/S003_open_redirect_protection/{symbol-based-analyzer.js → typescript/semantic-analyzer.js} +1 -1
  138. package/rules/security/S004_sensitive_data_logging/config.json +1 -1
  139. package/rules/security/S004_sensitive_data_logging/dart/analyzer.js +58 -0
  140. package/rules/security/S004_sensitive_data_logging/index.js +93 -0
  141. package/rules/security/S005_no_origin_auth/dart/analyzer.js +30 -0
  142. package/rules/security/S005_no_origin_auth/index.js +83 -0
  143. package/rules/security/S005_no_origin_auth/{analyzer.js → typescript/analyzer.js} +1 -0
  144. package/rules/security/S006_no_plaintext_recovery_codes/dart/analyzer.js +30 -0
  145. package/rules/security/S006_no_plaintext_recovery_codes/index.js +83 -0
  146. package/rules/security/S007_no_plaintext_otp/dart/analyzer.js +30 -0
  147. package/rules/security/S007_no_plaintext_otp/index.js +83 -0
  148. package/rules/security/S009_no_insecure_encryption/dart/analyzer.js +30 -0
  149. package/rules/security/S009_no_insecure_encryption/index.js +83 -0
  150. package/rules/security/S010_no_insecure_encryption/dart/analyzer.js +30 -0
  151. package/rules/security/S010_no_insecure_encryption/index.js +83 -0
  152. package/rules/security/S011_secure_guid_generation/dart/analyzer.js +30 -0
  153. package/rules/security/S011_secure_guid_generation/index.js +83 -0
  154. package/rules/security/S012_hardcoded_secrets/dart/analyzer.js +30 -0
  155. package/rules/security/S012_hardcoded_secrets/index.js +83 -0
  156. package/rules/security/S012_hardcoded_secrets/typescript/config.json +75 -0
  157. package/rules/security/S013_tls_enforcement/dart/analyzer.js +30 -0
  158. package/rules/security/S013_tls_enforcement/index.js +83 -0
  159. package/rules/security/S014_tls_version_enforcement/dart/analyzer.js +30 -0
  160. package/rules/security/S014_tls_version_enforcement/index.js +83 -0
  161. package/rules/security/S015_insecure_tls_certificate/config.json +41 -0
  162. package/rules/security/S015_insecure_tls_certificate/dart/analyzer.js +19 -0
  163. package/rules/security/S015_insecure_tls_certificate/index.js +83 -0
  164. package/rules/security/S016_no_sensitive_querystring/dart/analyzer.js +30 -0
  165. package/rules/security/S016_no_sensitive_querystring/index.js +83 -0
  166. package/rules/security/S017_use_parameterized_queries/dart/analyzer.js +30 -0
  167. package/rules/security/S017_use_parameterized_queries/index.js +83 -0
  168. package/rules/security/S019_smtp_injection_protection/dart/analyzer.js +30 -0
  169. package/rules/security/S019_smtp_injection_protection/index.js +83 -0
  170. package/rules/security/S020_no_eval_dynamic_code/dart/analyzer.js +30 -0
  171. package/rules/security/S020_no_eval_dynamic_code/index.js +83 -0
  172. package/rules/security/S022_escape_output_context/dart/analyzer.js +30 -0
  173. package/rules/security/S022_escape_output_context/index.js +83 -0
  174. package/rules/security/S023_no_json_injection/dart/analyzer.js +30 -0
  175. package/rules/security/S023_no_json_injection/index.js +83 -0
  176. package/rules/security/S024_xpath_xxe_protection/dart/analyzer.js +30 -0
  177. package/rules/security/S024_xpath_xxe_protection/index.js +83 -0
  178. package/rules/security/S025_server_side_validation/dart/analyzer.js +30 -0
  179. package/rules/security/S025_server_side_validation/index.js +83 -0
  180. package/rules/security/S026_json_schema_validation/dart/analyzer.js +30 -0
  181. package/rules/security/S026_json_schema_validation/index.js +83 -0
  182. package/rules/security/S027_no_hardcoded_secrets/dart/analyzer.js +30 -0
  183. package/rules/security/S027_no_hardcoded_secrets/index.js +83 -0
  184. package/rules/security/S028_file_upload_size_limits/dart/analyzer.js +30 -0
  185. package/rules/security/S028_file_upload_size_limits/index.js +83 -0
  186. package/rules/security/S029_csrf_protection/dart/analyzer.js +30 -0
  187. package/rules/security/S029_csrf_protection/index.js +83 -0
  188. package/rules/security/S030_directory_browsing_protection/dart/analyzer.js +30 -0
  189. package/rules/security/S030_directory_browsing_protection/index.js +83 -0
  190. package/rules/security/S031_secure_session_cookies/dart/analyzer.js +30 -0
  191. package/rules/security/S031_secure_session_cookies/index.js +83 -0
  192. package/rules/security/S032_httponly_session_cookies/dart/analyzer.js +30 -0
  193. package/rules/security/S032_httponly_session_cookies/index.js +83 -0
  194. package/rules/security/S033_samesite_session_cookies/dart/analyzer.js +30 -0
  195. package/rules/security/S033_samesite_session_cookies/index.js +83 -0
  196. package/rules/security/S034_host_prefix_session_cookies/dart/analyzer.js +30 -0
  197. package/rules/security/S034_host_prefix_session_cookies/index.js +83 -0
  198. package/rules/security/S035_path_session_cookies/dart/analyzer.js +30 -0
  199. package/rules/security/S035_path_session_cookies/index.js +83 -0
  200. package/rules/security/S036_lfi_rfi_protection/dart/analyzer.js +30 -0
  201. package/rules/security/S036_lfi_rfi_protection/index.js +83 -0
  202. package/rules/security/S037_cache_headers/dart/analyzer.js +30 -0
  203. package/rules/security/S037_cache_headers/index.js +83 -0
  204. package/rules/security/S038_no_version_headers/dart/analyzer.js +30 -0
  205. package/rules/security/S038_no_version_headers/index.js +83 -0
  206. package/rules/security/S039_no_session_tokens_in_url/dart/analyzer.js +30 -0
  207. package/rules/security/S039_no_session_tokens_in_url/index.js +83 -0
  208. package/rules/security/S040_session_fixation_protection/dart/analyzer.js +30 -0
  209. package/rules/security/S040_session_fixation_protection/index.js +83 -0
  210. package/rules/security/S041_session_token_invalidation/dart/analyzer.js +30 -0
  211. package/rules/security/S041_session_token_invalidation/index.js +83 -0
  212. package/rules/security/S042_require_re_authentication_for_long_lived/dart/analyzer.js +30 -0
  213. package/rules/security/S042_require_re_authentication_for_long_lived/index.js +83 -0
  214. package/rules/security/S043_password_changes_invalidate_all_sessions/dart/analyzer.js +30 -0
  215. package/rules/security/S043_password_changes_invalidate_all_sessions/index.js +83 -0
  216. package/rules/security/S044_re_authentication_required/dart/analyzer.js +30 -0
  217. package/rules/security/S044_re_authentication_required/index.js +83 -0
  218. package/rules/security/S045_brute_force_protection/dart/analyzer.js +30 -0
  219. package/rules/security/S045_brute_force_protection/index.js +83 -0
  220. package/rules/security/S048_no_current_password_in_reset/dart/analyzer.js +30 -0
  221. package/rules/security/S048_no_current_password_in_reset/index.js +83 -0
  222. package/rules/security/S049_short_validity_tokens/dart/analyzer.js +30 -0
  223. package/rules/security/S049_short_validity_tokens/index.js +83 -0
  224. package/rules/security/S049_short_validity_tokens/typescript/config.json +124 -0
  225. package/rules/security/S051_password_length_policy/dart/analyzer.js +30 -0
  226. package/rules/security/S051_password_length_policy/index.js +83 -0
  227. package/rules/security/S051_password_length_policy/typescript/config.json +83 -0
  228. package/rules/security/S052_weak_otp_entropy/dart/analyzer.js +30 -0
  229. package/rules/security/S052_weak_otp_entropy/index.js +83 -0
  230. package/rules/security/S052_weak_otp_entropy/typescript/config.json +57 -0
  231. package/rules/security/S054_no_default_accounts/dart/analyzer.js +30 -0
  232. package/rules/security/S054_no_default_accounts/index.js +83 -0
  233. package/rules/security/S054_no_default_accounts/typescript/config.json +101 -0
  234. package/rules/security/S055_content_type_validation/dart/analyzer.js +30 -0
  235. package/rules/security/S055_content_type_validation/index.js +83 -0
  236. package/rules/security/S056_log_injection_protection/dart/analyzer.js +30 -0
  237. package/rules/security/S056_log_injection_protection/index.js +83 -0
  238. package/rules/security/S057_utc_logging/dart/analyzer.js +30 -0
  239. package/rules/security/S057_utc_logging/index.js +83 -0
  240. package/rules/security/S057_utc_logging/typescript/config.json +105 -0
  241. package/rules/security/S058_no_ssrf/dart/analyzer.js +30 -0
  242. package/rules/security/S058_no_ssrf/index.js +83 -0
  243. package/rules/security/S058_no_ssrf/{analyzer.js → typescript/analyzer.js} +0 -1
  244. package/rules/security/S058_no_ssrf/typescript/config.json +125 -0
  245. package/scripts/build-release.sh +12 -0
  246. package/scripts/copy-arch-detect.js +78 -0
  247. package/rules/common/C002_no_duplicate_code/test-cases/api-handlers.ts +0 -64
  248. package/rules/common/C002_no_duplicate_code/test-cases/data-processor.ts +0 -46
  249. package/rules/common/C002_no_duplicate_code/test-cases/good-example.tsx +0 -40
  250. package/rules/common/C002_no_duplicate_code/test-cases/product-service.ts +0 -57
  251. package/rules/common/C002_no_duplicate_code/test-cases/user-service.ts +0 -49
  252. package/rules/common/C067_no_hardcoded_config/symbol-based-analyzer.js.backup +0 -3853
  253. package/rules/security/S003_open_redirect_protection/analyzer.js +0 -135
  254. /package/rules/common/C002_no_duplicate_code/{analyzer.js → typescript/analyzer.js} +0 -0
  255. /package/rules/common/C003_no_vague_abbreviations/{analyzer.js → typescript/analyzer.js} +0 -0
  256. /package/rules/common/C006_function_naming/{analyzer.js → typescript/analyzer.js} +0 -0
  257. /package/rules/common/{C008 → C008_variable_declaration_locality}/config.json +0 -0
  258. /package/rules/common/{C008 → C008_variable_declaration_locality/typescript}/analyzer.js +0 -0
  259. /package/rules/common/{C008 → C008_variable_declaration_locality/typescript}/ts-morph-analyzer.js +0 -0
  260. /package/rules/common/C010_limit_block_nesting/{analyzer.js → typescript/analyzer.js} +0 -0
  261. /package/rules/common/C010_limit_block_nesting/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  262. /package/rules/common/C010_limit_block_nesting/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  263. /package/rules/common/C012_command_query_separation/{analyzer.js → typescript/analyzer.js} +0 -0
  264. /package/rules/common/C012_command_query_separation/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
  265. /package/rules/common/C013_no_dead_code/{analyzer.js → typescript/analyzer.js} +0 -0
  266. /package/rules/common/C013_no_dead_code/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  267. /package/rules/common/C013_no_dead_code/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  268. /package/rules/common/C014_dependency_injection/{analyzer.js → typescript/analyzer.js} +0 -0
  269. /package/rules/common/C014_dependency_injection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  270. /package/rules/common/C017_constructor_logic/{analyzer.js → typescript/analyzer.js} +0 -0
  271. /package/rules/common/C017_constructor_logic/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  272. /package/rules/common/C018_no_throw_generic_error/{analyzer.js → typescript/analyzer.js} +0 -0
  273. /package/rules/common/C018_no_throw_generic_error/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  274. /package/rules/common/C018_no_throw_generic_error/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  275. /package/rules/common/C019_log_level_usage/{analyzer.js → typescript/analyzer.js} +0 -0
  276. /package/rules/common/C019_log_level_usage/{pattern-analyzer.js → typescript/pattern-analyzer.js} +0 -0
  277. /package/rules/common/C019_log_level_usage/{system-log-analyzer.js → typescript/system-log-analyzer.js} +0 -0
  278. /package/rules/common/C020_unused_imports/{analyzer.js → typescript/analyzer.js} +0 -0
  279. /package/rules/common/C021_import_organization/{analyzer.js → typescript/analyzer.js} +0 -0
  280. /package/rules/common/C023_no_duplicate_variable/{analyzer.js → typescript/analyzer.js} +0 -0
  281. /package/rules/common/C023_no_duplicate_variable/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  282. /package/rules/common/C024_no_scatter_hardcoded_constants/{analyzer.js → typescript/analyzer.js} +0 -0
  283. /package/rules/common/C029_catch_block_logging/{analyzer.js → typescript/analyzer.js} +0 -0
  284. /package/rules/common/C030_use_custom_error_classes/{analyzer.js → typescript/analyzer.js} +0 -0
  285. /package/rules/common/C031_validation_separation/{analyzer.js → typescript/analyzer.js} +0 -0
  286. /package/rules/common/C033_separate_service_repository/{README.md → typescript/README.md} +0 -0
  287. /package/rules/common/C033_separate_service_repository/{analyzer.js → typescript/analyzer.js} +0 -0
  288. /package/rules/common/C033_separate_service_repository/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  289. /package/rules/common/C033_separate_service_repository/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  290. /package/rules/common/C035_error_logging_context/{STRATEGY.md → typescript/STRATEGY.md} +0 -0
  291. /package/rules/common/C035_error_logging_context/{analyzer.js → typescript/analyzer.js} +0 -0
  292. /package/rules/common/C035_error_logging_context/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  293. /package/rules/common/C035_error_logging_context/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  294. /package/rules/common/C040_centralized_validation/{analyzer.js → typescript/analyzer.js} +0 -0
  295. /package/rules/common/C040_centralized_validation/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  296. /package/rules/common/C040_centralized_validation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  297. /package/rules/common/C041_no_sensitive_hardcode/{analyzer.js → typescript/analyzer.js} +0 -0
  298. /package/rules/common/C041_no_sensitive_hardcode/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  299. /package/rules/common/C042_boolean_name_prefix/{analyzer.js → typescript/analyzer.js} +0 -0
  300. /package/rules/common/C043_no_console_or_print/{analyzer.js → typescript/analyzer.js} +0 -0
  301. /package/rules/common/C047_no_duplicate_retry_logic/{analyzer.js → typescript/analyzer.js} +0 -0
  302. /package/rules/common/C047_no_duplicate_retry_logic/{c047-semantic-rule.js → typescript/c047-semantic-rule.js} +0 -0
  303. /package/rules/common/C047_no_duplicate_retry_logic/{symbol-analyzer-enhanced.js → typescript/symbol-analyzer-enhanced.js} +0 -0
  304. /package/rules/common/C047_no_duplicate_retry_logic/{symbol-config.json → typescript/symbol-config.json} +0 -0
  305. /package/rules/common/C048_no_bypass_architectural_layers/{analyzer.js → typescript/analyzer.js} +0 -0
  306. /package/rules/common/C048_no_bypass_architectural_layers/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  307. /package/rules/common/C052_parsing_or_data_transformation/{analyzer.js → typescript/analyzer.js} +0 -0
  308. /package/rules/common/C052_parsing_or_data_transformation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  309. /package/rules/common/C060_no_override_superclass/{analyzer.js → typescript/analyzer.js} +0 -0
  310. /package/rules/common/C060_no_override_superclass/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  311. /package/rules/common/C065_one_behavior_per_test/{analyzer.js → typescript/analyzer.js} +0 -0
  312. /package/rules/common/C067_no_hardcoded_config/{analyzer.js → typescript/analyzer.js} +0 -0
  313. /package/rules/common/C067_no_hardcoded_config/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  314. /package/rules/common/C070_no_real_time_tests/{analyzer.js → typescript/analyzer.js} +0 -0
  315. /package/rules/common/C070_no_real_time_tests/{regex-analyzer.js → typescript/regex-analyzer.js} +0 -0
  316. /package/rules/common/C072_single_test_behavior/{analyzer.js → typescript/analyzer.js} +0 -0
  317. /package/rules/common/C073_validate_required_config_on_startup/{README.md → typescript/README.md} +0 -0
  318. /package/rules/common/C073_validate_required_config_on_startup/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  319. /package/rules/common/C075_explicit_return_types/{analyzer.js → typescript/analyzer.js} +0 -0
  320. /package/rules/common/C076_explicit_function_types/{README.md → typescript/README.md} +0 -0
  321. /package/rules/common/C076_explicit_function_types/{analyzer.js → typescript/analyzer.js} +0 -0
  322. /package/rules/common/C076_explicit_function_types/{semantic-analyzer.js → typescript/semantic-analyzer.js} +0 -0
  323. /package/rules/security/S003_open_redirect_protection/{README.md → typescript/README.md} +0 -0
  324. /package/rules/security/S004_sensitive_data_logging/{analyzer.js → typescript/analyzer.js} +0 -0
  325. /package/rules/security/S004_sensitive_data_logging/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  326. /package/rules/security/S005_no_origin_auth/{README.md → typescript/README.md} +0 -0
  327. /package/rules/security/S005_no_origin_auth/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
  328. /package/rules/security/S005_no_origin_auth/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  329. /package/rules/security/S006_no_plaintext_recovery_codes/{README.md → typescript/README.md} +0 -0
  330. /package/rules/security/S006_no_plaintext_recovery_codes/{analyzer.js → typescript/analyzer.js} +0 -0
  331. /package/rules/security/S006_no_plaintext_recovery_codes/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  332. /package/rules/security/S007_no_plaintext_otp/{README.md → typescript/README.md} +0 -0
  333. /package/rules/security/S007_no_plaintext_otp/{analyzer.js → typescript/analyzer.js} +0 -0
  334. /package/rules/security/S007_no_plaintext_otp/{semantic-analyzer.js → typescript/semantic-analyzer.js} +0 -0
  335. /package/rules/security/S007_no_plaintext_otp/{semantic-config.json → typescript/semantic-config.json} +0 -0
  336. /package/rules/security/S007_no_plaintext_otp/{semantic-wrapper.js → typescript/semantic-wrapper.js} +0 -0
  337. /package/rules/security/S009_no_insecure_encryption/{README.md → typescript/README.md} +0 -0
  338. /package/rules/security/S009_no_insecure_encryption/{analyzer.js → typescript/analyzer.js} +0 -0
  339. /package/rules/security/S010_no_insecure_encryption/{README.md → typescript/README.md} +0 -0
  340. /package/rules/security/S010_no_insecure_encryption/{analyzer.js → typescript/analyzer.js} +0 -0
  341. /package/rules/security/S011_secure_guid_generation/{README.md → typescript/README.md} +0 -0
  342. /package/rules/security/S011_secure_guid_generation/{analyzer.js → typescript/analyzer.js} +0 -0
  343. /package/rules/security/S011_secure_guid_generation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  344. /package/rules/security/S012_hardcoded_secrets/{analyzer.js → typescript/analyzer.js} +0 -0
  345. /package/rules/security/S012_hardcoded_secrets/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  346. /package/rules/security/S013_tls_enforcement/{README.md → typescript/README.md} +0 -0
  347. /package/rules/security/S013_tls_enforcement/{analyzer.js → typescript/analyzer.js} +0 -0
  348. /package/rules/security/S013_tls_enforcement/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  349. /package/rules/security/S014_tls_version_enforcement/{README.md → typescript/README.md} +0 -0
  350. /package/rules/security/S014_tls_version_enforcement/{analyzer.js → typescript/analyzer.js} +0 -0
  351. /package/rules/security/S014_tls_version_enforcement/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  352. /package/rules/security/S015_insecure_tls_certificate/{analyzer.js → typescript/analyzer.js} +0 -0
  353. /package/rules/security/S015_insecure_tls_certificate/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
  354. /package/rules/security/S016_no_sensitive_querystring/{analyzer.js → typescript/analyzer.js} +0 -0
  355. /package/rules/security/S016_no_sensitive_querystring/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  356. /package/rules/security/S016_no_sensitive_querystring/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  357. /package/rules/security/S017_use_parameterized_queries/{README.md → typescript/README.md} +0 -0
  358. /package/rules/security/S017_use_parameterized_queries/{analyzer.js → typescript/analyzer.js} +0 -0
  359. /package/rules/security/S017_use_parameterized_queries/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  360. /package/rules/security/S019_smtp_injection_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  361. /package/rules/security/S019_smtp_injection_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  362. /package/rules/security/S020_no_eval_dynamic_code/{README.md → typescript/README.md} +0 -0
  363. /package/rules/security/S020_no_eval_dynamic_code/{analyzer.js → typescript/analyzer.js} +0 -0
  364. /package/rules/security/S020_no_eval_dynamic_code/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  365. /package/rules/security/S022_escape_output_context/{README.md → typescript/README.md} +0 -0
  366. /package/rules/security/S022_escape_output_context/{analyzer.js → typescript/analyzer.js} +0 -0
  367. /package/rules/security/S023_no_json_injection/{analyzer.js → typescript/analyzer.js} +0 -0
  368. /package/rules/security/S023_no_json_injection/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
  369. /package/rules/security/S024_xpath_xxe_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  370. /package/rules/security/S024_xpath_xxe_protection/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  371. /package/rules/security/S024_xpath_xxe_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  372. /package/rules/security/S025_server_side_validation/{README.md → typescript/README.md} +0 -0
  373. /package/rules/security/S025_server_side_validation/{analyzer.js → typescript/analyzer.js} +0 -0
  374. /package/rules/security/S025_server_side_validation/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  375. /package/rules/security/S025_server_side_validation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  376. /package/rules/security/S026_json_schema_validation/{analyzer.js → typescript/analyzer.js} +0 -0
  377. /package/rules/security/S027_no_hardcoded_secrets/{analyzer.js → typescript/analyzer.js} +0 -0
  378. /package/rules/security/S027_no_hardcoded_secrets/{categories.json → typescript/categories.json} +0 -0
  379. /package/rules/security/S027_no_hardcoded_secrets/{categorized-analyzer.js → typescript/categorized-analyzer.js} +0 -0
  380. /package/rules/security/S028_file_upload_size_limits/{README.md → typescript/README.md} +0 -0
  381. /package/rules/security/S028_file_upload_size_limits/{analyzer.js → typescript/analyzer.js} +0 -0
  382. /package/rules/security/S028_file_upload_size_limits/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  383. /package/rules/security/S029_csrf_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  384. /package/rules/security/S030_directory_browsing_protection/{README.md → typescript/README.md} +0 -0
  385. /package/rules/security/S030_directory_browsing_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  386. /package/rules/security/S030_directory_browsing_protection/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  387. /package/rules/security/S030_directory_browsing_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  388. /package/rules/security/S031_secure_session_cookies/{README.md → typescript/README.md} +0 -0
  389. /package/rules/security/S031_secure_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
  390. /package/rules/security/S031_secure_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  391. /package/rules/security/S032_httponly_session_cookies/{FRAMEWORK_SUPPORT.md → typescript/FRAMEWORK_SUPPORT.md} +0 -0
  392. /package/rules/security/S032_httponly_session_cookies/{README.md → typescript/README.md} +0 -0
  393. /package/rules/security/S032_httponly_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
  394. /package/rules/security/S032_httponly_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  395. /package/rules/security/S032_httponly_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  396. /package/rules/security/S033_samesite_session_cookies/{README.md → typescript/README.md} +0 -0
  397. /package/rules/security/S033_samesite_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
  398. /package/rules/security/S033_samesite_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  399. /package/rules/security/S033_samesite_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  400. /package/rules/security/S034_host_prefix_session_cookies/{README.md → typescript/README.md} +0 -0
  401. /package/rules/security/S034_host_prefix_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
  402. /package/rules/security/S034_host_prefix_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  403. /package/rules/security/S034_host_prefix_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  404. /package/rules/security/S035_path_session_cookies/{README.md → typescript/README.md} +0 -0
  405. /package/rules/security/S035_path_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
  406. /package/rules/security/S035_path_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  407. /package/rules/security/S035_path_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  408. /package/rules/security/S036_lfi_rfi_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  409. /package/rules/security/S037_cache_headers/{README.md → typescript/README.md} +0 -0
  410. /package/rules/security/S037_cache_headers/{analyzer.js → typescript/analyzer.js} +0 -0
  411. /package/rules/security/S037_cache_headers/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  412. /package/rules/security/S037_cache_headers/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  413. /package/rules/security/S038_no_version_headers/{README.md → typescript/README.md} +0 -0
  414. /package/rules/security/S038_no_version_headers/{analyzer.js → typescript/analyzer.js} +0 -0
  415. /package/rules/security/S038_no_version_headers/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  416. /package/rules/security/S038_no_version_headers/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  417. /package/rules/security/S039_no_session_tokens_in_url/{README.md → typescript/README.md} +0 -0
  418. /package/rules/security/S039_no_session_tokens_in_url/{analyzer.js → typescript/analyzer.js} +0 -0
  419. /package/rules/security/S039_no_session_tokens_in_url/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  420. /package/rules/security/S039_no_session_tokens_in_url/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  421. /package/rules/security/S040_session_fixation_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  422. /package/rules/security/S041_session_token_invalidation/{README.md → typescript/README.md} +0 -0
  423. /package/rules/security/S041_session_token_invalidation/{analyzer.js → typescript/analyzer.js} +0 -0
  424. /package/rules/security/S041_session_token_invalidation/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  425. /package/rules/security/S041_session_token_invalidation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  426. /package/rules/security/S042_require_re_authentication_for_long_lived/{README.md → typescript/README.md} +0 -0
  427. /package/rules/security/S042_require_re_authentication_for_long_lived/{analyzer.js → typescript/analyzer.js} +0 -0
  428. /package/rules/security/S042_require_re_authentication_for_long_lived/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  429. /package/rules/security/S043_password_changes_invalidate_all_sessions/{README.md → typescript/README.md} +0 -0
  430. /package/rules/security/S043_password_changes_invalidate_all_sessions/{analyzer.js → typescript/analyzer.js} +0 -0
  431. /package/rules/security/S043_password_changes_invalidate_all_sessions/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  432. /package/rules/security/S044_re_authentication_required/{README.md → typescript/README.md} +0 -0
  433. /package/rules/security/S044_re_authentication_required/{analyzer.js → typescript/analyzer.js} +0 -0
  434. /package/rules/security/S044_re_authentication_required/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  435. /package/rules/security/S044_re_authentication_required/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  436. /package/rules/security/S045_brute_force_protection/{README.md → typescript/README.md} +0 -0
  437. /package/rules/security/S045_brute_force_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  438. /package/rules/security/S045_brute_force_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  439. /package/rules/security/S048_no_current_password_in_reset/{README.md → typescript/README.md} +0 -0
  440. /package/rules/security/S048_no_current_password_in_reset/{analyzer.js → typescript/analyzer.js} +0 -0
  441. /package/rules/security/S049_short_validity_tokens/{analyzer.js → typescript/analyzer.js} +0 -0
  442. /package/rules/security/S049_short_validity_tokens/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  443. /package/rules/security/S049_short_validity_tokens/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  444. /package/rules/security/S051_password_length_policy/{analyzer.js → typescript/analyzer.js} +0 -0
  445. /package/rules/security/S052_weak_otp_entropy/{analyzer.js → typescript/analyzer.js} +0 -0
  446. /package/rules/security/S054_no_default_accounts/{README.md → typescript/README.md} +0 -0
  447. /package/rules/security/S054_no_default_accounts/{analyzer.js → typescript/analyzer.js} +0 -0
  448. /package/rules/security/S055_content_type_validation/{README.md → typescript/README.md} +0 -0
  449. /package/rules/security/S055_content_type_validation/{analyzer.js → typescript/analyzer.js} +0 -0
  450. /package/rules/security/S055_content_type_validation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  451. /package/rules/security/S056_log_injection_protection/{analyzer.js → typescript/analyzer.js} +0 -0
  452. /package/rules/security/S056_log_injection_protection/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
  453. /package/rules/security/S056_log_injection_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
  454. /package/rules/security/S057_utc_logging/{README.md → typescript/README.md} +0 -0
  455. /package/rules/security/S057_utc_logging/{analyzer.js → typescript/analyzer.js} +0 -0
  456. /package/rules/security/S058_no_ssrf/{README.md → typescript/README.md} +0 -0
@@ -0,0 +1,745 @@
1
+ # Dart Rule Execution Flow
2
+
3
+ > Tài liệu mô tả chi tiết luồng hoạt động của một rule khi phân tích code Dart trong SunLint.
4
+ > Lấy ví dụ: **Rule C002 - No Duplicate Code**
5
+
6
+ ## 1. Tổng quan Architecture
7
+
8
+ ```
9
+ ┌─────────────────────────────────────────────────────────────────────────────┐
10
+ │ SUNLINT ARCHITECTURE │
11
+ ├─────────────────────────────────────────────────────────────────────────────┤
12
+ │ │
13
+ │ ┌─────────────┐ ┌──────────────────┐ ┌─────────────────────────────┐ │
14
+ │ │ CLI │───▶│ Heuristic │───▶│ DartAnalyzer (JS) │ │
15
+ │ │ (cli.js) │ │ Engine │ │ (dart-analyzer.js) │ │
16
+ │ └─────────────┘ └──────────────────┘ └──────────────┬──────────────┘ │
17
+ │ │ │
18
+ │ JSON-RPC over STDIO │
19
+ │ │ │
20
+ │ ┌──────────────────────────────────────▼──────────────┐ │
21
+ │ │ DART BINARY (sunlint-dart-macos) │ │
22
+ │ │ ┌─────────────────┐ ┌──────────────────────────┐ │ │
23
+ │ │ │ JsonRpcServer │ │ AnalyzerService │ │ │
24
+ │ │ └────────┬────────┘ └────────────┬─────────────┘ │ │
25
+ │ │ │ │ │ │
26
+ │ │ ▼ ▼ │ │
27
+ │ │ ┌─────────────────────────────────────────────┐ │ │
28
+ │ │ │ lib/rules/C002_no_duplicate_code.dart │ │ │
29
+ │ │ └─────────────────────────────────────────────┘ │ │
30
+ │ └─────────────────────────────────────────────────────┘ │
31
+ │ │
32
+ └─────────────────────────────────────────────────────────────────────────────┘
33
+ ```
34
+
35
+ ---
36
+
37
+ ## 2. Chi tiết từng bước
38
+
39
+ ### Step 1: CLI Command
40
+
41
+ ```bash
42
+ node cli.js --rule=C002 \
43
+ --input="examples/rule-test-fixtures/dart-rules/C002_no_duplicate_code/violations" \
44
+ --engine=heuristic \
45
+ --languages=dart \
46
+ --include="**/*.dart"
47
+ ```
48
+
49
+ **File:** `cli.js`
50
+
51
+ **Chức năng:**
52
+ - Parse command line arguments
53
+ - Load configuration
54
+ - Initialize engines
55
+ - Dispatch to appropriate engine
56
+
57
+ ---
58
+
59
+ ### Step 2: Heuristic Engine
60
+
61
+ **File:** `engines/heuristic-engine.js`
62
+
63
+ #### 2.1. Detect Dart Support
64
+
65
+ ```javascript
66
+ // Line 27-51
67
+ function detectDartSupport(ruleId) {
68
+ const rulesBasePath = path.join(__dirname, '../rules');
69
+ const categories = ['common', 'security', 'typescript'];
70
+
71
+ for (const category of categories) {
72
+ const categoryPath = path.join(rulesBasePath, category);
73
+ // Scan for: rules/common/C002_no_duplicate_code/dart/
74
+ for (const folder of ruleFolders) {
75
+ if (folder.startsWith(ruleId + '_')) {
76
+ const dartPath = path.join(categoryPath, folder, 'dart');
77
+ if (fs.existsSync(dartPath)) {
78
+ return true; // ✅ C002 supports Dart
79
+ }
80
+ }
81
+ }
82
+ }
83
+ return false;
84
+ }
85
+ ```
86
+
87
+ #### 2.2. Check DartAnalyzer Availability
88
+
89
+ ```javascript
90
+ // Line 922-927
91
+ const isDartRule = detectDartSupport(rule.id); // true for C002
92
+ const hasDartFiles = filesByLanguage['dart'].length > 0;
93
+ const dartAnalyzer = this.semanticEngineManager?.getAnalyzer('dart');
94
+ const useDartAnalyzer = isDartRule && hasDartFiles && dartAnalyzer?.isReady();
95
+ ```
96
+
97
+ #### 2.3. Call DartAnalyzer
98
+
99
+ ```javascript
100
+ // Line 948-972
101
+ if (useDartAnalyzer) {
102
+ const dartFiles = filesByLanguage['dart'];
103
+ const rules = [{ id: rule.id, config: rule.config || {} }];
104
+
105
+ for (const filePath of dartFiles) {
106
+ const violations = await dartAnalyzer.analyzeFile(filePath, rules, options);
107
+ ruleViolations.push(...violations);
108
+ }
109
+ }
110
+ ```
111
+
112
+ ---
113
+
114
+ ### Step 3: Dart Analyzer Client (JavaScript)
115
+
116
+ **File:** `core/adapters/dart-analyzer.js`
117
+
118
+ #### 3.1. Resolve Binary
119
+
120
+ ```javascript
121
+ // Line 288-337
122
+ async resolveBinary() {
123
+ const platform = process.platform;
124
+ const binaryName = platform === 'darwin'
125
+ ? 'sunlint-dart-macos'
126
+ : `sunlint-dart-${platform}`;
127
+
128
+ // Priority 1: Bundled binary
129
+ const bundledPath = path.join(__dirname, '../../dart_analyzer/bin', binaryName);
130
+ if (fs.existsSync(bundledPath)) {
131
+ return bundledPath;
132
+ }
133
+ // ... fallback options
134
+ }
135
+ ```
136
+
137
+ #### 3.2. Start Subprocess
138
+
139
+ ```javascript
140
+ // Line 35-81
141
+ async start(binaryPath) {
142
+ this.process = spawn(binaryPath, [], {
143
+ stdio: ['pipe', 'pipe', 'pipe'],
144
+ env: { ...process.env }
145
+ });
146
+
147
+ // Handle stdout (JSON-RPC responses)
148
+ this.process.stdout.on('data', (data) => {
149
+ this.handleData(data.toString());
150
+ });
151
+ }
152
+ ```
153
+
154
+ #### 3.3. Send JSON-RPC Request
155
+
156
+ ```javascript
157
+ // Line 368-405
158
+ async analyzeFile(filePath, rules, options = {}) {
159
+ if (this.client && this.client.isConnected()) {
160
+ // Send JSON-RPC request
161
+ const result = await this.client.sendRequest('analyze', {
162
+ filePath,
163
+ rules: rules.map(r => ({
164
+ id: r.id || r.ruleId,
165
+ config: r.config || {}
166
+ }))
167
+ });
168
+ violations = result.violations || [];
169
+ }
170
+ }
171
+ ```
172
+
173
+ **JSON-RPC Request Format:**
174
+ ```json
175
+ {
176
+ "jsonrpc": "2.0",
177
+ "id": 1,
178
+ "method": "analyze",
179
+ "params": {
180
+ "filePath": "/path/to/file.dart",
181
+ "rules": [{ "id": "C002", "config": {} }]
182
+ }
183
+ }
184
+ ```
185
+
186
+ ---
187
+
188
+ ### Step 4: Dart Binary - JSON-RPC Server
189
+
190
+ **File:** `dart_analyzer/lib/json_rpc_server.dart`
191
+
192
+ #### 4.1. Receive Request
193
+
194
+ ```dart
195
+ // Line 48-64
196
+ Future<void> _handleLine(String line) async {
197
+ final request = jsonDecode(line) as Map<String, dynamic>;
198
+ final response = await _processRequest(request);
199
+ _sendResponse(response);
200
+ }
201
+ ```
202
+
203
+ #### 4.2. Route to Handler
204
+
205
+ ```dart
206
+ // Line 106-122
207
+ Future<dynamic> _invokeMethod(String method, Map<String, dynamic> params) async {
208
+ switch (method) {
209
+ case 'initialize':
210
+ return await _handleInitialize(params);
211
+ case 'analyze':
212
+ return await _handleAnalyze(params); // ← C002 goes here
213
+ case 'getSymbolTable':
214
+ return await _handleGetSymbolTable(params);
215
+ // ...
216
+ }
217
+ }
218
+ ```
219
+
220
+ #### 4.3. Handle Analyze Request
221
+
222
+ ```dart
223
+ // Line 156-174
224
+ Future<Map<String, dynamic>> _handleAnalyze(Map<String, dynamic> params) async {
225
+ final filePath = params['filePath'] as String?;
226
+ final rulesData = params['rules'] as List<dynamic>?;
227
+
228
+ final violations = await _analyzerService.analyzeFile(
229
+ filePath: filePath!,
230
+ rulesData: rulesData,
231
+ );
232
+
233
+ return {
234
+ 'violations': violations.map((v) => v.toJson()).toList(),
235
+ 'fileAnalyzed': filePath,
236
+ };
237
+ }
238
+ ```
239
+
240
+ ---
241
+
242
+ ### Step 5: Analyzer Service
243
+
244
+ **File:** `dart_analyzer/lib/analyzer_service.dart`
245
+
246
+ #### 5.1. Register Analyzers
247
+
248
+ ```dart
249
+ // Line 36-46
250
+ void _registerAnalyzers() {
251
+ // Common rules (C-series)
252
+ _analyzers['C002'] = C002NoDuplicateCodeAnalyzer();
253
+ _analyzers['C003'] = C003NoVagueAbbreviationsAnalyzer();
254
+
255
+ // Security rules (S-series)
256
+ _analyzers['S003'] = S003OpenRedirectProtectionAnalyzer();
257
+ _analyzers['S004'] = S004SensitiveDataLoggingAnalyzer();
258
+ }
259
+ ```
260
+
261
+ #### 5.2. Analyze File
262
+
263
+ ```dart
264
+ // Line 204-257
265
+ Future<List<Violation>> analyzeFile({
266
+ required String filePath,
267
+ List<dynamic>? rulesData,
268
+ }) async {
269
+ // Get resolved AST from Dart Analyzer package
270
+ final context = _contextCollection!.contextFor(absolutePath);
271
+ final result = await context.currentSession.getResolvedUnit(absolutePath);
272
+
273
+ final unit = result.unit;
274
+ final violations = <Violation>[];
275
+
276
+ // Run each applicable analyzer
277
+ for (final rule in rules) {
278
+ final analyzer = _analyzers[rule.id]; // Get C002 analyzer
279
+ if (analyzer == null) continue;
280
+
281
+ final ruleViolations = analyzer.analyze(
282
+ unit: unit,
283
+ filePath: absolutePath,
284
+ rule: rule,
285
+ lineInfo: result.lineInfo,
286
+ );
287
+ violations.addAll(ruleViolations);
288
+ }
289
+
290
+ return violations;
291
+ }
292
+ ```
293
+
294
+ ---
295
+
296
+ ### Step 6: C002 Rule Analyzer
297
+
298
+ **File:** `dart_analyzer/lib/rules/C002_no_duplicate_code.dart`
299
+
300
+ #### 6.1. Analyzer Class
301
+
302
+ ```dart
303
+ class C002NoDuplicateCodeAnalyzer extends BaseAnalyzer {
304
+ @override
305
+ String get ruleId => 'C002';
306
+
307
+ static const int minDuplicateLines = 10;
308
+ static const double similarityThreshold = 0.85;
309
+
310
+ final Map<String, List<_CodeBlock>> _codeBlocks = {};
311
+ }
312
+ ```
313
+
314
+ #### 6.2. Analyze Method
315
+
316
+ ```dart
317
+ // Line 33-51
318
+ @override
319
+ List<Violation> analyze({
320
+ required CompilationUnit unit,
321
+ required String filePath,
322
+ required Rule rule,
323
+ required LineInfo lineInfo,
324
+ }) {
325
+ final violations = <Violation>[];
326
+
327
+ // Create AST visitor
328
+ final visitor = _DuplicateCodeVisitor(
329
+ filePath: filePath,
330
+ lineInfo: lineInfo,
331
+ violations: violations,
332
+ analyzer: this,
333
+ codeBlocks: _codeBlocks,
334
+ );
335
+
336
+ // Traverse AST
337
+ unit.accept(visitor);
338
+
339
+ // Detect duplicates
340
+ _detectDuplicates(violations);
341
+
342
+ return violations;
343
+ }
344
+ ```
345
+
346
+ #### 6.3. AST Visitor
347
+
348
+ ```dart
349
+ class _DuplicateCodeVisitor extends RecursiveAstVisitor<void> {
350
+ @override
351
+ void visitFunctionDeclaration(FunctionDeclaration node) {
352
+ final body = node.functionExpression.body;
353
+ if (body is BlockFunctionBody) {
354
+ _processBlock(body.block, 'function', node.name.lexeme);
355
+ }
356
+ super.visitFunctionDeclaration(node);
357
+ }
358
+
359
+ @override
360
+ void visitMethodDeclaration(MethodDeclaration node) {
361
+ final body = node.body;
362
+ if (body is BlockFunctionBody) {
363
+ _processBlock(body.block, 'method', node.name.lexeme);
364
+ }
365
+ super.visitMethodDeclaration(node);
366
+ }
367
+ }
368
+ ```
369
+
370
+ #### 6.4. Process Code Block
371
+
372
+ ```dart
373
+ void _processBlock(Block block, String type, String name) {
374
+ final startLine = analyzer.getLine(lineInfo, block.offset);
375
+ final endLine = analyzer.getLine(lineInfo, block.end);
376
+ final lineCount = endLine - startLine + 1;
377
+
378
+ // Skip if less than 10 lines
379
+ if (lineCount < C002NoDuplicateCodeAnalyzer.minDuplicateLines) return;
380
+
381
+ // Normalize code for comparison
382
+ final normalizedLines = _normalizeBlock(block);
383
+ final hash = _hashLines(normalizedLines);
384
+
385
+ // Store for comparison
386
+ codeBlocks.putIfAbsent(filePath, () => []).add(_CodeBlock(
387
+ filePath: filePath,
388
+ startLine: startLine,
389
+ endLine: endLine,
390
+ hash: hash,
391
+ normalizedLines: normalizedLines,
392
+ type: '$type:$name',
393
+ ));
394
+ }
395
+ ```
396
+
397
+ #### 6.5. Detect Duplicates
398
+
399
+ ```dart
400
+ void _detectDuplicates(List<Violation> violations) {
401
+ final allBlocks = _codeBlocks.values.expand((b) => b).toList();
402
+
403
+ for (var i = 0; i < allBlocks.length; i++) {
404
+ for (var j = i + 1; j < allBlocks.length; j++) {
405
+ final block1 = allBlocks[i];
406
+ final block2 = allBlocks[j];
407
+
408
+ // Check for exact match via hash
409
+ if (block1.hash == block2.hash) {
410
+ violations.add(createViolation(
411
+ filePath: block2.filePath,
412
+ line: block2.startLine,
413
+ column: 1,
414
+ message: 'Duplicate code block found (${block2.lineCount} lines)...',
415
+ severity: 'warning',
416
+ ));
417
+ }
418
+ // Check for similar code (LCS algorithm)
419
+ else {
420
+ final similarity = _calculateSimilarity(block1, block2);
421
+ if (similarity >= similarityThreshold) {
422
+ violations.add(createViolation(...));
423
+ }
424
+ }
425
+ }
426
+ }
427
+ }
428
+ ```
429
+
430
+ ---
431
+
432
+ ### Step 7: Response Flow
433
+
434
+ ```
435
+ C002 Analyzer
436
+ ↓ List<Violation>
437
+ AnalyzerService
438
+ ↓ violations.map((v) => v.toJson())
439
+ JsonRpcServer
440
+ ↓ JSON-RPC Response
441
+ DartAnalyzerClient (JS)
442
+ ↓ result.violations
443
+ HeuristicEngine
444
+ ↓ ruleViolations
445
+ CLI Output
446
+ ```
447
+
448
+ **JSON-RPC Response Format:**
449
+ ```json
450
+ {
451
+ "jsonrpc": "2.0",
452
+ "id": 1,
453
+ "result": {
454
+ "violations": [
455
+ {
456
+ "ruleId": "C002",
457
+ "filePath": "/path/to/file.dart",
458
+ "line": 31,
459
+ "column": 1,
460
+ "message": "Duplicate code block found (19 lines) - same as line 10",
461
+ "severity": "warning",
462
+ "analysisMethod": "ast",
463
+ "metadata": {
464
+ "duplicateOf": "/path/to/file.dart:10",
465
+ "lineCount": 19,
466
+ "similarity": 1.0
467
+ }
468
+ }
469
+ ],
470
+ "fileAnalyzed": "/path/to/file.dart"
471
+ }
472
+ }
473
+ ```
474
+
475
+ ---
476
+
477
+ ## 3. File Structure
478
+
479
+ ### Rule Definition (TypeScript side)
480
+
481
+ ```
482
+ rules/common/C002_no_duplicate_code/
483
+ ├── config.json # Rule configuration
484
+ ├── index.js # Router (multi-language)
485
+ ├── typescript/
486
+ │ └── analyzer.js # TypeScript analyzer
487
+ ├── dart/
488
+ │ └── analyzer.js # JS wrapper (delegates to binary)
489
+ └── test-cases/ # TypeScript test cases
490
+ ```
491
+
492
+ ### Rule Implementation (Dart side)
493
+
494
+ ```
495
+ dart_analyzer/
496
+ ├── bin/
497
+ │ ├── sunlint_dart_analyzer.dart # Entry point
498
+ │ └── sunlint-dart-macos # Compiled binary
499
+ ├── lib/
500
+ │ ├── analyzer_service.dart # Main service
501
+ │ ├── json_rpc_server.dart # JSON-RPC handler
502
+ │ ├── models/
503
+ │ │ ├── rule.dart
504
+ │ │ └── violation.dart
505
+ │ └── rules/
506
+ │ ├── base_analyzer.dart # Base class
507
+ │ ├── C002_no_duplicate_code.dart
508
+ │ ├── C003_no_vague_abbreviations.dart
509
+ │ ├── S003_open_redirect_protection.dart
510
+ │ └── S004_sensitive_data_logging.dart
511
+ └── pubspec.yaml
512
+ ```
513
+
514
+ ### Test Fixtures
515
+
516
+ ```
517
+ examples/rule-test-fixtures/dart-rules/
518
+ ├── C002_no_duplicate_code/
519
+ │ ├── clean/ # ✅ No violations expected
520
+ │ │ ├── data_validator.dart
521
+ │ │ └── payment_service.dart
522
+ │ └── violations/ # ❌ Violations expected
523
+ │ ├── data_processor.dart
524
+ │ └── user_service.dart
525
+ ├── C003_no_vague_abbreviations/
526
+ │ ├── clean/
527
+ │ └── violations/
528
+ ├── S003_open_redirect_protection/
529
+ │ ├── clean/
530
+ │ └── violations/
531
+ └── S004_sensitive_data_logging/
532
+ ├── clean/
533
+ └── violations/
534
+ ```
535
+
536
+ ---
537
+
538
+ ## 4. Commands
539
+
540
+ ### Run Single Rule on Violations
541
+
542
+ ```bash
543
+ # From sunlint directory
544
+ cd /path/to/sunlint
545
+
546
+ # Run C002 on violations folder
547
+ node cli.js --rule=C002 \
548
+ --input="examples/rule-test-fixtures/dart-rules/C002_no_duplicate_code/violations" \
549
+ --languages=dart \
550
+ --include="**/*.dart"
551
+ ```
552
+
553
+ ### Run Single Rule on Clean Code
554
+
555
+ ```bash
556
+ node cli.js --rule=C002 \
557
+ --input="examples/rule-test-fixtures/dart-rules/C002_no_duplicate_code/clean" \
558
+ --languages=dart \
559
+ --include="**/*.dart"
560
+ ```
561
+
562
+ ### Run All Dart Rules
563
+
564
+ ```bash
565
+ node cli.js --rule=C002,C003,S003,S004 \
566
+ --input="examples/rule-test-fixtures/dart-rules" \
567
+ --languages=dart \
568
+ --include="**/*.dart"
569
+ ```
570
+
571
+ ### Verbose Mode
572
+
573
+ ```bash
574
+ node cli.js --rule=C002 \
575
+ --input="examples/rule-test-fixtures/dart-rules/C002_no_duplicate_code/violations" \
576
+ --languages=dart \
577
+ --include="**/*.dart" \
578
+ --verbose
579
+ ```
580
+
581
+ ---
582
+
583
+ ## 5. Adding a New Dart Rule
584
+
585
+ ### Step 1: Create TypeScript Rule Structure
586
+
587
+ ```bash
588
+ mkdir -p rules/common/CXXX_rule_name/{typescript,dart}
589
+ ```
590
+
591
+ ### Step 2: Create config.json
592
+
593
+ ```json
594
+ {
595
+ "id": "CXXX",
596
+ "name": "Rule Name",
597
+ "description": "Rule description",
598
+ "category": "common",
599
+ "severity": "warning",
600
+ "languages": ["typescript", "javascript", "dart"]
601
+ }
602
+ ```
603
+
604
+ ### Step 3: Create index.js Router
605
+
606
+ ```javascript
607
+ // rules/common/CXXX_rule_name/index.js
608
+ const path = require('path');
609
+
610
+ class CXXXRouter {
611
+ getAnalyzer(language) {
612
+ const normalizedLang = this.normalizeLanguage(language);
613
+ const analyzerPath = path.join(__dirname, normalizedLang, 'analyzer.js');
614
+ return require(analyzerPath);
615
+ }
616
+ // ...
617
+ }
618
+
619
+ module.exports = new CXXXRouter();
620
+ ```
621
+
622
+ ### Step 4: Create Dart Analyzer
623
+
624
+ ```dart
625
+ // dart_analyzer/lib/rules/CXXX_rule_name.dart
626
+ class CXXXRuleAnalyzer extends BaseAnalyzer {
627
+ @override
628
+ String get ruleId => 'CXXX';
629
+
630
+ @override
631
+ List<Violation> analyze({
632
+ required CompilationUnit unit,
633
+ required String filePath,
634
+ required Rule rule,
635
+ required LineInfo lineInfo,
636
+ }) {
637
+ final violations = <Violation>[];
638
+ // Implementation
639
+ return violations;
640
+ }
641
+ }
642
+ ```
643
+
644
+ ### Step 5: Register in AnalyzerService
645
+
646
+ ```dart
647
+ // dart_analyzer/lib/analyzer_service.dart
648
+ void _registerAnalyzers() {
649
+ // ...
650
+ _analyzers['CXXX'] = CXXXRuleAnalyzer();
651
+ }
652
+ ```
653
+
654
+ ### Step 6: Create Test Fixtures
655
+
656
+ ```
657
+ examples/rule-test-fixtures/dart-rules/CXXX_rule_name/
658
+ ├── clean/
659
+ │ └── good_example.dart
660
+ └── violations/
661
+ └── bad_example.dart
662
+ ```
663
+
664
+ ### Step 7: Rebuild Dart Binary
665
+
666
+ ```bash
667
+ cd dart_analyzer
668
+ dart pub get
669
+ dart compile exe bin/sunlint_dart_analyzer.dart -o bin/sunlint-dart-macos
670
+ ```
671
+
672
+ ---
673
+
674
+ ## 6. Troubleshooting
675
+
676
+ ### No files found
677
+
678
+ ```bash
679
+ # Ensure --languages=dart and --include="**/*.dart" are set
680
+ node cli.js --rule=C002 --input=path --languages=dart --include="**/*.dart"
681
+ ```
682
+
683
+ ### DartAnalyzer not initialized
684
+
685
+ ```bash
686
+ # Check if binary exists
687
+ ls -la dart_analyzer/bin/sunlint-dart-macos
688
+
689
+ # Rebuild if needed
690
+ cd dart_analyzer && dart compile exe bin/sunlint_dart_analyzer.dart -o bin/sunlint-dart-macos
691
+ ```
692
+
693
+ ### Rule not supported
694
+
695
+ ```bash
696
+ # Check if dart/ folder exists in rule directory
697
+ ls -la rules/common/C002_no_duplicate_code/dart/
698
+
699
+ # Check if rule is registered in analyzer_service.dart
700
+ grep "C002" dart_analyzer/lib/analyzer_service.dart
701
+ ```
702
+
703
+ ---
704
+
705
+ ## 7. Summary Diagram
706
+
707
+ ```
708
+ ┌────────────────────────────────────────────────────────────────────────────┐
709
+ │ C002 EXECUTION FLOW │
710
+ ├────────────────────────────────────────────────────────────────────────────┤
711
+ │ │
712
+ │ 1. CLI Command │
713
+ │ └── node cli.js --rule=C002 --input=... --languages=dart │
714
+ │ │ │
715
+ │ 2. Heuristic Engine ▼ │
716
+ │ ├── detectDartSupport('C002') → true │
717
+ │ ├── Get DartAnalyzer from SemanticEngineManager │
718
+ │ └── Call dartAnalyzer.analyzeFile(filePath, rules) │
719
+ │ │ │
720
+ │ 3. DartAnalyzer (JS) ▼ │
721
+ │ ├── Connect to sunlint-dart-macos binary │
722
+ │ └── Send JSON-RPC: { method: 'analyze', params: {...} } │
723
+ │ │ │
724
+ │ 4. JSON-RPC Server ▼ (Dart Binary) │
725
+ │ ├── Receive request on stdin │
726
+ │ └── Route to _handleAnalyze() │
727
+ │ │ │
728
+ │ 5. AnalyzerService ▼ │
729
+ │ ├── _analyzers['C002'] → C002NoDuplicateCodeAnalyzer │
730
+ │ ├── Get ResolvedUnitResult from Dart Analyzer package │
731
+ │ └── Call analyzer.analyze(unit, filePath, rule, lineInfo) │
732
+ │ │ │
733
+ │ 6. C002 Analyzer ▼ │
734
+ │ ├── Create _DuplicateCodeVisitor │
735
+ │ ├── Traverse AST: unit.accept(visitor) │
736
+ │ ├── Collect code blocks ≥ 10 lines │
737
+ │ ├── Normalize & hash blocks │
738
+ │ ├── Compare for duplicates (exact match or similarity) │
739
+ │ └── Return List<Violation> │
740
+ │ │ │
741
+ │ 7. Response ▼ │
742
+ │ └── Violations → JSON → stdout → JS client → CLI output │
743
+ │ │
744
+ └────────────────────────────────────────────────────────────────────────────┘
745
+ ```