@ttsc/lint 0.13.0 → 0.14.0-dev.20250530.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 +955 -85
- package/lib/defaultFormat.d.ts +15 -8
- package/lib/defaultFormat.js +15 -8
- 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/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/format/ITtscLintFormat.d.ts +128 -0
- package/lib/structures/{TtscLintRuleMap.js → format/ITtscLintFormat.js} +1 -1
- package/lib/structures/format/ITtscLintFormat.js.map +1 -0
- package/lib/structures/format/ITtscLintFormatJsDoc.d.ts +17 -0
- package/lib/structures/{ITtscLintFormatConfig.js → format/ITtscLintFormatJsDoc.js} +1 -1
- package/lib/structures/format/ITtscLintFormatJsDoc.js.map +1 -0
- package/lib/structures/format/ITtscLintFormatSortImports.d.ts +54 -0
- package/lib/structures/format/ITtscLintFormatSortImports.js +3 -0
- package/lib/structures/format/ITtscLintFormatSortImports.js.map +1 -0
- package/lib/structures/format/index.d.ts +3 -0
- package/lib/structures/format/index.js +20 -0
- package/lib/structures/format/index.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 +95 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +13 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +75 -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 +16 -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 +1229 -0
- package/lib/structures/rules/ITtscLintCoreRules.js +3 -0
- 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 +125 -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 +154 -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 +162 -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 +190 -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 +133 -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 +294 -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 +180 -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 +312 -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 +179 -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 +49 -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 +37 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js +11 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRules.d.ts +276 -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 +182 -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 +65 -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 +141 -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 +178 -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 +20 -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 +165 -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 +88 -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 +21 -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 +293 -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 +1074 -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 +133 -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 +118 -71
- package/linthost/config_format.go +270 -104
- package/linthost/directives.go +67 -25
- package/linthost/dispatch.go +14 -3
- package/linthost/engine.go +160 -40
- package/linthost/fix.go +10 -3
- package/linthost/flags_gen.go +17 -15
- package/linthost/format.go +222 -25
- package/linthost/format_editor_settings.go +262 -0
- package/linthost/host.go +40 -3
- package/linthost/lsp.go +898 -0
- package/linthost/print_dispatch.go +5 -2
- package/linthost/print_engine.go +5 -5
- package/linthost/print_nodes_call.go +149 -67
- package/linthost/print_nodes_function.go +27 -2
- package/linthost/print_nodes_list.go +40 -5
- package/linthost/print_nodes_object.go +1 -1
- package/linthost/print_nodes_ternary.go +86 -0
- 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 +95 -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_arrow_parens.go +167 -0
- package/linthost/rules_format_bracket_spacing.go +117 -0
- package/linthost/rules_format_clause_join.go +172 -0
- package/linthost/rules_format_declaration_header.go +595 -0
- package/linthost/rules_format_indent.go +372 -0
- package/linthost/rules_format_jsdoc.go +5 -5
- package/linthost/rules_format_orphan_semi.go +106 -0
- package/linthost/rules_format_parameter_properties.go +175 -0
- package/linthost/rules_format_print_width.go +66 -55
- package/linthost/rules_format_quote_props.go +169 -0
- package/linthost/rules_format_quotes.go +76 -30
- package/linthost/rules_format_semi.go +186 -11
- package/linthost/rules_format_sort_imports.go +437 -118
- package/linthost/rules_format_statement_split.go +343 -0
- package/linthost/rules_format_ternary_nullish_parens.go +77 -0
- package/linthost/rules_format_trailing_comma.go +22 -3
- package/linthost/rules_format_whitespace.go +336 -0
- 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 +1057 -2
- 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 +159 -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 +17 -10
- package/src/index.ts +65 -43
- package/src/structures/ITtscLintConfig.ts +14 -8
- package/src/structures/TtscLintRuleSetting.ts +55 -0
- package/src/structures/format/ITtscLintFormat.ts +141 -0
- package/src/structures/format/ITtscLintFormatJsDoc.ts +18 -0
- package/src/structures/format/ITtscLintFormatSortImports.ts +62 -0
- package/src/structures/format/index.ts +3 -0
- package/src/structures/index.ts +3 -4
- package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +117 -0
- package/src/structures/rules/ITtscLintBoundariesRules.ts +91 -0
- package/src/structures/rules/ITtscLintContributorRules.ts +20 -0
- package/src/structures/rules/ITtscLintCoreRules.ts +1378 -0
- package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
- package/src/structures/rules/ITtscLintCypressRules.ts +141 -0
- package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +200 -0
- package/src/structures/rules/ITtscLintFunctionalRules.ts +197 -0
- package/src/structures/rules/ITtscLintJestRules.ts +209 -0
- package/src/structures/rules/ITtscLintJsdocRules.ts +146 -0
- package/src/structures/rules/ITtscLintJsxA11yRules.ts +331 -0
- package/src/structures/rules/ITtscLintNextjsRules.ts +201 -0
- package/src/structures/rules/ITtscLintPlaywrightRules.ts +343 -0
- package/src/structures/rules/ITtscLintPromiseRules.ts +196 -0
- package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
- package/src/structures/rules/ITtscLintReactPerfRules.ts +53 -0
- package/src/structures/rules/ITtscLintReactRuleOptions.ts +41 -0
- package/src/structures/rules/ITtscLintReactRules.ts +308 -0
- package/src/structures/rules/ITtscLintRegexpRules.ts +204 -0
- package/src/structures/rules/ITtscLintRuleOptionsMap.ts +88 -0
- package/src/structures/rules/ITtscLintRules.ts +77 -0
- package/src/structures/rules/ITtscLintSecurityRules.ts +155 -0
- package/src/structures/rules/ITtscLintSolidRules.ts +199 -0
- package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +22 -0
- package/src/structures/rules/ITtscLintStorybookRules.ts +184 -0
- package/src/structures/rules/ITtscLintTanstackQueryRules.ts +96 -0
- package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +23 -0
- package/src/structures/rules/ITtscLintTestingLibraryRules.ts +325 -0
- package/src/structures/rules/ITtscLintTypeScriptRules.ts +1172 -0
- package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
- package/src/structures/rules/ITtscLintVitestRules.ts +146 -0
- package/src/structures/rules/index.ts +31 -0
- package/lib/structures/ITtscLintFormatConfig.d.ts +0 -153
- 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/ITtscLintFormatConfig.ts +0 -168
- package/src/structures/TtscLintRule.ts +0 -160
- package/src/structures/TtscLintRuleMap.ts +0 -55
- package/src/structures/TtscLintRuleOptions.ts +0 -151
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// typescript/restrict-plus-operands: the `+` operator is overloaded in
|
|
2
|
+
// JavaScript — it numerically adds two numbers, lexically concatenates
|
|
3
|
+
// two strings, and silently coerces every other combination. `1 + "a"`
|
|
4
|
+
// becomes `"1a"`, `null + 5` becomes `5`, `{} + 1` becomes `"[object
|
|
5
|
+
// Object]1"`. Each of these is almost always a bug: the author meant
|
|
6
|
+
// either numeric addition or explicit string concatenation, not the
|
|
7
|
+
// runtime's lossy fallback. typescript-eslint:
|
|
8
|
+
// https://typescript-eslint.io/rules/restrict-plus-operands/
|
|
9
|
+
package linthost
|
|
10
|
+
|
|
11
|
+
import (
|
|
12
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
13
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// restrictPlusOperands fires on `<lhs> + <rhs>` when the operands are
|
|
17
|
+
// not both number-like, both string-like, or both bigint-like. The
|
|
18
|
+
// rule is type-aware: without a Checker it cannot prove the operand
|
|
19
|
+
// kinds, so it bails out to avoid false positives on plain JS or on
|
|
20
|
+
// files that opt out of typechecking. `any` / `unknown` / `never`
|
|
21
|
+
// operands are treated as unrestricted to keep false positives off
|
|
22
|
+
// generic helpers; the upstream rule does the same.
|
|
23
|
+
type restrictPlusOperands struct{}
|
|
24
|
+
|
|
25
|
+
func (restrictPlusOperands) Name() string { return "typescript/restrict-plus-operands" }
|
|
26
|
+
func (restrictPlusOperands) NeedsTypeChecker() bool {
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
func (restrictPlusOperands) Visits() []shimast.Kind {
|
|
30
|
+
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
31
|
+
}
|
|
32
|
+
func (restrictPlusOperands) Check(ctx *Context, node *shimast.Node) {
|
|
33
|
+
if ctx.Checker == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
expr := node.AsBinaryExpression()
|
|
37
|
+
if expr == nil || expr.OperatorToken == nil {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
if expr.OperatorToken.Kind != shimast.KindPlusToken {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
if expr.Left == nil || expr.Right == nil {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
left := ctx.Checker.GetTypeAtLocation(expr.Left)
|
|
47
|
+
right := ctx.Checker.GetTypeAtLocation(expr.Right)
|
|
48
|
+
if left == nil || right == nil {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
leftKind := restrictPlusOperandsKind(left)
|
|
52
|
+
rightKind := restrictPlusOperandsKind(right)
|
|
53
|
+
// Skip when either side is unconstrained (any / unknown / never /
|
|
54
|
+
// generic) — the rule would otherwise fire on every generic helper
|
|
55
|
+
// that accepts `T extends number | string`.
|
|
56
|
+
if leftKind == restrictPlusOperandsAny || rightKind == restrictPlusOperandsAny {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
if leftKind == rightKind && leftKind != restrictPlusOperandsOther {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
ctx.Report(node, "Operands of `+` must both be `number`, both `string`, or both `bigint`. Mixed or non-primitive operands are silently coerced by the runtime and almost always a bug.")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// restrictPlusOperandsKind classifies t as one of the four buckets the
|
|
66
|
+
// rule cares about. A union is accepted only when every constituent
|
|
67
|
+
// lands in the same primitive bucket — `string | number` is
|
|
68
|
+
// deliberately rejected because each branch would coerce the other
|
|
69
|
+
// side differently at runtime.
|
|
70
|
+
type restrictPlusOperandsBucket int
|
|
71
|
+
|
|
72
|
+
const (
|
|
73
|
+
restrictPlusOperandsOther restrictPlusOperandsBucket = iota
|
|
74
|
+
restrictPlusOperandsAny
|
|
75
|
+
restrictPlusOperandsNumber
|
|
76
|
+
restrictPlusOperandsString
|
|
77
|
+
restrictPlusOperandsBigInt
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
func restrictPlusOperandsKind(t *shimchecker.Type) restrictPlusOperandsBucket {
|
|
81
|
+
if t == nil {
|
|
82
|
+
return restrictPlusOperandsOther
|
|
83
|
+
}
|
|
84
|
+
flags := t.Flags()
|
|
85
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
86
|
+
return restrictPlusOperandsAny
|
|
87
|
+
}
|
|
88
|
+
if flags&shimchecker.TypeFlagsStringLike != 0 {
|
|
89
|
+
return restrictPlusOperandsString
|
|
90
|
+
}
|
|
91
|
+
if flags&shimchecker.TypeFlagsNumberLike != 0 {
|
|
92
|
+
return restrictPlusOperandsNumber
|
|
93
|
+
}
|
|
94
|
+
if flags&shimchecker.TypeFlagsBigIntLike != 0 {
|
|
95
|
+
return restrictPlusOperandsBigInt
|
|
96
|
+
}
|
|
97
|
+
if flags&shimchecker.TypeFlagsUnion != 0 {
|
|
98
|
+
var seen restrictPlusOperandsBucket
|
|
99
|
+
for _, part := range t.Types() {
|
|
100
|
+
if part == nil {
|
|
101
|
+
continue
|
|
102
|
+
}
|
|
103
|
+
kind := restrictPlusOperandsKind(part)
|
|
104
|
+
if kind == restrictPlusOperandsAny {
|
|
105
|
+
return restrictPlusOperandsAny
|
|
106
|
+
}
|
|
107
|
+
if kind == restrictPlusOperandsOther {
|
|
108
|
+
return restrictPlusOperandsOther
|
|
109
|
+
}
|
|
110
|
+
if seen == 0 {
|
|
111
|
+
seen = kind
|
|
112
|
+
continue
|
|
113
|
+
}
|
|
114
|
+
if seen != kind {
|
|
115
|
+
return restrictPlusOperandsOther
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if seen != 0 {
|
|
119
|
+
return seen
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return restrictPlusOperandsOther
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
func init() {
|
|
126
|
+
Register(restrictPlusOperands{})
|
|
127
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// typescript/restrict-template-expressions: every interpolation inside a
|
|
2
|
+
// template literal coerces its value through `String()` at runtime, so
|
|
3
|
+
// non-string-friendly types silently render as `"[object Object]"`,
|
|
4
|
+
// `"null"`, or `"undefined"`. The rule requires each embedded expression
|
|
5
|
+
// to be statically known as `string`, `number`, `bigint`, `boolean`, or
|
|
6
|
+
// a union of those — anything else (object types, `null`, `undefined`,
|
|
7
|
+
// `void`) must be converted explicitly at the call site.
|
|
8
|
+
// typescript-eslint:
|
|
9
|
+
// https://typescript-eslint.io/rules/restrict-template-expressions/
|
|
10
|
+
package linthost
|
|
11
|
+
|
|
12
|
+
import (
|
|
13
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
14
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
// restrictTemplateExpressions reports each `${expr}` span inside a
|
|
18
|
+
// template literal whose expression has a non-stringy static type.
|
|
19
|
+
// Type-aware: without a Checker the rule cannot tell `string | number`
|
|
20
|
+
// apart from `string | null`, so it bails — the AST alone never has
|
|
21
|
+
// enough information to decide this case.
|
|
22
|
+
//
|
|
23
|
+
// `any` / `unknown` / `never` pass through on purpose. They propagate
|
|
24
|
+
// from generic helpers and a strict rejection would explode the
|
|
25
|
+
// false-positive volume; the upstream rule makes the same choice
|
|
26
|
+
// behind its `allowAny` / `allowNever` options, which default to true.
|
|
27
|
+
type restrictTemplateExpressions struct{}
|
|
28
|
+
|
|
29
|
+
func (restrictTemplateExpressions) Name() string {
|
|
30
|
+
return "typescript/restrict-template-expressions"
|
|
31
|
+
}
|
|
32
|
+
func (restrictTemplateExpressions) NeedsTypeChecker() bool {
|
|
33
|
+
return true
|
|
34
|
+
}
|
|
35
|
+
func (restrictTemplateExpressions) Visits() []shimast.Kind {
|
|
36
|
+
return []shimast.Kind{shimast.KindTemplateExpression}
|
|
37
|
+
}
|
|
38
|
+
func (restrictTemplateExpressions) Check(ctx *Context, node *shimast.Node) {
|
|
39
|
+
if ctx.Checker == nil {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
expr := node.AsTemplateExpression()
|
|
43
|
+
if expr == nil || expr.TemplateSpans == nil {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
for _, spanNode := range expr.TemplateSpans.Nodes {
|
|
47
|
+
span := spanNode.AsTemplateSpan()
|
|
48
|
+
if span == nil || span.Expression == nil {
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
t := ctx.Checker.GetTypeAtLocation(span.Expression)
|
|
52
|
+
if t == nil {
|
|
53
|
+
continue
|
|
54
|
+
}
|
|
55
|
+
if restrictTemplateExpressionsIsStringy(ctx.Checker, t) {
|
|
56
|
+
continue
|
|
57
|
+
}
|
|
58
|
+
ctx.Report(span.Expression, "Template interpolations must be string-like (`string`, `number`, `bigint`, or `boolean`) — convert the value explicitly to avoid coercing to `\"[object Object]\"`, `\"null\"`, or `\"undefined\"`.")
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// restrictTemplateExpressionsIsStringy reports whether t is safe to
|
|
63
|
+
// drop into a template-literal slot — string / number / bigint /
|
|
64
|
+
// boolean, or a union/intersection whose every constituent is.
|
|
65
|
+
// `any` / `unknown` / `never` pass through (return true) so generic
|
|
66
|
+
// helpers propagate without lighting up the rule everywhere.
|
|
67
|
+
func restrictTemplateExpressionsIsStringy(checker *shimchecker.Checker, t *shimchecker.Type) bool {
|
|
68
|
+
if checker == nil || t == nil {
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
flags := t.Flags()
|
|
72
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
73
|
+
return true
|
|
74
|
+
}
|
|
75
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
76
|
+
for _, part := range t.Types() {
|
|
77
|
+
if part == nil {
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
if !restrictTemplateExpressionsIsStringy(checker, part) {
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return true
|
|
85
|
+
}
|
|
86
|
+
const stringyMask = shimchecker.TypeFlagsStringLike |
|
|
87
|
+
shimchecker.TypeFlagsNumberLike |
|
|
88
|
+
shimchecker.TypeFlagsBigIntLike |
|
|
89
|
+
shimchecker.TypeFlagsBooleanLike
|
|
90
|
+
return flags&stringyMask != 0
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
func init() {
|
|
94
|
+
Register(restrictTemplateExpressions{})
|
|
95
|
+
}
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
// Additional AST-only `typescript/*` rules from
|
|
2
|
+
// typescript-eslint. Each rule is a small pattern match — no Checker,
|
|
3
|
+
// no scope analysis — and corresponds 1:1 with the upstream rule of
|
|
4
|
+
// the same name.
|
|
5
|
+
//
|
|
6
|
+
// Implemented here:
|
|
7
|
+
// - typescript/no-array-for-each
|
|
8
|
+
// - typescript/no-extraneous-class
|
|
9
|
+
// - typescript/no-invalid-void-type
|
|
10
|
+
package linthost
|
|
11
|
+
|
|
12
|
+
import (
|
|
13
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// noArrayForEach reports `arr.forEach(...)` calls and suggests
|
|
17
|
+
// `for ... of` instead. The for-of form supports early termination
|
|
18
|
+
// (`break`/`return`) and `await`, while `forEach` swallows both. The
|
|
19
|
+
// rule does not confirm that the receiver is actually an array — the
|
|
20
|
+
// syntactic shape is the signal, matching the upstream rule's behavior.
|
|
21
|
+
// https://typescript-eslint.io/rules/no-array-for-each/
|
|
22
|
+
type noArrayForEach struct{}
|
|
23
|
+
|
|
24
|
+
func (noArrayForEach) Name() string { return "typescript/no-array-for-each" }
|
|
25
|
+
func (noArrayForEach) Visits() []shimast.Kind {
|
|
26
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
27
|
+
}
|
|
28
|
+
func (noArrayForEach) Check(ctx *Context, node *shimast.Node) {
|
|
29
|
+
call := node.AsCallExpression()
|
|
30
|
+
if call == nil || call.Expression == nil {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
_, method, ok := promisePropertyAccessParts(call.Expression)
|
|
34
|
+
if !ok || method != "forEach" {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
ctx.Report(node, "Prefer `for ... of` over `Array.forEach()` — `forEach` does not support `await` or `break`.")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// noExtraneousClass reports class declarations that exist purely as a
|
|
41
|
+
// namespace for static members or are entirely empty. A namespace
|
|
42
|
+
// import or a plain function is almost always clearer than `class Util
|
|
43
|
+
// { static foo() { … } }`, and the class adds a layer of indirection
|
|
44
|
+
// without providing any instance behavior.
|
|
45
|
+
// https://typescript-eslint.io/rules/no-extraneous-class/
|
|
46
|
+
//
|
|
47
|
+
// Trigger:
|
|
48
|
+
// - the class has no `extends` heritage,
|
|
49
|
+
// - no constructor with a non-empty body, and
|
|
50
|
+
// - every member is `static` (or the class has no members at all).
|
|
51
|
+
type noExtraneousClass struct{}
|
|
52
|
+
|
|
53
|
+
func (noExtraneousClass) Name() string { return "typescript/no-extraneous-class" }
|
|
54
|
+
func (noExtraneousClass) Visits() []shimast.Kind {
|
|
55
|
+
return []shimast.Kind{shimast.KindClassDeclaration, shimast.KindClassExpression}
|
|
56
|
+
}
|
|
57
|
+
func (noExtraneousClass) Check(ctx *Context, node *shimast.Node) {
|
|
58
|
+
if classExtendsAnother(node) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
if classImplementsAnInterface(node) {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
members := classMembers(node)
|
|
65
|
+
if len(members) == 0 {
|
|
66
|
+
ctx.Report(node, "Empty class — prefer a plain function or namespace.")
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
hasInstanceMember := false
|
|
70
|
+
hasNonTrivialConstructor := false
|
|
71
|
+
for _, member := range members {
|
|
72
|
+
if member == nil {
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
if member.Kind == shimast.KindConstructor {
|
|
76
|
+
ctor := member.AsConstructorDeclaration()
|
|
77
|
+
if ctor != nil && ctor.Body != nil && len(ctor.Body.Statements()) > 0 {
|
|
78
|
+
hasNonTrivialConstructor = true
|
|
79
|
+
}
|
|
80
|
+
continue
|
|
81
|
+
}
|
|
82
|
+
if !hasModifier(member, shimast.KindStaticKeyword) {
|
|
83
|
+
hasInstanceMember = true
|
|
84
|
+
break
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if !hasInstanceMember && !hasNonTrivialConstructor {
|
|
88
|
+
ctx.Report(node, "Class only declares static members — prefer a namespace or top-level functions.")
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// classImplementsAnInterface reports whether the class has an
|
|
93
|
+
// `implements …` heritage clause. Classes that implement an interface
|
|
94
|
+
// are intentionally polymorphic at runtime, so noExtraneousClass
|
|
95
|
+
// should not fire on them.
|
|
96
|
+
func classImplementsAnInterface(class *shimast.Node) bool {
|
|
97
|
+
var clauses []*shimast.Node
|
|
98
|
+
switch class.Kind {
|
|
99
|
+
case shimast.KindClassDeclaration:
|
|
100
|
+
decl := class.AsClassDeclaration()
|
|
101
|
+
if decl == nil || decl.HeritageClauses == nil {
|
|
102
|
+
return false
|
|
103
|
+
}
|
|
104
|
+
clauses = decl.HeritageClauses.Nodes
|
|
105
|
+
case shimast.KindClassExpression:
|
|
106
|
+
expr := class.AsClassExpression()
|
|
107
|
+
if expr == nil || expr.HeritageClauses == nil {
|
|
108
|
+
return false
|
|
109
|
+
}
|
|
110
|
+
clauses = expr.HeritageClauses.Nodes
|
|
111
|
+
default:
|
|
112
|
+
return false
|
|
113
|
+
}
|
|
114
|
+
for _, clause := range clauses {
|
|
115
|
+
if clause == nil {
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
hc := clause.AsHeritageClause()
|
|
119
|
+
if hc == nil || hc.Token != shimast.KindImplementsKeyword {
|
|
120
|
+
continue
|
|
121
|
+
}
|
|
122
|
+
if hc.Types != nil && len(hc.Types.Nodes) > 0 {
|
|
123
|
+
return true
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return false
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// noInvalidVoidType reports a `void` type used as a union constituent
|
|
130
|
+
// or as a generic-type argument. `void` is meaningful only as the sole
|
|
131
|
+
// return type of a function — `void | string` and `Promise<void>` are
|
|
132
|
+
// fine, but `string | void` is almost always a confusion with
|
|
133
|
+
// `undefined`.
|
|
134
|
+
// https://typescript-eslint.io/rules/no-invalid-void-type/
|
|
135
|
+
//
|
|
136
|
+
// Allowed positions:
|
|
137
|
+
// - the return type annotation of a function-like (Function/Method/
|
|
138
|
+
// Arrow/Constructor/CallSignature/MethodSignature/FunctionType);
|
|
139
|
+
// - inside `Promise<void>`, `Generator<void, …, …>`, etc. — these
|
|
140
|
+
// are the established generic exceptions in typescript-eslint.
|
|
141
|
+
type noInvalidVoidType struct{}
|
|
142
|
+
|
|
143
|
+
func (noInvalidVoidType) Name() string { return "typescript/no-invalid-void-type" }
|
|
144
|
+
func (noInvalidVoidType) Visits() []shimast.Kind {
|
|
145
|
+
return []shimast.Kind{shimast.KindVoidKeyword}
|
|
146
|
+
}
|
|
147
|
+
func (noInvalidVoidType) Check(ctx *Context, node *shimast.Node) {
|
|
148
|
+
// The `void` keyword shows up both as a type node and as the unary
|
|
149
|
+
// `void X` expression operator. Filter by parent kind — the
|
|
150
|
+
// expression operator's parent is VoidExpression, not a type position.
|
|
151
|
+
parent := node.Parent
|
|
152
|
+
if parent == nil || parent.Kind == shimast.KindVoidExpression {
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
if isValidVoidPosition(node) {
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
ctx.Report(node, "`void` is only valid as the return type annotation of a function or as a known generic argument.")
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// isValidVoidPosition reports whether a `void` type node sits in one
|
|
162
|
+
// of the approved positions: a function return type or an
|
|
163
|
+
// allow-listed generic type argument (Promise/Generator/AsyncGenerator/
|
|
164
|
+
// Iterator/AsyncIterator/IterableIterator).
|
|
165
|
+
func isValidVoidPosition(node *shimast.Node) bool {
|
|
166
|
+
parent := node.Parent
|
|
167
|
+
if parent == nil {
|
|
168
|
+
return false
|
|
169
|
+
}
|
|
170
|
+
switch parent.Kind {
|
|
171
|
+
case shimast.KindFunctionDeclaration,
|
|
172
|
+
shimast.KindFunctionExpression,
|
|
173
|
+
shimast.KindArrowFunction,
|
|
174
|
+
shimast.KindMethodDeclaration,
|
|
175
|
+
shimast.KindMethodSignature,
|
|
176
|
+
shimast.KindConstructor,
|
|
177
|
+
shimast.KindGetAccessor,
|
|
178
|
+
shimast.KindSetAccessor,
|
|
179
|
+
shimast.KindCallSignature,
|
|
180
|
+
shimast.KindConstructSignature,
|
|
181
|
+
shimast.KindFunctionType,
|
|
182
|
+
shimast.KindConstructorType,
|
|
183
|
+
shimast.KindIndexSignature:
|
|
184
|
+
return parent.Type() == node
|
|
185
|
+
case shimast.KindTypeReference:
|
|
186
|
+
// `void` as a generic argument — allowed inside the typescript-
|
|
187
|
+
// eslint approved set.
|
|
188
|
+
grand := parent.Parent
|
|
189
|
+
if grand == nil {
|
|
190
|
+
return false
|
|
191
|
+
}
|
|
192
|
+
if grand.Kind == shimast.KindTypeReference {
|
|
193
|
+
ref := grand.AsTypeReferenceNode()
|
|
194
|
+
if ref == nil {
|
|
195
|
+
return false
|
|
196
|
+
}
|
|
197
|
+
name := identifierText(ref.TypeName)
|
|
198
|
+
switch name {
|
|
199
|
+
case "Promise", "Generator", "AsyncGenerator", "Iterator", "AsyncIterator", "IterableIterator", "AsyncIterableIterator":
|
|
200
|
+
return true
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Walk up: if the parent chain leads directly to an allow-listed
|
|
205
|
+
// generic type reference's typeArguments list, accept.
|
|
206
|
+
for cur := parent; cur != nil; cur = cur.Parent {
|
|
207
|
+
if cur.Kind == shimast.KindTypeReference {
|
|
208
|
+
ref := cur.AsTypeReferenceNode()
|
|
209
|
+
if ref == nil {
|
|
210
|
+
return false
|
|
211
|
+
}
|
|
212
|
+
name := identifierText(ref.TypeName)
|
|
213
|
+
switch name {
|
|
214
|
+
case "Promise", "Generator", "AsyncGenerator", "Iterator", "AsyncIterator", "IterableIterator", "AsyncIterableIterator":
|
|
215
|
+
return true
|
|
216
|
+
}
|
|
217
|
+
return false
|
|
218
|
+
}
|
|
219
|
+
// Stop walking past statement boundaries — `void` in
|
|
220
|
+
// `let x: string | void;` should still fire.
|
|
221
|
+
switch cur.Kind {
|
|
222
|
+
case shimast.KindVariableDeclaration,
|
|
223
|
+
shimast.KindParameter,
|
|
224
|
+
shimast.KindPropertyDeclaration,
|
|
225
|
+
shimast.KindPropertySignature:
|
|
226
|
+
return false
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return false
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// explicitMemberAccessibility requires every class member declaration
|
|
233
|
+
// to carry a `public` / `private` / `protected` modifier. Implicit
|
|
234
|
+
// public is permitted by TypeScript but obscures intent — explicit
|
|
235
|
+
// keywords make the encapsulation contract self-documenting and
|
|
236
|
+
// catch the common bug of "I forgot to make this private."
|
|
237
|
+
// https://typescript-eslint.io/rules/explicit-member-accessibility/
|
|
238
|
+
//
|
|
239
|
+
// Class fields whose name starts with `#` are exempt — the private
|
|
240
|
+
// hash already carries the same meaning. The constructor is exempt;
|
|
241
|
+
// upstream allows omitting accessibility on the constructor itself.
|
|
242
|
+
type explicitMemberAccessibility struct{}
|
|
243
|
+
|
|
244
|
+
func (explicitMemberAccessibility) Name() string {
|
|
245
|
+
return "typescript/explicit-member-accessibility"
|
|
246
|
+
}
|
|
247
|
+
func (explicitMemberAccessibility) Visits() []shimast.Kind {
|
|
248
|
+
return []shimast.Kind{
|
|
249
|
+
shimast.KindMethodDeclaration,
|
|
250
|
+
shimast.KindPropertyDeclaration,
|
|
251
|
+
shimast.KindGetAccessor,
|
|
252
|
+
shimast.KindSetAccessor,
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
func (explicitMemberAccessibility) Check(ctx *Context, node *shimast.Node) {
|
|
256
|
+
// Skip non-class-scoped members.
|
|
257
|
+
parent := node.Parent
|
|
258
|
+
if parent == nil ||
|
|
259
|
+
(parent.Kind != shimast.KindClassDeclaration && parent.Kind != shimast.KindClassExpression) {
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
// Skip private hash identifiers.
|
|
263
|
+
if name := node.Name(); name != nil && name.Kind == shimast.KindPrivateIdentifier {
|
|
264
|
+
return
|
|
265
|
+
}
|
|
266
|
+
if classMemberHasAccessibility(node) {
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
ctx.Report(node, "Class member is missing an explicit accessibility modifier (`public`, `private`, or `protected`).")
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// classMemberHasAccessibility reports whether the member carries an
|
|
273
|
+
// explicit `public` / `private` / `protected` modifier.
|
|
274
|
+
func classMemberHasAccessibility(node *shimast.Node) bool {
|
|
275
|
+
if node == nil {
|
|
276
|
+
return false
|
|
277
|
+
}
|
|
278
|
+
mods := node.Modifiers()
|
|
279
|
+
if mods == nil {
|
|
280
|
+
return false
|
|
281
|
+
}
|
|
282
|
+
for _, m := range mods.Nodes {
|
|
283
|
+
if m == nil {
|
|
284
|
+
continue
|
|
285
|
+
}
|
|
286
|
+
switch m.Kind {
|
|
287
|
+
case shimast.KindPublicKeyword,
|
|
288
|
+
shimast.KindPrivateKeyword,
|
|
289
|
+
shimast.KindProtectedKeyword:
|
|
290
|
+
return true
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return false
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// consistentGenericConstructors reports the redundant pattern where a
|
|
297
|
+
// variable is annotated with a generic type AND the same generic
|
|
298
|
+
// arguments are repeated on the constructor call:
|
|
299
|
+
//
|
|
300
|
+
// const m: Map<string, number> = new Map<string, number>();
|
|
301
|
+
//
|
|
302
|
+
// One of the two type-argument lists is enough. The upstream default
|
|
303
|
+
// prefers the constructor form; the annotation form is also valid but
|
|
304
|
+
// stating both is noise.
|
|
305
|
+
// https://typescript-eslint.io/rules/consistent-generic-constructors/
|
|
306
|
+
type consistentGenericConstructors struct{}
|
|
307
|
+
|
|
308
|
+
func (consistentGenericConstructors) Name() string {
|
|
309
|
+
return "typescript/consistent-generic-constructors"
|
|
310
|
+
}
|
|
311
|
+
func (consistentGenericConstructors) Visits() []shimast.Kind {
|
|
312
|
+
return []shimast.Kind{shimast.KindVariableDeclaration}
|
|
313
|
+
}
|
|
314
|
+
func (consistentGenericConstructors) Check(ctx *Context, node *shimast.Node) {
|
|
315
|
+
decl := node.AsVariableDeclaration()
|
|
316
|
+
if decl == nil || decl.Type == nil || decl.Initializer == nil {
|
|
317
|
+
return
|
|
318
|
+
}
|
|
319
|
+
if decl.Type.Kind != shimast.KindTypeReference {
|
|
320
|
+
return
|
|
321
|
+
}
|
|
322
|
+
typeRef := decl.Type.AsTypeReferenceNode()
|
|
323
|
+
if typeRef == nil || typeRef.TypeArguments == nil {
|
|
324
|
+
return
|
|
325
|
+
}
|
|
326
|
+
initializer := stripParens(decl.Initializer)
|
|
327
|
+
if initializer == nil || initializer.Kind != shimast.KindNewExpression {
|
|
328
|
+
return
|
|
329
|
+
}
|
|
330
|
+
ne := initializer.AsNewExpression()
|
|
331
|
+
if ne == nil || ne.TypeArguments == nil {
|
|
332
|
+
return
|
|
333
|
+
}
|
|
334
|
+
ctx.Report(initializer, "Redundant generic arguments — the annotation already pins the type parameters; drop them from the constructor or vice versa.")
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// preferNumericLiterals reports `parseInt(literal, radix)` calls that
|
|
338
|
+
// could be written as an ES2015+ numeric literal (binary `0b…`, octal
|
|
339
|
+
// `0o…`, hex `0x…`). The literal form is shorter, type-safe, and not
|
|
340
|
+
// subject to runtime radix mismatches.
|
|
341
|
+
// https://eslint.org/docs/latest/rules/prefer-numeric-literals
|
|
342
|
+
type preferNumericLiterals struct{}
|
|
343
|
+
|
|
344
|
+
func (preferNumericLiterals) Name() string { return "prefer-numeric-literals" }
|
|
345
|
+
func (preferNumericLiterals) Visits() []shimast.Kind {
|
|
346
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
347
|
+
}
|
|
348
|
+
func (preferNumericLiterals) Check(ctx *Context, node *shimast.Node) {
|
|
349
|
+
call := node.AsCallExpression()
|
|
350
|
+
if call == nil || call.Expression == nil || call.Arguments == nil {
|
|
351
|
+
return
|
|
352
|
+
}
|
|
353
|
+
calleeName := identifierText(call.Expression)
|
|
354
|
+
if calleeName != "parseInt" && calleeName != "Number" {
|
|
355
|
+
return
|
|
356
|
+
}
|
|
357
|
+
args := call.Arguments.Nodes
|
|
358
|
+
if calleeName == "parseInt" && len(args) != 2 {
|
|
359
|
+
return
|
|
360
|
+
}
|
|
361
|
+
if calleeName == "Number" && len(args) != 1 {
|
|
362
|
+
return
|
|
363
|
+
}
|
|
364
|
+
first := stripParens(args[0])
|
|
365
|
+
if first == nil || first.Kind != shimast.KindStringLiteral {
|
|
366
|
+
return
|
|
367
|
+
}
|
|
368
|
+
if calleeName == "parseInt" {
|
|
369
|
+
radix := stripParens(args[1])
|
|
370
|
+
if radix == nil || radix.Kind != shimast.KindNumericLiteral {
|
|
371
|
+
return
|
|
372
|
+
}
|
|
373
|
+
switch numericLiteralText(radix) {
|
|
374
|
+
case "2", "8", "16":
|
|
375
|
+
ctx.Report(node, "Use a numeric literal (`0b…` / `0o…` / `0x…`) instead of `parseInt(\""+stringLiteralText(first)+"\", "+numericLiteralText(radix)+")`.")
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
func init() {
|
|
381
|
+
Register(noArrayForEach{})
|
|
382
|
+
Register(noExtraneousClass{})
|
|
383
|
+
Register(noInvalidVoidType{})
|
|
384
|
+
Register(explicitMemberAccessibility{})
|
|
385
|
+
Register(consistentGenericConstructors{})
|
|
386
|
+
Register(preferNumericLiterals{})
|
|
387
|
+
}
|