@ttsc/lint 0.14.0-dev.20260529.1 → 0.14.0
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/README.md +85 -87
- package/lib/defaultFormat.d.ts +10 -6
- package/lib/defaultFormat.js +10 -6
- package/lib/defaultFormat.js.map +1 -1
- package/lib/structures/ITtscLintConfig.d.ts +5 -5
- package/lib/structures/TtscLintRuleSetting.d.ts +19 -19
- package/lib/structures/{ITtscLintFormat.d.ts → format/ITtscLintFormat.d.ts} +45 -70
- package/lib/structures/format/ITtscLintFormat.js.map +1 -0
- package/lib/structures/format/ITtscLintFormatJsDoc.d.ts +15 -0
- package/lib/structures/format/ITtscLintFormatJsDoc.js +3 -0
- package/lib/structures/format/ITtscLintFormatJsDoc.js.map +1 -0
- package/lib/structures/format/ITtscLintFormatSortImports.d.ts +54 -0
- package/lib/structures/format/ITtscLintFormatSortImports.js +3 -0
- package/lib/structures/format/ITtscLintFormatSortImports.js.map +1 -0
- package/lib/structures/format/index.d.ts +3 -0
- package/lib/structures/format/index.js +20 -0
- package/lib/structures/format/index.js.map +1 -0
- package/lib/structures/index.d.ts +1 -1
- package/lib/structures/index.js +1 -1
- package/lib/structures/index.js.map +1 -1
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +18 -27
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +4 -5
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -1
- package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +29 -33
- package/lib/structures/rules/ITtscLintContributorRules.d.ts +6 -7
- package/lib/structures/rules/ITtscLintCoreRules.d.ts +380 -408
- package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +5 -5
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js +2 -2
- package/lib/structures/rules/ITtscLintCypressRules.d.ts +34 -38
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +21 -24
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +2 -2
- package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +51 -56
- package/lib/structures/rules/ITtscLintJestRules.d.ts +63 -74
- package/lib/structures/rules/ITtscLintJsdocRules.d.ts +47 -54
- package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +94 -102
- package/lib/structures/rules/ITtscLintNextjsRules.d.ts +50 -55
- package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +104 -122
- package/lib/structures/rules/ITtscLintPromiseRules.d.ts +62 -71
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +4 -4
- package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +17 -19
- package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +8 -10
- package/lib/structures/rules/ITtscLintReactRuleOptions.js +1 -2
- package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -1
- package/lib/structures/rules/ITtscLintReactRules.d.ts +91 -104
- package/lib/structures/rules/ITtscLintRegexpRules.d.ts +46 -54
- package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +7 -8
- package/lib/structures/rules/ITtscLintSecurityRules.d.ts +45 -52
- package/lib/structures/rules/ITtscLintSolidRules.d.ts +53 -56
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +3 -4
- package/lib/structures/rules/ITtscLintStorybookRules.d.ts +60 -69
- package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +31 -37
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +2 -3
- package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +102 -119
- package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +460 -518
- package/lib/structures/rules/ITtscLintVitestRules.d.ts +43 -51
- package/linthost/config.go +89 -72
- package/linthost/config_format.go +265 -99
- package/linthost/directives.go +5 -1
- package/linthost/display_width.go +72 -0
- package/linthost/fix.go +26 -1
- package/linthost/format.go +222 -25
- package/linthost/format_editor_settings.go +262 -0
- package/linthost/lsp.go +8 -4
- package/linthost/print_dispatch.go +3 -0
- package/linthost/print_doc.go +13 -0
- package/linthost/print_engine.go +68 -11
- package/linthost/print_nodes_array.go +108 -5
- package/linthost/print_nodes_call.go +515 -74
- package/linthost/print_nodes_function.go +25 -0
- package/linthost/print_nodes_imports.go +47 -14
- package/linthost/print_nodes_list.go +191 -8
- package/linthost/print_nodes_object.go +12 -6
- package/linthost/print_nodes_ternary.go +106 -0
- package/linthost/rules_boundaries.go +400 -400
- package/linthost/rules_camelcase.go +81 -81
- package/linthost/rules_complexity.go +52 -51
- package/linthost/rules_consistent_return.go +81 -81
- package/linthost/rules_core_extra.go +472 -472
- package/linthost/rules_curly.go +43 -43
- package/linthost/rules_default_case.go +15 -15
- package/linthost/rules_default_case_last.go +22 -22
- package/linthost/rules_format_arrow_parens.go +167 -0
- package/linthost/rules_format_bracket_spacing.go +117 -0
- package/linthost/rules_format_clause_join.go +172 -0
- package/linthost/rules_format_declaration_header.go +664 -0
- package/linthost/rules_format_indent.go +616 -0
- package/linthost/rules_format_jsdoc.go +4 -4
- package/linthost/rules_format_orphan_semi.go +106 -0
- package/linthost/rules_format_parameter_properties.go +175 -0
- package/linthost/rules_format_print_width.go +185 -69
- package/linthost/rules_format_quote_props.go +169 -0
- package/linthost/rules_format_quotes.go +75 -29
- package/linthost/rules_format_semi.go +185 -10
- package/linthost/rules_format_sort_imports.go +456 -121
- package/linthost/rules_format_statement_split.go +368 -0
- package/linthost/rules_format_ternary_nullish_parens.go +77 -0
- package/linthost/rules_format_trailing_comma.go +21 -2
- package/linthost/rules_format_whitespace.go +336 -0
- package/linthost/rules_functional.go +688 -688
- package/linthost/rules_gap.go +146 -11
- package/linthost/rules_grouped_accessor_pairs.go +60 -60
- package/linthost/rules_guard_for_in.go +122 -122
- package/linthost/rules_id_length.go +44 -44
- package/linthost/rules_imports.go +11 -3
- package/linthost/rules_init_declarations.go +25 -25
- package/linthost/rules_jsx_a11y.go +844 -844
- package/linthost/rules_max_classes_per_file.go +24 -24
- package/linthost/rules_max_depth.go +43 -43
- package/linthost/rules_max_lines.go +53 -53
- package/linthost/rules_max_lines_per_function.go +28 -28
- package/linthost/rules_max_nested_callbacks.go +26 -26
- package/linthost/rules_max_params.go +20 -20
- package/linthost/rules_max_statements.go +29 -29
- package/linthost/rules_nextjs.go +5 -5
- package/linthost/rules_no_else_return.go +38 -38
- package/linthost/rules_no_empty_named_blocks.go +45 -45
- package/linthost/rules_no_import_assign.go +96 -96
- package/linthost/rules_no_invalid_this.go +19 -19
- package/linthost/rules_no_loop_func.go +43 -43
- package/linthost/rules_no_magic_numbers.go +60 -60
- package/linthost/rules_no_mixed_operators.go +44 -44
- package/linthost/rules_no_param_reassign.go +64 -64
- package/linthost/rules_no_restricted_imports.go +45 -45
- package/linthost/rules_no_restricted_syntax.go +17 -17
- package/linthost/rules_no_shadow.go +112 -112
- package/linthost/rules_no_unreachable.go +36 -36
- package/linthost/rules_no_useless_assignment.go +79 -79
- package/linthost/rules_no_useless_constructor.go +167 -167
- package/linthost/rules_no_useless_return.go +28 -28
- package/linthost/rules_prefer_arrow_callback.go +74 -74
- package/linthost/rules_prefer_destructuring.go +61 -61
- package/linthost/rules_prefer_named_capture_group.go +87 -87
- package/linthost/rules_prefer_rest_params.go +61 -61
- package/linthost/rules_promise.go +800 -800
- package/linthost/rules_react.go +600 -600
- package/linthost/rules_react_extras.go +162 -162
- package/linthost/rules_react_hooks.go +2 -2
- package/linthost/rules_react_perf.go +231 -231
- package/linthost/rules_regexp.go +293 -293
- package/linthost/rules_security.go +613 -613
- package/linthost/rules_sort_imports.go +37 -37
- package/linthost/rules_sort_keys.go +88 -88
- package/linthost/rules_suggestions.go +13 -0
- package/linthost/rules_ts.go +2 -2
- package/linthost/rules_ts_async.go +247 -247
- package/linthost/rules_ts_class_literal_property_style.go +64 -64
- package/linthost/rules_ts_consistent_type_exports.go +209 -209
- package/linthost/rules_ts_explicit_function_return_type.go +35 -35
- package/linthost/rules_ts_extra.go +6 -2
- package/linthost/rules_ts_no_base_to_string.go +140 -140
- package/linthost/rules_ts_no_confusing_void.go +28 -28
- package/linthost/rules_ts_no_deprecated.go +110 -110
- package/linthost/rules_ts_no_for_in_array.go +45 -45
- package/linthost/rules_ts_no_magic_numbers.go +67 -67
- package/linthost/rules_ts_no_meaningless_void_operator.go +44 -44
- package/linthost/rules_ts_no_misused_spread.go +64 -64
- package/linthost/rules_ts_no_redundant_type_constituents.go +72 -72
- package/linthost/rules_ts_no_restricted_types.go +28 -28
- package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +87 -87
- package/linthost/rules_ts_no_unnecessary_condition.go +184 -184
- package/linthost/rules_ts_no_unnecessary_qualifier.go +72 -72
- package/linthost/rules_ts_no_unnecessary_template_expression.go +120 -120
- package/linthost/rules_ts_no_unnecessary_type_arguments.go +171 -171
- package/linthost/rules_ts_no_unnecessary_type_assertion.go +90 -90
- package/linthost/rules_ts_no_unsafe_argument.go +50 -50
- package/linthost/rules_ts_no_unsafe_assignment.go +60 -60
- package/linthost/rules_ts_no_unsafe_call.go +40 -40
- package/linthost/rules_ts_no_unsafe_enum_comparison.go +147 -147
- package/linthost/rules_ts_no_unsafe_member_access.go +29 -29
- package/linthost/rules_ts_no_unsafe_return.go +64 -64
- package/linthost/rules_ts_no_unsafe_unary_minus.go +42 -42
- package/linthost/rules_ts_no_useless_constructor.go +20 -20
- package/linthost/rules_ts_non_nullable_type_assertion_style.go +60 -60
- package/linthost/rules_ts_parameter_properties.go +10 -10
- package/linthost/rules_ts_prefer_find.go +116 -116
- package/linthost/rules_ts_prefer_includes.go +173 -173
- package/linthost/rules_ts_prefer_nullish_coalescing.go +54 -54
- package/linthost/rules_ts_prefer_optional_chain.go +156 -156
- package/linthost/rules_ts_prefer_promise_reject_errors.go +104 -104
- package/linthost/rules_ts_prefer_readonly.go +31 -31
- package/linthost/rules_ts_prefer_reduce_type_parameter.go +74 -74
- package/linthost/rules_ts_prefer_regexp_exec.go +69 -69
- package/linthost/rules_ts_prefer_return_this_type.go +79 -79
- package/linthost/rules_ts_prefer_string_starts_ends_with.go +237 -237
- package/linthost/rules_ts_promise_function_async.go +41 -41
- package/linthost/rules_ts_related_getter_setter_pairs.go +61 -61
- package/linthost/rules_ts_require_array_sort_compare.go +58 -58
- package/linthost/rules_ts_restrict_plus_operands.go +82 -82
- package/linthost/rules_ts_restrict_template_expressions.go +50 -50
- package/linthost/rules_ts_simple.go +249 -249
- package/linthost/rules_ts_sort_type_constituents.go +88 -88
- package/linthost/rules_ts_strict_boolean_expressions.go +103 -103
- package/linthost/rules_ts_switch_exhaustiveness_check.go +90 -90
- package/linthost/rules_ts_unbound_method.go +65 -65
- package/linthost/rules_tsdoc.go +88 -88
- package/linthost/rules_unicorn_better_regex.go +1 -1
- package/linthost/rules_unicorn_catch_error_name.go +19 -19
- package/linthost/rules_unicorn_consistent_assert.go +20 -20
- package/linthost/rules_unicorn_consistent_date_clone.go +27 -27
- package/linthost/rules_unicorn_consistent_destructuring.go +3 -3
- package/linthost/rules_unicorn_consistent_empty_array_spread.go +34 -34
- package/linthost/rules_unicorn_consistent_existence_index_check.go +42 -42
- package/linthost/rules_unicorn_consistent_function_scoping.go +3 -3
- package/linthost/rules_unicorn_consistent_template_literal_escape.go +3 -3
- package/linthost/rules_unicorn_custom_error_definition.go +92 -92
- package/linthost/rules_unicorn_empty_brace_spaces.go +47 -47
- package/linthost/rules_unicorn_error_message.go +34 -34
- package/linthost/rules_unicorn_escape_case.go +14 -14
- package/linthost/rules_unicorn_expiring_todo_comments.go +36 -36
- package/linthost/rules_unicorn_explicit_length_check.go +51 -51
- package/linthost/rules_unicorn_filename_case.go +1 -1
- package/linthost/rules_unicorn_import_style.go +1 -1
- package/linthost/rules_unicorn_isolated_functions.go +2 -2
- package/linthost/rules_unicorn_new_for_builtins.go +49 -49
- package/linthost/rules_unicorn_no_abusive_eslint_disable.go +31 -31
- package/linthost/rules_unicorn_no_accessor_recursion.go +69 -69
- package/linthost/rules_unicorn_no_anonymous_default_export.go +40 -40
- package/linthost/rules_unicorn_no_array_callback_reference.go +33 -33
- package/linthost/rules_unicorn_no_array_for_each.go +14 -14
- package/linthost/rules_unicorn_no_array_method_this_argument.go +29 -29
- package/linthost/rules_unicorn_no_array_reduce.go +15 -15
- package/linthost/rules_unicorn_no_array_reverse.go +17 -17
- package/linthost/rules_unicorn_no_array_sort.go +17 -17
- package/linthost/rules_unicorn_no_await_expression_member.go +12 -12
- package/linthost/rules_unicorn_no_await_in_promise_methods.go +38 -38
- package/linthost/rules_unicorn_no_console_spaces.go +30 -30
- package/linthost/rules_unicorn_no_document_cookie.go +13 -13
- package/linthost/rules_unicorn_no_empty_file.go +16 -16
- package/linthost/rules_unicorn_no_for_loop.go +58 -58
- package/linthost/rules_unicorn_no_hex_escape.go +11 -11
- package/linthost/rules_unicorn_no_immediate_mutation.go +55 -55
- package/linthost/rules_unicorn_no_instanceof_builtins.go +34 -34
- package/linthost/rules_unicorn_no_invalid_fetch_options.go +52 -52
- package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +25 -25
- package/linthost/rules_unicorn_no_keyword_prefix.go +56 -56
- package/linthost/rules_unicorn_no_lonely_if.go +21 -21
- package/linthost/rules_unicorn_no_magic_array_flat_depth.go +22 -22
- package/linthost/rules_unicorn_no_named_default.go +25 -25
- package/linthost/rules_unicorn_no_negated_condition.go +54 -54
- package/linthost/rules_unicorn_no_negation_in_equality_check.go +23 -23
- package/linthost/rules_unicorn_no_nested_ternary.go +15 -15
- package/linthost/rules_unicorn_no_new_array.go +5 -5
- package/linthost/rules_unicorn_no_new_buffer.go +5 -5
- package/linthost/rules_unicorn_no_null.go +2 -2
- package/linthost/rules_unicorn_no_object_as_default_parameter.go +19 -19
- package/linthost/rules_unicorn_no_process_exit.go +17 -17
- package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +29 -29
- package/linthost/rules_unicorn_no_static_only_class.go +27 -27
- package/linthost/rules_unicorn_no_thenable.go +47 -47
- package/linthost/rules_unicorn_no_this_assignment.go +10 -10
- package/linthost/rules_unicorn_no_typeof_undefined.go +31 -31
- package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +23 -23
- package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +37 -37
- package/linthost/rules_unicorn_no_unnecessary_await.go +24 -24
- package/linthost/rules_unicorn_no_unnecessary_slice_end.go +22 -22
- package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +67 -67
- package/linthost/rules_unicorn_no_unreadable_iife.go +22 -22
- package/linthost/rules_unicorn_no_useless_collection_argument.go +34 -34
- package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +18 -18
- package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +49 -49
- package/linthost/rules_unicorn_no_useless_iterator_to_array.go +41 -41
- package/linthost/rules_unicorn_no_useless_length_check.go +82 -82
- package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +42 -42
- package/linthost/rules_unicorn_no_useless_spread.go +38 -38
- package/linthost/rules_unicorn_no_useless_switch_case.go +29 -29
- package/linthost/rules_unicorn_no_useless_undefined.go +25 -25
- package/linthost/rules_unicorn_no_zero_fractions.go +17 -17
- package/linthost/rules_unicorn_number_literal_case.go +33 -33
- package/linthost/rules_unicorn_numeric_separators_style.go +36 -36
- package/linthost/rules_unicorn_prefer_add_event_listener.go +30 -30
- package/linthost/rules_unicorn_prefer_array_find.go +27 -27
- package/linthost/rules_unicorn_prefer_array_flat.go +25 -25
- package/linthost/rules_unicorn_prefer_array_flat_map.go +37 -37
- package/linthost/rules_unicorn_prefer_array_index_of.go +108 -108
- package/linthost/rules_unicorn_prefer_array_some.go +43 -43
- package/linthost/rules_unicorn_prefer_at.go +42 -42
- package/linthost/rules_unicorn_prefer_bigint_literals.go +42 -42
- package/linthost/rules_unicorn_prefer_blob_reading_methods.go +15 -15
- package/linthost/rules_unicorn_prefer_class_fields.go +57 -57
- package/linthost/rules_unicorn_prefer_classlist_toggle.go +76 -76
- package/linthost/rules_unicorn_prefer_code_point.go +21 -21
- package/linthost/rules_unicorn_prefer_date_now.go +47 -47
- package/linthost/rules_unicorn_prefer_default_parameters.go +96 -96
- package/linthost/rules_unicorn_prefer_dom_node_append.go +14 -14
- package/linthost/rules_unicorn_prefer_dom_node_dataset.go +27 -27
- package/linthost/rules_unicorn_prefer_dom_node_remove.go +17 -17
- package/linthost/rules_unicorn_prefer_dom_node_text_content.go +11 -11
- package/linthost/rules_unicorn_prefer_event_target.go +10 -10
- package/linthost/rules_unicorn_prefer_export_from.go +99 -99
- package/linthost/rules_unicorn_prefer_global_this.go +91 -91
- package/linthost/rules_unicorn_prefer_import_meta_properties.go +38 -38
- package/linthost/rules_unicorn_prefer_includes.go +108 -108
- package/linthost/rules_unicorn_prefer_json_parse_buffer.go +37 -37
- package/linthost/rules_unicorn_prefer_keyboard_event_key.go +10 -10
- package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +20 -20
- package/linthost/rules_unicorn_prefer_math_min_max.go +33 -33
- package/linthost/rules_unicorn_prefer_math_trunc.go +32 -32
- package/linthost/rules_unicorn_prefer_modern_dom_apis.go +18 -18
- package/linthost/rules_unicorn_prefer_modern_math_apis.go +38 -38
- package/linthost/rules_unicorn_prefer_module.go +22 -22
- package/linthost/rules_unicorn_prefer_native_coercion_functions.go +73 -73
- package/linthost/rules_unicorn_prefer_negative_index.go +46 -46
- package/linthost/rules_unicorn_prefer_node_protocol.go +90 -90
- package/linthost/rules_unicorn_prefer_number_properties.go +57 -57
- package/linthost/rules_unicorn_prefer_object_from_entries.go +26 -26
- package/linthost/rules_unicorn_prefer_optional_catch_binding.go +24 -24
- package/linthost/rules_unicorn_prefer_prototype_methods.go +25 -25
- package/linthost/rules_unicorn_prefer_query_selector.go +25 -25
- package/linthost/rules_unicorn_prefer_reflect_apply.go +10 -10
- package/linthost/rules_unicorn_prefer_regexp_test_rule.go +47 -47
- package/linthost/rules_unicorn_prefer_response_static_json.go +26 -26
- package/linthost/rules_unicorn_prefer_set_has.go +16 -16
- package/linthost/rules_unicorn_prefer_set_size.go +22 -22
- package/linthost/rules_unicorn_prefer_simple_condition_first.go +3 -3
- package/linthost/rules_unicorn_prefer_single_call.go +59 -59
- package/linthost/rules_unicorn_prefer_spread.go +24 -24
- package/linthost/rules_unicorn_prefer_string_raw.go +12 -12
- package/linthost/rules_unicorn_prefer_string_replace_all.go +46 -46
- package/linthost/rules_unicorn_prefer_string_slice.go +17 -17
- package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +104 -104
- package/linthost/rules_unicorn_prefer_string_trim_start_end.go +21 -21
- package/linthost/rules_unicorn_prefer_structured_clone.go +36 -36
- package/linthost/rules_unicorn_prefer_switch.go +65 -65
- package/linthost/rules_unicorn_prefer_ternary.go +35 -35
- package/linthost/rules_unicorn_prefer_top_level_await.go +34 -34
- package/linthost/rules_unicorn_prefer_type_error.go +84 -84
- package/linthost/rules_unicorn_prevent_abbreviations.go +68 -68
- package/linthost/rules_unicorn_relative_url_style.go +19 -19
- package/linthost/rules_unicorn_require_array_join_separator.go +18 -18
- package/linthost/rules_unicorn_require_module_attributes.go +25 -25
- package/linthost/rules_unicorn_require_module_specifiers.go +28 -28
- package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +18 -18
- package/linthost/rules_unicorn_require_post_message_target_origin.go +18 -18
- package/linthost/rules_unicorn_string_content.go +1 -1
- package/linthost/rules_unicorn_switch_case_braces.go +16 -16
- package/linthost/rules_unicorn_switch_case_break_position.go +3 -3
- package/linthost/rules_unicorn_template_indent.go +1 -1
- package/linthost/rules_unicorn_text_encoding_identifier_case.go +36 -36
- package/linthost/rules_unicorn_throw_new_error.go +30 -30
- package/linthost/rules_var.go +273 -3
- package/package.json +3 -3
- package/src/defaultFormat.ts +11 -7
- package/src/structures/ITtscLintConfig.ts +5 -5
- package/src/structures/TtscLintRuleSetting.ts +19 -19
- package/src/structures/{ITtscLintFormat.ts → format/ITtscLintFormat.ts} +48 -75
- package/src/structures/format/ITtscLintFormatJsDoc.ts +16 -0
- package/src/structures/format/ITtscLintFormatSortImports.ts +62 -0
- package/src/structures/format/index.ts +3 -0
- package/src/structures/index.ts +1 -1
- package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +20 -31
- package/src/structures/rules/ITtscLintBoundariesRules.ts +32 -36
- package/src/structures/rules/ITtscLintContributorRules.ts +6 -7
- package/src/structures/rules/ITtscLintCoreRules.ts +380 -408
- package/src/structures/rules/ITtscLintCypressRuleOptions.ts +5 -5
- package/src/structures/rules/ITtscLintCypressRules.ts +34 -38
- package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +28 -41
- package/src/structures/rules/ITtscLintFunctionalRules.ts +51 -56
- package/src/structures/rules/ITtscLintJestRules.ts +63 -74
- package/src/structures/rules/ITtscLintJsdocRules.ts +47 -54
- package/src/structures/rules/ITtscLintJsxA11yRules.ts +94 -102
- package/src/structures/rules/ITtscLintNextjsRules.ts +50 -55
- package/src/structures/rules/ITtscLintPlaywrightRules.ts +104 -122
- package/src/structures/rules/ITtscLintPromiseRules.ts +62 -71
- package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +4 -4
- package/src/structures/rules/ITtscLintReactPerfRules.ts +17 -19
- package/src/structures/rules/ITtscLintReactRuleOptions.ts +8 -10
- package/src/structures/rules/ITtscLintReactRules.ts +91 -104
- package/src/structures/rules/ITtscLintRegexpRules.ts +46 -54
- package/src/structures/rules/ITtscLintRuleOptionsMap.ts +7 -8
- package/src/structures/rules/ITtscLintSecurityRules.ts +45 -52
- package/src/structures/rules/ITtscLintSolidRules.ts +53 -56
- package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +3 -4
- package/src/structures/rules/ITtscLintStorybookRules.ts +60 -69
- package/src/structures/rules/ITtscLintTanstackQueryRules.ts +31 -37
- package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +2 -3
- package/src/structures/rules/ITtscLintTestingLibraryRules.ts +102 -119
- package/src/structures/rules/ITtscLintTypeScriptRules.ts +460 -518
- package/src/structures/rules/ITtscLintVitestRules.ts +43 -51
- package/lib/structures/ITtscLintFormat.js.map +0 -1
- /package/lib/structures/{ITtscLintFormat.js → format/ITtscLintFormat.js} +0 -0
package/linthost/rules_gap.go
CHANGED
|
@@ -244,12 +244,27 @@ func (noWrapperObjectTypes) Check(ctx *Context, node *shimast.Node) {
|
|
|
244
244
|
)
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
// fileShadowsWrapperName reports whether the source file
|
|
248
|
-
// `String`/`Number`/`Boolean`/`Symbol`/`BigInt`/`Object` at top level
|
|
249
|
-
//
|
|
247
|
+
// fileShadowsWrapperName reports whether the source file binds its own
|
|
248
|
+
// `String`/`Number`/`Boolean`/`Symbol`/`BigInt`/`Object` at top level, so
|
|
249
|
+
// the referenced name is NOT the global wrapper and a rewrite to the
|
|
250
|
+
// primitive would change the type. Walks SourceFile.Statements once; no
|
|
250
251
|
// memoization because the rule already runs once per TypeReference and
|
|
251
252
|
// the average statement count per file dominates the cost over the inner
|
|
252
253
|
// loop.
|
|
254
|
+
//
|
|
255
|
+
// The guard is intentionally comprehensive: it returns true when the
|
|
256
|
+
// wrapper name is bound by ANY file-scope declaration, because over-bailing
|
|
257
|
+
// (declining to rewrite a real global wrapper because a same-named binding
|
|
258
|
+
// exists) is safe — it only skips a lint fix — whereas under-bailing
|
|
259
|
+
// silently corrupts the type. A binding shadows the global when it comes
|
|
260
|
+
// from:
|
|
261
|
+
// - a `type` / `interface` / `class` / `enum` declaration,
|
|
262
|
+
// - a `function` declaration,
|
|
263
|
+
// - a `namespace` / `module` declaration,
|
|
264
|
+
// - a top-level `let` / `const` / `var` value declaration,
|
|
265
|
+
// - an import binding (default, namespace, or named — including an
|
|
266
|
+
// aliased `{ X as String }`, where the LOCAL name is what binds), or
|
|
267
|
+
// - an `import X = require(...)` / `import X = A.B` binding.
|
|
253
268
|
func fileShadowsWrapperName(file *shimast.SourceFile, name string) bool {
|
|
254
269
|
if file == nil || file.Statements == nil {
|
|
255
270
|
return false
|
|
@@ -258,24 +273,144 @@ func fileShadowsWrapperName(file *shimast.SourceFile, name string) bool {
|
|
|
258
273
|
if stmt == nil {
|
|
259
274
|
continue
|
|
260
275
|
}
|
|
261
|
-
var declName *shimast.Node
|
|
262
276
|
switch stmt.Kind {
|
|
263
277
|
case shimast.KindTypeAliasDeclaration:
|
|
264
|
-
if alias := stmt.AsTypeAliasDeclaration(); alias != nil
|
|
265
|
-
|
|
278
|
+
if alias := stmt.AsTypeAliasDeclaration(); alias != nil &&
|
|
279
|
+
identifierText(alias.Name()) == name {
|
|
280
|
+
return true
|
|
266
281
|
}
|
|
267
282
|
case shimast.KindInterfaceDeclaration:
|
|
268
|
-
if iface := stmt.AsInterfaceDeclaration(); iface != nil
|
|
269
|
-
|
|
283
|
+
if iface := stmt.AsInterfaceDeclaration(); iface != nil &&
|
|
284
|
+
identifierText(iface.Name()) == name {
|
|
285
|
+
return true
|
|
270
286
|
}
|
|
271
287
|
case shimast.KindClassDeclaration:
|
|
272
|
-
if cls := stmt.AsClassDeclaration(); cls != nil
|
|
273
|
-
|
|
288
|
+
if cls := stmt.AsClassDeclaration(); cls != nil &&
|
|
289
|
+
identifierText(cls.Name()) == name {
|
|
290
|
+
return true
|
|
291
|
+
}
|
|
292
|
+
case shimast.KindEnumDeclaration:
|
|
293
|
+
if enm := stmt.AsEnumDeclaration(); enm != nil &&
|
|
294
|
+
identifierText(enm.Name()) == name {
|
|
295
|
+
return true
|
|
296
|
+
}
|
|
297
|
+
case shimast.KindFunctionDeclaration:
|
|
298
|
+
if fn := stmt.AsFunctionDeclaration(); fn != nil &&
|
|
299
|
+
identifierText(fn.Name()) == name {
|
|
300
|
+
return true
|
|
301
|
+
}
|
|
302
|
+
case shimast.KindModuleDeclaration:
|
|
303
|
+
if mod := stmt.AsModuleDeclaration(); mod != nil &&
|
|
304
|
+
identifierText(mod.Name()) == name {
|
|
305
|
+
return true
|
|
306
|
+
}
|
|
307
|
+
case shimast.KindVariableStatement:
|
|
308
|
+
if variableStatementBindsName(stmt, name) {
|
|
309
|
+
return true
|
|
310
|
+
}
|
|
311
|
+
case shimast.KindImportDeclaration:
|
|
312
|
+
if importDeclarationBindsName(stmt, name) {
|
|
313
|
+
return true
|
|
314
|
+
}
|
|
315
|
+
case shimast.KindImportEqualsDeclaration:
|
|
316
|
+
if imp := stmt.AsImportEqualsDeclaration(); imp != nil &&
|
|
317
|
+
identifierText(imp.Name()) == name {
|
|
318
|
+
return true
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return false
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// variableStatementBindsName reports whether a top-level `let`/`const`/`var`
|
|
326
|
+
// statement binds `name` through a (possibly destructured) declaration.
|
|
327
|
+
func variableStatementBindsName(stmt *shimast.Node, name string) bool {
|
|
328
|
+
vs := stmt.AsVariableStatement()
|
|
329
|
+
if vs == nil || vs.DeclarationList == nil {
|
|
330
|
+
return false
|
|
331
|
+
}
|
|
332
|
+
list := vs.DeclarationList.AsVariableDeclarationList()
|
|
333
|
+
if list == nil || list.Declarations == nil {
|
|
334
|
+
return false
|
|
335
|
+
}
|
|
336
|
+
for _, declNode := range list.Declarations.Nodes {
|
|
337
|
+
if declNode == nil {
|
|
338
|
+
continue
|
|
339
|
+
}
|
|
340
|
+
decl := declNode.AsVariableDeclaration()
|
|
341
|
+
if decl != nil && bindingNameContains(decl.Name(), name) {
|
|
342
|
+
return true
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return false
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// bindingNameContains reports whether a binding name (a plain identifier or
|
|
349
|
+
// an object/array binding pattern) introduces `name`.
|
|
350
|
+
func bindingNameContains(binding *shimast.Node, name string) bool {
|
|
351
|
+
if binding == nil {
|
|
352
|
+
return false
|
|
353
|
+
}
|
|
354
|
+
if binding.Kind == shimast.KindIdentifier {
|
|
355
|
+
return identifierText(binding) == name
|
|
356
|
+
}
|
|
357
|
+
found := false
|
|
358
|
+
binding.ForEachChild(func(child *shimast.Node) bool {
|
|
359
|
+
if child == nil {
|
|
360
|
+
return false
|
|
361
|
+
}
|
|
362
|
+
if child.Kind == shimast.KindBindingElement {
|
|
363
|
+
if elem := child.AsBindingElement(); elem != nil &&
|
|
364
|
+
bindingNameContains(elem.Name(), name) {
|
|
365
|
+
found = true
|
|
366
|
+
return true
|
|
274
367
|
}
|
|
275
368
|
}
|
|
276
|
-
|
|
369
|
+
return false
|
|
370
|
+
})
|
|
371
|
+
return found
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// importDeclarationBindsName reports whether a top-level import statement
|
|
375
|
+
// introduces `name` as a local binding: a default import, a namespace
|
|
376
|
+
// import, or a named import (using the LOCAL name, so `{ X as String }`
|
|
377
|
+
// binds `String`).
|
|
378
|
+
func importDeclarationBindsName(stmt *shimast.Node, name string) bool {
|
|
379
|
+
decl := stmt.AsImportDeclaration()
|
|
380
|
+
if decl == nil || decl.ImportClause == nil {
|
|
381
|
+
return false
|
|
382
|
+
}
|
|
383
|
+
clause := decl.ImportClause.AsImportClause()
|
|
384
|
+
if clause == nil {
|
|
385
|
+
return false
|
|
386
|
+
}
|
|
387
|
+
if identifierText(clause.Name()) == name {
|
|
388
|
+
return true
|
|
389
|
+
}
|
|
390
|
+
bindings := clause.NamedBindings
|
|
391
|
+
if bindings == nil {
|
|
392
|
+
return false
|
|
393
|
+
}
|
|
394
|
+
switch bindings.Kind {
|
|
395
|
+
case shimast.KindNamespaceImport:
|
|
396
|
+
if ns := bindings.AsNamespaceImport(); ns != nil &&
|
|
397
|
+
identifierText(ns.Name()) == name {
|
|
277
398
|
return true
|
|
278
399
|
}
|
|
400
|
+
case shimast.KindNamedImports:
|
|
401
|
+
named := bindings.AsNamedImports()
|
|
402
|
+
if named == nil || named.Elements == nil {
|
|
403
|
+
return false
|
|
404
|
+
}
|
|
405
|
+
for _, specNode := range named.Elements.Nodes {
|
|
406
|
+
if specNode == nil {
|
|
407
|
+
continue
|
|
408
|
+
}
|
|
409
|
+
if spec := specNode.AsImportSpecifier(); spec != nil &&
|
|
410
|
+
identifierText(spec.Name()) == name {
|
|
411
|
+
return true
|
|
412
|
+
}
|
|
413
|
+
}
|
|
279
414
|
}
|
|
280
415
|
return false
|
|
281
416
|
}
|
|
@@ -19,69 +19,69 @@ type groupedAccessorPairs struct{}
|
|
|
19
19
|
|
|
20
20
|
func (groupedAccessorPairs) Name() string { return "grouped-accessor-pairs" }
|
|
21
21
|
func (groupedAccessorPairs) Visits() []shimast.Kind {
|
|
22
|
-
|
|
22
|
+
return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
|
|
23
23
|
}
|
|
24
24
|
func (groupedAccessorPairs) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
25
|
+
members := classMembers(node)
|
|
26
|
+
if len(members) < 2 {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
type slot struct {
|
|
30
|
+
name string
|
|
31
|
+
static bool
|
|
32
|
+
}
|
|
33
|
+
type entry struct {
|
|
34
|
+
index int
|
|
35
|
+
kind shimast.Kind
|
|
36
|
+
node *shimast.Node
|
|
37
|
+
}
|
|
38
|
+
groups := map[slot][]entry{}
|
|
39
|
+
for i, member := range members {
|
|
40
|
+
if member == nil {
|
|
41
|
+
continue
|
|
42
|
+
}
|
|
43
|
+
if member.Kind != shimast.KindGetAccessor && member.Kind != shimast.KindSetAccessor {
|
|
44
|
+
continue
|
|
45
|
+
}
|
|
46
|
+
name := classMemberName(member)
|
|
47
|
+
if name == "" {
|
|
48
|
+
continue
|
|
49
|
+
}
|
|
50
|
+
key := slot{name: name, static: hasModifier(member, shimast.KindStaticKeyword)}
|
|
51
|
+
groups[key] = append(groups[key], entry{index: i, kind: member.Kind, node: member})
|
|
52
|
+
}
|
|
53
|
+
for _, entries := range groups {
|
|
54
|
+
if len(entries) < 2 {
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
// Find a getter/setter pair within the group.
|
|
58
|
+
var get, set *entry
|
|
59
|
+
for i := range entries {
|
|
60
|
+
e := &entries[i]
|
|
61
|
+
if e.kind == shimast.KindGetAccessor && get == nil {
|
|
62
|
+
get = e
|
|
63
|
+
} else if e.kind == shimast.KindSetAccessor && set == nil {
|
|
64
|
+
set = e
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if get == nil || set == nil {
|
|
68
|
+
continue
|
|
69
|
+
}
|
|
70
|
+
// Adjacent indices in the members list satisfy the rule.
|
|
71
|
+
diff := get.index - set.index
|
|
72
|
+
if diff == 1 || diff == -1 {
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
// Report on whichever half appears later — the earlier one
|
|
76
|
+
// reads fine in isolation; the later one is the surprise.
|
|
77
|
+
later := get
|
|
78
|
+
if set.index > get.index {
|
|
79
|
+
later = set
|
|
80
|
+
}
|
|
81
|
+
ctx.Report(later.node, "Accessor pair should be grouped.")
|
|
82
|
+
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
func init() {
|
|
86
|
-
|
|
86
|
+
Register(groupedAccessorPairs{})
|
|
87
87
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
package linthost
|
|
18
18
|
|
|
19
19
|
import (
|
|
20
|
-
|
|
20
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
type guardForIn struct{}
|
|
@@ -25,19 +25,19 @@ type guardForIn struct{}
|
|
|
25
25
|
func (guardForIn) Name() string { return "guard-for-in" }
|
|
26
26
|
func (guardForIn) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindForInStatement} }
|
|
27
27
|
func (guardForIn) Check(ctx *Context, node *shimast.Node) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
stmt := node.AsForInOrOfStatement()
|
|
29
|
+
if stmt == nil || stmt.Statement == nil {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
first := firstBodyStatement(stmt.Statement)
|
|
33
|
+
if first == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
key := forInKeyName(stmt.Initializer)
|
|
37
|
+
if isHasOwnGuard(first, key) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
ctx.Report(node, "The body of a `for...in` should be wrapped in an `if (Object.hasOwn(...))` statement to filter unwanted properties from the prototype.")
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// firstBodyStatement returns the first executable statement inside a
|
|
@@ -45,22 +45,22 @@ func (guardForIn) Check(ctx *Context, node *shimast.Node) {
|
|
|
45
45
|
// non-block body is itself the only statement. Returns nil for an
|
|
46
46
|
// empty block — an empty body cannot leak inherited keys.
|
|
47
47
|
func firstBodyStatement(body *shimast.Node) *shimast.Node {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
48
|
+
if body == nil {
|
|
49
|
+
return nil
|
|
50
|
+
}
|
|
51
|
+
if body.Kind != shimast.KindBlock {
|
|
52
|
+
return body
|
|
53
|
+
}
|
|
54
|
+
block := body.AsBlock()
|
|
55
|
+
if block == nil || block.Statements == nil {
|
|
56
|
+
return nil
|
|
57
|
+
}
|
|
58
|
+
for _, s := range block.Statements.Nodes {
|
|
59
|
+
if s != nil {
|
|
60
|
+
return s
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return nil
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
// forInKeyName extracts the identifier text of the loop key from a
|
|
@@ -69,28 +69,28 @@ func firstBodyStatement(body *shimast.Node) *shimast.Node {
|
|
|
69
69
|
// or a bare Identifier (`for (key in …)`). Destructuring patterns and
|
|
70
70
|
// other shapes return "" so the rule skips its key-identity check.
|
|
71
71
|
func forInKeyName(init *shimast.Node) string {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
72
|
+
if init == nil {
|
|
73
|
+
return ""
|
|
74
|
+
}
|
|
75
|
+
if name := identifierText(init); name != "" {
|
|
76
|
+
return name
|
|
77
|
+
}
|
|
78
|
+
if init.Kind != shimast.KindVariableDeclarationList {
|
|
79
|
+
return ""
|
|
80
|
+
}
|
|
81
|
+
list := init.AsVariableDeclarationList()
|
|
82
|
+
if list == nil || list.Declarations == nil || len(list.Declarations.Nodes) != 1 {
|
|
83
|
+
return ""
|
|
84
|
+
}
|
|
85
|
+
decl := list.Declarations.Nodes[0]
|
|
86
|
+
if decl == nil {
|
|
87
|
+
return ""
|
|
88
|
+
}
|
|
89
|
+
v := decl.AsVariableDeclaration()
|
|
90
|
+
if v == nil {
|
|
91
|
+
return ""
|
|
92
|
+
}
|
|
93
|
+
return identifierText(v.Name())
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
// isHasOwnGuard reports whether `stmt` is the canonical own-key guard
|
|
@@ -110,89 +110,89 @@ func forInKeyName(init *shimast.Node) string {
|
|
|
110
110
|
// initializer; otherwise any second argument is accepted (the rule
|
|
111
111
|
// has no reliable handle on the key name).
|
|
112
112
|
func isHasOwnGuard(stmt *shimast.Node, key string) bool {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
113
|
+
if stmt == nil || stmt.Kind != shimast.KindIfStatement {
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
ifStmt := stmt.AsIfStatement()
|
|
117
|
+
if ifStmt == nil || ifStmt.Expression == nil {
|
|
118
|
+
return false
|
|
119
|
+
}
|
|
120
|
+
cond := stripParens(ifStmt.Expression)
|
|
121
|
+
if cond == nil {
|
|
122
|
+
return false
|
|
123
|
+
}
|
|
124
|
+
if isHasOwnCall(cond, key) {
|
|
125
|
+
return true
|
|
126
|
+
}
|
|
127
|
+
if cond.Kind != shimast.KindPrefixUnaryExpression {
|
|
128
|
+
return false
|
|
129
|
+
}
|
|
130
|
+
pre := cond.AsPrefixUnaryExpression()
|
|
131
|
+
if pre == nil || pre.Operator != shimast.KindExclamationToken {
|
|
132
|
+
return false
|
|
133
|
+
}
|
|
134
|
+
if !isHasOwnCall(stripParens(pre.Operand), key) {
|
|
135
|
+
return false
|
|
136
|
+
}
|
|
137
|
+
// Negated guard: require the then branch to be a single `continue`
|
|
138
|
+
// so the rest of the loop runs only for own keys.
|
|
139
|
+
return isLoneContinue(ifStmt.ThenStatement)
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// isHasOwnCall reports whether `node` is `Object.hasOwn(obj, key)` or
|
|
143
143
|
// `Object.prototype.hasOwnProperty.call(obj, key)`. The second
|
|
144
144
|
// argument must match `key` when one is supplied.
|
|
145
145
|
func isHasOwnCall(node *shimast.Node, key string) bool {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
146
|
+
if node == nil || node.Kind != shimast.KindCallExpression {
|
|
147
|
+
return false
|
|
148
|
+
}
|
|
149
|
+
call := node.AsCallExpression()
|
|
150
|
+
if call == nil || call.Expression == nil || call.Arguments == nil {
|
|
151
|
+
return false
|
|
152
|
+
}
|
|
153
|
+
args := call.Arguments.Nodes
|
|
154
|
+
if len(args) < 2 {
|
|
155
|
+
return false
|
|
156
|
+
}
|
|
157
|
+
callee := stripParens(call.Expression)
|
|
158
|
+
switch {
|
|
159
|
+
case isMatchingPropertyAccess(callee, "Object", "hasOwn"):
|
|
160
|
+
// `Object.hasOwn(obj, key)` — both arguments belong to the
|
|
161
|
+
// caller; the key check is the second argument.
|
|
162
|
+
case isMatchingPropertyAccess(callee, "Object", "prototype", "hasOwnProperty", "call"):
|
|
163
|
+
// `Object.prototype.hasOwnProperty.call(obj, key)` — same
|
|
164
|
+
// argument layout because `.call(obj, key)` passes the
|
|
165
|
+
// receiver explicitly.
|
|
166
|
+
default:
|
|
167
|
+
return false
|
|
168
|
+
}
|
|
169
|
+
if key == "" {
|
|
170
|
+
return true
|
|
171
|
+
}
|
|
172
|
+
return identifierText(stripParens(args[1])) == key
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
// isLoneContinue reports whether `stmt` is a bare `continue;` (or a
|
|
176
176
|
// block containing exactly one `continue;`). Used to validate the
|
|
177
177
|
// then-branch of the negated-guard shape.
|
|
178
178
|
func isLoneContinue(stmt *shimast.Node) bool {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
179
|
+
if stmt == nil {
|
|
180
|
+
return false
|
|
181
|
+
}
|
|
182
|
+
if stmt.Kind == shimast.KindContinueStatement {
|
|
183
|
+
return true
|
|
184
|
+
}
|
|
185
|
+
if stmt.Kind != shimast.KindBlock {
|
|
186
|
+
return false
|
|
187
|
+
}
|
|
188
|
+
block := stmt.AsBlock()
|
|
189
|
+
if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
|
|
190
|
+
return false
|
|
191
|
+
}
|
|
192
|
+
return block.Statements.Nodes[0] != nil &&
|
|
193
|
+
block.Statements.Nodes[0].Kind == shimast.KindContinueStatement
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
func init() {
|
|
197
|
-
|
|
197
|
+
Register(guardForIn{})
|
|
198
198
|
}
|