@ttsc/lint 0.13.1 → 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 +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,147 @@
|
|
|
1
|
+
// unicorn/prefer-array-index-of: `arr.findIndex(x => x === literal)` is
|
|
2
|
+
// the long-hand spelling of `arr.indexOf(literal)`. Both return the
|
|
3
|
+
// index of the first matching element; `indexOf` is a direct comparison
|
|
4
|
+
// against a value and is faster, shorter, and clearer about intent.
|
|
5
|
+
//
|
|
6
|
+
// AST-only: visit each `CallExpression` whose callee is
|
|
7
|
+
// `PropertyAccess(_, findIndex)`. The single argument must be a
|
|
8
|
+
// function (`ArrowFunction` or `FunctionExpression`) with exactly one
|
|
9
|
+
// parameter. The function body — concise body, or a block body whose
|
|
10
|
+
// single statement is a `return` — must be a strict-equality comparison
|
|
11
|
+
// between the parameter identifier and a literal (string, number,
|
|
12
|
+
// boolean, null, bigint). Reports on the call.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-index-of.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornPreferArrayIndexOf struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornPreferArrayIndexOf) Name() string { return "unicorn/prefer-array-index-of" }
|
|
21
|
+
func (unicornPreferArrayIndexOf) Visits() []shimast.Kind {
|
|
22
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
23
|
+
}
|
|
24
|
+
func (unicornPreferArrayIndexOf) 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 || identifierText(access.Name()) != "findIndex" {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
fn := stripParens(call.Arguments.Nodes[0])
|
|
38
|
+
if fn == nil {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
var body *shimast.Node
|
|
42
|
+
switch fn.Kind {
|
|
43
|
+
case shimast.KindArrowFunction:
|
|
44
|
+
arrow := fn.AsArrowFunction()
|
|
45
|
+
if arrow == nil {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
body = arrow.Body
|
|
49
|
+
case shimast.KindFunctionExpression:
|
|
50
|
+
expr := fn.AsFunctionExpression()
|
|
51
|
+
if expr == nil {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
body = expr.Body
|
|
55
|
+
default:
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
params := fn.Parameters()
|
|
59
|
+
if len(params) != 1 {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
paramName := parameterIdentifierName(params[0])
|
|
63
|
+
if paramName == "" {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
expr := unicornPreferArrayIndexOfBodyExpression(body)
|
|
67
|
+
if expr == nil {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
bin := expr.AsBinaryExpression()
|
|
71
|
+
if bin == nil || bin.OperatorToken == nil ||
|
|
72
|
+
bin.OperatorToken.Kind != shimast.KindEqualsEqualsEqualsToken {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
left := stripParens(bin.Left)
|
|
76
|
+
right := stripParens(bin.Right)
|
|
77
|
+
if left == nil || right == nil {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
if unicornPreferArrayIndexOfMatchesParam(left, paramName) &&
|
|
81
|
+
unicornPreferArrayIndexOfIsLiteral(right) {
|
|
82
|
+
ctx.Report(node, "Prefer `Array#indexOf()` over `Array#findIndex(x => x === literal)`.")
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
if unicornPreferArrayIndexOfMatchesParam(right, paramName) &&
|
|
86
|
+
unicornPreferArrayIndexOfIsLiteral(left) {
|
|
87
|
+
ctx.Report(node, "Prefer `Array#indexOf()` over `Array#findIndex(x => x === literal)`.")
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// unicornPreferArrayIndexOfBodyExpression normalizes the function body to
|
|
92
|
+
// the comparison expression: a concise arrow body returns its expression,
|
|
93
|
+
// a block body with a single `return expr;` returns the expression.
|
|
94
|
+
func unicornPreferArrayIndexOfBodyExpression(body *shimast.Node) *shimast.Node {
|
|
95
|
+
if body == nil {
|
|
96
|
+
return nil
|
|
97
|
+
}
|
|
98
|
+
if body.Kind != shimast.KindBlock {
|
|
99
|
+
expr := stripParens(body)
|
|
100
|
+
if expr == nil || expr.Kind != shimast.KindBinaryExpression {
|
|
101
|
+
return nil
|
|
102
|
+
}
|
|
103
|
+
return expr
|
|
104
|
+
}
|
|
105
|
+
block := body.AsBlock()
|
|
106
|
+
if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
|
|
107
|
+
return nil
|
|
108
|
+
}
|
|
109
|
+
stmt := block.Statements.Nodes[0]
|
|
110
|
+
if stmt == nil || stmt.Kind != shimast.KindReturnStatement {
|
|
111
|
+
return nil
|
|
112
|
+
}
|
|
113
|
+
ret := stmt.AsReturnStatement()
|
|
114
|
+
if ret == nil || ret.Expression == nil {
|
|
115
|
+
return nil
|
|
116
|
+
}
|
|
117
|
+
expr := stripParens(ret.Expression)
|
|
118
|
+
if expr == nil || expr.Kind != shimast.KindBinaryExpression {
|
|
119
|
+
return nil
|
|
120
|
+
}
|
|
121
|
+
return expr
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
func unicornPreferArrayIndexOfMatchesParam(node *shimast.Node, name string) bool {
|
|
125
|
+
return identifierText(node) == name
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
func unicornPreferArrayIndexOfIsLiteral(node *shimast.Node) bool {
|
|
129
|
+
if node == nil {
|
|
130
|
+
return false
|
|
131
|
+
}
|
|
132
|
+
switch node.Kind {
|
|
133
|
+
case shimast.KindStringLiteral,
|
|
134
|
+
shimast.KindNumericLiteral,
|
|
135
|
+
shimast.KindBigIntLiteral,
|
|
136
|
+
shimast.KindNoSubstitutionTemplateLiteral,
|
|
137
|
+
shimast.KindNullKeyword,
|
|
138
|
+
shimast.KindTrueKeyword,
|
|
139
|
+
shimast.KindFalseKeyword:
|
|
140
|
+
return true
|
|
141
|
+
}
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
func init() {
|
|
146
|
+
Register(unicornPreferArrayIndexOf{})
|
|
147
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// unicorn/prefer-array-some: `arr.filter(predicate).length > 0` walks the
|
|
2
|
+
// whole array and allocates an intermediate filtered array just to ask
|
|
3
|
+
// the boolean question "does any element match?". `arr.some(predicate)`
|
|
4
|
+
// short-circuits at the first hit and reads as the intent.
|
|
5
|
+
//
|
|
6
|
+
// AST-only: visit each `BinaryExpression`. The operator must be one of
|
|
7
|
+
// `>`, `>=`, `!==`, `!=`. The left operand must be
|
|
8
|
+
// `PropertyAccess(CallExpression(_, filter), length)`. The right operand
|
|
9
|
+
// must be the numeric literal `0`. Reports on the binary expression.
|
|
10
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-some.md
|
|
11
|
+
package linthost
|
|
12
|
+
|
|
13
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
14
|
+
|
|
15
|
+
type unicornPreferArraySome struct{}
|
|
16
|
+
|
|
17
|
+
func (unicornPreferArraySome) Name() string { return "unicorn/prefer-array-some" }
|
|
18
|
+
func (unicornPreferArraySome) Visits() []shimast.Kind {
|
|
19
|
+
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
20
|
+
}
|
|
21
|
+
func (unicornPreferArraySome) Check(ctx *Context, node *shimast.Node) {
|
|
22
|
+
bin := node.AsBinaryExpression()
|
|
23
|
+
if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
switch bin.OperatorToken.Kind {
|
|
27
|
+
case shimast.KindGreaterThanToken,
|
|
28
|
+
shimast.KindGreaterThanEqualsToken,
|
|
29
|
+
shimast.KindExclamationEqualsEqualsToken,
|
|
30
|
+
shimast.KindExclamationEqualsToken:
|
|
31
|
+
default:
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
right := stripParens(bin.Right)
|
|
35
|
+
if right == nil || right.Kind != shimast.KindNumericLiteral {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
if numericLiteralText(right) != "0" {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
left := stripParens(bin.Left)
|
|
42
|
+
if left == nil || left.Kind != shimast.KindPropertyAccessExpression {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
outer := left.AsPropertyAccessExpression()
|
|
46
|
+
if outer == nil || identifierText(outer.Name()) != "length" {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
receiver := stripParens(outer.Expression)
|
|
50
|
+
if receiver == nil || receiver.Kind != shimast.KindCallExpression {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
call := receiver.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 || identifierText(access.Name()) != "filter" {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
ctx.Report(node, "Prefer `Array#some()` over `.filter(...).length > 0`.")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
func init() {
|
|
66
|
+
Register(unicornPreferArraySome{})
|
|
67
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// unicorn/prefer-at: `arr[arr.length - 1]` is the legacy spelling of
|
|
2
|
+
// "last element". ES2022 introduced `Array#at(-N)` (and `String#at(-N)`)
|
|
3
|
+
// which lets you reach for the same value from the tail without
|
|
4
|
+
// repeating the receiver and the subtraction. The rule pushes authors
|
|
5
|
+
// toward the built-in.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit each `ElementAccessExpression`. The index expression
|
|
8
|
+
// must be a `BinaryExpression` whose operator is `-`, whose left side is
|
|
9
|
+
// `PropertyAccess(_, length)`, and whose right side is a positive
|
|
10
|
+
// numeric literal. The receiver of the `.length` access does not need
|
|
11
|
+
// to match the element-access receiver textually; mismatches are
|
|
12
|
+
// uncommon enough that the AST-only check stays useful in practice.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-at.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornPreferAt struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornPreferAt) Name() string { return "unicorn/prefer-at" }
|
|
21
|
+
func (unicornPreferAt) Visits() []shimast.Kind {
|
|
22
|
+
return []shimast.Kind{shimast.KindElementAccessExpression}
|
|
23
|
+
}
|
|
24
|
+
func (unicornPreferAt) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
+
access := node.AsElementAccessExpression()
|
|
26
|
+
if access == nil || access.ArgumentExpression == nil {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
index := stripParens(access.ArgumentExpression)
|
|
30
|
+
if index == nil || index.Kind != shimast.KindBinaryExpression {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
bin := index.AsBinaryExpression()
|
|
34
|
+
if bin == nil || bin.OperatorToken == nil ||
|
|
35
|
+
bin.OperatorToken.Kind != shimast.KindMinusToken {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
left := stripParens(bin.Left)
|
|
39
|
+
if left == nil || left.Kind != shimast.KindPropertyAccessExpression {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
prop := left.AsPropertyAccessExpression()
|
|
43
|
+
if prop == nil || identifierText(prop.Name()) != "length" {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
right := stripParens(bin.Right)
|
|
47
|
+
if right == nil || right.Kind != shimast.KindNumericLiteral {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
text := numericLiteralText(right)
|
|
51
|
+
if !unicornPreferAtIsPositiveInteger(text) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
ctx.Report(node, "Prefer `Array#at(-N)` / `String#at(-N)` over `arr[arr.length - N]`.")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// unicornPreferAtIsPositiveInteger reports whether `text` is the literal
|
|
58
|
+
// form of a positive integer (>= 1). Leading zeros are accepted because
|
|
59
|
+
// the JS scanner already normalized them; the only rejections are the
|
|
60
|
+
// empty string, plain `0`, and anything containing a non-digit (decimals,
|
|
61
|
+
// `e`-notation, hex, bigint suffix).
|
|
62
|
+
func unicornPreferAtIsPositiveInteger(text string) bool {
|
|
63
|
+
if text == "" || text == "0" {
|
|
64
|
+
return false
|
|
65
|
+
}
|
|
66
|
+
for i := 0; i < len(text); i++ {
|
|
67
|
+
c := text[i]
|
|
68
|
+
if c < '0' || c > '9' {
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return true
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
func init() {
|
|
76
|
+
Register(unicornPreferAt{})
|
|
77
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// unicorn/prefer-bigint-literals: `BigInt(1)` and `BigInt("1")` both
|
|
2
|
+
// allocate a BigInt at runtime through a constructor call, while the
|
|
3
|
+
// equivalent `1n` literal is one parse-time token with no call
|
|
4
|
+
// overhead. The rule asks authors to use the literal form when the
|
|
5
|
+
// argument is a known integer.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit `KindCallExpression`, fire when the callee is the
|
|
8
|
+
// bare `BigInt` identifier called with exactly one argument that is
|
|
9
|
+
// either a numeric literal of any shape, or a string literal whose
|
|
10
|
+
// content is a decimal-digit-only integer (optionally signed). The
|
|
11
|
+
// conservative string check avoids flagging `BigInt("0x10")` and
|
|
12
|
+
// other shapes that need a runtime parse.
|
|
13
|
+
//
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-bigint-literals.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornPreferBigintLiterals struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornPreferBigintLiterals) Name() string { return "unicorn/prefer-bigint-literals" }
|
|
22
|
+
func (unicornPreferBigintLiterals) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
24
|
+
}
|
|
25
|
+
func (unicornPreferBigintLiterals) Check(ctx *Context, node *shimast.Node) {
|
|
26
|
+
call := node.AsCallExpression()
|
|
27
|
+
if call == nil || identifierText(call.Expression) != "BigInt" {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
arg := stripParens(call.Arguments.Nodes[0])
|
|
34
|
+
if arg == nil {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
switch arg.Kind {
|
|
38
|
+
case shimast.KindNumericLiteral:
|
|
39
|
+
// `BigInt(1)` — always rewritable to `1n`.
|
|
40
|
+
case shimast.KindStringLiteral:
|
|
41
|
+
text := stringLiteralText(arg)
|
|
42
|
+
if !unicornPreferBigintLiteralsIsDecimalInteger(text) {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
default:
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
ctx.Report(node, "Prefer BigInt literal `1n` over `BigInt(1)`.")
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// unicornPreferBigintLiteralsIsDecimalInteger reports whether `text` is
|
|
52
|
+
// a non-empty decimal-integer literal — digits only, optional leading
|
|
53
|
+
// minus. The check is intentionally conservative; anything more exotic
|
|
54
|
+
// (hex prefix, exponent, decimal point) leaves the BigInt call alone.
|
|
55
|
+
func unicornPreferBigintLiteralsIsDecimalInteger(text string) bool {
|
|
56
|
+
if text == "" {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
i := 0
|
|
60
|
+
if text[0] == '-' || text[0] == '+' {
|
|
61
|
+
i++
|
|
62
|
+
}
|
|
63
|
+
if i == len(text) {
|
|
64
|
+
return false
|
|
65
|
+
}
|
|
66
|
+
for ; i < len(text); i++ {
|
|
67
|
+
ch := text[i]
|
|
68
|
+
if ch < '0' || ch > '9' {
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return true
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
func init() {
|
|
76
|
+
Register(unicornPreferBigintLiterals{})
|
|
77
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// unicorn/prefer-blob-reading-methods: `FileReader#readAsArrayBuffer`
|
|
2
|
+
// and `FileReader#readAsText` predate the promise-returning `Blob`
|
|
3
|
+
// methods. They require attaching `load` / `error` listeners and reading
|
|
4
|
+
// `reader.result` in a callback, while `Blob#arrayBuffer()` and
|
|
5
|
+
// `Blob#text()` return a Promise that resolves to the same value
|
|
6
|
+
// directly. The newer shape is shorter, easier to reason about, and the
|
|
7
|
+
// rule discourages the legacy callback form.
|
|
8
|
+
//
|
|
9
|
+
// AST-only: visit each `CallExpression`, match a property-access callee
|
|
10
|
+
// whose method identifier is `readAsArrayBuffer` or `readAsText`, and
|
|
11
|
+
// fire on the call. The receiver is not type-checked — the syntactic
|
|
12
|
+
// shape is the signal regardless of whether the value is statically a
|
|
13
|
+
// `FileReader`.
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-blob-reading-methods.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornPreferBlobReadingMethods struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornPreferBlobReadingMethods) Name() string {
|
|
22
|
+
return "unicorn/prefer-blob-reading-methods"
|
|
23
|
+
}
|
|
24
|
+
func (unicornPreferBlobReadingMethods) Visits() []shimast.Kind {
|
|
25
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
26
|
+
}
|
|
27
|
+
func (unicornPreferBlobReadingMethods) Check(ctx *Context, node *shimast.Node) {
|
|
28
|
+
call := node.AsCallExpression()
|
|
29
|
+
if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
33
|
+
if access == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
switch identifierText(access.Name()) {
|
|
37
|
+
case "readAsArrayBuffer", "readAsText":
|
|
38
|
+
ctx.Report(node, "Prefer `Blob#arrayBuffer()` / `Blob#text()` over `FileReader#readAsArrayBuffer` / `readAsText`.")
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
func init() {
|
|
43
|
+
Register(unicornPreferBlobReadingMethods{})
|
|
44
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// unicorn/prefer-class-fields: assigning a primitive literal to
|
|
2
|
+
// `this.<field>` inside a class constructor is a TC39-era pattern that
|
|
3
|
+
// modern class-field declarations now express directly. The class-field
|
|
4
|
+
// form is shorter, makes the field visible at the class level without
|
|
5
|
+
// stepping through the constructor body, and avoids accidentally
|
|
6
|
+
// re-initializing a property that was already declared with a typed
|
|
7
|
+
// declaration.
|
|
8
|
+
//
|
|
9
|
+
// AST-only: visit `KindConstructor`. For each top-level statement in the
|
|
10
|
+
// constructor body, fire on any `ExpressionStatement` whose expression
|
|
11
|
+
// is an `=` `BinaryExpression` whose LHS is a property access on
|
|
12
|
+
// `this` and whose RHS is a primitive literal (`StringLiteral`,
|
|
13
|
+
// `NumericLiteral`, `KindTrueKeyword`, `KindFalseKeyword`,
|
|
14
|
+
// `KindNullKeyword`). The check is per-assignment, not per-constructor,
|
|
15
|
+
// so a constructor mixing several such assignments reports each one.
|
|
16
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-class-fields.md
|
|
17
|
+
package linthost
|
|
18
|
+
|
|
19
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
20
|
+
|
|
21
|
+
type unicornPreferClassFields struct{}
|
|
22
|
+
|
|
23
|
+
func (unicornPreferClassFields) Name() string { return "unicorn/prefer-class-fields" }
|
|
24
|
+
func (unicornPreferClassFields) Visits() []shimast.Kind {
|
|
25
|
+
return []shimast.Kind{shimast.KindConstructor}
|
|
26
|
+
}
|
|
27
|
+
func (unicornPreferClassFields) Check(ctx *Context, node *shimast.Node) {
|
|
28
|
+
ctor := node.AsConstructorDeclaration()
|
|
29
|
+
if ctor == nil || ctor.Body == nil {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
body := ctor.Body.AsBlock()
|
|
33
|
+
if body == nil || body.Statements == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
for _, stmt := range body.Statements.Nodes {
|
|
37
|
+
if stmt == nil || stmt.Kind != shimast.KindExpressionStatement {
|
|
38
|
+
continue
|
|
39
|
+
}
|
|
40
|
+
exprStmt := stmt.AsExpressionStatement()
|
|
41
|
+
if exprStmt == nil || exprStmt.Expression == nil {
|
|
42
|
+
continue
|
|
43
|
+
}
|
|
44
|
+
expr := stripParens(exprStmt.Expression)
|
|
45
|
+
if expr == nil || expr.Kind != shimast.KindBinaryExpression {
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
bin := expr.AsBinaryExpression()
|
|
49
|
+
if bin == nil || bin.OperatorToken == nil || bin.OperatorToken.Kind != shimast.KindEqualsToken {
|
|
50
|
+
continue
|
|
51
|
+
}
|
|
52
|
+
lhs := stripParens(bin.Left)
|
|
53
|
+
if lhs == nil || lhs.Kind != shimast.KindPropertyAccessExpression {
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
access := lhs.AsPropertyAccessExpression()
|
|
57
|
+
if access == nil {
|
|
58
|
+
continue
|
|
59
|
+
}
|
|
60
|
+
receiver := stripParens(access.Expression)
|
|
61
|
+
if receiver == nil || receiver.Kind != shimast.KindThisKeyword {
|
|
62
|
+
continue
|
|
63
|
+
}
|
|
64
|
+
rhs := stripParens(bin.Right)
|
|
65
|
+
if !isPrimitiveLiteralForClassField(rhs) {
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
ctx.Report(expr, "Prefer class field declarations over constructor assignments to `this.field`.")
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// isPrimitiveLiteralForClassField reports whether `node` is one of the
|
|
73
|
+
// primitive-literal kinds that the prefer-class-fields rule treats as
|
|
74
|
+
// "trivially hoistable" to a class field initializer.
|
|
75
|
+
func isPrimitiveLiteralForClassField(node *shimast.Node) bool {
|
|
76
|
+
if node == nil {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
switch node.Kind {
|
|
80
|
+
case shimast.KindStringLiteral,
|
|
81
|
+
shimast.KindNumericLiteral,
|
|
82
|
+
shimast.KindTrueKeyword,
|
|
83
|
+
shimast.KindFalseKeyword,
|
|
84
|
+
shimast.KindNullKeyword,
|
|
85
|
+
shimast.KindNoSubstitutionTemplateLiteral:
|
|
86
|
+
return true
|
|
87
|
+
}
|
|
88
|
+
return false
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
func init() {
|
|
92
|
+
Register(unicornPreferClassFields{})
|
|
93
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// unicorn/prefer-classlist-toggle: an `if (cond) el.classList.add(name)
|
|
2
|
+
// else el.classList.remove(name)` block can be collapsed into a single
|
|
3
|
+
// `el.classList.toggle(name, cond)` call. The toggle form is shorter,
|
|
4
|
+
// avoids accidental drift between the two branches, and matches the
|
|
5
|
+
// spec-blessed shape for conditional class management.
|
|
6
|
+
//
|
|
7
|
+
// AST-only minimum-viable port: visit `IfStatement` and match when both
|
|
8
|
+
// branches contain a single `ExpressionStatement` of
|
|
9
|
+
// `X.classList.add(arg)` and `X.classList.remove(arg)` (in either
|
|
10
|
+
// order), with identical receiver text on `X.classList` and identical
|
|
11
|
+
// argument text. Textual identity uses `nodeText` so this works without
|
|
12
|
+
// the Checker; receivers that differ at the type level but share their
|
|
13
|
+
// spelling will still match (the rule's signal is the syntactic shape
|
|
14
|
+
// of the two-branch toggle).
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-classlist-toggle.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
|
|
20
|
+
type unicornPreferClasslistToggle struct{}
|
|
21
|
+
|
|
22
|
+
func (unicornPreferClasslistToggle) Name() string { return "unicorn/prefer-classlist-toggle" }
|
|
23
|
+
func (unicornPreferClasslistToggle) Visits() []shimast.Kind {
|
|
24
|
+
return []shimast.Kind{shimast.KindIfStatement}
|
|
25
|
+
}
|
|
26
|
+
func (unicornPreferClasslistToggle) Check(ctx *Context, node *shimast.Node) {
|
|
27
|
+
stmt := node.AsIfStatement()
|
|
28
|
+
if stmt == nil || stmt.ThenStatement == nil || stmt.ElseStatement == nil {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
thenCall := classlistToggleSingleCall(stmt.ThenStatement)
|
|
32
|
+
elseCall := classlistToggleSingleCall(stmt.ElseStatement)
|
|
33
|
+
if thenCall == nil || elseCall == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
thenMethod, thenReceiver, thenArg := classlistAddRemoveParts(thenCall)
|
|
37
|
+
elseMethod, elseReceiver, elseArg := classlistAddRemoveParts(elseCall)
|
|
38
|
+
if thenMethod == "" || elseMethod == "" {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
// One branch must be `add`, the other `remove` — order does not
|
|
42
|
+
// matter; the toggle rewrite is symmetric.
|
|
43
|
+
if !((thenMethod == "add" && elseMethod == "remove") ||
|
|
44
|
+
(thenMethod == "remove" && elseMethod == "add")) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
if nodeText(ctx.File, thenReceiver) != nodeText(ctx.File, elseReceiver) {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
if nodeText(ctx.File, thenArg) != nodeText(ctx.File, elseArg) {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
ctx.Report(node, "Prefer `classList.toggle(name, condition)` over manual `add`/`remove` branches.")
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// classlistToggleSingleCall returns the single CallExpression inside a
|
|
57
|
+
// then/else branch — accepting either a bare ExpressionStatement or a
|
|
58
|
+
// Block wrapping exactly one ExpressionStatement. Returns nil for any
|
|
59
|
+
// other shape.
|
|
60
|
+
func classlistToggleSingleCall(branch *shimast.Node) *shimast.Node {
|
|
61
|
+
if branch == nil {
|
|
62
|
+
return nil
|
|
63
|
+
}
|
|
64
|
+
stmt := branch
|
|
65
|
+
if branch.Kind == shimast.KindBlock {
|
|
66
|
+
block := branch.AsBlock()
|
|
67
|
+
if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
|
|
68
|
+
return nil
|
|
69
|
+
}
|
|
70
|
+
stmt = block.Statements.Nodes[0]
|
|
71
|
+
}
|
|
72
|
+
if stmt == nil || stmt.Kind != shimast.KindExpressionStatement {
|
|
73
|
+
return nil
|
|
74
|
+
}
|
|
75
|
+
expr := stmt.AsExpressionStatement()
|
|
76
|
+
if expr == nil || expr.Expression == nil {
|
|
77
|
+
return nil
|
|
78
|
+
}
|
|
79
|
+
call := stripParens(expr.Expression)
|
|
80
|
+
if call == nil || call.Kind != shimast.KindCallExpression {
|
|
81
|
+
return nil
|
|
82
|
+
}
|
|
83
|
+
return call
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// classlistAddRemoveParts pulls (method, receiver, arg) out of a
|
|
87
|
+
// `X.classList.add(arg)` / `X.classList.remove(arg)` call, where
|
|
88
|
+
// `receiver` is the `X.classList` chain (the property-access expression
|
|
89
|
+
// node) and `arg` is the single argument. Returns ("", nil, nil) for
|
|
90
|
+
// any other shape.
|
|
91
|
+
func classlistAddRemoveParts(call *shimast.Node) (string, *shimast.Node, *shimast.Node) {
|
|
92
|
+
ce := call.AsCallExpression()
|
|
93
|
+
if ce == nil || ce.Expression == nil || ce.Arguments == nil || len(ce.Arguments.Nodes) != 1 {
|
|
94
|
+
return "", nil, nil
|
|
95
|
+
}
|
|
96
|
+
if ce.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
97
|
+
return "", nil, nil
|
|
98
|
+
}
|
|
99
|
+
access := ce.Expression.AsPropertyAccessExpression()
|
|
100
|
+
if access == nil {
|
|
101
|
+
return "", nil, nil
|
|
102
|
+
}
|
|
103
|
+
method := identifierText(access.Name())
|
|
104
|
+
if method != "add" && method != "remove" {
|
|
105
|
+
return "", nil, nil
|
|
106
|
+
}
|
|
107
|
+
receiver := access.Expression
|
|
108
|
+
if receiver == nil || receiver.Kind != shimast.KindPropertyAccessExpression {
|
|
109
|
+
return "", nil, nil
|
|
110
|
+
}
|
|
111
|
+
receiverAccess := receiver.AsPropertyAccessExpression()
|
|
112
|
+
if receiverAccess == nil || identifierText(receiverAccess.Name()) != "classList" {
|
|
113
|
+
return "", nil, nil
|
|
114
|
+
}
|
|
115
|
+
return method, receiver, ce.Arguments.Nodes[0]
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
func init() {
|
|
119
|
+
Register(unicornPreferClasslistToggle{})
|
|
120
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// unicorn/prefer-code-point: `String#charCodeAt` and
|
|
2
|
+
// `String.fromCharCode` operate on UTF-16 code units, so they split
|
|
3
|
+
// astral characters (anything above U+FFFF) into surrogate pairs and
|
|
4
|
+
// return numbers that no longer correspond to the Unicode code point
|
|
5
|
+
// the source string visually shows. `String#codePointAt` and
|
|
6
|
+
// `String.fromCodePoint` operate on full code points and round-trip
|
|
7
|
+
// astral characters correctly.
|
|
8
|
+
//
|
|
9
|
+
// AST-only: visit `CallExpression`, match property-access callees whose
|
|
10
|
+
// method identifier is `charCodeAt` or `fromCharCode`. For
|
|
11
|
+
// `fromCharCode` also require the receiver to be the literal identifier
|
|
12
|
+
// `String` so we only flag the static `String.fromCharCode` form; for
|
|
13
|
+
// `charCodeAt` the receiver may be anything (any string instance).
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-code-point.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornPreferCodePoint struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornPreferCodePoint) Name() string { return "unicorn/prefer-code-point" }
|
|
22
|
+
func (unicornPreferCodePoint) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
24
|
+
}
|
|
25
|
+
func (unicornPreferCodePoint) Check(ctx *Context, node *shimast.Node) {
|
|
26
|
+
call := node.AsCallExpression()
|
|
27
|
+
if call == nil || call.Expression == nil || 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 "charCodeAt":
|
|
36
|
+
// Instance call — receiver type is irrelevant.
|
|
37
|
+
ctx.Report(node, "Prefer `String#codePointAt()` / `String.fromCodePoint()` over `charCodeAt` / `fromCharCode`.")
|
|
38
|
+
case "fromCharCode":
|
|
39
|
+
// Static call — only the `String.fromCharCode(...)` shape.
|
|
40
|
+
if identifierText(access.Expression) != "String" {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
ctx.Report(node, "Prefer `String#codePointAt()` / `String.fromCodePoint()` over `charCodeAt` / `fromCharCode`.")
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func init() {
|
|
48
|
+
Register(unicornPreferCodePoint{})
|
|
49
|
+
}
|