@ttsc/lint 0.13.1 → 0.14.0-dev.20260528.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 +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,195 @@
|
|
|
1
|
+
// typescript/no-deprecated: flag references to declarations annotated
|
|
2
|
+
// `@deprecated` in their JSDoc. The deprecation marker is the API
|
|
3
|
+
// owner's signal that a binding is on its way out; callers that keep
|
|
4
|
+
// reaching for it accumulate work to undo later, and the rule surfaces
|
|
5
|
+
// the dependency at the reference site. typescript-eslint:
|
|
6
|
+
// https://typescript-eslint.io/rules/no-deprecated/
|
|
7
|
+
//
|
|
8
|
+
// Type-aware. The rule visits the AST kinds that name a symbol —
|
|
9
|
+
// bare identifiers, property-access expressions, call / new
|
|
10
|
+
// expressions, and JSX opening / self-closing tag names — and asks the
|
|
11
|
+
// Checker for the symbol at the reference location. When any of the
|
|
12
|
+
// symbol's declarations carries a `@deprecated` JSDoc tag (attached
|
|
13
|
+
// either to the declaration itself or to its declaration block — e.g.
|
|
14
|
+
// JSDoc on a VariableStatement covers the inner VariableDeclaration),
|
|
15
|
+
// the rule reports at the reference with the deprecation comment when
|
|
16
|
+
// one is present.
|
|
17
|
+
//
|
|
18
|
+
// To avoid double-firing and silencing the deprecation site itself:
|
|
19
|
+
//
|
|
20
|
+
// - identifiers at a declaration-name position (`function foo`,
|
|
21
|
+
// `const foo`, `class Foo`, …) are skipped — they are the marker,
|
|
22
|
+
// not a reference;
|
|
23
|
+
// - the bare-identifier arm reports the canonical reference position
|
|
24
|
+
// for property-access tails, JSX tag names, and call / new callees,
|
|
25
|
+
// so the CallExpression, NewExpression, PropertyAccessExpression,
|
|
26
|
+
// and JSX-element arms register only to keep the rule honest about
|
|
27
|
+
// what it inspects — they don't report a second time.
|
|
28
|
+
package linthost
|
|
29
|
+
|
|
30
|
+
import (
|
|
31
|
+
"strings"
|
|
32
|
+
|
|
33
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
type noDeprecated struct{}
|
|
37
|
+
|
|
38
|
+
func (noDeprecated) Name() string { return "typescript/no-deprecated" }
|
|
39
|
+
func (noDeprecated) NeedsTypeChecker() bool {
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
42
|
+
func (noDeprecated) Visits() []shimast.Kind {
|
|
43
|
+
return []shimast.Kind{
|
|
44
|
+
shimast.KindIdentifier,
|
|
45
|
+
shimast.KindPropertyAccessExpression,
|
|
46
|
+
shimast.KindCallExpression,
|
|
47
|
+
shimast.KindNewExpression,
|
|
48
|
+
shimast.KindJsxOpeningElement,
|
|
49
|
+
shimast.KindJsxSelfClosingElement,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
func (noDeprecated) Check(ctx *Context, node *shimast.Node) {
|
|
53
|
+
if ctx.Checker == nil {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
// All non-identifier kinds delegate to the identifier walk for
|
|
57
|
+
// reporting — they're listed in Visits() to keep the contract
|
|
58
|
+
// explicit about which structural shapes carry symbol references,
|
|
59
|
+
// but the actual diagnostic is emitted once per identifier so a
|
|
60
|
+
// chain like `obj.method()` reports the `method` identifier, not
|
|
61
|
+
// the surrounding PropertyAccess and CallExpression as well.
|
|
62
|
+
if node.Kind != shimast.KindIdentifier {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
if noDeprecatedSkipIdentifier(node) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
symbol := ctx.Checker.GetSymbolAtLocation(node)
|
|
69
|
+
if symbol == nil {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
tag := findDeprecatedJSDocTag(symbol)
|
|
73
|
+
if tag == nil {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
// Don't report when this identifier IS the name of one of the
|
|
77
|
+
// symbol's declarations — that's the deprecation marker itself.
|
|
78
|
+
if noDeprecatedLocationIsDeclarationName(node, symbol) {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
name := identifierText(node)
|
|
82
|
+
if name == "" {
|
|
83
|
+
name = symbol.Name
|
|
84
|
+
}
|
|
85
|
+
message := "`" + name + "` is deprecated."
|
|
86
|
+
if comment := jsdocDeprecatedComment(tag); comment != "" {
|
|
87
|
+
message = message + " " + comment
|
|
88
|
+
}
|
|
89
|
+
ctx.Report(node, message)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// noDeprecatedSkipIdentifier reports whether an identifier visit
|
|
93
|
+
// should be skipped. The skipped positions are:
|
|
94
|
+
//
|
|
95
|
+
// - the LHS of a QualifiedName (`A.B` — only `B` resolves to the
|
|
96
|
+
// referenced symbol).
|
|
97
|
+
//
|
|
98
|
+
// The general "is this identifier the declaration name?" gate is
|
|
99
|
+
// applied later against the resolved symbol's declarations — see
|
|
100
|
+
// `noDeprecatedLocationIsDeclarationName` — which handles every
|
|
101
|
+
// declaration kind without enumerating each one here.
|
|
102
|
+
func noDeprecatedSkipIdentifier(node *shimast.Node) bool {
|
|
103
|
+
parent := node.Parent
|
|
104
|
+
if parent == nil {
|
|
105
|
+
return false
|
|
106
|
+
}
|
|
107
|
+
if parent.Kind == shimast.KindQualifiedName {
|
|
108
|
+
qn := parent.AsQualifiedName()
|
|
109
|
+
if qn != nil && qn.Left == node {
|
|
110
|
+
return true
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return false
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// noDeprecatedLocationIsDeclarationName reports whether `loc` is the
|
|
117
|
+
// name node of one of `symbol`'s declarations — i.e. the deprecation
|
|
118
|
+
// marker itself rather than a reference site.
|
|
119
|
+
func noDeprecatedLocationIsDeclarationName(loc *shimast.Node, symbol *shimast.Symbol) bool {
|
|
120
|
+
if loc == nil || symbol == nil {
|
|
121
|
+
return false
|
|
122
|
+
}
|
|
123
|
+
for _, decl := range symbol.Declarations {
|
|
124
|
+
if decl == nil {
|
|
125
|
+
continue
|
|
126
|
+
}
|
|
127
|
+
if decl.Name() == loc {
|
|
128
|
+
return true
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return false
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// findDeprecatedJSDocTag walks the symbol's declarations for a
|
|
135
|
+
// `@deprecated` JSDoc tag and returns the first one found. The walk
|
|
136
|
+
// climbs each declaration's ancestors up to the SourceFile because
|
|
137
|
+
// JSDoc on a VariableDeclaration is attached to the enclosing
|
|
138
|
+
// VariableStatement, and JSDoc on an ExportSpecifier may be on the
|
|
139
|
+
// outer ExportDeclaration.
|
|
140
|
+
func findDeprecatedJSDocTag(symbol *shimast.Symbol) *shimast.Node {
|
|
141
|
+
if symbol == nil {
|
|
142
|
+
return nil
|
|
143
|
+
}
|
|
144
|
+
for _, decl := range symbol.Declarations {
|
|
145
|
+
if tag := deprecatedJSDocTagOnNodeOrAncestors(decl); tag != nil {
|
|
146
|
+
return tag
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return nil
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// deprecatedJSDocTagOnNodeOrAncestors walks up from `node` looking for
|
|
153
|
+
// a `@deprecated` JSDoc tag attached to any ancestor. Returns the
|
|
154
|
+
// first matching tag, or nil.
|
|
155
|
+
func deprecatedJSDocTagOnNodeOrAncestors(node *shimast.Node) *shimast.Node {
|
|
156
|
+
for n := node; n != nil; n = n.Parent {
|
|
157
|
+
for _, jsdoc := range n.JSDoc(nil) {
|
|
158
|
+
data := jsdoc.AsJSDoc()
|
|
159
|
+
if data == nil || data.Tags == nil {
|
|
160
|
+
continue
|
|
161
|
+
}
|
|
162
|
+
for _, tag := range data.Tags.Nodes {
|
|
163
|
+
if tag.Kind == shimast.KindJSDocDeprecatedTag {
|
|
164
|
+
return tag
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if n.Kind == shimast.KindSourceFile {
|
|
169
|
+
return nil
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return nil
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// jsdocDeprecatedComment returns the textual comment that follows the
|
|
176
|
+
// `@deprecated` token in `tag`'s source range, trimmed of surrounding
|
|
177
|
+
// whitespace. Empty when the tag has no comment.
|
|
178
|
+
func jsdocDeprecatedComment(tag *shimast.Node) string {
|
|
179
|
+
if tag == nil {
|
|
180
|
+
return ""
|
|
181
|
+
}
|
|
182
|
+
src := strings.TrimSpace(shimast.NodeText(tag))
|
|
183
|
+
if src == "" {
|
|
184
|
+
return ""
|
|
185
|
+
}
|
|
186
|
+
const prefix = "@deprecated"
|
|
187
|
+
if strings.HasPrefix(src, prefix) {
|
|
188
|
+
src = src[len(prefix):]
|
|
189
|
+
}
|
|
190
|
+
return strings.TrimSpace(src)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
func init() {
|
|
194
|
+
Register(noDeprecated{})
|
|
195
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// typescript/no-for-in-array: `for (const k in arr)` iterates the
|
|
2
|
+
// enumerable property NAMES of `arr` — including inherited members and any
|
|
3
|
+
// custom properties someone has attached to `Array.prototype` — and yields
|
|
4
|
+
// them as strings, not as numeric indices. The author almost always meant
|
|
5
|
+
// `for...of` (values) or a plain index loop (numeric keys). typescript-eslint:
|
|
6
|
+
// https://typescript-eslint.io/rules/no-for-in-array/
|
|
7
|
+
package linthost
|
|
8
|
+
|
|
9
|
+
import (
|
|
10
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
11
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
// noForInArray fires on `for (... in <expr>)` when the Checker reports that
|
|
15
|
+
// `<expr>` is an array or tuple type. Type-aware: without a Checker the rule
|
|
16
|
+
// cannot tell an array from a plain record-shaped object, so it bails to
|
|
17
|
+
// avoid false positives. The constituent-recursion shape mirrors
|
|
18
|
+
// `requireArraySortCompareIsArrayLike` — a union like `number[] | string[]`
|
|
19
|
+
// is still array-like because every constituent is.
|
|
20
|
+
type noForInArray struct{}
|
|
21
|
+
|
|
22
|
+
func (noForInArray) Name() string { return "typescript/no-for-in-array" }
|
|
23
|
+
func (noForInArray) NeedsTypeChecker() bool {
|
|
24
|
+
return true
|
|
25
|
+
}
|
|
26
|
+
func (noForInArray) Visits() []shimast.Kind {
|
|
27
|
+
return []shimast.Kind{shimast.KindForInStatement}
|
|
28
|
+
}
|
|
29
|
+
func (noForInArray) Check(ctx *Context, node *shimast.Node) {
|
|
30
|
+
if ctx.Checker == nil {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
stmt := node.AsForInOrOfStatement()
|
|
34
|
+
if stmt == nil || stmt.Expression == nil {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
t := ctx.Checker.GetTypeAtLocation(stmt.Expression)
|
|
38
|
+
if t == nil {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
if !noForInArrayIsArrayLike(ctx.Checker, t) {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
ctx.Report(node, "Iterating an array with `for...in` yields enumerable property names (as strings), including inherited members. Use `for...of`, `forEach`, or an indexed `for` loop instead.")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// noForInArrayIsArrayLike reports whether t is provably an array or tuple.
|
|
48
|
+
// Mirrors `requireArraySortCompareIsArrayLike`: recurse into union /
|
|
49
|
+
// intersection constituents and consider the whole type array-like only when
|
|
50
|
+
// every constituent is. `any` / `unknown` / `never` are intentionally NOT
|
|
51
|
+
// treated as array-like — they leak from generic helpers and would explode
|
|
52
|
+
// the false-positive volume on otherwise legitimate `for...in` over a
|
|
53
|
+
// genuinely-keyed object.
|
|
54
|
+
func noForInArrayIsArrayLike(checker *shimchecker.Checker, t *shimchecker.Type) bool {
|
|
55
|
+
if checker == nil || t == nil {
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
flags := t.Flags()
|
|
59
|
+
if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
|
|
63
|
+
for _, part := range t.Types() {
|
|
64
|
+
if part == nil {
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
if !noForInArrayIsArrayLike(checker, part) {
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return true
|
|
72
|
+
}
|
|
73
|
+
if shimchecker.Checker_isArrayType(checker, t) {
|
|
74
|
+
return true
|
|
75
|
+
}
|
|
76
|
+
if shimchecker.IsTupleType(t) {
|
|
77
|
+
return true
|
|
78
|
+
}
|
|
79
|
+
return false
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
func init() {
|
|
83
|
+
Register(noForInArray{})
|
|
84
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// typescript/no-magic-numbers: TS-aware extension of the core
|
|
2
|
+
// `no-magic-numbers` rule. Numeric literals that appear inline in
|
|
3
|
+
// expressions tend to be unexplained constants — `if (count > 86400)`
|
|
4
|
+
// is opaque, `if (count > SECONDS_PER_DAY)` is not. The rule asks the
|
|
5
|
+
// author to lift those values into a named constant or enum.
|
|
6
|
+
// typescript-eslint:
|
|
7
|
+
// https://typescript-eslint.io/rules/no-magic-numbers/
|
|
8
|
+
//
|
|
9
|
+
// AST-only. The trigger is a `KindNumericLiteral` (or a numeric literal
|
|
10
|
+
// wrapped in a unary `+` / `-`). The TS variant differs from the core
|
|
11
|
+
// rule in one detail that this implementation enforces: numeric
|
|
12
|
+
// literals used as enum member initializers are NOT magic — an
|
|
13
|
+
// `enum Status { OK = 200 }` declaration IS the lifting step the rule
|
|
14
|
+
// pushes authors toward, so flagging the `200` would be backwards.
|
|
15
|
+
//
|
|
16
|
+
// Type-position numeric literals are also skipped: a literal that
|
|
17
|
+
// appears inside a `KindLiteralType` (e.g. `type N = 5`) is a type, not
|
|
18
|
+
// a runtime constant, and the rule's concern is runtime magic numbers.
|
|
19
|
+
// The well-known unit values `-1`, `0`, and `1` pass through because
|
|
20
|
+
// they almost always carry intrinsic meaning (sentinel, identity,
|
|
21
|
+
// step) and treating them as magic produces only noise.
|
|
22
|
+
package linthost
|
|
23
|
+
|
|
24
|
+
import (
|
|
25
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
type tsNoMagicNumbers struct{}
|
|
29
|
+
|
|
30
|
+
func (tsNoMagicNumbers) Name() string { return "typescript/no-magic-numbers" }
|
|
31
|
+
func (tsNoMagicNumbers) Visits() []shimast.Kind {
|
|
32
|
+
return []shimast.Kind{shimast.KindNumericLiteral}
|
|
33
|
+
}
|
|
34
|
+
func (tsNoMagicNumbers) Check(ctx *Context, node *shimast.Node) {
|
|
35
|
+
if node == nil {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
// Identify the surface node that represents the numeric value:
|
|
39
|
+
// either the literal itself or the wrapping `+lit` / `-lit` unary.
|
|
40
|
+
surface := node
|
|
41
|
+
if parent := node.Parent; parent != nil && parent.Kind == shimast.KindPrefixUnaryExpression {
|
|
42
|
+
prefix := parent.AsPrefixUnaryExpression()
|
|
43
|
+
if prefix != nil && (prefix.Operator == shimast.KindMinusToken || prefix.Operator == shimast.KindPlusToken) && prefix.Operand == node {
|
|
44
|
+
surface = parent
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Skip when the literal lives inside a type position. A literal type
|
|
48
|
+
// (`type N = 5`, `Array<10>`) is not a runtime constant — the
|
|
49
|
+
// rule's concern is unexplained runtime values.
|
|
50
|
+
if isInsideTypePosition(surface) {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
// TS extension: enum member initializers are themselves the named
|
|
54
|
+
// constant the rule is asking for. `enum S { OK = 200 }` lifts the
|
|
55
|
+
// value into `S.OK`; flagging the `200` would push authors to
|
|
56
|
+
// double-wrap an already-named constant.
|
|
57
|
+
if isEnumMemberInitializer(surface) {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
// Whitelisted unit values: -1 / 0 / 1 carry intrinsic meaning (not
|
|
61
|
+
// found, identity, step) in almost every codebase. Treating them as
|
|
62
|
+
// magic produces only noise.
|
|
63
|
+
if isWellKnownUnitNumber(ctx.File, surface) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
ctx.Report(surface, "No magic number: extract into a named constant or enum member.")
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// isEnumMemberInitializer reports whether surface is the initializer
|
|
70
|
+
// expression of an enum member (`enum X { A = 1 }`). The literal node
|
|
71
|
+
// itself (or its unary wrapper) is the EnumMember.Initializer in that
|
|
72
|
+
// case, which is exactly the position the TS extension whitelists.
|
|
73
|
+
func isEnumMemberInitializer(surface *shimast.Node) bool {
|
|
74
|
+
parent := surface.Parent
|
|
75
|
+
if parent == nil || parent.Kind != shimast.KindEnumMember {
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
member := parent.AsEnumMember()
|
|
79
|
+
return member != nil && member.Initializer == surface
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// isInsideTypePosition reports whether `surface` is reached only
|
|
83
|
+
// through type-syntax ancestors before hitting a value-bearing node.
|
|
84
|
+
// Literal types, type arguments, and type aliases are type positions;
|
|
85
|
+
// the rule has nothing to say about literals that never reach runtime.
|
|
86
|
+
func isInsideTypePosition(surface *shimast.Node) bool {
|
|
87
|
+
for p := surface.Parent; p != nil; p = p.Parent {
|
|
88
|
+
switch p.Kind {
|
|
89
|
+
case shimast.KindLiteralType,
|
|
90
|
+
shimast.KindTypeReference,
|
|
91
|
+
shimast.KindTypeAliasDeclaration,
|
|
92
|
+
shimast.KindUnionType,
|
|
93
|
+
shimast.KindIntersectionType,
|
|
94
|
+
shimast.KindTypeOperator,
|
|
95
|
+
shimast.KindIndexedAccessType,
|
|
96
|
+
shimast.KindMappedType,
|
|
97
|
+
shimast.KindConditionalType,
|
|
98
|
+
shimast.KindTypeParameter:
|
|
99
|
+
return true
|
|
100
|
+
case shimast.KindPrefixUnaryExpression,
|
|
101
|
+
shimast.KindParenthesizedExpression:
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
return false
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// isWellKnownUnitNumber reports whether `surface` is the literal `0`,
|
|
110
|
+
// `1`, or `-1`. The match is on source text to keep handling of `0.0`
|
|
111
|
+
// vs `0` and `1e0` vs `1` consistent with what the author actually
|
|
112
|
+
// wrote — only the bare textual form is whitelisted.
|
|
113
|
+
func isWellKnownUnitNumber(file *shimast.SourceFile, surface *shimast.Node) bool {
|
|
114
|
+
text := nodeText(file, surface)
|
|
115
|
+
switch text {
|
|
116
|
+
case "0", "1", "-1":
|
|
117
|
+
return true
|
|
118
|
+
}
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
func init() {
|
|
123
|
+
Register(tsNoMagicNumbers{})
|
|
124
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// typescript/no-meaningless-void-operator reports `void X` where the
|
|
2
|
+
// operand `X` is already statically typed `void`. The `void` operator
|
|
3
|
+
// always evaluates to `undefined`; if the operand was going to produce
|
|
4
|
+
// `undefined` anyway, the operator adds nothing and obscures the
|
|
5
|
+
// intent. The most common shape is `void someVoidReturningCall()`
|
|
6
|
+
// somewhere a `void` discard would be useful for a non-void operand
|
|
7
|
+
// (e.g. fire-and-forget Promise) — but a `void`-typed operand is
|
|
8
|
+
// already discarded.
|
|
9
|
+
// https://typescript-eslint.io/rules/no-meaningless-void-operator/
|
|
10
|
+
//
|
|
11
|
+
// Type-aware. Without a Checker the rule cannot tell `void` from any
|
|
12
|
+
// other type, so Context.Checker == nil short-circuits the Check to a
|
|
13
|
+
// no-op the way the other type-aware rules do. The upstream
|
|
14
|
+
// `checkNever` option is left at its default of `false`: only the
|
|
15
|
+
// `void` operand triggers, `never` does not.
|
|
16
|
+
package linthost
|
|
17
|
+
|
|
18
|
+
import (
|
|
19
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
20
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
type noMeaninglessVoidOperator struct{}
|
|
24
|
+
|
|
25
|
+
func (noMeaninglessVoidOperator) Name() string {
|
|
26
|
+
return "typescript/no-meaningless-void-operator"
|
|
27
|
+
}
|
|
28
|
+
func (noMeaninglessVoidOperator) NeedsTypeChecker() bool { return true }
|
|
29
|
+
func (noMeaninglessVoidOperator) Visits() []shimast.Kind {
|
|
30
|
+
return []shimast.Kind{shimast.KindVoidExpression}
|
|
31
|
+
}
|
|
32
|
+
func (noMeaninglessVoidOperator) Check(ctx *Context, node *shimast.Node) {
|
|
33
|
+
if ctx.Checker == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
expr := node.AsVoidExpression()
|
|
37
|
+
if expr == nil || expr.Expression == nil {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
operand := stripParens(expr.Expression)
|
|
41
|
+
if operand == nil {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
t := ctx.Checker.GetTypeAtLocation(operand)
|
|
45
|
+
if t == nil {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
if !isVoidOnlyType(t) {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
ctx.Report(node, "The `void` operator on a value already typed `void` adds nothing — drop the operator.")
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// isVoidOnlyType reports whether t is the bare `void` type or a union
|
|
55
|
+
// composed entirely of `void` constituents. The upstream rule fires
|
|
56
|
+
// only when the operand carries no non-void member; a mixed `void |
|
|
57
|
+
// number` operand still needs the operator to discard the runtime
|
|
58
|
+
// value, so it is left alone.
|
|
59
|
+
func isVoidOnlyType(t *shimchecker.Type) bool {
|
|
60
|
+
if t == nil {
|
|
61
|
+
return false
|
|
62
|
+
}
|
|
63
|
+
flags := t.Flags()
|
|
64
|
+
if flags&shimchecker.TypeFlagsVoid != 0 {
|
|
65
|
+
return true
|
|
66
|
+
}
|
|
67
|
+
if flags&shimchecker.TypeFlagsUnion != 0 {
|
|
68
|
+
parts := t.Types()
|
|
69
|
+
if len(parts) == 0 {
|
|
70
|
+
return false
|
|
71
|
+
}
|
|
72
|
+
for _, part := range parts {
|
|
73
|
+
if !isVoidOnlyType(part) {
|
|
74
|
+
return false
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return true
|
|
78
|
+
}
|
|
79
|
+
return false
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
func init() {
|
|
83
|
+
Register(noMeaninglessVoidOperator{})
|
|
84
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// AST-only subset of the upstream `typescript/no-misused-spread` rule.
|
|
2
|
+
//
|
|
3
|
+
// The full upstream rule needs the type checker to decide whether the
|
|
4
|
+
// spread operand is actually iterable (or a plain object). This subset
|
|
5
|
+
// catches the three syntactic shapes that are unambiguously wrong even
|
|
6
|
+
// without type information:
|
|
7
|
+
//
|
|
8
|
+
// 1. Object literal spread inside an array literal — `[...{ a: 1 }]`.
|
|
9
|
+
// Object literals are not iterable, so this is always a TypeError
|
|
10
|
+
// at runtime.
|
|
11
|
+
// 2. Object literal spread as a call/construct argument —
|
|
12
|
+
// `f(...{ a: 1 })`, `new Set(...{ a: 1 })`. Same reason: the
|
|
13
|
+
// callee receives the spread via iteration.
|
|
14
|
+
// 3. Array literal spread inside an object literal — `{ ...[1, 2] }`.
|
|
15
|
+
// The array's numeric indices become string keys (`"0"`, `"1"`,
|
|
16
|
+
// …) which is almost never what the author intended.
|
|
17
|
+
//
|
|
18
|
+
// https://typescript-eslint.io/rules/no-misused-spread/
|
|
19
|
+
package linthost
|
|
20
|
+
|
|
21
|
+
import (
|
|
22
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
type noMisusedSpread struct{}
|
|
26
|
+
|
|
27
|
+
func (noMisusedSpread) Name() string { return "typescript/no-misused-spread" }
|
|
28
|
+
func (noMisusedSpread) Visits() []shimast.Kind {
|
|
29
|
+
return []shimast.Kind{
|
|
30
|
+
shimast.KindArrayLiteralExpression,
|
|
31
|
+
shimast.KindObjectLiteralExpression,
|
|
32
|
+
shimast.KindCallExpression,
|
|
33
|
+
shimast.KindNewExpression,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
func (noMisusedSpread) Check(ctx *Context, node *shimast.Node) {
|
|
37
|
+
switch node.Kind {
|
|
38
|
+
case shimast.KindArrayLiteralExpression:
|
|
39
|
+
arr := node.AsArrayLiteralExpression()
|
|
40
|
+
if arr == nil || arr.Elements == nil {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
for _, elem := range arr.Elements.Nodes {
|
|
44
|
+
reportObjectSpreadInIterable(ctx, elem)
|
|
45
|
+
}
|
|
46
|
+
case shimast.KindCallExpression:
|
|
47
|
+
call := node.AsCallExpression()
|
|
48
|
+
if call == nil || call.Arguments == nil {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
for _, arg := range call.Arguments.Nodes {
|
|
52
|
+
reportObjectSpreadInIterable(ctx, arg)
|
|
53
|
+
}
|
|
54
|
+
case shimast.KindNewExpression:
|
|
55
|
+
ne := node.AsNewExpression()
|
|
56
|
+
if ne == nil || ne.Arguments == nil {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
for _, arg := range ne.Arguments.Nodes {
|
|
60
|
+
reportObjectSpreadInIterable(ctx, arg)
|
|
61
|
+
}
|
|
62
|
+
case shimast.KindObjectLiteralExpression:
|
|
63
|
+
obj := node.AsObjectLiteralExpression()
|
|
64
|
+
if obj == nil || obj.Properties == nil {
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
for _, prop := range obj.Properties.Nodes {
|
|
68
|
+
if prop == nil || prop.Kind != shimast.KindSpreadAssignment {
|
|
69
|
+
continue
|
|
70
|
+
}
|
|
71
|
+
spread := prop.AsSpreadAssignment()
|
|
72
|
+
if spread == nil {
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
inner := stripParens(spread.Expression)
|
|
76
|
+
if inner != nil && inner.Kind == shimast.KindArrayLiteralExpression {
|
|
77
|
+
ctx.Report(prop, "Spreading an array literal into an object literal coerces numeric indices to string keys — likely a mistake.")
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// reportObjectSpreadInIterable reports the spread element when its
|
|
84
|
+
// operand is an object literal in a position that consumes the spread
|
|
85
|
+
// via iteration (array literal element or function/constructor
|
|
86
|
+
// argument).
|
|
87
|
+
func reportObjectSpreadInIterable(ctx *Context, elem *shimast.Node) {
|
|
88
|
+
if elem == nil || elem.Kind != shimast.KindSpreadElement {
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
spread := elem.AsSpreadElement()
|
|
92
|
+
if spread == nil {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
inner := stripParens(spread.Expression)
|
|
96
|
+
if inner == nil || inner.Kind != shimast.KindObjectLiteralExpression {
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
ctx.Report(elem, "Spread of an object literal into an iterable context is meaningless — object literals are not iterable.")
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
func init() {
|
|
103
|
+
Register(noMisusedSpread{})
|
|
104
|
+
}
|