@ttsc/lint 0.13.1 → 0.14.0-dev.20260528.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +948 -69
- package/lib/defaultFormat.d.ts +9 -6
- package/lib/defaultFormat.js +9 -6
- package/lib/defaultFormat.js.map +1 -1
- package/lib/index.d.ts +46 -0
- package/lib/index.js +35 -10
- package/lib/index.js.map +1 -1
- package/lib/structures/ITtscLintConfig.d.ts +12 -6
- package/lib/structures/{ITtscLintFormatConfig.d.ts → ITtscLintFormat.d.ts} +2 -2
- package/lib/structures/{TtscLintRuleMap.js → ITtscLintFormat.js} +1 -1
- package/lib/structures/ITtscLintFormat.js.map +1 -0
- package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
- package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
- package/lib/structures/TtscLintRuleSetting.js.map +1 -0
- package/lib/structures/index.d.ts +3 -4
- package/lib/structures/index.js +3 -4
- package/lib/structures/index.js.map +1 -1
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +104 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +14 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +79 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintContributorRules.d.ts +17 -0
- package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
- package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintCoreRules.d.ts +1257 -0
- package/lib/structures/{ITtscLintFormatConfig.js → rules/ITtscLintCoreRules.js} +1 -1
- package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintCypressRules.d.ts +129 -0
- package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
- package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +157 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +167 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJestRules.d.ts +201 -0
- package/lib/structures/rules/ITtscLintJestRules.js +3 -0
- package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJsdocRules.d.ts +140 -0
- package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
- package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +302 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintNextjsRules.d.ts +185 -0
- package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
- package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +330 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintPromiseRules.d.ts +188 -0
- package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
- package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +51 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +39 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js +12 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRules.d.ts +289 -0
- package/lib/structures/rules/ITtscLintReactRules.js +3 -0
- package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintRegexpRules.d.ts +190 -0
- package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
- package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +66 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
- package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
- package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
- package/lib/structures/rules/ITtscLintRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintSecurityRules.d.ts +148 -0
- package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
- package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintSolidRules.d.ts +181 -0
- package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
- package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +21 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintStorybookRules.d.ts +174 -0
- package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
- package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +94 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +22 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +310 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1132 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
- package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
- package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintVitestRules.d.ts +141 -0
- package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
- package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
- package/lib/structures/rules/index.d.ts +31 -0
- package/lib/structures/rules/index.js +48 -0
- package/lib/structures/rules/index.js.map +1 -0
- package/linthost/ast_helpers.go +30 -5
- package/linthost/config.go +48 -17
- package/linthost/config_format.go +9 -9
- package/linthost/directives.go +67 -25
- package/linthost/dispatch.go +14 -3
- package/linthost/engine.go +152 -31
- package/linthost/fix.go +2 -2
- package/linthost/lsp.go +747 -0
- package/linthost/print_dispatch.go +2 -2
- package/linthost/print_nodes_function.go +2 -2
- package/linthost/print_nodes_object.go +1 -1
- package/linthost/rule_names.go +14 -0
- package/linthost/rules_arrays.go +2 -2
- package/linthost/rules_boundaries.go +532 -0
- package/linthost/rules_camelcase.go +133 -0
- package/linthost/rules_complexity.go +94 -0
- package/linthost/rules_consistent_return.go +130 -0
- package/linthost/rules_console.go +1 -1
- package/linthost/rules_core_extra.go +739 -0
- package/linthost/rules_curly.go +70 -0
- package/linthost/rules_cypress.go +608 -0
- package/linthost/rules_debugger.go +2 -2
- package/linthost/rules_default_case.go +39 -0
- package/linthost/rules_default_case_last.go +46 -0
- package/linthost/rules_dupes.go +3 -3
- package/linthost/rules_empty.go +3 -3
- package/linthost/rules_escape.go +44 -24
- package/linthost/rules_eval.go +2 -2
- package/linthost/rules_finally.go +2 -2
- package/linthost/rules_format_jsdoc.go +1 -1
- package/linthost/rules_format_print_width.go +9 -9
- package/linthost/rules_format_quotes.go +1 -1
- package/linthost/rules_format_semi.go +1 -1
- package/linthost/rules_format_sort_imports.go +1 -1
- package/linthost/rules_format_trailing_comma.go +1 -1
- package/linthost/rules_functional.go +967 -0
- package/linthost/rules_gap.go +24 -45
- package/linthost/rules_grouped_accessor_pairs.go +87 -0
- package/linthost/rules_guard_for_in.go +198 -0
- package/linthost/rules_id_length.go +77 -0
- package/linthost/rules_imports.go +70 -2
- package/linthost/rules_init_declarations.go +53 -0
- package/linthost/rules_jest.go +618 -0
- package/linthost/rules_jsdoc.go +502 -0
- package/linthost/rules_jsx_a11y.go +1264 -0
- package/linthost/rules_logic.go +12 -12
- package/linthost/rules_loops.go +1 -1
- package/linthost/rules_max_classes_per_file.go +58 -0
- package/linthost/rules_max_depth.go +83 -0
- package/linthost/rules_max_lines.go +101 -0
- package/linthost/rules_max_lines_per_function.go +57 -0
- package/linthost/rules_max_nested_callbacks.go +61 -0
- package/linthost/rules_max_params.go +49 -0
- package/linthost/rules_max_statements.go +59 -0
- package/linthost/rules_misc.go +1 -1
- package/linthost/rules_nextjs.go +697 -0
- package/linthost/rules_no_else_return.go +75 -0
- package/linthost/rules_no_empty_named_blocks.go +91 -0
- package/linthost/rules_no_extend_native.go +51 -0
- package/linthost/rules_no_import_assign.go +140 -0
- package/linthost/rules_no_invalid_this.go +52 -0
- package/linthost/rules_no_loop_func.go +85 -0
- package/linthost/rules_no_magic_numbers.go +123 -0
- package/linthost/rules_no_mixed_operators.go +80 -0
- package/linthost/rules_no_param_reassign.go +98 -0
- package/linthost/rules_no_redeclare.go +270 -0
- package/linthost/rules_no_restricted_imports.go +105 -0
- package/linthost/rules_no_restricted_syntax.go +49 -0
- package/linthost/rules_no_shadow.go +147 -0
- package/linthost/rules_no_unreachable.go +77 -0
- package/linthost/rules_no_useless_assignment.go +120 -0
- package/linthost/rules_no_useless_constructor.go +245 -0
- package/linthost/rules_no_useless_return.go +51 -0
- package/linthost/rules_params.go +1 -1
- package/linthost/rules_playwright.go +788 -0
- package/linthost/rules_prefer_arrow_callback.go +124 -0
- package/linthost/rules_prefer_destructuring.go +98 -0
- package/linthost/rules_prefer_named_capture_group.go +129 -0
- package/linthost/rules_prefer_rest_params.go +94 -0
- package/linthost/rules_problems.go +41 -30
- package/linthost/rules_promise.go +1128 -73
- package/linthost/rules_protos.go +2 -2
- package/linthost/rules_react.go +773 -0
- package/linthost/rules_react_extras.go +227 -0
- package/linthost/rules_react_hooks.go +848 -0
- package/linthost/rules_react_perf.go +293 -0
- package/linthost/rules_react_refresh.go +583 -0
- package/linthost/rules_regexp.go +410 -0
- package/linthost/rules_security.go +830 -0
- package/linthost/rules_self.go +2 -2
- package/linthost/rules_solid.go +1073 -0
- package/linthost/rules_sort_imports.go +69 -0
- package/linthost/rules_sort_keys.go +134 -0
- package/linthost/rules_storybook.go +1176 -0
- package/linthost/rules_strings.go +4 -4
- package/linthost/rules_suggestions.go +38 -38
- package/linthost/rules_tanstack_query.go +844 -0
- package/linthost/rules_testing_library.go +1204 -0
- package/linthost/rules_throw.go +1 -1
- package/linthost/rules_ts.go +19 -19
- package/linthost/rules_ts_async.go +399 -0
- package/linthost/rules_ts_class_literal_property_style.go +115 -0
- package/linthost/rules_ts_consistent_type_exports.go +256 -0
- package/linthost/rules_ts_explicit_function_return_type.go +67 -0
- package/linthost/rules_ts_extra.go +155 -36
- package/linthost/rules_ts_no_base_to_string.go +218 -0
- package/linthost/rules_ts_no_confusing_void.go +72 -0
- package/linthost/rules_ts_no_deprecated.go +195 -0
- package/linthost/rules_ts_no_for_in_array.go +84 -0
- package/linthost/rules_ts_no_magic_numbers.go +124 -0
- package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
- package/linthost/rules_ts_no_misused_spread.go +104 -0
- package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
- package/linthost/rules_ts_no_restricted_types.go +62 -0
- package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
- package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
- package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
- package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
- package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
- package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
- package/linthost/rules_ts_no_unsafe_argument.go +82 -0
- package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
- package/linthost/rules_ts_no_unsafe_call.go +82 -0
- package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
- package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
- package/linthost/rules_ts_no_unsafe_return.go +126 -0
- package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
- package/linthost/rules_ts_no_useless_constructor.go +52 -0
- package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
- package/linthost/rules_ts_parameter_properties.go +38 -0
- package/linthost/rules_ts_prefer_find.go +178 -0
- package/linthost/rules_ts_prefer_includes.go +255 -0
- package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
- package/linthost/rules_ts_prefer_optional_chain.go +228 -0
- package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
- package/linthost/rules_ts_prefer_readonly.go +73 -0
- package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
- package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
- package/linthost/rules_ts_prefer_return_this_type.go +135 -0
- package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
- package/linthost/rules_ts_promise_function_async.go +77 -0
- package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
- package/linthost/rules_ts_require_array_sort_compare.go +96 -0
- package/linthost/rules_ts_restrict_plus_operands.go +127 -0
- package/linthost/rules_ts_restrict_template_expressions.go +95 -0
- package/linthost/rules_ts_simple.go +387 -0
- package/linthost/rules_ts_sort_type_constituents.go +144 -0
- package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
- package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
- package/linthost/rules_ts_unbound_method.go +126 -0
- package/linthost/rules_tsdoc.go +136 -0
- package/linthost/rules_unicorn_better_regex.go +27 -0
- package/linthost/rules_unicorn_catch_error_name.go +46 -0
- package/linthost/rules_unicorn_consistent_assert.go +47 -0
- package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
- package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
- package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
- package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
- package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
- package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
- package/linthost/rules_unicorn_custom_error_definition.go +138 -0
- package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
- package/linthost/rules_unicorn_error_message.go +64 -0
- package/linthost/rules_unicorn_escape_case.go +51 -0
- package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
- package/linthost/rules_unicorn_explicit_length_check.go +88 -0
- package/linthost/rules_unicorn_filename_case.go +29 -0
- package/linthost/rules_unicorn_import_style.go +28 -0
- package/linthost/rules_unicorn_isolated_functions.go +29 -0
- package/linthost/rules_unicorn_new_for_builtins.go +87 -0
- package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
- package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
- package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
- package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
- package/linthost/rules_unicorn_no_array_for_each.go +40 -0
- package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
- package/linthost/rules_unicorn_no_array_reduce.go +41 -0
- package/linthost/rules_unicorn_no_array_reverse.go +44 -0
- package/linthost/rules_unicorn_no_array_sort.go +43 -0
- package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
- package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
- package/linthost/rules_unicorn_no_console_spaces.go +61 -0
- package/linthost/rules_unicorn_no_document_cookie.go +41 -0
- package/linthost/rules_unicorn_no_empty_file.go +44 -0
- package/linthost/rules_unicorn_no_for_loop.go +102 -0
- package/linthost/rules_unicorn_no_hex_escape.go +42 -0
- package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
- package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
- package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
- package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
- package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
- package/linthost/rules_unicorn_no_lonely_if.go +44 -0
- package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
- package/linthost/rules_unicorn_no_named_default.go +54 -0
- package/linthost/rules_unicorn_no_negated_condition.go +85 -0
- package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
- package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
- package/linthost/rules_unicorn_no_new_array.go +30 -0
- package/linthost/rules_unicorn_no_new_buffer.go +31 -0
- package/linthost/rules_unicorn_no_null.go +24 -0
- package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
- package/linthost/rules_unicorn_no_process_exit.go +43 -0
- package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
- package/linthost/rules_unicorn_no_static_only_class.go +56 -0
- package/linthost/rules_unicorn_no_thenable.go +74 -0
- package/linthost/rules_unicorn_no_this_assignment.go +35 -0
- package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
- package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
- package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
- package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
- package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
- package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
- package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
- package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
- package/linthost/rules_unicorn_no_unused_properties.go +30 -0
- package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
- package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
- package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
- package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
- package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
- package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
- package/linthost/rules_unicorn_no_useless_spread.go +67 -0
- package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
- package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
- package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
- package/linthost/rules_unicorn_number_literal_case.go +69 -0
- package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
- package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
- package/linthost/rules_unicorn_prefer_array_find.go +51 -0
- package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
- package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
- package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
- package/linthost/rules_unicorn_prefer_array_some.go +67 -0
- package/linthost/rules_unicorn_prefer_at.go +77 -0
- package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
- package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
- package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
- package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
- package/linthost/rules_unicorn_prefer_code_point.go +49 -0
- package/linthost/rules_unicorn_prefer_date_now.go +78 -0
- package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
- package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
- package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
- package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
- package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
- package/linthost/rules_unicorn_prefer_event_target.go +36 -0
- package/linthost/rules_unicorn_prefer_export_from.go +129 -0
- package/linthost/rules_unicorn_prefer_global_this.go +127 -0
- package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
- package/linthost/rules_unicorn_prefer_includes.go +149 -0
- package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
- package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
- package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
- package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
- package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
- package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
- package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
- package/linthost/rules_unicorn_prefer_module.go +50 -0
- package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
- package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
- package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
- package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
- package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
- package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
- package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
- package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
- package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
- package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
- package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
- package/linthost/rules_unicorn_prefer_set_has.go +42 -0
- package/linthost/rules_unicorn_prefer_set_size.go +48 -0
- package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
- package/linthost/rules_unicorn_prefer_single_call.go +96 -0
- package/linthost/rules_unicorn_prefer_spread.go +51 -0
- package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
- package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
- package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
- package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
- package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
- package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
- package/linthost/rules_unicorn_prefer_switch.go +103 -0
- package/linthost/rules_unicorn_prefer_ternary.go +71 -0
- package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
- package/linthost/rules_unicorn_prefer_type_error.go +127 -0
- package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
- package/linthost/rules_unicorn_relative_url_style.go +49 -0
- package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
- package/linthost/rules_unicorn_require_module_attributes.go +54 -0
- package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
- package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
- package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
- package/linthost/rules_unicorn_string_content.go +27 -0
- package/linthost/rules_unicorn_switch_case_braces.go +42 -0
- package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
- package/linthost/rules_unicorn_template_indent.go +28 -0
- package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
- package/linthost/rules_unicorn_throw_new_error.go +61 -0
- package/linthost/rules_var.go +4 -4
- package/linthost/rules_vitest.go +568 -0
- package/package.json +3 -3
- package/plugin/main.go +49 -3
- package/rule/astutil/astutil.go +10 -3
- package/rule/rule.go +12 -10
- package/src/defaultFormat.ts +11 -8
- package/src/index.ts +40 -16
- package/src/structures/ITtscLintConfig.ts +12 -6
- package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
- package/src/structures/TtscLintRuleSetting.ts +55 -0
- package/src/structures/index.ts +3 -4
- package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
- package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
- package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
- package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
- package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
- package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
- package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
- package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
- package/src/structures/rules/ITtscLintJestRules.ts +220 -0
- package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
- package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
- package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
- package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
- package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
- package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
- package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
- package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
- package/src/structures/rules/ITtscLintReactRules.ts +321 -0
- package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
- package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
- package/src/structures/rules/ITtscLintRules.ts +77 -0
- package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
- package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
- package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
- package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
- package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
- package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
- package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
- package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
- package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
- package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
- package/src/structures/rules/index.ts +31 -0
- package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
- package/lib/structures/TtscLintRule.d.ts +0 -17
- package/lib/structures/TtscLintRule.js.map +0 -1
- package/lib/structures/TtscLintRuleMap.d.ts +0 -46
- package/lib/structures/TtscLintRuleMap.js.map +0 -1
- package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
- package/lib/structures/TtscLintRuleOptions.js.map +0 -1
- package/src/structures/TtscLintRule.ts +0 -160
- package/src/structures/TtscLintRuleMap.ts +0 -55
- package/src/structures/TtscLintRuleOptions.ts +0 -151
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// typescript/no-unnecessary-template-expression: a backtick literal
|
|
2
|
+
// that carries no template-only behavior is just noise — a regular
|
|
3
|
+
// string literal renders the same characters with one fewer indirection.
|
|
4
|
+
// typescript-eslint:
|
|
5
|
+
// https://typescript-eslint.io/rules/no-unnecessary-template-expression/
|
|
6
|
+
//
|
|
7
|
+
// Type-aware. Three shapes collapse cleanly to a regular string literal:
|
|
8
|
+
//
|
|
9
|
+
// - A `NoSubstitutionTemplateLiteral` with no escaped backticks. The
|
|
10
|
+
// `\`` escape is what would force the template form once converted —
|
|
11
|
+
// a regular `"..."` does not need to escape a backtick, but the
|
|
12
|
+
// surrounding lint expects an exact source-preserving rewrite, so
|
|
13
|
+
// skip the literal when one is present.
|
|
14
|
+
// - A `TemplateExpression` whose head and the one span's tail text are
|
|
15
|
+
// both empty AND whose single span's expression is statically
|
|
16
|
+
// string-typed. `` `${name}` `` then coerces a known-string value
|
|
17
|
+
// through `String()` for no reason; just use `name`.
|
|
18
|
+
// - A `TemplateExpression` whose single span's expression is a
|
|
19
|
+
// `StringLiteral` or `NoSubstitutionTemplateLiteral` literal and
|
|
20
|
+
// whose head / tail text are empty — `` `${"abc"}` `` is the same
|
|
21
|
+
// as `"abc"`, independent of any Checker state.
|
|
22
|
+
//
|
|
23
|
+
// Tagged templates (`` tag`abc` ``, `` tag`${x}` ``) are excluded
|
|
24
|
+
// because the tag function reads the raw template payload and would
|
|
25
|
+
// observe a different shape if the literal were rewritten to a string.
|
|
26
|
+
package linthost
|
|
27
|
+
|
|
28
|
+
import (
|
|
29
|
+
"strings"
|
|
30
|
+
|
|
31
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
32
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
type noUnnecessaryTemplateExpression struct{}
|
|
36
|
+
|
|
37
|
+
func (noUnnecessaryTemplateExpression) Name() string {
|
|
38
|
+
return "typescript/no-unnecessary-template-expression"
|
|
39
|
+
}
|
|
40
|
+
func (noUnnecessaryTemplateExpression) NeedsTypeChecker() bool {
|
|
41
|
+
return true
|
|
42
|
+
}
|
|
43
|
+
func (noUnnecessaryTemplateExpression) Visits() []shimast.Kind {
|
|
44
|
+
return []shimast.Kind{
|
|
45
|
+
shimast.KindNoSubstitutionTemplateLiteral,
|
|
46
|
+
shimast.KindTemplateExpression,
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
func (noUnnecessaryTemplateExpression) Check(ctx *Context, node *shimast.Node) {
|
|
50
|
+
// Tag-function readers (`String.raw`, `dedent`, `gql`, `css`, …) see
|
|
51
|
+
// the raw template payload, so rewriting to a string literal would
|
|
52
|
+
// change observable behavior. Skip the entire literal in that case,
|
|
53
|
+
// matching `no-useless-escape`.
|
|
54
|
+
if isInsideTaggedTemplate(node) {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
switch node.Kind {
|
|
58
|
+
case shimast.KindNoSubstitutionTemplateLiteral:
|
|
59
|
+
lit := node.AsNoSubstitutionTemplateLiteral()
|
|
60
|
+
if lit == nil {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
// `RawText` is the verbatim payload between the backticks. The
|
|
64
|
+
// presence of `\`` means the source intentionally escapes a
|
|
65
|
+
// backtick that the template-literal form requires; leave such
|
|
66
|
+
// literals alone so the rewrite is always a pure source change.
|
|
67
|
+
if strings.Contains(lit.RawText, "\\`") {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
ctx.Report(node, noUnnecessaryTemplateExpressionMessage)
|
|
71
|
+
case shimast.KindTemplateExpression:
|
|
72
|
+
expr := node.AsTemplateExpression()
|
|
73
|
+
if expr == nil || expr.TemplateSpans == nil {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
spans := expr.TemplateSpans.Nodes
|
|
77
|
+
if len(spans) != 1 {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
// Head text must be empty: `` `prefix${...}` `` has surrounding
|
|
81
|
+
// chars that are load-bearing and cannot collapse.
|
|
82
|
+
head := expr.Head
|
|
83
|
+
if head == nil || templateLiteralLikeText(head) != "" {
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
span := spans[0].AsTemplateSpan()
|
|
87
|
+
if span == nil || span.Expression == nil || span.Literal == nil {
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
// Tail text must be empty for the same reason as the head.
|
|
91
|
+
if templateLiteralLikeText(span.Literal) != "" {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
inner := span.Expression
|
|
95
|
+
// A literal string operand collapses without consulting the
|
|
96
|
+
// Checker — `` `${"abc"}` `` is identical to `"abc"`.
|
|
97
|
+
if inner.Kind == shimast.KindStringLiteral ||
|
|
98
|
+
inner.Kind == shimast.KindNoSubstitutionTemplateLiteral {
|
|
99
|
+
ctx.Report(node, noUnnecessaryTemplateExpressionMessage)
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
if ctx.Checker == nil {
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
t := ctx.Checker.GetTypeAtLocation(inner)
|
|
106
|
+
if t == nil {
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
if isStringTypedForTemplateCollapse(t) {
|
|
110
|
+
ctx.Report(node, noUnnecessaryTemplateExpressionMessage)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const noUnnecessaryTemplateExpressionMessage = "Unnecessary template literal — replace the backtick form with a regular string literal."
|
|
116
|
+
|
|
117
|
+
// templateLiteralLikeText returns the parsed text payload of a
|
|
118
|
+
// TemplateHead / TemplateMiddle / TemplateTail / NoSubstitutionTemplate-
|
|
119
|
+
// Literal node. The same `Text` field lives on every shape via the
|
|
120
|
+
// shared `TemplateLiteralLikeNodeBase`, so we dispatch by kind.
|
|
121
|
+
func templateLiteralLikeText(node *shimast.Node) string {
|
|
122
|
+
if node == nil {
|
|
123
|
+
return ""
|
|
124
|
+
}
|
|
125
|
+
switch node.Kind {
|
|
126
|
+
case shimast.KindTemplateHead:
|
|
127
|
+
if h := node.AsTemplateHead(); h != nil {
|
|
128
|
+
return h.Text
|
|
129
|
+
}
|
|
130
|
+
case shimast.KindTemplateMiddle:
|
|
131
|
+
if m := node.AsTemplateMiddle(); m != nil {
|
|
132
|
+
return m.Text
|
|
133
|
+
}
|
|
134
|
+
case shimast.KindTemplateTail:
|
|
135
|
+
if tl := node.AsTemplateTail(); tl != nil {
|
|
136
|
+
return tl.Text
|
|
137
|
+
}
|
|
138
|
+
case shimast.KindNoSubstitutionTemplateLiteral:
|
|
139
|
+
if l := node.AsNoSubstitutionTemplateLiteral(); l != nil {
|
|
140
|
+
return l.Text
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return ""
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// isStringTypedForTemplateCollapse reports whether `t` is provably a
|
|
147
|
+
// string-like type whose interpolation in `` `${x}` `` is a no-op
|
|
148
|
+
// coercion. `any` / `unknown` / `never` are deliberately excluded so the
|
|
149
|
+
// rule does not light up on generic helpers — the upstream rule's
|
|
150
|
+
// `allowAny` semantics match this conservative choice. Union and
|
|
151
|
+
// intersection types collapse only when every constituent is itself
|
|
152
|
+
// string-like.
|
|
153
|
+
func isStringTypedForTemplateCollapse(t *shimchecker.Type) bool {
|
|
154
|
+
if t == nil {
|
|
155
|
+
return false
|
|
156
|
+
}
|
|
157
|
+
flags := t.Flags()
|
|
158
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
159
|
+
return false
|
|
160
|
+
}
|
|
161
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
162
|
+
parts := t.Types()
|
|
163
|
+
if len(parts) == 0 {
|
|
164
|
+
return false
|
|
165
|
+
}
|
|
166
|
+
for _, part := range parts {
|
|
167
|
+
if !isStringTypedForTemplateCollapse(part) {
|
|
168
|
+
return false
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return true
|
|
172
|
+
}
|
|
173
|
+
return flags&shimchecker.TypeFlagsStringLike != 0
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
func init() {
|
|
177
|
+
Register(noUnnecessaryTemplateExpression{})
|
|
178
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// typescript/no-unnecessary-type-arguments: when a generic's explicit
|
|
2
|
+
// type argument matches the corresponding parameter's declared default,
|
|
3
|
+
// the argument is just restating the default. Dropping it leaves the
|
|
4
|
+
// identical type because TypeScript would substitute the default
|
|
5
|
+
// anyway. typescript-eslint:
|
|
6
|
+
// https://typescript-eslint.io/rules/no-unnecessary-type-arguments/
|
|
7
|
+
package linthost
|
|
8
|
+
|
|
9
|
+
import (
|
|
10
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
// noUnnecessaryTypeArguments visits the three syntactic positions that
|
|
14
|
+
// carry an explicit type-argument list — `Foo<T>` in type position,
|
|
15
|
+
// `new Foo<T>(…)`, and `foo<T>(…)` — and compares each argument against
|
|
16
|
+
// the parameter default declared on the generic. The check is type-aware
|
|
17
|
+
// because matching against the default requires resolving the generic's
|
|
18
|
+
// symbol back to its parameter list; the AST alone doesn't carry that
|
|
19
|
+
// link.
|
|
20
|
+
//
|
|
21
|
+
// The rule reports the rightmost run of arguments that equal their
|
|
22
|
+
// defaults: a trailing default-equal arg can be dropped without
|
|
23
|
+
// affecting the leftmost positional args. Once a non-equal arg appears
|
|
24
|
+
// scanning from the right, every argument to its left must stay
|
|
25
|
+
// explicit even when it equals its own default — TypeScript can only
|
|
26
|
+
// omit a contiguous suffix.
|
|
27
|
+
type noUnnecessaryTypeArguments struct{}
|
|
28
|
+
|
|
29
|
+
func (noUnnecessaryTypeArguments) Name() string {
|
|
30
|
+
return "typescript/no-unnecessary-type-arguments"
|
|
31
|
+
}
|
|
32
|
+
func (noUnnecessaryTypeArguments) NeedsTypeChecker() bool {
|
|
33
|
+
return true
|
|
34
|
+
}
|
|
35
|
+
func (noUnnecessaryTypeArguments) Visits() []shimast.Kind {
|
|
36
|
+
return []shimast.Kind{
|
|
37
|
+
shimast.KindTypeReference,
|
|
38
|
+
shimast.KindExpressionWithTypeArguments,
|
|
39
|
+
shimast.KindCallExpression,
|
|
40
|
+
shimast.KindNewExpression,
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
func (noUnnecessaryTypeArguments) Check(ctx *Context, node *shimast.Node) {
|
|
44
|
+
if ctx.Checker == nil {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
args, nameNode := noUnnecessaryTypeArgumentsExtract(node)
|
|
48
|
+
if len(args) == 0 || nameNode == nil {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
params := noUnnecessaryTypeArgumentsResolveParameters(ctx, nameNode)
|
|
52
|
+
if len(params) == 0 {
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
// Walk from the right: report contiguous trailing args that equal
|
|
56
|
+
// their declared defaults. Stop at the first mismatch — only the
|
|
57
|
+
// suffix is droppable.
|
|
58
|
+
for i := len(args) - 1; i >= 0; i-- {
|
|
59
|
+
if i >= len(params) {
|
|
60
|
+
continue
|
|
61
|
+
}
|
|
62
|
+
param := params[i]
|
|
63
|
+
if param == nil {
|
|
64
|
+
break
|
|
65
|
+
}
|
|
66
|
+
defaultNode := param.DefaultType
|
|
67
|
+
if defaultNode == nil {
|
|
68
|
+
break
|
|
69
|
+
}
|
|
70
|
+
argNode := args[i]
|
|
71
|
+
if argNode == nil {
|
|
72
|
+
break
|
|
73
|
+
}
|
|
74
|
+
argType := ctx.Checker.GetTypeFromTypeNode(argNode)
|
|
75
|
+
defaultType := ctx.Checker.GetTypeFromTypeNode(defaultNode)
|
|
76
|
+
if argType == nil || defaultType == nil {
|
|
77
|
+
break
|
|
78
|
+
}
|
|
79
|
+
if !ctx.Checker.IsTypeAssignableTo(argType, defaultType) {
|
|
80
|
+
break
|
|
81
|
+
}
|
|
82
|
+
if !ctx.Checker.IsTypeAssignableTo(defaultType, argType) {
|
|
83
|
+
break
|
|
84
|
+
}
|
|
85
|
+
ctx.Report(argNode, "This type argument equals the declared default — drop it.")
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// noUnnecessaryTypeArgumentsExtract returns the explicit type-argument
|
|
90
|
+
// nodes and the identifier-or-property-access naming the generic the
|
|
91
|
+
// arguments apply to. Returns (nil, nil) when the node carries no
|
|
92
|
+
// explicit type arguments — the rule only fires on opt-in argument
|
|
93
|
+
// lists.
|
|
94
|
+
func noUnnecessaryTypeArgumentsExtract(node *shimast.Node) ([]*shimast.Node, *shimast.Node) {
|
|
95
|
+
switch node.Kind {
|
|
96
|
+
case shimast.KindTypeReference:
|
|
97
|
+
ref := node.AsTypeReferenceNode()
|
|
98
|
+
if ref == nil || ref.TypeArguments == nil {
|
|
99
|
+
return nil, nil
|
|
100
|
+
}
|
|
101
|
+
return ref.TypeArguments.Nodes, ref.TypeName
|
|
102
|
+
case shimast.KindExpressionWithTypeArguments:
|
|
103
|
+
ewta := node.AsExpressionWithTypeArguments()
|
|
104
|
+
if ewta == nil || ewta.TypeArguments == nil {
|
|
105
|
+
return nil, nil
|
|
106
|
+
}
|
|
107
|
+
return ewta.TypeArguments.Nodes, ewta.Expression
|
|
108
|
+
case shimast.KindCallExpression:
|
|
109
|
+
call := node.AsCallExpression()
|
|
110
|
+
if call == nil || call.TypeArguments == nil {
|
|
111
|
+
return nil, nil
|
|
112
|
+
}
|
|
113
|
+
return call.TypeArguments.Nodes, call.Expression
|
|
114
|
+
case shimast.KindNewExpression:
|
|
115
|
+
ne := node.AsNewExpression()
|
|
116
|
+
if ne == nil || ne.TypeArguments == nil {
|
|
117
|
+
return nil, nil
|
|
118
|
+
}
|
|
119
|
+
return ne.TypeArguments.Nodes, ne.Expression
|
|
120
|
+
}
|
|
121
|
+
return nil, nil
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// noUnnecessaryTypeArgumentsResolveParameters resolves `nameNode` to a
|
|
125
|
+
// symbol and returns the type parameters declared on the first
|
|
126
|
+
// declaration that carries one. Returns nil when the symbol does not
|
|
127
|
+
// resolve or no declaration carries a type-parameter list — the rule
|
|
128
|
+
// then has nothing to compare against.
|
|
129
|
+
func noUnnecessaryTypeArgumentsResolveParameters(ctx *Context, nameNode *shimast.Node) []*shimast.TypeParameterDeclaration {
|
|
130
|
+
if nameNode == nil {
|
|
131
|
+
return nil
|
|
132
|
+
}
|
|
133
|
+
target := nameNode
|
|
134
|
+
// For property accesses (`a.b.Foo<T>`) the symbol-bearing identifier
|
|
135
|
+
// is the rightmost name, not the dotted root.
|
|
136
|
+
if target.Kind == shimast.KindPropertyAccessExpression {
|
|
137
|
+
access := target.AsPropertyAccessExpression()
|
|
138
|
+
if access == nil || access.Name() == nil {
|
|
139
|
+
return nil
|
|
140
|
+
}
|
|
141
|
+
target = access.Name()
|
|
142
|
+
} else if target.Kind == shimast.KindQualifiedName {
|
|
143
|
+
qn := target.AsQualifiedName()
|
|
144
|
+
if qn == nil || qn.Right == nil {
|
|
145
|
+
return nil
|
|
146
|
+
}
|
|
147
|
+
target = qn.Right
|
|
148
|
+
}
|
|
149
|
+
symbol := ctx.Checker.GetSymbolAtLocation(target)
|
|
150
|
+
if symbol == nil {
|
|
151
|
+
return nil
|
|
152
|
+
}
|
|
153
|
+
for _, decl := range symbol.Declarations {
|
|
154
|
+
if list := noUnnecessaryTypeArgumentsParamList(decl); list != nil {
|
|
155
|
+
return list
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return nil
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// noUnnecessaryTypeArgumentsParamList returns the type-parameter list on
|
|
162
|
+
// `decl` when the declaration kind carries one, or nil otherwise. The
|
|
163
|
+
// enumerated kinds match the host types TypeScript binds generic
|
|
164
|
+
// arguments against — function-shaped declarations, class / interface
|
|
165
|
+
// / alias declarations, and the method-like signatures that may appear
|
|
166
|
+
// inside them.
|
|
167
|
+
func noUnnecessaryTypeArgumentsParamList(decl *shimast.Node) []*shimast.TypeParameterDeclaration {
|
|
168
|
+
if decl == nil {
|
|
169
|
+
return nil
|
|
170
|
+
}
|
|
171
|
+
var list *shimast.TypeParameterList
|
|
172
|
+
switch decl.Kind {
|
|
173
|
+
case shimast.KindFunctionDeclaration:
|
|
174
|
+
if d := decl.AsFunctionDeclaration(); d != nil {
|
|
175
|
+
list = d.TypeParameters
|
|
176
|
+
}
|
|
177
|
+
case shimast.KindClassDeclaration:
|
|
178
|
+
if d := decl.AsClassDeclaration(); d != nil {
|
|
179
|
+
list = d.TypeParameters
|
|
180
|
+
}
|
|
181
|
+
case shimast.KindClassExpression:
|
|
182
|
+
if d := decl.AsClassExpression(); d != nil {
|
|
183
|
+
list = d.TypeParameters
|
|
184
|
+
}
|
|
185
|
+
case shimast.KindInterfaceDeclaration:
|
|
186
|
+
if d := decl.AsInterfaceDeclaration(); d != nil {
|
|
187
|
+
list = d.TypeParameters
|
|
188
|
+
}
|
|
189
|
+
case shimast.KindTypeAliasDeclaration:
|
|
190
|
+
if d := decl.AsTypeAliasDeclaration(); d != nil {
|
|
191
|
+
list = d.TypeParameters
|
|
192
|
+
}
|
|
193
|
+
case shimast.KindMethodDeclaration:
|
|
194
|
+
if d := decl.AsMethodDeclaration(); d != nil {
|
|
195
|
+
list = d.TypeParameters
|
|
196
|
+
}
|
|
197
|
+
case shimast.KindMethodSignature:
|
|
198
|
+
if d := decl.AsMethodSignatureDeclaration(); d != nil {
|
|
199
|
+
list = d.TypeParameters
|
|
200
|
+
}
|
|
201
|
+
case shimast.KindFunctionExpression:
|
|
202
|
+
if d := decl.AsFunctionExpression(); d != nil {
|
|
203
|
+
list = d.TypeParameters
|
|
204
|
+
}
|
|
205
|
+
case shimast.KindArrowFunction:
|
|
206
|
+
if d := decl.AsArrowFunction(); d != nil {
|
|
207
|
+
list = d.TypeParameters
|
|
208
|
+
}
|
|
209
|
+
case shimast.KindCallSignature:
|
|
210
|
+
if d := decl.AsCallSignatureDeclaration(); d != nil {
|
|
211
|
+
list = d.TypeParameters
|
|
212
|
+
}
|
|
213
|
+
case shimast.KindConstructSignature:
|
|
214
|
+
if d := decl.AsConstructSignatureDeclaration(); d != nil {
|
|
215
|
+
list = d.TypeParameters
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if list == nil || len(list.Nodes) == 0 {
|
|
219
|
+
return nil
|
|
220
|
+
}
|
|
221
|
+
out := make([]*shimast.TypeParameterDeclaration, 0, len(list.Nodes))
|
|
222
|
+
for _, n := range list.Nodes {
|
|
223
|
+
if n == nil {
|
|
224
|
+
out = append(out, nil)
|
|
225
|
+
continue
|
|
226
|
+
}
|
|
227
|
+
out = append(out, n.AsTypeParameterDeclaration())
|
|
228
|
+
}
|
|
229
|
+
return out
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
func init() {
|
|
233
|
+
Register(noUnnecessaryTypeArguments{})
|
|
234
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// typescript/no-unnecessary-type-assertion: `x as T`, `<T>x`, and `x!`
|
|
2
|
+
// add nothing when the static type of `x` already equals `T` (or is
|
|
3
|
+
// already non-nullable, for the `!` form). typescript-eslint
|
|
4
|
+
// recommended-type-checked:
|
|
5
|
+
// https://typescript-eslint.io/rules/no-unnecessary-type-assertion/
|
|
6
|
+
package linthost
|
|
7
|
+
|
|
8
|
+
import (
|
|
9
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
10
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
// noUnnecessaryTypeAssertion reports redundant `as`, type-prefix, and
|
|
14
|
+
// non-null assertions. Implementation notes:
|
|
15
|
+
//
|
|
16
|
+
// - Type-aware: requires the Checker so the source expression's static
|
|
17
|
+
// type can be compared against the asserted target. The shim
|
|
18
|
+
// re-exports the unexported `GetTypeFromTypeNode` and
|
|
19
|
+
// `IsTypeAssignableTo` methods directly, the same plumbing that the
|
|
20
|
+
// sibling `non-nullable-type-assertion-style` rule uses.
|
|
21
|
+
// - Symmetric assignability is used in place of literal type identity
|
|
22
|
+
// for the same reason as `non-nullable-type-assertion-style`: the
|
|
23
|
+
// Checker may widen literal types on one side and not the other
|
|
24
|
+
// (e.g. `"foo" as string` versus the literal `"foo"`), so requiring
|
|
25
|
+
// both directions of assignability stands in for structural
|
|
26
|
+
// equivalence without over-firing on widening.
|
|
27
|
+
// - The `as const` form is intentionally skipped because it produces
|
|
28
|
+
// a strictly narrower type than the source expression; `as const`
|
|
29
|
+
// assertions on already-literal expressions are handled by the
|
|
30
|
+
// companion `typescript/prefer-as-const` rule.
|
|
31
|
+
// - For `x!` (NonNullExpression) the rule fires when the inner
|
|
32
|
+
// expression's static type has no `null` or `undefined`
|
|
33
|
+
// constituent — the `!` strips nothing.
|
|
34
|
+
type noUnnecessaryTypeAssertion struct{}
|
|
35
|
+
|
|
36
|
+
func (noUnnecessaryTypeAssertion) Name() string {
|
|
37
|
+
return "typescript/no-unnecessary-type-assertion"
|
|
38
|
+
}
|
|
39
|
+
func (noUnnecessaryTypeAssertion) NeedsTypeChecker() bool {
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
42
|
+
func (noUnnecessaryTypeAssertion) Visits() []shimast.Kind {
|
|
43
|
+
return []shimast.Kind{
|
|
44
|
+
shimast.KindAsExpression,
|
|
45
|
+
shimast.KindTypeAssertionExpression,
|
|
46
|
+
shimast.KindNonNullExpression,
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
func (noUnnecessaryTypeAssertion) Check(ctx *Context, node *shimast.Node) {
|
|
50
|
+
if ctx.Checker == nil {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
switch node.Kind {
|
|
54
|
+
case shimast.KindAsExpression:
|
|
55
|
+
as := node.AsAsExpression()
|
|
56
|
+
if as == nil || as.Expression == nil || as.Type == nil {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
if isConstTypeReference(as.Type) {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
noUnnecessaryTypeAssertionCheckAssertion(ctx, node, as.Expression, as.Type)
|
|
63
|
+
case shimast.KindTypeAssertionExpression:
|
|
64
|
+
ta := node.AsTypeAssertion()
|
|
65
|
+
if ta == nil || ta.Expression == nil || ta.Type == nil {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
if isConstTypeReference(ta.Type) {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
noUnnecessaryTypeAssertionCheckAssertion(ctx, node, ta.Expression, ta.Type)
|
|
72
|
+
case shimast.KindNonNullExpression:
|
|
73
|
+
nn := node.AsNonNullExpression()
|
|
74
|
+
if nn == nil || nn.Expression == nil {
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
sourceType := ctx.Checker.GetTypeAtLocation(nn.Expression)
|
|
78
|
+
if sourceType == nil {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
if noUnnecessaryTypeAssertionIsNullable(sourceType) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
ctx.Report(node, "This assertion is unnecessary since it does not change the type of the expression.")
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// noUnnecessaryTypeAssertionCheckAssertion runs the shared logic for
|
|
89
|
+
// `expr as T` and `<T>expr`: report when the asserted type and source
|
|
90
|
+
// type are mutually assignable.
|
|
91
|
+
func noUnnecessaryTypeAssertionCheckAssertion(ctx *Context, node, expr, typeNode *shimast.Node) {
|
|
92
|
+
sourceType := ctx.Checker.GetTypeAtLocation(expr)
|
|
93
|
+
if sourceType == nil {
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
assertedType := ctx.Checker.GetTypeFromTypeNode(typeNode)
|
|
97
|
+
if assertedType == nil {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
// Bidirectional assignability stands in for type identity: see the
|
|
101
|
+
// note on `non-nullable-type-assertion-style`. The assertion is
|
|
102
|
+
// redundant only when both sides describe the same set of values.
|
|
103
|
+
if !ctx.Checker.IsTypeAssignableTo(sourceType, assertedType) {
|
|
104
|
+
return
|
|
105
|
+
}
|
|
106
|
+
if !ctx.Checker.IsTypeAssignableTo(assertedType, sourceType) {
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
ctx.Report(node, "This assertion is unnecessary since it does not change the type of the expression.")
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// isConstTypeReference reports whether the type node is the bare
|
|
113
|
+
// identifier `const`, i.e. the `as const` syntax. The TypeScript parser
|
|
114
|
+
// represents `as const` as an AsExpression / TypeAssertion whose type
|
|
115
|
+
// node is a TypeReference to the identifier `const` rather than a real
|
|
116
|
+
// type — every other rule that touches assertion nodes needs to skip
|
|
117
|
+
// it because it is structurally an assertion but semantically a const
|
|
118
|
+
// context request.
|
|
119
|
+
func isConstTypeReference(typeNode *shimast.Node) bool {
|
|
120
|
+
if typeNode == nil || typeNode.Kind != shimast.KindTypeReference {
|
|
121
|
+
return false
|
|
122
|
+
}
|
|
123
|
+
ref := typeNode.AsTypeReferenceNode()
|
|
124
|
+
if ref == nil {
|
|
125
|
+
return false
|
|
126
|
+
}
|
|
127
|
+
return identifierText(ref.TypeName) == "const"
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// noUnnecessaryTypeAssertionIsNullable reports whether t carries `null`
|
|
131
|
+
// or `undefined` at the top level or inside a union constituent. The
|
|
132
|
+
// shape mirrors `nonNullableTypeAssertionStyleIsNullable` because both
|
|
133
|
+
// rules answer the same question about the source expression.
|
|
134
|
+
func noUnnecessaryTypeAssertionIsNullable(t *shimchecker.Type) bool {
|
|
135
|
+
if t == nil {
|
|
136
|
+
return false
|
|
137
|
+
}
|
|
138
|
+
flags := t.Flags()
|
|
139
|
+
if flags&(shimchecker.TypeFlagsNull|shimchecker.TypeFlagsUndefined) != 0 {
|
|
140
|
+
return true
|
|
141
|
+
}
|
|
142
|
+
if flags&shimchecker.TypeFlagsUnion != 0 {
|
|
143
|
+
for _, part := range t.Types() {
|
|
144
|
+
if part == nil {
|
|
145
|
+
continue
|
|
146
|
+
}
|
|
147
|
+
if noUnnecessaryTypeAssertionIsNullable(part) {
|
|
148
|
+
return true
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return false
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
func init() {
|
|
156
|
+
Register(noUnnecessaryTypeAssertion{})
|
|
157
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// typescript/no-unsafe-argument: passing an `any`-typed value into a
|
|
2
|
+
// concretely typed parameter discards every static check the function's
|
|
3
|
+
// signature would otherwise enforce. The call still runs, but the value
|
|
4
|
+
// flows in unchecked and downstream uses operate on whatever the
|
|
5
|
+
// runtime actually supplies. typescript-eslint:
|
|
6
|
+
// https://typescript-eslint.io/rules/no-unsafe-argument/
|
|
7
|
+
//
|
|
8
|
+
// Type-aware. The rule visits `CallExpression` and `NewExpression` and
|
|
9
|
+
// reports each argument whose static type carries `TypeFlagsAny` when
|
|
10
|
+
// the callee's resolved type is itself a concrete (non-`any`) callable.
|
|
11
|
+
// `unknown` is intentionally NOT flagged: it forces a narrowing
|
|
12
|
+
// assertion before the call, which is the explicit ergonomic the
|
|
13
|
+
// upstream rule pushes toward.
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import (
|
|
17
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
type noUnsafeArgument struct{}
|
|
21
|
+
|
|
22
|
+
func (noUnsafeArgument) Name() string { return "typescript/no-unsafe-argument" }
|
|
23
|
+
func (noUnsafeArgument) NeedsTypeChecker() bool {
|
|
24
|
+
return true
|
|
25
|
+
}
|
|
26
|
+
func (noUnsafeArgument) Visits() []shimast.Kind {
|
|
27
|
+
return []shimast.Kind{
|
|
28
|
+
shimast.KindCallExpression,
|
|
29
|
+
shimast.KindNewExpression,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
func (noUnsafeArgument) Check(ctx *Context, node *shimast.Node) {
|
|
33
|
+
if ctx.Checker == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
var callee *shimast.Node
|
|
37
|
+
var args []*shimast.Node
|
|
38
|
+
switch node.Kind {
|
|
39
|
+
case shimast.KindCallExpression:
|
|
40
|
+
if call := node.AsCallExpression(); call != nil {
|
|
41
|
+
callee = call.Expression
|
|
42
|
+
if call.Arguments != nil {
|
|
43
|
+
args = call.Arguments.Nodes
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
case shimast.KindNewExpression:
|
|
47
|
+
if ne := node.AsNewExpression(); ne != nil {
|
|
48
|
+
callee = ne.Expression
|
|
49
|
+
if ne.Arguments != nil {
|
|
50
|
+
args = ne.Arguments.Nodes
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if callee == nil || len(args) == 0 {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
calleeType := ctx.Checker.GetTypeAtLocation(callee)
|
|
58
|
+
if calleeType == nil || typeIsUnsafeAny(calleeType) {
|
|
59
|
+
// Callee itself is `any` — no-unsafe-call handles that.
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
for _, arg := range args {
|
|
63
|
+
if arg == nil {
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
stripped := stripParens(arg)
|
|
67
|
+
if stripped == nil {
|
|
68
|
+
continue
|
|
69
|
+
}
|
|
70
|
+
argType := ctx.Checker.GetTypeAtLocation(stripped)
|
|
71
|
+
if !typeIsUnsafeAny(argType) {
|
|
72
|
+
continue
|
|
73
|
+
}
|
|
74
|
+
ctx.Report(arg, noUnsafeArgumentMessage)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const noUnsafeArgumentMessage = "Unsafe passing of a value typed as `any` into a typed parameter. Narrow the value before forwarding it."
|
|
79
|
+
|
|
80
|
+
func init() {
|
|
81
|
+
Register(noUnsafeArgument{})
|
|
82
|
+
}
|