@ttsc/lint 0.13.0 → 0.14.0-dev.20260528
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +948 -69
- package/lib/defaultFormat.d.ts +9 -6
- package/lib/defaultFormat.js +9 -6
- package/lib/defaultFormat.js.map +1 -1
- package/lib/index.d.ts +46 -0
- package/lib/index.js +60 -37
- package/lib/index.js.map +1 -1
- package/lib/structures/ITtscLintConfig.d.ts +12 -6
- package/lib/structures/{ITtscLintFormatConfig.d.ts → ITtscLintFormat.d.ts} +2 -2
- package/lib/structures/{TtscLintRuleMap.js → ITtscLintFormat.js} +1 -1
- package/lib/structures/ITtscLintFormat.js.map +1 -0
- package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
- package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
- package/lib/structures/TtscLintRuleSetting.js.map +1 -0
- package/lib/structures/index.d.ts +3 -4
- package/lib/structures/index.js +3 -4
- package/lib/structures/index.js.map +1 -1
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +104 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +14 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +79 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintContributorRules.d.ts +17 -0
- package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
- package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintCoreRules.d.ts +1257 -0
- package/lib/structures/{ITtscLintFormatConfig.js → rules/ITtscLintCoreRules.js} +1 -1
- package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintCypressRules.d.ts +129 -0
- package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
- package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +157 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +167 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJestRules.d.ts +201 -0
- package/lib/structures/rules/ITtscLintJestRules.js +3 -0
- package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJsdocRules.d.ts +140 -0
- package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
- package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +302 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintNextjsRules.d.ts +185 -0
- package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
- package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +330 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintPromiseRules.d.ts +188 -0
- package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
- package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +51 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +39 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js +12 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRules.d.ts +289 -0
- package/lib/structures/rules/ITtscLintReactRules.js +3 -0
- package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintRegexpRules.d.ts +190 -0
- package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
- package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +66 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
- package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
- package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
- package/lib/structures/rules/ITtscLintRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintSecurityRules.d.ts +148 -0
- package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
- package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintSolidRules.d.ts +181 -0
- package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
- package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +21 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintStorybookRules.d.ts +174 -0
- package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
- package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +94 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +22 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +310 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1132 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
- package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
- package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintVitestRules.d.ts +141 -0
- package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
- package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
- package/lib/structures/rules/index.d.ts +31 -0
- package/lib/structures/rules/index.js +48 -0
- package/lib/structures/rules/index.js.map +1 -0
- package/linthost/ast_helpers.go +30 -5
- package/linthost/compile.go +33 -2
- package/linthost/config.go +48 -17
- package/linthost/config_format.go +9 -9
- package/linthost/directives.go +67 -25
- package/linthost/dispatch.go +14 -3
- package/linthost/engine.go +160 -40
- package/linthost/fix.go +2 -2
- package/linthost/flags_gen.go +17 -15
- package/linthost/host.go +40 -3
- package/linthost/lsp.go +747 -0
- package/linthost/print_dispatch.go +2 -2
- package/linthost/print_nodes_function.go +2 -2
- package/linthost/print_nodes_object.go +1 -1
- package/linthost/rule_names.go +14 -0
- package/linthost/rules_arrays.go +2 -2
- package/linthost/rules_boundaries.go +532 -0
- package/linthost/rules_camelcase.go +133 -0
- package/linthost/rules_complexity.go +94 -0
- package/linthost/rules_consistent_return.go +130 -0
- package/linthost/rules_console.go +1 -1
- package/linthost/rules_core_extra.go +739 -0
- package/linthost/rules_curly.go +70 -0
- package/linthost/rules_cypress.go +608 -0
- package/linthost/rules_debugger.go +2 -2
- package/linthost/rules_default_case.go +39 -0
- package/linthost/rules_default_case_last.go +46 -0
- package/linthost/rules_dupes.go +3 -3
- package/linthost/rules_empty.go +3 -3
- package/linthost/rules_escape.go +44 -24
- package/linthost/rules_eval.go +2 -2
- package/linthost/rules_finally.go +2 -2
- package/linthost/rules_format_jsdoc.go +1 -1
- package/linthost/rules_format_print_width.go +9 -9
- package/linthost/rules_format_quotes.go +1 -1
- package/linthost/rules_format_semi.go +1 -1
- package/linthost/rules_format_sort_imports.go +1 -1
- package/linthost/rules_format_trailing_comma.go +1 -1
- package/linthost/rules_functional.go +967 -0
- package/linthost/rules_gap.go +24 -45
- package/linthost/rules_grouped_accessor_pairs.go +87 -0
- package/linthost/rules_guard_for_in.go +198 -0
- package/linthost/rules_id_length.go +77 -0
- package/linthost/rules_imports.go +70 -2
- package/linthost/rules_init_declarations.go +53 -0
- package/linthost/rules_jest.go +618 -0
- package/linthost/rules_jsdoc.go +502 -0
- package/linthost/rules_jsx_a11y.go +1264 -0
- package/linthost/rules_logic.go +12 -12
- package/linthost/rules_loops.go +1 -1
- package/linthost/rules_max_classes_per_file.go +58 -0
- package/linthost/rules_max_depth.go +83 -0
- package/linthost/rules_max_lines.go +101 -0
- package/linthost/rules_max_lines_per_function.go +57 -0
- package/linthost/rules_max_nested_callbacks.go +61 -0
- package/linthost/rules_max_params.go +49 -0
- package/linthost/rules_max_statements.go +59 -0
- package/linthost/rules_misc.go +1 -1
- package/linthost/rules_nextjs.go +697 -0
- package/linthost/rules_no_else_return.go +75 -0
- package/linthost/rules_no_empty_named_blocks.go +91 -0
- package/linthost/rules_no_extend_native.go +51 -0
- package/linthost/rules_no_import_assign.go +140 -0
- package/linthost/rules_no_invalid_this.go +52 -0
- package/linthost/rules_no_loop_func.go +85 -0
- package/linthost/rules_no_magic_numbers.go +123 -0
- package/linthost/rules_no_mixed_operators.go +80 -0
- package/linthost/rules_no_param_reassign.go +98 -0
- package/linthost/rules_no_redeclare.go +270 -0
- package/linthost/rules_no_restricted_imports.go +105 -0
- package/linthost/rules_no_restricted_syntax.go +49 -0
- package/linthost/rules_no_shadow.go +147 -0
- package/linthost/rules_no_unreachable.go +77 -0
- package/linthost/rules_no_useless_assignment.go +120 -0
- package/linthost/rules_no_useless_constructor.go +245 -0
- package/linthost/rules_no_useless_return.go +51 -0
- package/linthost/rules_params.go +1 -1
- package/linthost/rules_playwright.go +788 -0
- package/linthost/rules_prefer_arrow_callback.go +124 -0
- package/linthost/rules_prefer_destructuring.go +98 -0
- package/linthost/rules_prefer_named_capture_group.go +129 -0
- package/linthost/rules_prefer_rest_params.go +94 -0
- package/linthost/rules_problems.go +41 -30
- package/linthost/rules_promise.go +1128 -73
- package/linthost/rules_protos.go +2 -2
- package/linthost/rules_react.go +773 -0
- package/linthost/rules_react_extras.go +227 -0
- package/linthost/rules_react_hooks.go +848 -0
- package/linthost/rules_react_perf.go +293 -0
- package/linthost/rules_react_refresh.go +583 -0
- package/linthost/rules_regexp.go +410 -0
- package/linthost/rules_security.go +830 -0
- package/linthost/rules_self.go +2 -2
- package/linthost/rules_solid.go +1073 -0
- package/linthost/rules_sort_imports.go +69 -0
- package/linthost/rules_sort_keys.go +134 -0
- package/linthost/rules_storybook.go +1176 -0
- package/linthost/rules_strings.go +4 -4
- package/linthost/rules_suggestions.go +38 -38
- package/linthost/rules_tanstack_query.go +844 -0
- package/linthost/rules_testing_library.go +1204 -0
- package/linthost/rules_throw.go +1 -1
- package/linthost/rules_ts.go +19 -19
- package/linthost/rules_ts_async.go +399 -0
- package/linthost/rules_ts_class_literal_property_style.go +115 -0
- package/linthost/rules_ts_consistent_type_exports.go +256 -0
- package/linthost/rules_ts_explicit_function_return_type.go +67 -0
- package/linthost/rules_ts_extra.go +155 -36
- package/linthost/rules_ts_no_base_to_string.go +218 -0
- package/linthost/rules_ts_no_confusing_void.go +72 -0
- package/linthost/rules_ts_no_deprecated.go +195 -0
- package/linthost/rules_ts_no_for_in_array.go +84 -0
- package/linthost/rules_ts_no_magic_numbers.go +124 -0
- package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
- package/linthost/rules_ts_no_misused_spread.go +104 -0
- package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
- package/linthost/rules_ts_no_restricted_types.go +62 -0
- package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
- package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
- package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
- package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
- package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
- package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
- package/linthost/rules_ts_no_unsafe_argument.go +82 -0
- package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
- package/linthost/rules_ts_no_unsafe_call.go +82 -0
- package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
- package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
- package/linthost/rules_ts_no_unsafe_return.go +126 -0
- package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
- package/linthost/rules_ts_no_useless_constructor.go +52 -0
- package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
- package/linthost/rules_ts_parameter_properties.go +38 -0
- package/linthost/rules_ts_prefer_find.go +178 -0
- package/linthost/rules_ts_prefer_includes.go +255 -0
- package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
- package/linthost/rules_ts_prefer_optional_chain.go +228 -0
- package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
- package/linthost/rules_ts_prefer_readonly.go +73 -0
- package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
- package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
- package/linthost/rules_ts_prefer_return_this_type.go +135 -0
- package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
- package/linthost/rules_ts_promise_function_async.go +77 -0
- package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
- package/linthost/rules_ts_require_array_sort_compare.go +96 -0
- package/linthost/rules_ts_restrict_plus_operands.go +127 -0
- package/linthost/rules_ts_restrict_template_expressions.go +95 -0
- package/linthost/rules_ts_simple.go +387 -0
- package/linthost/rules_ts_sort_type_constituents.go +144 -0
- package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
- package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
- package/linthost/rules_ts_unbound_method.go +126 -0
- package/linthost/rules_tsdoc.go +136 -0
- package/linthost/rules_unicorn_better_regex.go +27 -0
- package/linthost/rules_unicorn_catch_error_name.go +46 -0
- package/linthost/rules_unicorn_consistent_assert.go +47 -0
- package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
- package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
- package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
- package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
- package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
- package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
- package/linthost/rules_unicorn_custom_error_definition.go +138 -0
- package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
- package/linthost/rules_unicorn_error_message.go +64 -0
- package/linthost/rules_unicorn_escape_case.go +51 -0
- package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
- package/linthost/rules_unicorn_explicit_length_check.go +88 -0
- package/linthost/rules_unicorn_filename_case.go +29 -0
- package/linthost/rules_unicorn_import_style.go +28 -0
- package/linthost/rules_unicorn_isolated_functions.go +29 -0
- package/linthost/rules_unicorn_new_for_builtins.go +87 -0
- package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
- package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
- package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
- package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
- package/linthost/rules_unicorn_no_array_for_each.go +40 -0
- package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
- package/linthost/rules_unicorn_no_array_reduce.go +41 -0
- package/linthost/rules_unicorn_no_array_reverse.go +44 -0
- package/linthost/rules_unicorn_no_array_sort.go +43 -0
- package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
- package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
- package/linthost/rules_unicorn_no_console_spaces.go +61 -0
- package/linthost/rules_unicorn_no_document_cookie.go +41 -0
- package/linthost/rules_unicorn_no_empty_file.go +44 -0
- package/linthost/rules_unicorn_no_for_loop.go +102 -0
- package/linthost/rules_unicorn_no_hex_escape.go +42 -0
- package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
- package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
- package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
- package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
- package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
- package/linthost/rules_unicorn_no_lonely_if.go +44 -0
- package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
- package/linthost/rules_unicorn_no_named_default.go +54 -0
- package/linthost/rules_unicorn_no_negated_condition.go +85 -0
- package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
- package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
- package/linthost/rules_unicorn_no_new_array.go +30 -0
- package/linthost/rules_unicorn_no_new_buffer.go +31 -0
- package/linthost/rules_unicorn_no_null.go +24 -0
- package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
- package/linthost/rules_unicorn_no_process_exit.go +43 -0
- package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
- package/linthost/rules_unicorn_no_static_only_class.go +56 -0
- package/linthost/rules_unicorn_no_thenable.go +74 -0
- package/linthost/rules_unicorn_no_this_assignment.go +35 -0
- package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
- package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
- package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
- package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
- package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
- package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
- package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
- package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
- package/linthost/rules_unicorn_no_unused_properties.go +30 -0
- package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
- package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
- package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
- package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
- package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
- package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
- package/linthost/rules_unicorn_no_useless_spread.go +67 -0
- package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
- package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
- package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
- package/linthost/rules_unicorn_number_literal_case.go +69 -0
- package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
- package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
- package/linthost/rules_unicorn_prefer_array_find.go +51 -0
- package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
- package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
- package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
- package/linthost/rules_unicorn_prefer_array_some.go +67 -0
- package/linthost/rules_unicorn_prefer_at.go +77 -0
- package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
- package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
- package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
- package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
- package/linthost/rules_unicorn_prefer_code_point.go +49 -0
- package/linthost/rules_unicorn_prefer_date_now.go +78 -0
- package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
- package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
- package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
- package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
- package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
- package/linthost/rules_unicorn_prefer_event_target.go +36 -0
- package/linthost/rules_unicorn_prefer_export_from.go +129 -0
- package/linthost/rules_unicorn_prefer_global_this.go +127 -0
- package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
- package/linthost/rules_unicorn_prefer_includes.go +149 -0
- package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
- package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
- package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
- package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
- package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
- package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
- package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
- package/linthost/rules_unicorn_prefer_module.go +50 -0
- package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
- package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
- package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
- package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
- package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
- package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
- package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
- package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
- package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
- package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
- package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
- package/linthost/rules_unicorn_prefer_set_has.go +42 -0
- package/linthost/rules_unicorn_prefer_set_size.go +48 -0
- package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
- package/linthost/rules_unicorn_prefer_single_call.go +96 -0
- package/linthost/rules_unicorn_prefer_spread.go +51 -0
- package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
- package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
- package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
- package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
- package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
- package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
- package/linthost/rules_unicorn_prefer_switch.go +103 -0
- package/linthost/rules_unicorn_prefer_ternary.go +71 -0
- package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
- package/linthost/rules_unicorn_prefer_type_error.go +127 -0
- package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
- package/linthost/rules_unicorn_relative_url_style.go +49 -0
- package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
- package/linthost/rules_unicorn_require_module_attributes.go +54 -0
- package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
- package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
- package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
- package/linthost/rules_unicorn_string_content.go +27 -0
- package/linthost/rules_unicorn_switch_case_braces.go +42 -0
- package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
- package/linthost/rules_unicorn_template_indent.go +28 -0
- package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
- package/linthost/rules_unicorn_throw_new_error.go +61 -0
- package/linthost/rules_var.go +10 -4
- package/linthost/rules_vitest.go +568 -0
- package/package.json +3 -3
- package/plugin/main.go +49 -3
- package/rule/astutil/astutil.go +10 -3
- package/rule/rule.go +12 -10
- package/src/defaultFormat.ts +11 -8
- package/src/index.ts +65 -43
- package/src/structures/ITtscLintConfig.ts +12 -6
- package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
- package/src/structures/TtscLintRuleSetting.ts +55 -0
- package/src/structures/index.ts +3 -4
- package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
- package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
- package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
- package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
- package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
- package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
- package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
- package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
- package/src/structures/rules/ITtscLintJestRules.ts +220 -0
- package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
- package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
- package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
- package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
- package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
- package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
- package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
- package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
- package/src/structures/rules/ITtscLintReactRules.ts +321 -0
- package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
- package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
- package/src/structures/rules/ITtscLintRules.ts +77 -0
- package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
- package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
- package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
- package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
- package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
- package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
- package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
- package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
- package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
- package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
- package/src/structures/rules/index.ts +31 -0
- package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
- package/lib/structures/TtscLintRule.d.ts +0 -17
- package/lib/structures/TtscLintRule.js.map +0 -1
- package/lib/structures/TtscLintRuleMap.d.ts +0 -46
- package/lib/structures/TtscLintRuleMap.js.map +0 -1
- package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
- package/lib/structures/TtscLintRuleOptions.js.map +0 -1
- package/src/structures/TtscLintRule.ts +0 -160
- package/src/structures/TtscLintRuleMap.ts +0 -55
- package/src/structures/TtscLintRuleOptions.ts +0 -151
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// typescript/related-getter-setter-pairs reports a `get` accessor
|
|
2
|
+
// whose declared return type does not match the parameter type of the
|
|
3
|
+
// companion `set` accessor on the same class. The accessor pair
|
|
4
|
+
// presents a single conceptual field at the call site — `obj.value =
|
|
5
|
+
// X` followed by `Y = obj.value` should round-trip with compatible
|
|
6
|
+
// types — but TypeScript otherwise lets the two accessors carry
|
|
7
|
+
// independent annotations. The rule fires when the writer cannot
|
|
8
|
+
// accept what the reader is about to surface.
|
|
9
|
+
// https://typescript-eslint.io/rules/related-getter-setter-pairs/
|
|
10
|
+
//
|
|
11
|
+
// Type-aware. The comparison resolves both sides through
|
|
12
|
+
// `GetTypeFromTypeNode` so type aliases, generic parameters, and union
|
|
13
|
+
// constituents collapse to the same set of values before the
|
|
14
|
+
// equality check. Without a Checker the rule short-circuits to a
|
|
15
|
+
// no-op the way the other type-aware rules do.
|
|
16
|
+
//
|
|
17
|
+
// The rule visits each `KindGetAccessor`. For every getter that
|
|
18
|
+
// carries a return-type annotation and lives inside a class
|
|
19
|
+
// declaration / expression, it locates the matching `set` accessor by
|
|
20
|
+
// name (using the same `classMembers` + `classMemberName` helpers as
|
|
21
|
+
// `class-literal-property-style`) and compares the annotated types
|
|
22
|
+
// bidirectionally — both sides must describe the same set of values
|
|
23
|
+
// for the accessor pair to round-trip safely.
|
|
24
|
+
package linthost
|
|
25
|
+
|
|
26
|
+
import (
|
|
27
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
type relatedGetterSetterPairs struct{}
|
|
31
|
+
|
|
32
|
+
func (relatedGetterSetterPairs) Name() string {
|
|
33
|
+
return "typescript/related-getter-setter-pairs"
|
|
34
|
+
}
|
|
35
|
+
func (relatedGetterSetterPairs) NeedsTypeChecker() bool { return true }
|
|
36
|
+
func (relatedGetterSetterPairs) Visits() []shimast.Kind {
|
|
37
|
+
return []shimast.Kind{shimast.KindGetAccessor}
|
|
38
|
+
}
|
|
39
|
+
func (relatedGetterSetterPairs) Check(ctx *Context, node *shimast.Node) {
|
|
40
|
+
if ctx.Checker == nil {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
parent := node.Parent
|
|
44
|
+
if parent == nil ||
|
|
45
|
+
(parent.Kind != shimast.KindClassDeclaration && parent.Kind != shimast.KindClassExpression) {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
getReturnType := node.Type()
|
|
49
|
+
if getReturnType == nil {
|
|
50
|
+
// No annotated return type — nothing to compare against.
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
name := classMemberName(node)
|
|
54
|
+
if name == "" {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
setter := findClassSetterFor(parent, name)
|
|
58
|
+
if setter == nil {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
setParamType := setterParameterType(setter)
|
|
62
|
+
if setParamType == nil {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
getType := ctx.Checker.GetTypeFromTypeNode(getReturnType)
|
|
66
|
+
setType := ctx.Checker.GetTypeFromTypeNode(setParamType)
|
|
67
|
+
if getType == nil || setType == nil {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
// Bidirectional assignability stands in for type identity — the
|
|
71
|
+
// same shape `no-unnecessary-type-assertion` uses. The accessor
|
|
72
|
+
// pair is safe only when reading and writing describe the same
|
|
73
|
+
// set of values.
|
|
74
|
+
if ctx.Checker.IsTypeAssignableTo(getType, setType) &&
|
|
75
|
+
ctx.Checker.IsTypeAssignableTo(setType, getType) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
ctx.Report(node, "Getter return type does not match the corresponding setter parameter type on `"+name+"`.")
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// findClassSetterFor returns the `set` accessor declared on `class`
|
|
82
|
+
// whose name matches `name`, or nil when no such setter exists.
|
|
83
|
+
func findClassSetterFor(class *shimast.Node, name string) *shimast.Node {
|
|
84
|
+
for _, member := range classMembers(class) {
|
|
85
|
+
if member == nil || member.Kind != shimast.KindSetAccessor {
|
|
86
|
+
continue
|
|
87
|
+
}
|
|
88
|
+
if classMemberName(member) == name {
|
|
89
|
+
return member
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return nil
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// setterParameterType returns the type-annotation node of a `set`
|
|
96
|
+
// accessor's single parameter. A setter without a parameter, or with a
|
|
97
|
+
// parameter that carries no annotation, returns nil — the rule cannot
|
|
98
|
+
// compare against an inferred type.
|
|
99
|
+
func setterParameterType(setter *shimast.Node) *shimast.Node {
|
|
100
|
+
params := setter.Parameters()
|
|
101
|
+
if len(params) == 0 {
|
|
102
|
+
return nil
|
|
103
|
+
}
|
|
104
|
+
decl := params[0].AsParameterDeclaration()
|
|
105
|
+
if decl == nil {
|
|
106
|
+
return nil
|
|
107
|
+
}
|
|
108
|
+
return decl.Type
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
func init() {
|
|
112
|
+
Register(relatedGetterSetterPairs{})
|
|
113
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// typescript/require-array-sort-compare: require an explicit comparator
|
|
2
|
+
// for `arr.sort()` and `arr.toSorted()`. Without a comparator, both
|
|
3
|
+
// methods coerce elements to strings before ordering them, so
|
|
4
|
+
// `[10, 2, 1].sort()` evaluates to `[1, 10, 2]` — almost never what the
|
|
5
|
+
// caller meant. The fix is to pass `(a, b) => a - b`-style comparator.
|
|
6
|
+
// typescript-eslint:
|
|
7
|
+
// https://typescript-eslint.io/rules/require-array-sort-compare/
|
|
8
|
+
package linthost
|
|
9
|
+
|
|
10
|
+
import (
|
|
11
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
12
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
// requireArraySortCompare reports `<arr>.sort()` and `<arr>.toSorted()`
|
|
16
|
+
// when no comparator argument is supplied. Type-aware: the Checker
|
|
17
|
+
// confirms the receiver is an array (or tuple) so user-defined methods
|
|
18
|
+
// named `sort` / `toSorted` on non-array types do not trip the rule.
|
|
19
|
+
type requireArraySortCompare struct{}
|
|
20
|
+
|
|
21
|
+
func (requireArraySortCompare) Name() string {
|
|
22
|
+
return "typescript/require-array-sort-compare"
|
|
23
|
+
}
|
|
24
|
+
func (requireArraySortCompare) NeedsTypeChecker() bool {
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
func (requireArraySortCompare) Visits() []shimast.Kind {
|
|
28
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
29
|
+
}
|
|
30
|
+
func (requireArraySortCompare) Check(ctx *Context, node *shimast.Node) {
|
|
31
|
+
if ctx.Checker == nil {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
call := node.AsCallExpression()
|
|
35
|
+
if call == nil || call.Expression == nil {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
// Only fire when the callee is a property access ending in `.sort`
|
|
39
|
+
// or `.toSorted` and the call passes zero arguments.
|
|
40
|
+
receiver, method, ok := promisePropertyAccessParts(call.Expression)
|
|
41
|
+
if !ok || (method != "sort" && method != "toSorted") {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
if call.Arguments != nil && len(call.Arguments.Nodes) > 0 {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
if receiver == nil {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
t := ctx.Checker.GetTypeAtLocation(receiver)
|
|
51
|
+
if t == nil {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
if !requireArraySortCompareIsArrayLike(ctx.Checker, t) {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
ctx.Report(node, "Require an explicit compareFunction for `."+method+"()` — without one, elements are coerced to strings before being ordered.")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// requireArraySortCompareIsArrayLike reports whether t is provably an
|
|
61
|
+
// array or a tuple. The check follows the same recurse-into-constituents
|
|
62
|
+
// pattern as `isAwaitable` so a union like `number[] | string[]` still
|
|
63
|
+
// resolves to "array" via every constituent. `any` / `unknown` / `never`
|
|
64
|
+
// are intentionally NOT treated as array-like — they propagate from
|
|
65
|
+
// generic helpers and would explode the false-positive volume.
|
|
66
|
+
func requireArraySortCompareIsArrayLike(checker *shimchecker.Checker, t *shimchecker.Type) bool {
|
|
67
|
+
if checker == nil || t == nil {
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
flags := t.Flags()
|
|
71
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
75
|
+
for _, part := range t.Types() {
|
|
76
|
+
if part == nil {
|
|
77
|
+
continue
|
|
78
|
+
}
|
|
79
|
+
if !requireArraySortCompareIsArrayLike(checker, part) {
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return true
|
|
84
|
+
}
|
|
85
|
+
if shimchecker.Checker_isArrayType(checker, t) {
|
|
86
|
+
return true
|
|
87
|
+
}
|
|
88
|
+
if shimchecker.IsTupleType(t) {
|
|
89
|
+
return true
|
|
90
|
+
}
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
func init() {
|
|
95
|
+
Register(requireArraySortCompare{})
|
|
96
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// typescript/restrict-plus-operands: the `+` operator is overloaded in
|
|
2
|
+
// JavaScript — it numerically adds two numbers, lexically concatenates
|
|
3
|
+
// two strings, and silently coerces every other combination. `1 + "a"`
|
|
4
|
+
// becomes `"1a"`, `null + 5` becomes `5`, `{} + 1` becomes `"[object
|
|
5
|
+
// Object]1"`. Each of these is almost always a bug: the author meant
|
|
6
|
+
// either numeric addition or explicit string concatenation, not the
|
|
7
|
+
// runtime's lossy fallback. typescript-eslint:
|
|
8
|
+
// https://typescript-eslint.io/rules/restrict-plus-operands/
|
|
9
|
+
package linthost
|
|
10
|
+
|
|
11
|
+
import (
|
|
12
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
13
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// restrictPlusOperands fires on `<lhs> + <rhs>` when the operands are
|
|
17
|
+
// not both number-like, both string-like, or both bigint-like. The
|
|
18
|
+
// rule is type-aware: without a Checker it cannot prove the operand
|
|
19
|
+
// kinds, so it bails out to avoid false positives on plain JS or on
|
|
20
|
+
// files that opt out of typechecking. `any` / `unknown` / `never`
|
|
21
|
+
// operands are treated as unrestricted to keep false positives off
|
|
22
|
+
// generic helpers; the upstream rule does the same.
|
|
23
|
+
type restrictPlusOperands struct{}
|
|
24
|
+
|
|
25
|
+
func (restrictPlusOperands) Name() string { return "typescript/restrict-plus-operands" }
|
|
26
|
+
func (restrictPlusOperands) NeedsTypeChecker() bool {
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
func (restrictPlusOperands) Visits() []shimast.Kind {
|
|
30
|
+
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
31
|
+
}
|
|
32
|
+
func (restrictPlusOperands) Check(ctx *Context, node *shimast.Node) {
|
|
33
|
+
if ctx.Checker == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
expr := node.AsBinaryExpression()
|
|
37
|
+
if expr == nil || expr.OperatorToken == nil {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
if expr.OperatorToken.Kind != shimast.KindPlusToken {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
if expr.Left == nil || expr.Right == nil {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
left := ctx.Checker.GetTypeAtLocation(expr.Left)
|
|
47
|
+
right := ctx.Checker.GetTypeAtLocation(expr.Right)
|
|
48
|
+
if left == nil || right == nil {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
leftKind := restrictPlusOperandsKind(left)
|
|
52
|
+
rightKind := restrictPlusOperandsKind(right)
|
|
53
|
+
// Skip when either side is unconstrained (any / unknown / never /
|
|
54
|
+
// generic) — the rule would otherwise fire on every generic helper
|
|
55
|
+
// that accepts `T extends number | string`.
|
|
56
|
+
if leftKind == restrictPlusOperandsAny || rightKind == restrictPlusOperandsAny {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
if leftKind == rightKind && leftKind != restrictPlusOperandsOther {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
ctx.Report(node, "Operands of `+` must both be `number`, both `string`, or both `bigint`. Mixed or non-primitive operands are silently coerced by the runtime and almost always a bug.")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// restrictPlusOperandsKind classifies t as one of the four buckets the
|
|
66
|
+
// rule cares about. A union is accepted only when every constituent
|
|
67
|
+
// lands in the same primitive bucket — `string | number` is
|
|
68
|
+
// deliberately rejected because each branch would coerce the other
|
|
69
|
+
// side differently at runtime.
|
|
70
|
+
type restrictPlusOperandsBucket int
|
|
71
|
+
|
|
72
|
+
const (
|
|
73
|
+
restrictPlusOperandsOther restrictPlusOperandsBucket = iota
|
|
74
|
+
restrictPlusOperandsAny
|
|
75
|
+
restrictPlusOperandsNumber
|
|
76
|
+
restrictPlusOperandsString
|
|
77
|
+
restrictPlusOperandsBigInt
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
func restrictPlusOperandsKind(t *shimchecker.Type) restrictPlusOperandsBucket {
|
|
81
|
+
if t == nil {
|
|
82
|
+
return restrictPlusOperandsOther
|
|
83
|
+
}
|
|
84
|
+
flags := t.Flags()
|
|
85
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
86
|
+
return restrictPlusOperandsAny
|
|
87
|
+
}
|
|
88
|
+
if flags&shimchecker.TypeFlagsStringLike != 0 {
|
|
89
|
+
return restrictPlusOperandsString
|
|
90
|
+
}
|
|
91
|
+
if flags&shimchecker.TypeFlagsNumberLike != 0 {
|
|
92
|
+
return restrictPlusOperandsNumber
|
|
93
|
+
}
|
|
94
|
+
if flags&shimchecker.TypeFlagsBigIntLike != 0 {
|
|
95
|
+
return restrictPlusOperandsBigInt
|
|
96
|
+
}
|
|
97
|
+
if flags&shimchecker.TypeFlagsUnion != 0 {
|
|
98
|
+
var seen restrictPlusOperandsBucket
|
|
99
|
+
for _, part := range t.Types() {
|
|
100
|
+
if part == nil {
|
|
101
|
+
continue
|
|
102
|
+
}
|
|
103
|
+
kind := restrictPlusOperandsKind(part)
|
|
104
|
+
if kind == restrictPlusOperandsAny {
|
|
105
|
+
return restrictPlusOperandsAny
|
|
106
|
+
}
|
|
107
|
+
if kind == restrictPlusOperandsOther {
|
|
108
|
+
return restrictPlusOperandsOther
|
|
109
|
+
}
|
|
110
|
+
if seen == 0 {
|
|
111
|
+
seen = kind
|
|
112
|
+
continue
|
|
113
|
+
}
|
|
114
|
+
if seen != kind {
|
|
115
|
+
return restrictPlusOperandsOther
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if seen != 0 {
|
|
119
|
+
return seen
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return restrictPlusOperandsOther
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
func init() {
|
|
126
|
+
Register(restrictPlusOperands{})
|
|
127
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// typescript/restrict-template-expressions: every interpolation inside a
|
|
2
|
+
// template literal coerces its value through `String()` at runtime, so
|
|
3
|
+
// non-string-friendly types silently render as `"[object Object]"`,
|
|
4
|
+
// `"null"`, or `"undefined"`. The rule requires each embedded expression
|
|
5
|
+
// to be statically known as `string`, `number`, `bigint`, `boolean`, or
|
|
6
|
+
// a union of those — anything else (object types, `null`, `undefined`,
|
|
7
|
+
// `void`) must be converted explicitly at the call site.
|
|
8
|
+
// typescript-eslint:
|
|
9
|
+
// https://typescript-eslint.io/rules/restrict-template-expressions/
|
|
10
|
+
package linthost
|
|
11
|
+
|
|
12
|
+
import (
|
|
13
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
14
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
// restrictTemplateExpressions reports each `${expr}` span inside a
|
|
18
|
+
// template literal whose expression has a non-stringy static type.
|
|
19
|
+
// Type-aware: without a Checker the rule cannot tell `string | number`
|
|
20
|
+
// apart from `string | null`, so it bails — the AST alone never has
|
|
21
|
+
// enough information to decide this case.
|
|
22
|
+
//
|
|
23
|
+
// `any` / `unknown` / `never` pass through on purpose. They propagate
|
|
24
|
+
// from generic helpers and a strict rejection would explode the
|
|
25
|
+
// false-positive volume; the upstream rule makes the same choice
|
|
26
|
+
// behind its `allowAny` / `allowNever` options, which default to true.
|
|
27
|
+
type restrictTemplateExpressions struct{}
|
|
28
|
+
|
|
29
|
+
func (restrictTemplateExpressions) Name() string {
|
|
30
|
+
return "typescript/restrict-template-expressions"
|
|
31
|
+
}
|
|
32
|
+
func (restrictTemplateExpressions) NeedsTypeChecker() bool {
|
|
33
|
+
return true
|
|
34
|
+
}
|
|
35
|
+
func (restrictTemplateExpressions) Visits() []shimast.Kind {
|
|
36
|
+
return []shimast.Kind{shimast.KindTemplateExpression}
|
|
37
|
+
}
|
|
38
|
+
func (restrictTemplateExpressions) Check(ctx *Context, node *shimast.Node) {
|
|
39
|
+
if ctx.Checker == nil {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
expr := node.AsTemplateExpression()
|
|
43
|
+
if expr == nil || expr.TemplateSpans == nil {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
for _, spanNode := range expr.TemplateSpans.Nodes {
|
|
47
|
+
span := spanNode.AsTemplateSpan()
|
|
48
|
+
if span == nil || span.Expression == nil {
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
t := ctx.Checker.GetTypeAtLocation(span.Expression)
|
|
52
|
+
if t == nil {
|
|
53
|
+
continue
|
|
54
|
+
}
|
|
55
|
+
if restrictTemplateExpressionsIsStringy(ctx.Checker, t) {
|
|
56
|
+
continue
|
|
57
|
+
}
|
|
58
|
+
ctx.Report(span.Expression, "Template interpolations must be string-like (`string`, `number`, `bigint`, or `boolean`) — convert the value explicitly to avoid coercing to `\"[object Object]\"`, `\"null\"`, or `\"undefined\"`.")
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// restrictTemplateExpressionsIsStringy reports whether t is safe to
|
|
63
|
+
// drop into a template-literal slot — string / number / bigint /
|
|
64
|
+
// boolean, or a union/intersection whose every constituent is.
|
|
65
|
+
// `any` / `unknown` / `never` pass through (return true) so generic
|
|
66
|
+
// helpers propagate without lighting up the rule everywhere.
|
|
67
|
+
func restrictTemplateExpressionsIsStringy(checker *shimchecker.Checker, t *shimchecker.Type) bool {
|
|
68
|
+
if checker == nil || t == nil {
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
flags := t.Flags()
|
|
72
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
73
|
+
return true
|
|
74
|
+
}
|
|
75
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
76
|
+
for _, part := range t.Types() {
|
|
77
|
+
if part == nil {
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
if !restrictTemplateExpressionsIsStringy(checker, part) {
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return true
|
|
85
|
+
}
|
|
86
|
+
const stringyMask = shimchecker.TypeFlagsStringLike |
|
|
87
|
+
shimchecker.TypeFlagsNumberLike |
|
|
88
|
+
shimchecker.TypeFlagsBigIntLike |
|
|
89
|
+
shimchecker.TypeFlagsBooleanLike
|
|
90
|
+
return flags&stringyMask != 0
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
func init() {
|
|
94
|
+
Register(restrictTemplateExpressions{})
|
|
95
|
+
}
|