@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,102 @@
|
|
|
1
|
+
// typescript/no-unsafe-assignment: assigning an `any`-typed value into
|
|
2
|
+
// a concretely typed location erases the static guarantee the target
|
|
3
|
+
// declaration carries. `const num: number = anyValue;` compiles, but
|
|
4
|
+
// every later use of `num` operates on whatever `anyValue` actually
|
|
5
|
+
// holds at runtime. typescript-eslint:
|
|
6
|
+
// https://typescript-eslint.io/rules/no-unsafe-assignment/
|
|
7
|
+
//
|
|
8
|
+
// Type-aware. The rule visits two shapes:
|
|
9
|
+
//
|
|
10
|
+
// - `VariableDeclaration` — the initializer of `let x: T = ...` or
|
|
11
|
+
// `const x: T = ...`. Without a typed target the assignment is
|
|
12
|
+
// trivially safe (the local becomes `any` too), so the rule
|
|
13
|
+
// requires an explicit type annotation OR a target that resolves
|
|
14
|
+
// to a non-`any` type.
|
|
15
|
+
// - `BinaryExpression` with `=` operator — a plain reassignment like
|
|
16
|
+
// `x = anyValue`. The LHS already has a static type from its
|
|
17
|
+
// declaration; the rule fires when the RHS is `any` and the LHS is
|
|
18
|
+
// not.
|
|
19
|
+
//
|
|
20
|
+
// As with the rest of the unsafe-* family `unknown` is intentionally
|
|
21
|
+
// NOT flagged: it forces a narrowing assertion before the value can be
|
|
22
|
+
// stored in a typed slot, which is the explicit ergonomic the upstream
|
|
23
|
+
// rule pushes toward.
|
|
24
|
+
package linthost
|
|
25
|
+
|
|
26
|
+
import (
|
|
27
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
type noUnsafeAssignment struct{}
|
|
31
|
+
|
|
32
|
+
func (noUnsafeAssignment) Name() string { return "typescript/no-unsafe-assignment" }
|
|
33
|
+
func (noUnsafeAssignment) NeedsTypeChecker() bool {
|
|
34
|
+
return true
|
|
35
|
+
}
|
|
36
|
+
func (noUnsafeAssignment) Visits() []shimast.Kind {
|
|
37
|
+
return []shimast.Kind{
|
|
38
|
+
shimast.KindVariableDeclaration,
|
|
39
|
+
shimast.KindBinaryExpression,
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
func (noUnsafeAssignment) Check(ctx *Context, node *shimast.Node) {
|
|
43
|
+
if ctx.Checker == nil {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
switch node.Kind {
|
|
47
|
+
case shimast.KindVariableDeclaration:
|
|
48
|
+
decl := node.AsVariableDeclaration()
|
|
49
|
+
if decl == nil || decl.Initializer == nil {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
// Only flag when the target has an explicit type annotation —
|
|
53
|
+
// `const x = anyValue;` widens `x` to `any` too, which is the
|
|
54
|
+
// `no-explicit-any` family's concern, not this rule's.
|
|
55
|
+
if decl.Type == nil {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
rhs := stripParens(decl.Initializer)
|
|
59
|
+
if rhs == nil {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
rhsType := ctx.Checker.GetTypeAtLocation(rhs)
|
|
63
|
+
if !typeIsUnsafeAny(rhsType) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
lhsType := ctx.Checker.GetTypeFromTypeNode(decl.Type)
|
|
67
|
+
if typeIsUnsafeAny(lhsType) {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
ctx.Report(node, noUnsafeAssignmentMessage)
|
|
71
|
+
case shimast.KindBinaryExpression:
|
|
72
|
+
bin := node.AsBinaryExpression()
|
|
73
|
+
if bin == nil || bin.OperatorToken == nil {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
if bin.OperatorToken.Kind != shimast.KindEqualsToken {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
if bin.Left == nil || bin.Right == nil {
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
rhs := stripParens(bin.Right)
|
|
83
|
+
if rhs == nil {
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
rhsType := ctx.Checker.GetTypeAtLocation(rhs)
|
|
87
|
+
if !typeIsUnsafeAny(rhsType) {
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
lhsType := ctx.Checker.GetTypeAtLocation(bin.Left)
|
|
91
|
+
if typeIsUnsafeAny(lhsType) {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
ctx.Report(node, noUnsafeAssignmentMessage)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const noUnsafeAssignmentMessage = "Unsafe assignment of a value typed as `any` to a typed target. Narrow the value before storing it."
|
|
99
|
+
|
|
100
|
+
func init() {
|
|
101
|
+
Register(noUnsafeAssignment{})
|
|
102
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// typescript/no-unsafe-call: invoking a value whose static type is
|
|
2
|
+
// `any` discards every signature check the type system would otherwise
|
|
3
|
+
// perform. The runtime call still happens, but the parameter list is
|
|
4
|
+
// unchecked, the return type is `any`, and any downstream use of the
|
|
5
|
+
// result silently spreads the `any` further. typescript-eslint:
|
|
6
|
+
// https://typescript-eslint.io/rules/no-unsafe-call/
|
|
7
|
+
//
|
|
8
|
+
// Type-aware. The rule visits the three syntactic invocation shapes —
|
|
9
|
+
// `f(...)`, `new F(...)`, and the tagged-template form `f` + ``"x"`` —
|
|
10
|
+
// and reports when the callee resolves to a type whose flags include
|
|
11
|
+
// `TypeFlagsAny`. `unknown` is intentionally not flagged: it requires a
|
|
12
|
+
// narrowing assertion before the call, which is the explicit ergonomics
|
|
13
|
+
// the upstream rule pushes toward. `never` is also skipped — a never
|
|
14
|
+
// callee means the code is unreachable, which is a different rule's
|
|
15
|
+
// concern.
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import (
|
|
19
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
20
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
type noUnsafeCall struct{}
|
|
24
|
+
|
|
25
|
+
func (noUnsafeCall) Name() string { return "typescript/no-unsafe-call" }
|
|
26
|
+
func (noUnsafeCall) NeedsTypeChecker() bool {
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
func (noUnsafeCall) Visits() []shimast.Kind {
|
|
30
|
+
return []shimast.Kind{
|
|
31
|
+
shimast.KindCallExpression,
|
|
32
|
+
shimast.KindNewExpression,
|
|
33
|
+
shimast.KindTaggedTemplateExpression,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
func (noUnsafeCall) Check(ctx *Context, node *shimast.Node) {
|
|
37
|
+
if ctx.Checker == nil {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
var callee *shimast.Node
|
|
41
|
+
switch node.Kind {
|
|
42
|
+
case shimast.KindCallExpression:
|
|
43
|
+
if call := node.AsCallExpression(); call != nil {
|
|
44
|
+
callee = call.Expression
|
|
45
|
+
}
|
|
46
|
+
case shimast.KindNewExpression:
|
|
47
|
+
if ne := node.AsNewExpression(); ne != nil {
|
|
48
|
+
callee = ne.Expression
|
|
49
|
+
}
|
|
50
|
+
case shimast.KindTaggedTemplateExpression:
|
|
51
|
+
if tag := node.AsTaggedTemplateExpression(); tag != nil {
|
|
52
|
+
callee = tag.Tag
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if callee == nil {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
t := ctx.Checker.GetTypeAtLocation(callee)
|
|
59
|
+
if !typeIsUnsafeAny(t) {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
ctx.Report(callee, noUnsafeCallMessage)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const noUnsafeCallMessage = "Unsafe call of a value typed as `any`. Narrow the callee to a concrete signature before invoking it."
|
|
66
|
+
|
|
67
|
+
// typeIsUnsafeAny reports whether `t` carries the `any` flag — the only
|
|
68
|
+
// shape these unsafe-* rules flag. `unknown` is intentionally NOT
|
|
69
|
+
// included: it forces a narrowing assertion at the use site, which is
|
|
70
|
+
// the safer ergonomic the upstream rules push toward. Returns false on
|
|
71
|
+
// nil so an absent type silently bypasses the rule rather than firing
|
|
72
|
+
// on every unanalysable expression.
|
|
73
|
+
func typeIsUnsafeAny(t *shimchecker.Type) bool {
|
|
74
|
+
if t == nil {
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
return t.Flags()&shimchecker.TypeFlagsAny != 0
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
func init() {
|
|
81
|
+
Register(noUnsafeCall{})
|
|
82
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// typescript/no-unsafe-enum-comparison: `===` / `!==` (and the `==` /
|
|
2
|
+
// `!=` cousins) silently accept any value that shares the widened
|
|
3
|
+
// primitive of an enum member. A string enum value compared with a raw
|
|
4
|
+
// string literal therefore matches whichever string happens to land in
|
|
5
|
+
// the other operand, even when the literal is not declared on the enum
|
|
6
|
+
// at all. The fix is to compare against one of the enum's own members
|
|
7
|
+
// so a typo surfaces at compile time.
|
|
8
|
+
// typescript-eslint:
|
|
9
|
+
// https://typescript-eslint.io/rules/no-unsafe-enum-comparison/
|
|
10
|
+
//
|
|
11
|
+
// Type-aware. Without a Checker we cannot tell an enum-typed value
|
|
12
|
+
// apart from a plain `string` / `number`, so Context.Checker == nil
|
|
13
|
+
// short-circuits the visit the same way every other type-aware rule
|
|
14
|
+
// in this package does.
|
|
15
|
+
//
|
|
16
|
+
// The matching algorithm mirrors typescript-eslint:
|
|
17
|
+
//
|
|
18
|
+
// - one side must carry an enum type (TypeFlagsEnumLike — covers
|
|
19
|
+
// both the enum union and its literal members);
|
|
20
|
+
// - the other side must be the widened primitive (string-/number-/
|
|
21
|
+
// bigint-like) WITHOUT carrying the same enum;
|
|
22
|
+
// - `any`, `unknown`, `never`, and identical enums on both sides
|
|
23
|
+
// pass through.
|
|
24
|
+
package linthost
|
|
25
|
+
|
|
26
|
+
import (
|
|
27
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
28
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
type noUnsafeEnumComparison struct{}
|
|
32
|
+
|
|
33
|
+
func (noUnsafeEnumComparison) Name() string { return "typescript/no-unsafe-enum-comparison" }
|
|
34
|
+
func (noUnsafeEnumComparison) NeedsTypeChecker() bool {
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
func (noUnsafeEnumComparison) Visits() []shimast.Kind {
|
|
38
|
+
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
39
|
+
}
|
|
40
|
+
func (noUnsafeEnumComparison) Check(ctx *Context, node *shimast.Node) {
|
|
41
|
+
if ctx.Checker == nil {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
bin := node.AsBinaryExpression()
|
|
45
|
+
if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
switch bin.OperatorToken.Kind {
|
|
49
|
+
case shimast.KindEqualsEqualsToken,
|
|
50
|
+
shimast.KindEqualsEqualsEqualsToken,
|
|
51
|
+
shimast.KindExclamationEqualsToken,
|
|
52
|
+
shimast.KindExclamationEqualsEqualsToken:
|
|
53
|
+
default:
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
left := ctx.Checker.GetTypeAtLocation(bin.Left)
|
|
57
|
+
right := ctx.Checker.GetTypeAtLocation(bin.Right)
|
|
58
|
+
if left == nil || right == nil {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
if noUnsafeEnumComparisonMismatch(left, right) || noUnsafeEnumComparisonMismatch(right, left) {
|
|
62
|
+
ctx.Report(node, "Unsafe comparison between an enum-typed value and a plain primitive of the same widened type. Compare against one of the enum's own members so a typo surfaces at compile time.")
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// noUnsafeEnumComparisonMismatch reports whether `enumSide` carries an
|
|
67
|
+
// enum type and `otherSide` is the widened primitive without naming the
|
|
68
|
+
// same enum. Both arms walk union constituents — a `Color | undefined`
|
|
69
|
+
// still counts as the enum side, and the comparison `color === "red"`
|
|
70
|
+
// is still unsafe even when `color` carries an extra nullish branch.
|
|
71
|
+
func noUnsafeEnumComparisonMismatch(enumSide, otherSide *shimchecker.Type) bool {
|
|
72
|
+
if !noUnsafeEnumComparisonHasEnum(enumSide) {
|
|
73
|
+
return false
|
|
74
|
+
}
|
|
75
|
+
// `any` / `unknown` / `never` on the other side silently propagate
|
|
76
|
+
// from generic helpers — flagging them would explode false positives
|
|
77
|
+
// the same way `restrict-template-expressions` mitigates with its
|
|
78
|
+
// `allowAny` default.
|
|
79
|
+
if noUnsafeEnumComparisonIsLoose(otherSide) {
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
// If the other side is provably the same enum (or one of its
|
|
83
|
+
// members), the comparison is the safe shape the rule recommends.
|
|
84
|
+
if noUnsafeEnumComparisonSharesEnum(enumSide, otherSide) {
|
|
85
|
+
return false
|
|
86
|
+
}
|
|
87
|
+
// The mismatch only fires when the non-enum side is the widened
|
|
88
|
+
// primitive that the enum widens to. A `Color === Status.Active`
|
|
89
|
+
// comparison (two unrelated enums of the same widened number) also
|
|
90
|
+
// trips this branch via the other call ordering.
|
|
91
|
+
if !noUnsafeEnumComparisonIsBareLiteralLike(otherSide) && !noUnsafeEnumComparisonHasEnum(otherSide) {
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
return true
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// noUnsafeEnumComparisonHasEnum reports whether t (or any constituent of
|
|
98
|
+
// a union) carries an enum-like flag. `TypeFlagsEnumLike` covers both
|
|
99
|
+
// the enum union type produced by `enum E { ... }` and the canonical
|
|
100
|
+
// `TypeFlagsEnumLiteral`-tagged literal types for each member.
|
|
101
|
+
func noUnsafeEnumComparisonHasEnum(t *shimchecker.Type) bool {
|
|
102
|
+
if t == nil {
|
|
103
|
+
return false
|
|
104
|
+
}
|
|
105
|
+
flags := t.Flags()
|
|
106
|
+
if flags&shimchecker.TypeFlagsEnumLike != 0 {
|
|
107
|
+
return true
|
|
108
|
+
}
|
|
109
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
110
|
+
for _, part := range t.Types() {
|
|
111
|
+
if noUnsafeEnumComparisonHasEnum(part) {
|
|
112
|
+
return true
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return false
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// noUnsafeEnumComparisonIsLoose reports whether t propagates from a
|
|
120
|
+
// generic helper without naming a concrete type — `any` / `unknown` /
|
|
121
|
+
// `never`. The upstream rule keeps these silent so type-erasure paths
|
|
122
|
+
// (`JSON.parse`, untyped APIs) don't light up everywhere.
|
|
123
|
+
func noUnsafeEnumComparisonIsLoose(t *shimchecker.Type) bool {
|
|
124
|
+
if t == nil {
|
|
125
|
+
return true
|
|
126
|
+
}
|
|
127
|
+
return t.Flags()&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// noUnsafeEnumComparisonSharesEnum reports whether both sides refer to
|
|
131
|
+
// the same enum declaration. The Checker canonicalizes enum literal
|
|
132
|
+
// types per member, so identity follows the type's name symbol (or the
|
|
133
|
+
// enum union's symbol) up the parent chain to the EnumDeclaration node
|
|
134
|
+
// — comparing those addresses tells us whether `Color.Red` and
|
|
135
|
+
// `Color.Blue` come from the same enum.
|
|
136
|
+
func noUnsafeEnumComparisonSharesEnum(a, b *shimchecker.Type) bool {
|
|
137
|
+
aDecl := noUnsafeEnumComparisonEnumDeclaration(a)
|
|
138
|
+
bDecl := noUnsafeEnumComparisonEnumDeclaration(b)
|
|
139
|
+
if aDecl == nil || bDecl == nil {
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
return aDecl == bDecl
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// noUnsafeEnumComparisonEnumDeclaration returns the EnumDeclaration
|
|
146
|
+
// node that t (or any constituent of a union) belongs to, or nil when
|
|
147
|
+
// t is not an enum-flavored type. Both the enum union type and each
|
|
148
|
+
// enum-literal member carry the enum's symbol via Type.Symbol; the
|
|
149
|
+
// symbol's parent declaration is the EnumDeclaration we identify by.
|
|
150
|
+
func noUnsafeEnumComparisonEnumDeclaration(t *shimchecker.Type) *shimast.Node {
|
|
151
|
+
if t == nil {
|
|
152
|
+
return nil
|
|
153
|
+
}
|
|
154
|
+
flags := t.Flags()
|
|
155
|
+
if flags&shimchecker.TypeFlagsEnumLike != 0 {
|
|
156
|
+
sym := t.Symbol()
|
|
157
|
+
if sym == nil {
|
|
158
|
+
return nil
|
|
159
|
+
}
|
|
160
|
+
for _, decl := range sym.Declarations {
|
|
161
|
+
if decl == nil {
|
|
162
|
+
continue
|
|
163
|
+
}
|
|
164
|
+
if decl.Kind == shimast.KindEnumDeclaration {
|
|
165
|
+
return decl
|
|
166
|
+
}
|
|
167
|
+
// Enum member literal types carry the member symbol; walk
|
|
168
|
+
// one level up to land on the surrounding EnumDeclaration.
|
|
169
|
+
if decl.Parent != nil && decl.Parent.Kind == shimast.KindEnumDeclaration {
|
|
170
|
+
return decl.Parent
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return nil
|
|
174
|
+
}
|
|
175
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
176
|
+
var seen *shimast.Node
|
|
177
|
+
for _, part := range t.Types() {
|
|
178
|
+
decl := noUnsafeEnumComparisonEnumDeclaration(part)
|
|
179
|
+
if decl == nil {
|
|
180
|
+
continue
|
|
181
|
+
}
|
|
182
|
+
if seen == nil {
|
|
183
|
+
seen = decl
|
|
184
|
+
continue
|
|
185
|
+
}
|
|
186
|
+
if seen != decl {
|
|
187
|
+
return nil
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return seen
|
|
191
|
+
}
|
|
192
|
+
return nil
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// noUnsafeEnumComparisonIsBareLiteralLike reports whether t is a plain
|
|
196
|
+
// primitive or primitive literal — the widened side of an enum
|
|
197
|
+
// comparison. Unions are considered bare when every constituent is.
|
|
198
|
+
// Pure `null` / `undefined` operands are exempt because they don't
|
|
199
|
+
// share an enum's primitive widening — `color === null` is a real
|
|
200
|
+
// nullability check, not a same-primitive mistake.
|
|
201
|
+
func noUnsafeEnumComparisonIsBareLiteralLike(t *shimchecker.Type) bool {
|
|
202
|
+
if t == nil {
|
|
203
|
+
return false
|
|
204
|
+
}
|
|
205
|
+
flags := t.Flags()
|
|
206
|
+
if flags&shimchecker.TypeFlagsEnumLike != 0 {
|
|
207
|
+
return false
|
|
208
|
+
}
|
|
209
|
+
const primitiveMask = shimchecker.TypeFlagsStringLike |
|
|
210
|
+
shimchecker.TypeFlagsNumberLike |
|
|
211
|
+
shimchecker.TypeFlagsBigIntLike
|
|
212
|
+
if flags&primitiveMask != 0 {
|
|
213
|
+
return true
|
|
214
|
+
}
|
|
215
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
216
|
+
anyMatch := false
|
|
217
|
+
for _, part := range t.Types() {
|
|
218
|
+
if part == nil {
|
|
219
|
+
continue
|
|
220
|
+
}
|
|
221
|
+
if noUnsafeEnumComparisonHasEnum(part) {
|
|
222
|
+
return false
|
|
223
|
+
}
|
|
224
|
+
if noUnsafeEnumComparisonIsBareLiteralLike(part) {
|
|
225
|
+
anyMatch = true
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return anyMatch
|
|
229
|
+
}
|
|
230
|
+
return false
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
func init() {
|
|
234
|
+
Register(noUnsafeEnumComparison{})
|
|
235
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// typescript/no-unsafe-member-access: reading a property off a value
|
|
2
|
+
// whose static type is `any` silently yields another `any`, and the
|
|
3
|
+
// next operation on that result is unchecked too. `x.foo.bar.baz` is
|
|
4
|
+
// the cascade that lets a single `any` propagate through an entire
|
|
5
|
+
// expression tree. typescript-eslint:
|
|
6
|
+
// https://typescript-eslint.io/rules/no-unsafe-member-access/
|
|
7
|
+
//
|
|
8
|
+
// Type-aware. The rule visits dotted access (`x.foo`) and computed
|
|
9
|
+
// access (`x[k]`) and reports when the receiver resolves to `any`. As
|
|
10
|
+
// with the rest of the unsafe-* family `unknown` is intentionally NOT
|
|
11
|
+
// flagged: it forces a narrowing assertion before the access, which is
|
|
12
|
+
// the explicit ergonomic the upstream rule pushes toward.
|
|
13
|
+
package linthost
|
|
14
|
+
|
|
15
|
+
import (
|
|
16
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
type noUnsafeMemberAccess struct{}
|
|
20
|
+
|
|
21
|
+
func (noUnsafeMemberAccess) Name() string { return "typescript/no-unsafe-member-access" }
|
|
22
|
+
func (noUnsafeMemberAccess) NeedsTypeChecker() bool {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
func (noUnsafeMemberAccess) Visits() []shimast.Kind {
|
|
26
|
+
return []shimast.Kind{
|
|
27
|
+
shimast.KindPropertyAccessExpression,
|
|
28
|
+
shimast.KindElementAccessExpression,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
func (noUnsafeMemberAccess) Check(ctx *Context, node *shimast.Node) {
|
|
32
|
+
if ctx.Checker == nil {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
var receiver *shimast.Node
|
|
36
|
+
switch node.Kind {
|
|
37
|
+
case shimast.KindPropertyAccessExpression:
|
|
38
|
+
if access := node.AsPropertyAccessExpression(); access != nil {
|
|
39
|
+
receiver = access.Expression
|
|
40
|
+
}
|
|
41
|
+
case shimast.KindElementAccessExpression:
|
|
42
|
+
if access := node.AsElementAccessExpression(); access != nil {
|
|
43
|
+
receiver = access.Expression
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if receiver == nil {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
t := ctx.Checker.GetTypeAtLocation(receiver)
|
|
50
|
+
if !typeIsUnsafeAny(t) {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
ctx.Report(node, "Unsafe member access on a value typed as `any`. Narrow the receiver to a concrete type before reading a property.")
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
func init() {
|
|
57
|
+
Register(noUnsafeMemberAccess{})
|
|
58
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// typescript/no-unsafe-return: a `return X;` whose expression carries
|
|
2
|
+
// the `any` type from a function whose declared return shape is
|
|
3
|
+
// concrete leaks `any` past the type boundary. Callers see the declared
|
|
4
|
+
// shape, lose every downstream type check on the value, and the bug
|
|
5
|
+
// that introduced the `any` migrates to whichever site reads the result.
|
|
6
|
+
// typescript-eslint:
|
|
7
|
+
// https://typescript-eslint.io/rules/no-unsafe-return/
|
|
8
|
+
//
|
|
9
|
+
// Type-aware. Without a Checker we cannot tell `any` apart from a
|
|
10
|
+
// concrete shape, so Context.Checker == nil short-circuits the visit
|
|
11
|
+
// the same way `no-floating-promises` and `restrict-plus-operands` do.
|
|
12
|
+
//
|
|
13
|
+
// The rule walks each `return` to its enclosing function-like
|
|
14
|
+
// declaration, asks the Checker for that function's signature, and
|
|
15
|
+
// compares the declared return type against the expression type:
|
|
16
|
+
//
|
|
17
|
+
// - the expression must be `any`-typed (raw `any`, not `unknown`);
|
|
18
|
+
// - the declared return type must be concrete — `any`, `unknown`, and
|
|
19
|
+
// `void` are deliberately exempt because they advertise the same
|
|
20
|
+
// looseness at the boundary and a strict rejection would explode
|
|
21
|
+
// on every generic helper that propagates `unknown`.
|
|
22
|
+
package linthost
|
|
23
|
+
|
|
24
|
+
import (
|
|
25
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
26
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
type noUnsafeReturn struct{}
|
|
30
|
+
|
|
31
|
+
func (noUnsafeReturn) Name() string { return "typescript/no-unsafe-return" }
|
|
32
|
+
func (noUnsafeReturn) NeedsTypeChecker() bool {
|
|
33
|
+
return true
|
|
34
|
+
}
|
|
35
|
+
func (noUnsafeReturn) Visits() []shimast.Kind {
|
|
36
|
+
return []shimast.Kind{shimast.KindReturnStatement}
|
|
37
|
+
}
|
|
38
|
+
func (noUnsafeReturn) Check(ctx *Context, node *shimast.Node) {
|
|
39
|
+
if ctx.Checker == nil {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
ret := node.AsReturnStatement()
|
|
43
|
+
if ret == nil || ret.Expression == nil {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
fn := noUnsafeReturnEnclosingFunction(node)
|
|
47
|
+
if fn == nil {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
sig := ctx.Checker.GetSignatureFromDeclaration(fn)
|
|
51
|
+
if sig == nil {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
declared := ctx.Checker.GetReturnTypeOfSignature(sig)
|
|
55
|
+
if declared == nil {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
if !noUnsafeReturnIsConcrete(declared) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
exprType := ctx.Checker.GetTypeAtLocation(ret.Expression)
|
|
62
|
+
if exprType == nil {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
if !noUnsafeReturnIsAny(exprType) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
ctx.Report(ret.Expression, "Unsafe return of `any` value from function with a concrete declared return type. The `any` leaks past the type boundary and disables downstream type checks.")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// noUnsafeReturnEnclosingFunction walks up the parent chain to the
|
|
72
|
+
// nearest function-like declaration that owns this `return`. Nested
|
|
73
|
+
// functions establish their own return scope, so the walk stops at the
|
|
74
|
+
// first function-like ancestor — mirroring the `consistent-return`
|
|
75
|
+
// scope rule already established in this package.
|
|
76
|
+
func noUnsafeReturnEnclosingFunction(node *shimast.Node) *shimast.Node {
|
|
77
|
+
for cur := node.Parent; cur != nil; cur = cur.Parent {
|
|
78
|
+
if isFunctionLikeKind(cur) {
|
|
79
|
+
return cur
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return nil
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// noUnsafeReturnIsConcrete reports whether the declared return type is
|
|
86
|
+
// strict enough to be worth protecting. `any`, `unknown`, and `void`
|
|
87
|
+
// are the three shapes that explicitly advertise looseness — the
|
|
88
|
+
// upstream rule exempts them so generic helpers that propagate
|
|
89
|
+
// `unknown` and side-effect functions that return `void` do not light
|
|
90
|
+
// up everywhere. Unions are concrete only when every constituent is.
|
|
91
|
+
func noUnsafeReturnIsConcrete(t *shimchecker.Type) bool {
|
|
92
|
+
if t == nil {
|
|
93
|
+
return false
|
|
94
|
+
}
|
|
95
|
+
flags := t.Flags()
|
|
96
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsVoid) != 0 {
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
100
|
+
for _, part := range t.Types() {
|
|
101
|
+
if part == nil {
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
if !noUnsafeReturnIsConcrete(part) {
|
|
105
|
+
return false
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return true
|
|
109
|
+
}
|
|
110
|
+
return true
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// noUnsafeReturnIsAny reports whether t is the raw `any` type. The
|
|
114
|
+
// upstream rule treats `unknown` as a safe escape hatch — values
|
|
115
|
+
// returned as `unknown` cannot be used without further narrowing, so
|
|
116
|
+
// they don't leak silently — and only flags the lossy `any` case.
|
|
117
|
+
func noUnsafeReturnIsAny(t *shimchecker.Type) bool {
|
|
118
|
+
if t == nil {
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
121
|
+
return t.Flags()&shimchecker.TypeFlagsAny != 0
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
func init() {
|
|
125
|
+
Register(noUnsafeReturn{})
|
|
126
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// typescript/no-unsafe-unary-minus: the unary `-` operator coerces its
|
|
2
|
+
// operand via `Number()` at runtime, so strings, booleans, and plain
|
|
3
|
+
// objects silently produce `NaN`, `0`, `-1`, or `-NaN` instead of a
|
|
4
|
+
// negated number. The rule restricts the operator to operands whose
|
|
5
|
+
// static type is number-like or bigint-like — the two shapes where the
|
|
6
|
+
// negation is a real arithmetic operation rather than a hidden
|
|
7
|
+
// coercion. typescript-eslint:
|
|
8
|
+
// https://typescript-eslint.io/rules/no-unsafe-unary-minus/
|
|
9
|
+
//
|
|
10
|
+
// Type-aware. Without a Checker the rule cannot tell `-x` on a number
|
|
11
|
+
// apart from `-x` on a string, so Context.Checker == nil short-circuits
|
|
12
|
+
// the visit the same way every other type-aware rule in this package
|
|
13
|
+
// does. `any` / `unknown` / `never` pass through to match the upstream
|
|
14
|
+
// `allowAny`-style defaults that keep generic helpers quiet.
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import (
|
|
18
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
type noUnsafeUnaryMinus struct{}
|
|
23
|
+
|
|
24
|
+
func (noUnsafeUnaryMinus) Name() string { return "typescript/no-unsafe-unary-minus" }
|
|
25
|
+
func (noUnsafeUnaryMinus) NeedsTypeChecker() bool {
|
|
26
|
+
return true
|
|
27
|
+
}
|
|
28
|
+
func (noUnsafeUnaryMinus) Visits() []shimast.Kind {
|
|
29
|
+
return []shimast.Kind{shimast.KindPrefixUnaryExpression}
|
|
30
|
+
}
|
|
31
|
+
func (noUnsafeUnaryMinus) Check(ctx *Context, node *shimast.Node) {
|
|
32
|
+
if ctx.Checker == nil {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
expr := node.AsPrefixUnaryExpression()
|
|
36
|
+
if expr == nil || expr.Operator != shimast.KindMinusToken || expr.Operand == nil {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
t := ctx.Checker.GetTypeAtLocation(expr.Operand)
|
|
40
|
+
if t == nil {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
if noUnsafeUnaryMinusIsNumeric(t) {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
ctx.Report(node, "Unary `-` requires a number-like or bigint-like operand. Other shapes are silently coerced via `Number(x)` and almost always indicate a bug.")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// noUnsafeUnaryMinusIsNumeric reports whether t is provably number-like
|
|
50
|
+
// or bigint-like. `any` / `unknown` / `never` are treated as numeric to
|
|
51
|
+
// keep the rule silent on generic helpers and untyped boundaries —
|
|
52
|
+
// matching the upstream `allowAny` posture. Unions and intersections
|
|
53
|
+
// must have every constituent numeric for the whole type to count.
|
|
54
|
+
func noUnsafeUnaryMinusIsNumeric(t *shimchecker.Type) bool {
|
|
55
|
+
if t == nil {
|
|
56
|
+
return true
|
|
57
|
+
}
|
|
58
|
+
flags := t.Flags()
|
|
59
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
60
|
+
return true
|
|
61
|
+
}
|
|
62
|
+
if flags&(shimchecker.TypeFlagsNumberLike|shimchecker.TypeFlagsBigIntLike) != 0 {
|
|
63
|
+
return true
|
|
64
|
+
}
|
|
65
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
66
|
+
for _, part := range t.Types() {
|
|
67
|
+
if part == nil {
|
|
68
|
+
continue
|
|
69
|
+
}
|
|
70
|
+
if !noUnsafeUnaryMinusIsNumeric(part) {
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return true
|
|
75
|
+
}
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
func init() {
|
|
80
|
+
Register(noUnsafeUnaryMinus{})
|
|
81
|
+
}
|