@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
package/linthost/rules_gap.go
CHANGED
|
@@ -13,7 +13,7 @@ import (
|
|
|
13
13
|
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
14
14
|
)
|
|
15
15
|
|
|
16
|
-
//
|
|
16
|
+
// noEmptyStaticBlock: `class C { static {} }` has no effect.
|
|
17
17
|
// ESLint recommended: https://eslint.org/docs/latest/rules/no-empty-static-block
|
|
18
18
|
type noEmptyStaticBlock struct{}
|
|
19
19
|
|
|
@@ -32,7 +32,7 @@ func (noEmptyStaticBlock) Check(ctx *Context, node *shimast.Node) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
//
|
|
35
|
+
// noSetterReturn: setters must not return a value.
|
|
36
36
|
// ESLint recommended: https://eslint.org/docs/latest/rules/no-setter-return
|
|
37
37
|
type noSetterReturn struct{}
|
|
38
38
|
|
|
@@ -61,7 +61,7 @@ func isInsideDirectSetter(node *shimast.Node) bool {
|
|
|
61
61
|
return false
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
//
|
|
64
|
+
// noUnusedLabels: a label is useful only when a break/continue targets it.
|
|
65
65
|
// ESLint recommended: https://eslint.org/docs/latest/rules/no-unused-labels
|
|
66
66
|
type noUnusedLabels struct{}
|
|
67
67
|
|
|
@@ -95,11 +95,11 @@ func (noUnusedLabels) Check(ctx *Context, node *shimast.Node) {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
//
|
|
98
|
+
// noDynamicDelete: avoid deleting properties through dynamic keys.
|
|
99
99
|
// typescript-eslint strict: https://typescript-eslint.io/rules/no-dynamic-delete/
|
|
100
100
|
type noDynamicDelete struct{}
|
|
101
101
|
|
|
102
|
-
func (noDynamicDelete) Name() string { return "no-dynamic-delete" }
|
|
102
|
+
func (noDynamicDelete) Name() string { return "typescript/no-dynamic-delete" }
|
|
103
103
|
func (noDynamicDelete) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindDeleteExpression} }
|
|
104
104
|
func (noDynamicDelete) Check(ctx *Context, node *shimast.Node) {
|
|
105
105
|
del := node.AsDeleteExpression()
|
|
@@ -114,7 +114,7 @@ func (noDynamicDelete) Check(ctx *Context, node *shimast.Node) {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
// isStaticPropertyKey reports whether node is a literal key that can
|
|
117
|
-
// appear in a delete expression without triggering
|
|
117
|
+
// appear in a delete expression without triggering noDynamicDelete:
|
|
118
118
|
// string literals, no-substitution template literals, and numeric literals.
|
|
119
119
|
func isStaticPropertyKey(node *shimast.Node) bool {
|
|
120
120
|
node = stripParens(node)
|
|
@@ -130,12 +130,12 @@ func isStaticPropertyKey(node *shimast.Node) bool {
|
|
|
130
130
|
return false
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
//
|
|
133
|
+
// noNonNullAssertedNullishCoalescing: `foo! ?? bar` is contradictory.
|
|
134
134
|
// typescript-eslint strict: https://typescript-eslint.io/rules/no-non-null-asserted-nullish-coalescing/
|
|
135
135
|
type noNonNullAssertedNullishCoalescing struct{}
|
|
136
136
|
|
|
137
137
|
func (noNonNullAssertedNullishCoalescing) Name() string {
|
|
138
|
-
return "no-non-null-asserted-nullish-coalescing"
|
|
138
|
+
return "typescript/no-non-null-asserted-nullish-coalescing"
|
|
139
139
|
}
|
|
140
140
|
func (noNonNullAssertedNullishCoalescing) Visits() []shimast.Kind {
|
|
141
141
|
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
@@ -153,11 +153,11 @@ func (noNonNullAssertedNullishCoalescing) Check(ctx *Context, node *shimast.Node
|
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
//
|
|
156
|
+
// noUnnecessaryTypeConstraint: `<T extends any>` / `<T extends unknown>`.
|
|
157
157
|
// typescript-eslint recommended: https://typescript-eslint.io/rules/no-unnecessary-type-constraint/
|
|
158
158
|
type noUnnecessaryTypeConstraint struct{}
|
|
159
159
|
|
|
160
|
-
func (noUnnecessaryTypeConstraint) Name() string { return "no-unnecessary-type-constraint" }
|
|
160
|
+
func (noUnnecessaryTypeConstraint) Name() string { return "typescript/no-unnecessary-type-constraint" }
|
|
161
161
|
func (noUnnecessaryTypeConstraint) Visits() []shimast.Kind {
|
|
162
162
|
return []shimast.Kind{shimast.KindTypeParameter}
|
|
163
163
|
}
|
|
@@ -184,11 +184,11 @@ func (noUnnecessaryTypeConstraint) Check(ctx *Context, node *shimast.Node) {
|
|
|
184
184
|
)
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
//
|
|
187
|
+
// noUnsafeFunctionType: `Function` accepts any callable shape.
|
|
188
188
|
// typescript-eslint recommended: https://typescript-eslint.io/rules/no-unsafe-function-type/
|
|
189
189
|
type noUnsafeFunctionType struct{}
|
|
190
190
|
|
|
191
|
-
func (noUnsafeFunctionType) Name() string { return "no-unsafe-function-type" }
|
|
191
|
+
func (noUnsafeFunctionType) Name() string { return "typescript/no-unsafe-function-type" }
|
|
192
192
|
func (noUnsafeFunctionType) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindTypeReference} }
|
|
193
193
|
func (noUnsafeFunctionType) Check(ctx *Context, node *shimast.Node) {
|
|
194
194
|
ref := node.AsTypeReferenceNode()
|
|
@@ -198,12 +198,12 @@ func (noUnsafeFunctionType) Check(ctx *Context, node *shimast.Node) {
|
|
|
198
198
|
ctx.Report(node, "The Function type is unsafe. Use a specific function type instead.")
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
//
|
|
201
|
+
// noWrapperObjectTypes: prefer primitive type keywords over boxed object
|
|
202
202
|
// type names such as `String` and `Boolean`.
|
|
203
203
|
// typescript-eslint recommended: https://typescript-eslint.io/rules/no-wrapper-object-types/
|
|
204
204
|
type noWrapperObjectTypes struct{}
|
|
205
205
|
|
|
206
|
-
func (noWrapperObjectTypes) Name() string { return "no-wrapper-object-types" }
|
|
206
|
+
func (noWrapperObjectTypes) Name() string { return "typescript/no-wrapper-object-types" }
|
|
207
207
|
func (noWrapperObjectTypes) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindTypeReference} }
|
|
208
208
|
func (noWrapperObjectTypes) Check(ctx *Context, node *shimast.Node) {
|
|
209
209
|
ref := node.AsTypeReferenceNode()
|
|
@@ -301,31 +301,11 @@ func wrapperPrimitive(name string) (string, bool) {
|
|
|
301
301
|
return "", false
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
-
//
|
|
305
|
-
// typescript-eslint strict: https://typescript-eslint.io/rules/no-useless-constructor/
|
|
306
|
-
type noUselessConstructor struct{}
|
|
307
|
-
|
|
308
|
-
func (noUselessConstructor) Name() string { return "no-useless-constructor" }
|
|
309
|
-
func (noUselessConstructor) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindConstructor} }
|
|
310
|
-
func (noUselessConstructor) Check(ctx *Context, node *shimast.Node) {
|
|
311
|
-
ctor := node.AsConstructorDeclaration()
|
|
312
|
-
if ctor == nil || ctor.Body == nil {
|
|
313
|
-
return
|
|
314
|
-
}
|
|
315
|
-
if len(node.Parameters()) != 0 {
|
|
316
|
-
return
|
|
317
|
-
}
|
|
318
|
-
body := ctor.Body.AsBlock()
|
|
319
|
-
if body == nil || body.Statements == nil || len(body.Statements.Nodes) == 0 {
|
|
320
|
-
ctx.Report(node, "Useless empty constructor.")
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// prefer-literal-enum-member: computed enum members are harder to inspect.
|
|
304
|
+
// preferLiteralEnumMember: computed enum members are harder to inspect.
|
|
325
305
|
// typescript-eslint strict: https://typescript-eslint.io/rules/prefer-literal-enum-member/
|
|
326
306
|
type preferLiteralEnumMember struct{}
|
|
327
307
|
|
|
328
|
-
func (preferLiteralEnumMember) Name() string { return "prefer-literal-enum-member" }
|
|
308
|
+
func (preferLiteralEnumMember) Name() string { return "typescript/prefer-literal-enum-member" }
|
|
329
309
|
func (preferLiteralEnumMember) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindEnumMember} }
|
|
330
310
|
func (preferLiteralEnumMember) Check(ctx *Context, node *shimast.Node) {
|
|
331
311
|
member := node.AsEnumMember()
|
|
@@ -335,11 +315,11 @@ func (preferLiteralEnumMember) Check(ctx *Context, node *shimast.Node) {
|
|
|
335
315
|
ctx.Report(member.Initializer, "Enum member initializer should be a literal value.")
|
|
336
316
|
}
|
|
337
317
|
|
|
338
|
-
//
|
|
318
|
+
// consistentTypeAssertions: prefer `value as Type` over `<Type>value`.
|
|
339
319
|
// typescript-eslint stylistic: https://typescript-eslint.io/rules/consistent-type-assertions/
|
|
340
320
|
type consistentTypeAssertions struct{}
|
|
341
321
|
|
|
342
|
-
func (consistentTypeAssertions) Name() string { return "consistent-type-assertions" }
|
|
322
|
+
func (consistentTypeAssertions) Name() string { return "typescript/consistent-type-assertions" }
|
|
343
323
|
func (consistentTypeAssertions) Visits() []shimast.Kind {
|
|
344
324
|
return []shimast.Kind{shimast.KindTypeAssertionExpression}
|
|
345
325
|
}
|
|
@@ -347,12 +327,12 @@ func (consistentTypeAssertions) Check(ctx *Context, node *shimast.Node) {
|
|
|
347
327
|
ctx.Report(node, "Use `as` type assertions instead of angle-bracket assertions.")
|
|
348
328
|
}
|
|
349
329
|
|
|
350
|
-
//
|
|
330
|
+
// consistentTypeDefinitions: prefer interfaces for object-shaped public
|
|
351
331
|
// contracts. This mirrors typescript-eslint's default option.
|
|
352
332
|
// typescript-eslint stylistic: https://typescript-eslint.io/rules/consistent-type-definitions/
|
|
353
333
|
type consistentTypeDefinitions struct{}
|
|
354
334
|
|
|
355
|
-
func (consistentTypeDefinitions) Name() string { return "consistent-type-definitions" }
|
|
335
|
+
func (consistentTypeDefinitions) Name() string { return "typescript/consistent-type-definitions" }
|
|
356
336
|
func (consistentTypeDefinitions) Visits() []shimast.Kind {
|
|
357
337
|
return []shimast.Kind{shimast.KindTypeAliasDeclaration}
|
|
358
338
|
}
|
|
@@ -364,7 +344,7 @@ func (consistentTypeDefinitions) Check(ctx *Context, node *shimast.Node) {
|
|
|
364
344
|
ctx.Report(node, "Use an interface instead of a type literal alias.")
|
|
365
345
|
}
|
|
366
346
|
|
|
367
|
-
//
|
|
347
|
+
// dotNotation: `obj["prop"]` should be `obj.prop` when the key is a valid
|
|
368
348
|
// identifier.
|
|
369
349
|
// ESLint canonical: https://eslint.org/docs/latest/rules/dot-notation
|
|
370
350
|
type dotNotation struct{}
|
|
@@ -436,7 +416,7 @@ func isReservedWord(value string) bool {
|
|
|
436
416
|
|
|
437
417
|
// isSimpleIdentifierName reports whether value is a valid bare identifier
|
|
438
418
|
// (ASCII letters, digits, underscore, dollar sign; digits not first). Used
|
|
439
|
-
// by
|
|
419
|
+
// by dotNotation to decide whether bracket access can become dot access.
|
|
440
420
|
func isSimpleIdentifierName(value string) bool {
|
|
441
421
|
if value == "" {
|
|
442
422
|
return false
|
|
@@ -453,12 +433,12 @@ func isSimpleIdentifierName(value string) bool {
|
|
|
453
433
|
return true
|
|
454
434
|
}
|
|
455
435
|
|
|
456
|
-
//
|
|
436
|
+
// noUnsafeDeclarationMerging: class/interface merging hides runtime vs type
|
|
457
437
|
// surface differences.
|
|
458
438
|
// typescript-eslint recommended: https://typescript-eslint.io/rules/no-unsafe-declaration-merging/
|
|
459
439
|
type noUnsafeDeclarationMerging struct{}
|
|
460
440
|
|
|
461
|
-
func (noUnsafeDeclarationMerging) Name() string { return "no-unsafe-declaration-merging" }
|
|
441
|
+
func (noUnsafeDeclarationMerging) Name() string { return "typescript/no-unsafe-declaration-merging" }
|
|
462
442
|
func (noUnsafeDeclarationMerging) Visits() []shimast.Kind {
|
|
463
443
|
return []shimast.Kind{shimast.KindSourceFile}
|
|
464
444
|
}
|
|
@@ -500,7 +480,6 @@ func init() {
|
|
|
500
480
|
Register(noUnsafeDeclarationMerging{})
|
|
501
481
|
Register(noUnsafeFunctionType{})
|
|
502
482
|
Register(noWrapperObjectTypes{})
|
|
503
|
-
Register(noUselessConstructor{})
|
|
504
483
|
Register(preferLiteralEnumMember{})
|
|
505
484
|
Register(consistentTypeAssertions{})
|
|
506
485
|
Register(consistentTypeDefinitions{})
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// groupedAccessorPairs: a `get` and `set` accessor that share the same
|
|
2
|
+
// property name should be declared next to each other in the class
|
|
3
|
+
// body. When the pair is split apart by unrelated members, a reader
|
|
4
|
+
// scanning the class has to chase the read and write halves separately
|
|
5
|
+
// — and patches to one half are easy to make without noticing the
|
|
6
|
+
// other.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: walk every class declaration/expression, group members by
|
|
9
|
+
// (name, static-ness), and for any group that contains both a getter
|
|
10
|
+
// and a setter check that their member indices are adjacent. The
|
|
11
|
+
// second-encountered half is the one reported, because the first half
|
|
12
|
+
// reads correctly until the reader hits the second declaration.
|
|
13
|
+
// https://eslint.org/docs/latest/rules/grouped-accessor-pairs
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type groupedAccessorPairs struct{}
|
|
19
|
+
|
|
20
|
+
func (groupedAccessorPairs) Name() string { return "grouped-accessor-pairs" }
|
|
21
|
+
func (groupedAccessorPairs) Visits() []shimast.Kind {
|
|
22
|
+
return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
|
|
23
|
+
}
|
|
24
|
+
func (groupedAccessorPairs) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
+
members := classMembers(node)
|
|
26
|
+
if len(members) < 2 {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
type slot struct {
|
|
30
|
+
name string
|
|
31
|
+
static bool
|
|
32
|
+
}
|
|
33
|
+
type entry struct {
|
|
34
|
+
index int
|
|
35
|
+
kind shimast.Kind
|
|
36
|
+
node *shimast.Node
|
|
37
|
+
}
|
|
38
|
+
groups := map[slot][]entry{}
|
|
39
|
+
for i, member := range members {
|
|
40
|
+
if member == nil {
|
|
41
|
+
continue
|
|
42
|
+
}
|
|
43
|
+
if member.Kind != shimast.KindGetAccessor && member.Kind != shimast.KindSetAccessor {
|
|
44
|
+
continue
|
|
45
|
+
}
|
|
46
|
+
name := classMemberName(member)
|
|
47
|
+
if name == "" {
|
|
48
|
+
continue
|
|
49
|
+
}
|
|
50
|
+
key := slot{name: name, static: hasModifier(member, shimast.KindStaticKeyword)}
|
|
51
|
+
groups[key] = append(groups[key], entry{index: i, kind: member.Kind, node: member})
|
|
52
|
+
}
|
|
53
|
+
for _, entries := range groups {
|
|
54
|
+
if len(entries) < 2 {
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
// Find a getter/setter pair within the group.
|
|
58
|
+
var get, set *entry
|
|
59
|
+
for i := range entries {
|
|
60
|
+
e := &entries[i]
|
|
61
|
+
if e.kind == shimast.KindGetAccessor && get == nil {
|
|
62
|
+
get = e
|
|
63
|
+
} else if e.kind == shimast.KindSetAccessor && set == nil {
|
|
64
|
+
set = e
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if get == nil || set == nil {
|
|
68
|
+
continue
|
|
69
|
+
}
|
|
70
|
+
// Adjacent indices in the members list satisfy the rule.
|
|
71
|
+
diff := get.index - set.index
|
|
72
|
+
if diff == 1 || diff == -1 {
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
// Report on whichever half appears later — the earlier one
|
|
76
|
+
// reads fine in isolation; the later one is the surprise.
|
|
77
|
+
later := get
|
|
78
|
+
if set.index > get.index {
|
|
79
|
+
later = set
|
|
80
|
+
}
|
|
81
|
+
ctx.Report(later.node, "Accessor pair should be grouped.")
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func init() {
|
|
86
|
+
Register(groupedAccessorPairs{})
|
|
87
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// guardForIn: `for (key in obj)` walks the prototype chain and yields
|
|
2
|
+
// every enumerable name, inherited or own. Most authors only ever care
|
|
3
|
+
// about own keys, so an unguarded body silently leaks work onto
|
|
4
|
+
// prototype-chain entries someone else attached. The canonical guard is
|
|
5
|
+
// `if (Object.hasOwn(obj, key))` or the older
|
|
6
|
+
// `Object.prototype.hasOwnProperty.call(obj, key)`; an inverted-guard
|
|
7
|
+
// `continue` (`if (!Object.hasOwn(...)) continue;`) is the equivalent
|
|
8
|
+
// early-skip shape.
|
|
9
|
+
//
|
|
10
|
+
// Conservative baseline: the rule only inspects the FIRST executable
|
|
11
|
+
// statement of the loop body. The body either opens with a guard
|
|
12
|
+
// covering everything that follows, or it does not — anything more
|
|
13
|
+
// nuanced is the developer's responsibility. The guard expression must
|
|
14
|
+
// reference the loop's own key binding; a hard-coded call on an
|
|
15
|
+
// unrelated identifier is not a real guard.
|
|
16
|
+
// https://eslint.org/docs/latest/rules/guard-for-in
|
|
17
|
+
package linthost
|
|
18
|
+
|
|
19
|
+
import (
|
|
20
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
type guardForIn struct{}
|
|
24
|
+
|
|
25
|
+
func (guardForIn) Name() string { return "guard-for-in" }
|
|
26
|
+
func (guardForIn) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindForInStatement} }
|
|
27
|
+
func (guardForIn) Check(ctx *Context, node *shimast.Node) {
|
|
28
|
+
stmt := node.AsForInOrOfStatement()
|
|
29
|
+
if stmt == nil || stmt.Statement == nil {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
first := firstBodyStatement(stmt.Statement)
|
|
33
|
+
if first == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
key := forInKeyName(stmt.Initializer)
|
|
37
|
+
if isHasOwnGuard(first, key) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
ctx.Report(node, "The body of a `for...in` should be wrapped in an `if (Object.hasOwn(...))` statement to filter unwanted properties from the prototype.")
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// firstBodyStatement returns the first executable statement inside a
|
|
44
|
+
// loop body. A block body unwraps to its first statement; a bare
|
|
45
|
+
// non-block body is itself the only statement. Returns nil for an
|
|
46
|
+
// empty block — an empty body cannot leak inherited keys.
|
|
47
|
+
func firstBodyStatement(body *shimast.Node) *shimast.Node {
|
|
48
|
+
if body == nil {
|
|
49
|
+
return nil
|
|
50
|
+
}
|
|
51
|
+
if body.Kind != shimast.KindBlock {
|
|
52
|
+
return body
|
|
53
|
+
}
|
|
54
|
+
block := body.AsBlock()
|
|
55
|
+
if block == nil || block.Statements == nil {
|
|
56
|
+
return nil
|
|
57
|
+
}
|
|
58
|
+
for _, s := range block.Statements.Nodes {
|
|
59
|
+
if s != nil {
|
|
60
|
+
return s
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return nil
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// forInKeyName extracts the identifier text of the loop key from a
|
|
67
|
+
// `for (… in obj)` initializer. The initializer is either a
|
|
68
|
+
// VariableDeclarationList with one declaration (`for (const key in …)`)
|
|
69
|
+
// or a bare Identifier (`for (key in …)`). Destructuring patterns and
|
|
70
|
+
// other shapes return "" so the rule skips its key-identity check.
|
|
71
|
+
func forInKeyName(init *shimast.Node) string {
|
|
72
|
+
if init == nil {
|
|
73
|
+
return ""
|
|
74
|
+
}
|
|
75
|
+
if name := identifierText(init); name != "" {
|
|
76
|
+
return name
|
|
77
|
+
}
|
|
78
|
+
if init.Kind != shimast.KindVariableDeclarationList {
|
|
79
|
+
return ""
|
|
80
|
+
}
|
|
81
|
+
list := init.AsVariableDeclarationList()
|
|
82
|
+
if list == nil || list.Declarations == nil || len(list.Declarations.Nodes) != 1 {
|
|
83
|
+
return ""
|
|
84
|
+
}
|
|
85
|
+
decl := list.Declarations.Nodes[0]
|
|
86
|
+
if decl == nil {
|
|
87
|
+
return ""
|
|
88
|
+
}
|
|
89
|
+
v := decl.AsVariableDeclaration()
|
|
90
|
+
if v == nil {
|
|
91
|
+
return ""
|
|
92
|
+
}
|
|
93
|
+
return identifierText(v.Name())
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// isHasOwnGuard reports whether `stmt` is the canonical own-key guard
|
|
97
|
+
// that should open a `for...in` body. Two shapes count:
|
|
98
|
+
//
|
|
99
|
+
// 1. `if (<has-own>(obj, key)) { … }` — positive guard wrapping the
|
|
100
|
+
// real body. The else branch (if any) is allowed because the
|
|
101
|
+
// developer has explicitly handled the inherited-key case.
|
|
102
|
+
// 2. `if (!<has-own>(obj, key)) continue;` — inverted-guard early
|
|
103
|
+
// skip. The then branch must be a single `continue` (with or
|
|
104
|
+
// without a block wrapper) so the rest of the loop body only runs
|
|
105
|
+
// for own keys.
|
|
106
|
+
//
|
|
107
|
+
// `<has-own>` is either `Object.hasOwn(obj, key)` or
|
|
108
|
+
// `Object.prototype.hasOwnProperty.call(obj, key)`. The second
|
|
109
|
+
// argument must match `key` when one was extracted from the
|
|
110
|
+
// initializer; otherwise any second argument is accepted (the rule
|
|
111
|
+
// has no reliable handle on the key name).
|
|
112
|
+
func isHasOwnGuard(stmt *shimast.Node, key string) bool {
|
|
113
|
+
if stmt == nil || stmt.Kind != shimast.KindIfStatement {
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
ifStmt := stmt.AsIfStatement()
|
|
117
|
+
if ifStmt == nil || ifStmt.Expression == nil {
|
|
118
|
+
return false
|
|
119
|
+
}
|
|
120
|
+
cond := stripParens(ifStmt.Expression)
|
|
121
|
+
if cond == nil {
|
|
122
|
+
return false
|
|
123
|
+
}
|
|
124
|
+
if isHasOwnCall(cond, key) {
|
|
125
|
+
return true
|
|
126
|
+
}
|
|
127
|
+
if cond.Kind != shimast.KindPrefixUnaryExpression {
|
|
128
|
+
return false
|
|
129
|
+
}
|
|
130
|
+
pre := cond.AsPrefixUnaryExpression()
|
|
131
|
+
if pre == nil || pre.Operator != shimast.KindExclamationToken {
|
|
132
|
+
return false
|
|
133
|
+
}
|
|
134
|
+
if !isHasOwnCall(stripParens(pre.Operand), key) {
|
|
135
|
+
return false
|
|
136
|
+
}
|
|
137
|
+
// Negated guard: require the then branch to be a single `continue`
|
|
138
|
+
// so the rest of the loop runs only for own keys.
|
|
139
|
+
return isLoneContinue(ifStmt.ThenStatement)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// isHasOwnCall reports whether `node` is `Object.hasOwn(obj, key)` or
|
|
143
|
+
// `Object.prototype.hasOwnProperty.call(obj, key)`. The second
|
|
144
|
+
// argument must match `key` when one is supplied.
|
|
145
|
+
func isHasOwnCall(node *shimast.Node, key string) bool {
|
|
146
|
+
if node == nil || node.Kind != shimast.KindCallExpression {
|
|
147
|
+
return false
|
|
148
|
+
}
|
|
149
|
+
call := node.AsCallExpression()
|
|
150
|
+
if call == nil || call.Expression == nil || call.Arguments == nil {
|
|
151
|
+
return false
|
|
152
|
+
}
|
|
153
|
+
args := call.Arguments.Nodes
|
|
154
|
+
if len(args) < 2 {
|
|
155
|
+
return false
|
|
156
|
+
}
|
|
157
|
+
callee := stripParens(call.Expression)
|
|
158
|
+
switch {
|
|
159
|
+
case isMatchingPropertyAccess(callee, "Object", "hasOwn"):
|
|
160
|
+
// `Object.hasOwn(obj, key)` — both arguments belong to the
|
|
161
|
+
// caller; the key check is the second argument.
|
|
162
|
+
case isMatchingPropertyAccess(callee, "Object", "prototype", "hasOwnProperty", "call"):
|
|
163
|
+
// `Object.prototype.hasOwnProperty.call(obj, key)` — same
|
|
164
|
+
// argument layout because `.call(obj, key)` passes the
|
|
165
|
+
// receiver explicitly.
|
|
166
|
+
default:
|
|
167
|
+
return false
|
|
168
|
+
}
|
|
169
|
+
if key == "" {
|
|
170
|
+
return true
|
|
171
|
+
}
|
|
172
|
+
return identifierText(stripParens(args[1])) == key
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// isLoneContinue reports whether `stmt` is a bare `continue;` (or a
|
|
176
|
+
// block containing exactly one `continue;`). Used to validate the
|
|
177
|
+
// then-branch of the negated-guard shape.
|
|
178
|
+
func isLoneContinue(stmt *shimast.Node) bool {
|
|
179
|
+
if stmt == nil {
|
|
180
|
+
return false
|
|
181
|
+
}
|
|
182
|
+
if stmt.Kind == shimast.KindContinueStatement {
|
|
183
|
+
return true
|
|
184
|
+
}
|
|
185
|
+
if stmt.Kind != shimast.KindBlock {
|
|
186
|
+
return false
|
|
187
|
+
}
|
|
188
|
+
block := stmt.AsBlock()
|
|
189
|
+
if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
|
|
190
|
+
return false
|
|
191
|
+
}
|
|
192
|
+
return block.Statements.Nodes[0] != nil &&
|
|
193
|
+
block.Statements.Nodes[0].Kind == shimast.KindContinueStatement
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
func init() {
|
|
197
|
+
Register(guardForIn{})
|
|
198
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// idLength reports declaration names shorter than the default minimum
|
|
2
|
+
// of two characters. Single-letter bindings (`a`, `x`, `t`) are
|
|
3
|
+
// notoriously hard to grep, fold poorly into call-site documentation,
|
|
4
|
+
// and frequently collide with the convention of using single letters
|
|
5
|
+
// only for true free variables.
|
|
6
|
+
// https://eslint.org/docs/latest/rules/id-length
|
|
7
|
+
//
|
|
8
|
+
// Conservative baseline: only the four declaration kinds the ESLint
|
|
9
|
+
// rule documents as in-scope are inspected — variable, function,
|
|
10
|
+
// class, and parameter declarations. Each name is read through the
|
|
11
|
+
// shared `identifierText` helper so destructuring patterns and
|
|
12
|
+
// computed property names contribute zero findings.
|
|
13
|
+
package linthost
|
|
14
|
+
|
|
15
|
+
import (
|
|
16
|
+
"strconv"
|
|
17
|
+
|
|
18
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
// idLengthMinimum is the default minimum identifier length. ESLint
|
|
22
|
+
// uses 2; mirroring it keeps the rule's default behavior aligned with
|
|
23
|
+
// upstream and lets the existing fixture annotations remain stable.
|
|
24
|
+
const idLengthMinimum = 2
|
|
25
|
+
|
|
26
|
+
type idLength struct{}
|
|
27
|
+
|
|
28
|
+
func (idLength) Name() string { return "id-length" }
|
|
29
|
+
func (idLength) Visits() []shimast.Kind {
|
|
30
|
+
return []shimast.Kind{
|
|
31
|
+
shimast.KindVariableDeclaration,
|
|
32
|
+
shimast.KindParameter,
|
|
33
|
+
shimast.KindFunctionDeclaration,
|
|
34
|
+
shimast.KindClassDeclaration,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
func (idLength) Check(ctx *Context, node *shimast.Node) {
|
|
38
|
+
var nameNode *shimast.Node
|
|
39
|
+
switch node.Kind {
|
|
40
|
+
case shimast.KindVariableDeclaration:
|
|
41
|
+
decl := node.AsVariableDeclaration()
|
|
42
|
+
if decl == nil {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
nameNode = decl.Name()
|
|
46
|
+
case shimast.KindParameter:
|
|
47
|
+
decl := node.AsParameterDeclaration()
|
|
48
|
+
if decl == nil {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
nameNode = decl.Name()
|
|
52
|
+
case shimast.KindFunctionDeclaration:
|
|
53
|
+
decl := node.AsFunctionDeclaration()
|
|
54
|
+
if decl == nil {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
nameNode = decl.Name()
|
|
58
|
+
case shimast.KindClassDeclaration:
|
|
59
|
+
decl := node.AsClassDeclaration()
|
|
60
|
+
if decl == nil {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
nameNode = decl.Name()
|
|
64
|
+
}
|
|
65
|
+
name := identifierText(nameNode)
|
|
66
|
+
if name == "" {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
if len([]rune(name)) >= idLengthMinimum {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
ctx.Report(nameNode, "Identifier name '"+name+"' is too short (< "+strconv.Itoa(idLengthMinimum)+").")
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
func init() {
|
|
76
|
+
Register(idLength{})
|
|
77
|
+
}
|
|
@@ -5,14 +5,14 @@ import (
|
|
|
5
5
|
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
6
6
|
)
|
|
7
7
|
|
|
8
|
-
//
|
|
8
|
+
// noImportTypeSideEffects: an import whose every named specifier
|
|
9
9
|
// uses the inline `type` modifier is morally a type-only import; hoist
|
|
10
10
|
// the `type` to the import clause to make that intent explicit and let
|
|
11
11
|
// `verbatimModuleSyntax` elide the import entirely. typescript-eslint
|
|
12
12
|
// stylistic: https://typescript-eslint.io/rules/no-import-type-side-effects/
|
|
13
13
|
type noImportTypeSideEffects struct{}
|
|
14
14
|
|
|
15
|
-
func (noImportTypeSideEffects) Name() string { return "no-import-type-side-effects" }
|
|
15
|
+
func (noImportTypeSideEffects) Name() string { return "typescript/no-import-type-side-effects" }
|
|
16
16
|
func (noImportTypeSideEffects) Visits() []shimast.Kind {
|
|
17
17
|
return []shimast.Kind{shimast.KindImportDeclaration}
|
|
18
18
|
}
|
|
@@ -94,6 +94,74 @@ func (noImportTypeSideEffects) Check(ctx *Context, node *shimast.Node) {
|
|
|
94
94
|
ctx.ReportFix(node, message, edits...)
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
// noUselessEmptyExport: `export {}` is only useful as a module marker.
|
|
98
|
+
// Once a file or namespace block already contains another import/export,
|
|
99
|
+
// the empty export does not change module-ness and can be removed.
|
|
100
|
+
type noUselessEmptyExport struct{}
|
|
101
|
+
|
|
102
|
+
func (noUselessEmptyExport) Name() string { return "typescript/no-useless-empty-export" }
|
|
103
|
+
func (noUselessEmptyExport) Visits() []shimast.Kind {
|
|
104
|
+
return []shimast.Kind{shimast.KindSourceFile, shimast.KindModuleBlock}
|
|
105
|
+
}
|
|
106
|
+
func (noUselessEmptyExport) Check(ctx *Context, node *shimast.Node) {
|
|
107
|
+
if ctx.File != nil && ctx.File.IsDeclarationFile {
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
statements := node.Statements()
|
|
111
|
+
if len(statements) == 0 {
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
emptyExports := []*shimast.Node{}
|
|
115
|
+
foundOtherModuleSyntax := false
|
|
116
|
+
for _, stmt := range statements {
|
|
117
|
+
if stmt == nil {
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
if isEmptyExportDeclaration(stmt) {
|
|
121
|
+
emptyExports = append(emptyExports, stmt)
|
|
122
|
+
continue
|
|
123
|
+
}
|
|
124
|
+
if isModuleSyntaxStatement(stmt) {
|
|
125
|
+
foundOtherModuleSyntax = true
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if !foundOtherModuleSyntax {
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
for _, stmt := range emptyExports {
|
|
132
|
+
ctx.Report(stmt, "Empty export does not change module-ness here.")
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
func isEmptyExportDeclaration(node *shimast.Node) bool {
|
|
137
|
+
if node == nil || node.Kind != shimast.KindExportDeclaration {
|
|
138
|
+
return false
|
|
139
|
+
}
|
|
140
|
+
decl := node.AsExportDeclaration()
|
|
141
|
+
if decl == nil || decl.ExportClause == nil || decl.ModuleSpecifier != nil {
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
if decl.ExportClause.Kind != shimast.KindNamedExports {
|
|
145
|
+
return false
|
|
146
|
+
}
|
|
147
|
+
named := decl.ExportClause.AsNamedExports()
|
|
148
|
+
return named != nil && (named.Elements == nil || len(named.Elements.Nodes) == 0)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
func isModuleSyntaxStatement(node *shimast.Node) bool {
|
|
152
|
+
if node == nil {
|
|
153
|
+
return false
|
|
154
|
+
}
|
|
155
|
+
switch node.Kind {
|
|
156
|
+
case shimast.KindImportDeclaration, shimast.KindImportEqualsDeclaration, shimast.KindExportAssignment:
|
|
157
|
+
return true
|
|
158
|
+
case shimast.KindExportDeclaration:
|
|
159
|
+
return !isEmptyExportDeclaration(node)
|
|
160
|
+
}
|
|
161
|
+
return hasModifier(node, shimast.KindExportKeyword)
|
|
162
|
+
}
|
|
163
|
+
|
|
97
164
|
func init() {
|
|
98
165
|
Register(noImportTypeSideEffects{})
|
|
166
|
+
Register(noUselessEmptyExport{})
|
|
99
167
|
}
|