@ttsc/lint 0.13.1 → 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 +35 -10
- 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/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 +152 -31
- package/linthost/fix.go +10 -3
- package/linthost/format.go +222 -25
- package/linthost/format_editor_settings.go +262 -0
- 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 +4 -4
- package/linthost/rules_vitest.go +568 -0
- package/package.json +3 -3
- package/plugin/main.go +49 -3
- package/rule/astutil/astutil.go +10 -3
- package/rule/rule.go +12 -10
- package/src/defaultFormat.ts +17 -10
- package/src/index.ts +40 -16
- 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
|
@@ -11,10 +11,10 @@ import (
|
|
|
11
11
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
-
//
|
|
14
|
+
// noConfusingNonNullAssertion: `a! == b` reads ambiguously.
|
|
15
15
|
type noConfusingNonNullAssertion struct{}
|
|
16
16
|
|
|
17
|
-
func (noConfusingNonNullAssertion) Name() string { return "no-confusing-non-null-assertion" }
|
|
17
|
+
func (noConfusingNonNullAssertion) Name() string { return "typescript/no-confusing-non-null-assertion" }
|
|
18
18
|
func (noConfusingNonNullAssertion) Visits() []shimast.Kind {
|
|
19
19
|
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
20
20
|
}
|
|
@@ -37,11 +37,11 @@ func (noConfusingNonNullAssertion) Check(ctx *Context, node *shimast.Node) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
//
|
|
40
|
+
// noDuplicateEnumValues: `enum E { A = 1, B = 1 }` — duplicate values
|
|
41
41
|
// silently collapse.
|
|
42
42
|
type noDuplicateEnumValues struct{}
|
|
43
43
|
|
|
44
|
-
func (noDuplicateEnumValues) Name() string { return "no-duplicate-enum-values" }
|
|
44
|
+
func (noDuplicateEnumValues) Name() string { return "typescript/no-duplicate-enum-values" }
|
|
45
45
|
func (noDuplicateEnumValues) Visits() []shimast.Kind {
|
|
46
46
|
return []shimast.Kind{shimast.KindEnumDeclaration}
|
|
47
47
|
}
|
|
@@ -77,13 +77,13 @@ func (noDuplicateEnumValues) Check(ctx *Context, node *shimast.Node) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
//
|
|
80
|
+
// noMixedEnums: forbid enums that mix numeric and string member shapes.
|
|
81
81
|
// A single enum with `{ A, B = "two" }` produces broken reverse mappings
|
|
82
82
|
// and surprising assignability. typescript-eslint recommended:
|
|
83
83
|
// https://typescript-eslint.io/rules/no-mixed-enums/
|
|
84
84
|
type noMixedEnums struct{}
|
|
85
85
|
|
|
86
|
-
func (noMixedEnums) Name() string { return "no-mixed-enums" }
|
|
86
|
+
func (noMixedEnums) Name() string { return "typescript/no-mixed-enums" }
|
|
87
87
|
func (noMixedEnums) Visits() []shimast.Kind {
|
|
88
88
|
return []shimast.Kind{shimast.KindEnumDeclaration}
|
|
89
89
|
}
|
|
@@ -137,10 +137,10 @@ func (noMixedEnums) Check(ctx *Context, node *shimast.Node) {
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
//
|
|
140
|
+
// noExtraNonNullAssertion: `a!!` / `a!?.b` collapses two assertions.
|
|
141
141
|
type noExtraNonNullAssertion struct{}
|
|
142
142
|
|
|
143
|
-
func (noExtraNonNullAssertion) Name() string { return "no-extra-non-null-assertion" }
|
|
143
|
+
func (noExtraNonNullAssertion) Name() string { return "typescript/no-extra-non-null-assertion" }
|
|
144
144
|
func (noExtraNonNullAssertion) Visits() []shimast.Kind {
|
|
145
145
|
return []shimast.Kind{shimast.KindNonNullExpression}
|
|
146
146
|
}
|
|
@@ -169,11 +169,13 @@ func (noExtraNonNullAssertion) Check(ctx *Context, node *shimast.Node) {
|
|
|
169
169
|
)
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
//
|
|
172
|
+
// noNonNullAssertedOptionalChain: `foo?.bar!` — the chain produces
|
|
173
173
|
// undefined; asserting non-null on the whole chain defeats the chain.
|
|
174
174
|
type noNonNullAssertedOptionalChain struct{}
|
|
175
175
|
|
|
176
|
-
func (noNonNullAssertedOptionalChain) Name() string {
|
|
176
|
+
func (noNonNullAssertedOptionalChain) Name() string {
|
|
177
|
+
return "typescript/no-non-null-asserted-optional-chain"
|
|
178
|
+
}
|
|
177
179
|
func (noNonNullAssertedOptionalChain) Visits() []shimast.Kind {
|
|
178
180
|
return []shimast.Kind{shimast.KindNonNullExpression}
|
|
179
181
|
}
|
|
@@ -224,12 +226,12 @@ func containsOptionalChain(node *shimast.Node) bool {
|
|
|
224
226
|
return false
|
|
225
227
|
}
|
|
226
228
|
|
|
227
|
-
//
|
|
229
|
+
// noMisusedNew: declaring a `new` signature on a non-class interface
|
|
228
230
|
// or a `constructor` method on an interface — these don't do what
|
|
229
231
|
// authors expect.
|
|
230
232
|
type noMisusedNew struct{}
|
|
231
233
|
|
|
232
|
-
func (noMisusedNew) Name() string { return "no-misused-new" }
|
|
234
|
+
func (noMisusedNew) Name() string { return "typescript/no-misused-new" }
|
|
233
235
|
func (noMisusedNew) Visits() []shimast.Kind {
|
|
234
236
|
return []shimast.Kind{shimast.KindInterfaceDeclaration, shimast.KindTypeAliasDeclaration}
|
|
235
237
|
}
|
|
@@ -257,11 +259,109 @@ func (noMisusedNew) Check(ctx *Context, node *shimast.Node) {
|
|
|
257
259
|
}
|
|
258
260
|
}
|
|
259
261
|
|
|
260
|
-
//
|
|
262
|
+
// noUnnecessaryParameterPropertyAssignment: parameter properties already
|
|
263
|
+
// assign the constructor argument to `this.<name>` before the body runs.
|
|
264
|
+
// A body-level `this.x = x` immediately repeats that initialization.
|
|
265
|
+
type noUnnecessaryParameterPropertyAssignment struct{}
|
|
266
|
+
|
|
267
|
+
func (noUnnecessaryParameterPropertyAssignment) Name() string {
|
|
268
|
+
return "typescript/no-unnecessary-parameter-property-assignment"
|
|
269
|
+
}
|
|
270
|
+
func (noUnnecessaryParameterPropertyAssignment) Visits() []shimast.Kind {
|
|
271
|
+
return []shimast.Kind{shimast.KindConstructor}
|
|
272
|
+
}
|
|
273
|
+
func (noUnnecessaryParameterPropertyAssignment) Check(ctx *Context, node *shimast.Node) {
|
|
274
|
+
parameterProperties := map[string]bool{}
|
|
275
|
+
for _, param := range node.Parameters() {
|
|
276
|
+
name, ok := parameterPropertyName(param)
|
|
277
|
+
if ok {
|
|
278
|
+
parameterProperties[name] = true
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if len(parameterProperties) == 0 {
|
|
282
|
+
return
|
|
283
|
+
}
|
|
284
|
+
body := node.Body()
|
|
285
|
+
if body == nil || body.Kind != shimast.KindBlock {
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
block := body.AsBlock()
|
|
289
|
+
if block == nil || block.Statements == nil {
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
assigned := map[string]bool{}
|
|
293
|
+
for _, stmt := range block.Statements.Nodes {
|
|
294
|
+
property, value, ok := thisPropertyAssignment(stmt)
|
|
295
|
+
if !ok {
|
|
296
|
+
continue
|
|
297
|
+
}
|
|
298
|
+
if parameterProperties[property] && !assigned[property] && value == property {
|
|
299
|
+
ctx.Report(stmt, "This assignment repeats the constructor parameter property initialization.")
|
|
300
|
+
}
|
|
301
|
+
assigned[property] = true
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
func parameterPropertyName(param *shimast.Node) (string, bool) {
|
|
306
|
+
if param == nil || param.Kind != shimast.KindParameter {
|
|
307
|
+
return "", false
|
|
308
|
+
}
|
|
309
|
+
if !isParameterProperty(param) {
|
|
310
|
+
return "", false
|
|
311
|
+
}
|
|
312
|
+
decl := param.AsParameterDeclaration()
|
|
313
|
+
if decl == nil {
|
|
314
|
+
return "", false
|
|
315
|
+
}
|
|
316
|
+
name := identifierText(decl.Name())
|
|
317
|
+
return name, name != ""
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
func isParameterProperty(param *shimast.Node) bool {
|
|
321
|
+
return hasModifier(param, shimast.KindPublicKeyword) ||
|
|
322
|
+
hasModifier(param, shimast.KindPrivateKeyword) ||
|
|
323
|
+
hasModifier(param, shimast.KindProtectedKeyword) ||
|
|
324
|
+
hasModifier(param, shimast.KindReadonlyKeyword) ||
|
|
325
|
+
hasModifier(param, shimast.KindOverrideKeyword)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
func thisPropertyAssignment(stmt *shimast.Node) (property string, value string, ok bool) {
|
|
329
|
+
if stmt == nil || stmt.Kind != shimast.KindExpressionStatement {
|
|
330
|
+
return "", "", false
|
|
331
|
+
}
|
|
332
|
+
exprStmt := stmt.AsExpressionStatement()
|
|
333
|
+
if exprStmt == nil || exprStmt.Expression == nil {
|
|
334
|
+
return "", "", false
|
|
335
|
+
}
|
|
336
|
+
expr := stripParens(exprStmt.Expression)
|
|
337
|
+
if expr == nil || expr.Kind != shimast.KindBinaryExpression {
|
|
338
|
+
return "", "", false
|
|
339
|
+
}
|
|
340
|
+
binary := expr.AsBinaryExpression()
|
|
341
|
+
if binary == nil || binary.OperatorToken == nil || binary.OperatorToken.Kind != shimast.KindEqualsToken {
|
|
342
|
+
return "", "", false
|
|
343
|
+
}
|
|
344
|
+
left := stripParens(binary.Left)
|
|
345
|
+
if left == nil || left.Kind != shimast.KindPropertyAccessExpression {
|
|
346
|
+
return "", "", false
|
|
347
|
+
}
|
|
348
|
+
access := left.AsPropertyAccessExpression()
|
|
349
|
+
if access == nil || access.Expression == nil || access.Expression.Kind != shimast.KindThisKeyword {
|
|
350
|
+
return "", "", false
|
|
351
|
+
}
|
|
352
|
+
property = identifierText(access.Name())
|
|
353
|
+
value = identifierText(stripParens(binary.Right))
|
|
354
|
+
if property == "" {
|
|
355
|
+
return "", "", false
|
|
356
|
+
}
|
|
357
|
+
return property, value, true
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// preferEnumInitializers: every enum member should have an explicit
|
|
261
361
|
// initializer (avoids order-dependent values).
|
|
262
362
|
type preferEnumInitializers struct{}
|
|
263
363
|
|
|
264
|
-
func (preferEnumInitializers) Name() string { return "prefer-enum-initializers" }
|
|
364
|
+
func (preferEnumInitializers) Name() string { return "typescript/prefer-enum-initializers" }
|
|
265
365
|
func (preferEnumInitializers) Visits() []shimast.Kind {
|
|
266
366
|
return []shimast.Kind{shimast.KindEnumDeclaration}
|
|
267
367
|
}
|
|
@@ -281,7 +381,7 @@ func (preferEnumInitializers) Check(ctx *Context, node *shimast.Node) {
|
|
|
281
381
|
}
|
|
282
382
|
}
|
|
283
383
|
|
|
284
|
-
//
|
|
384
|
+
// preferForOf: `for (let i = 0; i < arr.length; i++) { use(arr[i]) }`
|
|
285
385
|
// can usually be replaced with `for (const x of arr) { use(x); }`.
|
|
286
386
|
type preferForOf struct{}
|
|
287
387
|
|
|
@@ -351,13 +451,13 @@ func isCounterIncrement(node *shimast.Node, counter string) bool {
|
|
|
351
451
|
return false
|
|
352
452
|
}
|
|
353
453
|
|
|
354
|
-
//
|
|
454
|
+
// preferFunctionType: a single-call-signature interface or type alias
|
|
355
455
|
// is more readably written as a function type.
|
|
356
456
|
//
|
|
357
457
|
// interface F { (x: number): string } -> type F = (x: number) => string
|
|
358
458
|
type preferFunctionType struct{}
|
|
359
459
|
|
|
360
|
-
func (preferFunctionType) Name() string { return "prefer-function-type" }
|
|
460
|
+
func (preferFunctionType) Name() string { return "typescript/prefer-function-type" }
|
|
361
461
|
func (preferFunctionType) Visits() []shimast.Kind {
|
|
362
462
|
return []shimast.Kind{shimast.KindInterfaceDeclaration}
|
|
363
463
|
}
|
|
@@ -376,11 +476,30 @@ func (preferFunctionType) Check(ctx *Context, node *shimast.Node) {
|
|
|
376
476
|
ctx.Report(node, "Interface only has a call signature; use 'type' alias and function type instead.")
|
|
377
477
|
}
|
|
378
478
|
|
|
379
|
-
//
|
|
479
|
+
// methodSignatureStyle: prefer function-property signatures over method
|
|
480
|
+
// shorthand in interfaces and type literals. This implements the default
|
|
481
|
+
// @typescript-eslint mode (`property`) as a diagnostic-only rule.
|
|
482
|
+
type methodSignatureStyle struct{}
|
|
483
|
+
|
|
484
|
+
func (methodSignatureStyle) Name() string { return "typescript/method-signature-style" }
|
|
485
|
+
func (methodSignatureStyle) Visits() []shimast.Kind {
|
|
486
|
+
return []shimast.Kind{shimast.KindMethodSignature}
|
|
487
|
+
}
|
|
488
|
+
func (methodSignatureStyle) Check(ctx *Context, node *shimast.Node) {
|
|
489
|
+
if node.Parent == nil {
|
|
490
|
+
return
|
|
491
|
+
}
|
|
492
|
+
switch node.Parent.Kind {
|
|
493
|
+
case shimast.KindInterfaceDeclaration, shimast.KindTypeLiteral:
|
|
494
|
+
ctx.Report(node, "Use a function-property signature instead of a method signature.")
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// preferNamespaceKeyword: `module Foo {}` (TS namespace via `module`
|
|
380
499
|
// keyword) → `namespace Foo {}`.
|
|
381
500
|
type preferNamespaceKeyword struct{}
|
|
382
501
|
|
|
383
|
-
func (preferNamespaceKeyword) Name() string { return "prefer-namespace-keyword" }
|
|
502
|
+
func (preferNamespaceKeyword) Name() string { return "typescript/prefer-namespace-keyword" }
|
|
384
503
|
func (preferNamespaceKeyword) Visits() []shimast.Kind {
|
|
385
504
|
return []shimast.Kind{shimast.KindModuleDeclaration}
|
|
386
505
|
}
|
|
@@ -408,11 +527,11 @@ func (preferNamespaceKeyword) Check(ctx *Context, node *shimast.Node) {
|
|
|
408
527
|
)
|
|
409
528
|
}
|
|
410
529
|
|
|
411
|
-
//
|
|
530
|
+
// tripleSlashReference: `/// <reference path="..." />` directives.
|
|
412
531
|
// Discouraged in modern code in favor of `import`.
|
|
413
532
|
type tripleSlashReference struct{}
|
|
414
533
|
|
|
415
|
-
func (tripleSlashReference) Name() string { return "triple-slash-reference" }
|
|
534
|
+
func (tripleSlashReference) Name() string { return "typescript/triple-slash-reference" }
|
|
416
535
|
func (tripleSlashReference) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindSourceFile} }
|
|
417
536
|
func (tripleSlashReference) Check(ctx *Context, node *shimast.Node) {
|
|
418
537
|
if ctx.File == nil {
|
|
@@ -426,10 +545,10 @@ func (tripleSlashReference) Check(ctx *Context, node *shimast.Node) {
|
|
|
426
545
|
}
|
|
427
546
|
}
|
|
428
547
|
|
|
429
|
-
//
|
|
548
|
+
// noArrayDelete: `delete arr[0]` leaves a sparse hole. Use `splice`.
|
|
430
549
|
type noArrayDelete struct{}
|
|
431
550
|
|
|
432
|
-
func (noArrayDelete) Name() string { return "no-array-delete" }
|
|
551
|
+
func (noArrayDelete) Name() string { return "typescript/no-array-delete" }
|
|
433
552
|
func (noArrayDelete) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindDeleteExpression} }
|
|
434
553
|
func (noArrayDelete) Check(ctx *Context, node *shimast.Node) {
|
|
435
554
|
del := node.AsDeleteExpression()
|
|
@@ -451,7 +570,7 @@ func (noArrayDelete) Check(ctx *Context, node *shimast.Node) {
|
|
|
451
570
|
}
|
|
452
571
|
}
|
|
453
572
|
|
|
454
|
-
//
|
|
573
|
+
// consistentTypeImports: `import { Foo } from "./types"` where Foo is
|
|
455
574
|
// only used as a type → `import type { Foo } from "./types"`. We
|
|
456
575
|
// approximate by flagging every `import type` candidate where the
|
|
457
576
|
// specifier appears in a type-only context inside the file.
|
|
@@ -462,7 +581,7 @@ func (noArrayDelete) Check(ctx *Context, node *shimast.Node) {
|
|
|
462
581
|
// common case.
|
|
463
582
|
type consistentTypeImports struct{}
|
|
464
583
|
|
|
465
|
-
func (consistentTypeImports) Name() string { return "consistent-type-imports" }
|
|
584
|
+
func (consistentTypeImports) Name() string { return "typescript/consistent-type-imports" }
|
|
466
585
|
func (consistentTypeImports) Visits() []shimast.Kind {
|
|
467
586
|
return []shimast.Kind{shimast.KindImportDeclaration}
|
|
468
587
|
}
|
|
@@ -549,12 +668,12 @@ func allUsesAreTypeOnly(root *shimast.Node, names []string) bool {
|
|
|
549
668
|
return allOk
|
|
550
669
|
}
|
|
551
670
|
|
|
552
|
-
//
|
|
671
|
+
// noEmptyObjectType: `interface Foo {}` / `type Foo = {}`. ESLint
|
|
553
672
|
// flags empty types because they're equivalent to `unknown` (everything
|
|
554
673
|
// satisfies `{}`).
|
|
555
674
|
type noEmptyObjectType struct{}
|
|
556
675
|
|
|
557
|
-
func (noEmptyObjectType) Name() string { return "no-empty-object-type" }
|
|
676
|
+
func (noEmptyObjectType) Name() string { return "typescript/no-empty-object-type" }
|
|
558
677
|
func (noEmptyObjectType) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindTypeLiteral} }
|
|
559
678
|
func (noEmptyObjectType) Check(ctx *Context, node *shimast.Node) {
|
|
560
679
|
lit := node.AsTypeLiteralNode()
|
|
@@ -566,10 +685,10 @@ func (noEmptyObjectType) Check(ctx *Context, node *shimast.Node) {
|
|
|
566
685
|
}
|
|
567
686
|
}
|
|
568
687
|
|
|
569
|
-
//
|
|
688
|
+
// arrayType: `Array<T>` vs `T[]`. ESLint default mode prefers `T[]`.
|
|
570
689
|
type arrayType struct{}
|
|
571
690
|
|
|
572
|
-
func (arrayType) Name() string { return "array-type" }
|
|
691
|
+
func (arrayType) Name() string { return "typescript/array-type" }
|
|
573
692
|
func (arrayType) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindTypeReference} }
|
|
574
693
|
func (arrayType) Check(ctx *Context, node *shimast.Node) {
|
|
575
694
|
ref := node.AsTypeReferenceNode()
|
|
@@ -590,11 +709,13 @@ func (arrayType) Check(ctx *Context, node *shimast.Node) {
|
|
|
590
709
|
}
|
|
591
710
|
}
|
|
592
711
|
|
|
593
|
-
//
|
|
712
|
+
// consistentIndexedObjectStyle: `{ [key: string]: T }` vs
|
|
594
713
|
// `Record<string, T>`. ESLint default prefers `Record`.
|
|
595
714
|
type consistentIndexedObjectStyle struct{}
|
|
596
715
|
|
|
597
|
-
func (consistentIndexedObjectStyle) Name() string {
|
|
716
|
+
func (consistentIndexedObjectStyle) Name() string {
|
|
717
|
+
return "typescript/consistent-indexed-object-style"
|
|
718
|
+
}
|
|
598
719
|
func (consistentIndexedObjectStyle) Visits() []shimast.Kind {
|
|
599
720
|
return []shimast.Kind{shimast.KindTypeLiteral}
|
|
600
721
|
}
|
|
@@ -611,17 +732,17 @@ func (consistentIndexedObjectStyle) Check(ctx *Context, node *shimast.Node) {
|
|
|
611
732
|
}
|
|
612
733
|
|
|
613
734
|
// no-explicit-any-rest-parameter — keeping this distinct from
|
|
614
|
-
//
|
|
735
|
+
// noExplicitAny: rest parameters typed `...args: any[]` are common
|
|
615
736
|
// enough that users want to allow them; this rule lets them ban that
|
|
616
737
|
// shape specifically.
|
|
617
738
|
//
|
|
618
739
|
// (Skipped: too narrow / overlaps with no-explicit-any.)
|
|
619
740
|
|
|
620
|
-
//
|
|
741
|
+
// banTslintComment: `// tslint:disable`. tslint is dead; comments
|
|
621
742
|
// referencing it should be cleaned up.
|
|
622
743
|
type banTslintComment struct{}
|
|
623
744
|
|
|
624
|
-
func (banTslintComment) Name() string { return "ban-tslint-comment" }
|
|
745
|
+
func (banTslintComment) Name() string { return "typescript/ban-tslint-comment" }
|
|
625
746
|
func (banTslintComment) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindSourceFile} }
|
|
626
747
|
func (banTslintComment) Check(ctx *Context, node *shimast.Node) {
|
|
627
748
|
if ctx.File == nil {
|
|
@@ -644,12 +765,12 @@ func (banTslintComment) Check(ctx *Context, node *shimast.Node) {
|
|
|
644
765
|
}
|
|
645
766
|
}
|
|
646
767
|
|
|
647
|
-
//
|
|
768
|
+
// adjacentOverloadSignatures: function/method overloads must be
|
|
648
769
|
// declared next to each other. ESLint catches the visual confusion
|
|
649
770
|
// when overloads are interleaved with other members.
|
|
650
771
|
type adjacentOverloadSignatures struct{}
|
|
651
772
|
|
|
652
|
-
func (adjacentOverloadSignatures) Name() string { return "adjacent-overload-signatures" }
|
|
773
|
+
func (adjacentOverloadSignatures) Name() string { return "typescript/adjacent-overload-signatures" }
|
|
653
774
|
func (adjacentOverloadSignatures) Visits() []shimast.Kind {
|
|
654
775
|
return []shimast.Kind{shimast.KindInterfaceDeclaration, shimast.KindTypeLiteral, shimast.KindClassDeclaration, shimast.KindClassExpression, shimast.KindModuleBlock, shimast.KindSourceFile}
|
|
655
776
|
}
|
|
@@ -764,9 +885,11 @@ func init() {
|
|
|
764
885
|
Register(noExtraNonNullAssertion{})
|
|
765
886
|
Register(noNonNullAssertedOptionalChain{})
|
|
766
887
|
Register(noMisusedNew{})
|
|
888
|
+
Register(noUnnecessaryParameterPropertyAssignment{})
|
|
767
889
|
Register(preferEnumInitializers{})
|
|
768
890
|
Register(preferForOf{})
|
|
769
891
|
Register(preferFunctionType{})
|
|
892
|
+
Register(methodSignatureStyle{})
|
|
770
893
|
Register(preferNamespaceKeyword{})
|
|
771
894
|
Register(tripleSlashReference{})
|
|
772
895
|
Register(noArrayDelete{})
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// typescript/no-base-to-string: a string-coercion context that
|
|
2
|
+
// resolves `toString` to the default `Object.prototype.toString`
|
|
3
|
+
// produces the useless `"[object Object]"` placeholder at runtime.
|
|
4
|
+
// typescript-eslint:
|
|
5
|
+
// https://typescript-eslint.io/rules/no-base-to-string/
|
|
6
|
+
//
|
|
7
|
+
// Type-aware. The rule visits the three shapes that implicitly coerce
|
|
8
|
+
// a value through `toString`:
|
|
9
|
+
//
|
|
10
|
+
// - `${x}` — every interpolated expression in a TemplateExpression;
|
|
11
|
+
// - `x + y` — when one operand is statically string-typed the other
|
|
12
|
+
// operand is coerced;
|
|
13
|
+
// - `String(x)` — explicit one-argument coercion.
|
|
14
|
+
//
|
|
15
|
+
// A type is "safely stringifiable" when it is a primitive-like type
|
|
16
|
+
// (`string`-/`number`-/`bigint`-/`boolean`-like, `null`, `undefined`),
|
|
17
|
+
// when the Checker reports it as `any` / `unknown` / `never` (those
|
|
18
|
+
// escape strict reasoning the same way `await-thenable` lets them
|
|
19
|
+
// pass), or when it overrides `toString` away from the global
|
|
20
|
+
// `Object` interface. Unions are safe only when every constituent is
|
|
21
|
+
// safe; intersections are safe when any constituent is safe.
|
|
22
|
+
package linthost
|
|
23
|
+
|
|
24
|
+
import (
|
|
25
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
26
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
type noBaseToString struct{}
|
|
30
|
+
|
|
31
|
+
func (noBaseToString) Name() string { return "typescript/no-base-to-string" }
|
|
32
|
+
func (noBaseToString) NeedsTypeChecker() bool {
|
|
33
|
+
return true
|
|
34
|
+
}
|
|
35
|
+
func (noBaseToString) Visits() []shimast.Kind {
|
|
36
|
+
return []shimast.Kind{
|
|
37
|
+
shimast.KindTemplateExpression,
|
|
38
|
+
shimast.KindBinaryExpression,
|
|
39
|
+
shimast.KindCallExpression,
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
func (noBaseToString) Check(ctx *Context, node *shimast.Node) {
|
|
43
|
+
if ctx.Checker == nil {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
switch node.Kind {
|
|
47
|
+
case shimast.KindTemplateExpression:
|
|
48
|
+
expr := node.AsTemplateExpression()
|
|
49
|
+
if expr == nil || expr.TemplateSpans == nil {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
for _, spanNode := range expr.TemplateSpans.Nodes {
|
|
53
|
+
span := spanNode.AsTemplateSpan()
|
|
54
|
+
if span == nil || span.Expression == nil {
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
reportIfBaseToString(ctx, span.Expression)
|
|
58
|
+
}
|
|
59
|
+
case shimast.KindBinaryExpression:
|
|
60
|
+
bin := node.AsBinaryExpression()
|
|
61
|
+
if bin == nil || bin.OperatorToken == nil || bin.OperatorToken.Kind != shimast.KindPlusToken {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
left := stripParens(bin.Left)
|
|
65
|
+
right := stripParens(bin.Right)
|
|
66
|
+
if left == nil || right == nil {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
leftType := ctx.Checker.GetTypeAtLocation(left)
|
|
70
|
+
rightType := ctx.Checker.GetTypeAtLocation(right)
|
|
71
|
+
if isStringLikeType(leftType) {
|
|
72
|
+
if !isSafeToStringType(ctx.Checker, rightType) {
|
|
73
|
+
ctx.Report(right, baseToStringMessage)
|
|
74
|
+
}
|
|
75
|
+
} else if isStringLikeType(rightType) {
|
|
76
|
+
if !isSafeToStringType(ctx.Checker, leftType) {
|
|
77
|
+
ctx.Report(left, baseToStringMessage)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
case shimast.KindCallExpression:
|
|
81
|
+
call := node.AsCallExpression()
|
|
82
|
+
if call == nil || call.Expression == nil || call.Arguments == nil {
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
if call.Expression.Kind != shimast.KindIdentifier || identifierText(call.Expression) != "String" {
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
if len(call.Arguments.Nodes) != 1 {
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
reportIfBaseToString(ctx, call.Arguments.Nodes[0])
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const baseToStringMessage = "Value implicitly coerces to '[object Object]'. Override `toString` or pass an explicit string representation."
|
|
96
|
+
|
|
97
|
+
func reportIfBaseToString(ctx *Context, expr *shimast.Node) {
|
|
98
|
+
if expr == nil {
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
t := ctx.Checker.GetTypeAtLocation(expr)
|
|
102
|
+
if isSafeToStringType(ctx.Checker, t) {
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
ctx.Report(expr, baseToStringMessage)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// isStringLikeType reports whether t is provably string-typed (a
|
|
109
|
+
// literal, the primitive, a template-literal type, or any combination
|
|
110
|
+
// thereof). Used to decide whether the OTHER operand of a `+`
|
|
111
|
+
// expression is being coerced.
|
|
112
|
+
func isStringLikeType(t *shimchecker.Type) bool {
|
|
113
|
+
if t == nil {
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
flags := t.Flags()
|
|
117
|
+
if flags&shimchecker.TypeFlagsStringLike != 0 {
|
|
118
|
+
return true
|
|
119
|
+
}
|
|
120
|
+
if flags&shimchecker.TypeFlagsUnion != 0 {
|
|
121
|
+
for _, part := range t.Types() {
|
|
122
|
+
if !isStringLikeType(part) {
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return true
|
|
127
|
+
}
|
|
128
|
+
return false
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// isSafeToStringType reports whether `t` can be implicitly coerced to a
|
|
132
|
+
// string without producing the default `Object.prototype.toString`
|
|
133
|
+
// output. The shape mirrors `isAwaitable` in rules_promise.go: union
|
|
134
|
+
// constituents must all be safe; intersection constituents are safe
|
|
135
|
+
// when any one of them is. The `any` / `unknown` / `never` cases pass
|
|
136
|
+
// because flagging them would explode at generic-helper boundaries —
|
|
137
|
+
// the same conservatism `no-floating-promises` adopts.
|
|
138
|
+
func isSafeToStringType(checker *shimchecker.Checker, t *shimchecker.Type) bool {
|
|
139
|
+
if checker == nil || t == nil {
|
|
140
|
+
return true
|
|
141
|
+
}
|
|
142
|
+
flags := t.Flags()
|
|
143
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
144
|
+
return true
|
|
145
|
+
}
|
|
146
|
+
if flags&(shimchecker.TypeFlagsStringLike|
|
|
147
|
+
shimchecker.TypeFlagsNumberLike|
|
|
148
|
+
shimchecker.TypeFlagsBigIntLike|
|
|
149
|
+
shimchecker.TypeFlagsBooleanLike|
|
|
150
|
+
shimchecker.TypeFlagsNull|
|
|
151
|
+
shimchecker.TypeFlagsUndefined) != 0 {
|
|
152
|
+
return true
|
|
153
|
+
}
|
|
154
|
+
if flags&shimchecker.TypeFlagsUnion != 0 {
|
|
155
|
+
for _, part := range t.Types() {
|
|
156
|
+
if !isSafeToStringType(checker, part) {
|
|
157
|
+
return false
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return true
|
|
161
|
+
}
|
|
162
|
+
if flags&shimchecker.TypeFlagsIntersection != 0 {
|
|
163
|
+
for _, part := range t.Types() {
|
|
164
|
+
if isSafeToStringType(checker, part) {
|
|
165
|
+
return true
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return false
|
|
169
|
+
}
|
|
170
|
+
return typeOverridesToString(checker, t)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// typeOverridesToString reports whether `t` carries a `toString` method
|
|
174
|
+
// that is NOT the default declaration on the global `Object` interface.
|
|
175
|
+
// The lib.es5.d.ts `Object` interface declares `toString(): string`; a
|
|
176
|
+
// custom override is what makes coercion meaningful at runtime. If no
|
|
177
|
+
// `toString` is reachable at all the type is treated as base — the
|
|
178
|
+
// only way to coerce it is the prototype-chain default.
|
|
179
|
+
func typeOverridesToString(checker *shimchecker.Checker, t *shimchecker.Type) bool {
|
|
180
|
+
prop := checker.GetPropertyOfType(t, "toString")
|
|
181
|
+
if prop == nil {
|
|
182
|
+
return false
|
|
183
|
+
}
|
|
184
|
+
for _, decl := range prop.Declarations {
|
|
185
|
+
if decl == nil {
|
|
186
|
+
continue
|
|
187
|
+
}
|
|
188
|
+
if !isObjectToStringDeclaration(decl) {
|
|
189
|
+
return true
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return false
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// isObjectToStringDeclaration reports whether `decl` is the
|
|
196
|
+
// `toString(): string` member that lives on the global `Object`
|
|
197
|
+
// interface in lib.es5.d.ts. Walking the parent chain stops at the
|
|
198
|
+
// nearest `interface Object {}` / `interface ObjectConstructor {}`
|
|
199
|
+
// declaration; anything else (Array, Date, Error, user classes, etc.)
|
|
200
|
+
// counts as a real override.
|
|
201
|
+
func isObjectToStringDeclaration(decl *shimast.Node) bool {
|
|
202
|
+
parent := decl.Parent
|
|
203
|
+
if parent == nil {
|
|
204
|
+
return false
|
|
205
|
+
}
|
|
206
|
+
if parent.Kind != shimast.KindInterfaceDeclaration {
|
|
207
|
+
return false
|
|
208
|
+
}
|
|
209
|
+
iface := parent.AsInterfaceDeclaration()
|
|
210
|
+
if iface == nil {
|
|
211
|
+
return false
|
|
212
|
+
}
|
|
213
|
+
return identifierText(iface.Name()) == "Object"
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
func init() {
|
|
217
|
+
Register(noBaseToString{})
|
|
218
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// noConfusingVoidExpression reports `void X` operator uses placed in
|
|
2
|
+
// positions where the surrounding context expects a value. The `void`
|
|
3
|
+
// operator always evaluates to `undefined`, so threading it through a
|
|
4
|
+
// binary expression, ternary, call argument, initializer, or `return`
|
|
5
|
+
// statement is almost always a confusion between the operator and the
|
|
6
|
+
// `void` type.
|
|
7
|
+
//
|
|
8
|
+
// Allowed positions:
|
|
9
|
+
// - statement: `void x;`
|
|
10
|
+
// - arrow function concise body: `() => void x`
|
|
11
|
+
// - operand of an enclosing `void`: `void void x` — only the outer
|
|
12
|
+
// `void` is checked; the inner one is acceptable as the `void`
|
|
13
|
+
// operand of another `void`.
|
|
14
|
+
//
|
|
15
|
+
// This rule is AST-only — it does not consult the Checker for the
|
|
16
|
+
// surrounding function's return type, so `return void X` from a
|
|
17
|
+
// `void`-returning function is still reported. This matches the
|
|
18
|
+
// behavior the upstream rule produces with its
|
|
19
|
+
// `ignoreVoidReturningFunctions: false` default.
|
|
20
|
+
//
|
|
21
|
+
// https://typescript-eslint.io/rules/no-confusing-void-expression/
|
|
22
|
+
package linthost
|
|
23
|
+
|
|
24
|
+
import (
|
|
25
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
type noConfusingVoidExpression struct{}
|
|
29
|
+
|
|
30
|
+
func (noConfusingVoidExpression) Name() string {
|
|
31
|
+
return "typescript/no-confusing-void-expression"
|
|
32
|
+
}
|
|
33
|
+
func (noConfusingVoidExpression) Visits() []shimast.Kind {
|
|
34
|
+
return []shimast.Kind{shimast.KindVoidExpression}
|
|
35
|
+
}
|
|
36
|
+
func (noConfusingVoidExpression) Check(ctx *Context, node *shimast.Node) {
|
|
37
|
+
if isValidVoidExpressionPosition(node) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
ctx.Report(node, "Placing `void` operator in a value position is confusing — use it only as a statement, an arrow concise body, or inside another `void`.")
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// isValidVoidExpressionPosition reports whether the `void X`
|
|
44
|
+
// expression at `node` sits in one of the three permitted positions.
|
|
45
|
+
// Parenthesized expressions are transparent — `(void x)` keeps the
|
|
46
|
+
// same effective context as `void x` for the surrounding code.
|
|
47
|
+
func isValidVoidExpressionPosition(node *shimast.Node) bool {
|
|
48
|
+
parent := node.Parent
|
|
49
|
+
for parent != nil && parent.Kind == shimast.KindParenthesizedExpression {
|
|
50
|
+
node = parent
|
|
51
|
+
parent = parent.Parent
|
|
52
|
+
}
|
|
53
|
+
if parent == nil {
|
|
54
|
+
return false
|
|
55
|
+
}
|
|
56
|
+
switch parent.Kind {
|
|
57
|
+
case shimast.KindExpressionStatement:
|
|
58
|
+
return true
|
|
59
|
+
case shimast.KindVoidExpression:
|
|
60
|
+
// `void void x` — the inner `void` is the operand of another
|
|
61
|
+
// `void`, which discards the result anyway.
|
|
62
|
+
return true
|
|
63
|
+
case shimast.KindArrowFunction:
|
|
64
|
+
arrow := parent.AsArrowFunction()
|
|
65
|
+
return arrow != nil && arrow.Body == node
|
|
66
|
+
}
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
func init() {
|
|
71
|
+
Register(noConfusingVoidExpression{})
|
|
72
|
+
}
|