@ttsc/lint 0.13.1 → 0.14.0-dev.20260528
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 +948 -69
- package/lib/defaultFormat.d.ts +9 -6
- package/lib/defaultFormat.js +9 -6
- package/lib/defaultFormat.js.map +1 -1
- package/lib/index.d.ts +46 -0
- package/lib/index.js +35 -10
- package/lib/index.js.map +1 -1
- package/lib/structures/ITtscLintConfig.d.ts +12 -6
- package/lib/structures/{ITtscLintFormatConfig.d.ts → ITtscLintFormat.d.ts} +2 -2
- package/lib/structures/{TtscLintRuleMap.js → ITtscLintFormat.js} +1 -1
- package/lib/structures/ITtscLintFormat.js.map +1 -0
- 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/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 +104 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +14 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +79 -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 +17 -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 +1257 -0
- package/lib/structures/{ITtscLintFormatConfig.js → rules/ITtscLintCoreRules.js} +1 -1
- 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 +129 -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 +157 -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 +167 -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 +201 -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 +140 -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 +302 -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 +185 -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 +330 -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 +188 -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 +51 -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 +39 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js +12 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRules.d.ts +289 -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 +190 -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 +66 -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 +148 -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 +181 -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 +21 -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 +174 -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 +94 -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 +22 -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 +310 -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 +1132 -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 +141 -0
- package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
- package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
- package/lib/structures/rules/index.d.ts +31 -0
- package/lib/structures/rules/index.js +48 -0
- package/lib/structures/rules/index.js.map +1 -0
- package/linthost/ast_helpers.go +30 -5
- package/linthost/config.go +48 -17
- package/linthost/config_format.go +9 -9
- package/linthost/directives.go +67 -25
- package/linthost/dispatch.go +14 -3
- package/linthost/engine.go +152 -31
- package/linthost/fix.go +2 -2
- package/linthost/lsp.go +747 -0
- package/linthost/print_dispatch.go +2 -2
- package/linthost/print_nodes_function.go +2 -2
- package/linthost/print_nodes_object.go +1 -1
- 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 +94 -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_jsdoc.go +1 -1
- package/linthost/rules_format_print_width.go +9 -9
- package/linthost/rules_format_quotes.go +1 -1
- package/linthost/rules_format_semi.go +1 -1
- package/linthost/rules_format_sort_imports.go +1 -1
- package/linthost/rules_format_trailing_comma.go +1 -1
- 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 +1128 -73
- 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 +155 -36
- package/linthost/rules_ts_no_base_to_string.go +218 -0
- package/linthost/rules_ts_no_confusing_void.go +72 -0
- package/linthost/rules_ts_no_deprecated.go +195 -0
- package/linthost/rules_ts_no_for_in_array.go +84 -0
- package/linthost/rules_ts_no_magic_numbers.go +124 -0
- package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
- package/linthost/rules_ts_no_misused_spread.go +104 -0
- package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
- package/linthost/rules_ts_no_restricted_types.go +62 -0
- package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
- package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
- package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
- package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
- package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
- package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
- package/linthost/rules_ts_no_unsafe_argument.go +82 -0
- package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
- package/linthost/rules_ts_no_unsafe_call.go +82 -0
- package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
- package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
- package/linthost/rules_ts_no_unsafe_return.go +126 -0
- package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
- package/linthost/rules_ts_no_useless_constructor.go +52 -0
- package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
- package/linthost/rules_ts_parameter_properties.go +38 -0
- package/linthost/rules_ts_prefer_find.go +178 -0
- package/linthost/rules_ts_prefer_includes.go +255 -0
- package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
- package/linthost/rules_ts_prefer_optional_chain.go +228 -0
- package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
- package/linthost/rules_ts_prefer_readonly.go +73 -0
- package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
- package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
- package/linthost/rules_ts_prefer_return_this_type.go +135 -0
- package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
- package/linthost/rules_ts_promise_function_async.go +77 -0
- package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
- package/linthost/rules_ts_require_array_sort_compare.go +96 -0
- package/linthost/rules_ts_restrict_plus_operands.go +127 -0
- package/linthost/rules_ts_restrict_template_expressions.go +95 -0
- package/linthost/rules_ts_simple.go +387 -0
- package/linthost/rules_ts_sort_type_constituents.go +144 -0
- package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
- package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
- package/linthost/rules_ts_unbound_method.go +126 -0
- package/linthost/rules_tsdoc.go +136 -0
- package/linthost/rules_unicorn_better_regex.go +27 -0
- package/linthost/rules_unicorn_catch_error_name.go +46 -0
- package/linthost/rules_unicorn_consistent_assert.go +47 -0
- package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
- package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
- package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
- package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
- package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
- package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
- package/linthost/rules_unicorn_custom_error_definition.go +138 -0
- package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
- package/linthost/rules_unicorn_error_message.go +64 -0
- package/linthost/rules_unicorn_escape_case.go +51 -0
- package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
- package/linthost/rules_unicorn_explicit_length_check.go +88 -0
- package/linthost/rules_unicorn_filename_case.go +29 -0
- package/linthost/rules_unicorn_import_style.go +28 -0
- package/linthost/rules_unicorn_isolated_functions.go +29 -0
- package/linthost/rules_unicorn_new_for_builtins.go +87 -0
- package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
- package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
- package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
- package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
- package/linthost/rules_unicorn_no_array_for_each.go +40 -0
- package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
- package/linthost/rules_unicorn_no_array_reduce.go +41 -0
- package/linthost/rules_unicorn_no_array_reverse.go +44 -0
- package/linthost/rules_unicorn_no_array_sort.go +43 -0
- package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
- package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
- package/linthost/rules_unicorn_no_console_spaces.go +61 -0
- package/linthost/rules_unicorn_no_document_cookie.go +41 -0
- package/linthost/rules_unicorn_no_empty_file.go +44 -0
- package/linthost/rules_unicorn_no_for_loop.go +102 -0
- package/linthost/rules_unicorn_no_hex_escape.go +42 -0
- package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
- package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
- package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
- package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
- package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
- package/linthost/rules_unicorn_no_lonely_if.go +44 -0
- package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
- package/linthost/rules_unicorn_no_named_default.go +54 -0
- package/linthost/rules_unicorn_no_negated_condition.go +85 -0
- package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
- package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
- package/linthost/rules_unicorn_no_new_array.go +30 -0
- package/linthost/rules_unicorn_no_new_buffer.go +31 -0
- package/linthost/rules_unicorn_no_null.go +24 -0
- package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
- package/linthost/rules_unicorn_no_process_exit.go +43 -0
- package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
- package/linthost/rules_unicorn_no_static_only_class.go +56 -0
- package/linthost/rules_unicorn_no_thenable.go +74 -0
- package/linthost/rules_unicorn_no_this_assignment.go +35 -0
- package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
- package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
- package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
- package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
- package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
- package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
- package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
- package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
- package/linthost/rules_unicorn_no_unused_properties.go +30 -0
- package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
- package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
- package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
- package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
- package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
- package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
- package/linthost/rules_unicorn_no_useless_spread.go +67 -0
- package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
- package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
- package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
- package/linthost/rules_unicorn_number_literal_case.go +69 -0
- package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
- package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
- package/linthost/rules_unicorn_prefer_array_find.go +51 -0
- package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
- package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
- package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
- package/linthost/rules_unicorn_prefer_array_some.go +67 -0
- package/linthost/rules_unicorn_prefer_at.go +77 -0
- package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
- package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
- package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
- package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
- package/linthost/rules_unicorn_prefer_code_point.go +49 -0
- package/linthost/rules_unicorn_prefer_date_now.go +78 -0
- package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
- package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
- package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
- package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
- package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
- package/linthost/rules_unicorn_prefer_event_target.go +36 -0
- package/linthost/rules_unicorn_prefer_export_from.go +129 -0
- package/linthost/rules_unicorn_prefer_global_this.go +127 -0
- package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
- package/linthost/rules_unicorn_prefer_includes.go +149 -0
- package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
- package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
- package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
- package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
- package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
- package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
- package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
- package/linthost/rules_unicorn_prefer_module.go +50 -0
- package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
- package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
- package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
- package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
- package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
- package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
- package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
- package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
- package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
- package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
- package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
- package/linthost/rules_unicorn_prefer_set_has.go +42 -0
- package/linthost/rules_unicorn_prefer_set_size.go +48 -0
- package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
- package/linthost/rules_unicorn_prefer_single_call.go +96 -0
- package/linthost/rules_unicorn_prefer_spread.go +51 -0
- package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
- package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
- package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
- package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
- package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
- package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
- package/linthost/rules_unicorn_prefer_switch.go +103 -0
- package/linthost/rules_unicorn_prefer_ternary.go +71 -0
- package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
- package/linthost/rules_unicorn_prefer_type_error.go +127 -0
- package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
- package/linthost/rules_unicorn_relative_url_style.go +49 -0
- package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
- package/linthost/rules_unicorn_require_module_attributes.go +54 -0
- package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
- package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
- package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
- package/linthost/rules_unicorn_string_content.go +27 -0
- package/linthost/rules_unicorn_switch_case_braces.go +42 -0
- package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
- package/linthost/rules_unicorn_template_indent.go +28 -0
- package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
- package/linthost/rules_unicorn_throw_new_error.go +61 -0
- package/linthost/rules_var.go +4 -4
- package/linthost/rules_vitest.go +568 -0
- package/package.json +3 -3
- package/plugin/main.go +49 -3
- package/rule/astutil/astutil.go +10 -3
- package/rule/rule.go +12 -10
- package/src/defaultFormat.ts +11 -8
- package/src/index.ts +40 -16
- package/src/structures/ITtscLintConfig.ts +12 -6
- package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
- package/src/structures/TtscLintRuleSetting.ts +55 -0
- package/src/structures/index.ts +3 -4
- package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
- package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
- package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
- package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
- package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
- package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
- package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
- package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
- package/src/structures/rules/ITtscLintJestRules.ts +220 -0
- package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
- package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
- package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
- package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
- package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
- package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
- package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
- package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
- package/src/structures/rules/ITtscLintReactRules.ts +321 -0
- package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
- package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
- package/src/structures/rules/ITtscLintRules.ts +77 -0
- package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
- package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
- package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
- package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
- package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
- package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
- package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
- package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
- package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
- package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
- package/src/structures/rules/index.ts +31 -0
- 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/TtscLintRule.ts +0 -160
- package/src/structures/TtscLintRuleMap.ts +0 -55
- package/src/structures/TtscLintRuleOptions.ts +0 -151
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// unicorn/no-array-sort: `Array#sort()` mutates the array in place and
|
|
2
|
+
// returns the same reference, so any caller holding the original sees
|
|
3
|
+
// the sorted order too. ES2023 introduced `Array#toSorted()`, which
|
|
4
|
+
// returns a fresh sorted copy and leaves the source untouched; the rule
|
|
5
|
+
// pushes authors toward the non-mutating form.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit each `CallExpression`, check that the callee is a
|
|
8
|
+
// property access whose method identifier is `sort`, and accept either
|
|
9
|
+
// zero arguments or exactly one (the optional comparator). Calls with
|
|
10
|
+
// two or more arguments are almost certainly a different `sort` on a
|
|
11
|
+
// user-defined type and are excluded by design.
|
|
12
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-sort.md
|
|
13
|
+
package linthost
|
|
14
|
+
|
|
15
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
|
+
|
|
17
|
+
type unicornNoArraySort struct{}
|
|
18
|
+
|
|
19
|
+
func (unicornNoArraySort) Name() string { return "unicorn/no-array-sort" }
|
|
20
|
+
func (unicornNoArraySort) Visits() []shimast.Kind {
|
|
21
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
22
|
+
}
|
|
23
|
+
func (unicornNoArraySort) Check(ctx *Context, node *shimast.Node) {
|
|
24
|
+
call := node.AsCallExpression()
|
|
25
|
+
if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
29
|
+
if access == nil {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
if identifierText(access.Name()) != "sort" {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
if call.Arguments != nil && len(call.Arguments.Nodes) > 1 {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
ctx.Report(node, "Prefer `Array#toSorted()` over the mutating `Array#sort()`.")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func init() {
|
|
42
|
+
Register(unicornNoArraySort{})
|
|
43
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// unicorn/no-await-expression-member: `(await foo).bar` and
|
|
2
|
+
// `(await foo)[index]` mix two reading positions in one expression —
|
|
3
|
+
// the resolution step (`await foo`) and the projection step (`.bar`).
|
|
4
|
+
// Splitting them into a temporary `const value = await foo; value.bar`
|
|
5
|
+
// makes the order of operations explicit and lines up better with
|
|
6
|
+
// stepping through the async function in a debugger.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: any `PropertyAccessExpression` whose receiver is an
|
|
9
|
+
// `AwaitExpression` (possibly wrapped in `ParenthesizedExpression`) fires.
|
|
10
|
+
// `ElementAccessExpression` is left out of this minimal pass — the
|
|
11
|
+
// PropertyAccess shape is the canonical violation cited in the upstream
|
|
12
|
+
// docs and matches the receiver shape directly via `stripParens`.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-await-expression-member.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type unicornNoAwaitExpressionMember struct{}
|
|
19
|
+
|
|
20
|
+
func (unicornNoAwaitExpressionMember) Name() string {
|
|
21
|
+
return "unicorn/no-await-expression-member"
|
|
22
|
+
}
|
|
23
|
+
func (unicornNoAwaitExpressionMember) Visits() []shimast.Kind {
|
|
24
|
+
return []shimast.Kind{shimast.KindPropertyAccessExpression}
|
|
25
|
+
}
|
|
26
|
+
func (unicornNoAwaitExpressionMember) Check(ctx *Context, node *shimast.Node) {
|
|
27
|
+
access := node.AsPropertyAccessExpression()
|
|
28
|
+
if access == nil {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
receiver := stripParens(access.Expression)
|
|
32
|
+
if receiver == nil || receiver.Kind != shimast.KindAwaitExpression {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
ctx.Report(node, "Don't use member access on an `await` expression — assign the awaited value to a variable first.")
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
func init() {
|
|
39
|
+
Register(unicornNoAwaitExpressionMember{})
|
|
40
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// unicorn/no-await-in-promise-methods: awaiting an element inside the
|
|
2
|
+
// array argument of `Promise.all` / `Promise.allSettled` / `Promise.race`
|
|
3
|
+
// / `Promise.any` defeats the parallelism the call exists for. The
|
|
4
|
+
// awaits resolve serially in source order before the array is even
|
|
5
|
+
// handed to `Promise.<method>`, so the combinator only sees the
|
|
6
|
+
// already-resolved values.
|
|
7
|
+
//
|
|
8
|
+
// AST-only: visit each `CallExpression`, match the callee against
|
|
9
|
+
// `Promise.<method>` for the four parallel combinators, and check the
|
|
10
|
+
// sole argument's `ArrayLiteralExpression` elements for any
|
|
11
|
+
// `AwaitExpression` shape. Fire on the offending await node so the
|
|
12
|
+
// report anchors to the actual misuse.
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-await-in-promise-methods.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
var unicornNoAwaitInPromiseMethodsMethods = map[string]struct{}{
|
|
19
|
+
"all": {},
|
|
20
|
+
"allSettled": {},
|
|
21
|
+
"race": {},
|
|
22
|
+
"any": {},
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type unicornNoAwaitInPromiseMethods struct{}
|
|
26
|
+
|
|
27
|
+
func (unicornNoAwaitInPromiseMethods) Name() string {
|
|
28
|
+
return "unicorn/no-await-in-promise-methods"
|
|
29
|
+
}
|
|
30
|
+
func (unicornNoAwaitInPromiseMethods) Visits() []shimast.Kind {
|
|
31
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
32
|
+
}
|
|
33
|
+
func (unicornNoAwaitInPromiseMethods) Check(ctx *Context, node *shimast.Node) {
|
|
34
|
+
call := node.AsCallExpression()
|
|
35
|
+
if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
39
|
+
if access == nil {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
if identifierText(access.Expression) != "Promise" {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
method := identifierText(access.Name())
|
|
46
|
+
if _, ok := unicornNoAwaitInPromiseMethodsMethods[method]; !ok {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
arg := call.Arguments.Nodes[0]
|
|
53
|
+
if arg == nil || arg.Kind != shimast.KindArrayLiteralExpression {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
arr := arg.AsArrayLiteralExpression()
|
|
57
|
+
if arr == nil || arr.Elements == nil {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
for _, elem := range arr.Elements.Nodes {
|
|
61
|
+
if elem != nil && elem.Kind == shimast.KindAwaitExpression {
|
|
62
|
+
ctx.Report(elem, "Don't `await` inside `Promise."+method+"` array members — the awaits serialize the calls.")
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
func init() {
|
|
68
|
+
Register(unicornNoAwaitInPromiseMethods{})
|
|
69
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// unicorn/no-console-spaces: `console.log("a ", "b")` produces
|
|
2
|
+
// `"a b"` with a doubled space because the runtime already inserts a
|
|
3
|
+
// single ASCII space between arguments. Leading/trailing whitespace on
|
|
4
|
+
// the literal duplicates that separator and is almost always a leftover
|
|
5
|
+
// from hand-formatting. The rule flags every string-literal argument
|
|
6
|
+
// whose content starts or ends with a space so the source converges on
|
|
7
|
+
// argument-only content and the runtime owns the separator.
|
|
8
|
+
//
|
|
9
|
+
// AST-only and identifier-text-driven: dispatch on `CallExpression`,
|
|
10
|
+
// match a `console.<method>` callee against the six common log
|
|
11
|
+
// methods, and report each `StringLiteral` argument with a leading or
|
|
12
|
+
// trailing space. The receiver is matched by identifier text only;
|
|
13
|
+
// shadowed `console` bindings are out of scope, mirroring the other
|
|
14
|
+
// console-shape rules in this family.
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-console-spaces.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import (
|
|
19
|
+
"strings"
|
|
20
|
+
|
|
21
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
type unicornNoConsoleSpaces struct{}
|
|
25
|
+
|
|
26
|
+
func (unicornNoConsoleSpaces) Name() string { return "unicorn/no-console-spaces" }
|
|
27
|
+
func (unicornNoConsoleSpaces) Visits() []shimast.Kind {
|
|
28
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
29
|
+
}
|
|
30
|
+
func (unicornNoConsoleSpaces) Check(ctx *Context, node *shimast.Node) {
|
|
31
|
+
call := node.AsCallExpression()
|
|
32
|
+
if call == nil || call.Expression == nil ||
|
|
33
|
+
call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
37
|
+
if access == nil || identifierText(access.Expression) != "console" {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
switch identifierText(access.Name()) {
|
|
41
|
+
case "log", "warn", "error", "info", "debug", "trace":
|
|
42
|
+
default:
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
if call.Arguments == nil {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
for _, arg := range call.Arguments.Nodes {
|
|
49
|
+
if arg == nil || arg.Kind != shimast.KindStringLiteral {
|
|
50
|
+
continue
|
|
51
|
+
}
|
|
52
|
+
text := stringLiteralText(arg)
|
|
53
|
+
if strings.HasPrefix(text, " ") || strings.HasSuffix(text, " ") {
|
|
54
|
+
ctx.Report(arg, "Don't include leading or trailing spaces in `console.<method>` arguments.")
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
func init() {
|
|
60
|
+
Register(unicornNoConsoleSpaces{})
|
|
61
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// unicorn/no-document-cookie: writing to (or reading) `document.cookie`
|
|
2
|
+
// directly mixes name/value parsing, serialization, attribute handling,
|
|
3
|
+
// and quoting concerns into one mutable string. The replacement is the
|
|
4
|
+
// async Cookie Store API (`cookieStore.set`/`cookieStore.get`) or a
|
|
5
|
+
// dedicated cookie wrapper — both surface attribute fields as data
|
|
6
|
+
// instead of string-encoded options.
|
|
7
|
+
//
|
|
8
|
+
// AST-only and identifier-text-driven: any `PropertyAccessExpression`
|
|
9
|
+
// whose receiver identifier is `document` and whose property name is
|
|
10
|
+
// `cookie` matches, so the same visit handles both the read
|
|
11
|
+
// (`document.cookie`) and the assignment LHS (`document.cookie = "..."`).
|
|
12
|
+
// Shadowed `document` bindings and computed/optional access are out of
|
|
13
|
+
// scope, mirroring `unicorn/no-process-exit`.
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-document-cookie.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornNoDocumentCookie struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornNoDocumentCookie) Name() string { return "unicorn/no-document-cookie" }
|
|
22
|
+
func (unicornNoDocumentCookie) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{shimast.KindPropertyAccessExpression}
|
|
24
|
+
}
|
|
25
|
+
func (unicornNoDocumentCookie) Check(ctx *Context, node *shimast.Node) {
|
|
26
|
+
access := node.AsPropertyAccessExpression()
|
|
27
|
+
if access == nil {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
if identifierText(access.Expression) != "document" {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
if identifierText(access.Name()) != "cookie" {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
ctx.Report(node, "Don't use `document.cookie` directly; use the Cookie Store API or a wrapper.")
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
func init() {
|
|
40
|
+
Register(unicornNoDocumentCookie{})
|
|
41
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// unicorn/no-empty-file: a source file with no executable contribution
|
|
2
|
+
// — every statement is a bare `;` empty-statement (or there are no
|
|
3
|
+
// statements at all) — usually exists by accident: a placeholder kept
|
|
4
|
+
// around past its purpose, a generator output for a missing input, or
|
|
5
|
+
// a copy of a file whose body was deleted. The rule flags these so the
|
|
6
|
+
// file is either filled with content or removed.
|
|
7
|
+
//
|
|
8
|
+
// SourceFile dispatch: the engine fires `KindSourceFile` visits once
|
|
9
|
+
// per file at the file root (see engine.runFile). For visibility into
|
|
10
|
+
// where the diagnostic lands when reporters render `path:line:col`, the
|
|
11
|
+
// rule reports on the first statement node when one exists (so the
|
|
12
|
+
// pointer matches the file's source line); when the file truly has no
|
|
13
|
+
// statements at all it falls back to `ReportRange(0, 0, …)` so the
|
|
14
|
+
// diagnostic still surfaces.
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-empty-file.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
|
|
20
|
+
type unicornNoEmptyFile struct{}
|
|
21
|
+
|
|
22
|
+
func (unicornNoEmptyFile) Name() string { return "unicorn/no-empty-file" }
|
|
23
|
+
func (unicornNoEmptyFile) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindSourceFile} }
|
|
24
|
+
func (unicornNoEmptyFile) Check(ctx *Context, node *shimast.Node) {
|
|
25
|
+
if ctx.File == nil {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
statements := ctx.File.Statements
|
|
29
|
+
const message = "Empty files are not allowed."
|
|
30
|
+
if statements == nil || len(statements.Nodes) == 0 {
|
|
31
|
+
ctx.ReportRange(0, 0, message)
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
for _, stmt := range statements.Nodes {
|
|
35
|
+
if stmt == nil || stmt.Kind != shimast.KindEmptyStatement {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
ctx.Report(statements.Nodes[0], message)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
func init() {
|
|
43
|
+
Register(unicornNoEmptyFile{})
|
|
44
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// unicorn/no-for-loop: the classic `for (let i = 0; i < arr.length; i++)`
|
|
2
|
+
// pattern is an index-based array walk that has a direct `for…of`
|
|
3
|
+
// translation. The index variable, the length re-read, and the manual
|
|
4
|
+
// increment are all incidental bookkeeping the language now expresses
|
|
5
|
+
// with one keyword.
|
|
6
|
+
//
|
|
7
|
+
// AST-only and syntactic: dispatch on `ForStatement` and match the
|
|
8
|
+
// three classic shapes — `let i = 0` initializer, `i < X.length`
|
|
9
|
+
// condition (the RHS must be a `.length` access; bare counters
|
|
10
|
+
// `i < n` are not flagged because the suggested `for…of` rewrite does
|
|
11
|
+
// not apply), and `i++` incrementor. The length operand is not
|
|
12
|
+
// required to resolve to an array at the type level; the syntactic
|
|
13
|
+
// shape is the signal the rule wants to discourage.
|
|
14
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-for-loop.md
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type unicornNoForLoop struct{}
|
|
20
|
+
|
|
21
|
+
func (unicornNoForLoop) Name() string { return "unicorn/no-for-loop" }
|
|
22
|
+
func (unicornNoForLoop) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindForStatement} }
|
|
23
|
+
func (unicornNoForLoop) Check(ctx *Context, node *shimast.Node) {
|
|
24
|
+
stmt := node.AsForStatement()
|
|
25
|
+
if stmt == nil || stmt.Initializer == nil || stmt.Condition == nil || stmt.Incrementor == nil {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
indexName := indexInitializerName(stmt.Initializer)
|
|
29
|
+
if indexName == "" {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
if !isLessThanCondition(stmt.Condition, indexName) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
if !isPostfixIncrementOf(stmt.Incrementor, indexName) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
ctx.Report(node, "Use `for…of` over an index-based `for` loop over an array.")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// indexInitializerName returns the variable name of a `let i = 0`
|
|
42
|
+
// initializer, or "" when the initializer is anything else.
|
|
43
|
+
func indexInitializerName(init *shimast.Node) string {
|
|
44
|
+
if init == nil || init.Kind != shimast.KindVariableDeclarationList {
|
|
45
|
+
return ""
|
|
46
|
+
}
|
|
47
|
+
list := init.AsVariableDeclarationList()
|
|
48
|
+
if list == nil || list.Declarations == nil || len(list.Declarations.Nodes) != 1 {
|
|
49
|
+
return ""
|
|
50
|
+
}
|
|
51
|
+
decl := list.Declarations.Nodes[0].AsVariableDeclaration()
|
|
52
|
+
if decl == nil || decl.Initializer == nil {
|
|
53
|
+
return ""
|
|
54
|
+
}
|
|
55
|
+
if numericLiteralText(stripParens(decl.Initializer)) != "0" {
|
|
56
|
+
return ""
|
|
57
|
+
}
|
|
58
|
+
return identifierText(decl.Name())
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// isLessThanCondition reports whether `cond` has the shape
|
|
62
|
+
// `<name> < <something>.length`. The right-hand operand must be a
|
|
63
|
+
// property access ending in `length`; bare counter loops such as
|
|
64
|
+
// `for (let i = 0; i < n; i++)` are NOT flagged because the rule's
|
|
65
|
+
// suggested rewrite (`for…of`) only applies to array iteration.
|
|
66
|
+
func isLessThanCondition(cond *shimast.Node, name string) bool {
|
|
67
|
+
node := stripParens(cond)
|
|
68
|
+
if node == nil || node.Kind != shimast.KindBinaryExpression {
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
bin := node.AsBinaryExpression()
|
|
72
|
+
if bin == nil || bin.OperatorToken == nil ||
|
|
73
|
+
bin.OperatorToken.Kind != shimast.KindLessThanToken {
|
|
74
|
+
return false
|
|
75
|
+
}
|
|
76
|
+
if identifierText(stripParens(bin.Left)) != name {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
right := stripParens(bin.Right)
|
|
80
|
+
if right == nil || right.Kind != shimast.KindPropertyAccessExpression {
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
access := right.AsPropertyAccessExpression()
|
|
84
|
+
return access != nil && identifierText(access.Name()) == "length"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// isPostfixIncrementOf reports whether `inc` has the shape `<name>++`.
|
|
88
|
+
func isPostfixIncrementOf(inc *shimast.Node, name string) bool {
|
|
89
|
+
node := stripParens(inc)
|
|
90
|
+
if node == nil || node.Kind != shimast.KindPostfixUnaryExpression {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
post := node.AsPostfixUnaryExpression()
|
|
94
|
+
if post == nil || post.Operator != shimast.KindPlusPlusToken {
|
|
95
|
+
return false
|
|
96
|
+
}
|
|
97
|
+
return identifierText(post.Operand) == name
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
func init() {
|
|
101
|
+
Register(unicornNoForLoop{})
|
|
102
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// unicorn/no-hex-escape: `\xHH` escapes inside string and template
|
|
2
|
+
// literals are legal but they read worse than the equivalent
|
|
3
|
+
// `\u00HH` Unicode escape — there's only one way to write a Unicode
|
|
4
|
+
// escape, while a hex escape silently widens to a Unicode escape at
|
|
5
|
+
// runtime anyway. The rule nudges authors toward the Unicode form.
|
|
6
|
+
//
|
|
7
|
+
// AST-only: visit `KindStringLiteral` and `KindNoSubstitutionTemplateLiteral`,
|
|
8
|
+
// read the raw source text via `nodeText` (the parser already decodes
|
|
9
|
+
// escapes into the `.Text` value, so a normal accessor would see `©`
|
|
10
|
+
// instead of `\xA9`), and fire when the source contains a `\xHH`
|
|
11
|
+
// occurrence where HH is two hex digits.
|
|
12
|
+
//
|
|
13
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-hex-escape.md
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import (
|
|
17
|
+
"regexp"
|
|
18
|
+
|
|
19
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
var unicornNoHexEscapePattern = regexp.MustCompile(`\\x[0-9A-Fa-f]{2}`)
|
|
23
|
+
|
|
24
|
+
type unicornNoHexEscape struct{}
|
|
25
|
+
|
|
26
|
+
func (unicornNoHexEscape) Name() string { return "unicorn/no-hex-escape" }
|
|
27
|
+
func (unicornNoHexEscape) Visits() []shimast.Kind {
|
|
28
|
+
return []shimast.Kind{shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral}
|
|
29
|
+
}
|
|
30
|
+
func (unicornNoHexEscape) Check(ctx *Context, node *shimast.Node) {
|
|
31
|
+
source := nodeText(ctx.File, node)
|
|
32
|
+
if source == "" {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
if unicornNoHexEscapePattern.MatchString(source) {
|
|
36
|
+
ctx.Report(node, "Prefer Unicode escapes (`\\uXXXX`) over hex escapes (`\\xHH`).")
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func init() {
|
|
41
|
+
Register(unicornNoHexEscape{})
|
|
42
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// unicorn/no-immediate-mutation: mutating an expression on the same
|
|
2
|
+
// statement that produces it — e.g. `[1, 2, 3].push(4)` or
|
|
3
|
+
// `arr.map(...).sort()` — discards the mutator's return value (which is
|
|
4
|
+
// either the new length or `void`) and obscures whether the author
|
|
5
|
+
// wanted the array, the count, or the side effect. The rule splits the
|
|
6
|
+
// two operations: construct first, then mutate (or use the non-mutating
|
|
7
|
+
// counterpart).
|
|
8
|
+
//
|
|
9
|
+
// AST-only: visit each `CallExpression`. Match when the callee is a
|
|
10
|
+
// `PropertyAccessExpression(receiver, name)` where `name` is one of the
|
|
11
|
+
// mutating array methods AND the receiver (after `stripParens`) is
|
|
12
|
+
// either an `ArrayLiteralExpression` or another call expression whose
|
|
13
|
+
// callee is a non-mutating array method that produces a fresh array.
|
|
14
|
+
// Fire on the outer call.
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-immediate-mutation.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
|
|
20
|
+
var unicornNoImmediateMutationMethods = map[string]struct{}{
|
|
21
|
+
"push": {},
|
|
22
|
+
"pop": {},
|
|
23
|
+
"shift": {},
|
|
24
|
+
"unshift": {},
|
|
25
|
+
"splice": {},
|
|
26
|
+
"sort": {},
|
|
27
|
+
"reverse": {},
|
|
28
|
+
"copyWithin": {},
|
|
29
|
+
"fill": {},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
var unicornNoImmediateMutationFreshMethods = map[string]struct{}{
|
|
33
|
+
"map": {},
|
|
34
|
+
"filter": {},
|
|
35
|
+
"slice": {},
|
|
36
|
+
"concat": {},
|
|
37
|
+
"flat": {},
|
|
38
|
+
"flatMap": {},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type unicornNoImmediateMutation struct{}
|
|
42
|
+
|
|
43
|
+
func (unicornNoImmediateMutation) Name() string { return "unicorn/no-immediate-mutation" }
|
|
44
|
+
func (unicornNoImmediateMutation) Visits() []shimast.Kind {
|
|
45
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
46
|
+
}
|
|
47
|
+
func (unicornNoImmediateMutation) Check(ctx *Context, node *shimast.Node) {
|
|
48
|
+
call := node.AsCallExpression()
|
|
49
|
+
if call == nil || call.Expression == nil {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
if call.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
access := call.Expression.AsPropertyAccessExpression()
|
|
56
|
+
if access == nil {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
method := identifierText(access.Name())
|
|
60
|
+
if _, ok := unicornNoImmediateMutationMethods[method]; !ok {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
receiver := stripParens(access.Expression)
|
|
64
|
+
if receiver == nil {
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
if receiver.Kind == shimast.KindArrayLiteralExpression {
|
|
68
|
+
ctx.Report(node, "Don't mutate a freshly built array — separate the construction and the mutation, or use a non-mutating method.")
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
if receiver.Kind == shimast.KindCallExpression {
|
|
72
|
+
inner := receiver.AsCallExpression()
|
|
73
|
+
if inner == nil || inner.Expression == nil ||
|
|
74
|
+
inner.Expression.Kind != shimast.KindPropertyAccessExpression {
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
innerAccess := inner.Expression.AsPropertyAccessExpression()
|
|
78
|
+
if innerAccess == nil {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
innerName := identifierText(innerAccess.Name())
|
|
82
|
+
if _, ok := unicornNoImmediateMutationFreshMethods[innerName]; ok {
|
|
83
|
+
ctx.Report(node, "Don't mutate a freshly built array — separate the construction and the mutation, or use a non-mutating method.")
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
func init() {
|
|
89
|
+
Register(unicornNoImmediateMutation{})
|
|
90
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// unicorn/no-instanceof-builtins: `x instanceof Array` (and the other
|
|
2
|
+
// built-in container constructors) is broken across realms and for
|
|
3
|
+
// user-defined subclasses. The cross-realm hazard is well known —
|
|
4
|
+
// `Array` in an iframe is a different constructor than the host
|
|
5
|
+
// `Array`, so a cross-realm value fails the check despite being an
|
|
6
|
+
// array; the subclass hazard is subtler — `instanceof` walks the
|
|
7
|
+
// prototype chain, so a `MyError extends Error` still passes
|
|
8
|
+
// `x instanceof Error` and obscures the actual type.
|
|
9
|
+
//
|
|
10
|
+
// AST-only: visit each `BinaryExpression` whose operator token is
|
|
11
|
+
// `instanceof`. The right-hand operand must be a bare identifier whose
|
|
12
|
+
// text appears in the built-in allowlist. Property-access or computed
|
|
13
|
+
// right-hand operands are out of scope because they cannot be matched
|
|
14
|
+
// syntactically against the global names.
|
|
15
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-instanceof-builtins.md
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
19
|
+
|
|
20
|
+
var unicornNoInstanceofBuiltinsNames = map[string]struct{}{
|
|
21
|
+
"Array": {},
|
|
22
|
+
"Error": {},
|
|
23
|
+
"EvalError": {},
|
|
24
|
+
"RangeError": {},
|
|
25
|
+
"ReferenceError": {},
|
|
26
|
+
"SyntaxError": {},
|
|
27
|
+
"TypeError": {},
|
|
28
|
+
"URIError": {},
|
|
29
|
+
"AggregateError": {},
|
|
30
|
+
"Map": {},
|
|
31
|
+
"Set": {},
|
|
32
|
+
"WeakMap": {},
|
|
33
|
+
"WeakSet": {},
|
|
34
|
+
"Date": {},
|
|
35
|
+
"RegExp": {},
|
|
36
|
+
"Promise": {},
|
|
37
|
+
"Function": {},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type unicornNoInstanceofBuiltins struct{}
|
|
41
|
+
|
|
42
|
+
func (unicornNoInstanceofBuiltins) Name() string { return "unicorn/no-instanceof-builtins" }
|
|
43
|
+
func (unicornNoInstanceofBuiltins) Visits() []shimast.Kind {
|
|
44
|
+
return []shimast.Kind{shimast.KindBinaryExpression}
|
|
45
|
+
}
|
|
46
|
+
func (unicornNoInstanceofBuiltins) Check(ctx *Context, node *shimast.Node) {
|
|
47
|
+
bin := node.AsBinaryExpression()
|
|
48
|
+
if bin == nil || bin.OperatorToken == nil || bin.Right == nil {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
if bin.OperatorToken.Kind != shimast.KindInstanceOfKeyword {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
name := identifierText(bin.Right)
|
|
55
|
+
if name == "" {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
if _, ok := unicornNoInstanceofBuiltinsNames[name]; !ok {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
ctx.Report(node, "Don't use `instanceof <Builtin>` — it breaks across realms and for subclasses. Use a type predicate or duck-typing instead.")
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
func init() {
|
|
65
|
+
Register(unicornNoInstanceofBuiltins{})
|
|
66
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// unicorn/no-invalid-fetch-options: passing a `body` together with a
|
|
2
|
+
// `GET` or `HEAD` `fetch()` call throws at runtime because the spec
|
|
3
|
+
// forbids a request body for those methods. The rule catches the
|
|
4
|
+
// mismatch at parse time so the throw never reaches production.
|
|
5
|
+
//
|
|
6
|
+
// AST-only: visit each `CallExpression`, match when the callee is a
|
|
7
|
+
// bare `fetch` identifier and the second argument is an object literal
|
|
8
|
+
// containing both a string-literal `method` of `GET` / `HEAD`
|
|
9
|
+
// (case-insensitive) AND a `body` property of any shape. Report on the
|
|
10
|
+
// call so the diagnostic lands at the offending site.
|
|
11
|
+
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-invalid-fetch-options.md
|
|
12
|
+
package linthost
|
|
13
|
+
|
|
14
|
+
import (
|
|
15
|
+
"strings"
|
|
16
|
+
|
|
17
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
type unicornNoInvalidFetchOptions struct{}
|
|
21
|
+
|
|
22
|
+
func (unicornNoInvalidFetchOptions) Name() string { return "unicorn/no-invalid-fetch-options" }
|
|
23
|
+
func (unicornNoInvalidFetchOptions) Visits() []shimast.Kind {
|
|
24
|
+
return []shimast.Kind{shimast.KindCallExpression}
|
|
25
|
+
}
|
|
26
|
+
func (unicornNoInvalidFetchOptions) Check(ctx *Context, node *shimast.Node) {
|
|
27
|
+
call := node.AsCallExpression()
|
|
28
|
+
if call == nil {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
if identifierText(call.Expression) != "fetch" {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if call.Arguments == nil || len(call.Arguments.Nodes) < 2 {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
init := stripParens(call.Arguments.Nodes[1])
|
|
38
|
+
if init == nil || init.Kind != shimast.KindObjectLiteralExpression {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
obj := init.AsObjectLiteralExpression()
|
|
42
|
+
if obj == nil || obj.Properties == nil {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
hasBody := false
|
|
46
|
+
methodIsBodyless := false
|
|
47
|
+
for _, prop := range obj.Properties.Nodes {
|
|
48
|
+
if prop == nil || prop.Kind != shimast.KindPropertyAssignment {
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
assignment := prop.AsPropertyAssignment()
|
|
52
|
+
if assignment == nil || assignment.Name() == nil {
|
|
53
|
+
continue
|
|
54
|
+
}
|
|
55
|
+
key := identifierText(assignment.Name())
|
|
56
|
+
if key == "" && assignment.Name().Kind == shimast.KindStringLiteral {
|
|
57
|
+
key = stringLiteralText(assignment.Name())
|
|
58
|
+
}
|
|
59
|
+
switch key {
|
|
60
|
+
case "body":
|
|
61
|
+
hasBody = true
|
|
62
|
+
case "method":
|
|
63
|
+
value := stripParens(assignment.Initializer)
|
|
64
|
+
if value != nil && value.Kind == shimast.KindStringLiteral {
|
|
65
|
+
m := strings.ToLower(stringLiteralText(value))
|
|
66
|
+
if m == "get" || m == "head" {
|
|
67
|
+
methodIsBodyless = true
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if hasBody && methodIsBodyless {
|
|
73
|
+
ctx.Report(node, "Don't pass `body` with GET/HEAD `fetch` — it throws at runtime.")
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
func init() {
|
|
78
|
+
Register(unicornNoInvalidFetchOptions{})
|
|
79
|
+
}
|