@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,37 @@
|
|
|
1
|
+
// unicorn/prefer-dom-node-text-content: `HTMLElement#innerText` triggers
|
|
2
|
+
// layout, ignores hidden subtrees, and varies across engines — its
|
|
3
|
+
// `Node#textContent` counterpart returns the raw concatenated text of
|
|
4
|
+
// every descendant text node and is the supported modern shape.
|
|
5
|
+
//
|
|
6
|
+
// AST-only and identifier-text-driven: visit every
|
|
7
|
+
// `PropertyAccessExpression`, match the property name `innerText`, and
|
|
8
|
+
// fire on the property-access node. The receiver expression is not
|
|
9
|
+
// type-checked; the legacy property name is the signal the rule
|
|
10
|
+
// discourages.
|
|
11
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-dom-node-text-content.md
|
|
12
|
+
package linthost
|
|
13
|
+
|
|
14
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
15
|
+
|
|
16
|
+
type unicornPreferDomNodeTextContent struct{}
|
|
17
|
+
|
|
18
|
+
func (unicornPreferDomNodeTextContent) Name() string {
|
|
19
|
+
return "unicorn/prefer-dom-node-text-content"
|
|
20
|
+
}
|
|
21
|
+
func (unicornPreferDomNodeTextContent) Visits() []shimast.Kind {
|
|
22
|
+
return []shimast.Kind{shimast.KindPropertyAccessExpression}
|
|
23
|
+
}
|
|
24
|
+
func (unicornPreferDomNodeTextContent) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
+
access := node.AsPropertyAccessExpression()
|
|
26
|
+
if access == nil {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
if identifierText(access.Name()) != "innerText" {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
ctx.Report(node, "Prefer `Node#textContent` over `HTMLElement#innerText`.")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func init() {
|
|
36
|
+
Register(unicornPreferDomNodeTextContent{})
|
|
37
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// unicorn/prefer-event-target: Node's `EventEmitter` is the legacy
|
|
2
|
+
// event API. The browser and modern Node (`>=15`) both ship the
|
|
3
|
+
// standard `EventTarget` interface, which works in both runtimes
|
|
4
|
+
// without a polyfill. Code that needs to run in both should prefer
|
|
5
|
+
// `EventTarget` so it stays portable.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit `NewExpression`. Match when the callee is a bare
|
|
8
|
+
// identifier whose name is `EventEmitter`. The receiver is not
|
|
9
|
+
// type-checked — the rule's signal is the literal `new EventEmitter()`
|
|
10
|
+
// shape; a `new events.EventEmitter()` qualified form would not match,
|
|
11
|
+
// matching upstream's own AST-only behavior.
|
|
12
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-event-target.md
|
|
13
|
+
package linthost
|
|
14
|
+
|
|
15
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
|
+
|
|
17
|
+
type unicornPreferEventTarget struct{}
|
|
18
|
+
|
|
19
|
+
func (unicornPreferEventTarget) Name() string { return "unicorn/prefer-event-target" }
|
|
20
|
+
func (unicornPreferEventTarget) Visits() []shimast.Kind {
|
|
21
|
+
return []shimast.Kind{shimast.KindNewExpression}
|
|
22
|
+
}
|
|
23
|
+
func (unicornPreferEventTarget) Check(ctx *Context, node *shimast.Node) {
|
|
24
|
+
ne := node.AsNewExpression()
|
|
25
|
+
if ne == nil || ne.Expression == nil {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
if identifierText(ne.Expression) != "EventEmitter" {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
ctx.Report(node, "Prefer `EventTarget` over `EventEmitter` when sharing code between Node and the browser.")
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
func init() {
|
|
35
|
+
Register(unicornPreferEventTarget{})
|
|
36
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// unicorn/prefer-export-from: when the only purpose of a local import is
|
|
2
|
+
// to re-export it under the same name, the canonical shape is the
|
|
3
|
+
// `export { X } from "Y"` re-export, which skips the intermediate local
|
|
4
|
+
// binding entirely. The split `import { X } from "Y"; export { X };`
|
|
5
|
+
// form is longer, allocates a binding that never gets used, and reads
|
|
6
|
+
// as if the author meant to consume `X` locally before deciding not to.
|
|
7
|
+
//
|
|
8
|
+
// AST-only minimum-viable port: visit `SourceFile` and walk top-level
|
|
9
|
+
// statements once. Build a map from each unrenamed named-binding of an
|
|
10
|
+
// `import { X } from "Y"` declaration to its module specifier text, then
|
|
11
|
+
// fire on every later `export { X };` statement (no rename, no
|
|
12
|
+
// `from`-clause) whose identifier appears in that map. Default and
|
|
13
|
+
// namespace imports, renamed bindings, and re-exports with their own
|
|
14
|
+
// `from`-clause are out of scope; the MVP only catches the textbook
|
|
15
|
+
// "import then immediately re-export" pair.
|
|
16
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-export-from.md
|
|
17
|
+
package linthost
|
|
18
|
+
|
|
19
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
20
|
+
|
|
21
|
+
type unicornPreferExportFrom struct{}
|
|
22
|
+
|
|
23
|
+
func (unicornPreferExportFrom) Name() string { return "unicorn/prefer-export-from" }
|
|
24
|
+
func (unicornPreferExportFrom) Visits() []shimast.Kind {
|
|
25
|
+
return []shimast.Kind{shimast.KindSourceFile}
|
|
26
|
+
}
|
|
27
|
+
func (unicornPreferExportFrom) Check(ctx *Context, node *shimast.Node) {
|
|
28
|
+
statements := node.Statements()
|
|
29
|
+
if len(statements) == 0 {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
// Map of locally-imported simple binding name → true. Built on a
|
|
33
|
+
// first pass so a re-export earlier in the file does not accidentally
|
|
34
|
+
// match an import declared later; the upstream rule is anchored on
|
|
35
|
+
// "imported above, re-exported below" ordering.
|
|
36
|
+
imported := map[string]bool{}
|
|
37
|
+
for _, stmt := range statements {
|
|
38
|
+
if stmt == nil || stmt.Kind != shimast.KindImportDeclaration {
|
|
39
|
+
continue
|
|
40
|
+
}
|
|
41
|
+
decl := stmt.AsImportDeclaration()
|
|
42
|
+
if decl == nil || decl.ImportClause == nil {
|
|
43
|
+
continue
|
|
44
|
+
}
|
|
45
|
+
clause := decl.ImportClause.AsImportClause()
|
|
46
|
+
if clause == nil || clause.NamedBindings == nil ||
|
|
47
|
+
clause.NamedBindings.Kind != shimast.KindNamedImports {
|
|
48
|
+
continue
|
|
49
|
+
}
|
|
50
|
+
// A default-bound or namespace-mixed import is out of scope: the
|
|
51
|
+
// MVP only rewrites pure `import { X } from "Y"` pairs.
|
|
52
|
+
if clause.Name() != nil {
|
|
53
|
+
continue
|
|
54
|
+
}
|
|
55
|
+
named := clause.NamedBindings.AsNamedImports()
|
|
56
|
+
if named == nil || named.Elements == nil {
|
|
57
|
+
continue
|
|
58
|
+
}
|
|
59
|
+
for _, spec := range named.Elements.Nodes {
|
|
60
|
+
s := spec.AsImportSpecifier()
|
|
61
|
+
if s == nil {
|
|
62
|
+
continue
|
|
63
|
+
}
|
|
64
|
+
// PropertyName is set only when the specifier is renamed
|
|
65
|
+
// (`import { a as b }`); skip those — `export { b }` would
|
|
66
|
+
// require `export { b as b } from "Y"` which is itself a
|
|
67
|
+
// useless rename.
|
|
68
|
+
if s.PropertyName != nil {
|
|
69
|
+
continue
|
|
70
|
+
}
|
|
71
|
+
name := identifierText(s.Name())
|
|
72
|
+
if name == "" {
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
imported[name] = true
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if len(imported) == 0 {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
for _, stmt := range statements {
|
|
82
|
+
if stmt == nil || stmt.Kind != shimast.KindExportDeclaration {
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
decl := stmt.AsExportDeclaration()
|
|
86
|
+
if decl == nil || decl.ExportClause == nil {
|
|
87
|
+
continue
|
|
88
|
+
}
|
|
89
|
+
// Skip `export { X } from "Y"` — already in the target shape.
|
|
90
|
+
if decl.ModuleSpecifier != nil {
|
|
91
|
+
continue
|
|
92
|
+
}
|
|
93
|
+
if decl.ExportClause.Kind != shimast.KindNamedExports {
|
|
94
|
+
continue
|
|
95
|
+
}
|
|
96
|
+
named := decl.ExportClause.AsNamedExports()
|
|
97
|
+
if named == nil || named.Elements == nil || len(named.Elements.Nodes) == 0 {
|
|
98
|
+
continue
|
|
99
|
+
}
|
|
100
|
+
matched := false
|
|
101
|
+
for _, el := range named.Elements.Nodes {
|
|
102
|
+
spec := el.AsExportSpecifier()
|
|
103
|
+
if spec == nil {
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
// PropertyName != nil means `export { a as b }` — a rename
|
|
107
|
+
// the from-clause rewrite cannot preserve without also
|
|
108
|
+
// touching the import side. Skip.
|
|
109
|
+
if spec.PropertyName != nil {
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
name := identifierText(spec.Name())
|
|
113
|
+
if name == "" {
|
|
114
|
+
continue
|
|
115
|
+
}
|
|
116
|
+
if imported[name] {
|
|
117
|
+
matched = true
|
|
118
|
+
break
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if matched {
|
|
122
|
+
ctx.Report(stmt, "Use `export { X } from \"Y\"` instead of importing then re-exporting.")
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
func init() {
|
|
128
|
+
Register(unicornPreferExportFrom{})
|
|
129
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// unicorn/prefer-global-this: `window`, `self`, and `global` are
|
|
2
|
+
// environment-specific global aliases. Using them locks code to a
|
|
3
|
+
// single runtime (browser, worker, Node) and forces feature-detection
|
|
4
|
+
// boilerplate when the same code needs to run elsewhere. `globalThis`
|
|
5
|
+
// is the standardized cross-runtime alias and the canonical form for
|
|
6
|
+
// the same reference.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: visit every `Identifier`. The rule fires only when the
|
|
9
|
+
// identifier sits in a value-expression position; declaration names,
|
|
10
|
+
// property-access right sides, parameter names, property-assignment
|
|
11
|
+
// keys, and type references are filtered out by parent-kind gating so
|
|
12
|
+
// the diagnostic is anchored on actual reads of the global.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-global-this.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornPreferGlobalThis struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornPreferGlobalThis) Name() string { return "unicorn/prefer-global-this" }
|
|
21
|
+
func (unicornPreferGlobalThis) Visits() []shimast.Kind {
|
|
22
|
+
return []shimast.Kind{shimast.KindIdentifier}
|
|
23
|
+
}
|
|
24
|
+
func (unicornPreferGlobalThis) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
+
name := identifierText(node)
|
|
26
|
+
switch name {
|
|
27
|
+
case "window", "self", "global":
|
|
28
|
+
default:
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
if !isUnicornValuePositionIdentifier(node) {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
ctx.Report(node, "Prefer `globalThis` over `window` / `self` / `global`.")
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// isUnicornValuePositionIdentifier reports whether `node` (a bare
|
|
38
|
+
// Identifier) appears in a value-expression position rather than as a
|
|
39
|
+
// binding name, property key, member-access right side, or type
|
|
40
|
+
// reference. Declaration names and property keys are read positions
|
|
41
|
+
// for the *name* itself, so they must not contribute to rules that
|
|
42
|
+
// flag *uses* of a global.
|
|
43
|
+
func isUnicornValuePositionIdentifier(node *shimast.Node) bool {
|
|
44
|
+
if node == nil || node.Kind != shimast.KindIdentifier || node.Parent == nil {
|
|
45
|
+
return false
|
|
46
|
+
}
|
|
47
|
+
parent := node.Parent
|
|
48
|
+
switch parent.Kind {
|
|
49
|
+
case shimast.KindVariableDeclaration:
|
|
50
|
+
decl := parent.AsVariableDeclaration()
|
|
51
|
+
if decl != nil && decl.Name() == node {
|
|
52
|
+
return false
|
|
53
|
+
}
|
|
54
|
+
case shimast.KindBindingElement:
|
|
55
|
+
elem := parent.AsBindingElement()
|
|
56
|
+
if elem != nil && elem.Name() == node {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
case shimast.KindParameter:
|
|
60
|
+
param := parent.AsParameterDeclaration()
|
|
61
|
+
if param != nil && param.Name() == node {
|
|
62
|
+
return false
|
|
63
|
+
}
|
|
64
|
+
case shimast.KindFunctionDeclaration:
|
|
65
|
+
fn := parent.AsFunctionDeclaration()
|
|
66
|
+
if fn != nil && fn.Name() == node {
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
case shimast.KindFunctionExpression:
|
|
70
|
+
fn := parent.AsFunctionExpression()
|
|
71
|
+
if fn != nil && fn.Name() == node {
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
case shimast.KindClassDeclaration:
|
|
75
|
+
cls := parent.AsClassDeclaration()
|
|
76
|
+
if cls != nil && cls.Name() == node {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
case shimast.KindClassExpression:
|
|
80
|
+
cls := parent.AsClassExpression()
|
|
81
|
+
if cls != nil && cls.Name() == node {
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
84
|
+
case shimast.KindPropertyAccessExpression:
|
|
85
|
+
access := parent.AsPropertyAccessExpression()
|
|
86
|
+
if access != nil && access.Name() == node {
|
|
87
|
+
return false
|
|
88
|
+
}
|
|
89
|
+
case shimast.KindPropertyAssignment:
|
|
90
|
+
prop := parent.AsPropertyAssignment()
|
|
91
|
+
if prop != nil && prop.Name() == node {
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
case shimast.KindShorthandPropertyAssignment:
|
|
95
|
+
// `{window}` shorthand — the identifier is both name and read,
|
|
96
|
+
// but the read here is the value position, so allow.
|
|
97
|
+
case shimast.KindMethodDeclaration,
|
|
98
|
+
shimast.KindGetAccessor,
|
|
99
|
+
shimast.KindSetAccessor,
|
|
100
|
+
shimast.KindPropertyDeclaration:
|
|
101
|
+
// These have a Name() slot that is not a value expression.
|
|
102
|
+
return false
|
|
103
|
+
case shimast.KindTypeReference,
|
|
104
|
+
shimast.KindQualifiedName,
|
|
105
|
+
shimast.KindImportSpecifier,
|
|
106
|
+
shimast.KindExportSpecifier,
|
|
107
|
+
shimast.KindNamespaceImport,
|
|
108
|
+
shimast.KindImportClause,
|
|
109
|
+
shimast.KindNamespaceExport,
|
|
110
|
+
shimast.KindLabeledStatement,
|
|
111
|
+
shimast.KindBreakStatement,
|
|
112
|
+
shimast.KindContinueStatement,
|
|
113
|
+
shimast.KindJsxAttribute,
|
|
114
|
+
shimast.KindEnumDeclaration,
|
|
115
|
+
shimast.KindEnumMember,
|
|
116
|
+
shimast.KindModuleDeclaration,
|
|
117
|
+
shimast.KindTypeParameter,
|
|
118
|
+
shimast.KindInterfaceDeclaration,
|
|
119
|
+
shimast.KindTypeAliasDeclaration:
|
|
120
|
+
return false
|
|
121
|
+
}
|
|
122
|
+
return true
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
func init() {
|
|
126
|
+
Register(unicornPreferGlobalThis{})
|
|
127
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// unicorn/prefer-import-meta-properties: the legacy
|
|
2
|
+
// `fileURLToPath(import.meta.url)` pattern was the only way to obtain
|
|
3
|
+
// the on-disk path of the current ES module before Node added the
|
|
4
|
+
// dedicated `import.meta.dirname` and `import.meta.filename`
|
|
5
|
+
// properties. Once those exist, the workaround is pure noise — it
|
|
6
|
+
// imports `url` for one call and adds a layer the reader has to
|
|
7
|
+
// translate back to "the current file's directory / filename".
|
|
8
|
+
//
|
|
9
|
+
// AST-only: visit `CallExpression`, match a bare `fileURLToPath`
|
|
10
|
+
// callee, and check that the sole argument is the property access
|
|
11
|
+
// `import.meta.url`. The canonical legacy shape is the only case
|
|
12
|
+
// covered — other call sites of `fileURLToPath` are out of scope.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-import-meta-properties.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornPreferImportMetaProperties struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornPreferImportMetaProperties) Name() string {
|
|
21
|
+
return "unicorn/prefer-import-meta-properties"
|
|
22
|
+
}
|
|
23
|
+
func (unicornPreferImportMetaProperties) Visits() []shimast.Kind {
|
|
24
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
25
|
+
}
|
|
26
|
+
func (unicornPreferImportMetaProperties) Check(ctx *Context, node *shimast.Node) {
|
|
27
|
+
call := node.AsCallExpression()
|
|
28
|
+
if call == nil || call.Expression == nil {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
if identifierText(call.Expression) != "fileURLToPath" {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
arg := stripParens(call.Arguments.Nodes[0])
|
|
38
|
+
if arg == nil || arg.Kind != shimast.KindPropertyAccessExpression {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
access := arg.AsPropertyAccessExpression()
|
|
42
|
+
if access == nil {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
if identifierText(access.Name()) != "url" {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
receiver := stripParens(access.Expression)
|
|
49
|
+
if receiver == nil {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
// `import.meta` parses as either a MetaProperty token or a
|
|
53
|
+
// PropertyAccess(import, meta) chain depending on the path; both
|
|
54
|
+
// resolve textually to the same source span.
|
|
55
|
+
if receiver.Kind == shimast.KindMetaProperty {
|
|
56
|
+
ctx.Report(node, "Prefer `import.meta.dirname` / `import.meta.filename` over `fileURLToPath(import.meta.url)`.")
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
if isMatchingPropertyAccess(receiver, "import", "meta") {
|
|
60
|
+
ctx.Report(node, "Prefer `import.meta.dirname` / `import.meta.filename` over `fileURLToPath(import.meta.url)`.")
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
func init() {
|
|
65
|
+
Register(unicornPreferImportMetaProperties{})
|
|
66
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// unicorn/prefer-includes: `arr.indexOf(x) !== -1` (and its `=== -1`,
|
|
2
|
+
// `> -1`, `>= 0`, `< 0` siblings) is the legacy idiom for membership
|
|
3
|
+
// testing. The intent is obvious only after the reader translates the
|
|
4
|
+
// magic number; `arr.includes(x)` says the same thing without the
|
|
5
|
+
// translation step. The rule applies to both arrays and strings — both
|
|
6
|
+
// expose `indexOf` and both expose `includes`.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: a `BinaryExpression` whose operator is one of the
|
|
9
|
+
// recognized comparisons and whose operands are `<call>.indexOf(...)`
|
|
10
|
+
// vs. one of `-1` / `0` (allowing the literal-or-unary-minus shape for
|
|
11
|
+
// `-1`) matches. For symmetric operators (`===`, `!==`, `==`, `!=`)
|
|
12
|
+
// either operand may carry the call. For asymmetric operators (`<`,
|
|
13
|
+
// `>=`, `>`) only the canonical orientation `indexOf(x) <op> <literal>`
|
|
14
|
+
// is recognized; the swapped form (`0 < indexOf(x)`) has different
|
|
15
|
+
// semantics (e.g. "found at index >= 1") and is intentionally NOT
|
|
16
|
+
// rewritten to `includes`.
|
|
17
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-includes.md
|
|
18
|
+
package linthost
|
|
19
|
+
|
|
20
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
21
|
+
|
|
22
|
+
type unicornPreferIncludes struct{}
|
|
23
|
+
|
|
24
|
+
func (unicornPreferIncludes) Name() string { return "unicorn/prefer-includes" }
|
|
25
|
+
func (unicornPreferIncludes) Visits() []shimast.Kind {
|
|
26
|
+
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
27
|
+
}
|
|
28
|
+
func (unicornPreferIncludes) Check(ctx *Context, node *shimast.Node) {
|
|
29
|
+
bin := node.AsBinaryExpression()
|
|
30
|
+
if bin == nil || bin.OperatorToken == nil || bin.Left == nil || bin.Right == nil {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
op := bin.OperatorToken.Kind
|
|
34
|
+
wantNegOne := false
|
|
35
|
+
wantZero := false
|
|
36
|
+
switch op {
|
|
37
|
+
case shimast.KindEqualsEqualsEqualsToken,
|
|
38
|
+
shimast.KindExclamationEqualsEqualsToken,
|
|
39
|
+
shimast.KindEqualsEqualsToken,
|
|
40
|
+
shimast.KindExclamationEqualsToken:
|
|
41
|
+
wantNegOne = true
|
|
42
|
+
case shimast.KindLessThanToken:
|
|
43
|
+
// `indexOf(x) < 0`
|
|
44
|
+
wantZero = true
|
|
45
|
+
case shimast.KindGreaterThanEqualsToken:
|
|
46
|
+
// `indexOf(x) >= 0`
|
|
47
|
+
wantZero = true
|
|
48
|
+
case shimast.KindGreaterThanToken:
|
|
49
|
+
// Not in the canonical set for this orientation; handled below
|
|
50
|
+
// via `> -1` matching against the negative-one form.
|
|
51
|
+
wantNegOne = true
|
|
52
|
+
default:
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
left := stripParens(bin.Left)
|
|
56
|
+
right := stripParens(bin.Right)
|
|
57
|
+
matched := unicornPreferIncludesMatches(left, right, op, wantNegOne, wantZero)
|
|
58
|
+
// Equality is symmetric — also try the swapped orientation.
|
|
59
|
+
// Asymmetric operators (`<`, `>=`, `>`) only match the canonical
|
|
60
|
+
// orientation; swapping `indexOf(x) < 0` to `0 < indexOf(x)` changes
|
|
61
|
+
// the meaning ("found at index >= 1") and must not be rewritten.
|
|
62
|
+
if !matched {
|
|
63
|
+
switch op {
|
|
64
|
+
case shimast.KindEqualsEqualsEqualsToken,
|
|
65
|
+
shimast.KindExclamationEqualsEqualsToken,
|
|
66
|
+
shimast.KindEqualsEqualsToken,
|
|
67
|
+
shimast.KindExclamationEqualsToken:
|
|
68
|
+
matched = unicornPreferIncludesMatches(right, left, op, wantNegOne, wantZero)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if matched {
|
|
72
|
+
ctx.Report(node, "Prefer `Array#includes()` / `String#includes()` over `indexOf` comparisons.")
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
func unicornPreferIncludesMatches(
|
|
77
|
+
callSide, literalSide *shimast.Node,
|
|
78
|
+
op shimast.Kind,
|
|
79
|
+
wantNegOne, wantZero bool,
|
|
80
|
+
) bool {
|
|
81
|
+
if callSide == nil || literalSide == nil {
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
84
|
+
if callSide.Kind != shimast.KindCallExpression {
|
|
85
|
+
return false
|
|
86
|
+
}
|
|
87
|
+
call := callSide.AsCallExpression()
|
|
88
|
+
if call == nil || call.Expression == nil ||
|
|
89
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
93
|
+
if access == nil || identifierText(access.Name()) != "indexOf" {
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
// `> -1`, `>= 0`, `< 0`, `=== -1`, `!== -1`, `== -1`, `!= -1`.
|
|
97
|
+
switch op {
|
|
98
|
+
case shimast.KindGreaterThanToken:
|
|
99
|
+
// Only `indexOf(x) > -1` matches.
|
|
100
|
+
return unicornPreferIncludesIsNegativeOne(literalSide)
|
|
101
|
+
case shimast.KindLessThanToken:
|
|
102
|
+
// Only `indexOf(x) < 0` matches.
|
|
103
|
+
return unicornPreferIncludesIsZero(literalSide)
|
|
104
|
+
case shimast.KindGreaterThanEqualsToken:
|
|
105
|
+
// Only `indexOf(x) >= 0` matches.
|
|
106
|
+
return unicornPreferIncludesIsZero(literalSide)
|
|
107
|
+
}
|
|
108
|
+
if wantNegOne && unicornPreferIncludesIsNegativeOne(literalSide) {
|
|
109
|
+
return true
|
|
110
|
+
}
|
|
111
|
+
if wantZero && unicornPreferIncludesIsZero(literalSide) {
|
|
112
|
+
return true
|
|
113
|
+
}
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
func unicornPreferIncludesIsNegativeOne(node *shimast.Node) bool {
|
|
118
|
+
node = stripParens(node)
|
|
119
|
+
if node == nil {
|
|
120
|
+
return false
|
|
121
|
+
}
|
|
122
|
+
if node.Kind == shimast.KindPrefixUnaryExpression {
|
|
123
|
+
prefix := node.AsPrefixUnaryExpression()
|
|
124
|
+
if prefix == nil || prefix.Operator != shimast.KindMinusToken || prefix.Operand == nil {
|
|
125
|
+
return false
|
|
126
|
+
}
|
|
127
|
+
if prefix.Operand.Kind != shimast.KindNumericLiteral {
|
|
128
|
+
return false
|
|
129
|
+
}
|
|
130
|
+
return numericLiteralText(prefix.Operand) == "1"
|
|
131
|
+
}
|
|
132
|
+
if node.Kind == shimast.KindNumericLiteral {
|
|
133
|
+
// Some tokenizers preserve the leading `-` in the literal text.
|
|
134
|
+
return numericLiteralText(node) == "-1"
|
|
135
|
+
}
|
|
136
|
+
return false
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
func unicornPreferIncludesIsZero(node *shimast.Node) bool {
|
|
140
|
+
node = stripParens(node)
|
|
141
|
+
if node == nil || node.Kind != shimast.KindNumericLiteral {
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
return numericLiteralText(node) == "0"
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
func init() {
|
|
148
|
+
Register(unicornPreferIncludes{})
|
|
149
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// unicorn/prefer-json-parse-buffer: as of Node 21, `JSON.parse`
|
|
2
|
+
// accepts a `Buffer` directly and decodes it internally, so the common
|
|
3
|
+
// `JSON.parse(buf.toString())` pattern allocates an extra intermediate
|
|
4
|
+
// string for nothing. Dropping the `.toString()` avoids the allocation
|
|
5
|
+
// and reads at least as clearly.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit `CallExpression`. Match the outer call where the
|
|
8
|
+
// callee is `JSON.parse` (`PropertyAccess(Identifier("JSON"), parse)`)
|
|
9
|
+
// AND the single argument is itself a `CallExpression` whose callee is
|
|
10
|
+
// `PropertyAccess(_, toString)` taking no arguments — i.e. the
|
|
11
|
+
// syntactic shape `JSON.parse(x.toString())`. The receiver type of
|
|
12
|
+
// `x` is not checked, so non-buffer receivers will produce false
|
|
13
|
+
// positives; this is the documented trade for an AST-only port.
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-json-parse-buffer.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornPreferJsonParseBuffer struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornPreferJsonParseBuffer) Name() string { return "unicorn/prefer-json-parse-buffer" }
|
|
22
|
+
func (unicornPreferJsonParseBuffer) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
24
|
+
}
|
|
25
|
+
func (unicornPreferJsonParseBuffer) Check(ctx *Context, node *shimast.Node) {
|
|
26
|
+
call := node.AsCallExpression()
|
|
27
|
+
if call == nil || call.Expression == nil || call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
// Callee must be `JSON.parse`.
|
|
31
|
+
if call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
35
|
+
if access == nil {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
if identifierText(access.Expression) != "JSON" || identifierText(access.Name()) != "parse" {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
// Argument must be `_.toString()` with no arguments.
|
|
42
|
+
arg := stripParens(call.Arguments.Nodes[0])
|
|
43
|
+
if arg == nil || arg.Kind != shimast.KindCallExpression {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
innerCall := arg.AsCallExpression()
|
|
47
|
+
if innerCall == nil || innerCall.Expression == nil {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
if innerCall.Arguments != nil && len(innerCall.Arguments.Nodes) != 0 {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
if innerCall.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
innerAccess := innerCall.Expression.AsPropertyAccessExpression()
|
|
57
|
+
if innerAccess == nil || identifierText(innerAccess.Name()) != "toString" {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
ctx.Report(node, "Prefer passing a `Buffer` directly to `JSON.parse` (Node 21+) over decoding to a string first.")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
func init() {
|
|
64
|
+
Register(unicornPreferJsonParseBuffer{})
|
|
65
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// unicorn/prefer-keyboard-event-key: `KeyboardEvent#keyCode`,
|
|
2
|
+
// `KeyboardEvent#charCode`, and `KeyboardEvent#which` are all
|
|
3
|
+
// deprecated. They expose layout-dependent integer codes that change
|
|
4
|
+
// across browsers and keyboard layouts and force code to maintain
|
|
5
|
+
// magic-number tables. `KeyboardEvent#key` returns the resolved key
|
|
6
|
+
// label as a string and is the spec-blessed replacement.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: visit `PropertyAccessExpression` and match the right-hand
|
|
9
|
+
// identifier name against the deprecated property set. The receiver
|
|
10
|
+
// is intentionally not type-checked — the rule accepts the syntactic
|
|
11
|
+
// shape as the signal, which produces a small number of harmless
|
|
12
|
+
// false positives on non-event objects but is the correct trade for
|
|
13
|
+
// an AST-only port.
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-keyboard-event-key.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornPreferKeyboardEventKey struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornPreferKeyboardEventKey) Name() string { return "unicorn/prefer-keyboard-event-key" }
|
|
22
|
+
func (unicornPreferKeyboardEventKey) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{shimast.KindPropertyAccessExpression}
|
|
24
|
+
}
|
|
25
|
+
func (unicornPreferKeyboardEventKey) Check(ctx *Context, node *shimast.Node) {
|
|
26
|
+
access := node.AsPropertyAccessExpression()
|
|
27
|
+
if access == nil {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
switch identifierText(access.Name()) {
|
|
31
|
+
case "keyCode", "charCode", "which":
|
|
32
|
+
ctx.Report(node, "Prefer `KeyboardEvent#key` over the deprecated `keyCode` / `charCode` / `which`.")
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func init() {
|
|
37
|
+
Register(unicornPreferKeyboardEventKey{})
|
|
38
|
+
}
|