@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,75 @@
|
|
|
1
|
+
// unicorn/numeric-separators-style: ES2021 numeric separators (`_`)
|
|
2
|
+
// only help readability when the grouping itself is conventional —
|
|
3
|
+
// thousands for decimal (`1_000_000`) and four-digit groups for hex /
|
|
4
|
+
// binary / octal (`0xFFFF_FFFF`). Off-by-one groupings (`1_2345`) read
|
|
5
|
+
// worse than the unseparated form. The rule fires when any literal
|
|
6
|
+
// already uses `_` but its groups don't match the canonical pattern.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: visit `KindNumericLiteral`, read the raw source via
|
|
9
|
+
// `nodeText` so the underscores survive parser normalization, pick the
|
|
10
|
+
// canonical group size from the prefix (`0x`/`0X` → 4, `0b`/`0B` → 4,
|
|
11
|
+
// `0o`/`0O` → 4, anything else → 3), and reject any literal that
|
|
12
|
+
// contains an underscore but whose integer portion fails the
|
|
13
|
+
// canonical-grouping regex.
|
|
14
|
+
//
|
|
15
|
+
// Conservative MVP: only the integer portion is checked. Floats and
|
|
16
|
+
// scientific notation that contain `_` follow the decimal grouping
|
|
17
|
+
// rule applied to the leading integer digits.
|
|
18
|
+
//
|
|
19
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/numeric-separators-style.md
|
|
20
|
+
package linthost
|
|
21
|
+
|
|
22
|
+
import (
|
|
23
|
+
"regexp"
|
|
24
|
+
"strings"
|
|
25
|
+
|
|
26
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
var (
|
|
30
|
+
unicornNumericSeparatorsDecimal = regexp.MustCompile(`^[0-9]{1,3}(_[0-9]{3})*$`)
|
|
31
|
+
unicornNumericSeparatorsRadix4 = regexp.MustCompile(`^[0-9A-Fa-f]{1,4}(_[0-9A-Fa-f]{4})*$`)
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
type unicornNumericSeparatorsStyle struct{}
|
|
35
|
+
|
|
36
|
+
func (unicornNumericSeparatorsStyle) Name() string { return "unicorn/numeric-separators-style" }
|
|
37
|
+
func (unicornNumericSeparatorsStyle) Visits() []shimast.Kind {
|
|
38
|
+
return []shimast.Kind{shimast.KindNumericLiteral, shimast.KindBigIntLiteral}
|
|
39
|
+
}
|
|
40
|
+
func (unicornNumericSeparatorsStyle) Check(ctx *Context, node *shimast.Node) {
|
|
41
|
+
source := strings.TrimSpace(nodeText(ctx.File, node))
|
|
42
|
+
if source == "" || !strings.Contains(source, "_") {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
// Strip a trailing BigInt `n` so the digit-grouping regex doesn't see it.
|
|
46
|
+
source = strings.TrimSuffix(source, "n")
|
|
47
|
+
|
|
48
|
+
// Pick the integer portion and the canonical grouping pattern based
|
|
49
|
+
// on prefix; floats fall through to the decimal rule applied to the
|
|
50
|
+
// leading integer digits before the `.` or `e`/`E`.
|
|
51
|
+
integer := source
|
|
52
|
+
pattern := unicornNumericSeparatorsDecimal
|
|
53
|
+
if len(source) >= 2 && source[0] == '0' {
|
|
54
|
+
switch source[1] {
|
|
55
|
+
case 'x', 'X', 'b', 'B', 'o', 'O':
|
|
56
|
+
integer = source[2:]
|
|
57
|
+
pattern = unicornNumericSeparatorsRadix4
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if pattern == unicornNumericSeparatorsDecimal {
|
|
61
|
+
if dot := strings.IndexAny(integer, ".eE"); dot >= 0 {
|
|
62
|
+
integer = integer[:dot]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if !strings.Contains(integer, "_") {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
if !pattern.MatchString(integer) {
|
|
69
|
+
ctx.Report(node, "Use canonical separator grouping for numeric literals (3 digits for decimal, 4 for hex).")
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
func init() {
|
|
74
|
+
Register(unicornNumericSeparatorsStyle{})
|
|
75
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// unicorn/prefer-add-event-listener: assigning a function to an
|
|
2
|
+
// `on*` DOM property (`el.onclick = …`) installs at most one handler
|
|
3
|
+
// — any prior assignment is silently overwritten. `addEventListener`
|
|
4
|
+
// composes: every listener that registers receives the event, and
|
|
5
|
+
// `removeEventListener` revokes exactly the listener that was added.
|
|
6
|
+
// The property-assignment form is therefore a fragile shape that the
|
|
7
|
+
// rule encourages replacing with the explicit listener API.
|
|
8
|
+
//
|
|
9
|
+
// AST-only: visit each `BinaryExpression`, restrict to `=` assignments
|
|
10
|
+
// whose LHS is a property access, and match property names that start
|
|
11
|
+
// with `on` followed by at least one lowercase letter (so unrelated
|
|
12
|
+
// names like `onnxruntime` or `onClickHandler` don't fire). The
|
|
13
|
+
// assignment node itself is reported so the diagnostic underlines the
|
|
14
|
+
// statement the reader needs to rewrite.
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-add-event-listener.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
|
|
20
|
+
type unicornPreferAddEventListener struct{}
|
|
21
|
+
|
|
22
|
+
func (unicornPreferAddEventListener) Name() string { return "unicorn/prefer-add-event-listener" }
|
|
23
|
+
func (unicornPreferAddEventListener) Visits() []shimast.Kind {
|
|
24
|
+
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
25
|
+
}
|
|
26
|
+
func (unicornPreferAddEventListener) Check(ctx *Context, node *shimast.Node) {
|
|
27
|
+
bin := node.AsBinaryExpression()
|
|
28
|
+
if bin == nil || bin.OperatorToken == nil {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
if bin.OperatorToken.Kind != shimast.KindEqualsToken {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
lhs := stripParens(bin.Left)
|
|
35
|
+
if lhs == nil || lhs.Kind != shimast.KindPropertyAccessExpression {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
access := lhs.AsPropertyAccessExpression()
|
|
39
|
+
if access == nil {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
name := identifierText(access.Name())
|
|
43
|
+
if !isUnicornOnEventName(name) {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
ctx.Report(node, "Prefer `addEventListener` / `removeEventListener` over assigning to `on*` properties.")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// isUnicornOnEventName reports whether `name` is `on<lower>...` of at
|
|
50
|
+
// least 3 characters. The third-character lowercase gate prevents
|
|
51
|
+
// matches on `onClick`, `onnxruntime`, and other names that begin with
|
|
52
|
+
// `on` but are not DOM event handlers.
|
|
53
|
+
func isUnicornOnEventName(name string) bool {
|
|
54
|
+
if len(name) < 3 {
|
|
55
|
+
return false
|
|
56
|
+
}
|
|
57
|
+
if name[0] != 'o' || name[1] != 'n' {
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
c := name[2]
|
|
61
|
+
return c >= 'a' && c <= 'z'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
func init() {
|
|
65
|
+
Register(unicornPreferAddEventListener{})
|
|
66
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// unicorn/prefer-array-find: `arr.filter(predicate)[0]` walks the full
|
|
2
|
+
// array and allocates an intermediate result just to discard everything
|
|
3
|
+
// after the first match. `arr.find(predicate)` returns the same value
|
|
4
|
+
// without the wasted work and reads as the actual intent.
|
|
5
|
+
//
|
|
6
|
+
// AST-only: visit each `ElementAccessExpression`. The receiver must be a
|
|
7
|
+
// `CallExpression` whose callee is a `PropertyAccess(_, filter)` and the
|
|
8
|
+
// index argument must be the numeric literal `0`. Reports on the element
|
|
9
|
+
// access so editors highlight the whole `.filter(...)[0]` chain.
|
|
10
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-find.md
|
|
11
|
+
package linthost
|
|
12
|
+
|
|
13
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
14
|
+
|
|
15
|
+
type unicornPreferArrayFind struct{}
|
|
16
|
+
|
|
17
|
+
func (unicornPreferArrayFind) Name() string { return "unicorn/prefer-array-find" }
|
|
18
|
+
func (unicornPreferArrayFind) Visits() []shimast.Kind {
|
|
19
|
+
return []shimast.Kind{shimast.KindElementAccessExpression}
|
|
20
|
+
}
|
|
21
|
+
func (unicornPreferArrayFind) Check(ctx *Context, node *shimast.Node) {
|
|
22
|
+
access := node.AsElementAccessExpression()
|
|
23
|
+
if access == nil || access.Expression == nil || access.ArgumentExpression == nil {
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
index := stripParens(access.ArgumentExpression)
|
|
27
|
+
if index == nil || index.Kind != shimast.KindNumericLiteral {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
if numericLiteralText(index) != "0" {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
receiver := stripParens(access.Expression)
|
|
34
|
+
if receiver == nil || receiver.Kind != shimast.KindCallExpression {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
call := receiver.AsCallExpression()
|
|
38
|
+
if call == nil || call.Expression == nil ||
|
|
39
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
prop := call.Expression.AsPropertyAccessExpression()
|
|
43
|
+
if prop == nil || identifierText(prop.Name()) != "filter" {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
ctx.Report(node, "Prefer `Array#find()` over `Array#filter(...)[0]`.")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
func init() {
|
|
50
|
+
Register(unicornPreferArrayFind{})
|
|
51
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// unicorn/prefer-array-flat: `[].concat(a, b, c)` is the legacy flatten
|
|
2
|
+
// idiom — it works because `Array#concat` spreads array arguments — but
|
|
3
|
+
// it loses readability the moment a non-array sneaks into the argument
|
|
4
|
+
// list (it then gets pushed in as a single element instead of being
|
|
5
|
+
// flattened). `Array#flat()` has stable, type-aware semantics and is the
|
|
6
|
+
// supported one-line equivalent.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: visit each `CallExpression`, match a property-access callee
|
|
9
|
+
// whose receiver is an empty array-literal expression and whose method
|
|
10
|
+
// identifier is `concat`, and fire when at least one argument is
|
|
11
|
+
// supplied. The empty-array receiver gate is what isolates the
|
|
12
|
+
// flattening idiom from ordinary `.concat()` usage on real arrays.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-flat.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornPreferArrayFlat struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornPreferArrayFlat) Name() string { return "unicorn/prefer-array-flat" }
|
|
21
|
+
func (unicornPreferArrayFlat) Visits() []shimast.Kind {
|
|
22
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
23
|
+
}
|
|
24
|
+
func (unicornPreferArrayFlat) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
+
call := node.AsCallExpression()
|
|
26
|
+
if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
30
|
+
if access == nil {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
if identifierText(access.Name()) != "concat" {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
receiver := stripParens(access.Expression)
|
|
37
|
+
if receiver == nil || receiver.Kind != shimast.KindArrayLiteralExpression {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
arr := receiver.AsArrayLiteralExpression()
|
|
41
|
+
if arr == nil || arr.Elements == nil || len(arr.Elements.Nodes) != 0 {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
ctx.Report(node, "Prefer `Array#flat()` over `[].concat(...arrays)`.")
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
func init() {
|
|
51
|
+
Register(unicornPreferArrayFlat{})
|
|
52
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// unicorn/prefer-array-flat-map: the pair `someArr.map(fn).flat()` walks
|
|
2
|
+
// the source array twice — once to map and once to flatten — when a
|
|
3
|
+
// single `flatMap` call would do both in one pass. The rule flags the
|
|
4
|
+
// chained shape so authors collapse it to the built-in.
|
|
5
|
+
//
|
|
6
|
+
// AST-only: a `CallExpression` whose callee is `.flat` AND whose
|
|
7
|
+
// receiver is itself a `CallExpression` whose callee is `.map` matches.
|
|
8
|
+
// The `.flat(...)` call must be argument-less or explicitly `.flat(1)`
|
|
9
|
+
// — `.map(fn).flat(2)` is NOT equivalent to `.flatMap(fn)` because the
|
|
10
|
+
// latter only flattens one level. The diagnostic anchors on the outer
|
|
11
|
+
// call so editors highlight the whole `.map(...).flat(...)` chain.
|
|
12
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-flat-map.md
|
|
13
|
+
package linthost
|
|
14
|
+
|
|
15
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
|
+
|
|
17
|
+
type unicornPreferArrayFlatMap struct{}
|
|
18
|
+
|
|
19
|
+
func (unicornPreferArrayFlatMap) Name() string { return "unicorn/prefer-array-flat-map" }
|
|
20
|
+
func (unicornPreferArrayFlatMap) Visits() []shimast.Kind {
|
|
21
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
22
|
+
}
|
|
23
|
+
func (unicornPreferArrayFlatMap) Check(ctx *Context, node *shimast.Node) {
|
|
24
|
+
call := node.AsCallExpression()
|
|
25
|
+
if call == nil || call.Expression == nil ||
|
|
26
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
outerAccess := call.Expression.AsPropertyAccessExpression()
|
|
30
|
+
if outerAccess == nil || identifierText(outerAccess.Name()) != "flat" {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
// `.flat(2)` and deeper are NOT equivalent to `.flatMap` — only the
|
|
34
|
+
// default depth (no arg) or explicit depth 1 collapse cleanly.
|
|
35
|
+
if call.Arguments != nil && len(call.Arguments.Nodes) > 0 {
|
|
36
|
+
if len(call.Arguments.Nodes) != 1 {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
arg := stripParens(call.Arguments.Nodes[0])
|
|
40
|
+
if arg == nil || arg.Kind != shimast.KindNumericLiteral ||
|
|
41
|
+
numericLiteralText(arg) != "1" {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
receiver := stripParens(outerAccess.Expression)
|
|
46
|
+
if receiver == nil || receiver.Kind != shimast.KindCallExpression {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
innerCall := receiver.AsCallExpression()
|
|
50
|
+
if innerCall == nil || innerCall.Expression == nil ||
|
|
51
|
+
innerCall.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
innerAccess := innerCall.Expression.AsPropertyAccessExpression()
|
|
55
|
+
if innerAccess == nil || identifierText(innerAccess.Name()) != "map" {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
ctx.Report(node, "Prefer `Array#flatMap` over `Array#map().flat()`.")
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
func init() {
|
|
62
|
+
Register(unicornPreferArrayFlatMap{})
|
|
63
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// unicorn/prefer-array-index-of: `arr.findIndex(x => x === literal)` is
|
|
2
|
+
// the long-hand spelling of `arr.indexOf(literal)`. Both return the
|
|
3
|
+
// index of the first matching element; `indexOf` is a direct comparison
|
|
4
|
+
// against a value and is faster, shorter, and clearer about intent.
|
|
5
|
+
//
|
|
6
|
+
// AST-only: visit each `CallExpression` whose callee is
|
|
7
|
+
// `PropertyAccess(_, findIndex)`. The single argument must be a
|
|
8
|
+
// function (`ArrowFunction` or `FunctionExpression`) with exactly one
|
|
9
|
+
// parameter. The function body — concise body, or a block body whose
|
|
10
|
+
// single statement is a `return` — must be a strict-equality comparison
|
|
11
|
+
// between the parameter identifier and a literal (string, number,
|
|
12
|
+
// boolean, null, bigint). Reports on the call.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-index-of.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornPreferArrayIndexOf struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornPreferArrayIndexOf) Name() string { return "unicorn/prefer-array-index-of" }
|
|
21
|
+
func (unicornPreferArrayIndexOf) Visits() []shimast.Kind {
|
|
22
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
23
|
+
}
|
|
24
|
+
func (unicornPreferArrayIndexOf) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
+
call := node.AsCallExpression()
|
|
26
|
+
if call == nil || call.Expression == nil ||
|
|
27
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
31
|
+
if access == nil || identifierText(access.Name()) != "findIndex" {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
fn := stripParens(call.Arguments.Nodes[0])
|
|
38
|
+
if fn == nil {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
var body *shimast.Node
|
|
42
|
+
switch fn.Kind {
|
|
43
|
+
case shimast.KindArrowFunction:
|
|
44
|
+
arrow := fn.AsArrowFunction()
|
|
45
|
+
if arrow == nil {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
body = arrow.Body
|
|
49
|
+
case shimast.KindFunctionExpression:
|
|
50
|
+
expr := fn.AsFunctionExpression()
|
|
51
|
+
if expr == nil {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
body = expr.Body
|
|
55
|
+
default:
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
params := fn.Parameters()
|
|
59
|
+
if len(params) != 1 {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
paramName := parameterIdentifierName(params[0])
|
|
63
|
+
if paramName == "" {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
expr := unicornPreferArrayIndexOfBodyExpression(body)
|
|
67
|
+
if expr == nil {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
bin := expr.AsBinaryExpression()
|
|
71
|
+
if bin == nil || bin.OperatorToken == nil ||
|
|
72
|
+
bin.OperatorToken.Kind != shimast.KindEqualsEqualsEqualsToken {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
left := stripParens(bin.Left)
|
|
76
|
+
right := stripParens(bin.Right)
|
|
77
|
+
if left == nil || right == nil {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
if unicornPreferArrayIndexOfMatchesParam(left, paramName) &&
|
|
81
|
+
unicornPreferArrayIndexOfIsLiteral(right) {
|
|
82
|
+
ctx.Report(node, "Prefer `Array#indexOf()` over `Array#findIndex(x => x === literal)`.")
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
if unicornPreferArrayIndexOfMatchesParam(right, paramName) &&
|
|
86
|
+
unicornPreferArrayIndexOfIsLiteral(left) {
|
|
87
|
+
ctx.Report(node, "Prefer `Array#indexOf()` over `Array#findIndex(x => x === literal)`.")
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// unicornPreferArrayIndexOfBodyExpression normalizes the function body to
|
|
92
|
+
// the comparison expression: a concise arrow body returns its expression,
|
|
93
|
+
// a block body with a single `return expr;` returns the expression.
|
|
94
|
+
func unicornPreferArrayIndexOfBodyExpression(body *shimast.Node) *shimast.Node {
|
|
95
|
+
if body == nil {
|
|
96
|
+
return nil
|
|
97
|
+
}
|
|
98
|
+
if body.Kind != shimast.KindBlock {
|
|
99
|
+
expr := stripParens(body)
|
|
100
|
+
if expr == nil || expr.Kind != shimast.KindBinaryExpression {
|
|
101
|
+
return nil
|
|
102
|
+
}
|
|
103
|
+
return expr
|
|
104
|
+
}
|
|
105
|
+
block := body.AsBlock()
|
|
106
|
+
if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
|
|
107
|
+
return nil
|
|
108
|
+
}
|
|
109
|
+
stmt := block.Statements.Nodes[0]
|
|
110
|
+
if stmt == nil || stmt.Kind != shimast.KindReturnStatement {
|
|
111
|
+
return nil
|
|
112
|
+
}
|
|
113
|
+
ret := stmt.AsReturnStatement()
|
|
114
|
+
if ret == nil || ret.Expression == nil {
|
|
115
|
+
return nil
|
|
116
|
+
}
|
|
117
|
+
expr := stripParens(ret.Expression)
|
|
118
|
+
if expr == nil || expr.Kind != shimast.KindBinaryExpression {
|
|
119
|
+
return nil
|
|
120
|
+
}
|
|
121
|
+
return expr
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
func unicornPreferArrayIndexOfMatchesParam(node *shimast.Node, name string) bool {
|
|
125
|
+
return identifierText(node) == name
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
func unicornPreferArrayIndexOfIsLiteral(node *shimast.Node) bool {
|
|
129
|
+
if node == nil {
|
|
130
|
+
return false
|
|
131
|
+
}
|
|
132
|
+
switch node.Kind {
|
|
133
|
+
case shimast.KindStringLiteral,
|
|
134
|
+
shimast.KindNumericLiteral,
|
|
135
|
+
shimast.KindBigIntLiteral,
|
|
136
|
+
shimast.KindNoSubstitutionTemplateLiteral,
|
|
137
|
+
shimast.KindNullKeyword,
|
|
138
|
+
shimast.KindTrueKeyword,
|
|
139
|
+
shimast.KindFalseKeyword:
|
|
140
|
+
return true
|
|
141
|
+
}
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
func init() {
|
|
146
|
+
Register(unicornPreferArrayIndexOf{})
|
|
147
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// unicorn/prefer-array-some: `arr.filter(predicate).length > 0` walks the
|
|
2
|
+
// whole array and allocates an intermediate filtered array just to ask
|
|
3
|
+
// the boolean question "does any element match?". `arr.some(predicate)`
|
|
4
|
+
// short-circuits at the first hit and reads as the intent.
|
|
5
|
+
//
|
|
6
|
+
// AST-only: visit each `BinaryExpression`. The operator must be one of
|
|
7
|
+
// `>`, `>=`, `!==`, `!=`. The left operand must be
|
|
8
|
+
// `PropertyAccess(CallExpression(_, filter), length)`. The right operand
|
|
9
|
+
// must be the numeric literal `0`. Reports on the binary expression.
|
|
10
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-some.md
|
|
11
|
+
package linthost
|
|
12
|
+
|
|
13
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
14
|
+
|
|
15
|
+
type unicornPreferArraySome struct{}
|
|
16
|
+
|
|
17
|
+
func (unicornPreferArraySome) Name() string { return "unicorn/prefer-array-some" }
|
|
18
|
+
func (unicornPreferArraySome) Visits() []shimast.Kind {
|
|
19
|
+
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
20
|
+
}
|
|
21
|
+
func (unicornPreferArraySome) Check(ctx *Context, node *shimast.Node) {
|
|
22
|
+
bin := node.AsBinaryExpression()
|
|
23
|
+
if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
switch bin.OperatorToken.Kind {
|
|
27
|
+
case shimast.KindGreaterThanToken,
|
|
28
|
+
shimast.KindGreaterThanEqualsToken,
|
|
29
|
+
shimast.KindExclamationEqualsEqualsToken,
|
|
30
|
+
shimast.KindExclamationEqualsToken:
|
|
31
|
+
default:
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
right := stripParens(bin.Right)
|
|
35
|
+
if right == nil || right.Kind != shimast.KindNumericLiteral {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
if numericLiteralText(right) != "0" {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
left := stripParens(bin.Left)
|
|
42
|
+
if left == nil || left.Kind != shimast.KindPropertyAccessExpression {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
outer := left.AsPropertyAccessExpression()
|
|
46
|
+
if outer == nil || identifierText(outer.Name()) != "length" {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
receiver := stripParens(outer.Expression)
|
|
50
|
+
if receiver == nil || receiver.Kind != shimast.KindCallExpression {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
call := receiver.AsCallExpression()
|
|
54
|
+
if call == nil || call.Expression == nil ||
|
|
55
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
59
|
+
if access == nil || identifierText(access.Name()) != "filter" {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
ctx.Report(node, "Prefer `Array#some()` over `.filter(...).length > 0`.")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
func init() {
|
|
66
|
+
Register(unicornPreferArraySome{})
|
|
67
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// unicorn/prefer-at: `arr[arr.length - 1]` is the legacy spelling of
|
|
2
|
+
// "last element". ES2022 introduced `Array#at(-N)` (and `String#at(-N)`)
|
|
3
|
+
// which lets you reach for the same value from the tail without
|
|
4
|
+
// repeating the receiver and the subtraction. The rule pushes authors
|
|
5
|
+
// toward the built-in.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit each `ElementAccessExpression`. The index expression
|
|
8
|
+
// must be a `BinaryExpression` whose operator is `-`, whose left side is
|
|
9
|
+
// `PropertyAccess(_, length)`, and whose right side is a positive
|
|
10
|
+
// numeric literal. The receiver of the `.length` access does not need
|
|
11
|
+
// to match the element-access receiver textually; mismatches are
|
|
12
|
+
// uncommon enough that the AST-only check stays useful in practice.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-at.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornPreferAt struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornPreferAt) Name() string { return "unicorn/prefer-at" }
|
|
21
|
+
func (unicornPreferAt) Visits() []shimast.Kind {
|
|
22
|
+
return []shimast.Kind{shimast.KindElementAccessExpression}
|
|
23
|
+
}
|
|
24
|
+
func (unicornPreferAt) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
+
access := node.AsElementAccessExpression()
|
|
26
|
+
if access == nil || access.ArgumentExpression == nil {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
index := stripParens(access.ArgumentExpression)
|
|
30
|
+
if index == nil || index.Kind != shimast.KindBinaryExpression {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
bin := index.AsBinaryExpression()
|
|
34
|
+
if bin == nil || bin.OperatorToken == nil ||
|
|
35
|
+
bin.OperatorToken.Kind != shimast.KindMinusToken {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
left := stripParens(bin.Left)
|
|
39
|
+
if left == nil || left.Kind != shimast.KindPropertyAccessExpression {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
prop := left.AsPropertyAccessExpression()
|
|
43
|
+
if prop == nil || identifierText(prop.Name()) != "length" {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
right := stripParens(bin.Right)
|
|
47
|
+
if right == nil || right.Kind != shimast.KindNumericLiteral {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
text := numericLiteralText(right)
|
|
51
|
+
if !unicornPreferAtIsPositiveInteger(text) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
ctx.Report(node, "Prefer `Array#at(-N)` / `String#at(-N)` over `arr[arr.length - N]`.")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// unicornPreferAtIsPositiveInteger reports whether `text` is the literal
|
|
58
|
+
// form of a positive integer (>= 1). Leading zeros are accepted because
|
|
59
|
+
// the JS scanner already normalized them; the only rejections are the
|
|
60
|
+
// empty string, plain `0`, and anything containing a non-digit (decimals,
|
|
61
|
+
// `e`-notation, hex, bigint suffix).
|
|
62
|
+
func unicornPreferAtIsPositiveInteger(text string) bool {
|
|
63
|
+
if text == "" || text == "0" {
|
|
64
|
+
return false
|
|
65
|
+
}
|
|
66
|
+
for i := 0; i < len(text); i++ {
|
|
67
|
+
c := text[i]
|
|
68
|
+
if c < '0' || c > '9' {
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return true
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
func init() {
|
|
76
|
+
Register(unicornPreferAt{})
|
|
77
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// unicorn/prefer-bigint-literals: `BigInt(1)` and `BigInt("1")` both
|
|
2
|
+
// allocate a BigInt at runtime through a constructor call, while the
|
|
3
|
+
// equivalent `1n` literal is one parse-time token with no call
|
|
4
|
+
// overhead. The rule asks authors to use the literal form when the
|
|
5
|
+
// argument is a known integer.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit `KindCallExpression`, fire when the callee is the
|
|
8
|
+
// bare `BigInt` identifier called with exactly one argument that is
|
|
9
|
+
// either a numeric literal of any shape, or a string literal whose
|
|
10
|
+
// content is a decimal-digit-only integer (optionally signed). The
|
|
11
|
+
// conservative string check avoids flagging `BigInt("0x10")` and
|
|
12
|
+
// other shapes that need a runtime parse.
|
|
13
|
+
//
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-bigint-literals.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornPreferBigintLiterals struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornPreferBigintLiterals) Name() string { return "unicorn/prefer-bigint-literals" }
|
|
22
|
+
func (unicornPreferBigintLiterals) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
24
|
+
}
|
|
25
|
+
func (unicornPreferBigintLiterals) Check(ctx *Context, node *shimast.Node) {
|
|
26
|
+
call := node.AsCallExpression()
|
|
27
|
+
if call == nil || identifierText(call.Expression) != "BigInt" {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
arg := stripParens(call.Arguments.Nodes[0])
|
|
34
|
+
if arg == nil {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
switch arg.Kind {
|
|
38
|
+
case shimast.KindNumericLiteral:
|
|
39
|
+
// `BigInt(1)` — always rewritable to `1n`.
|
|
40
|
+
case shimast.KindStringLiteral:
|
|
41
|
+
text := stringLiteralText(arg)
|
|
42
|
+
if !unicornPreferBigintLiteralsIsDecimalInteger(text) {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
default:
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
ctx.Report(node, "Prefer BigInt literal `1n` over `BigInt(1)`.")
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// unicornPreferBigintLiteralsIsDecimalInteger reports whether `text` is
|
|
52
|
+
// a non-empty decimal-integer literal — digits only, optional leading
|
|
53
|
+
// minus. The check is intentionally conservative; anything more exotic
|
|
54
|
+
// (hex prefix, exponent, decimal point) leaves the BigInt call alone.
|
|
55
|
+
func unicornPreferBigintLiteralsIsDecimalInteger(text string) bool {
|
|
56
|
+
if text == "" {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
i := 0
|
|
60
|
+
if text[0] == '-' || text[0] == '+' {
|
|
61
|
+
i++
|
|
62
|
+
}
|
|
63
|
+
if i == len(text) {
|
|
64
|
+
return false
|
|
65
|
+
}
|
|
66
|
+
for ; i < len(text); i++ {
|
|
67
|
+
ch := text[i]
|
|
68
|
+
if ch < '0' || ch > '9' {
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return true
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
func init() {
|
|
76
|
+
Register(unicornPreferBigintLiterals{})
|
|
77
|
+
}
|