@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,103 @@
|
|
|
1
|
+
// unicorn/prefer-switch: a long `if (x === "a") {…} else if (x === "b")
|
|
2
|
+
// {…} else if (x === "c") {…}` ladder repeats both the discriminant and
|
|
3
|
+
// the equality check on every branch; `switch (x)` collapses the cascade
|
|
4
|
+
// into one labelled lookup and signals intent ("dispatch on the value of
|
|
5
|
+
// x") more directly. The cliff for the rewrite is at three branches —
|
|
6
|
+
// fewer than that, the if-cascade and the switch are about equally
|
|
7
|
+
// readable.
|
|
8
|
+
//
|
|
9
|
+
// AST-only minimum-viable port: visit `IfStatement` and only fire on
|
|
10
|
+
// the outermost `if` of a chain. Walk the else-chain and require it to
|
|
11
|
+
// contain THREE OR MORE `else if` clauses whose condition is a
|
|
12
|
+
// `BinaryExpression` with `===` (or `==`) AND whose left operand is
|
|
13
|
+
// textually identical to the outermost if's left operand AND whose
|
|
14
|
+
// right operand is a string-or-numeric literal. The outermost `if`
|
|
15
|
+
// itself must satisfy the same shape. The shape constraint is
|
|
16
|
+
// intentionally conservative — switch can only dispatch on equality
|
|
17
|
+
// against literal labels.
|
|
18
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-switch.md
|
|
19
|
+
package linthost
|
|
20
|
+
|
|
21
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
22
|
+
|
|
23
|
+
type unicornPreferSwitch struct{}
|
|
24
|
+
|
|
25
|
+
func (unicornPreferSwitch) Name() string { return "unicorn/prefer-switch" }
|
|
26
|
+
func (unicornPreferSwitch) Visits() []shimast.Kind {
|
|
27
|
+
return []shimast.Kind{shimast.KindIfStatement}
|
|
28
|
+
}
|
|
29
|
+
func (unicornPreferSwitch) Check(ctx *Context, node *shimast.Node) {
|
|
30
|
+
// Only fire on the outermost if — if our parent is also an
|
|
31
|
+
// `IfStatement` whose else-branch is `node`, this is a middle of the
|
|
32
|
+
// chain and a higher-up visit will report it once.
|
|
33
|
+
if node.Parent != nil && node.Parent.Kind == shimast.KindIfStatement {
|
|
34
|
+
parent := node.Parent.AsIfStatement()
|
|
35
|
+
if parent != nil && parent.ElseStatement == node {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
stmt := node.AsIfStatement()
|
|
40
|
+
if stmt == nil || stmt.Expression == nil {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
discriminant, ok := unicornPreferSwitchDiscriminant(ctx, stmt.Expression)
|
|
44
|
+
if !ok {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
// Count the outermost `if` plus every well-shaped `else if` that
|
|
48
|
+
// compares against the same discriminant.
|
|
49
|
+
branches := 1
|
|
50
|
+
cur := stmt.ElseStatement
|
|
51
|
+
for cur != nil && cur.Kind == shimast.KindIfStatement {
|
|
52
|
+
inner := cur.AsIfStatement()
|
|
53
|
+
if inner == nil || inner.Expression == nil {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
next, ok := unicornPreferSwitchDiscriminant(ctx, inner.Expression)
|
|
57
|
+
if !ok || next != discriminant {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
branches++
|
|
61
|
+
cur = inner.ElseStatement
|
|
62
|
+
}
|
|
63
|
+
if branches >= 3 {
|
|
64
|
+
ctx.Report(node, "Three or more `else if` clauses comparing the same value should be a `switch`.")
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// unicornPreferSwitchDiscriminant returns the textual form of the left
|
|
69
|
+
// operand of an `===`/`==` comparison against a string-or-numeric
|
|
70
|
+
// literal. Returns ok=false for any other shape.
|
|
71
|
+
func unicornPreferSwitchDiscriminant(ctx *Context, expr *shimast.Node) (string, bool) {
|
|
72
|
+
expr = stripParens(expr)
|
|
73
|
+
if expr == nil || expr.Kind != shimast.KindBinaryExpression {
|
|
74
|
+
return "", false
|
|
75
|
+
}
|
|
76
|
+
bin := expr.AsBinaryExpression()
|
|
77
|
+
if bin == nil || bin.OperatorToken == nil {
|
|
78
|
+
return "", false
|
|
79
|
+
}
|
|
80
|
+
switch bin.OperatorToken.Kind {
|
|
81
|
+
case shimast.KindEqualsEqualsEqualsToken, shimast.KindEqualsEqualsToken:
|
|
82
|
+
default:
|
|
83
|
+
return "", false
|
|
84
|
+
}
|
|
85
|
+
right := stripParens(bin.Right)
|
|
86
|
+
if right == nil {
|
|
87
|
+
return "", false
|
|
88
|
+
}
|
|
89
|
+
switch right.Kind {
|
|
90
|
+
case shimast.KindStringLiteral, shimast.KindNumericLiteral:
|
|
91
|
+
default:
|
|
92
|
+
return "", false
|
|
93
|
+
}
|
|
94
|
+
left := stripParens(bin.Left)
|
|
95
|
+
if left == nil {
|
|
96
|
+
return "", false
|
|
97
|
+
}
|
|
98
|
+
return nodeText(ctx.File, left), true
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
func init() {
|
|
102
|
+
Register(unicornPreferSwitch{})
|
|
103
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// unicorn/prefer-ternary: when an `if`/`else` pair only differs in the
|
|
2
|
+
// value being returned (or, in the upstream rule, assigned), the
|
|
3
|
+
// equivalent `return cond ? a : b` is one line, removes the
|
|
4
|
+
// duplicated `return` keyword, and matches the shape of every other
|
|
5
|
+
// "pick one of two values" expression in the language.
|
|
6
|
+
//
|
|
7
|
+
// AST-only minimum-viable port: visit `IfStatement` and match only the
|
|
8
|
+
// return-statement case. Both then- and else-branches must each be a
|
|
9
|
+
// single `ReturnStatement` with a non-nil expression — either a bare
|
|
10
|
+
// `return …;` directly under the if, or a block wrapping exactly one
|
|
11
|
+
// such return. The assignment shape (`if (cond) x = a; else x = b;`)
|
|
12
|
+
// from the upstream rule is out of scope for this MVP; both call sites
|
|
13
|
+
// look syntactically symmetric, so adding the assignment branch later
|
|
14
|
+
// is a straightforward extension.
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-ternary.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
|
|
20
|
+
type unicornPreferTernary struct{}
|
|
21
|
+
|
|
22
|
+
func (unicornPreferTernary) Name() string { return "unicorn/prefer-ternary" }
|
|
23
|
+
func (unicornPreferTernary) Visits() []shimast.Kind {
|
|
24
|
+
return []shimast.Kind{shimast.KindIfStatement}
|
|
25
|
+
}
|
|
26
|
+
func (unicornPreferTernary) Check(ctx *Context, node *shimast.Node) {
|
|
27
|
+
stmt := node.AsIfStatement()
|
|
28
|
+
if stmt == nil || stmt.ThenStatement == nil || stmt.ElseStatement == nil {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
// Reject `else if` — an `if`/`else if`/`else` ladder is a different
|
|
32
|
+
// rewrite target (it becomes nested ternaries, which the upstream
|
|
33
|
+
// rule explicitly does not require).
|
|
34
|
+
if stmt.ElseStatement.Kind == shimast.KindIfStatement {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
if !unicornPreferTernaryIsSingleReturn(stmt.ThenStatement) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
if !unicornPreferTernaryIsSingleReturn(stmt.ElseStatement) {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
ctx.Report(node, "Use a ternary instead of `if`/`else` whose branches differ only in the returned value.")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// unicornPreferTernaryIsSingleReturn reports whether `branch` is a
|
|
47
|
+
// single `return expr;` — either directly or wrapped in a one-statement
|
|
48
|
+
// block. Returns false for empty returns (`return;`); ternary cannot
|
|
49
|
+
// fold those because both arms have to produce a value.
|
|
50
|
+
func unicornPreferTernaryIsSingleReturn(branch *shimast.Node) bool {
|
|
51
|
+
if branch == nil {
|
|
52
|
+
return false
|
|
53
|
+
}
|
|
54
|
+
stmt := branch
|
|
55
|
+
if branch.Kind == shimast.KindBlock {
|
|
56
|
+
block := branch.AsBlock()
|
|
57
|
+
if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
stmt = block.Statements.Nodes[0]
|
|
61
|
+
}
|
|
62
|
+
if stmt == nil || stmt.Kind != shimast.KindReturnStatement {
|
|
63
|
+
return false
|
|
64
|
+
}
|
|
65
|
+
ret := stmt.AsReturnStatement()
|
|
66
|
+
return ret != nil && ret.Expression != nil
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
func init() {
|
|
70
|
+
Register(unicornPreferTernary{})
|
|
71
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// unicorn/prefer-top-level-await: ES modules support top-level `await`,
|
|
2
|
+
// which produces a flat synchronous-looking sequence and surfaces
|
|
3
|
+
// rejections through the host. A `.then(cb)` continuation at the module
|
|
4
|
+
// scope re-introduces the callback shape the host could have flattened
|
|
5
|
+
// for free, and silently swallows rejections unless the author wires up
|
|
6
|
+
// an explicit `.catch`.
|
|
7
|
+
//
|
|
8
|
+
// AST-only minimum-viable port: visit `CallExpression` and fire when the
|
|
9
|
+
// callee is `PropertyAccess(_, then)` AND the call sits at the top
|
|
10
|
+
// level of the source file — i.e., walking parents from the call's
|
|
11
|
+
// enclosing statement, the first statement-ancestor's parent is a
|
|
12
|
+
// `SourceFile`. Calls inside a function, class, namespace body, or
|
|
13
|
+
// inside any nested block are excluded; top-level `await` only applies
|
|
14
|
+
// to the module body.
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-top-level-await.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
|
|
20
|
+
type unicornPreferTopLevelAwait struct{}
|
|
21
|
+
|
|
22
|
+
func (unicornPreferTopLevelAwait) Name() string { return "unicorn/prefer-top-level-await" }
|
|
23
|
+
func (unicornPreferTopLevelAwait) Visits() []shimast.Kind {
|
|
24
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
25
|
+
}
|
|
26
|
+
func (unicornPreferTopLevelAwait) Check(ctx *Context, node *shimast.Node) {
|
|
27
|
+
call := node.AsCallExpression()
|
|
28
|
+
if call == nil || call.Expression == nil ||
|
|
29
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
33
|
+
if access == nil || identifierText(access.Name()) != "then" {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
if !unicornPreferTopLevelAwaitIsTopLevel(node) {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
ctx.Report(node, "Prefer top-level `await` over `.then` chains in ES modules.")
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// unicornPreferTopLevelAwaitIsTopLevel walks ancestors and reports
|
|
43
|
+
// whether `node` is positioned in the top-level statement list of a
|
|
44
|
+
// `SourceFile`. The walk crosses parenthesized expressions and
|
|
45
|
+
// expression statements; it stops the moment it sees any function-like,
|
|
46
|
+
// class-body, block, or module-block boundary, which would push the call
|
|
47
|
+
// out of module scope.
|
|
48
|
+
func unicornPreferTopLevelAwaitIsTopLevel(node *shimast.Node) bool {
|
|
49
|
+
for cur := node.Parent; cur != nil; cur = cur.Parent {
|
|
50
|
+
switch cur.Kind {
|
|
51
|
+
case shimast.KindSourceFile:
|
|
52
|
+
return true
|
|
53
|
+
case shimast.KindFunctionDeclaration,
|
|
54
|
+
shimast.KindFunctionExpression,
|
|
55
|
+
shimast.KindArrowFunction,
|
|
56
|
+
shimast.KindMethodDeclaration,
|
|
57
|
+
shimast.KindGetAccessor,
|
|
58
|
+
shimast.KindSetAccessor,
|
|
59
|
+
shimast.KindConstructor,
|
|
60
|
+
shimast.KindClassDeclaration,
|
|
61
|
+
shimast.KindClassExpression,
|
|
62
|
+
shimast.KindModuleBlock,
|
|
63
|
+
shimast.KindBlock:
|
|
64
|
+
return false
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
func init() {
|
|
71
|
+
Register(unicornPreferTopLevelAwait{})
|
|
72
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// unicorn/prefer-type-error: a guard whose condition is a runtime
|
|
2
|
+
// `typeof` / `instanceof` check throws to signal "wrong type", not
|
|
3
|
+
// "wrong value". JavaScript's `TypeError` exists precisely for that
|
|
4
|
+
// distinction, and tooling (e.g. assertion libraries) treats the two
|
|
5
|
+
// error classes differently. The rule asks throwers to switch from
|
|
6
|
+
// `Error` to `TypeError` whenever the surrounding check is a type
|
|
7
|
+
// check.
|
|
8
|
+
//
|
|
9
|
+
// AST-only: visit every `IfStatement`, require its condition (after
|
|
10
|
+
// `stripParens`, optionally unwrapping a `!` prefix) to be a runtime
|
|
11
|
+
// type check — either a `KindTypeOfExpression`, a `KindBinaryExpression`
|
|
12
|
+
// with the `instanceof` operator, or a `==` / `===` / `!=` / `!==`
|
|
13
|
+
// comparison where one side is a `typeof` expression. The then-branch
|
|
14
|
+
// must be a single `KindThrowStatement` of `new Error(...)`. Fire on
|
|
15
|
+
// the throw.
|
|
16
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-type-error.md
|
|
17
|
+
package linthost
|
|
18
|
+
|
|
19
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
20
|
+
|
|
21
|
+
type unicornPreferTypeError struct{}
|
|
22
|
+
|
|
23
|
+
func (unicornPreferTypeError) Name() string { return "unicorn/prefer-type-error" }
|
|
24
|
+
func (unicornPreferTypeError) Visits() []shimast.Kind {
|
|
25
|
+
return []shimast.Kind{shimast.KindIfStatement}
|
|
26
|
+
}
|
|
27
|
+
func (unicornPreferTypeError) Check(ctx *Context, node *shimast.Node) {
|
|
28
|
+
stmt := node.AsIfStatement()
|
|
29
|
+
if stmt == nil || stmt.Expression == nil || stmt.ThenStatement == nil {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
cond := stripParens(stmt.Expression)
|
|
33
|
+
if cond == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
// Accept either the bare type check (`typeof x !== "number"`) or a
|
|
37
|
+
// negation of one (`!(x instanceof Foo)`).
|
|
38
|
+
if cond.Kind == shimast.KindPrefixUnaryExpression {
|
|
39
|
+
prefix := cond.AsPrefixUnaryExpression()
|
|
40
|
+
if prefix == nil || prefix.Operator != shimast.KindExclamationToken {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
cond = stripParens(prefix.Operand)
|
|
44
|
+
}
|
|
45
|
+
if !unicornPreferTypeErrorIsTypeCheck(cond) {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
throw := unicornPreferTypeErrorSingleThrow(stmt.ThenStatement)
|
|
49
|
+
if throw == nil {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
throwStmt := throw.AsThrowStatement()
|
|
53
|
+
if throwStmt == nil {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
expr := stripParens(throwStmt.Expression)
|
|
57
|
+
if expr == nil || expr.Kind != shimast.KindNewExpression {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
ne := expr.AsNewExpression()
|
|
61
|
+
if ne == nil || identifierText(ne.Expression) != "Error" {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
ctx.Report(throw, "Throw `TypeError` (not `Error`) when the surrounding check is a runtime type check.")
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// unicornPreferTypeErrorIsTypeCheck reports whether `node` is a
|
|
68
|
+
// `typeof x` expression or `x instanceof Y` BinaryExpression. Both
|
|
69
|
+
// shapes encode a runtime type test, which is what the rule keys off.
|
|
70
|
+
func unicornPreferTypeErrorIsTypeCheck(node *shimast.Node) bool {
|
|
71
|
+
if node == nil {
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
switch node.Kind {
|
|
75
|
+
case shimast.KindTypeOfExpression:
|
|
76
|
+
return true
|
|
77
|
+
case shimast.KindBinaryExpression:
|
|
78
|
+
bin := node.AsBinaryExpression()
|
|
79
|
+
if bin == nil || bin.OperatorToken == nil {
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
if bin.OperatorToken.Kind == shimast.KindInstanceOfKeyword {
|
|
83
|
+
return true
|
|
84
|
+
}
|
|
85
|
+
// `typeof x !== "string"` style — covers the common idiom.
|
|
86
|
+
switch bin.OperatorToken.Kind {
|
|
87
|
+
case shimast.KindEqualsEqualsEqualsToken,
|
|
88
|
+
shimast.KindEqualsEqualsToken,
|
|
89
|
+
shimast.KindExclamationEqualsEqualsToken,
|
|
90
|
+
shimast.KindExclamationEqualsToken:
|
|
91
|
+
left := stripParens(bin.Left)
|
|
92
|
+
right := stripParens(bin.Right)
|
|
93
|
+
return (left != nil && left.Kind == shimast.KindTypeOfExpression) ||
|
|
94
|
+
(right != nil && right.Kind == shimast.KindTypeOfExpression)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// unicornPreferTypeErrorSingleThrow returns the single `throw`
|
|
101
|
+
// statement inside `branch` — accepting either a bare ThrowStatement
|
|
102
|
+
// or a Block wrapping exactly one ThrowStatement. Returns nil for any
|
|
103
|
+
// other shape.
|
|
104
|
+
func unicornPreferTypeErrorSingleThrow(branch *shimast.Node) *shimast.Node {
|
|
105
|
+
if branch == nil {
|
|
106
|
+
return nil
|
|
107
|
+
}
|
|
108
|
+
if branch.Kind == shimast.KindThrowStatement {
|
|
109
|
+
return branch
|
|
110
|
+
}
|
|
111
|
+
if branch.Kind != shimast.KindBlock {
|
|
112
|
+
return nil
|
|
113
|
+
}
|
|
114
|
+
block := branch.AsBlock()
|
|
115
|
+
if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
|
|
116
|
+
return nil
|
|
117
|
+
}
|
|
118
|
+
stmt := block.Statements.Nodes[0]
|
|
119
|
+
if stmt == nil || stmt.Kind != shimast.KindThrowStatement {
|
|
120
|
+
return nil
|
|
121
|
+
}
|
|
122
|
+
return stmt
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
func init() {
|
|
126
|
+
Register(unicornPreferTypeError{})
|
|
127
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// unicorn/prevent-abbreviations: abbreviated identifier names (`err`,
|
|
2
|
+
// `cb`, `ctx`, `idx`) are a project-wide readability tax — every
|
|
3
|
+
// reader has to expand the shorthand mentally on the spot. The
|
|
4
|
+
// upstream rule maintains a large allowlist + replacements map; this
|
|
5
|
+
// MVP carries the most universal abbreviations only and fires on any
|
|
6
|
+
// identifier whose lower-cased text matches one of them, in both
|
|
7
|
+
// reference and declaration positions, so a `param` parameter and a
|
|
8
|
+
// `void param` read are both reported.
|
|
9
|
+
//
|
|
10
|
+
// AST-only: visit every `Identifier`, lowercase the lexeme, look it up
|
|
11
|
+
// in `unicornPreventAbbreviationsDictionary`. No scope analysis is
|
|
12
|
+
// performed because the rule's diagnostic is about the *name*, not the
|
|
13
|
+
// binding — every occurrence of `idx` is equally noisy.
|
|
14
|
+
//
|
|
15
|
+
// Hot-path budget: `KindIdentifier` is the most frequent AST kind in
|
|
16
|
+
// any TypeScript program, so this Check is invoked tens-of-thousands
|
|
17
|
+
// of times per file. A length pre-filter eliminates ~90 % of inputs
|
|
18
|
+
// without touching memory (the longest dictionary entry is six
|
|
19
|
+
// characters); an additional `isAllLowerASCII` check skips
|
|
20
|
+
// `strings.ToLower`'s allocation for the common case of already-
|
|
21
|
+
// lower-cased identifiers.
|
|
22
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prevent-abbreviations.md
|
|
23
|
+
package linthost
|
|
24
|
+
|
|
25
|
+
import (
|
|
26
|
+
"strings"
|
|
27
|
+
|
|
28
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
// unicornPreventAbbreviationsDictionary is the MVP allowlist of
|
|
32
|
+
// abbreviations that fire the rule. Lower-cased keys; the rule
|
|
33
|
+
// case-folds the identifier before lookup. Intentionally conservative
|
|
34
|
+
// — picks the abbreviations universally agreed across upstream
|
|
35
|
+
// presets so the rule doesn't flap on neutral words.
|
|
36
|
+
var unicornPreventAbbreviationsDictionary = map[string]struct{}{
|
|
37
|
+
"arr": {},
|
|
38
|
+
"args": {},
|
|
39
|
+
"attr": {},
|
|
40
|
+
"btn": {},
|
|
41
|
+
"cb": {},
|
|
42
|
+
"cmd": {},
|
|
43
|
+
"ctx": {},
|
|
44
|
+
"db": {},
|
|
45
|
+
"dest": {},
|
|
46
|
+
"dir": {},
|
|
47
|
+
"doc": {},
|
|
48
|
+
"el": {},
|
|
49
|
+
"elem": {},
|
|
50
|
+
"env": {},
|
|
51
|
+
"err": {},
|
|
52
|
+
"evt": {},
|
|
53
|
+
"fn": {},
|
|
54
|
+
"func": {},
|
|
55
|
+
"idx": {},
|
|
56
|
+
"len": {},
|
|
57
|
+
"lib": {},
|
|
58
|
+
"mgr": {},
|
|
59
|
+
"mod": {},
|
|
60
|
+
"msg": {},
|
|
61
|
+
"num": {},
|
|
62
|
+
"obj": {},
|
|
63
|
+
"opts": {},
|
|
64
|
+
"param": {},
|
|
65
|
+
"params": {},
|
|
66
|
+
"pkg": {},
|
|
67
|
+
"prev": {},
|
|
68
|
+
"prop": {},
|
|
69
|
+
"props": {},
|
|
70
|
+
"ref": {},
|
|
71
|
+
"res": {},
|
|
72
|
+
"ret": {},
|
|
73
|
+
"src": {},
|
|
74
|
+
"str": {},
|
|
75
|
+
"tmp": {},
|
|
76
|
+
"val": {},
|
|
77
|
+
"var": {},
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// unicornPreventAbbreviationsMaxLen is the longest dictionary key
|
|
81
|
+
// length. Any identifier longer than this cannot match — the Check
|
|
82
|
+
// returns immediately without touching the dictionary.
|
|
83
|
+
const unicornPreventAbbreviationsMaxLen = 6
|
|
84
|
+
|
|
85
|
+
type unicornPreventAbbreviations struct{}
|
|
86
|
+
|
|
87
|
+
func (unicornPreventAbbreviations) Name() string { return "unicorn/prevent-abbreviations" }
|
|
88
|
+
func (unicornPreventAbbreviations) Visits() []shimast.Kind {
|
|
89
|
+
return []shimast.Kind{shimast.KindIdentifier}
|
|
90
|
+
}
|
|
91
|
+
func (unicornPreventAbbreviations) Check(ctx *Context, node *shimast.Node) {
|
|
92
|
+
name := identifierText(node)
|
|
93
|
+
if name == "" || len(name) > unicornPreventAbbreviationsMaxLen {
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
// Fast path: dictionary keys are pre-lowercased, so an
|
|
97
|
+
// already-lower-case identifier avoids `strings.ToLower`'s
|
|
98
|
+
// allocation entirely. The Check is invoked once per identifier
|
|
99
|
+
// in the file, so the saved allocations multiply.
|
|
100
|
+
lookup := name
|
|
101
|
+
if !isAllLowerASCII(name) {
|
|
102
|
+
lookup = strings.ToLower(name)
|
|
103
|
+
}
|
|
104
|
+
if _, ok := unicornPreventAbbreviationsDictionary[lookup]; !ok {
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
ctx.Report(node, "Prefer the long form over abbreviated identifiers (e.g. `error` over `err`).")
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// isAllLowerASCII reports whether `s` is a non-empty ASCII string
|
|
111
|
+
// whose every byte is a lower-case letter. Used by hot-path Checks
|
|
112
|
+
// that look up an already-normalized dictionary — the result is
|
|
113
|
+
// equivalent to `s == strings.ToLower(s)` for all-ASCII inputs but
|
|
114
|
+
// avoids the lowercase allocation.
|
|
115
|
+
func isAllLowerASCII(s string) bool {
|
|
116
|
+
for i := 0; i < len(s); i++ {
|
|
117
|
+
c := s[i]
|
|
118
|
+
if c >= 'A' && c <= 'Z' {
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return true
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
func init() {
|
|
126
|
+
Register(unicornPreventAbbreviations{})
|
|
127
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// unicorn/relative-url-style: `new URL("./foo", base)` and
|
|
2
|
+
// `new URL("foo", base)` resolve identically, so the leading `./` is
|
|
3
|
+
// noise. The rule normalizes on the "never leading `./`" style and
|
|
4
|
+
// fires whenever a `new URL(…)` literal first argument starts with
|
|
5
|
+
// `./`.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit `KindNewExpression`, accept when the callee is the
|
|
8
|
+
// bare `URL` identifier, and inspect the first argument — when it's a
|
|
9
|
+
// string-shaped literal whose text starts with `./`, report the
|
|
10
|
+
// argument node. Absolute URLs (`http://…`), schemeless protocol
|
|
11
|
+
// references, and paths starting with `/` or `../` are untouched; only
|
|
12
|
+
// the explicit `./` prefix is the redundant case the rule targets.
|
|
13
|
+
//
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/relative-url-style.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import (
|
|
18
|
+
"strings"
|
|
19
|
+
|
|
20
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
type unicornRelativeURLStyle struct{}
|
|
24
|
+
|
|
25
|
+
func (unicornRelativeURLStyle) Name() string { return "unicorn/relative-url-style" }
|
|
26
|
+
func (unicornRelativeURLStyle) Visits() []shimast.Kind {
|
|
27
|
+
return []shimast.Kind{shimast.KindNewExpression}
|
|
28
|
+
}
|
|
29
|
+
func (unicornRelativeURLStyle) Check(ctx *Context, node *shimast.Node) {
|
|
30
|
+
expr := node.AsNewExpression()
|
|
31
|
+
if expr == nil || identifierText(expr.Expression) != "URL" {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if expr.Arguments == nil || len(expr.Arguments.Nodes) == 0 {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
arg := expr.Arguments.Nodes[0]
|
|
38
|
+
text := stringLiteralText(arg)
|
|
39
|
+
if text == "" {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
if strings.HasPrefix(text, "./") {
|
|
43
|
+
ctx.Report(arg, "Drop the leading `./` from relative URLs passed to `new URL`.")
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func init() {
|
|
48
|
+
Register(unicornRelativeURLStyle{})
|
|
49
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// unicorn/require-array-join-separator: `Array#join()` defaults its
|
|
2
|
+
// separator to a comma when called with no arguments. Authors rarely
|
|
3
|
+
// mean to rely on that — the implicit separator is locale-flavored in
|
|
4
|
+
// related APIs (`Intl.ListFormat`) and the comma default is one of the
|
|
5
|
+
// quieter sources of "why is this comma here?" diffs. The rule pushes
|
|
6
|
+
// every call site to spell out the separator so the intent is in the
|
|
7
|
+
// source.
|
|
8
|
+
//
|
|
9
|
+
// AST-only: visit each `CallExpression`, accept only the property-access
|
|
10
|
+
// `x.join` shape, and report when the call carries zero arguments. Any
|
|
11
|
+
// explicit argument — empty string included — passes.
|
|
12
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/require-array-join-separator.md
|
|
13
|
+
package linthost
|
|
14
|
+
|
|
15
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
|
+
|
|
17
|
+
type unicornRequireArrayJoinSeparator struct{}
|
|
18
|
+
|
|
19
|
+
func (unicornRequireArrayJoinSeparator) Name() string {
|
|
20
|
+
return "unicorn/require-array-join-separator"
|
|
21
|
+
}
|
|
22
|
+
func (unicornRequireArrayJoinSeparator) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
24
|
+
}
|
|
25
|
+
func (unicornRequireArrayJoinSeparator) Check(ctx *Context, node *shimast.Node) {
|
|
26
|
+
call := node.AsCallExpression()
|
|
27
|
+
if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
31
|
+
if access == nil {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if identifierText(access.Name()) != "join" {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
if call.Arguments != nil && len(call.Arguments.Nodes) > 0 {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
ctx.Report(node, "Pass an explicit separator argument to `Array#join()`.")
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
func init() {
|
|
44
|
+
Register(unicornRequireArrayJoinSeparator{})
|
|
45
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// unicorn/require-module-attributes: import / export `with { … }`
|
|
2
|
+
// clauses carry semantic information (`type: "json"`, `type: "css"`).
|
|
3
|
+
// Writing `with {}` with no entries serves no purpose and is almost
|
|
4
|
+
// always a mistake. The rule fires when an import or export carries an
|
|
5
|
+
// attributes clause with zero attribute entries.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit `KindImportDeclaration` and `KindExportDeclaration`,
|
|
8
|
+
// follow the `.Attributes` field (an `ImportAttributesNode`), descend
|
|
9
|
+
// into its inner `ImportAttributes.Attributes` list, and report when
|
|
10
|
+
// the list is present but empty. The clause-present-but-empty shape is
|
|
11
|
+
// rare in practice but legal syntax, so a precise zero-entry check is
|
|
12
|
+
// the right anchor.
|
|
13
|
+
//
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/require-module-attributes.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornRequireModuleAttributes struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornRequireModuleAttributes) Name() string {
|
|
22
|
+
return "unicorn/require-module-attributes"
|
|
23
|
+
}
|
|
24
|
+
func (unicornRequireModuleAttributes) Visits() []shimast.Kind {
|
|
25
|
+
return []shimast.Kind{shimast.KindImportDeclaration, shimast.KindExportDeclaration}
|
|
26
|
+
}
|
|
27
|
+
func (unicornRequireModuleAttributes) Check(ctx *Context, node *shimast.Node) {
|
|
28
|
+
var attrs *shimast.Node
|
|
29
|
+
switch node.Kind {
|
|
30
|
+
case shimast.KindImportDeclaration:
|
|
31
|
+
if decl := node.AsImportDeclaration(); decl != nil {
|
|
32
|
+
attrs = decl.Attributes
|
|
33
|
+
}
|
|
34
|
+
case shimast.KindExportDeclaration:
|
|
35
|
+
if decl := node.AsExportDeclaration(); decl != nil {
|
|
36
|
+
attrs = decl.Attributes
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if attrs == nil {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
imp := attrs.AsImportAttributes()
|
|
43
|
+
if imp == nil {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
if imp.Attributes != nil && len(imp.Attributes.Nodes) > 0 {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
ctx.Report(node, "Import/export `with {}` should have at least one attribute.")
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
func init() {
|
|
53
|
+
Register(unicornRequireModuleAttributes{})
|
|
54
|
+
}
|