@ttsc/lint 0.13.0 → 0.14.0-dev.20260528
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +948 -69
- package/lib/defaultFormat.d.ts +9 -6
- package/lib/defaultFormat.js +9 -6
- package/lib/defaultFormat.js.map +1 -1
- package/lib/index.d.ts +46 -0
- package/lib/index.js +60 -37
- package/lib/index.js.map +1 -1
- package/lib/structures/ITtscLintConfig.d.ts +12 -6
- package/lib/structures/{ITtscLintFormatConfig.d.ts → ITtscLintFormat.d.ts} +2 -2
- package/lib/structures/{TtscLintRuleMap.js → ITtscLintFormat.js} +1 -1
- package/lib/structures/ITtscLintFormat.js.map +1 -0
- package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
- package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
- package/lib/structures/TtscLintRuleSetting.js.map +1 -0
- package/lib/structures/index.d.ts +3 -4
- package/lib/structures/index.js +3 -4
- package/lib/structures/index.js.map +1 -1
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +104 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +14 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +79 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintContributorRules.d.ts +17 -0
- package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
- package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintCoreRules.d.ts +1257 -0
- package/lib/structures/{ITtscLintFormatConfig.js → rules/ITtscLintCoreRules.js} +1 -1
- package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintCypressRules.d.ts +129 -0
- package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
- package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +157 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +167 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJestRules.d.ts +201 -0
- package/lib/structures/rules/ITtscLintJestRules.js +3 -0
- package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJsdocRules.d.ts +140 -0
- package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
- package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +302 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintNextjsRules.d.ts +185 -0
- package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
- package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +330 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintPromiseRules.d.ts +188 -0
- package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
- package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +51 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +39 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js +12 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRules.d.ts +289 -0
- package/lib/structures/rules/ITtscLintReactRules.js +3 -0
- package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintRegexpRules.d.ts +190 -0
- package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
- package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +66 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
- package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
- package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
- package/lib/structures/rules/ITtscLintRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintSecurityRules.d.ts +148 -0
- package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
- package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintSolidRules.d.ts +181 -0
- package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
- package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +21 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintStorybookRules.d.ts +174 -0
- package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
- package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +94 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +22 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +310 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1132 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
- package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
- package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintVitestRules.d.ts +141 -0
- package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
- package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
- package/lib/structures/rules/index.d.ts +31 -0
- package/lib/structures/rules/index.js +48 -0
- package/lib/structures/rules/index.js.map +1 -0
- package/linthost/ast_helpers.go +30 -5
- package/linthost/compile.go +33 -2
- package/linthost/config.go +48 -17
- package/linthost/config_format.go +9 -9
- package/linthost/directives.go +67 -25
- package/linthost/dispatch.go +14 -3
- package/linthost/engine.go +160 -40
- package/linthost/fix.go +2 -2
- package/linthost/flags_gen.go +17 -15
- package/linthost/host.go +40 -3
- package/linthost/lsp.go +747 -0
- package/linthost/print_dispatch.go +2 -2
- package/linthost/print_nodes_function.go +2 -2
- package/linthost/print_nodes_object.go +1 -1
- package/linthost/rule_names.go +14 -0
- package/linthost/rules_arrays.go +2 -2
- package/linthost/rules_boundaries.go +532 -0
- package/linthost/rules_camelcase.go +133 -0
- package/linthost/rules_complexity.go +94 -0
- package/linthost/rules_consistent_return.go +130 -0
- package/linthost/rules_console.go +1 -1
- package/linthost/rules_core_extra.go +739 -0
- package/linthost/rules_curly.go +70 -0
- package/linthost/rules_cypress.go +608 -0
- package/linthost/rules_debugger.go +2 -2
- package/linthost/rules_default_case.go +39 -0
- package/linthost/rules_default_case_last.go +46 -0
- package/linthost/rules_dupes.go +3 -3
- package/linthost/rules_empty.go +3 -3
- package/linthost/rules_escape.go +44 -24
- package/linthost/rules_eval.go +2 -2
- package/linthost/rules_finally.go +2 -2
- package/linthost/rules_format_jsdoc.go +1 -1
- package/linthost/rules_format_print_width.go +9 -9
- package/linthost/rules_format_quotes.go +1 -1
- package/linthost/rules_format_semi.go +1 -1
- package/linthost/rules_format_sort_imports.go +1 -1
- package/linthost/rules_format_trailing_comma.go +1 -1
- package/linthost/rules_functional.go +967 -0
- package/linthost/rules_gap.go +24 -45
- package/linthost/rules_grouped_accessor_pairs.go +87 -0
- package/linthost/rules_guard_for_in.go +198 -0
- package/linthost/rules_id_length.go +77 -0
- package/linthost/rules_imports.go +70 -2
- package/linthost/rules_init_declarations.go +53 -0
- package/linthost/rules_jest.go +618 -0
- package/linthost/rules_jsdoc.go +502 -0
- package/linthost/rules_jsx_a11y.go +1264 -0
- package/linthost/rules_logic.go +12 -12
- package/linthost/rules_loops.go +1 -1
- package/linthost/rules_max_classes_per_file.go +58 -0
- package/linthost/rules_max_depth.go +83 -0
- package/linthost/rules_max_lines.go +101 -0
- package/linthost/rules_max_lines_per_function.go +57 -0
- package/linthost/rules_max_nested_callbacks.go +61 -0
- package/linthost/rules_max_params.go +49 -0
- package/linthost/rules_max_statements.go +59 -0
- package/linthost/rules_misc.go +1 -1
- package/linthost/rules_nextjs.go +697 -0
- package/linthost/rules_no_else_return.go +75 -0
- package/linthost/rules_no_empty_named_blocks.go +91 -0
- package/linthost/rules_no_extend_native.go +51 -0
- package/linthost/rules_no_import_assign.go +140 -0
- package/linthost/rules_no_invalid_this.go +52 -0
- package/linthost/rules_no_loop_func.go +85 -0
- package/linthost/rules_no_magic_numbers.go +123 -0
- package/linthost/rules_no_mixed_operators.go +80 -0
- package/linthost/rules_no_param_reassign.go +98 -0
- package/linthost/rules_no_redeclare.go +270 -0
- package/linthost/rules_no_restricted_imports.go +105 -0
- package/linthost/rules_no_restricted_syntax.go +49 -0
- package/linthost/rules_no_shadow.go +147 -0
- package/linthost/rules_no_unreachable.go +77 -0
- package/linthost/rules_no_useless_assignment.go +120 -0
- package/linthost/rules_no_useless_constructor.go +245 -0
- package/linthost/rules_no_useless_return.go +51 -0
- package/linthost/rules_params.go +1 -1
- package/linthost/rules_playwright.go +788 -0
- package/linthost/rules_prefer_arrow_callback.go +124 -0
- package/linthost/rules_prefer_destructuring.go +98 -0
- package/linthost/rules_prefer_named_capture_group.go +129 -0
- package/linthost/rules_prefer_rest_params.go +94 -0
- package/linthost/rules_problems.go +41 -30
- package/linthost/rules_promise.go +1128 -73
- package/linthost/rules_protos.go +2 -2
- package/linthost/rules_react.go +773 -0
- package/linthost/rules_react_extras.go +227 -0
- package/linthost/rules_react_hooks.go +848 -0
- package/linthost/rules_react_perf.go +293 -0
- package/linthost/rules_react_refresh.go +583 -0
- package/linthost/rules_regexp.go +410 -0
- package/linthost/rules_security.go +830 -0
- package/linthost/rules_self.go +2 -2
- package/linthost/rules_solid.go +1073 -0
- package/linthost/rules_sort_imports.go +69 -0
- package/linthost/rules_sort_keys.go +134 -0
- package/linthost/rules_storybook.go +1176 -0
- package/linthost/rules_strings.go +4 -4
- package/linthost/rules_suggestions.go +38 -38
- package/linthost/rules_tanstack_query.go +844 -0
- package/linthost/rules_testing_library.go +1204 -0
- package/linthost/rules_throw.go +1 -1
- package/linthost/rules_ts.go +19 -19
- package/linthost/rules_ts_async.go +399 -0
- package/linthost/rules_ts_class_literal_property_style.go +115 -0
- package/linthost/rules_ts_consistent_type_exports.go +256 -0
- package/linthost/rules_ts_explicit_function_return_type.go +67 -0
- package/linthost/rules_ts_extra.go +155 -36
- package/linthost/rules_ts_no_base_to_string.go +218 -0
- package/linthost/rules_ts_no_confusing_void.go +72 -0
- package/linthost/rules_ts_no_deprecated.go +195 -0
- package/linthost/rules_ts_no_for_in_array.go +84 -0
- package/linthost/rules_ts_no_magic_numbers.go +124 -0
- package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
- package/linthost/rules_ts_no_misused_spread.go +104 -0
- package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
- package/linthost/rules_ts_no_restricted_types.go +62 -0
- package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
- package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
- package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
- package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
- package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
- package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
- package/linthost/rules_ts_no_unsafe_argument.go +82 -0
- package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
- package/linthost/rules_ts_no_unsafe_call.go +82 -0
- package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
- package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
- package/linthost/rules_ts_no_unsafe_return.go +126 -0
- package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
- package/linthost/rules_ts_no_useless_constructor.go +52 -0
- package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
- package/linthost/rules_ts_parameter_properties.go +38 -0
- package/linthost/rules_ts_prefer_find.go +178 -0
- package/linthost/rules_ts_prefer_includes.go +255 -0
- package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
- package/linthost/rules_ts_prefer_optional_chain.go +228 -0
- package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
- package/linthost/rules_ts_prefer_readonly.go +73 -0
- package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
- package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
- package/linthost/rules_ts_prefer_return_this_type.go +135 -0
- package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
- package/linthost/rules_ts_promise_function_async.go +77 -0
- package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
- package/linthost/rules_ts_require_array_sort_compare.go +96 -0
- package/linthost/rules_ts_restrict_plus_operands.go +127 -0
- package/linthost/rules_ts_restrict_template_expressions.go +95 -0
- package/linthost/rules_ts_simple.go +387 -0
- package/linthost/rules_ts_sort_type_constituents.go +144 -0
- package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
- package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
- package/linthost/rules_ts_unbound_method.go +126 -0
- package/linthost/rules_tsdoc.go +136 -0
- package/linthost/rules_unicorn_better_regex.go +27 -0
- package/linthost/rules_unicorn_catch_error_name.go +46 -0
- package/linthost/rules_unicorn_consistent_assert.go +47 -0
- package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
- package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
- package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
- package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
- package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
- package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
- package/linthost/rules_unicorn_custom_error_definition.go +138 -0
- package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
- package/linthost/rules_unicorn_error_message.go +64 -0
- package/linthost/rules_unicorn_escape_case.go +51 -0
- package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
- package/linthost/rules_unicorn_explicit_length_check.go +88 -0
- package/linthost/rules_unicorn_filename_case.go +29 -0
- package/linthost/rules_unicorn_import_style.go +28 -0
- package/linthost/rules_unicorn_isolated_functions.go +29 -0
- package/linthost/rules_unicorn_new_for_builtins.go +87 -0
- package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
- package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
- package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
- package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
- package/linthost/rules_unicorn_no_array_for_each.go +40 -0
- package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
- package/linthost/rules_unicorn_no_array_reduce.go +41 -0
- package/linthost/rules_unicorn_no_array_reverse.go +44 -0
- package/linthost/rules_unicorn_no_array_sort.go +43 -0
- package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
- package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
- package/linthost/rules_unicorn_no_console_spaces.go +61 -0
- package/linthost/rules_unicorn_no_document_cookie.go +41 -0
- package/linthost/rules_unicorn_no_empty_file.go +44 -0
- package/linthost/rules_unicorn_no_for_loop.go +102 -0
- package/linthost/rules_unicorn_no_hex_escape.go +42 -0
- package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
- package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
- package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
- package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
- package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
- package/linthost/rules_unicorn_no_lonely_if.go +44 -0
- package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
- package/linthost/rules_unicorn_no_named_default.go +54 -0
- package/linthost/rules_unicorn_no_negated_condition.go +85 -0
- package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
- package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
- package/linthost/rules_unicorn_no_new_array.go +30 -0
- package/linthost/rules_unicorn_no_new_buffer.go +31 -0
- package/linthost/rules_unicorn_no_null.go +24 -0
- package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
- package/linthost/rules_unicorn_no_process_exit.go +43 -0
- package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
- package/linthost/rules_unicorn_no_static_only_class.go +56 -0
- package/linthost/rules_unicorn_no_thenable.go +74 -0
- package/linthost/rules_unicorn_no_this_assignment.go +35 -0
- package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
- package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
- package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
- package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
- package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
- package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
- package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
- package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
- package/linthost/rules_unicorn_no_unused_properties.go +30 -0
- package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
- package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
- package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
- package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
- package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
- package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
- package/linthost/rules_unicorn_no_useless_spread.go +67 -0
- package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
- package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
- package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
- package/linthost/rules_unicorn_number_literal_case.go +69 -0
- package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
- package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
- package/linthost/rules_unicorn_prefer_array_find.go +51 -0
- package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
- package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
- package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
- package/linthost/rules_unicorn_prefer_array_some.go +67 -0
- package/linthost/rules_unicorn_prefer_at.go +77 -0
- package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
- package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
- package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
- package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
- package/linthost/rules_unicorn_prefer_code_point.go +49 -0
- package/linthost/rules_unicorn_prefer_date_now.go +78 -0
- package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
- package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
- package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
- package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
- package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
- package/linthost/rules_unicorn_prefer_event_target.go +36 -0
- package/linthost/rules_unicorn_prefer_export_from.go +129 -0
- package/linthost/rules_unicorn_prefer_global_this.go +127 -0
- package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
- package/linthost/rules_unicorn_prefer_includes.go +149 -0
- package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
- package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
- package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
- package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
- package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
- package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
- package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
- package/linthost/rules_unicorn_prefer_module.go +50 -0
- package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
- package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
- package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
- package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
- package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
- package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
- package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
- package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
- package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
- package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
- package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
- package/linthost/rules_unicorn_prefer_set_has.go +42 -0
- package/linthost/rules_unicorn_prefer_set_size.go +48 -0
- package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
- package/linthost/rules_unicorn_prefer_single_call.go +96 -0
- package/linthost/rules_unicorn_prefer_spread.go +51 -0
- package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
- package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
- package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
- package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
- package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
- package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
- package/linthost/rules_unicorn_prefer_switch.go +103 -0
- package/linthost/rules_unicorn_prefer_ternary.go +71 -0
- package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
- package/linthost/rules_unicorn_prefer_type_error.go +127 -0
- package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
- package/linthost/rules_unicorn_relative_url_style.go +49 -0
- package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
- package/linthost/rules_unicorn_require_module_attributes.go +54 -0
- package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
- package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
- package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
- package/linthost/rules_unicorn_string_content.go +27 -0
- package/linthost/rules_unicorn_switch_case_braces.go +42 -0
- package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
- package/linthost/rules_unicorn_template_indent.go +28 -0
- package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
- package/linthost/rules_unicorn_throw_new_error.go +61 -0
- package/linthost/rules_var.go +10 -4
- package/linthost/rules_vitest.go +568 -0
- package/package.json +3 -3
- package/plugin/main.go +49 -3
- package/rule/astutil/astutil.go +10 -3
- package/rule/rule.go +12 -10
- package/src/defaultFormat.ts +11 -8
- package/src/index.ts +65 -43
- package/src/structures/ITtscLintConfig.ts +12 -6
- package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
- package/src/structures/TtscLintRuleSetting.ts +55 -0
- package/src/structures/index.ts +3 -4
- package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
- package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
- package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
- package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
- package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
- package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
- package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
- package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
- package/src/structures/rules/ITtscLintJestRules.ts +220 -0
- package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
- package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
- package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
- package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
- package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
- package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
- package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
- package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
- package/src/structures/rules/ITtscLintReactRules.ts +321 -0
- package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
- package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
- package/src/structures/rules/ITtscLintRules.ts +77 -0
- package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
- package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
- package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
- package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
- package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
- package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
- package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
- package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
- package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
- package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
- package/src/structures/rules/index.ts +31 -0
- package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
- package/lib/structures/TtscLintRule.d.ts +0 -17
- package/lib/structures/TtscLintRule.js.map +0 -1
- package/lib/structures/TtscLintRuleMap.d.ts +0 -46
- package/lib/structures/TtscLintRuleMap.js.map +0 -1
- package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
- package/lib/structures/TtscLintRuleOptions.js.map +0 -1
- package/src/structures/TtscLintRule.ts +0 -160
- package/src/structures/TtscLintRuleMap.ts +0 -55
- package/src/structures/TtscLintRuleOptions.ts +0 -151
package/linthost/rules_throw.go
CHANGED
|
@@ -2,7 +2,7 @@ package linthost
|
|
|
2
2
|
|
|
3
3
|
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
4
4
|
|
|
5
|
-
//
|
|
5
|
+
// noThrowLiteral: throw should always pass an Error subclass.
|
|
6
6
|
// https://eslint.org/docs/latest/rules/no-throw-literal
|
|
7
7
|
type noThrowLiteral struct{}
|
|
8
8
|
|
package/linthost/rules_ts.go
CHANGED
|
@@ -6,20 +6,20 @@ package linthost
|
|
|
6
6
|
|
|
7
7
|
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
8
8
|
|
|
9
|
-
//
|
|
9
|
+
// noExplicitAny: ban `: any` annotations. Loud equivalent of
|
|
10
10
|
// `@typescript-eslint/no-explicit-any`.
|
|
11
11
|
type noExplicitAny struct{}
|
|
12
12
|
|
|
13
|
-
func (noExplicitAny) Name() string { return "no-explicit-any" }
|
|
13
|
+
func (noExplicitAny) Name() string { return "typescript/no-explicit-any" }
|
|
14
14
|
func (noExplicitAny) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindAnyKeyword} }
|
|
15
15
|
func (noExplicitAny) Check(ctx *Context, node *shimast.Node) {
|
|
16
16
|
ctx.Report(node, "Unexpected any. Specify a different type.")
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
//
|
|
19
|
+
// noNonNullAssertion: ban the postfix `!` non-null assertion.
|
|
20
20
|
type noNonNullAssertion struct{}
|
|
21
21
|
|
|
22
|
-
func (noNonNullAssertion) Name() string { return "no-non-null-assertion" }
|
|
22
|
+
func (noNonNullAssertion) Name() string { return "typescript/no-non-null-assertion" }
|
|
23
23
|
func (noNonNullAssertion) Visits() []shimast.Kind {
|
|
24
24
|
return []shimast.Kind{shimast.KindNonNullExpression}
|
|
25
25
|
}
|
|
@@ -27,11 +27,11 @@ func (noNonNullAssertion) Check(ctx *Context, node *shimast.Node) {
|
|
|
27
27
|
ctx.Report(node, "Forbidden non-null assertion.")
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
//
|
|
30
|
+
// noEmptyInterface: empty `interface { }` declarations are an alias
|
|
31
31
|
// for the supertype with extra ceremony.
|
|
32
32
|
type noEmptyInterface struct{}
|
|
33
33
|
|
|
34
|
-
func (noEmptyInterface) Name() string { return "no-empty-interface" }
|
|
34
|
+
func (noEmptyInterface) Name() string { return "typescript/no-empty-interface" }
|
|
35
35
|
func (noEmptyInterface) Visits() []shimast.Kind {
|
|
36
36
|
return []shimast.Kind{shimast.KindInterfaceDeclaration}
|
|
37
37
|
}
|
|
@@ -45,11 +45,11 @@ func (noEmptyInterface) Check(ctx *Context, node *shimast.Node) {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
//
|
|
48
|
+
// noInferrableTypes: `let x: number = 0` — the annotation is what TS
|
|
49
49
|
// would have inferred anyway.
|
|
50
50
|
type noInferrableTypes struct{}
|
|
51
51
|
|
|
52
|
-
func (noInferrableTypes) Name() string { return "no-inferrable-types" }
|
|
52
|
+
func (noInferrableTypes) Name() string { return "typescript/no-inferrable-types" }
|
|
53
53
|
func (noInferrableTypes) Visits() []shimast.Kind {
|
|
54
54
|
return []shimast.Kind{shimast.KindVariableDeclaration, shimast.KindParameter, shimast.KindPropertyDeclaration}
|
|
55
55
|
}
|
|
@@ -126,11 +126,11 @@ func isUnaryNumeric(node *shimast.Node) bool {
|
|
|
126
126
|
return false
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
//
|
|
129
|
+
// noNamespace: TypeScript-only `namespace`/`module` declarations. They
|
|
130
130
|
// exist for legacy reasons; modern TS uses ES modules.
|
|
131
131
|
type noNamespace struct{}
|
|
132
132
|
|
|
133
|
-
func (noNamespace) Name() string { return "no-namespace" }
|
|
133
|
+
func (noNamespace) Name() string { return "typescript/no-namespace" }
|
|
134
134
|
func (noNamespace) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindModuleDeclaration} }
|
|
135
135
|
func (noNamespace) Check(ctx *Context, node *shimast.Node) {
|
|
136
136
|
decl := node.AsModuleDeclaration()
|
|
@@ -145,11 +145,11 @@ func (noNamespace) Check(ctx *Context, node *shimast.Node) {
|
|
|
145
145
|
ctx.Report(node, "ES2015 module syntax is preferred over namespaces.")
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
//
|
|
148
|
+
// noThisAlias: `const self = this;` reassigns `this` to a local. Use
|
|
149
149
|
// arrow functions or `.bind(this)` instead.
|
|
150
150
|
type noThisAlias struct{}
|
|
151
151
|
|
|
152
|
-
func (noThisAlias) Name() string { return "no-this-alias" }
|
|
152
|
+
func (noThisAlias) Name() string { return "typescript/no-this-alias" }
|
|
153
153
|
func (noThisAlias) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindVariableDeclaration} }
|
|
154
154
|
func (noThisAlias) Check(ctx *Context, node *shimast.Node) {
|
|
155
155
|
decl := node.AsVariableDeclaration()
|
|
@@ -161,10 +161,10 @@ func (noThisAlias) Check(ctx *Context, node *shimast.Node) {
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
//
|
|
164
|
+
// preferAsConst: `as 'foo'` / `as 1` should be `as const`.
|
|
165
165
|
type preferAsConst struct{}
|
|
166
166
|
|
|
167
|
-
func (preferAsConst) Name() string { return "prefer-as-const" }
|
|
167
|
+
func (preferAsConst) Name() string { return "typescript/prefer-as-const" }
|
|
168
168
|
func (preferAsConst) Visits() []shimast.Kind {
|
|
169
169
|
return []shimast.Kind{shimast.KindAsExpression, shimast.KindTypeAssertionExpression}
|
|
170
170
|
}
|
|
@@ -213,7 +213,7 @@ func (preferAsConst) Check(ctx *Context, node *shimast.Node) {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
// literalsMatchSourceText reports whether lhs and rhs are both literal
|
|
216
|
-
// expressions whose source text is identical. Used by
|
|
216
|
+
// expressions whose source text is identical. Used by preferAsConst to
|
|
217
217
|
// detect `x as "foo"` where "foo" matches x's literal value.
|
|
218
218
|
func literalsMatchSourceText(file *shimast.SourceFile, lhs, rhs *shimast.Node) bool {
|
|
219
219
|
if lhs == nil || rhs == nil {
|
|
@@ -225,11 +225,11 @@ func literalsMatchSourceText(file *shimast.SourceFile, lhs, rhs *shimast.Node) b
|
|
|
225
225
|
return nodeText(file, lhs) == nodeText(file, rhs)
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
//
|
|
228
|
+
// noRequireImports: ban `require(...)` calls in TS source. Use
|
|
229
229
|
// ES `import` instead.
|
|
230
230
|
type noRequireImports struct{}
|
|
231
231
|
|
|
232
|
-
func (noRequireImports) Name() string { return "no-require-imports" }
|
|
232
|
+
func (noRequireImports) Name() string { return "typescript/no-require-imports" }
|
|
233
233
|
func (noRequireImports) Visits() []shimast.Kind {
|
|
234
234
|
return []shimast.Kind{shimast.KindCallExpression, shimast.KindImportEqualsDeclaration}
|
|
235
235
|
}
|
|
@@ -250,11 +250,11 @@ func (noRequireImports) Check(ctx *Context, node *shimast.Node) {
|
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
-
//
|
|
253
|
+
// banTsComment: `// @ts-ignore` / `// @ts-nocheck` / `// @ts-expect-error`
|
|
254
254
|
// silence the type checker. Default mode flags every variant.
|
|
255
255
|
type banTsComment struct{}
|
|
256
256
|
|
|
257
|
-
func (banTsComment) Name() string { return "ban-ts-comment" }
|
|
257
|
+
func (banTsComment) Name() string { return "typescript/ban-ts-comment" }
|
|
258
258
|
func (banTsComment) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindSourceFile} }
|
|
259
259
|
func (banTsComment) Check(ctx *Context, node *shimast.Node) {
|
|
260
260
|
if ctx.File == nil {
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
// TypeScript async/error-flow rules: type-aware ports of the
|
|
2
|
+
// typescript-eslint recommended-type-checked rules that round out the
|
|
3
|
+
// async story alongside `typescript/await-thenable`,
|
|
4
|
+
// `typescript/no-floating-promises`, and `typescript/return-await`
|
|
5
|
+
// already in rules_promise.go.
|
|
6
|
+
//
|
|
7
|
+
// Implemented here:
|
|
8
|
+
// - typescript/require-await
|
|
9
|
+
// (AST-only; async function with no `await` in its body)
|
|
10
|
+
// - typescript/no-misused-promises
|
|
11
|
+
// (type-aware; Promise in conditional / logical / forEach position)
|
|
12
|
+
// - typescript/use-unknown-in-catch-callback-variable
|
|
13
|
+
// (type-aware; `.catch(err)` / `.then(_, err)` must annotate `unknown`)
|
|
14
|
+
// - typescript/only-throw-error
|
|
15
|
+
// (type-aware; `throw` of a primitive value)
|
|
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
|
+
// requireAwait reports `async` function bodies that contain no `await`
|
|
24
|
+
// expression. The function still pays the microtask cost and signals
|
|
25
|
+
// async semantics to callers; the missing `await` is almost always a
|
|
26
|
+
// refactor artifact. typescript-eslint:
|
|
27
|
+
// https://typescript-eslint.io/rules/require-await/
|
|
28
|
+
//
|
|
29
|
+
// AST-only. The walker stops at nested function-like boundaries so an
|
|
30
|
+
// `await` inside an inner non-async closure does not count toward the
|
|
31
|
+
// outer function. Async generators are exempt — they satisfy the
|
|
32
|
+
// async-keyword contract through `yield`.
|
|
33
|
+
type requireAwait struct{}
|
|
34
|
+
|
|
35
|
+
func (requireAwait) Name() string { return "typescript/require-await" }
|
|
36
|
+
func (requireAwait) Visits() []shimast.Kind {
|
|
37
|
+
return []shimast.Kind{
|
|
38
|
+
shimast.KindFunctionDeclaration,
|
|
39
|
+
shimast.KindFunctionExpression,
|
|
40
|
+
shimast.KindArrowFunction,
|
|
41
|
+
shimast.KindMethodDeclaration,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
func (requireAwait) Check(ctx *Context, node *shimast.Node) {
|
|
45
|
+
if !hasAsyncModifier(node) {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
if requireAwaitIsAsyncGenerator(node) {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
body := node.Body()
|
|
52
|
+
if body == nil {
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
if requireAwaitBodyHasAwait(body) {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
startPos := keywordStart(ctx.File, node, "async")
|
|
59
|
+
if startPos < 0 {
|
|
60
|
+
ctx.Report(node, "Async function has no `await` expression.")
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
ctx.ReportRange(startPos, startPos+len("async"), "Async function has no `await` expression.")
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// requireAwaitIsAsyncGenerator reports whether node is `async function*`,
|
|
67
|
+
// `async *method`, or the function-expression form thereof. Async
|
|
68
|
+
// generators are exempted by typescript-eslint: the generator's `yield`
|
|
69
|
+
// expressions express the suspend points and the rule would otherwise
|
|
70
|
+
// fire on every `async function*` that does not also `await`.
|
|
71
|
+
func requireAwaitIsAsyncGenerator(node *shimast.Node) bool {
|
|
72
|
+
switch node.Kind {
|
|
73
|
+
case shimast.KindFunctionDeclaration:
|
|
74
|
+
decl := node.AsFunctionDeclaration()
|
|
75
|
+
return decl != nil && decl.AsteriskToken != nil
|
|
76
|
+
case shimast.KindFunctionExpression:
|
|
77
|
+
expr := node.AsFunctionExpression()
|
|
78
|
+
return expr != nil && expr.AsteriskToken != nil
|
|
79
|
+
case shimast.KindMethodDeclaration:
|
|
80
|
+
decl := node.AsMethodDeclaration()
|
|
81
|
+
return decl != nil && decl.AsteriskToken != nil
|
|
82
|
+
}
|
|
83
|
+
return false
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// requireAwaitBodyHasAwait reports whether body (or any descendant that
|
|
87
|
+
// is not itself a nested function-like scope) contains an `await`
|
|
88
|
+
// expression. The walker mirrors `walkFunctionBody` in rules_promise.go
|
|
89
|
+
// but bails out early once an `await` is found.
|
|
90
|
+
func requireAwaitBodyHasAwait(body *shimast.Node) bool {
|
|
91
|
+
found := false
|
|
92
|
+
var walk func(*shimast.Node)
|
|
93
|
+
walk = func(n *shimast.Node) {
|
|
94
|
+
if found || n == nil {
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
if n != body && isFunctionLikeKind(n) {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
if n.Kind == shimast.KindAwaitExpression {
|
|
101
|
+
found = true
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
n.ForEachChild(func(child *shimast.Node) bool {
|
|
105
|
+
walk(child)
|
|
106
|
+
return false
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
walk(body)
|
|
110
|
+
return found
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// noMisusedPromises reports Promises supplied where a boolean or a
|
|
114
|
+
// `void`-returning callback is expected. The Promise is truthy as a
|
|
115
|
+
// value, so the conditional silently passes; the discarded Promise then
|
|
116
|
+
// leaks any rejection. typescript-eslint:
|
|
117
|
+
// https://typescript-eslint.io/rules/no-misused-promises/
|
|
118
|
+
//
|
|
119
|
+
// Type-aware. Covers the three highest-signal positions:
|
|
120
|
+
// - conditional positions: `if (p)`, `while (p)`, `do … while (p)`,
|
|
121
|
+
// `for (; p; …)`, `p ? a : b`, `!p`;
|
|
122
|
+
// - short-circuit / nullish operators: `p && x`, `p || x`, `p ?? x`;
|
|
123
|
+
// - array iteration: `.forEach(async fn)` where the callback returns
|
|
124
|
+
// a Promise the iteration never observes.
|
|
125
|
+
//
|
|
126
|
+
// JSX event-handler positions and arbitrary user-defined
|
|
127
|
+
// void-callback contracts are deferred — they need a richer expected-
|
|
128
|
+
// type inspection than this baseline.
|
|
129
|
+
type noMisusedPromises struct{}
|
|
130
|
+
|
|
131
|
+
func (noMisusedPromises) Name() string { return "typescript/no-misused-promises" }
|
|
132
|
+
func (noMisusedPromises) NeedsTypeChecker() bool {
|
|
133
|
+
return true
|
|
134
|
+
}
|
|
135
|
+
func (noMisusedPromises) Visits() []shimast.Kind {
|
|
136
|
+
return []shimast.Kind{
|
|
137
|
+
shimast.KindIfStatement,
|
|
138
|
+
shimast.KindWhileStatement,
|
|
139
|
+
shimast.KindDoStatement,
|
|
140
|
+
shimast.KindForStatement,
|
|
141
|
+
shimast.KindConditionalExpression,
|
|
142
|
+
shimast.KindPrefixUnaryExpression,
|
|
143
|
+
shimast.KindBinaryExpression,
|
|
144
|
+
shimast.KindCallExpression,
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
func (noMisusedPromises) Check(ctx *Context, node *shimast.Node) {
|
|
148
|
+
if ctx.Checker == nil {
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
switch node.Kind {
|
|
152
|
+
case shimast.KindIfStatement:
|
|
153
|
+
if stmt := node.AsIfStatement(); stmt != nil {
|
|
154
|
+
noMisusedPromisesReportConditional(ctx, stmt.Expression)
|
|
155
|
+
}
|
|
156
|
+
case shimast.KindWhileStatement:
|
|
157
|
+
if stmt := node.AsWhileStatement(); stmt != nil {
|
|
158
|
+
noMisusedPromisesReportConditional(ctx, stmt.Expression)
|
|
159
|
+
}
|
|
160
|
+
case shimast.KindDoStatement:
|
|
161
|
+
if stmt := node.AsDoStatement(); stmt != nil {
|
|
162
|
+
noMisusedPromisesReportConditional(ctx, stmt.Expression)
|
|
163
|
+
}
|
|
164
|
+
case shimast.KindForStatement:
|
|
165
|
+
if stmt := node.AsForStatement(); stmt != nil {
|
|
166
|
+
noMisusedPromisesReportConditional(ctx, stmt.Condition)
|
|
167
|
+
}
|
|
168
|
+
case shimast.KindConditionalExpression:
|
|
169
|
+
if expr := node.AsConditionalExpression(); expr != nil {
|
|
170
|
+
noMisusedPromisesReportConditional(ctx, expr.Condition)
|
|
171
|
+
}
|
|
172
|
+
case shimast.KindPrefixUnaryExpression:
|
|
173
|
+
expr := node.AsPrefixUnaryExpression()
|
|
174
|
+
if expr != nil && expr.Operator == shimast.KindExclamationToken {
|
|
175
|
+
noMisusedPromisesReportConditional(ctx, expr.Operand)
|
|
176
|
+
}
|
|
177
|
+
case shimast.KindBinaryExpression:
|
|
178
|
+
bin := node.AsBinaryExpression()
|
|
179
|
+
if bin == nil || bin.OperatorToken == nil {
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
switch bin.OperatorToken.Kind {
|
|
183
|
+
case shimast.KindAmpersandAmpersandToken,
|
|
184
|
+
shimast.KindBarBarToken,
|
|
185
|
+
shimast.KindQuestionQuestionToken:
|
|
186
|
+
noMisusedPromisesReportConditional(ctx, bin.Left)
|
|
187
|
+
}
|
|
188
|
+
case shimast.KindCallExpression:
|
|
189
|
+
if call := node.AsCallExpression(); call != nil {
|
|
190
|
+
noMisusedPromisesCheckVoidCallback(ctx, call)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// noMisusedPromisesReportConditional reports expr if it carries a
|
|
196
|
+
// Promise type. `await x` and `void x` are author-acknowledged opt-outs
|
|
197
|
+
// and pass through. `any` / `unknown` / `never` are intentionally NOT
|
|
198
|
+
// flagged because they propagate from generic helpers and would
|
|
199
|
+
// produce overwhelming false-positive volume in real codebases.
|
|
200
|
+
func noMisusedPromisesReportConditional(ctx *Context, expr *shimast.Node) {
|
|
201
|
+
target := stripParens(expr)
|
|
202
|
+
if target == nil {
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
switch target.Kind {
|
|
206
|
+
case shimast.KindAwaitExpression, shimast.KindVoidExpression:
|
|
207
|
+
return
|
|
208
|
+
}
|
|
209
|
+
t := ctx.Checker.GetTypeAtLocation(target)
|
|
210
|
+
if t == nil || !isPromiseTypedExpression(ctx.Checker, t) {
|
|
211
|
+
return
|
|
212
|
+
}
|
|
213
|
+
ctx.Report(target, "Expected non-Promise value in a boolean conditional position; did you forget `await`?")
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// noMisusedPromisesCheckVoidCallback fires when an async callback is
|
|
217
|
+
// passed to a method that expects a void-returning callback. The
|
|
218
|
+
// baseline targets the most common offender — `Array.prototype.forEach`
|
|
219
|
+
// — by name rather than by signature inspection. Restricting to
|
|
220
|
+
// `forEach` keeps the false-positive rate low; richer void-callback
|
|
221
|
+
// detection (e.g., JSX event handlers, user methods with `void` in
|
|
222
|
+
// their signature) is deferred.
|
|
223
|
+
func noMisusedPromisesCheckVoidCallback(ctx *Context, call *shimast.CallExpression) {
|
|
224
|
+
if call == nil || call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
|
|
225
|
+
return
|
|
226
|
+
}
|
|
227
|
+
_, method, ok := promisePropertyAccessParts(call.Expression)
|
|
228
|
+
if !ok || method != "forEach" {
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
callback := stripParens(call.Arguments.Nodes[0])
|
|
232
|
+
if callback == nil || !isFunctionLikeKind(callback) {
|
|
233
|
+
return
|
|
234
|
+
}
|
|
235
|
+
if !hasAsyncModifier(callback) {
|
|
236
|
+
return
|
|
237
|
+
}
|
|
238
|
+
ctx.Report(callback, "Async callback passed to forEach — the returned Promise will be discarded; use `for ... of` instead.")
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// useUnknownInCatchCallbackVariable requires the parameter of `.catch`
|
|
242
|
+
// and the second parameter of `.then` to be explicitly typed `unknown`.
|
|
243
|
+
// TypeScript 4.4+ types `try { } catch (e)` as `unknown` by default;
|
|
244
|
+
// promise chain callbacks still default to implicit `any`, so this rule
|
|
245
|
+
// closes that ergonomic gap. typescript-eslint:
|
|
246
|
+
// https://typescript-eslint.io/rules/use-unknown-in-catch-callback-variable/
|
|
247
|
+
//
|
|
248
|
+
// Type-aware: only fires when the receiver of `.catch` / `.then` is
|
|
249
|
+
// actually a Promise (rules out user-defined methods named `catch`).
|
|
250
|
+
// The annotation check is textual on the parameter's type node — the
|
|
251
|
+
// annotation must be exactly the token `unknown`.
|
|
252
|
+
type useUnknownInCatchCallbackVariable struct{}
|
|
253
|
+
|
|
254
|
+
func (useUnknownInCatchCallbackVariable) Name() string {
|
|
255
|
+
return "typescript/use-unknown-in-catch-callback-variable"
|
|
256
|
+
}
|
|
257
|
+
func (useUnknownInCatchCallbackVariable) NeedsTypeChecker() bool {
|
|
258
|
+
return true
|
|
259
|
+
}
|
|
260
|
+
func (useUnknownInCatchCallbackVariable) Visits() []shimast.Kind {
|
|
261
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
262
|
+
}
|
|
263
|
+
func (useUnknownInCatchCallbackVariable) Check(ctx *Context, node *shimast.Node) {
|
|
264
|
+
if ctx.Checker == nil {
|
|
265
|
+
return
|
|
266
|
+
}
|
|
267
|
+
call := node.AsCallExpression()
|
|
268
|
+
if call == nil || call.Expression == nil || call.Arguments == nil {
|
|
269
|
+
return
|
|
270
|
+
}
|
|
271
|
+
receiver, method, ok := promisePropertyAccessParts(call.Expression)
|
|
272
|
+
if !ok || (method != "catch" && method != "then") {
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
args := call.Arguments.Nodes
|
|
276
|
+
var callback *shimast.Node
|
|
277
|
+
switch method {
|
|
278
|
+
case "catch":
|
|
279
|
+
if len(args) < 1 {
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
callback = stripParens(args[0])
|
|
283
|
+
case "then":
|
|
284
|
+
if len(args) < 2 {
|
|
285
|
+
return
|
|
286
|
+
}
|
|
287
|
+
callback = stripParens(args[1])
|
|
288
|
+
}
|
|
289
|
+
if callback == nil || !isFunctionLikeKind(callback) {
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
if receiver == nil {
|
|
293
|
+
return
|
|
294
|
+
}
|
|
295
|
+
t := ctx.Checker.GetTypeAtLocation(receiver)
|
|
296
|
+
if t == nil || !isPromiseTypedExpression(ctx.Checker, t) {
|
|
297
|
+
return
|
|
298
|
+
}
|
|
299
|
+
params := callback.Parameters()
|
|
300
|
+
if len(params) == 0 {
|
|
301
|
+
return
|
|
302
|
+
}
|
|
303
|
+
param := params[0].AsParameterDeclaration()
|
|
304
|
+
if param == nil {
|
|
305
|
+
return
|
|
306
|
+
}
|
|
307
|
+
if param.Type == nil {
|
|
308
|
+
ctx.Report(params[0], "Catch callback parameter should be explicitly typed `unknown`.")
|
|
309
|
+
return
|
|
310
|
+
}
|
|
311
|
+
annotationText := nodeText(ctx.File, param.Type)
|
|
312
|
+
if annotationText != "unknown" {
|
|
313
|
+
ctx.Report(param.Type, "Catch callback parameter must be typed `unknown`, not `"+annotationText+"`.")
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// onlyThrowError reports `throw` of a value that is statically known
|
|
318
|
+
// to be a primitive (string / number / boolean / bigint / void /
|
|
319
|
+
// undefined / null). Throwing a non-Error loses the structured stack
|
|
320
|
+
// trace and breaks downstream `instanceof Error` checks.
|
|
321
|
+
// typescript-eslint:
|
|
322
|
+
// https://typescript-eslint.io/rules/only-throw-error/
|
|
323
|
+
//
|
|
324
|
+
// Type-aware. `any` / `unknown` / `never` pass through — they propagate
|
|
325
|
+
// from generic helpers and a strict rejection would explode at every
|
|
326
|
+
// re-throw of a caught `unknown`. Object types are conservatively
|
|
327
|
+
// allowed (a full base-type walk to confirm Error-derivation is
|
|
328
|
+
// deferred); the practical effect is that `throw "string"` and
|
|
329
|
+
// `throw 42` are caught but `throw { code: 1 }` slips through.
|
|
330
|
+
type onlyThrowError struct{}
|
|
331
|
+
|
|
332
|
+
func (onlyThrowError) Name() string { return "typescript/only-throw-error" }
|
|
333
|
+
func (onlyThrowError) NeedsTypeChecker() bool {
|
|
334
|
+
return true
|
|
335
|
+
}
|
|
336
|
+
func (onlyThrowError) Visits() []shimast.Kind {
|
|
337
|
+
return []shimast.Kind{shimast.KindThrowStatement}
|
|
338
|
+
}
|
|
339
|
+
func (onlyThrowError) Check(ctx *Context, node *shimast.Node) {
|
|
340
|
+
if ctx.Checker == nil {
|
|
341
|
+
return
|
|
342
|
+
}
|
|
343
|
+
stmt := node.AsThrowStatement()
|
|
344
|
+
if stmt == nil || stmt.Expression == nil {
|
|
345
|
+
return
|
|
346
|
+
}
|
|
347
|
+
expr := stripParens(stmt.Expression)
|
|
348
|
+
if expr == nil {
|
|
349
|
+
return
|
|
350
|
+
}
|
|
351
|
+
t := ctx.Checker.GetTypeAtLocation(expr)
|
|
352
|
+
if t == nil {
|
|
353
|
+
return
|
|
354
|
+
}
|
|
355
|
+
if onlyThrowErrorIsPrimitive(ctx.Checker, t) {
|
|
356
|
+
ctx.Report(node, "Throw an Error object instead of a non-Error value.")
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// onlyThrowErrorIsPrimitive returns true when t is a primitive type
|
|
361
|
+
// (string / number / boolean / bigint / void / undefined / null).
|
|
362
|
+
// any / unknown / never escape the check on purpose. Union and
|
|
363
|
+
// intersection types recurse — `string | number` is a primitive
|
|
364
|
+
// throw even though it is a composite type.
|
|
365
|
+
func onlyThrowErrorIsPrimitive(checker *shimchecker.Checker, t *shimchecker.Type) bool {
|
|
366
|
+
if checker == nil || t == nil {
|
|
367
|
+
return false
|
|
368
|
+
}
|
|
369
|
+
flags := t.Flags()
|
|
370
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
371
|
+
return false
|
|
372
|
+
}
|
|
373
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
374
|
+
for _, part := range t.Types() {
|
|
375
|
+
if part == nil {
|
|
376
|
+
continue
|
|
377
|
+
}
|
|
378
|
+
if onlyThrowErrorIsPrimitive(checker, part) {
|
|
379
|
+
return true
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return false
|
|
383
|
+
}
|
|
384
|
+
const primitiveMask = shimchecker.TypeFlagsStringLike |
|
|
385
|
+
shimchecker.TypeFlagsNumberLike |
|
|
386
|
+
shimchecker.TypeFlagsBigIntLike |
|
|
387
|
+
shimchecker.TypeFlagsBooleanLike |
|
|
388
|
+
shimchecker.TypeFlagsVoid |
|
|
389
|
+
shimchecker.TypeFlagsUndefined |
|
|
390
|
+
shimchecker.TypeFlagsNull
|
|
391
|
+
return flags&primitiveMask != 0
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
func init() {
|
|
395
|
+
Register(requireAwait{})
|
|
396
|
+
Register(noMisusedPromises{})
|
|
397
|
+
Register(useUnknownInCatchCallbackVariable{})
|
|
398
|
+
Register(onlyThrowError{})
|
|
399
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// AST-only `typescript/class-literal-property-style` rule from
|
|
2
|
+
// typescript-eslint. Implemented here as a standalone file because the
|
|
3
|
+
// rule's literal-shape predicate and getter/setter pairing are
|
|
4
|
+
// self-contained and unrelated to the other class-shape rules already
|
|
5
|
+
// living in rules_ts_simple.go.
|
|
6
|
+
package linthost
|
|
7
|
+
|
|
8
|
+
import (
|
|
9
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// classLiteralPropertyStyle reports `get foo() { return <literal>; }`
|
|
13
|
+
// accessors that have no companion setter — those should be expressed
|
|
14
|
+
// as a `readonly foo = <literal>;` field declaration. The getter form
|
|
15
|
+
// re-runs the body on every read and obscures the fact that the value
|
|
16
|
+
// is fixed; a readonly field is shorter, type-narrows to the literal
|
|
17
|
+
// type, and signals "this is a constant" at the call site.
|
|
18
|
+
// https://typescript-eslint.io/rules/class-literal-property-style/
|
|
19
|
+
//
|
|
20
|
+
// Default upstream config is `"fields"`, matching the wording above.
|
|
21
|
+
// The rule fires when:
|
|
22
|
+
// - the class member is a `get` accessor,
|
|
23
|
+
// - its body is a block containing a single `return <literal>;`,
|
|
24
|
+
// - the literal is a string, number, boolean, `null`, a template
|
|
25
|
+
// literal with no substitutions, or a unary-minus prefix on a
|
|
26
|
+
// numeric literal,
|
|
27
|
+
// - the class has no `set` accessor for the same member name.
|
|
28
|
+
type classLiteralPropertyStyle struct{}
|
|
29
|
+
|
|
30
|
+
func (classLiteralPropertyStyle) Name() string {
|
|
31
|
+
return "typescript/class-literal-property-style"
|
|
32
|
+
}
|
|
33
|
+
func (classLiteralPropertyStyle) Visits() []shimast.Kind {
|
|
34
|
+
return []shimast.Kind{shimast.KindGetAccessor}
|
|
35
|
+
}
|
|
36
|
+
func (classLiteralPropertyStyle) Check(ctx *Context, node *shimast.Node) {
|
|
37
|
+
parent := node.Parent
|
|
38
|
+
if parent == nil ||
|
|
39
|
+
(parent.Kind != shimast.KindClassDeclaration && parent.Kind != shimast.KindClassExpression) {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
accessor := node.AsGetAccessorDeclaration()
|
|
43
|
+
if accessor == nil || accessor.Body == nil || accessor.Body.Kind != shimast.KindBlock {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
statements := accessor.Body.Statements()
|
|
47
|
+
if len(statements) != 1 {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
ret := statements[0]
|
|
51
|
+
if ret == nil || ret.Kind != shimast.KindReturnStatement {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
retStmt := ret.AsReturnStatement()
|
|
55
|
+
if retStmt == nil || retStmt.Expression == nil {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
if !isClassLiteralPropertyValue(retStmt.Expression) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
name := classMemberName(node)
|
|
62
|
+
if name == "" {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
if classHasSetterFor(parent, name) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
ctx.Report(node, "Literal-returning getter `"+name+"` should be a `readonly` field instead.")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// isClassLiteralPropertyValue reports whether the expression is one of
|
|
72
|
+
// the literal shapes the rule accepts: a plain literal, a template
|
|
73
|
+
// literal without substitutions, or a unary-minus prefix on a numeric
|
|
74
|
+
// literal.
|
|
75
|
+
func isClassLiteralPropertyValue(expr *shimast.Node) bool {
|
|
76
|
+
if expr == nil {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
switch expr.Kind {
|
|
80
|
+
case shimast.KindStringLiteral,
|
|
81
|
+
shimast.KindNumericLiteral,
|
|
82
|
+
shimast.KindTrueKeyword,
|
|
83
|
+
shimast.KindFalseKeyword,
|
|
84
|
+
shimast.KindNullKeyword,
|
|
85
|
+
shimast.KindNoSubstitutionTemplateLiteral:
|
|
86
|
+
return true
|
|
87
|
+
case shimast.KindPrefixUnaryExpression:
|
|
88
|
+
prefix := expr.AsPrefixUnaryExpression()
|
|
89
|
+
if prefix == nil || prefix.Operator != shimast.KindMinusToken || prefix.Operand == nil {
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
return prefix.Operand.Kind == shimast.KindNumericLiteral
|
|
93
|
+
}
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// classHasSetterFor reports whether the class contains a `set`
|
|
98
|
+
// accessor whose name matches `name`. A getter paired with a setter
|
|
99
|
+
// is left alone because the field form cannot reproduce the setter's
|
|
100
|
+
// side effects.
|
|
101
|
+
func classHasSetterFor(class *shimast.Node, name string) bool {
|
|
102
|
+
for _, member := range classMembers(class) {
|
|
103
|
+
if member == nil || member.Kind != shimast.KindSetAccessor {
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
if classMemberName(member) == name {
|
|
107
|
+
return true
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return false
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
func init() {
|
|
114
|
+
Register(classLiteralPropertyStyle{})
|
|
115
|
+
}
|