@ttsc/lint 0.13.0 → 0.14.0-dev.20260528
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +948 -69
- package/lib/defaultFormat.d.ts +9 -6
- package/lib/defaultFormat.js +9 -6
- package/lib/defaultFormat.js.map +1 -1
- package/lib/index.d.ts +46 -0
- package/lib/index.js +60 -37
- 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/compile.go +33 -2
- 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 +160 -40
- package/linthost/fix.go +2 -2
- package/linthost/flags_gen.go +17 -15
- package/linthost/host.go +40 -3
- 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 +10 -4
- package/linthost/rules_vitest.go +568 -0
- package/package.json +3 -3
- package/plugin/main.go +49 -3
- package/rule/astutil/astutil.go +10 -3
- package/rule/rule.go +12 -10
- package/src/defaultFormat.ts +11 -8
- package/src/index.ts +65 -43
- 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,80 @@
|
|
|
1
|
+
// noMixedOperators flags expressions that mix operators from different
|
|
2
|
+
// precedence families without explicit parentheses around the inner
|
|
3
|
+
// expression. The classic gotcha is `a && b || c` — readers expect
|
|
4
|
+
// left-to-right grouping, but `&&` binds tighter than `||`, so the
|
|
5
|
+
// parse tree is actually `(a && b) || c`. Wrapping the inner
|
|
6
|
+
// sub-expression in parens removes the ambiguity for both the parser
|
|
7
|
+
// and the reader.
|
|
8
|
+
//
|
|
9
|
+
// The conservative baseline fires only on the highest-confusion mixes:
|
|
10
|
+
// logical mixed with a different logical, logical mixed with bitwise,
|
|
11
|
+
// and bitwise mixed with comparison. Same-operator chains (`a && b &&
|
|
12
|
+
// c`) and parenthesized inner children (`(a && b) || c`) never fire.
|
|
13
|
+
// https://eslint.org/docs/latest/rules/no-mixed-operators
|
|
14
|
+
package linthost
|
|
15
|
+
|
|
16
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
17
|
+
|
|
18
|
+
type noMixedOperators struct{}
|
|
19
|
+
|
|
20
|
+
const (
|
|
21
|
+
mixedGroupLogical = 1
|
|
22
|
+
mixedGroupBitwise = 2
|
|
23
|
+
mixedGroupComparison = 3
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
func (noMixedOperators) Name() string { return "no-mixed-operators" }
|
|
27
|
+
func (noMixedOperators) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindBinaryExpression} }
|
|
28
|
+
func (noMixedOperators) Check(ctx *Context, node *shimast.Node) {
|
|
29
|
+
expr := node.AsBinaryExpression()
|
|
30
|
+
if expr == nil || expr.OperatorToken == nil {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
parent := noMixedOperatorsGroup(expr.OperatorToken.Kind)
|
|
34
|
+
if parent == 0 {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
op := expr.OperatorToken.Kind
|
|
38
|
+
if noMixedOperatorsConflicts(parent, op, expr.Left) ||
|
|
39
|
+
noMixedOperatorsConflicts(parent, op, expr.Right) {
|
|
40
|
+
ctx.Report(node, "Unexpected mix of different operators. Wrap the inner expression in parentheses to make the grouping explicit.")
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// noMixedOperatorsConflicts returns true when `child` is an
|
|
45
|
+
// unparenthesized BinaryExpression whose operator group is confusing
|
|
46
|
+
// next to the parent group. Same operator never conflicts.
|
|
47
|
+
func noMixedOperatorsConflicts(parent int, parentOp shimast.Kind, child *shimast.Node) bool {
|
|
48
|
+
if child == nil || child.Kind != shimast.KindBinaryExpression {
|
|
49
|
+
return false
|
|
50
|
+
}
|
|
51
|
+
inner := child.AsBinaryExpression()
|
|
52
|
+
if inner == nil || inner.OperatorToken == nil || inner.OperatorToken.Kind == parentOp {
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
g := noMixedOperatorsGroup(inner.OperatorToken.Kind)
|
|
56
|
+
if g == 0 {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
if parent == mixedGroupLogical {
|
|
60
|
+
return g == mixedGroupLogical || g == mixedGroupBitwise
|
|
61
|
+
}
|
|
62
|
+
return parent == mixedGroupBitwise && (g == mixedGroupLogical || g == mixedGroupComparison)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
func noMixedOperatorsGroup(op shimast.Kind) int {
|
|
66
|
+
switch op {
|
|
67
|
+
case shimast.KindAmpersandAmpersandToken, shimast.KindBarBarToken, shimast.KindQuestionQuestionToken:
|
|
68
|
+
return mixedGroupLogical
|
|
69
|
+
case shimast.KindAmpersandToken, shimast.KindBarToken, shimast.KindCaretToken:
|
|
70
|
+
return mixedGroupBitwise
|
|
71
|
+
case shimast.KindEqualsEqualsToken, shimast.KindEqualsEqualsEqualsToken,
|
|
72
|
+
shimast.KindExclamationEqualsToken, shimast.KindExclamationEqualsEqualsToken,
|
|
73
|
+
shimast.KindLessThanToken, shimast.KindLessThanEqualsToken,
|
|
74
|
+
shimast.KindGreaterThanToken, shimast.KindGreaterThanEqualsToken:
|
|
75
|
+
return mixedGroupComparison
|
|
76
|
+
}
|
|
77
|
+
return 0
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
func init() { Register(noMixedOperators{}) }
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// noParamReassign: reassigning a function parameter inside the body of
|
|
2
|
+
// the function it belongs to. Mutating the binding makes the declared
|
|
3
|
+
// name stop pointing at the caller's argument and is the usual ESLint
|
|
4
|
+
// baseline of `no-param-reassign` — without the `props: true` extension
|
|
5
|
+
// that would also flag `param.foo = …`.
|
|
6
|
+
//
|
|
7
|
+
// Conservative scope tracking: collect simple-identifier parameter
|
|
8
|
+
// names, walk the body until a nested function-like introduces a fresh
|
|
9
|
+
// scope, and flag `name = …` / `name op= …` / `++name` / `name--` at
|
|
10
|
+
// any depth in between. A local `const name = 1` that shadows a
|
|
11
|
+
// parameter name will produce a false positive in v1 — proper scope
|
|
12
|
+
// tracking needs the resolver, which the AST-only baseline avoids.
|
|
13
|
+
// Destructured parameter bindings are skipped for the same reason.
|
|
14
|
+
// https://eslint.org/docs/latest/rules/no-param-reassign
|
|
15
|
+
package linthost
|
|
16
|
+
|
|
17
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
|
|
19
|
+
type noParamReassign struct{}
|
|
20
|
+
|
|
21
|
+
func (noParamReassign) Name() string { return "no-param-reassign" }
|
|
22
|
+
func (noParamReassign) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{
|
|
24
|
+
shimast.KindFunctionDeclaration,
|
|
25
|
+
shimast.KindFunctionExpression,
|
|
26
|
+
shimast.KindArrowFunction,
|
|
27
|
+
shimast.KindMethodDeclaration,
|
|
28
|
+
shimast.KindConstructor,
|
|
29
|
+
shimast.KindGetAccessor,
|
|
30
|
+
shimast.KindSetAccessor,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
func (noParamReassign) Check(ctx *Context, node *shimast.Node) {
|
|
34
|
+
body := node.Body()
|
|
35
|
+
if body == nil {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
names := map[string]bool{}
|
|
39
|
+
for _, p := range node.Parameters() {
|
|
40
|
+
if decl := p.AsParameterDeclaration(); decl != nil {
|
|
41
|
+
if name := identifierText(decl.Name()); name != "" {
|
|
42
|
+
names[name] = true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if len(names) == 0 {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
walkParamReassignBody(body, names, func(target *shimast.Node) {
|
|
50
|
+
ctx.Report(target, "Assignment to function parameter.")
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// walkParamReassignBody visits every assignment-like write in `root`
|
|
55
|
+
// without crossing nested function-like scopes. The target identifier
|
|
56
|
+
// must be a bare name in `names` for `report` to fire.
|
|
57
|
+
func walkParamReassignBody(root *shimast.Node, names map[string]bool, report func(*shimast.Node)) {
|
|
58
|
+
if root == nil {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
var walk func(*shimast.Node)
|
|
62
|
+
hits := func(operand *shimast.Node) bool {
|
|
63
|
+
name := identifierText(stripParens(operand))
|
|
64
|
+
return name != "" && names[name]
|
|
65
|
+
}
|
|
66
|
+
walk = func(node *shimast.Node) {
|
|
67
|
+
if node == nil || (node != root && isFunctionLikeKind(node)) {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
switch node.Kind {
|
|
71
|
+
case shimast.KindBinaryExpression:
|
|
72
|
+
expr := node.AsBinaryExpression()
|
|
73
|
+
if expr != nil && expr.OperatorToken != nil &&
|
|
74
|
+
isAssignmentOperator(expr.OperatorToken.Kind) && hits(expr.Left) {
|
|
75
|
+
report(node)
|
|
76
|
+
}
|
|
77
|
+
case shimast.KindPrefixUnaryExpression:
|
|
78
|
+
pre := node.AsPrefixUnaryExpression()
|
|
79
|
+
if pre != nil && (pre.Operator == shimast.KindPlusPlusToken || pre.Operator == shimast.KindMinusMinusToken) && hits(pre.Operand) {
|
|
80
|
+
report(node)
|
|
81
|
+
}
|
|
82
|
+
case shimast.KindPostfixUnaryExpression:
|
|
83
|
+
post := node.AsPostfixUnaryExpression()
|
|
84
|
+
if post != nil && (post.Operator == shimast.KindPlusPlusToken || post.Operator == shimast.KindMinusMinusToken) && hits(post.Operand) {
|
|
85
|
+
report(node)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
node.ForEachChild(func(child *shimast.Node) bool {
|
|
89
|
+
walk(child)
|
|
90
|
+
return false
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
walk(root)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
func init() {
|
|
97
|
+
Register(noParamReassign{})
|
|
98
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
package linthost
|
|
2
|
+
|
|
3
|
+
import shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
4
|
+
|
|
5
|
+
// noRedeclare: reject declaring the same binding more than once in the
|
|
6
|
+
// same scope. The second declaration silently overwrites the first;
|
|
7
|
+
// shadowing the binding in a nested scope is left alone because the
|
|
8
|
+
// inner declaration introduces a fresh binding.
|
|
9
|
+
// https://eslint.org/docs/latest/rules/no-redeclare
|
|
10
|
+
//
|
|
11
|
+
// Each visited scope (source file, module block, or block) builds a
|
|
12
|
+
// `name -> first node` map by walking only the immediate statement
|
|
13
|
+
// list — nested blocks introduce their own scopes and are processed by
|
|
14
|
+
// a separate visit. The exception is `var`: it hoists to the nearest
|
|
15
|
+
// function-like container, so a function-scope visit also descends
|
|
16
|
+
// past inner blocks to pull every nested `var` into the function
|
|
17
|
+
// scope. Function overload signatures share the implementation's name
|
|
18
|
+
// by design and are skipped, mirroring ESLint's behavior.
|
|
19
|
+
type noRedeclare struct{}
|
|
20
|
+
|
|
21
|
+
func (noRedeclare) Name() string { return "no-redeclare" }
|
|
22
|
+
func (noRedeclare) Visits() []shimast.Kind {
|
|
23
|
+
return []shimast.Kind{shimast.KindSourceFile, shimast.KindModuleBlock, shimast.KindBlock}
|
|
24
|
+
}
|
|
25
|
+
func (noRedeclare) Check(ctx *Context, node *shimast.Node) {
|
|
26
|
+
statements := scopeStatements(node)
|
|
27
|
+
if statements == nil {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
isFunctionScope := isFunctionScopeContainer(node)
|
|
31
|
+
seen := map[string]*shimast.Node{}
|
|
32
|
+
|
|
33
|
+
report := func(name string, declNode *shimast.Node) {
|
|
34
|
+
if prior, exists := seen[name]; exists {
|
|
35
|
+
_ = prior
|
|
36
|
+
ctx.Report(declNode, "'"+name+"' is already defined.")
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
seen[name] = declNode
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// A function-body block inherits its parameters as the outermost
|
|
43
|
+
// bindings of the function scope. Pre-seed the seen map so a later
|
|
44
|
+
// `var` or function declaration with the same name reports.
|
|
45
|
+
if isFunctionScope && node.Kind == shimast.KindBlock && node.Parent != nil && isFunctionLikeKind(node.Parent) {
|
|
46
|
+
for _, name := range parameterBindingNames(node.Parent) {
|
|
47
|
+
if name != "" {
|
|
48
|
+
seen[name] = node.Parent
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Pass 1: block-scoped declarations from the immediate statement
|
|
54
|
+
// list. `var` statements only contribute here in function-scope
|
|
55
|
+
// containers — inside a plain block they belong to the enclosing
|
|
56
|
+
// function scope and are reported there instead.
|
|
57
|
+
for _, stmt := range statements {
|
|
58
|
+
if stmt == nil {
|
|
59
|
+
continue
|
|
60
|
+
}
|
|
61
|
+
if stmt.Kind == shimast.KindVariableStatement && !isFunctionScope {
|
|
62
|
+
vs := stmt.AsVariableStatement()
|
|
63
|
+
if vs != nil && vs.DeclarationList != nil && shimast.IsVar(vs.DeclarationList) {
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
for _, name := range immediateDeclarationNames(stmt) {
|
|
68
|
+
if name != "" {
|
|
69
|
+
report(name, stmt)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Pass 2: var hoisting. Function scopes (source file, module block,
|
|
75
|
+
// function body) also collect every `var` declared in nested blocks
|
|
76
|
+
// up to the next function-like boundary. Top-level `var` statements
|
|
77
|
+
// are already reported in Pass 1, so this pass descends into each
|
|
78
|
+
// statement's children rather than visiting the statement itself.
|
|
79
|
+
if isFunctionScope {
|
|
80
|
+
for _, stmt := range statements {
|
|
81
|
+
if stmt == nil || stmt.Kind == shimast.KindVariableStatement {
|
|
82
|
+
continue
|
|
83
|
+
}
|
|
84
|
+
collectHoistedVarsInto(stmt, func(name string, declNode *shimast.Node) {
|
|
85
|
+
if name != "" {
|
|
86
|
+
report(name, declNode)
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// scopeStatements returns the direct statement list of a scope-defining
|
|
94
|
+
// container (source file, module block, or block). Returns nil for any
|
|
95
|
+
// other node kind so the caller can bail without further checks.
|
|
96
|
+
func scopeStatements(node *shimast.Node) []*shimast.Node {
|
|
97
|
+
switch node.Kind {
|
|
98
|
+
case shimast.KindSourceFile:
|
|
99
|
+
file := node.AsSourceFile()
|
|
100
|
+
if file != nil && file.Statements != nil {
|
|
101
|
+
return file.Statements.Nodes
|
|
102
|
+
}
|
|
103
|
+
case shimast.KindModuleBlock:
|
|
104
|
+
mb := node.AsModuleBlock()
|
|
105
|
+
if mb != nil && mb.Statements != nil {
|
|
106
|
+
return mb.Statements.Nodes
|
|
107
|
+
}
|
|
108
|
+
case shimast.KindBlock:
|
|
109
|
+
block := node.AsBlock()
|
|
110
|
+
if block != nil && block.Statements != nil {
|
|
111
|
+
return block.Statements.Nodes
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return nil
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// isFunctionScopeContainer reports whether node is a scope into which
|
|
118
|
+
// `var` declarations hoist: the source file, a module block, or a
|
|
119
|
+
// block that forms the body of a function-like declaration.
|
|
120
|
+
func isFunctionScopeContainer(node *shimast.Node) bool {
|
|
121
|
+
switch node.Kind {
|
|
122
|
+
case shimast.KindSourceFile, shimast.KindModuleBlock:
|
|
123
|
+
return true
|
|
124
|
+
case shimast.KindBlock:
|
|
125
|
+
return node.Parent != nil && isFunctionLikeKind(node.Parent)
|
|
126
|
+
}
|
|
127
|
+
return false
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// immediateDeclarationNames returns every binding name introduced by a
|
|
131
|
+
// single top-level statement of a scope. Variable statements contribute
|
|
132
|
+
// their identifier names regardless of `var`/`let`/`const` keyword;
|
|
133
|
+
// function and class declarations contribute their own name. Overload
|
|
134
|
+
// signatures (`function f(): void;` with no body) are skipped because
|
|
135
|
+
// they intentionally repeat the implementation's name. Ambient
|
|
136
|
+
// declarations (`declare var x: …`, `declare function f(): …`) are
|
|
137
|
+
// also skipped — TypeScript merges them with concrete declarations of
|
|
138
|
+
// the same name by design.
|
|
139
|
+
func immediateDeclarationNames(stmt *shimast.Node) []string {
|
|
140
|
+
if stmt == nil {
|
|
141
|
+
return nil
|
|
142
|
+
}
|
|
143
|
+
if stmt.ModifierFlags()&shimast.ModifierFlagsAmbient != 0 {
|
|
144
|
+
return nil
|
|
145
|
+
}
|
|
146
|
+
switch stmt.Kind {
|
|
147
|
+
case shimast.KindVariableStatement:
|
|
148
|
+
return variableStatementBindingNames(stmt)
|
|
149
|
+
case shimast.KindFunctionDeclaration:
|
|
150
|
+
decl := stmt.AsFunctionDeclaration()
|
|
151
|
+
if decl == nil || decl.Body == nil {
|
|
152
|
+
return nil
|
|
153
|
+
}
|
|
154
|
+
if name := identifierText(decl.Name()); name != "" {
|
|
155
|
+
return []string{name}
|
|
156
|
+
}
|
|
157
|
+
case shimast.KindClassDeclaration:
|
|
158
|
+
decl := stmt.AsClassDeclaration()
|
|
159
|
+
if decl == nil {
|
|
160
|
+
return nil
|
|
161
|
+
}
|
|
162
|
+
if name := identifierText(decl.Name()); name != "" {
|
|
163
|
+
return []string{name}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return nil
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// variableStatementBindingNames returns the identifier name of every
|
|
170
|
+
// declaration in a `var`/`let`/`const` statement. Destructuring
|
|
171
|
+
// patterns (`const { a } = obj`) are skipped — the rule cannot reason
|
|
172
|
+
// about pattern equality without scope resolution, so the conservative
|
|
173
|
+
// baseline only handles plain identifier bindings.
|
|
174
|
+
func variableStatementBindingNames(stmt *shimast.Node) []string {
|
|
175
|
+
vs := stmt.AsVariableStatement()
|
|
176
|
+
if vs == nil || vs.DeclarationList == nil {
|
|
177
|
+
return nil
|
|
178
|
+
}
|
|
179
|
+
list := vs.DeclarationList.AsVariableDeclarationList()
|
|
180
|
+
if list == nil || list.Declarations == nil {
|
|
181
|
+
return nil
|
|
182
|
+
}
|
|
183
|
+
var names []string
|
|
184
|
+
for _, decl := range list.Declarations.Nodes {
|
|
185
|
+
if decl == nil {
|
|
186
|
+
continue
|
|
187
|
+
}
|
|
188
|
+
v := decl.AsVariableDeclaration()
|
|
189
|
+
if v == nil {
|
|
190
|
+
continue
|
|
191
|
+
}
|
|
192
|
+
if name := identifierText(v.Name()); name != "" {
|
|
193
|
+
names = append(names, name)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return names
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// parameterBindingNames returns the identifier name of every plain
|
|
200
|
+
// parameter on a function-like node. Destructured parameters are
|
|
201
|
+
// skipped for the same reason as variableStatementBindingNames.
|
|
202
|
+
func parameterBindingNames(fn *shimast.Node) []string {
|
|
203
|
+
params := fn.Parameters()
|
|
204
|
+
if len(params) == 0 {
|
|
205
|
+
return nil
|
|
206
|
+
}
|
|
207
|
+
var names []string
|
|
208
|
+
for _, param := range params {
|
|
209
|
+
if param == nil {
|
|
210
|
+
continue
|
|
211
|
+
}
|
|
212
|
+
decl := param.AsParameterDeclaration()
|
|
213
|
+
if decl == nil {
|
|
214
|
+
continue
|
|
215
|
+
}
|
|
216
|
+
if name := identifierText(decl.Name()); name != "" {
|
|
217
|
+
names = append(names, name)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return names
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// collectHoistedVarsInto walks every descendant of node up to (but
|
|
224
|
+
// not into) a nested function-like boundary, invoking yield for each
|
|
225
|
+
// `var` binding it discovers. Both `var` statements and `for (var i …)`
|
|
226
|
+
// declaration lists contribute; the former carries a VariableStatement
|
|
227
|
+
// kind so the surrounding statement reports, the latter carries a bare
|
|
228
|
+
// VariableDeclarationList so each individual VariableDeclaration node
|
|
229
|
+
// reports. Plain identifier bindings only — destructuring patterns are
|
|
230
|
+
// skipped to keep the rule reliable.
|
|
231
|
+
func collectHoistedVarsInto(node *shimast.Node, yield func(string, *shimast.Node)) {
|
|
232
|
+
if node == nil || isFunctionLikeKind(node) {
|
|
233
|
+
return
|
|
234
|
+
}
|
|
235
|
+
if node.Kind == shimast.KindVariableStatement {
|
|
236
|
+
vs := node.AsVariableStatement()
|
|
237
|
+
if vs != nil && vs.DeclarationList != nil && shimast.IsVar(vs.DeclarationList) {
|
|
238
|
+
for _, name := range variableStatementBindingNames(node) {
|
|
239
|
+
yield(name, node)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return
|
|
243
|
+
}
|
|
244
|
+
if node.Kind == shimast.KindVariableDeclarationList {
|
|
245
|
+
list := node.AsVariableDeclarationList()
|
|
246
|
+
if list != nil && shimast.IsVar(node) && list.Declarations != nil {
|
|
247
|
+
for _, decl := range list.Declarations.Nodes {
|
|
248
|
+
if decl == nil {
|
|
249
|
+
continue
|
|
250
|
+
}
|
|
251
|
+
v := decl.AsVariableDeclaration()
|
|
252
|
+
if v == nil {
|
|
253
|
+
continue
|
|
254
|
+
}
|
|
255
|
+
if name := identifierText(v.Name()); name != "" {
|
|
256
|
+
yield(name, decl)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
node.ForEachChild(func(child *shimast.Node) bool {
|
|
263
|
+
collectHoistedVarsInto(child, yield)
|
|
264
|
+
return false
|
|
265
|
+
})
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
func init() {
|
|
269
|
+
Register(noRedeclare{})
|
|
270
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// noRestrictedImports reports an `import` (or `export … from`) whose
|
|
2
|
+
// module specifier matches a project-configured deny list. The rule is
|
|
3
|
+
// the policy hammer for forcing a module boundary: a package that has
|
|
4
|
+
// been renamed, a workspace internal that should not leak, or a heavy
|
|
5
|
+
// dependency that the project wants to discourage all share the same
|
|
6
|
+
// shape — flag the import at its source so the offending line is the
|
|
7
|
+
// one the developer fixes.
|
|
8
|
+
//
|
|
9
|
+
// Configuration shape: a `paths` array of bare module specifiers to
|
|
10
|
+
// flag, exact-match only. An empty (or missing) list is a no-op — the
|
|
11
|
+
// rule contributes no findings until the project lists something to
|
|
12
|
+
// restrict. The native engine's RuleConfig path does not carry options
|
|
13
|
+
// to the rule, so the Go unit test exercises the rule via a hard-coded
|
|
14
|
+
// default deny list (`lodash`, `underscore`) that fires whenever the
|
|
15
|
+
// rule is enabled with no options blob.
|
|
16
|
+
// https://eslint.org/docs/latest/rules/no-restricted-imports
|
|
17
|
+
package linthost
|
|
18
|
+
|
|
19
|
+
import (
|
|
20
|
+
"encoding/json"
|
|
21
|
+
|
|
22
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
type noRestrictedImports struct{}
|
|
26
|
+
|
|
27
|
+
// noRestrictedImportsOptions decodes the `paths` array from a user
|
|
28
|
+
// `[severity, options]` tuple. Anything else on the blob is ignored so
|
|
29
|
+
// future ESLint-compatible keys (e.g. `patterns`) can be layered in
|
|
30
|
+
// without changing existing configs.
|
|
31
|
+
type noRestrictedImportsOptions struct {
|
|
32
|
+
Paths []string `json:"paths"`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// hardCodedRestrictedImports is the default deny list used when the
|
|
36
|
+
// rule is enabled without an options blob. The Go-side test harness
|
|
37
|
+
// exercises the rule through `RuleConfig` (severity-only, no options),
|
|
38
|
+
// so the rule needs a deterministic non-empty default to be testable
|
|
39
|
+
// at the AST layer at all. The choice mirrors a common "don't lean on
|
|
40
|
+
// utility-belt libraries" lint setup in real projects.
|
|
41
|
+
var hardCodedRestrictedImports = []string{"lodash", "underscore"}
|
|
42
|
+
|
|
43
|
+
func (noRestrictedImports) Name() string { return "no-restricted-imports" }
|
|
44
|
+
func (noRestrictedImports) Visits() []shimast.Kind {
|
|
45
|
+
return []shimast.Kind{
|
|
46
|
+
shimast.KindImportDeclaration,
|
|
47
|
+
shimast.KindExportDeclaration,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
func (noRestrictedImports) Check(ctx *Context, node *shimast.Node) {
|
|
51
|
+
specifierNode := moduleSpecifierOf(node)
|
|
52
|
+
if specifierNode == nil {
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
specifier := stringLiteralText(specifierNode)
|
|
56
|
+
if specifier == "" {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
denied := resolveNoRestrictedImportsPaths(ctx)
|
|
60
|
+
for _, target := range denied {
|
|
61
|
+
if specifier == target {
|
|
62
|
+
ctx.Report(specifierNode, "'"+specifier+"' import is restricted from being used.")
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// moduleSpecifierOf returns the `from "…"` string-literal node of the
|
|
69
|
+
// import / re-export declaration. `export { x }` (no `from`) and
|
|
70
|
+
// every other shape returns nil so the caller short-circuits.
|
|
71
|
+
func moduleSpecifierOf(node *shimast.Node) *shimast.Node {
|
|
72
|
+
if node == nil {
|
|
73
|
+
return nil
|
|
74
|
+
}
|
|
75
|
+
switch node.Kind {
|
|
76
|
+
case shimast.KindImportDeclaration:
|
|
77
|
+
if imp := node.AsImportDeclaration(); imp != nil {
|
|
78
|
+
return imp.ModuleSpecifier
|
|
79
|
+
}
|
|
80
|
+
case shimast.KindExportDeclaration:
|
|
81
|
+
if exp := node.AsExportDeclaration(); exp != nil {
|
|
82
|
+
return exp.ModuleSpecifier
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return nil
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// resolveNoRestrictedImportsPaths returns the active deny list for the
|
|
89
|
+
// firing context. A `paths` array on the user's options blob wins; an
|
|
90
|
+
// empty / missing blob falls back to `hardCodedRestrictedImports` so
|
|
91
|
+
// the AST-layer test fires deterministically.
|
|
92
|
+
func resolveNoRestrictedImportsPaths(ctx *Context) []string {
|
|
93
|
+
if ctx == nil || len(ctx.Options) == 0 {
|
|
94
|
+
return hardCodedRestrictedImports
|
|
95
|
+
}
|
|
96
|
+
var opts noRestrictedImportsOptions
|
|
97
|
+
if err := json.Unmarshal(ctx.Options, &opts); err != nil || len(opts.Paths) == 0 {
|
|
98
|
+
return hardCodedRestrictedImports
|
|
99
|
+
}
|
|
100
|
+
return opts.Paths
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
func init() {
|
|
104
|
+
Register(noRestrictedImports{})
|
|
105
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// noRestrictedSyntax: a project-level escape hatch that lets a team
|
|
2
|
+
// ban specific AST node kinds outright. Upstream ESLint accepts an
|
|
3
|
+
// arbitrary selector list and a per-entry message; without the
|
|
4
|
+
// rule-options plumbing, this baseline ships a fixed default set that
|
|
5
|
+
// covers the two syntactic constructs almost every modern TypeScript
|
|
6
|
+
// project forbids: `with` (replaced by destructuring / explicit access
|
|
7
|
+
// long ago) and labeled statements (used only to bridge complex
|
|
8
|
+
// nested loops, which are themselves better refactored). The full
|
|
9
|
+
// configurable surface is deferred — projects that need a custom
|
|
10
|
+
// denylist can stack additional rules until option decoding lands.
|
|
11
|
+
// https://eslint.org/docs/latest/rules/no-restricted-syntax
|
|
12
|
+
package linthost
|
|
13
|
+
|
|
14
|
+
import (
|
|
15
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
// noRestrictedSyntaxDefault is the built-in denylist surfaced when no
|
|
19
|
+
// config is supplied. Each entry pairs a banned node kind with the
|
|
20
|
+
// short, actionable message reported at the offending node.
|
|
21
|
+
var noRestrictedSyntaxDefault = map[shimast.Kind]string{
|
|
22
|
+
shimast.KindWithStatement: "`with` statements are restricted — use explicit property access instead.",
|
|
23
|
+
shimast.KindLabeledStatement: "Labeled statements are restricted — refactor the surrounding control flow instead.",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type noRestrictedSyntax struct{}
|
|
27
|
+
|
|
28
|
+
func (noRestrictedSyntax) Name() string { return "no-restricted-syntax" }
|
|
29
|
+
func (noRestrictedSyntax) Visits() []shimast.Kind {
|
|
30
|
+
kinds := make([]shimast.Kind, 0, len(noRestrictedSyntaxDefault))
|
|
31
|
+
for kind := range noRestrictedSyntaxDefault {
|
|
32
|
+
kinds = append(kinds, kind)
|
|
33
|
+
}
|
|
34
|
+
return kinds
|
|
35
|
+
}
|
|
36
|
+
func (noRestrictedSyntax) Check(ctx *Context, node *shimast.Node) {
|
|
37
|
+
if node == nil {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
message, banned := noRestrictedSyntaxDefault[node.Kind]
|
|
41
|
+
if !banned {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
ctx.Report(node, message)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func init() {
|
|
48
|
+
Register(noRestrictedSyntax{})
|
|
49
|
+
}
|