@ttsc/lint 0.13.0 → 0.14.0-dev.20260528
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 +60 -37
- 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/compile.go +33 -2
- 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 +160 -40
- package/linthost/fix.go +2 -2
- package/linthost/flags_gen.go +17 -15
- package/linthost/host.go +40 -3
- 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 +10 -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 +65 -43
- 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,50 @@
|
|
|
1
|
+
// unicorn/no-unreadable-iife: an IIFE whose body is itself another
|
|
2
|
+
// call expression — `(() => f())()` — reads as two layers of
|
|
3
|
+
// invocation for one effective call. The shape obscures the actual
|
|
4
|
+
// computation and the rule asks authors to extract the call site so
|
|
5
|
+
// the inner function name appears at the top level instead of being
|
|
6
|
+
// hidden behind an anonymous arrow.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: visit `KindCallExpression`, accept when the callee is a
|
|
9
|
+
// `KindParenthesizedExpression` wrapping a `KindArrowFunction` whose
|
|
10
|
+
// body is a `KindCallExpression`. Block-bodied arrows and arrows that
|
|
11
|
+
// return a non-call expression don't match — only the arrow → call
|
|
12
|
+
// shape is "unreadable" in the upstream sense.
|
|
13
|
+
//
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-unreadable-iife.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornNoUnreadableIIFE struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornNoUnreadableIIFE) Name() string { return "unicorn/no-unreadable-iife" }
|
|
22
|
+
func (unicornNoUnreadableIIFE) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
24
|
+
}
|
|
25
|
+
func (unicornNoUnreadableIIFE) Check(ctx *Context, node *shimast.Node) {
|
|
26
|
+
call := node.AsCallExpression()
|
|
27
|
+
if call == nil || call.Expression == nil {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
if call.Expression.Kind != shimast.KindParenthesizedExpression {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
paren := call.Expression.AsParenthesizedExpression()
|
|
34
|
+
if paren == nil || paren.Expression == nil ||
|
|
35
|
+
paren.Expression.Kind != shimast.KindArrowFunction {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
arrow := paren.Expression.AsArrowFunction()
|
|
39
|
+
if arrow == nil || arrow.Body == nil {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
if arrow.Body.Kind != shimast.KindCallExpression {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
ctx.Report(node, "Avoid unreadable IIFEs — extract the function.")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
func init() {
|
|
49
|
+
Register(unicornNoUnreadableIIFE{})
|
|
50
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// unicorn/no-unused-properties: flags object-literal properties that
|
|
2
|
+
// are never read after the object is constructed. The signal is "this
|
|
3
|
+
// key sits in a literal that nothing reaches into" — analogous to
|
|
4
|
+
// `no-unused-vars` but for one level deeper inside object data.
|
|
5
|
+
//
|
|
6
|
+
// Escape-hatch / no-op port: implementing this faithfully requires
|
|
7
|
+
// per-object reachability and read tracking across the file (and across
|
|
8
|
+
// destructuring patterns, spread, computed access, and exports). That
|
|
9
|
+
// is a scope-and-flow problem the AST-only engine in this package
|
|
10
|
+
// cannot yet model without false positives every time a property is
|
|
11
|
+
// read through dynamic access. Registered so the typed-key/Go-registry
|
|
12
|
+
// parity check passes and so users can configure the rule, but it
|
|
13
|
+
// intentionally reports nothing until the analysis lands in a
|
|
14
|
+
// follow-up.
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-unused-properties.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
|
|
20
|
+
type unicornNoUnusedProperties struct{}
|
|
21
|
+
|
|
22
|
+
func (unicornNoUnusedProperties) Name() string { return "unicorn/no-unused-properties" }
|
|
23
|
+
func (unicornNoUnusedProperties) Visits() []shimast.Kind { return nil }
|
|
24
|
+
func (unicornNoUnusedProperties) Check(_ *Context, _ *shimast.Node) {
|
|
25
|
+
// Intentionally empty — see file header for the escape-hatch rationale.
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
func init() {
|
|
29
|
+
Register(unicornNoUnusedProperties{})
|
|
30
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// unicorn/no-useless-collection-argument: `new Set()`, `new Map()`,
|
|
2
|
+
// `new WeakSet()`, and `new WeakMap()` already start empty. Passing an
|
|
3
|
+
// explicit `null`, `undefined`, or `[]` reads as if the author meant to
|
|
4
|
+
// seed the collection with entries but came up empty — it adds noise
|
|
5
|
+
// without changing behavior. Zero-argument calls are the canonical
|
|
6
|
+
// correct form and are NOT flagged.
|
|
7
|
+
//
|
|
8
|
+
// AST-only and identifier-text-driven: visit every `NewExpression`
|
|
9
|
+
// whose callee identifier is one of the four collection constructors,
|
|
10
|
+
// then match a single argument that is a `null`/`undefined` literal,
|
|
11
|
+
// an `undefined` identifier, or an empty array literal. The receiver
|
|
12
|
+
// chain is not inspected; shadowed `Set`/`Map` bindings are out of
|
|
13
|
+
// scope, mirroring the other constructor-name-only unicorn rules.
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-collection-argument.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornNoUselessCollectionArgument struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornNoUselessCollectionArgument) Name() string {
|
|
22
|
+
return "unicorn/no-useless-collection-argument"
|
|
23
|
+
}
|
|
24
|
+
func (unicornNoUselessCollectionArgument) Visits() []shimast.Kind {
|
|
25
|
+
return []shimast.Kind{shimast.KindNewExpression}
|
|
26
|
+
}
|
|
27
|
+
func (unicornNoUselessCollectionArgument) Check(ctx *Context, node *shimast.Node) {
|
|
28
|
+
ne := node.AsNewExpression()
|
|
29
|
+
if ne == nil {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
switch identifierText(ne.Expression) {
|
|
33
|
+
case "Set", "Map", "WeakSet", "WeakMap":
|
|
34
|
+
default:
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
if ne.Arguments == nil || len(ne.Arguments.Nodes) != 1 {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
arg := stripParens(ne.Arguments.Nodes[0])
|
|
41
|
+
if arg == nil {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
switch arg.Kind {
|
|
45
|
+
case shimast.KindNullKeyword, shimast.KindUndefinedKeyword:
|
|
46
|
+
ctx.Report(node, "Don't pass a useless initializer to `new <Collection>()`.")
|
|
47
|
+
return
|
|
48
|
+
case shimast.KindIdentifier:
|
|
49
|
+
if identifierText(arg) == "undefined" {
|
|
50
|
+
ctx.Report(node, "Don't pass a useless initializer to `new <Collection>()`.")
|
|
51
|
+
}
|
|
52
|
+
return
|
|
53
|
+
case shimast.KindArrayLiteralExpression:
|
|
54
|
+
if arr := arg.AsArrayLiteralExpression(); arr != nil &&
|
|
55
|
+
(arr.Elements == nil || len(arr.Elements.Nodes) == 0) {
|
|
56
|
+
ctx.Report(node, "Don't pass a useless initializer to `new <Collection>()`.")
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
func init() {
|
|
62
|
+
Register(unicornNoUselessCollectionArgument{})
|
|
63
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// unicorn/no-useless-error-capture-stack-trace: `new Error()` already
|
|
2
|
+
// captures a stack trace by default, so calling
|
|
3
|
+
// `Error.captureStackTrace(this, …)` inside an Error-subclass
|
|
4
|
+
// constructor just rebuilds the same trace and adds noise without
|
|
5
|
+
// changing behavior. The rule flags the redundant call.
|
|
6
|
+
//
|
|
7
|
+
// AST-only MVP: visit each `CallExpression`, match when the callee is
|
|
8
|
+
// `Error.captureStackTrace` and the first argument is the `this`
|
|
9
|
+
// keyword. Detecting "inside an Error subclass constructor" is left to
|
|
10
|
+
// a future iteration — the MVP covers the common shape directly and is
|
|
11
|
+
// safe because `Error.captureStackTrace(this, …)` is uniformly useless
|
|
12
|
+
// inside subclasses anyway.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-error-capture-stack-trace.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornNoUselessErrorCaptureStackTrace struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornNoUselessErrorCaptureStackTrace) Name() string {
|
|
21
|
+
return "unicorn/no-useless-error-capture-stack-trace"
|
|
22
|
+
}
|
|
23
|
+
func (unicornNoUselessErrorCaptureStackTrace) Visits() []shimast.Kind {
|
|
24
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
25
|
+
}
|
|
26
|
+
func (unicornNoUselessErrorCaptureStackTrace) Check(ctx *Context, node *shimast.Node) {
|
|
27
|
+
call := node.AsCallExpression()
|
|
28
|
+
if call == nil || call.Expression == nil {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
if !isMatchingPropertyAccess(call.Expression, "Error", "captureStackTrace") {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) < 1 {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
first := stripParens(call.Arguments.Nodes[0])
|
|
38
|
+
if first == nil || first.Kind != shimast.KindThisKeyword {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
ctx.Report(node, "Don't call `Error.captureStackTrace(this, ...)` in an `Error` subclass — the default capture already happens.")
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func init() {
|
|
45
|
+
Register(unicornNoUselessErrorCaptureStackTrace{})
|
|
46
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// unicorn/no-useless-fallback-in-spread: spreading `null` or `undefined`
|
|
2
|
+
// into an object literal is already a runtime no-op, so the common
|
|
3
|
+
// defensive shape `...(x ?? {})` adds an allocation and a comparison
|
|
4
|
+
// that change nothing. The same goes for `...(x || {})` and the
|
|
5
|
+
// array-literal variants. Drop the fallback and spread the value
|
|
6
|
+
// directly.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: visit each spread node — `SpreadElement` only when its
|
|
9
|
+
// parent is an `ArrayLiteralExpression` (call-argument spread is
|
|
10
|
+
// excluded because spreading `null` / `undefined` into a function call
|
|
11
|
+
// throws a `TypeError`, so the fallback is load-bearing there) and
|
|
12
|
+
// `SpreadAssignment` for object spread. After stripping parentheses,
|
|
13
|
+
// the spread's operand must be a binary expression using `??` or `||`
|
|
14
|
+
// whose right-hand side is an empty object or array literal. The
|
|
15
|
+
// diagnostic anchors on the spread node so editors highlight the
|
|
16
|
+
// redundant fallback together with its `...`.
|
|
17
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-fallback-in-spread.md
|
|
18
|
+
package linthost
|
|
19
|
+
|
|
20
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
21
|
+
|
|
22
|
+
type unicornNoUselessFallbackInSpread struct{}
|
|
23
|
+
|
|
24
|
+
func (unicornNoUselessFallbackInSpread) Name() string {
|
|
25
|
+
return "unicorn/no-useless-fallback-in-spread"
|
|
26
|
+
}
|
|
27
|
+
func (unicornNoUselessFallbackInSpread) Visits() []shimast.Kind {
|
|
28
|
+
return []shimast.Kind{shimast.KindSpreadElement, shimast.KindSpreadAssignment}
|
|
29
|
+
}
|
|
30
|
+
func (unicornNoUselessFallbackInSpread) Check(ctx *Context, node *shimast.Node) {
|
|
31
|
+
var operand *shimast.Node
|
|
32
|
+
switch node.Kind {
|
|
33
|
+
case shimast.KindSpreadElement:
|
|
34
|
+
// Only flag array-literal spread. Call-argument spread of a
|
|
35
|
+
// null/undefined operand throws TypeError at runtime, so the
|
|
36
|
+
// `?? []` / `|| []` fallback is load-bearing in that position.
|
|
37
|
+
if node.Parent == nil || node.Parent.Kind != shimast.KindArrayLiteralExpression {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
if spread := node.AsSpreadElement(); spread != nil {
|
|
41
|
+
operand = spread.Expression
|
|
42
|
+
}
|
|
43
|
+
case shimast.KindSpreadAssignment:
|
|
44
|
+
if spread := node.AsSpreadAssignment(); spread != nil {
|
|
45
|
+
operand = spread.Expression
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
inner := stripParens(operand)
|
|
49
|
+
if inner == nil || inner.Kind != shimast.KindBinaryExpression {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
bin := inner.AsBinaryExpression()
|
|
53
|
+
if bin == nil || bin.OperatorToken == nil {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
switch bin.OperatorToken.Kind {
|
|
57
|
+
case shimast.KindQuestionQuestionToken, shimast.KindBarBarToken:
|
|
58
|
+
default:
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
right := stripParens(bin.Right)
|
|
62
|
+
if right == nil {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
switch right.Kind {
|
|
66
|
+
case shimast.KindObjectLiteralExpression:
|
|
67
|
+
if obj := right.AsObjectLiteralExpression(); obj != nil &&
|
|
68
|
+
(obj.Properties == nil || len(obj.Properties.Nodes) == 0) {
|
|
69
|
+
ctx.Report(node, "Don't use a useless `?? {}` or `?? []` fallback when spreading — `...null` and `...undefined` are no-ops.")
|
|
70
|
+
}
|
|
71
|
+
case shimast.KindArrayLiteralExpression:
|
|
72
|
+
if arr := right.AsArrayLiteralExpression(); arr != nil &&
|
|
73
|
+
(arr.Elements == nil || len(arr.Elements.Nodes) == 0) {
|
|
74
|
+
ctx.Report(node, "Don't use a useless `?? {}` or `?? []` fallback when spreading — `...null` and `...undefined` are no-ops.")
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
func init() {
|
|
80
|
+
Register(unicornNoUselessFallbackInSpread{})
|
|
81
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// unicorn/no-useless-iterator-to-array: wrapping an iterator-producing
|
|
2
|
+
// call in an array-literal spread (`[...arr.entries()]`) materializes
|
|
3
|
+
// every element into a throwaway array just to walk through it again.
|
|
4
|
+
// The wrappers `.entries()`, `.keys()`, `.values()` already return
|
|
5
|
+
// iterables that any iteration consumer can consume directly.
|
|
6
|
+
//
|
|
7
|
+
// AST-only and conservative: visit each `ArrayLiteralExpression` whose
|
|
8
|
+
// only element is a `SpreadElement` wrapping a `CallExpression` whose
|
|
9
|
+
// callee is `PropertyAccess(_, name)` with `name ∈ {entries, keys,
|
|
10
|
+
// values}`. The array literal must also be in an iterator-consuming
|
|
11
|
+
// parent position — currently only `for…of` is matched, since materializing
|
|
12
|
+
// an array to iterate it once is the rule's textbook case. Using the
|
|
13
|
+
// materialized array as data (`[...iter][0]`, `[...iter].map(…)`,
|
|
14
|
+
// `const arr = [...iter]`) is NOT flagged because the author wants the
|
|
15
|
+
// array, not a fresh walk.
|
|
16
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-iterator-to-array.md
|
|
17
|
+
package linthost
|
|
18
|
+
|
|
19
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
20
|
+
|
|
21
|
+
type unicornNoUselessIteratorToArray struct{}
|
|
22
|
+
|
|
23
|
+
func (unicornNoUselessIteratorToArray) Name() string {
|
|
24
|
+
return "unicorn/no-useless-iterator-to-array"
|
|
25
|
+
}
|
|
26
|
+
func (unicornNoUselessIteratorToArray) Visits() []shimast.Kind {
|
|
27
|
+
return []shimast.Kind{shimast.KindArrayLiteralExpression}
|
|
28
|
+
}
|
|
29
|
+
func (unicornNoUselessIteratorToArray) Check(ctx *Context, node *shimast.Node) {
|
|
30
|
+
// Only fire when the array literal is the iterable of a `for…of`
|
|
31
|
+
// loop — that's the canonical wasted-materialization shape. Other
|
|
32
|
+
// uses (`[...iter][0]`, `const arr = [...iter]`, `.map`, etc.)
|
|
33
|
+
// genuinely need the materialized array.
|
|
34
|
+
if node.Parent == nil || node.Parent.Kind != shimast.KindForOfStatement {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
arr := node.AsArrayLiteralExpression()
|
|
38
|
+
if arr == nil || arr.Elements == nil || len(arr.Elements.Nodes) != 1 {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
only := arr.Elements.Nodes[0]
|
|
42
|
+
if only == nil || only.Kind != shimast.KindSpreadElement {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
spread := only.AsSpreadElement()
|
|
46
|
+
if spread == nil {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
inner := stripParens(spread.Expression)
|
|
50
|
+
if inner == nil || inner.Kind != shimast.KindCallExpression {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
call := inner.AsCallExpression()
|
|
54
|
+
if call == nil || call.Expression == nil ||
|
|
55
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
59
|
+
if access == nil {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
switch identifierText(access.Name()) {
|
|
63
|
+
case "entries", "keys", "values":
|
|
64
|
+
default:
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
ctx.Report(node, "Don't wrap an iterator with `[...iter]` when iterating directly works.")
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
func init() {
|
|
71
|
+
Register(unicornNoUselessIteratorToArray{})
|
|
72
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// unicorn/no-useless-length-check: `arr.length > 0 && arr.some(…)`
|
|
2
|
+
// short-circuits on an empty array, but `arr.some(…)` already returns
|
|
3
|
+
// `false` for the empty case, so the leading length check is redundant.
|
|
4
|
+
// The same goes for `forEach` (returns `undefined` either way). The
|
|
5
|
+
// rule prunes the dead check so the call shape is the only thing the
|
|
6
|
+
// reader has to track.
|
|
7
|
+
//
|
|
8
|
+
// `every`, `map`, and `filter` are deliberately excluded from the `&&`
|
|
9
|
+
// set: `every` returns `true` on an empty array (so the length check
|
|
10
|
+
// IS load-bearing); `map` and `filter` return `[]` which is truthy
|
|
11
|
+
// (the length check changes the truthiness of the whole expression).
|
|
12
|
+
// Upstream covers those under the complementary `||` pattern
|
|
13
|
+
// (`array.length === 0 || array.every(…)`), which this MVP does not
|
|
14
|
+
// implement yet.
|
|
15
|
+
//
|
|
16
|
+
// AST-only MVP: visit each `BinaryExpression`, match operator `&&`,
|
|
17
|
+
// require LHS to be `PropertyAccess(X, length) > 0` or `!== 0`, and
|
|
18
|
+
// require RHS to be `CallExpression(PropertyAccess(X, name), …)` where
|
|
19
|
+
// `name` is one of `some` / `forEach` and the textual form of the two
|
|
20
|
+
// `X` expressions matches. Fire on the binary expression.
|
|
21
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-length-check.md
|
|
22
|
+
package linthost
|
|
23
|
+
|
|
24
|
+
import (
|
|
25
|
+
"fmt"
|
|
26
|
+
|
|
27
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
var unicornNoUselessLengthCheckMethods = map[string]struct{}{
|
|
31
|
+
"some": {},
|
|
32
|
+
"forEach": {},
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type unicornNoUselessLengthCheck struct{}
|
|
36
|
+
|
|
37
|
+
func (unicornNoUselessLengthCheck) Name() string { return "unicorn/no-useless-length-check" }
|
|
38
|
+
func (unicornNoUselessLengthCheck) Visits() []shimast.Kind {
|
|
39
|
+
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
40
|
+
}
|
|
41
|
+
func (unicornNoUselessLengthCheck) Check(ctx *Context, node *shimast.Node) {
|
|
42
|
+
bin := node.AsBinaryExpression()
|
|
43
|
+
if bin == nil || bin.OperatorToken == nil ||
|
|
44
|
+
bin.OperatorToken.Kind != shimast.KindAmpersandAmpersandToken {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
left := stripParens(bin.Left)
|
|
48
|
+
right := stripParens(bin.Right)
|
|
49
|
+
if left == nil || right == nil {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
lengthReceiver := unicornUselessLengthCheckLHSReceiver(ctx, left)
|
|
53
|
+
if lengthReceiver == "" {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
method, callReceiver := unicornUselessLengthCheckRHSReceiver(ctx, right)
|
|
57
|
+
if method == "" || callReceiver == "" {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
if lengthReceiver != callReceiver {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
ctx.Report(node, fmt.Sprintf("Useless `.length` check — `%s` already handles empty arrays correctly.", method))
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// unicornUselessLengthCheckLHSReceiver returns the textual form of `X`
|
|
67
|
+
// when `node` is `X.length > 0` or `X.length !== 0` (either operand
|
|
68
|
+
// order); returns "" otherwise.
|
|
69
|
+
func unicornUselessLengthCheckLHSReceiver(ctx *Context, node *shimast.Node) string {
|
|
70
|
+
bin := node.AsBinaryExpression()
|
|
71
|
+
if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
|
|
72
|
+
return ""
|
|
73
|
+
}
|
|
74
|
+
op := bin.OperatorToken.Kind
|
|
75
|
+
if op != shimast.KindGreaterThanToken &&
|
|
76
|
+
op != shimast.KindExclamationEqualsEqualsToken &&
|
|
77
|
+
op != shimast.KindExclamationEqualsToken {
|
|
78
|
+
return ""
|
|
79
|
+
}
|
|
80
|
+
lhs := stripParens(bin.Left)
|
|
81
|
+
rhs := stripParens(bin.Right)
|
|
82
|
+
// Try `X.length <op> 0`.
|
|
83
|
+
if recv := unicornUselessLengthCheckMatchLengthAccess(ctx, lhs); recv != "" &&
|
|
84
|
+
unicornUselessLengthCheckIsZero(rhs) {
|
|
85
|
+
return recv
|
|
86
|
+
}
|
|
87
|
+
// `0 !== X.length` (no `<` form because `>` is asymmetric — covered
|
|
88
|
+
// by the LHS branch above).
|
|
89
|
+
if op == shimast.KindExclamationEqualsEqualsToken || op == shimast.KindExclamationEqualsToken {
|
|
90
|
+
if recv := unicornUselessLengthCheckMatchLengthAccess(ctx, rhs); recv != "" &&
|
|
91
|
+
unicornUselessLengthCheckIsZero(lhs) {
|
|
92
|
+
return recv
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return ""
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// unicornUselessLengthCheckMatchLengthAccess returns the receiver text
|
|
99
|
+
// when `node` is a `PropertyAccessExpression(X, length)`; "" otherwise.
|
|
100
|
+
func unicornUselessLengthCheckMatchLengthAccess(ctx *Context, node *shimast.Node) string {
|
|
101
|
+
if node == nil || node.Kind != shimast.KindPropertyAccessExpression {
|
|
102
|
+
return ""
|
|
103
|
+
}
|
|
104
|
+
access := node.AsPropertyAccessExpression()
|
|
105
|
+
if access == nil || identifierText(access.Name()) != "length" {
|
|
106
|
+
return ""
|
|
107
|
+
}
|
|
108
|
+
return nodeText(ctx.File, access.Expression)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// unicornUselessLengthCheckIsZero reports whether `node` is the numeric
|
|
112
|
+
// literal `0`.
|
|
113
|
+
func unicornUselessLengthCheckIsZero(node *shimast.Node) bool {
|
|
114
|
+
return node != nil &&
|
|
115
|
+
node.Kind == shimast.KindNumericLiteral &&
|
|
116
|
+
numericLiteralText(node) == "0"
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// unicornUselessLengthCheckRHSReceiver returns (method, receiverText)
|
|
120
|
+
// when `node` is `X.method(...)` for one of the empty-safe iteration
|
|
121
|
+
// methods; ("", "") otherwise.
|
|
122
|
+
func unicornUselessLengthCheckRHSReceiver(ctx *Context, node *shimast.Node) (string, string) {
|
|
123
|
+
if node == nil || node.Kind != shimast.KindCallExpression {
|
|
124
|
+
return "", ""
|
|
125
|
+
}
|
|
126
|
+
call := node.AsCallExpression()
|
|
127
|
+
if call == nil || call.Expression == nil ||
|
|
128
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
129
|
+
return "", ""
|
|
130
|
+
}
|
|
131
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
132
|
+
if access == nil {
|
|
133
|
+
return "", ""
|
|
134
|
+
}
|
|
135
|
+
method := identifierText(access.Name())
|
|
136
|
+
if _, ok := unicornNoUselessLengthCheckMethods[method]; !ok {
|
|
137
|
+
return "", ""
|
|
138
|
+
}
|
|
139
|
+
return method, nodeText(ctx.File, access.Expression)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
func init() {
|
|
143
|
+
Register(unicornNoUselessLengthCheck{})
|
|
144
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// unicorn/no-useless-promise-resolve-reject: inside an `async`
|
|
2
|
+
// function, `return x` already wraps the value in a resolved promise
|
|
3
|
+
// and `throw err` already produces a rejected one. Writing `return
|
|
4
|
+
// Promise.resolve(x)` or `return Promise.reject(err)` rebuilds the
|
|
5
|
+
// wrapper the runtime would build anyway, hides the actual value
|
|
6
|
+
// behind an extra call, and reads as if the author forgot the
|
|
7
|
+
// function was async.
|
|
8
|
+
//
|
|
9
|
+
// AST-only and parent-walking: visit each `ReturnStatement`, find the
|
|
10
|
+
// nearest enclosing function-like ancestor, and require it to carry
|
|
11
|
+
// the `async` modifier. The return's expression after `stripParens`
|
|
12
|
+
// must be a `CallExpression` whose callee is
|
|
13
|
+
// `PropertyAccess(Identifier("Promise"), name)` with
|
|
14
|
+
// `name ∈ {resolve, reject}`. Arrow concise bodies are not handled
|
|
15
|
+
// here because the rule's contract anchors on the `return` keyword.
|
|
16
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-promise-resolve-reject.md
|
|
17
|
+
package linthost
|
|
18
|
+
|
|
19
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
20
|
+
|
|
21
|
+
type unicornNoUselessPromiseResolveReject struct{}
|
|
22
|
+
|
|
23
|
+
func (unicornNoUselessPromiseResolveReject) Name() string {
|
|
24
|
+
return "unicorn/no-useless-promise-resolve-reject"
|
|
25
|
+
}
|
|
26
|
+
func (unicornNoUselessPromiseResolveReject) Visits() []shimast.Kind {
|
|
27
|
+
return []shimast.Kind{shimast.KindReturnStatement}
|
|
28
|
+
}
|
|
29
|
+
func (unicornNoUselessPromiseResolveReject) Check(ctx *Context, node *shimast.Node) {
|
|
30
|
+
ret := node.AsReturnStatement()
|
|
31
|
+
if ret == nil || ret.Expression == nil {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if !unicornNoUselessPromiseResolveRejectInAsync(node) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
expr := stripParens(ret.Expression)
|
|
38
|
+
if expr == nil || expr.Kind != shimast.KindCallExpression {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
call := expr.AsCallExpression()
|
|
42
|
+
if call == nil || call.Expression == nil ||
|
|
43
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
47
|
+
if access == nil {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
if identifierText(access.Expression) != "Promise" {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
switch identifierText(access.Name()) {
|
|
54
|
+
case "resolve", "reject":
|
|
55
|
+
default:
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
ctx.Report(node, "In `async` functions, `return x` and `throw e` work identically — drop the `Promise.<method>` wrapper.")
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// unicornNoUselessPromiseResolveRejectInAsync walks ancestors of `node`
|
|
62
|
+
// and reports whether the nearest enclosing function-like declaration
|
|
63
|
+
// is marked `async`. Crossing a function boundary that is not async
|
|
64
|
+
// stops the walk — a nested non-async function shadows the outer
|
|
65
|
+
// async context.
|
|
66
|
+
func unicornNoUselessPromiseResolveRejectInAsync(node *shimast.Node) bool {
|
|
67
|
+
for cur := node.Parent; cur != nil; cur = cur.Parent {
|
|
68
|
+
switch cur.Kind {
|
|
69
|
+
case shimast.KindFunctionDeclaration,
|
|
70
|
+
shimast.KindFunctionExpression,
|
|
71
|
+
shimast.KindArrowFunction,
|
|
72
|
+
shimast.KindMethodDeclaration:
|
|
73
|
+
return hasModifier(cur, shimast.KindAsyncKeyword)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
func init() {
|
|
80
|
+
Register(unicornNoUselessPromiseResolveReject{})
|
|
81
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// unicorn/no-useless-spread: wrapping an already-spread literal in
|
|
2
|
+
// another spread produces the original literal — `[...[1, 2, 3]]` is
|
|
3
|
+
// just `[1, 2, 3]`, and `{...{a: 1}}` is `{a: 1}`. The extra spread
|
|
4
|
+
// reads like an attempted clone but allocates an intermediate literal
|
|
5
|
+
// for no observable effect.
|
|
6
|
+
//
|
|
7
|
+
// AST-only and conservative: visit every `ArrayLiteralExpression` and
|
|
8
|
+
// `ObjectLiteralExpression`; match when the literal contains exactly
|
|
9
|
+
// one element that is a `SpreadElement` / `SpreadAssignment` whose
|
|
10
|
+
// operand (after `stripParens`) is itself a literal of the same kind.
|
|
11
|
+
// The receiver expressions are not inspected — the syntactic shape
|
|
12
|
+
// `[...[…]]` / `{...{…}}` is the signal regardless of the inner
|
|
13
|
+
// literal's contents. Mirrors the conservative dispatch used by
|
|
14
|
+
// `unicorn/prefer-set-size`.
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-spread.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
|
|
20
|
+
type unicornNoUselessSpread struct{}
|
|
21
|
+
|
|
22
|
+
func (unicornNoUselessSpread) Name() string { return "unicorn/no-useless-spread" }
|
|
23
|
+
func (unicornNoUselessSpread) Visits() []shimast.Kind {
|
|
24
|
+
return []shimast.Kind{shimast.KindArrayLiteralExpression, shimast.KindObjectLiteralExpression}
|
|
25
|
+
}
|
|
26
|
+
func (unicornNoUselessSpread) Check(ctx *Context, node *shimast.Node) {
|
|
27
|
+
switch node.Kind {
|
|
28
|
+
case shimast.KindArrayLiteralExpression:
|
|
29
|
+
arr := node.AsArrayLiteralExpression()
|
|
30
|
+
if arr == nil || arr.Elements == nil || len(arr.Elements.Nodes) != 1 {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
only := arr.Elements.Nodes[0]
|
|
34
|
+
if only == nil || only.Kind != shimast.KindSpreadElement {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
spread := only.AsSpreadElement()
|
|
38
|
+
if spread == nil {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
inner := stripParens(spread.Expression)
|
|
42
|
+
if inner != nil && inner.Kind == shimast.KindArrayLiteralExpression {
|
|
43
|
+
ctx.Report(node, "Don't wrap an already-spread literal in another spread.")
|
|
44
|
+
}
|
|
45
|
+
case shimast.KindObjectLiteralExpression:
|
|
46
|
+
obj := node.AsObjectLiteralExpression()
|
|
47
|
+
if obj == nil || obj.Properties == nil || len(obj.Properties.Nodes) != 1 {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
only := obj.Properties.Nodes[0]
|
|
51
|
+
if only == nil || only.Kind != shimast.KindSpreadAssignment {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
spread := only.AsSpreadAssignment()
|
|
55
|
+
if spread == nil {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
inner := stripParens(spread.Expression)
|
|
59
|
+
if inner != nil && inner.Kind == shimast.KindObjectLiteralExpression {
|
|
60
|
+
ctx.Report(node, "Don't wrap an already-spread literal in another spread.")
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
func init() {
|
|
66
|
+
Register(unicornNoUselessSpread{})
|
|
67
|
+
}
|