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