@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
package/linthost/rules_logic.go
CHANGED
|
@@ -10,7 +10,7 @@ import (
|
|
|
10
10
|
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
-
//
|
|
13
|
+
// noExtraBooleanCast: `if (!!x)`, `if (Boolean(x))`, `Boolean(!!x)` —
|
|
14
14
|
// the conversion is implicit in a boolean context.
|
|
15
15
|
// https://eslint.org/docs/latest/rules/no-extra-boolean-cast
|
|
16
16
|
type noExtraBooleanCast struct{}
|
|
@@ -148,7 +148,7 @@ func skipParents(node *shimast.Node) *shimast.Node {
|
|
|
148
148
|
return node
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
//
|
|
151
|
+
// noUnsafeNegation: `!a in b` and `!a instanceof b` — the parser
|
|
152
152
|
// applies the negation to `a`, not to the whole comparison.
|
|
153
153
|
// https://eslint.org/docs/latest/rules/no-unsafe-negation
|
|
154
154
|
type noUnsafeNegation struct{}
|
|
@@ -247,13 +247,13 @@ func comparableLiteralKind(node *shimast.Node) string {
|
|
|
247
247
|
return ""
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
//
|
|
250
|
+
// useIsNaN: `x === NaN` is always false. Use `Number.isNaN(x)`.
|
|
251
251
|
// https://eslint.org/docs/latest/rules/use-isnan
|
|
252
|
-
type
|
|
252
|
+
type useIsNaN struct{}
|
|
253
253
|
|
|
254
|
-
func (
|
|
255
|
-
func (
|
|
256
|
-
func (
|
|
254
|
+
func (useIsNaN) Name() string { return "use-isnan" }
|
|
255
|
+
func (useIsNaN) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindBinaryExpression} }
|
|
256
|
+
func (useIsNaN) Check(ctx *Context, node *shimast.Node) {
|
|
257
257
|
expr := node.AsBinaryExpression()
|
|
258
258
|
if expr == nil || expr.OperatorToken == nil {
|
|
259
259
|
return
|
|
@@ -266,7 +266,7 @@ func (useIsnan) Check(ctx *Context, node *shimast.Node) {
|
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
//
|
|
269
|
+
// validTypeof: typeof expressions can only be compared to known type
|
|
270
270
|
// strings. Catches `typeof x === "stirng"`.
|
|
271
271
|
// https://eslint.org/docs/latest/rules/valid-typeof
|
|
272
272
|
type validTypeof struct{}
|
|
@@ -311,7 +311,7 @@ func isValidTypeofString(value string) bool {
|
|
|
311
311
|
return false
|
|
312
312
|
}
|
|
313
313
|
|
|
314
|
-
//
|
|
314
|
+
// noCompareNegZero: `x === -0`. Comparison ignores the sign — use
|
|
315
315
|
// `Object.is(x, -0)` if you really mean it.
|
|
316
316
|
// https://eslint.org/docs/latest/rules/no-compare-neg-zero
|
|
317
317
|
type noCompareNegZero struct{}
|
|
@@ -342,7 +342,7 @@ func isNegZero(node *shimast.Node) bool {
|
|
|
342
342
|
return numericLiteralText(prefix.Operand) == "0"
|
|
343
343
|
}
|
|
344
344
|
|
|
345
|
-
//
|
|
345
|
+
// noCondAssign: `if (a = b)` is almost always a typo for `if (a == b)`.
|
|
346
346
|
// Default mode matches ESLint's `except-parens` — wrapping in `( )`
|
|
347
347
|
// silences the rule.
|
|
348
348
|
// https://eslint.org/docs/latest/rules/no-cond-assign
|
|
@@ -418,7 +418,7 @@ func isAssignmentOperator(kind shimast.Kind) bool {
|
|
|
418
418
|
return false
|
|
419
419
|
}
|
|
420
420
|
|
|
421
|
-
//
|
|
421
|
+
// noConstantCondition: `if (true)`, `while (1)`, `if (literal)`. Often
|
|
422
422
|
// the result of leftover debug code or a typo.
|
|
423
423
|
// https://eslint.org/docs/latest/rules/no-constant-condition
|
|
424
424
|
type noConstantCondition struct{}
|
|
@@ -495,7 +495,7 @@ func init() {
|
|
|
495
495
|
Register(noExtraBooleanCast{})
|
|
496
496
|
Register(noUnsafeNegation{})
|
|
497
497
|
Register(eqeqeq{})
|
|
498
|
-
Register(
|
|
498
|
+
Register(useIsNaN{})
|
|
499
499
|
Register(validTypeof{})
|
|
500
500
|
Register(noCompareNegZero{})
|
|
501
501
|
Register(noCondAssign{})
|
package/linthost/rules_loops.go
CHANGED
|
@@ -2,7 +2,7 @@ package linthost
|
|
|
2
2
|
|
|
3
3
|
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
4
4
|
|
|
5
|
-
//
|
|
5
|
+
// forDirection: `for (var i = 10; i < 20; i--)` will never terminate.
|
|
6
6
|
// https://eslint.org/docs/latest/rules/for-direction
|
|
7
7
|
type forDirection struct{}
|
|
8
8
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// maxClassesPerFile: a file that declares many classes is almost
|
|
2
|
+
// always carrying several unrelated responsibilities. Splitting them
|
|
3
|
+
// into their own modules keeps imports honest and reduces the surface
|
|
4
|
+
// each reader has to scan. ESLint's default ceiling is one class per
|
|
5
|
+
// file, which @ttsc/lint mirrors as the only built-in threshold
|
|
6
|
+
// (option-decoding is deferred).
|
|
7
|
+
// https://eslint.org/docs/latest/rules/max-classes-per-file
|
|
8
|
+
//
|
|
9
|
+
// The rule counts both ClassDeclaration and ClassExpression nodes
|
|
10
|
+
// anywhere in the file so a helper class hidden inside an IIFE still
|
|
11
|
+
// contributes to the total. The finding is anchored at the first
|
|
12
|
+
// class that pushed the count past the limit — the second class
|
|
13
|
+
// under the default — so the diagnostic header points at the
|
|
14
|
+
// offending declaration rather than the file's opening line.
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import (
|
|
18
|
+
"fmt"
|
|
19
|
+
|
|
20
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
// maxClassesPerFileLimit is the class-count ceiling. Above this value
|
|
24
|
+
// the rule fires once for the file. Mirrors the ESLint default.
|
|
25
|
+
const maxClassesPerFileLimit = 1
|
|
26
|
+
|
|
27
|
+
type maxClassesPerFile struct{}
|
|
28
|
+
|
|
29
|
+
func (maxClassesPerFile) Name() string { return "max-classes-per-file" }
|
|
30
|
+
func (maxClassesPerFile) Visits() []shimast.Kind {
|
|
31
|
+
return []shimast.Kind{shimast.KindSourceFile}
|
|
32
|
+
}
|
|
33
|
+
func (maxClassesPerFile) Check(ctx *Context, node *shimast.Node) {
|
|
34
|
+
if node == nil {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
var classes []*shimast.Node
|
|
38
|
+
walkDescendants(node, func(n *shimast.Node) {
|
|
39
|
+
if n == nil {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
switch n.Kind {
|
|
43
|
+
case shimast.KindClassDeclaration, shimast.KindClassExpression:
|
|
44
|
+
classes = append(classes, n)
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
if len(classes) <= maxClassesPerFileLimit {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
// Report at the first class that pushed the count over the limit,
|
|
51
|
+
// so the diagnostic anchors on the offending declaration rather
|
|
52
|
+
// than the file's opening byte.
|
|
53
|
+
ctx.Report(classes[maxClassesPerFileLimit], fmt.Sprintf("File has too many classes (%d). Maximum allowed is %d.", len(classes), maxClassesPerFileLimit))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
func init() {
|
|
57
|
+
Register(maxClassesPerFile{})
|
|
58
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// maxDepth: deeply nested block statements are a readability tax — the
|
|
2
|
+
// reader must hold every enclosing condition or loop in mind to reason
|
|
3
|
+
// about the innermost statement. ESLint's default is `{ max: 4 }`, which
|
|
4
|
+
// @ttsc/lint mirrors as the only built-in threshold (option-decoding is
|
|
5
|
+
// deferred). Each function body re-starts the depth counter so nested
|
|
6
|
+
// function-like declarations are measured independently.
|
|
7
|
+
// https://eslint.org/docs/latest/rules/max-depth
|
|
8
|
+
package linthost
|
|
9
|
+
|
|
10
|
+
import (
|
|
11
|
+
"fmt"
|
|
12
|
+
|
|
13
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// maxDepthLimit is the block-nesting ceiling. Above this value the rule
|
|
17
|
+
// fires. Mirrors the ESLint default and matches the threshold documented
|
|
18
|
+
// in the README and website MDX.
|
|
19
|
+
const maxDepthLimit = 4
|
|
20
|
+
|
|
21
|
+
type maxDepth struct{}
|
|
22
|
+
|
|
23
|
+
func (maxDepth) Name() string { return "max-depth" }
|
|
24
|
+
func (maxDepth) Visits() []shimast.Kind {
|
|
25
|
+
return []shimast.Kind{
|
|
26
|
+
shimast.KindFunctionDeclaration,
|
|
27
|
+
shimast.KindFunctionExpression,
|
|
28
|
+
shimast.KindArrowFunction,
|
|
29
|
+
shimast.KindMethodDeclaration,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
func (maxDepth) Check(ctx *Context, node *shimast.Node) {
|
|
33
|
+
if node == nil {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
body := node.Body()
|
|
37
|
+
if body == nil || body.Kind != shimast.KindBlock {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
walkMaxDepthBody(body, node, 0, ctx)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// walkMaxDepthBody descends through `root` counting nested block-bearing
|
|
44
|
+
// statements without crossing nested function-like scopes. Each nested
|
|
45
|
+
// function is left for its own visit. The depth counter increments on
|
|
46
|
+
// statements whose bodies introduce a new block: `if`, `else`, `for`,
|
|
47
|
+
// `for-in`, `for-of`, `while`, `do-while`, `switch`, and `try` (plus
|
|
48
|
+
// each `catch` clause). When the depth exceeds the configured limit, a
|
|
49
|
+
// single finding is reported at the offending statement and the
|
|
50
|
+
// recursive walk continues so independent over-limit branches each get
|
|
51
|
+
// their own diagnostic.
|
|
52
|
+
func walkMaxDepthBody(node *shimast.Node, fn *shimast.Node, depth int, ctx *Context) {
|
|
53
|
+
if node == nil {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
if node != fn && isFunctionLikeKind(node) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
switch node.Kind {
|
|
60
|
+
case shimast.KindIfStatement,
|
|
61
|
+
shimast.KindForStatement,
|
|
62
|
+
shimast.KindForInStatement,
|
|
63
|
+
shimast.KindForOfStatement,
|
|
64
|
+
shimast.KindWhileStatement,
|
|
65
|
+
shimast.KindDoStatement,
|
|
66
|
+
shimast.KindSwitchStatement,
|
|
67
|
+
shimast.KindTryStatement,
|
|
68
|
+
shimast.KindCatchClause,
|
|
69
|
+
shimast.KindWithStatement:
|
|
70
|
+
depth++
|
|
71
|
+
if depth > maxDepthLimit {
|
|
72
|
+
ctx.Report(node, fmt.Sprintf("Blocks are nested too deeply (%d). Maximum allowed is %d.", depth, maxDepthLimit))
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
node.ForEachChild(func(child *shimast.Node) bool {
|
|
76
|
+
walkMaxDepthBody(child, fn, depth, ctx)
|
|
77
|
+
return false
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
func init() {
|
|
82
|
+
Register(maxDepth{})
|
|
83
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// maxLines: very long files are almost always doing more than one
|
|
2
|
+
// thing — the reader cannot hold the whole responsibility in their
|
|
3
|
+
// head, and follow-up changes tend to make the file longer rather than
|
|
4
|
+
// split it. ESLint's default ceiling is 300 lines, which @ttsc/lint
|
|
5
|
+
// mirrors as the only built-in threshold (option-decoding is deferred).
|
|
6
|
+
// https://eslint.org/docs/latest/rules/max-lines
|
|
7
|
+
//
|
|
8
|
+
// The rule counts every line in the file's source text — code,
|
|
9
|
+
// comments, and blank lines alike — because the goal is a hard cap on
|
|
10
|
+
// how much one file can hold, not a heuristic over "real" code. A file
|
|
11
|
+
// with N newline characters has N+1 lines unless the final character
|
|
12
|
+
// itself is a newline; in either case the count corresponds to the
|
|
13
|
+
// line on which the last byte appears. The finding is anchored at the
|
|
14
|
+
// first line that exceeded the limit (line `max+1`), matching ESLint
|
|
15
|
+
// so editor squiggles land on the offending row rather than the file's
|
|
16
|
+
// opening line.
|
|
17
|
+
package linthost
|
|
18
|
+
|
|
19
|
+
import (
|
|
20
|
+
"fmt"
|
|
21
|
+
|
|
22
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
// maxLinesLimit is the line-count ceiling. Above this value the rule
|
|
26
|
+
// fires once for the file. Mirrors the ESLint default.
|
|
27
|
+
const maxLinesLimit = 300
|
|
28
|
+
|
|
29
|
+
type maxLines struct{}
|
|
30
|
+
|
|
31
|
+
func (maxLines) Name() string { return "max-lines" }
|
|
32
|
+
func (maxLines) Visits() []shimast.Kind {
|
|
33
|
+
return []shimast.Kind{shimast.KindSourceFile}
|
|
34
|
+
}
|
|
35
|
+
func (maxLines) Check(ctx *Context, node *shimast.Node) {
|
|
36
|
+
if ctx.File == nil {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
src := ctx.File.Text()
|
|
40
|
+
count := countSourceLines(src)
|
|
41
|
+
if count <= maxLinesLimit {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
// Anchor at the start of line `max+1` — the first line that pushed
|
|
45
|
+
// the file past the limit. ESLint matches this anchor so editor
|
|
46
|
+
// squiggles land on the offending row.
|
|
47
|
+
pos := nthLineStart(src, maxLinesLimit)
|
|
48
|
+
if pos < 0 || pos >= len(src) {
|
|
49
|
+
pos = 0
|
|
50
|
+
}
|
|
51
|
+
end := pos + 1
|
|
52
|
+
if end > len(src) {
|
|
53
|
+
end = len(src)
|
|
54
|
+
}
|
|
55
|
+
if end <= pos {
|
|
56
|
+
end = pos + 1
|
|
57
|
+
}
|
|
58
|
+
ctx.ReportRange(pos, end, fmt.Sprintf("File has too many lines (%d). Maximum allowed is %d.", count, maxLinesLimit))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// nthLineStart returns the byte offset where the (`n`+1)-th line
|
|
62
|
+
// begins (0-indexed: passing 0 returns 0, passing 1 returns the byte
|
|
63
|
+
// after the first `\n`). Returns -1 when the file has fewer lines.
|
|
64
|
+
func nthLineStart(src string, n int) int {
|
|
65
|
+
if n <= 0 {
|
|
66
|
+
return 0
|
|
67
|
+
}
|
|
68
|
+
seen := 0
|
|
69
|
+
for i := 0; i < len(src); i++ {
|
|
70
|
+
if src[i] == '\n' {
|
|
71
|
+
seen++
|
|
72
|
+
if seen == n {
|
|
73
|
+
return i + 1
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return -1
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// countSourceLines returns the number of lines in `src`. Every `\n`
|
|
81
|
+
// terminates a line; a non-empty trailing fragment without a newline
|
|
82
|
+
// counts as one additional line. An empty source has zero lines.
|
|
83
|
+
func countSourceLines(src string) int {
|
|
84
|
+
if len(src) == 0 {
|
|
85
|
+
return 0
|
|
86
|
+
}
|
|
87
|
+
count := 0
|
|
88
|
+
for i := 0; i < len(src); i++ {
|
|
89
|
+
if src[i] == '\n' {
|
|
90
|
+
count++
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if src[len(src)-1] != '\n' {
|
|
94
|
+
count++
|
|
95
|
+
}
|
|
96
|
+
return count
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
func init() {
|
|
100
|
+
Register(maxLines{})
|
|
101
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// maxLinesPerFunction: a function whose body spans many lines is hard
|
|
2
|
+
// to scan and almost always benefits from extraction. ESLint's default
|
|
3
|
+
// is `{ max: 50 }`, which @ttsc/lint mirrors as the only built-in
|
|
4
|
+
// threshold (option-decoding is deferred). The line-span is measured
|
|
5
|
+
// between the opening and closing braces of the function's block body,
|
|
6
|
+
// inclusive, so the count reflects the real footprint a reader sees in
|
|
7
|
+
// the source — including blank lines and comments.
|
|
8
|
+
// https://eslint.org/docs/latest/rules/max-lines-per-function
|
|
9
|
+
package linthost
|
|
10
|
+
|
|
11
|
+
import (
|
|
12
|
+
"fmt"
|
|
13
|
+
|
|
14
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
15
|
+
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
// maxLinesPerFunctionLimit is the line-span ceiling. Above this value
|
|
19
|
+
// the rule fires. Mirrors the ESLint default and matches the threshold
|
|
20
|
+
// documented in the README and website MDX.
|
|
21
|
+
const maxLinesPerFunctionLimit = 50
|
|
22
|
+
|
|
23
|
+
type maxLinesPerFunction struct{}
|
|
24
|
+
|
|
25
|
+
func (maxLinesPerFunction) Name() string { return "max-lines-per-function" }
|
|
26
|
+
func (maxLinesPerFunction) Visits() []shimast.Kind {
|
|
27
|
+
return []shimast.Kind{
|
|
28
|
+
shimast.KindFunctionDeclaration,
|
|
29
|
+
shimast.KindFunctionExpression,
|
|
30
|
+
shimast.KindArrowFunction,
|
|
31
|
+
shimast.KindMethodDeclaration,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
func (maxLinesPerFunction) Check(ctx *Context, node *shimast.Node) {
|
|
35
|
+
if node == nil || ctx == nil || ctx.File == nil {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
body := node.Body()
|
|
39
|
+
if body == nil || body.Kind != shimast.KindBlock {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
startPos := shimscanner.SkipTrivia(ctx.File.Text(), body.Pos())
|
|
43
|
+
endPos := body.End()
|
|
44
|
+
if endPos > startPos {
|
|
45
|
+
endPos--
|
|
46
|
+
}
|
|
47
|
+
startLine := shimscanner.GetECMALineOfPosition(ctx.File, startPos)
|
|
48
|
+
endLine := shimscanner.GetECMALineOfPosition(ctx.File, endPos)
|
|
49
|
+
lines := endLine - startLine + 1
|
|
50
|
+
if lines > maxLinesPerFunctionLimit {
|
|
51
|
+
ctx.Report(node, fmt.Sprintf("Function has too many lines (%d). Maximum allowed is %d.", lines, maxLinesPerFunctionLimit))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
func init() {
|
|
56
|
+
Register(maxLinesPerFunction{})
|
|
57
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// maxNestedCallbacks: deeply nested anonymous functions are the
|
|
2
|
+
// classic "callback hell" shape — every new layer pushes the actual
|
|
3
|
+
// work further to the right and makes control-flow harder to follow.
|
|
4
|
+
// ESLint's default ceiling is ten levels of nesting, which @ttsc/lint
|
|
5
|
+
// mirrors as the only built-in threshold (option-decoding is deferred).
|
|
6
|
+
// https://eslint.org/docs/latest/rules/max-nested-callbacks
|
|
7
|
+
//
|
|
8
|
+
// A "callback" here is any function-expression or arrow-function node;
|
|
9
|
+
// named FunctionDeclarations are excluded from the count because the
|
|
10
|
+
// rule targets the anonymous-function nesting shape that produces
|
|
11
|
+
// callback hell, matching ESLint's behavior. Depth counts the current
|
|
12
|
+
// node plus every callback ancestor up to the enclosing source file;
|
|
13
|
+
// FunctionDeclaration boundaries are transparent because ESLint never
|
|
14
|
+
// pushes or pops the stack on them.
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import (
|
|
18
|
+
"fmt"
|
|
19
|
+
|
|
20
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
// maxNestedCallbacksLimit is the callback-nesting ceiling. Above this
|
|
24
|
+
// value the rule fires on the innermost callback. Mirrors the ESLint
|
|
25
|
+
// default of 10.
|
|
26
|
+
const maxNestedCallbacksLimit = 10
|
|
27
|
+
|
|
28
|
+
type maxNestedCallbacks struct{}
|
|
29
|
+
|
|
30
|
+
func (maxNestedCallbacks) Name() string { return "max-nested-callbacks" }
|
|
31
|
+
func (maxNestedCallbacks) Visits() []shimast.Kind {
|
|
32
|
+
return []shimast.Kind{
|
|
33
|
+
shimast.KindArrowFunction,
|
|
34
|
+
shimast.KindFunctionExpression,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
func (maxNestedCallbacks) Check(ctx *Context, node *shimast.Node) {
|
|
38
|
+
if node == nil {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
// Count this callback plus every callback ancestor up to the
|
|
42
|
+
// SourceFile. Only ArrowFunction and FunctionExpression
|
|
43
|
+
// contribute; FunctionDeclaration, methods, and accessors are
|
|
44
|
+
// transparent because ESLint never pushes or pops its callback
|
|
45
|
+
// stack on those node kinds.
|
|
46
|
+
depth := 1
|
|
47
|
+
for cur := node.Parent; cur != nil; cur = cur.Parent {
|
|
48
|
+
switch cur.Kind {
|
|
49
|
+
case shimast.KindArrowFunction, shimast.KindFunctionExpression:
|
|
50
|
+
depth++
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if depth <= maxNestedCallbacksLimit {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
ctx.Report(node, fmt.Sprintf("Too many nested callbacks (%d). Maximum allowed is %d.", depth, maxNestedCallbacksLimit))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
func init() {
|
|
60
|
+
Register(maxNestedCallbacks{})
|
|
61
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// maxParams: long parameter lists are almost always a code smell —
|
|
2
|
+
// readers cannot tell at the call site which argument means what, and
|
|
3
|
+
// the function usually wants to receive an options object instead.
|
|
4
|
+
// ESLint's default is `{ max: 3 }`, which @ttsc/lint mirrors as the
|
|
5
|
+
// only built-in threshold (option-decoding is deferred). Every
|
|
6
|
+
// function-like declaration counts: function declarations, function
|
|
7
|
+
// expressions, arrow functions, methods, accessors, and constructors.
|
|
8
|
+
// https://eslint.org/docs/latest/rules/max-params
|
|
9
|
+
package linthost
|
|
10
|
+
|
|
11
|
+
import (
|
|
12
|
+
"fmt"
|
|
13
|
+
|
|
14
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
// maxParamsLimit is the parameter-count ceiling. Above this value the
|
|
18
|
+
// rule fires. Mirrors the ESLint default and matches the threshold
|
|
19
|
+
// documented in the README and website MDX.
|
|
20
|
+
const maxParamsLimit = 3
|
|
21
|
+
|
|
22
|
+
type maxParams struct{}
|
|
23
|
+
|
|
24
|
+
func (maxParams) Name() string { return "max-params" }
|
|
25
|
+
func (maxParams) Visits() []shimast.Kind {
|
|
26
|
+
return []shimast.Kind{
|
|
27
|
+
shimast.KindFunctionDeclaration,
|
|
28
|
+
shimast.KindFunctionExpression,
|
|
29
|
+
shimast.KindArrowFunction,
|
|
30
|
+
shimast.KindMethodDeclaration,
|
|
31
|
+
shimast.KindGetAccessor,
|
|
32
|
+
shimast.KindSetAccessor,
|
|
33
|
+
shimast.KindConstructor,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
func (maxParams) Check(ctx *Context, node *shimast.Node) {
|
|
37
|
+
if node == nil {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
params := node.Parameters()
|
|
41
|
+
if len(params) <= maxParamsLimit {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
ctx.Report(node, fmt.Sprintf("Function has too many parameters (%d). Maximum allowed is %d.", len(params), maxParamsLimit))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func init() {
|
|
48
|
+
Register(maxParams{})
|
|
49
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// maxStatements: a function whose body contains too many statements is
|
|
2
|
+
// almost always doing more than one job. Splitting it into smaller
|
|
3
|
+
// helpers usually improves both readability and testability. ESLint's
|
|
4
|
+
// default is `{ max: 10 }`, which @ttsc/lint mirrors as the only
|
|
5
|
+
// built-in threshold (option-decoding is deferred). Only the function's
|
|
6
|
+
// own block-body statement list is counted — nested function-like
|
|
7
|
+
// declarations contribute exactly one statement (themselves) regardless
|
|
8
|
+
// of how many statements they internally contain.
|
|
9
|
+
// https://eslint.org/docs/latest/rules/max-statements
|
|
10
|
+
package linthost
|
|
11
|
+
|
|
12
|
+
import (
|
|
13
|
+
"fmt"
|
|
14
|
+
|
|
15
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
// maxStatementsLimit is the statement-count ceiling. Above this value
|
|
19
|
+
// the rule fires. Mirrors the ESLint default and matches the threshold
|
|
20
|
+
// documented in the README and website MDX.
|
|
21
|
+
const maxStatementsLimit = 10
|
|
22
|
+
|
|
23
|
+
type maxStatements struct{}
|
|
24
|
+
|
|
25
|
+
func (maxStatements) Name() string { return "max-statements" }
|
|
26
|
+
func (maxStatements) Visits() []shimast.Kind {
|
|
27
|
+
return []shimast.Kind{
|
|
28
|
+
shimast.KindFunctionDeclaration,
|
|
29
|
+
shimast.KindFunctionExpression,
|
|
30
|
+
shimast.KindArrowFunction,
|
|
31
|
+
shimast.KindMethodDeclaration,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
func (maxStatements) Check(ctx *Context, node *shimast.Node) {
|
|
35
|
+
if node == nil {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
body := node.Body()
|
|
39
|
+
if body == nil || body.Kind != shimast.KindBlock {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
block := body.AsBlock()
|
|
43
|
+
if block == nil || block.Statements == nil {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
count := 0
|
|
47
|
+
for _, stmt := range block.Statements.Nodes {
|
|
48
|
+
if stmt != nil {
|
|
49
|
+
count++
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if count > maxStatementsLimit {
|
|
53
|
+
ctx.Report(node, fmt.Sprintf("Function has too many statements (%d). Maximum allowed is %d.", count, maxStatementsLimit))
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
func init() {
|
|
58
|
+
Register(maxStatements{})
|
|
59
|
+
}
|
package/linthost/rules_misc.go
CHANGED
|
@@ -47,7 +47,7 @@ func (radix) Check(ctx *Context, node *shimast.Node) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
//
|
|
50
|
+
// noNewWrappers: `new String("")`, `new Number(0)`, `new Boolean(false)`
|
|
51
51
|
// build wrapper objects rarely intended.
|
|
52
52
|
// https://eslint.org/docs/latest/rules/no-new-wrappers
|
|
53
53
|
type noNewWrappers struct{}
|