@ttsc/lint 0.13.1 → 0.14.0-dev.20260528.1
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 +948 -69
- package/lib/defaultFormat.d.ts +9 -6
- package/lib/defaultFormat.js +9 -6
- package/lib/defaultFormat.js.map +1 -1
- package/lib/index.d.ts +46 -0
- package/lib/index.js +35 -10
- package/lib/index.js.map +1 -1
- package/lib/structures/ITtscLintConfig.d.ts +12 -6
- package/lib/structures/{ITtscLintFormatConfig.d.ts → ITtscLintFormat.d.ts} +2 -2
- package/lib/structures/{TtscLintRuleMap.js → ITtscLintFormat.js} +1 -1
- package/lib/structures/ITtscLintFormat.js.map +1 -0
- package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
- package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
- package/lib/structures/TtscLintRuleSetting.js.map +1 -0
- package/lib/structures/index.d.ts +3 -4
- package/lib/structures/index.js +3 -4
- package/lib/structures/index.js.map +1 -1
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +104 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +14 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +79 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintContributorRules.d.ts +17 -0
- package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
- package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintCoreRules.d.ts +1257 -0
- package/lib/structures/{ITtscLintFormatConfig.js → rules/ITtscLintCoreRules.js} +1 -1
- package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintCypressRules.d.ts +129 -0
- package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
- package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +157 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +167 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJestRules.d.ts +201 -0
- package/lib/structures/rules/ITtscLintJestRules.js +3 -0
- package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJsdocRules.d.ts +140 -0
- package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
- package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +302 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintNextjsRules.d.ts +185 -0
- package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
- package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +330 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintPromiseRules.d.ts +188 -0
- package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
- package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +51 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +39 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js +12 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRules.d.ts +289 -0
- package/lib/structures/rules/ITtscLintReactRules.js +3 -0
- package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintRegexpRules.d.ts +190 -0
- package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
- package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +66 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
- package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
- package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
- package/lib/structures/rules/ITtscLintRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintSecurityRules.d.ts +148 -0
- package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
- package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintSolidRules.d.ts +181 -0
- package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
- package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +21 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintStorybookRules.d.ts +174 -0
- package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
- package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +94 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +22 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +310 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1132 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
- package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
- package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintVitestRules.d.ts +141 -0
- package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
- package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
- package/lib/structures/rules/index.d.ts +31 -0
- package/lib/structures/rules/index.js +48 -0
- package/lib/structures/rules/index.js.map +1 -0
- package/linthost/ast_helpers.go +30 -5
- package/linthost/config.go +48 -17
- package/linthost/config_format.go +9 -9
- package/linthost/directives.go +67 -25
- package/linthost/dispatch.go +14 -3
- package/linthost/engine.go +152 -31
- package/linthost/fix.go +2 -2
- package/linthost/lsp.go +747 -0
- package/linthost/print_dispatch.go +2 -2
- package/linthost/print_nodes_function.go +2 -2
- package/linthost/print_nodes_object.go +1 -1
- package/linthost/rule_names.go +14 -0
- package/linthost/rules_arrays.go +2 -2
- package/linthost/rules_boundaries.go +532 -0
- package/linthost/rules_camelcase.go +133 -0
- package/linthost/rules_complexity.go +94 -0
- package/linthost/rules_consistent_return.go +130 -0
- package/linthost/rules_console.go +1 -1
- package/linthost/rules_core_extra.go +739 -0
- package/linthost/rules_curly.go +70 -0
- package/linthost/rules_cypress.go +608 -0
- package/linthost/rules_debugger.go +2 -2
- package/linthost/rules_default_case.go +39 -0
- package/linthost/rules_default_case_last.go +46 -0
- package/linthost/rules_dupes.go +3 -3
- package/linthost/rules_empty.go +3 -3
- package/linthost/rules_escape.go +44 -24
- package/linthost/rules_eval.go +2 -2
- package/linthost/rules_finally.go +2 -2
- package/linthost/rules_format_jsdoc.go +1 -1
- package/linthost/rules_format_print_width.go +9 -9
- package/linthost/rules_format_quotes.go +1 -1
- package/linthost/rules_format_semi.go +1 -1
- package/linthost/rules_format_sort_imports.go +1 -1
- package/linthost/rules_format_trailing_comma.go +1 -1
- package/linthost/rules_functional.go +967 -0
- package/linthost/rules_gap.go +24 -45
- package/linthost/rules_grouped_accessor_pairs.go +87 -0
- package/linthost/rules_guard_for_in.go +198 -0
- package/linthost/rules_id_length.go +77 -0
- package/linthost/rules_imports.go +70 -2
- package/linthost/rules_init_declarations.go +53 -0
- package/linthost/rules_jest.go +618 -0
- package/linthost/rules_jsdoc.go +502 -0
- package/linthost/rules_jsx_a11y.go +1264 -0
- package/linthost/rules_logic.go +12 -12
- package/linthost/rules_loops.go +1 -1
- package/linthost/rules_max_classes_per_file.go +58 -0
- package/linthost/rules_max_depth.go +83 -0
- package/linthost/rules_max_lines.go +101 -0
- package/linthost/rules_max_lines_per_function.go +57 -0
- package/linthost/rules_max_nested_callbacks.go +61 -0
- package/linthost/rules_max_params.go +49 -0
- package/linthost/rules_max_statements.go +59 -0
- package/linthost/rules_misc.go +1 -1
- package/linthost/rules_nextjs.go +697 -0
- package/linthost/rules_no_else_return.go +75 -0
- package/linthost/rules_no_empty_named_blocks.go +91 -0
- package/linthost/rules_no_extend_native.go +51 -0
- package/linthost/rules_no_import_assign.go +140 -0
- package/linthost/rules_no_invalid_this.go +52 -0
- package/linthost/rules_no_loop_func.go +85 -0
- package/linthost/rules_no_magic_numbers.go +123 -0
- package/linthost/rules_no_mixed_operators.go +80 -0
- package/linthost/rules_no_param_reassign.go +98 -0
- package/linthost/rules_no_redeclare.go +270 -0
- package/linthost/rules_no_restricted_imports.go +105 -0
- package/linthost/rules_no_restricted_syntax.go +49 -0
- package/linthost/rules_no_shadow.go +147 -0
- package/linthost/rules_no_unreachable.go +77 -0
- package/linthost/rules_no_useless_assignment.go +120 -0
- package/linthost/rules_no_useless_constructor.go +245 -0
- package/linthost/rules_no_useless_return.go +51 -0
- package/linthost/rules_params.go +1 -1
- package/linthost/rules_playwright.go +788 -0
- package/linthost/rules_prefer_arrow_callback.go +124 -0
- package/linthost/rules_prefer_destructuring.go +98 -0
- package/linthost/rules_prefer_named_capture_group.go +129 -0
- package/linthost/rules_prefer_rest_params.go +94 -0
- package/linthost/rules_problems.go +41 -30
- package/linthost/rules_promise.go +1128 -73
- package/linthost/rules_protos.go +2 -2
- package/linthost/rules_react.go +773 -0
- package/linthost/rules_react_extras.go +227 -0
- package/linthost/rules_react_hooks.go +848 -0
- package/linthost/rules_react_perf.go +293 -0
- package/linthost/rules_react_refresh.go +583 -0
- package/linthost/rules_regexp.go +410 -0
- package/linthost/rules_security.go +830 -0
- package/linthost/rules_self.go +2 -2
- package/linthost/rules_solid.go +1073 -0
- package/linthost/rules_sort_imports.go +69 -0
- package/linthost/rules_sort_keys.go +134 -0
- package/linthost/rules_storybook.go +1176 -0
- package/linthost/rules_strings.go +4 -4
- package/linthost/rules_suggestions.go +38 -38
- package/linthost/rules_tanstack_query.go +844 -0
- package/linthost/rules_testing_library.go +1204 -0
- package/linthost/rules_throw.go +1 -1
- package/linthost/rules_ts.go +19 -19
- package/linthost/rules_ts_async.go +399 -0
- package/linthost/rules_ts_class_literal_property_style.go +115 -0
- package/linthost/rules_ts_consistent_type_exports.go +256 -0
- package/linthost/rules_ts_explicit_function_return_type.go +67 -0
- package/linthost/rules_ts_extra.go +155 -36
- package/linthost/rules_ts_no_base_to_string.go +218 -0
- package/linthost/rules_ts_no_confusing_void.go +72 -0
- package/linthost/rules_ts_no_deprecated.go +195 -0
- package/linthost/rules_ts_no_for_in_array.go +84 -0
- package/linthost/rules_ts_no_magic_numbers.go +124 -0
- package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
- package/linthost/rules_ts_no_misused_spread.go +104 -0
- package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
- package/linthost/rules_ts_no_restricted_types.go +62 -0
- package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
- package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
- package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
- package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
- package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
- package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
- package/linthost/rules_ts_no_unsafe_argument.go +82 -0
- package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
- package/linthost/rules_ts_no_unsafe_call.go +82 -0
- package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
- package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
- package/linthost/rules_ts_no_unsafe_return.go +126 -0
- package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
- package/linthost/rules_ts_no_useless_constructor.go +52 -0
- package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
- package/linthost/rules_ts_parameter_properties.go +38 -0
- package/linthost/rules_ts_prefer_find.go +178 -0
- package/linthost/rules_ts_prefer_includes.go +255 -0
- package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
- package/linthost/rules_ts_prefer_optional_chain.go +228 -0
- package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
- package/linthost/rules_ts_prefer_readonly.go +73 -0
- package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
- package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
- package/linthost/rules_ts_prefer_return_this_type.go +135 -0
- package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
- package/linthost/rules_ts_promise_function_async.go +77 -0
- package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
- package/linthost/rules_ts_require_array_sort_compare.go +96 -0
- package/linthost/rules_ts_restrict_plus_operands.go +127 -0
- package/linthost/rules_ts_restrict_template_expressions.go +95 -0
- package/linthost/rules_ts_simple.go +387 -0
- package/linthost/rules_ts_sort_type_constituents.go +144 -0
- package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
- package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
- package/linthost/rules_ts_unbound_method.go +126 -0
- package/linthost/rules_tsdoc.go +136 -0
- package/linthost/rules_unicorn_better_regex.go +27 -0
- package/linthost/rules_unicorn_catch_error_name.go +46 -0
- package/linthost/rules_unicorn_consistent_assert.go +47 -0
- package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
- package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
- package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
- package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
- package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
- package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
- package/linthost/rules_unicorn_custom_error_definition.go +138 -0
- package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
- package/linthost/rules_unicorn_error_message.go +64 -0
- package/linthost/rules_unicorn_escape_case.go +51 -0
- package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
- package/linthost/rules_unicorn_explicit_length_check.go +88 -0
- package/linthost/rules_unicorn_filename_case.go +29 -0
- package/linthost/rules_unicorn_import_style.go +28 -0
- package/linthost/rules_unicorn_isolated_functions.go +29 -0
- package/linthost/rules_unicorn_new_for_builtins.go +87 -0
- package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
- package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
- package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
- package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
- package/linthost/rules_unicorn_no_array_for_each.go +40 -0
- package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
- package/linthost/rules_unicorn_no_array_reduce.go +41 -0
- package/linthost/rules_unicorn_no_array_reverse.go +44 -0
- package/linthost/rules_unicorn_no_array_sort.go +43 -0
- package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
- package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
- package/linthost/rules_unicorn_no_console_spaces.go +61 -0
- package/linthost/rules_unicorn_no_document_cookie.go +41 -0
- package/linthost/rules_unicorn_no_empty_file.go +44 -0
- package/linthost/rules_unicorn_no_for_loop.go +102 -0
- package/linthost/rules_unicorn_no_hex_escape.go +42 -0
- package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
- package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
- package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
- package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
- package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
- package/linthost/rules_unicorn_no_lonely_if.go +44 -0
- package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
- package/linthost/rules_unicorn_no_named_default.go +54 -0
- package/linthost/rules_unicorn_no_negated_condition.go +85 -0
- package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
- package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
- package/linthost/rules_unicorn_no_new_array.go +30 -0
- package/linthost/rules_unicorn_no_new_buffer.go +31 -0
- package/linthost/rules_unicorn_no_null.go +24 -0
- package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
- package/linthost/rules_unicorn_no_process_exit.go +43 -0
- package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
- package/linthost/rules_unicorn_no_static_only_class.go +56 -0
- package/linthost/rules_unicorn_no_thenable.go +74 -0
- package/linthost/rules_unicorn_no_this_assignment.go +35 -0
- package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
- package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
- package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
- package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
- package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
- package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
- package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
- package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
- package/linthost/rules_unicorn_no_unused_properties.go +30 -0
- package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
- package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
- package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
- package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
- package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
- package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
- package/linthost/rules_unicorn_no_useless_spread.go +67 -0
- package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
- package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
- package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
- package/linthost/rules_unicorn_number_literal_case.go +69 -0
- package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
- package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
- package/linthost/rules_unicorn_prefer_array_find.go +51 -0
- package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
- package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
- package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
- package/linthost/rules_unicorn_prefer_array_some.go +67 -0
- package/linthost/rules_unicorn_prefer_at.go +77 -0
- package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
- package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
- package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
- package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
- package/linthost/rules_unicorn_prefer_code_point.go +49 -0
- package/linthost/rules_unicorn_prefer_date_now.go +78 -0
- package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
- package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
- package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
- package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
- package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
- package/linthost/rules_unicorn_prefer_event_target.go +36 -0
- package/linthost/rules_unicorn_prefer_export_from.go +129 -0
- package/linthost/rules_unicorn_prefer_global_this.go +127 -0
- package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
- package/linthost/rules_unicorn_prefer_includes.go +149 -0
- package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
- package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
- package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
- package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
- package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
- package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
- package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
- package/linthost/rules_unicorn_prefer_module.go +50 -0
- package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
- package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
- package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
- package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
- package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
- package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
- package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
- package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
- package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
- package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
- package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
- package/linthost/rules_unicorn_prefer_set_has.go +42 -0
- package/linthost/rules_unicorn_prefer_set_size.go +48 -0
- package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
- package/linthost/rules_unicorn_prefer_single_call.go +96 -0
- package/linthost/rules_unicorn_prefer_spread.go +51 -0
- package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
- package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
- package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
- package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
- package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
- package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
- package/linthost/rules_unicorn_prefer_switch.go +103 -0
- package/linthost/rules_unicorn_prefer_ternary.go +71 -0
- package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
- package/linthost/rules_unicorn_prefer_type_error.go +127 -0
- package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
- package/linthost/rules_unicorn_relative_url_style.go +49 -0
- package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
- package/linthost/rules_unicorn_require_module_attributes.go +54 -0
- package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
- package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
- package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
- package/linthost/rules_unicorn_string_content.go +27 -0
- package/linthost/rules_unicorn_switch_case_braces.go +42 -0
- package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
- package/linthost/rules_unicorn_template_indent.go +28 -0
- package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
- package/linthost/rules_unicorn_throw_new_error.go +61 -0
- package/linthost/rules_var.go +4 -4
- package/linthost/rules_vitest.go +568 -0
- package/package.json +3 -3
- package/plugin/main.go +49 -3
- package/rule/astutil/astutil.go +10 -3
- package/rule/rule.go +12 -10
- package/src/defaultFormat.ts +11 -8
- package/src/index.ts +40 -16
- package/src/structures/ITtscLintConfig.ts +12 -6
- package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
- package/src/structures/TtscLintRuleSetting.ts +55 -0
- package/src/structures/index.ts +3 -4
- package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
- package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
- package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
- package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
- package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
- package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
- package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
- package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
- package/src/structures/rules/ITtscLintJestRules.ts +220 -0
- package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
- package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
- package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
- package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
- package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
- package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
- package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
- package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
- package/src/structures/rules/ITtscLintReactRules.ts +321 -0
- package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
- package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
- package/src/structures/rules/ITtscLintRules.ts +77 -0
- package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
- package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
- package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
- package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
- package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
- package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
- package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
- package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
- package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
- package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
- package/src/structures/rules/index.ts +31 -0
- package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
- package/lib/structures/TtscLintRule.d.ts +0 -17
- package/lib/structures/TtscLintRule.js.map +0 -1
- package/lib/structures/TtscLintRuleMap.d.ts +0 -46
- package/lib/structures/TtscLintRuleMap.js.map +0 -1
- package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
- package/lib/structures/TtscLintRuleOptions.js.map +0 -1
- package/src/structures/TtscLintRule.ts +0 -160
- package/src/structures/TtscLintRuleMap.ts +0 -55
- package/src/structures/TtscLintRuleOptions.ts +0 -151
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// unicorn/prefer-regexp-test: `if ("abc".match(/a/))` and
|
|
2
|
+
// `if (/a/.exec("abc"))` use match-array / null returns to encode a
|
|
3
|
+
// boolean question. `RegExp#test()` returns a boolean directly, avoids
|
|
4
|
+
// allocating the match result, and reads exactly like the question
|
|
5
|
+
// being asked.
|
|
6
|
+
//
|
|
7
|
+
// AST-only and parent-driven: visit each `CallExpression` whose callee
|
|
8
|
+
// is `PropertyAccess(_, match|exec)`, then confirm the call sits in a
|
|
9
|
+
// boolean position — the condition slot of `if`/`?:`, the operand of a
|
|
10
|
+
// unary `!`, or one of the short-circuit binary operators `&&`, `||`,
|
|
11
|
+
// `??`. Matches that aren't in a boolean position may still use the
|
|
12
|
+
// returned array, so they're out of scope.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-regexp-test.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornPreferRegexpTest struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornPreferRegexpTest) Name() string { return "unicorn/prefer-regexp-test" }
|
|
21
|
+
func (unicornPreferRegexpTest) Visits() []shimast.Kind {
|
|
22
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
23
|
+
}
|
|
24
|
+
func (unicornPreferRegexpTest) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
+
call := node.AsCallExpression()
|
|
26
|
+
if call == nil || call.Expression == nil ||
|
|
27
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
31
|
+
if access == nil {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
switch identifierText(access.Name()) {
|
|
35
|
+
case "match", "exec":
|
|
36
|
+
default:
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
if !unicornPreferRegexpTestInBooleanPosition(node) {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
ctx.Report(node, "Prefer `RegExp#test()` over `String#match()` / `RegExp#exec()` in a boolean context.")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// unicornPreferRegexpTestInBooleanPosition reports whether `node` sits in
|
|
46
|
+
// a position that consumes only its truthiness: the condition of an
|
|
47
|
+
// `if` / ternary, the operand of `!`, or one side of `&&` / `||` / `??`.
|
|
48
|
+
func unicornPreferRegexpTestInBooleanPosition(node *shimast.Node) bool {
|
|
49
|
+
parent := node.Parent
|
|
50
|
+
if parent == nil {
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
switch parent.Kind {
|
|
54
|
+
case shimast.KindIfStatement:
|
|
55
|
+
ifStmt := parent.AsIfStatement()
|
|
56
|
+
return ifStmt != nil && ifStmt.Expression == node
|
|
57
|
+
case shimast.KindConditionalExpression:
|
|
58
|
+
cond := parent.AsConditionalExpression()
|
|
59
|
+
return cond != nil && cond.Condition == node
|
|
60
|
+
case shimast.KindPrefixUnaryExpression:
|
|
61
|
+
pre := parent.AsPrefixUnaryExpression()
|
|
62
|
+
return pre != nil && pre.Operator == shimast.KindExclamationToken
|
|
63
|
+
case shimast.KindBinaryExpression:
|
|
64
|
+
bin := parent.AsBinaryExpression()
|
|
65
|
+
if bin == nil || bin.OperatorToken == nil {
|
|
66
|
+
return false
|
|
67
|
+
}
|
|
68
|
+
switch bin.OperatorToken.Kind {
|
|
69
|
+
case shimast.KindAmpersandAmpersandToken,
|
|
70
|
+
shimast.KindBarBarToken,
|
|
71
|
+
shimast.KindQuestionQuestionToken:
|
|
72
|
+
return true
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
func init() {
|
|
79
|
+
Register(unicornPreferRegexpTest{})
|
|
80
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// unicorn/prefer-response-static-json: `new Response(JSON.stringify(value), …)`
|
|
2
|
+
// is the manual two-step recipe — stringify then construct — that the
|
|
3
|
+
// platform's `Response.json(value, …)` static factory now performs in
|
|
4
|
+
// one call. The static factory also sets `Content-Type: application/json`
|
|
5
|
+
// automatically; the manual form leaves the header to the author.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit each `NewExpression`. Match when the callee identifier
|
|
8
|
+
// is `Response` AND the first argument is a `CallExpression` whose
|
|
9
|
+
// callee is the property chain `JSON.stringify`. Other arguments (init
|
|
10
|
+
// options) are intentionally not inspected — the rule fires regardless
|
|
11
|
+
// of headers/status because the simpler factory handles both shapes.
|
|
12
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-response-static-json.md
|
|
13
|
+
package linthost
|
|
14
|
+
|
|
15
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
|
+
|
|
17
|
+
type unicornPreferResponseStaticJson struct{}
|
|
18
|
+
|
|
19
|
+
func (unicornPreferResponseStaticJson) Name() string {
|
|
20
|
+
return "unicorn/prefer-response-static-json"
|
|
21
|
+
}
|
|
22
|
+
func (unicornPreferResponseStaticJson) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{shimast.KindNewExpression}
|
|
24
|
+
}
|
|
25
|
+
func (unicornPreferResponseStaticJson) Check(ctx *Context, node *shimast.Node) {
|
|
26
|
+
ne := node.AsNewExpression()
|
|
27
|
+
if ne == nil || identifierText(ne.Expression) != "Response" {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
if ne.Arguments == nil || len(ne.Arguments.Nodes) == 0 {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
first := stripParens(ne.Arguments.Nodes[0])
|
|
34
|
+
if first == nil || first.Kind != shimast.KindCallExpression {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
call := first.AsCallExpression()
|
|
38
|
+
if call == nil || call.Expression == nil ||
|
|
39
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
43
|
+
if access == nil ||
|
|
44
|
+
identifierText(access.Expression) != "JSON" ||
|
|
45
|
+
identifierText(access.Name()) != "stringify" {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
ctx.Report(node, "Prefer `Response.json(value)` over `new Response(JSON.stringify(value), ...)`.")
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
func init() {
|
|
52
|
+
Register(unicornPreferResponseStaticJson{})
|
|
53
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// unicorn/prefer-set-has: `[a, b, c].includes(x)` is `O(n)` per lookup,
|
|
2
|
+
// while `new Set([a, b, c]).has(x)` is `O(1)` after a single `O(n)`
|
|
3
|
+
// construction. For repeated membership lookups against a fixed
|
|
4
|
+
// collection the `Set` form is meaningfully faster and clearer about
|
|
5
|
+
// intent.
|
|
6
|
+
//
|
|
7
|
+
// AST-only minimum-viable port: only the literal-array-receiver shape
|
|
8
|
+
// (`[…].includes(x)`) is reported. The upstream rule also reasons
|
|
9
|
+
// about typed variable receivers, which requires type-flow analysis
|
|
10
|
+
// out of scope for this slice; expanding to typed receivers is a
|
|
11
|
+
// follow-up.
|
|
12
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-set-has.md
|
|
13
|
+
package linthost
|
|
14
|
+
|
|
15
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
|
+
|
|
17
|
+
type unicornPreferSetHas struct{}
|
|
18
|
+
|
|
19
|
+
func (unicornPreferSetHas) Name() string { return "unicorn/prefer-set-has" }
|
|
20
|
+
func (unicornPreferSetHas) Visits() []shimast.Kind {
|
|
21
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
22
|
+
}
|
|
23
|
+
func (unicornPreferSetHas) Check(ctx *Context, node *shimast.Node) {
|
|
24
|
+
call := node.AsCallExpression()
|
|
25
|
+
if call == nil || call.Expression == nil ||
|
|
26
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
30
|
+
if access == nil || identifierText(access.Name()) != "includes" {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
receiver := stripParens(access.Expression)
|
|
34
|
+
if receiver == nil || receiver.Kind != shimast.KindArrayLiteralExpression {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
ctx.Report(node, "Prefer `Set#has()` over `Array#includes()` for repeated membership lookups against a constant collection.")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func init() {
|
|
41
|
+
Register(unicornPreferSetHas{})
|
|
42
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// unicorn/prefer-set-size: `[...set].length` materializes the entire Set
|
|
2
|
+
// into a throwaway array just to read its element count. `Set#size` is a
|
|
3
|
+
// constant-time property that returns the same value without the
|
|
4
|
+
// allocation, and reads more naturally for the intent the code expresses.
|
|
5
|
+
//
|
|
6
|
+
// AST-only: visit each `PropertyAccessExpression`, match when the
|
|
7
|
+
// accessed property is named `length` AND the receiver is an
|
|
8
|
+
// array-literal expression whose only element is a SpreadElement (i.e.
|
|
9
|
+
// `[...x]`). The contents of the spread are not inspected — the
|
|
10
|
+
// syntactic shape `[...x].length` is the signal regardless of whether
|
|
11
|
+
// the spread source is statically a Set.
|
|
12
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-set-size.md
|
|
13
|
+
package linthost
|
|
14
|
+
|
|
15
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
|
+
|
|
17
|
+
type unicornPreferSetSize struct{}
|
|
18
|
+
|
|
19
|
+
func (unicornPreferSetSize) Name() string { return "unicorn/prefer-set-size" }
|
|
20
|
+
func (unicornPreferSetSize) Visits() []shimast.Kind {
|
|
21
|
+
return []shimast.Kind{shimast.KindPropertyAccessExpression}
|
|
22
|
+
}
|
|
23
|
+
func (unicornPreferSetSize) Check(ctx *Context, node *shimast.Node) {
|
|
24
|
+
access := node.AsPropertyAccessExpression()
|
|
25
|
+
if access == nil {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
if identifierText(access.Name()) != "length" {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
receiver := stripParens(access.Expression)
|
|
32
|
+
if receiver == nil || receiver.Kind != shimast.KindArrayLiteralExpression {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
arr := receiver.AsArrayLiteralExpression()
|
|
36
|
+
if arr == nil || arr.Elements == nil || len(arr.Elements.Nodes) != 1 {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
only := arr.Elements.Nodes[0]
|
|
40
|
+
if only == nil || only.Kind != shimast.KindSpreadElement {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
ctx.Report(node, "Prefer `Set#size` over `[...set].length`.")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func init() {
|
|
47
|
+
Register(unicornPreferSetSize{})
|
|
48
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// unicorn/prefer-simple-condition-first: when a `&&`/`||` chain mixes
|
|
2
|
+
// a "simple" operand (a bare identifier, a small literal comparison)
|
|
3
|
+
// with a "complex" one (a function call, a property chain), short-
|
|
4
|
+
// circuit evaluation reads more naturally if the simple operand sits
|
|
5
|
+
// to the left — the cheap test is the gate, the expensive test runs
|
|
6
|
+
// only if the gate passes.
|
|
7
|
+
//
|
|
8
|
+
// Escape-hatch / no-op port: ranking arbitrary expressions by
|
|
9
|
+
// "simpleness" requires a stable complexity heuristic the upstream rule
|
|
10
|
+
// embeds across hundreds of lines (literal counts, identifier depth,
|
|
11
|
+
// call-chain weight, parenthesization). Without a faithful port of that
|
|
12
|
+
// heuristic the rule would either over-fire on equally-weighted operands
|
|
13
|
+
// or under-fire on the cases it is meant to catch; either way users get
|
|
14
|
+
// confusing diagnostics. Registered so the typed-key/Go-registry parity
|
|
15
|
+
// check passes and so users can configure the rule, but it intentionally
|
|
16
|
+
// reports nothing until the heuristic lands in a follow-up.
|
|
17
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-simple-condition-first.md
|
|
18
|
+
package linthost
|
|
19
|
+
|
|
20
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
21
|
+
|
|
22
|
+
type unicornPreferSimpleConditionFirst struct{}
|
|
23
|
+
|
|
24
|
+
func (unicornPreferSimpleConditionFirst) Name() string {
|
|
25
|
+
return "unicorn/prefer-simple-condition-first"
|
|
26
|
+
}
|
|
27
|
+
func (unicornPreferSimpleConditionFirst) Visits() []shimast.Kind { return nil }
|
|
28
|
+
func (unicornPreferSimpleConditionFirst) Check(_ *Context, _ *shimast.Node) {
|
|
29
|
+
// Intentionally empty — see file header for the escape-hatch rationale.
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func init() {
|
|
33
|
+
Register(unicornPreferSimpleConditionFirst{})
|
|
34
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// unicorn/prefer-single-call: `xs.push(1); xs.push(2);` repeats the
|
|
2
|
+
// `xs.push` lookup and the call dispatch for what is conceptually one
|
|
3
|
+
// "append these values" operation. Variadic methods like `push`,
|
|
4
|
+
// `unshift`, `addEventListener`, and `removeEventListener` accept
|
|
5
|
+
// multiple arguments specifically so authors can collapse the back-to-
|
|
6
|
+
// back form into a single call.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: visit each `Block` AND `SourceFile`, scan the statement
|
|
9
|
+
// list for any pair of consecutive `ExpressionStatement`s whose
|
|
10
|
+
// expressions are `CallExpression`s targeting
|
|
11
|
+
// `PropertyAccess(<sameReceiverText>, <sameMethod>)` where the method
|
|
12
|
+
// is one of the variadic appenders. Receiver equivalence is decided
|
|
13
|
+
// by source-text comparison so chained receivers (e.g. `obj.list.push`)
|
|
14
|
+
// line up exactly. Report on the second statement so the diagnostic
|
|
15
|
+
// anchors to the redundant call.
|
|
16
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-single-call.md
|
|
17
|
+
package linthost
|
|
18
|
+
|
|
19
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
20
|
+
|
|
21
|
+
type unicornPreferSingleCall struct{}
|
|
22
|
+
|
|
23
|
+
func (unicornPreferSingleCall) Name() string { return "unicorn/prefer-single-call" }
|
|
24
|
+
func (unicornPreferSingleCall) Visits() []shimast.Kind {
|
|
25
|
+
return []shimast.Kind{shimast.KindBlock, shimast.KindSourceFile}
|
|
26
|
+
}
|
|
27
|
+
func (unicornPreferSingleCall) Check(ctx *Context, node *shimast.Node) {
|
|
28
|
+
var stmts []*shimast.Node
|
|
29
|
+
switch node.Kind {
|
|
30
|
+
case shimast.KindBlock:
|
|
31
|
+
block := node.AsBlock()
|
|
32
|
+
if block == nil || block.Statements == nil {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
stmts = block.Statements.Nodes
|
|
36
|
+
case shimast.KindSourceFile:
|
|
37
|
+
file := node.AsSourceFile()
|
|
38
|
+
if file == nil || file.Statements == nil {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
stmts = file.Statements.Nodes
|
|
42
|
+
default:
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
for i := 1; i < len(stmts); i++ {
|
|
46
|
+
prevReceiver, prevMethod := unicornPreferSingleCallExtract(ctx, stmts[i-1])
|
|
47
|
+
if prevReceiver == "" {
|
|
48
|
+
continue
|
|
49
|
+
}
|
|
50
|
+
currReceiver, currMethod := unicornPreferSingleCallExtract(ctx, stmts[i])
|
|
51
|
+
if currReceiver == "" {
|
|
52
|
+
continue
|
|
53
|
+
}
|
|
54
|
+
if prevReceiver != currReceiver || prevMethod != currMethod {
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
ctx.Report(stmts[i], "Combine consecutive `"+currMethod+"` calls with multiple arguments into a single call.")
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// unicornPreferSingleCallExtract returns (receiverText, methodName) for a
|
|
62
|
+
// statement of the shape `<receiver>.<method>(…);` where `method` is one
|
|
63
|
+
// of the variadic appenders the rule targets. Returns ("", "") for any
|
|
64
|
+
// other shape.
|
|
65
|
+
func unicornPreferSingleCallExtract(ctx *Context, stmt *shimast.Node) (string, string) {
|
|
66
|
+
if stmt == nil || stmt.Kind != shimast.KindExpressionStatement {
|
|
67
|
+
return "", ""
|
|
68
|
+
}
|
|
69
|
+
exprStmt := stmt.AsExpressionStatement()
|
|
70
|
+
if exprStmt == nil || exprStmt.Expression == nil {
|
|
71
|
+
return "", ""
|
|
72
|
+
}
|
|
73
|
+
call := stripParens(exprStmt.Expression)
|
|
74
|
+
if call == nil || call.Kind != shimast.KindCallExpression {
|
|
75
|
+
return "", ""
|
|
76
|
+
}
|
|
77
|
+
c := call.AsCallExpression()
|
|
78
|
+
if c == nil || c.Expression == nil || c.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
79
|
+
return "", ""
|
|
80
|
+
}
|
|
81
|
+
access := c.Expression.AsPropertyAccessExpression()
|
|
82
|
+
if access == nil || access.Expression == nil {
|
|
83
|
+
return "", ""
|
|
84
|
+
}
|
|
85
|
+
method := identifierText(access.Name())
|
|
86
|
+
switch method {
|
|
87
|
+
case "push", "unshift", "addEventListener", "removeEventListener":
|
|
88
|
+
default:
|
|
89
|
+
return "", ""
|
|
90
|
+
}
|
|
91
|
+
return nodeText(ctx.File, access.Expression), method
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
func init() {
|
|
95
|
+
Register(unicornPreferSingleCall{})
|
|
96
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// unicorn/prefer-spread: `Array.from(x)` with a single iterable argument
|
|
2
|
+
// is equivalent to a spread copy `[...x]`. The spread form is shorter,
|
|
3
|
+
// reads as a value-level operation rather than a constructor call, and
|
|
4
|
+
// removes the `Array` global from the read path entirely.
|
|
5
|
+
//
|
|
6
|
+
// AST-only: visit each `CallExpression`, match `Array.from(x)` — a
|
|
7
|
+
// callee that is a property access reading `from` on a bare identifier
|
|
8
|
+
// `Array`, with exactly one argument. The single-argument restriction
|
|
9
|
+
// is load-bearing: `Array.from(x, mapFn)` and `Array.from(x, mapFn,
|
|
10
|
+
// thisArg)` have observable behavior the spread does not (the mapper
|
|
11
|
+
// receives the index, and `thisArg` is bound on a non-arrow mapper), so
|
|
12
|
+
// the rule deliberately stays away from them.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-spread.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornPreferSpread struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornPreferSpread) Name() string { return "unicorn/prefer-spread" }
|
|
21
|
+
func (unicornPreferSpread) Visits() []shimast.Kind {
|
|
22
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
23
|
+
}
|
|
24
|
+
func (unicornPreferSpread) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
+
call := node.AsCallExpression()
|
|
26
|
+
if call == nil || call.Expression == nil {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
if call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
33
|
+
if access == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
if identifierText(access.Name()) != "from" {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
receiver := stripParens(access.Expression)
|
|
40
|
+
if identifierText(receiver) != "Array" {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
ctx.Report(node, "Prefer spread `[...x]` over `Array.from(x)` for single-arg shallow copies.")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
func init() {
|
|
50
|
+
Register(unicornPreferSpread{})
|
|
51
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// unicorn/prefer-string-raw: a string literal whose source contains
|
|
2
|
+
// `\\` (an escaped backslash) is using the escape syntax to represent a
|
|
3
|
+
// literal backslash. The same value, written through `String.raw` as
|
|
4
|
+
// a template literal, drops every backslash escape and reads as the
|
|
5
|
+
// literal text the author meant — particularly noticeable for Windows
|
|
6
|
+
// paths, regex source strings, and TeX-shaped snippets.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: visit `KindStringLiteral` and
|
|
9
|
+
// `KindNoSubstitutionTemplateLiteral`. The match keys on the raw source
|
|
10
|
+
// bytes of the literal node — `nodeText` returns the as-written source
|
|
11
|
+
// — and fires when those bytes contain the two-character sequence `\\`,
|
|
12
|
+
// i.e. an escaped backslash that `String.raw` would render literally.
|
|
13
|
+
// Untagged template literals with substitutions are out of scope; this
|
|
14
|
+
// rule only addresses the "single literal of fixed text" case.
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-raw.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import (
|
|
19
|
+
"strings"
|
|
20
|
+
|
|
21
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
type unicornPreferStringRaw struct{}
|
|
25
|
+
|
|
26
|
+
func (unicornPreferStringRaw) Name() string { return "unicorn/prefer-string-raw" }
|
|
27
|
+
func (unicornPreferStringRaw) Visits() []shimast.Kind {
|
|
28
|
+
return []shimast.Kind{shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral}
|
|
29
|
+
}
|
|
30
|
+
func (unicornPreferStringRaw) Check(ctx *Context, node *shimast.Node) {
|
|
31
|
+
raw := nodeText(ctx.File, node)
|
|
32
|
+
if raw == "" {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
if !strings.Contains(raw, `\\`) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
ctx.Report(node, "Prefer `String.raw` for strings with backslash escapes.")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func init() {
|
|
42
|
+
Register(unicornPreferStringRaw{})
|
|
43
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// unicorn/prefer-string-replace-all: `"abc".replace(/a/g, "x")` is the
|
|
2
|
+
// pre-ES2021 idiom for "replace every occurrence". ES2021's
|
|
3
|
+
// `String#replaceAll` does the same thing without the regex flag
|
|
4
|
+
// detour. The rule fires on `.replace(/<pattern>/g, replacement)` so
|
|
5
|
+
// authors switch to the explicit method.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: a `CallExpression` whose callee is `.replace` AND whose
|
|
8
|
+
// first argument is a `RegularExpressionLiteral` carrying the `g` flag
|
|
9
|
+
// in its trailing flag block matches. The flag is read from the raw
|
|
10
|
+
// source text — the AST does not split pattern from flags — using the
|
|
11
|
+
// shared `nodeText` accessor.
|
|
12
|
+
//
|
|
13
|
+
// To preserve semantics, the pattern body must also be literal — any
|
|
14
|
+
// regex metacharacter (`\`, `.`, `*`, `+`, `?`, `[`, `]`, `(`, `)`,
|
|
15
|
+
// `{`, `}`, `|`, `^`, `$`) disqualifies the rewrite, because
|
|
16
|
+
// `/<pat>/g` and `.replaceAll(<pat>, ...)` mean different things when
|
|
17
|
+
// the pattern is anything but a fixed string.
|
|
18
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-replace-all.md
|
|
19
|
+
package linthost
|
|
20
|
+
|
|
21
|
+
import (
|
|
22
|
+
"strings"
|
|
23
|
+
|
|
24
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
type unicornPreferStringReplaceAll struct{}
|
|
28
|
+
|
|
29
|
+
func (unicornPreferStringReplaceAll) Name() string { return "unicorn/prefer-string-replace-all" }
|
|
30
|
+
func (unicornPreferStringReplaceAll) Visits() []shimast.Kind {
|
|
31
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
32
|
+
}
|
|
33
|
+
func (unicornPreferStringReplaceAll) Check(ctx *Context, node *shimast.Node) {
|
|
34
|
+
call := node.AsCallExpression()
|
|
35
|
+
if call == nil || call.Expression == nil ||
|
|
36
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
40
|
+
if access == nil || identifierText(access.Name()) != "replace" {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) < 1 {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
first := stripParens(call.Arguments.Nodes[0])
|
|
47
|
+
if first == nil || first.Kind != shimast.KindRegularExpressionLiteral {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
raw := nodeText(ctx.File, first)
|
|
51
|
+
if !unicornPreferStringReplaceAllHasGlobalFlag(raw) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
if !unicornPreferStringReplaceAllIsLiteralPattern(raw) {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
ctx.Report(node, "Prefer `String#replaceAll(literal, replacement)` over `replace(/literal/g, replacement)`.")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// unicornPreferStringReplaceAllHasGlobalFlag returns true when `raw` (the
|
|
61
|
+
// source text of a RegularExpressionLiteral, including the surrounding
|
|
62
|
+
// `/` delimiters and trailing flag block) carries the `g` flag.
|
|
63
|
+
func unicornPreferStringReplaceAllHasGlobalFlag(raw string) bool {
|
|
64
|
+
if len(raw) < 3 || raw[0] != '/' {
|
|
65
|
+
return false
|
|
66
|
+
}
|
|
67
|
+
closing := strings.LastIndexByte(raw, '/')
|
|
68
|
+
if closing <= 0 {
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
flags := raw[closing+1:]
|
|
72
|
+
return strings.ContainsRune(flags, 'g')
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// unicornPreferStringReplaceAllIsLiteralPattern returns true when the
|
|
76
|
+
// pattern body of `raw` (the source text of a RegularExpressionLiteral)
|
|
77
|
+
// contains no regex metacharacters. Conservative: any metachar — even
|
|
78
|
+
// an escaped one like `\.` — disqualifies the rewrite, because
|
|
79
|
+
// recovering the original character cleanly from raw source requires
|
|
80
|
+
// regex-aware parsing we don't do here.
|
|
81
|
+
func unicornPreferStringReplaceAllIsLiteralPattern(raw string) bool {
|
|
82
|
+
if len(raw) < 3 || raw[0] != '/' {
|
|
83
|
+
return false
|
|
84
|
+
}
|
|
85
|
+
closing := strings.LastIndexByte(raw, '/')
|
|
86
|
+
if closing <= 0 {
|
|
87
|
+
return false
|
|
88
|
+
}
|
|
89
|
+
body := raw[1:closing]
|
|
90
|
+
return !strings.ContainsAny(body, `\.*+?[](){}|^$`)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
func init() {
|
|
94
|
+
Register(unicornPreferStringReplaceAll{})
|
|
95
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// unicorn/prefer-string-slice: `String#substr` is deprecated and
|
|
2
|
+
// `String#substring` has surprising "swap arguments when end < start"
|
|
3
|
+
// semantics. `String#slice` is the single modern alternative whose
|
|
4
|
+
// behavior matches author intent. The rule fires on any `.substr(…)`
|
|
5
|
+
// or `.substring(…)` callsite so the codebase converges on `.slice`.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: a `CallExpression` whose callee is a
|
|
8
|
+
// `PropertyAccessExpression` ending in `substr` or `substring`
|
|
9
|
+
// matches. Receiver typing is intentionally not checked — both names
|
|
10
|
+
// exist almost exclusively on strings in real code, and the
|
|
11
|
+
// upstream rule treats them as banned regardless.
|
|
12
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-slice.md
|
|
13
|
+
package linthost
|
|
14
|
+
|
|
15
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
|
+
|
|
17
|
+
type unicornPreferStringSlice struct{}
|
|
18
|
+
|
|
19
|
+
func (unicornPreferStringSlice) Name() string { return "unicorn/prefer-string-slice" }
|
|
20
|
+
func (unicornPreferStringSlice) Visits() []shimast.Kind {
|
|
21
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
22
|
+
}
|
|
23
|
+
func (unicornPreferStringSlice) Check(ctx *Context, node *shimast.Node) {
|
|
24
|
+
call := node.AsCallExpression()
|
|
25
|
+
if call == nil || call.Expression == nil ||
|
|
26
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
30
|
+
if access == nil {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
switch identifierText(access.Name()) {
|
|
34
|
+
case "substr", "substring":
|
|
35
|
+
default:
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
ctx.Report(node, "Prefer `String#slice()` over `substr` / `substring`.")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func init() {
|
|
42
|
+
Register(unicornPreferStringSlice{})
|
|
43
|
+
}
|