@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
|
@@ -23,55 +23,55 @@
|
|
|
23
23
|
package linthost
|
|
24
24
|
|
|
25
25
|
import (
|
|
26
|
-
|
|
26
|
+
"strings"
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
29
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
30
30
|
)
|
|
31
31
|
|
|
32
32
|
type preferStringStartsEndsWith struct{}
|
|
33
33
|
|
|
34
34
|
func (preferStringStartsEndsWith) Name() string {
|
|
35
|
-
|
|
35
|
+
return "typescript/prefer-string-starts-ends-with"
|
|
36
36
|
}
|
|
37
37
|
func (preferStringStartsEndsWith) NeedsTypeChecker() bool {
|
|
38
|
-
|
|
38
|
+
return true
|
|
39
39
|
}
|
|
40
40
|
func (preferStringStartsEndsWith) Visits() []shimast.Kind {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
return []shimast.Kind{
|
|
42
|
+
shimast.KindBinaryExpression,
|
|
43
|
+
shimast.KindCallExpression,
|
|
44
|
+
}
|
|
45
45
|
}
|
|
46
46
|
func (preferStringStartsEndsWith) Check(ctx *Context, node *shimast.Node) {
|
|
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
|
-
|
|
47
|
+
if ctx.Checker == nil {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
switch node.Kind {
|
|
51
|
+
case shimast.KindBinaryExpression:
|
|
52
|
+
bin := node.AsBinaryExpression()
|
|
53
|
+
if bin == nil || bin.OperatorToken == nil {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
if !preferStringStartsEndsWithIsEqualityOp(bin.OperatorToken.Kind) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
if preferStringStartsEndsWithBinary(ctx, bin.Left, bin.Right) {
|
|
60
|
+
ctx.Report(node, preferStringStartsEndsWithMessage)
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
if preferStringStartsEndsWithBinary(ctx, bin.Right, bin.Left) {
|
|
64
|
+
ctx.Report(node, preferStringStartsEndsWithMessage)
|
|
65
|
+
}
|
|
66
|
+
case shimast.KindCallExpression:
|
|
67
|
+
call := node.AsCallExpression()
|
|
68
|
+
if call == nil {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
if preferStringStartsEndsWithRegexTest(ctx, call) {
|
|
72
|
+
ctx.Report(node, preferStringStartsEndsWithMessage)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
const preferStringStartsEndsWithMessage = "Prefer `String#startsWith` / `String#endsWith` over the equivalent `indexOf` / `lastIndexOf` / anchored-regex idioms — clearer and avoids the off-by-one arithmetic."
|
|
@@ -81,14 +81,14 @@ const preferStringStartsEndsWithMessage = "Prefer `String#startsWith` / `String#
|
|
|
81
81
|
// `!=`, `!==` matter: every recognized shape compares two integers
|
|
82
82
|
// for equality (or inequality with a sentinel) rather than ordering.
|
|
83
83
|
func preferStringStartsEndsWithIsEqualityOp(kind shimast.Kind) bool {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
switch kind {
|
|
85
|
+
case shimast.KindEqualsEqualsToken,
|
|
86
|
+
shimast.KindEqualsEqualsEqualsToken,
|
|
87
|
+
shimast.KindExclamationEqualsToken,
|
|
88
|
+
shimast.KindExclamationEqualsEqualsToken:
|
|
89
|
+
return true
|
|
90
|
+
}
|
|
91
|
+
return false
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
// preferStringStartsEndsWithBinary inspects `call op other` for the
|
|
@@ -96,79 +96,79 @@ func preferStringStartsEndsWithIsEqualityOp(kind shimast.Kind) bool {
|
|
|
96
96
|
// the call is provably string-typed AND the right-hand side matches
|
|
97
97
|
// the sentinel of one of the recognized rewrites:
|
|
98
98
|
//
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
99
|
+
// str.indexOf(p) === 0
|
|
100
|
+
// str.indexOf(p, str.length - p.length) !== -1
|
|
101
|
+
// str.lastIndexOf(p) === str.length - p.length
|
|
102
102
|
func preferStringStartsEndsWithBinary(
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
ctx *Context,
|
|
104
|
+
callNode, otherNode *shimast.Node,
|
|
105
105
|
) bool {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
106
|
+
callNode = stripParens(callNode)
|
|
107
|
+
otherNode = stripParens(otherNode)
|
|
108
|
+
if callNode == nil || otherNode == nil {
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
if callNode.Kind != shimast.KindCallExpression {
|
|
112
|
+
return false
|
|
113
|
+
}
|
|
114
|
+
call := callNode.AsCallExpression()
|
|
115
|
+
if call == nil || call.Expression == nil {
|
|
116
|
+
return false
|
|
117
|
+
}
|
|
118
|
+
receiver, method, ok := promisePropertyAccessParts(call.Expression)
|
|
119
|
+
if !ok {
|
|
120
|
+
return false
|
|
121
|
+
}
|
|
122
|
+
if method != "indexOf" && method != "lastIndexOf" {
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
if receiver == nil {
|
|
126
|
+
return false
|
|
127
|
+
}
|
|
128
|
+
t := ctx.Checker.GetTypeAtLocation(receiver)
|
|
129
|
+
if !preferStringStartsEndsWithIsString(t) {
|
|
130
|
+
return false
|
|
131
|
+
}
|
|
132
|
+
args := call.Arguments
|
|
133
|
+
if args == nil || len(args.Nodes) == 0 {
|
|
134
|
+
return false
|
|
135
|
+
}
|
|
136
|
+
arg := stripParens(args.Nodes[0])
|
|
137
|
+
if arg == nil {
|
|
138
|
+
return false
|
|
139
|
+
}
|
|
140
|
+
receiverText := nodeText(ctx.File, receiver)
|
|
141
|
+
argText := nodeText(ctx.File, arg)
|
|
142
|
+
otherText := nodeText(ctx.File, otherNode)
|
|
143
|
+
if receiverText == "" || argText == "" {
|
|
144
|
+
return false
|
|
145
|
+
}
|
|
146
|
+
switch method {
|
|
147
|
+
case "indexOf":
|
|
148
|
+
// startsWith: `str.indexOf(p) === 0`
|
|
149
|
+
if len(args.Nodes) == 1 {
|
|
150
|
+
return otherText == "0"
|
|
151
|
+
}
|
|
152
|
+
// endsWith via positional indexOf: the second argument must
|
|
153
|
+
// equal `str.length - arg.length`, and the comparison must be
|
|
154
|
+
// against -1 (the sentinel for "not present at that
|
|
155
|
+
// position").
|
|
156
|
+
if len(args.Nodes) != 2 {
|
|
157
|
+
return false
|
|
158
|
+
}
|
|
159
|
+
second := stripParens(args.Nodes[1])
|
|
160
|
+
if !preferStringStartsEndsWithIsLengthMinusLength(ctx, second, receiverText, argText) {
|
|
161
|
+
return false
|
|
162
|
+
}
|
|
163
|
+
return preferStringStartsEndsWithIsMinusOne(otherText)
|
|
164
|
+
case "lastIndexOf":
|
|
165
|
+
// endsWith: `str.lastIndexOf(p) === str.length - p.length`
|
|
166
|
+
if len(args.Nodes) != 1 {
|
|
167
|
+
return false
|
|
168
|
+
}
|
|
169
|
+
return preferStringStartsEndsWithIsLengthMinusLengthText(otherText, receiverText, argText)
|
|
170
|
+
}
|
|
171
|
+
return false
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
// preferStringStartsEndsWithRegexTest reports whether `call` is a
|
|
@@ -179,29 +179,29 @@ func preferStringStartsEndsWithBinary(
|
|
|
179
179
|
// without that the call is not equivalent to a startsWith/endsWith
|
|
180
180
|
// rewrite (e.g. coercing a non-string regex argument).
|
|
181
181
|
func preferStringStartsEndsWithRegexTest(
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
ctx *Context,
|
|
183
|
+
call *shimast.CallExpression,
|
|
184
184
|
) bool {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
185
|
+
if call == nil || call.Expression == nil || call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
|
|
186
|
+
return false
|
|
187
|
+
}
|
|
188
|
+
receiver, method, ok := promisePropertyAccessParts(call.Expression)
|
|
189
|
+
if !ok || method != "test" {
|
|
190
|
+
return false
|
|
191
|
+
}
|
|
192
|
+
receiver = stripParens(receiver)
|
|
193
|
+
if receiver == nil || receiver.Kind != shimast.KindRegularExpressionLiteral {
|
|
194
|
+
return false
|
|
195
|
+
}
|
|
196
|
+
raw := nodeText(ctx.File, receiver)
|
|
197
|
+
if !preferStringStartsEndsWithIsAnchoredStaticRegex(raw) {
|
|
198
|
+
return false
|
|
199
|
+
}
|
|
200
|
+
arg := stripParens(call.Arguments.Nodes[0])
|
|
201
|
+
if arg == nil {
|
|
202
|
+
return false
|
|
203
|
+
}
|
|
204
|
+
return preferStringStartsEndsWithIsString(ctx.Checker.GetTypeAtLocation(arg))
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
// preferStringStartsEndsWithIsAnchoredStaticRegex reports whether
|
|
@@ -212,34 +212,34 @@ func preferStringStartsEndsWithRegexTest(
|
|
|
212
212
|
// like `i` would lower-case both sides, which `startsWith` does not
|
|
213
213
|
// do — so the rewrite would change meaning.
|
|
214
214
|
func preferStringStartsEndsWithIsAnchoredStaticRegex(raw string) bool {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
215
|
+
if len(raw) < 3 || raw[0] != '/' {
|
|
216
|
+
return false
|
|
217
|
+
}
|
|
218
|
+
closing := strings.LastIndexByte(raw, '/')
|
|
219
|
+
if closing <= 0 {
|
|
220
|
+
return false
|
|
221
|
+
}
|
|
222
|
+
pattern := raw[1:closing]
|
|
223
|
+
flags := raw[closing+1:]
|
|
224
|
+
if pattern == "" {
|
|
225
|
+
return false
|
|
226
|
+
}
|
|
227
|
+
for i := 0; i < len(flags); i++ {
|
|
228
|
+
switch flags[i] {
|
|
229
|
+
case 'g', 'y', 'd':
|
|
230
|
+
// stateful/position flags — fine for `.test` since we
|
|
231
|
+
// only call once
|
|
232
|
+
default:
|
|
233
|
+
return false
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if pattern[0] == '^' {
|
|
237
|
+
return preferStringStartsEndsWithIsStaticString(pattern[1:])
|
|
238
|
+
}
|
|
239
|
+
if pattern[len(pattern)-1] == '$' {
|
|
240
|
+
return preferStringStartsEndsWithIsStaticString(pattern[:len(pattern)-1])
|
|
241
|
+
}
|
|
242
|
+
return false
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
// preferStringStartsEndsWithIsStaticString reports whether `pattern`
|
|
@@ -249,35 +249,35 @@ func preferStringStartsEndsWithIsAnchoredStaticRegex(raw string) bool {
|
|
|
249
249
|
// `[`, `]`, `{`, `}`, `|`, `.` — disqualifies the body because the
|
|
250
250
|
// startsWith/endsWith rewrite would change matching semantics.
|
|
251
251
|
func preferStringStartsEndsWithIsStaticString(pattern string) bool {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
252
|
+
if pattern == "" {
|
|
253
|
+
return false
|
|
254
|
+
}
|
|
255
|
+
for i := 0; i < len(pattern); i++ {
|
|
256
|
+
ch := pattern[i]
|
|
257
|
+
if ch == '\\' {
|
|
258
|
+
// Accept only escapes that name a single literal
|
|
259
|
+
// character (`\.`, `\$`, `\^`, `\/`, `\\`, `\(`, `\)`,
|
|
260
|
+
// `\[`, `\]`, `\{`, `\}`, `\|`, `\+`, `\*`, `\?`).
|
|
261
|
+
// Reject character-class shortcuts (`\d`, `\w`, `\s`)
|
|
262
|
+
// and back-references — those would not survive a
|
|
263
|
+
// rewrite to startsWith/endsWith.
|
|
264
|
+
if i+1 >= len(pattern) {
|
|
265
|
+
return false
|
|
266
|
+
}
|
|
267
|
+
next := pattern[i+1]
|
|
268
|
+
switch next {
|
|
269
|
+
case '.', '$', '^', '/', '\\', '(', ')', '[', ']', '{', '}', '|', '+', '*', '?', '-':
|
|
270
|
+
i++
|
|
271
|
+
continue
|
|
272
|
+
}
|
|
273
|
+
return false
|
|
274
|
+
}
|
|
275
|
+
switch ch {
|
|
276
|
+
case '^', '$', '*', '+', '?', '(', ')', '[', ']', '{', '}', '|', '.':
|
|
277
|
+
return false
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return true
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
// preferStringStartsEndsWithIsLengthMinusLength reports whether
|
|
@@ -286,14 +286,14 @@ func preferStringStartsEndsWithIsStaticString(pattern string) bool {
|
|
|
286
286
|
// rewrite only fires when the call site spelled the offset that way
|
|
287
287
|
// — matching the upstream rule's textual shape detector.
|
|
288
288
|
func preferStringStartsEndsWithIsLengthMinusLength(
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
289
|
+
ctx *Context,
|
|
290
|
+
node *shimast.Node,
|
|
291
|
+
receiverText, argText string,
|
|
292
292
|
) bool {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
293
|
+
if node == nil {
|
|
294
|
+
return false
|
|
295
|
+
}
|
|
296
|
+
return preferStringStartsEndsWithIsLengthMinusLengthText(nodeText(ctx.File, node), receiverText, argText)
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
// preferStringStartsEndsWithIsLengthMinusLengthText is the text-level
|
|
@@ -301,29 +301,29 @@ func preferStringStartsEndsWithIsLengthMinusLength(
|
|
|
301
301
|
// so the `lastIndexOf === str.length - p.length` shape can use the
|
|
302
302
|
// same matcher against the binary RHS text.
|
|
303
303
|
func preferStringStartsEndsWithIsLengthMinusLengthText(text, receiverText, argText string) bool {
|
|
304
|
-
|
|
305
|
-
|
|
304
|
+
wanted := receiverText + ".length-" + argText + ".length"
|
|
305
|
+
return preferStringStartsEndsWithStripSpaces(text) == wanted
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
// preferStringStartsEndsWithStripSpaces removes whitespace from `s`.
|
|
309
309
|
// Used for the textual equality match — `a.length - b.length` and
|
|
310
310
|
// `a.length-b.length` should both match the canonical form.
|
|
311
311
|
func preferStringStartsEndsWithStripSpaces(s string) string {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
312
|
+
var b strings.Builder
|
|
313
|
+
for i := 0; i < len(s); i++ {
|
|
314
|
+
ch := s[i]
|
|
315
|
+
if ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' {
|
|
316
|
+
continue
|
|
317
|
+
}
|
|
318
|
+
b.WriteByte(ch)
|
|
319
|
+
}
|
|
320
|
+
return b.String()
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
// preferStringStartsEndsWithIsMinusOne reports whether `text` is the
|
|
324
324
|
// numeric literal `-1` (with or without internal whitespace).
|
|
325
325
|
func preferStringStartsEndsWithIsMinusOne(text string) bool {
|
|
326
|
-
|
|
326
|
+
return preferStringStartsEndsWithStripSpaces(text) == "-1"
|
|
327
327
|
}
|
|
328
328
|
|
|
329
329
|
// preferStringStartsEndsWithIsString reports whether t is provably
|
|
@@ -331,30 +331,30 @@ func preferStringStartsEndsWithIsMinusOne(text string) bool {
|
|
|
331
331
|
// rejects `any` / `unknown` / `never` so generic helpers don't fire.
|
|
332
332
|
// Union and intersection types must have every constituent string-like.
|
|
333
333
|
func preferStringStartsEndsWithIsString(t *shimchecker.Type) bool {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
334
|
+
if t == nil {
|
|
335
|
+
return false
|
|
336
|
+
}
|
|
337
|
+
flags := t.Flags()
|
|
338
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
339
|
+
return false
|
|
340
|
+
}
|
|
341
|
+
if flags&shimchecker.TypeFlagsStringLike != 0 {
|
|
342
|
+
return true
|
|
343
|
+
}
|
|
344
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
345
|
+
for _, part := range t.Types() {
|
|
346
|
+
if part == nil {
|
|
347
|
+
continue
|
|
348
|
+
}
|
|
349
|
+
if !preferStringStartsEndsWithIsString(part) {
|
|
350
|
+
return false
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return true
|
|
354
|
+
}
|
|
355
|
+
return false
|
|
356
356
|
}
|
|
357
357
|
|
|
358
358
|
func init() {
|
|
359
|
-
|
|
359
|
+
Register(preferStringStartsEndsWith{})
|
|
360
360
|
}
|
|
@@ -20,58 +20,58 @@
|
|
|
20
20
|
package linthost
|
|
21
21
|
|
|
22
22
|
import (
|
|
23
|
-
|
|
23
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
type promiseFunctionAsync struct{}
|
|
27
27
|
|
|
28
28
|
func (promiseFunctionAsync) Name() string { return "typescript/promise-function-async" }
|
|
29
29
|
func (promiseFunctionAsync) NeedsTypeChecker() bool {
|
|
30
|
-
|
|
30
|
+
return true
|
|
31
31
|
}
|
|
32
32
|
func (promiseFunctionAsync) Visits() []shimast.Kind {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
return []shimast.Kind{
|
|
34
|
+
shimast.KindFunctionDeclaration,
|
|
35
|
+
shimast.KindFunctionExpression,
|
|
36
|
+
shimast.KindArrowFunction,
|
|
37
|
+
shimast.KindMethodDeclaration,
|
|
38
|
+
}
|
|
39
39
|
}
|
|
40
40
|
func (promiseFunctionAsync) Check(ctx *Context, node *shimast.Node) {
|
|
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
|
-
|
|
41
|
+
if ctx.Checker == nil {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
if hasAsyncModifier(node) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
// Skip overload signatures and abstract methods — only the
|
|
48
|
+
// implementation signature carries an executable body that the
|
|
49
|
+
// `async` keyword could wrap.
|
|
50
|
+
if node.Body() == nil {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
if hasModifier(node, shimast.KindAbstractKeyword) {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
sig := ctx.Checker.GetSignatureFromDeclaration(node)
|
|
57
|
+
if sig == nil {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
returnType := ctx.Checker.GetReturnTypeOfSignature(sig)
|
|
61
|
+
if returnType == nil {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
if !isPromiseTypedExpression(ctx.Checker, returnType) {
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
startPos := keywordStart(ctx.File, node, "function")
|
|
68
|
+
if startPos >= 0 {
|
|
69
|
+
ctx.ReportRange(startPos, startPos+len("function"), "Function returning a Promise should be declared `async` so synchronous throws surface as a rejected Promise.")
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
ctx.Report(node, "Function returning a Promise should be declared `async` so synchronous throws surface as a rejected Promise.")
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
func init() {
|
|
76
|
-
|
|
76
|
+
Register(promiseFunctionAsync{})
|
|
77
77
|
}
|