@ttsc/lint 0.13.0 → 0.14.0-dev.20250530.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +955 -85
- package/lib/defaultFormat.d.ts +15 -8
- package/lib/defaultFormat.js +15 -8
- package/lib/defaultFormat.js.map +1 -1
- package/lib/index.d.ts +46 -0
- package/lib/index.js +60 -37
- package/lib/index.js.map +1 -1
- package/lib/structures/ITtscLintConfig.d.ts +12 -6
- package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
- package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
- package/lib/structures/TtscLintRuleSetting.js.map +1 -0
- package/lib/structures/format/ITtscLintFormat.d.ts +128 -0
- package/lib/structures/{TtscLintRuleMap.js → format/ITtscLintFormat.js} +1 -1
- package/lib/structures/format/ITtscLintFormat.js.map +1 -0
- package/lib/structures/format/ITtscLintFormatJsDoc.d.ts +17 -0
- package/lib/structures/{ITtscLintFormatConfig.js → format/ITtscLintFormatJsDoc.js} +1 -1
- package/lib/structures/format/ITtscLintFormatJsDoc.js.map +1 -0
- package/lib/structures/format/ITtscLintFormatSortImports.d.ts +54 -0
- package/lib/structures/format/ITtscLintFormatSortImports.js +3 -0
- package/lib/structures/format/ITtscLintFormatSortImports.js.map +1 -0
- package/lib/structures/format/index.d.ts +3 -0
- package/lib/structures/format/index.js +20 -0
- package/lib/structures/format/index.js.map +1 -0
- package/lib/structures/index.d.ts +3 -4
- package/lib/structures/index.js +3 -4
- package/lib/structures/index.js.map +1 -1
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +95 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +13 -0
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +75 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
- package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintContributorRules.d.ts +16 -0
- package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
- package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintCoreRules.d.ts +1229 -0
- package/lib/structures/rules/ITtscLintCoreRules.js +3 -0
- package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintCypressRules.d.ts +125 -0
- package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
- package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +154 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +162 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
- package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJestRules.d.ts +190 -0
- package/lib/structures/rules/ITtscLintJestRules.js +3 -0
- package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJsdocRules.d.ts +133 -0
- package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
- package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +294 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
- package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintNextjsRules.d.ts +180 -0
- package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
- package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +312 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
- package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintPromiseRules.d.ts +179 -0
- package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
- package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +49 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
- package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +37 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js +11 -0
- package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintReactRules.d.ts +276 -0
- package/lib/structures/rules/ITtscLintReactRules.js +3 -0
- package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintRegexpRules.d.ts +182 -0
- package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
- package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +65 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
- package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
- package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
- package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
- package/lib/structures/rules/ITtscLintRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintSecurityRules.d.ts +141 -0
- package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
- package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintSolidRules.d.ts +178 -0
- package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
- package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +20 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintStorybookRules.d.ts +165 -0
- package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
- package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +88 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
- package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +21 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +293 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
- package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1074 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
- package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
- package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
- package/lib/structures/rules/ITtscLintVitestRules.d.ts +133 -0
- package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
- package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
- package/lib/structures/rules/index.d.ts +31 -0
- package/lib/structures/rules/index.js +48 -0
- package/lib/structures/rules/index.js.map +1 -0
- package/linthost/ast_helpers.go +30 -5
- package/linthost/compile.go +33 -2
- package/linthost/config.go +118 -71
- package/linthost/config_format.go +270 -104
- package/linthost/directives.go +67 -25
- package/linthost/dispatch.go +14 -3
- package/linthost/engine.go +160 -40
- package/linthost/fix.go +10 -3
- package/linthost/flags_gen.go +17 -15
- package/linthost/format.go +222 -25
- package/linthost/format_editor_settings.go +262 -0
- package/linthost/host.go +40 -3
- package/linthost/lsp.go +898 -0
- package/linthost/print_dispatch.go +5 -2
- package/linthost/print_engine.go +5 -5
- package/linthost/print_nodes_call.go +149 -67
- package/linthost/print_nodes_function.go +27 -2
- package/linthost/print_nodes_list.go +40 -5
- package/linthost/print_nodes_object.go +1 -1
- package/linthost/print_nodes_ternary.go +86 -0
- package/linthost/rule_names.go +14 -0
- package/linthost/rules_arrays.go +2 -2
- package/linthost/rules_boundaries.go +532 -0
- package/linthost/rules_camelcase.go +133 -0
- package/linthost/rules_complexity.go +95 -0
- package/linthost/rules_consistent_return.go +130 -0
- package/linthost/rules_console.go +1 -1
- package/linthost/rules_core_extra.go +739 -0
- package/linthost/rules_curly.go +70 -0
- package/linthost/rules_cypress.go +608 -0
- package/linthost/rules_debugger.go +2 -2
- package/linthost/rules_default_case.go +39 -0
- package/linthost/rules_default_case_last.go +46 -0
- package/linthost/rules_dupes.go +3 -3
- package/linthost/rules_empty.go +3 -3
- package/linthost/rules_escape.go +44 -24
- package/linthost/rules_eval.go +2 -2
- package/linthost/rules_finally.go +2 -2
- package/linthost/rules_format_arrow_parens.go +167 -0
- package/linthost/rules_format_bracket_spacing.go +117 -0
- package/linthost/rules_format_clause_join.go +172 -0
- package/linthost/rules_format_declaration_header.go +595 -0
- package/linthost/rules_format_indent.go +372 -0
- package/linthost/rules_format_jsdoc.go +5 -5
- package/linthost/rules_format_orphan_semi.go +106 -0
- package/linthost/rules_format_parameter_properties.go +175 -0
- package/linthost/rules_format_print_width.go +66 -55
- package/linthost/rules_format_quote_props.go +169 -0
- package/linthost/rules_format_quotes.go +76 -30
- package/linthost/rules_format_semi.go +186 -11
- package/linthost/rules_format_sort_imports.go +437 -118
- package/linthost/rules_format_statement_split.go +343 -0
- package/linthost/rules_format_ternary_nullish_parens.go +77 -0
- package/linthost/rules_format_trailing_comma.go +22 -3
- package/linthost/rules_format_whitespace.go +336 -0
- package/linthost/rules_functional.go +967 -0
- package/linthost/rules_gap.go +24 -45
- package/linthost/rules_grouped_accessor_pairs.go +87 -0
- package/linthost/rules_guard_for_in.go +198 -0
- package/linthost/rules_id_length.go +77 -0
- package/linthost/rules_imports.go +70 -2
- package/linthost/rules_init_declarations.go +53 -0
- package/linthost/rules_jest.go +618 -0
- package/linthost/rules_jsdoc.go +502 -0
- package/linthost/rules_jsx_a11y.go +1264 -0
- package/linthost/rules_logic.go +12 -12
- package/linthost/rules_loops.go +1 -1
- package/linthost/rules_max_classes_per_file.go +58 -0
- package/linthost/rules_max_depth.go +83 -0
- package/linthost/rules_max_lines.go +101 -0
- package/linthost/rules_max_lines_per_function.go +57 -0
- package/linthost/rules_max_nested_callbacks.go +61 -0
- package/linthost/rules_max_params.go +49 -0
- package/linthost/rules_max_statements.go +59 -0
- package/linthost/rules_misc.go +1 -1
- package/linthost/rules_nextjs.go +697 -0
- package/linthost/rules_no_else_return.go +75 -0
- package/linthost/rules_no_empty_named_blocks.go +91 -0
- package/linthost/rules_no_extend_native.go +51 -0
- package/linthost/rules_no_import_assign.go +140 -0
- package/linthost/rules_no_invalid_this.go +52 -0
- package/linthost/rules_no_loop_func.go +85 -0
- package/linthost/rules_no_magic_numbers.go +123 -0
- package/linthost/rules_no_mixed_operators.go +80 -0
- package/linthost/rules_no_param_reassign.go +98 -0
- package/linthost/rules_no_redeclare.go +270 -0
- package/linthost/rules_no_restricted_imports.go +105 -0
- package/linthost/rules_no_restricted_syntax.go +49 -0
- package/linthost/rules_no_shadow.go +147 -0
- package/linthost/rules_no_unreachable.go +77 -0
- package/linthost/rules_no_useless_assignment.go +120 -0
- package/linthost/rules_no_useless_constructor.go +245 -0
- package/linthost/rules_no_useless_return.go +51 -0
- package/linthost/rules_params.go +1 -1
- package/linthost/rules_playwright.go +788 -0
- package/linthost/rules_prefer_arrow_callback.go +124 -0
- package/linthost/rules_prefer_destructuring.go +98 -0
- package/linthost/rules_prefer_named_capture_group.go +129 -0
- package/linthost/rules_prefer_rest_params.go +94 -0
- package/linthost/rules_problems.go +41 -30
- package/linthost/rules_promise.go +1057 -2
- package/linthost/rules_protos.go +2 -2
- package/linthost/rules_react.go +773 -0
- package/linthost/rules_react_extras.go +227 -0
- package/linthost/rules_react_hooks.go +848 -0
- package/linthost/rules_react_perf.go +293 -0
- package/linthost/rules_react_refresh.go +583 -0
- package/linthost/rules_regexp.go +410 -0
- package/linthost/rules_security.go +830 -0
- package/linthost/rules_self.go +2 -2
- package/linthost/rules_solid.go +1073 -0
- package/linthost/rules_sort_imports.go +69 -0
- package/linthost/rules_sort_keys.go +134 -0
- package/linthost/rules_storybook.go +1176 -0
- package/linthost/rules_strings.go +4 -4
- package/linthost/rules_suggestions.go +38 -38
- package/linthost/rules_tanstack_query.go +844 -0
- package/linthost/rules_testing_library.go +1204 -0
- package/linthost/rules_throw.go +1 -1
- package/linthost/rules_ts.go +19 -19
- package/linthost/rules_ts_async.go +399 -0
- package/linthost/rules_ts_class_literal_property_style.go +115 -0
- package/linthost/rules_ts_consistent_type_exports.go +256 -0
- package/linthost/rules_ts_explicit_function_return_type.go +67 -0
- package/linthost/rules_ts_extra.go +159 -36
- package/linthost/rules_ts_no_base_to_string.go +218 -0
- package/linthost/rules_ts_no_confusing_void.go +72 -0
- package/linthost/rules_ts_no_deprecated.go +195 -0
- package/linthost/rules_ts_no_for_in_array.go +84 -0
- package/linthost/rules_ts_no_magic_numbers.go +124 -0
- package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
- package/linthost/rules_ts_no_misused_spread.go +104 -0
- package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
- package/linthost/rules_ts_no_restricted_types.go +62 -0
- package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
- package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
- package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
- package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
- package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
- package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
- package/linthost/rules_ts_no_unsafe_argument.go +82 -0
- package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
- package/linthost/rules_ts_no_unsafe_call.go +82 -0
- package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
- package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
- package/linthost/rules_ts_no_unsafe_return.go +126 -0
- package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
- package/linthost/rules_ts_no_useless_constructor.go +52 -0
- package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
- package/linthost/rules_ts_parameter_properties.go +38 -0
- package/linthost/rules_ts_prefer_find.go +178 -0
- package/linthost/rules_ts_prefer_includes.go +255 -0
- package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
- package/linthost/rules_ts_prefer_optional_chain.go +228 -0
- package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
- package/linthost/rules_ts_prefer_readonly.go +73 -0
- package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
- package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
- package/linthost/rules_ts_prefer_return_this_type.go +135 -0
- package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
- package/linthost/rules_ts_promise_function_async.go +77 -0
- package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
- package/linthost/rules_ts_require_array_sort_compare.go +96 -0
- package/linthost/rules_ts_restrict_plus_operands.go +127 -0
- package/linthost/rules_ts_restrict_template_expressions.go +95 -0
- package/linthost/rules_ts_simple.go +387 -0
- package/linthost/rules_ts_sort_type_constituents.go +144 -0
- package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
- package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
- package/linthost/rules_ts_unbound_method.go +126 -0
- package/linthost/rules_tsdoc.go +136 -0
- package/linthost/rules_unicorn_better_regex.go +27 -0
- package/linthost/rules_unicorn_catch_error_name.go +46 -0
- package/linthost/rules_unicorn_consistent_assert.go +47 -0
- package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
- package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
- package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
- package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
- package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
- package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
- package/linthost/rules_unicorn_custom_error_definition.go +138 -0
- package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
- package/linthost/rules_unicorn_error_message.go +64 -0
- package/linthost/rules_unicorn_escape_case.go +51 -0
- package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
- package/linthost/rules_unicorn_explicit_length_check.go +88 -0
- package/linthost/rules_unicorn_filename_case.go +29 -0
- package/linthost/rules_unicorn_import_style.go +28 -0
- package/linthost/rules_unicorn_isolated_functions.go +29 -0
- package/linthost/rules_unicorn_new_for_builtins.go +87 -0
- package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
- package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
- package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
- package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
- package/linthost/rules_unicorn_no_array_for_each.go +40 -0
- package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
- package/linthost/rules_unicorn_no_array_reduce.go +41 -0
- package/linthost/rules_unicorn_no_array_reverse.go +44 -0
- package/linthost/rules_unicorn_no_array_sort.go +43 -0
- package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
- package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
- package/linthost/rules_unicorn_no_console_spaces.go +61 -0
- package/linthost/rules_unicorn_no_document_cookie.go +41 -0
- package/linthost/rules_unicorn_no_empty_file.go +44 -0
- package/linthost/rules_unicorn_no_for_loop.go +102 -0
- package/linthost/rules_unicorn_no_hex_escape.go +42 -0
- package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
- package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
- package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
- package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
- package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
- package/linthost/rules_unicorn_no_lonely_if.go +44 -0
- package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
- package/linthost/rules_unicorn_no_named_default.go +54 -0
- package/linthost/rules_unicorn_no_negated_condition.go +85 -0
- package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
- package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
- package/linthost/rules_unicorn_no_new_array.go +30 -0
- package/linthost/rules_unicorn_no_new_buffer.go +31 -0
- package/linthost/rules_unicorn_no_null.go +24 -0
- package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
- package/linthost/rules_unicorn_no_process_exit.go +43 -0
- package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
- package/linthost/rules_unicorn_no_static_only_class.go +56 -0
- package/linthost/rules_unicorn_no_thenable.go +74 -0
- package/linthost/rules_unicorn_no_this_assignment.go +35 -0
- package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
- package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
- package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
- package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
- package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
- package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
- package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
- package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
- package/linthost/rules_unicorn_no_unused_properties.go +30 -0
- package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
- package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
- package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
- package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
- package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
- package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
- package/linthost/rules_unicorn_no_useless_spread.go +67 -0
- package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
- package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
- package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
- package/linthost/rules_unicorn_number_literal_case.go +69 -0
- package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
- package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
- package/linthost/rules_unicorn_prefer_array_find.go +51 -0
- package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
- package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
- package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
- package/linthost/rules_unicorn_prefer_array_some.go +67 -0
- package/linthost/rules_unicorn_prefer_at.go +77 -0
- package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
- package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
- package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
- package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
- package/linthost/rules_unicorn_prefer_code_point.go +49 -0
- package/linthost/rules_unicorn_prefer_date_now.go +78 -0
- package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
- package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
- package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
- package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
- package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
- package/linthost/rules_unicorn_prefer_event_target.go +36 -0
- package/linthost/rules_unicorn_prefer_export_from.go +129 -0
- package/linthost/rules_unicorn_prefer_global_this.go +127 -0
- package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
- package/linthost/rules_unicorn_prefer_includes.go +149 -0
- package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
- package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
- package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
- package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
- package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
- package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
- package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
- package/linthost/rules_unicorn_prefer_module.go +50 -0
- package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
- package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
- package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
- package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
- package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
- package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
- package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
- package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
- package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
- package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
- package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
- package/linthost/rules_unicorn_prefer_set_has.go +42 -0
- package/linthost/rules_unicorn_prefer_set_size.go +48 -0
- package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
- package/linthost/rules_unicorn_prefer_single_call.go +96 -0
- package/linthost/rules_unicorn_prefer_spread.go +51 -0
- package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
- package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
- package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
- package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
- package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
- package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
- package/linthost/rules_unicorn_prefer_switch.go +103 -0
- package/linthost/rules_unicorn_prefer_ternary.go +71 -0
- package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
- package/linthost/rules_unicorn_prefer_type_error.go +127 -0
- package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
- package/linthost/rules_unicorn_relative_url_style.go +49 -0
- package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
- package/linthost/rules_unicorn_require_module_attributes.go +54 -0
- package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
- package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
- package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
- package/linthost/rules_unicorn_string_content.go +27 -0
- package/linthost/rules_unicorn_switch_case_braces.go +42 -0
- package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
- package/linthost/rules_unicorn_template_indent.go +28 -0
- package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
- package/linthost/rules_unicorn_throw_new_error.go +61 -0
- package/linthost/rules_var.go +10 -4
- package/linthost/rules_vitest.go +568 -0
- package/package.json +3 -3
- package/plugin/main.go +49 -3
- package/rule/astutil/astutil.go +10 -3
- package/rule/rule.go +12 -10
- package/src/defaultFormat.ts +17 -10
- package/src/index.ts +65 -43
- package/src/structures/ITtscLintConfig.ts +14 -8
- package/src/structures/TtscLintRuleSetting.ts +55 -0
- package/src/structures/format/ITtscLintFormat.ts +141 -0
- package/src/structures/format/ITtscLintFormatJsDoc.ts +18 -0
- package/src/structures/format/ITtscLintFormatSortImports.ts +62 -0
- package/src/structures/format/index.ts +3 -0
- package/src/structures/index.ts +3 -4
- package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +117 -0
- package/src/structures/rules/ITtscLintBoundariesRules.ts +91 -0
- package/src/structures/rules/ITtscLintContributorRules.ts +20 -0
- package/src/structures/rules/ITtscLintCoreRules.ts +1378 -0
- package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
- package/src/structures/rules/ITtscLintCypressRules.ts +141 -0
- package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +200 -0
- package/src/structures/rules/ITtscLintFunctionalRules.ts +197 -0
- package/src/structures/rules/ITtscLintJestRules.ts +209 -0
- package/src/structures/rules/ITtscLintJsdocRules.ts +146 -0
- package/src/structures/rules/ITtscLintJsxA11yRules.ts +331 -0
- package/src/structures/rules/ITtscLintNextjsRules.ts +201 -0
- package/src/structures/rules/ITtscLintPlaywrightRules.ts +343 -0
- package/src/structures/rules/ITtscLintPromiseRules.ts +196 -0
- package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
- package/src/structures/rules/ITtscLintReactPerfRules.ts +53 -0
- package/src/structures/rules/ITtscLintReactRuleOptions.ts +41 -0
- package/src/structures/rules/ITtscLintReactRules.ts +308 -0
- package/src/structures/rules/ITtscLintRegexpRules.ts +204 -0
- package/src/structures/rules/ITtscLintRuleOptionsMap.ts +88 -0
- package/src/structures/rules/ITtscLintRules.ts +77 -0
- package/src/structures/rules/ITtscLintSecurityRules.ts +155 -0
- package/src/structures/rules/ITtscLintSolidRules.ts +199 -0
- package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +22 -0
- package/src/structures/rules/ITtscLintStorybookRules.ts +184 -0
- package/src/structures/rules/ITtscLintTanstackQueryRules.ts +96 -0
- package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +23 -0
- package/src/structures/rules/ITtscLintTestingLibraryRules.ts +325 -0
- package/src/structures/rules/ITtscLintTypeScriptRules.ts +1172 -0
- package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
- package/src/structures/rules/ITtscLintVitestRules.ts +146 -0
- package/src/structures/rules/index.ts +31 -0
- package/lib/structures/ITtscLintFormatConfig.d.ts +0 -153
- package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
- package/lib/structures/TtscLintRule.d.ts +0 -17
- package/lib/structures/TtscLintRule.js.map +0 -1
- package/lib/structures/TtscLintRuleMap.d.ts +0 -46
- package/lib/structures/TtscLintRuleMap.js.map +0 -1
- package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
- package/lib/structures/TtscLintRuleOptions.js.map +0 -1
- package/src/structures/ITtscLintFormatConfig.ts +0 -168
- package/src/structures/TtscLintRule.ts +0 -160
- package/src/structures/TtscLintRuleMap.ts +0 -55
- package/src/structures/TtscLintRuleOptions.ts +0 -151
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
package linthost
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
5
|
+
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// formatIndent normalizes the leading indentation of each statement's
|
|
9
|
+
// first line to `depth * tabWidth` columns (or `depth` tabs under
|
|
10
|
+
// useTabs), mirroring Prettier's block indentation.
|
|
11
|
+
//
|
|
12
|
+
// The rule shares `format/statement-split`'s file-level walk: it
|
|
13
|
+
// registers for KindSourceFile and visits every statement in every
|
|
14
|
+
// statement list (SourceFile body, Block, ModuleBlock, case/default
|
|
15
|
+
// clause) at its nesting depth.
|
|
16
|
+
//
|
|
17
|
+
// Per-statement decision:
|
|
18
|
+
//
|
|
19
|
+
// 1. Find the statement's first non-trivia byte and the start of its
|
|
20
|
+
// physical line.
|
|
21
|
+
// 2. Abstain unless the statement is the first non-whitespace token on
|
|
22
|
+
// that line. A statement sharing a line with a previous statement is
|
|
23
|
+
// `format/statement-split`'s surface; keeping the two rules disjoint
|
|
24
|
+
// means their edits never overlap on one cascade pass.
|
|
25
|
+
// 3. Compare the leading-whitespace run `[lineStart, firstNonWS)` to the
|
|
26
|
+
// desired indent. When they differ, replace the run with the indent.
|
|
27
|
+
//
|
|
28
|
+
// The rule only ever touches a statement's own starting line. Interior
|
|
29
|
+
// and continuation lines belong to `format/print-width`, which owns
|
|
30
|
+
// reflow indentation; rewriting them here would fight that rule.
|
|
31
|
+
//
|
|
32
|
+
// Idempotent: a correctly-indented statement compares equal in step 3
|
|
33
|
+
// and emits nothing.
|
|
34
|
+
type formatIndent struct{}
|
|
35
|
+
|
|
36
|
+
func (formatIndent) Name() string { return "format/indent" }
|
|
37
|
+
func (formatIndent) IsFormat() bool { return true }
|
|
38
|
+
func (formatIndent) Visits() []shimast.Kind {
|
|
39
|
+
return []shimast.Kind{shimast.KindSourceFile}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
func (formatIndent) Check(ctx *Context, node *shimast.Node) {
|
|
43
|
+
if ctx == nil || ctx.File == nil {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
layout := loadFormatLayout(ctx)
|
|
47
|
+
src := ctx.File.Text()
|
|
48
|
+
var edits []TextEdit
|
|
49
|
+
forEachStatementInList(ctx.File, func(stmt *shimast.Node, depth int) {
|
|
50
|
+
// A statement whose indentation is owned by format/print-width's
|
|
51
|
+
// expression reflow (it sits inside a call/new/array/object that the
|
|
52
|
+
// printer lays out) must not be re-indented here: the printer hangs a
|
|
53
|
+
// callback body under its call-argument column, which is deeper than
|
|
54
|
+
// this rule's block-nesting depth, and reindenting it would oscillate
|
|
55
|
+
// against the printer pass forever (the cascade never converges).
|
|
56
|
+
if indentCededToReflow(stmt) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
start := shimscanner.SkipTrivia(src, stmt.Pos())
|
|
60
|
+
if start < 0 || start > len(src) {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
lineStart := lineStartOffset(src, start)
|
|
64
|
+
// Only the leading run may be whitespace for this to be the first
|
|
65
|
+
// token on its line. A non-whitespace byte in `[lineStart, start)`
|
|
66
|
+
// means a previous statement shares the line, defer to
|
|
67
|
+
// `format/statement-split`.
|
|
68
|
+
for i := lineStart; i < start; i++ {
|
|
69
|
+
if src[i] != ' ' && src[i] != '\t' {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
want := layout.indent(depth)
|
|
74
|
+
if src[lineStart:start] == want {
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
// Cede everything inside a chained-arrow body (`a => b => { … }`).
|
|
78
|
+
// Prettier indents such a body one extra level for the chain
|
|
79
|
+
// continuation, so the body block AND every statement nested below it
|
|
80
|
+
// sit one level deeper than the column-0 depth model computes;
|
|
81
|
+
// reindenting any of them to depth*tabWidth de-indents correct source.
|
|
82
|
+
// This is detected structurally (an ancestor block whose owning arrow is
|
|
83
|
+
// itself another arrow's body), so a mangled input cannot fool it,
|
|
84
|
+
// unlike a class method body, a switch case body, a single-head arrow,
|
|
85
|
+
// or a multi-line-condition `if` body, all of which the depth model
|
|
86
|
+
// places correctly.
|
|
87
|
+
if cededByChainedArrowAncestor(stmt) {
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
edits = append(edits, TextEdit{Pos: lineStart, End: start, Text: want})
|
|
91
|
+
})
|
|
92
|
+
// Second pass: align the block-closing `}` lines and the header lines
|
|
93
|
+
// (class / interface / type-literal member declarations and
|
|
94
|
+
// `case`/`default` labels) that are neither statements nor closing
|
|
95
|
+
// braces. Both surfaces are visited by a single ForEachChild descent
|
|
96
|
+
// (forEachIndentFrame) that tracks depth once and fires a brace callback
|
|
97
|
+
// and a header callback at the right nodes/depths; the two callbacks
|
|
98
|
+
// never target the same node, so this is exactly the two former
|
|
99
|
+
// descents fused.
|
|
100
|
+
//
|
|
101
|
+
// Closing brace: a `}` is not a statement, so the statement walk never
|
|
102
|
+
// touches it; without this a mangled (flat) block body gets its
|
|
103
|
+
// statements re-indented while the closing braces stay at their wrong
|
|
104
|
+
// column, and the cascade "converges" on that malformed result (exit 0
|
|
105
|
+
// on broken output). The brace aligns to the block OWNER's depth, one
|
|
106
|
+
// level shallower than the block's own statements, under the same cede /
|
|
107
|
+
// wrapped-head guards as the opening pass, so an expression-nested or
|
|
108
|
+
// wrapped-head block's `}` is left to the printer / its head.
|
|
109
|
+
//
|
|
110
|
+
// Header: the statement walk never visits a member declaration or a
|
|
111
|
+
// clause label (neither is a statement), so without this a flattened
|
|
112
|
+
// class body or switch leaves member headers and case labels at column 0
|
|
113
|
+
// while their bodies are re-indented, a malformed result the cascade
|
|
114
|
+
// reports as success.
|
|
115
|
+
forEachIndentFrame(
|
|
116
|
+
ctx.File,
|
|
117
|
+
func(block *shimast.Node, ownerDepth int) {
|
|
118
|
+
closeBrace := blockCloseBracePos(src, block)
|
|
119
|
+
if closeBrace < 0 {
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
lineStart := lineStartOffset(src, closeBrace)
|
|
123
|
+
// The `}` must be the first non-whitespace byte on its line; a brace
|
|
124
|
+
// sharing a line with content (`} else {`, `{ x }`) is not this
|
|
125
|
+
// rule's to move.
|
|
126
|
+
for i := lineStart; i < closeBrace; i++ {
|
|
127
|
+
if src[i] != ' ' && src[i] != '\t' {
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// indentCededToReflow walks block.Parent upward, the same ancestor
|
|
132
|
+
// chain a body statement would, so a callback / expression-nested
|
|
133
|
+
// block's `}` cedes in lockstep with its body (print-width owns it).
|
|
134
|
+
if indentCededToReflow(block) {
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
// Chained-arrow body: cede the `}` in lockstep with its body
|
|
138
|
+
// statements. A chained-arrow body's own brace, and any brace nested
|
|
139
|
+
// inside it, sit one extra level deep for the chain continuation, so
|
|
140
|
+
// leave them be.
|
|
141
|
+
if cededByChainedArrowAncestor(block) {
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
want := layout.indent(ownerDepth)
|
|
145
|
+
if src[lineStart:closeBrace] == want {
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
edits = append(edits, TextEdit{Pos: lineStart, End: closeBrace, Text: want})
|
|
149
|
+
},
|
|
150
|
+
func(header *shimast.Node, depth int) {
|
|
151
|
+
pos := shimscanner.SkipTrivia(src, header.Pos())
|
|
152
|
+
if pos < 0 || pos > len(src) {
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
lineStart := lineStartOffset(src, pos)
|
|
156
|
+
for i := lineStart; i < pos; i++ {
|
|
157
|
+
if src[i] != ' ' && src[i] != '\t' {
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if indentCededToReflow(header) || cededByChainedArrowAncestor(header) {
|
|
162
|
+
return
|
|
163
|
+
}
|
|
164
|
+
want := layout.indent(depth)
|
|
165
|
+
if src[lineStart:pos] == want {
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
edits = append(edits, TextEdit{Pos: lineStart, End: pos, Text: want})
|
|
169
|
+
},
|
|
170
|
+
)
|
|
171
|
+
if len(edits) == 0 {
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
ctx.ReportRangeFix(
|
|
175
|
+
edits[0].Pos,
|
|
176
|
+
edits[0].End,
|
|
177
|
+
"Statement indentation must match its nesting depth.",
|
|
178
|
+
edits...,
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// indentCededToReflow reports whether `stmt` lives inside an expression
|
|
183
|
+
// whose layout column format/indent cannot compute from block-nesting
|
|
184
|
+
// depth alone, a call/new argument, an array/object element, a
|
|
185
|
+
// conditional branch, or a parenthesized expression. format/indent's
|
|
186
|
+
// depth counts only Block/clause/declaration nesting, so a statement
|
|
187
|
+
// hung under such an expression (a callback body, a `new (class {…})()`
|
|
188
|
+
// method, a `cond ? () => {…} : …` arm) sits at a deeper column than its
|
|
189
|
+
// block depth, and reindenting it to depth*tabWidth both corrupts
|
|
190
|
+
// correct source and ping-pongs against format/print-width every cascade
|
|
191
|
+
// pass (the cascade never converges).
|
|
192
|
+
//
|
|
193
|
+
// Walking outward from the statement, an enclosing expression of those
|
|
194
|
+
// kinds means the indentation is owned by the printer (when print-width
|
|
195
|
+
// is active) or by the already-correct source (when it is off), so
|
|
196
|
+
// format/indent cedes. Reaching the source file or a module block first
|
|
197
|
+
// means the statement is in ordinary block/declaration position,
|
|
198
|
+
// format/indent owns it and indents to its nesting depth.
|
|
199
|
+
func indentCededToReflow(stmt *shimast.Node) bool {
|
|
200
|
+
for n := stmt.Parent; n != nil; n = n.Parent {
|
|
201
|
+
switch n.Kind {
|
|
202
|
+
case shimast.KindCallExpression,
|
|
203
|
+
shimast.KindNewExpression,
|
|
204
|
+
shimast.KindArrayLiteralExpression,
|
|
205
|
+
shimast.KindObjectLiteralExpression,
|
|
206
|
+
shimast.KindConditionalExpression,
|
|
207
|
+
shimast.KindParenthesizedExpression:
|
|
208
|
+
return true
|
|
209
|
+
case shimast.KindSourceFile,
|
|
210
|
+
shimast.KindModuleBlock:
|
|
211
|
+
return false
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return false
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// cededByChainedArrowAncestor reports whether `node` sits inside the body of
|
|
218
|
+
// a chained arrow (`a => b => { … }`). Prettier indents a chained arrow's
|
|
219
|
+
// body one extra level for the chain continuation, so the body block AND
|
|
220
|
+
// every statement / brace nested below it sit one level deeper than the
|
|
221
|
+
// column-0 depth model computes; format/indent must cede all of them or it
|
|
222
|
+
// de-indents correct source. Walking ancestor blocks (not just the nearest)
|
|
223
|
+
// catches a statement deep inside the body, e.g. an `if` body two levels
|
|
224
|
+
// down. Purely structural (AST kinds), so a mangled input cannot fool it,
|
|
225
|
+
// and it does NOT match a class method body, a switch case body, a
|
|
226
|
+
// single-head arrow body, or a multi-line-condition `if` body, those the
|
|
227
|
+
// depth model places correctly.
|
|
228
|
+
//
|
|
229
|
+
// `node` may be a statement (statement pass) or a Block (closing-brace
|
|
230
|
+
// pass). The walk starts at `node` itself so a Block argument's own
|
|
231
|
+
// chained-arrow-body-ness is tested (its `}` must cede too), then climbs
|
|
232
|
+
// ancestors for a statement nested deeper inside the body.
|
|
233
|
+
func cededByChainedArrowAncestor(node *shimast.Node) bool {
|
|
234
|
+
for n := node; n != nil; n = n.Parent {
|
|
235
|
+
if n.Kind == shimast.KindSourceFile {
|
|
236
|
+
return false
|
|
237
|
+
}
|
|
238
|
+
if n.Kind == shimast.KindBlock {
|
|
239
|
+
arrow := n.Parent
|
|
240
|
+
if arrow != nil && arrow.Kind == shimast.KindArrowFunction &&
|
|
241
|
+
arrow.Parent != nil && arrow.Parent.Kind == shimast.KindArrowFunction {
|
|
242
|
+
return true
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return false
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// forEachIndentFrame walks the file's AST once and fires two callbacks at
|
|
250
|
+
// the nodes/depths the former forEachBlockClose and forEachIndentHeader
|
|
251
|
+
// descents fired, fused into a single ForEachChild descent that tracks
|
|
252
|
+
// depth once. The two former walks computed an identical childDepth for
|
|
253
|
+
// every child kind and only differed in which callback they fired on which
|
|
254
|
+
// node (the brace surface and the header surface never overlap on one
|
|
255
|
+
// node), so one descent firing both is exactly the two passes combined.
|
|
256
|
+
//
|
|
257
|
+
// - brace(owner, ownerDepth): fired for every Block / ModuleBlock /
|
|
258
|
+
// CaseBlock / class / interface / type-literal owner with the depth
|
|
259
|
+
// its closing `}` aligns to (one level shallower than the owner's own
|
|
260
|
+
// statements). A case-body Block fires at depth-1 so its `}` aligns
|
|
261
|
+
// with the `case` label one level up. It mirrors walkStatementLists's
|
|
262
|
+
// depth model so all indent passes agree.
|
|
263
|
+
// - header(node, depth): fired for every class/interface/type-literal
|
|
264
|
+
// member declaration and every case/default label with the depth its
|
|
265
|
+
// header line should align to. A class/interface/type-literal body is
|
|
266
|
+
// a +1 frame and its member headers sit at that body depth; a switch's
|
|
267
|
+
// CaseBlock is a +1 frame and each case/default label sits at that
|
|
268
|
+
// CaseBlock depth (its body statements nest one deeper, handled by the
|
|
269
|
+
// statement pass).
|
|
270
|
+
func forEachIndentFrame(
|
|
271
|
+
file *shimast.SourceFile,
|
|
272
|
+
brace func(block *shimast.Node, ownerDepth int),
|
|
273
|
+
header func(node *shimast.Node, depth int),
|
|
274
|
+
) {
|
|
275
|
+
if file == nil {
|
|
276
|
+
return
|
|
277
|
+
}
|
|
278
|
+
walkIndentFrames(file.AsNode(), 0, brace, header)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
func walkIndentFrames(
|
|
282
|
+
node *shimast.Node,
|
|
283
|
+
depth int,
|
|
284
|
+
brace func(block *shimast.Node, ownerDepth int),
|
|
285
|
+
header func(node *shimast.Node, depth int),
|
|
286
|
+
) {
|
|
287
|
+
if node == nil {
|
|
288
|
+
return
|
|
289
|
+
}
|
|
290
|
+
node.ForEachChild(func(child *shimast.Node) bool {
|
|
291
|
+
if child == nil {
|
|
292
|
+
return false
|
|
293
|
+
}
|
|
294
|
+
childDepth := depth
|
|
295
|
+
switch child.Kind {
|
|
296
|
+
case shimast.KindBlock, shimast.KindModuleBlock:
|
|
297
|
+
isCaseBody := child.Kind == shimast.KindBlock && child.Parent != nil &&
|
|
298
|
+
(child.Parent.Kind == shimast.KindCaseClause ||
|
|
299
|
+
child.Parent.Kind == shimast.KindDefaultClause)
|
|
300
|
+
if isCaseBody {
|
|
301
|
+
// A case-body block (`case X: { … }`) adds no extra level for its
|
|
302
|
+
// statements (they stay at the clause body depth, this `depth`), but
|
|
303
|
+
// its own closing `}` aligns with the `case` label one level up.
|
|
304
|
+
brace(child, depth-1)
|
|
305
|
+
childDepth = depth
|
|
306
|
+
} else {
|
|
307
|
+
// The block's `}` aligns to the owner depth (this `depth`); its
|
|
308
|
+
// statements nest one deeper.
|
|
309
|
+
brace(child, depth)
|
|
310
|
+
childDepth = depth + 1
|
|
311
|
+
}
|
|
312
|
+
case shimast.KindCaseClause, shimast.KindDefaultClause:
|
|
313
|
+
// The label (`case X:` / `default:`) sits at the current (CaseBlock)
|
|
314
|
+
// depth; its body statements nest one deeper.
|
|
315
|
+
header(child, depth)
|
|
316
|
+
childDepth = depth + 1
|
|
317
|
+
case shimast.KindCaseBlock,
|
|
318
|
+
shimast.KindClassDeclaration,
|
|
319
|
+
shimast.KindClassExpression,
|
|
320
|
+
shimast.KindInterfaceDeclaration,
|
|
321
|
+
shimast.KindTypeLiteral:
|
|
322
|
+
// These carry a real closing `}` that is not a Block node: a switch's
|
|
323
|
+
// `}` (CaseBlock), a class/interface/type-literal body `}`. Align it to
|
|
324
|
+
// the depth the owner sits at (this `depth`); the members/clauses nest
|
|
325
|
+
// one deeper.
|
|
326
|
+
brace(child, depth)
|
|
327
|
+
childDepth = depth + 1
|
|
328
|
+
case shimast.KindObjectLiteralExpression:
|
|
329
|
+
// Object-literal braces live in expression position (assignments,
|
|
330
|
+
// arguments); their layout is the printer's / source's, so leave the
|
|
331
|
+
// `}` alone and only descend one level for any nested statement lists.
|
|
332
|
+
childDepth = depth + 1
|
|
333
|
+
case shimast.KindMethodDeclaration,
|
|
334
|
+
shimast.KindPropertyDeclaration,
|
|
335
|
+
shimast.KindGetAccessor,
|
|
336
|
+
shimast.KindSetAccessor,
|
|
337
|
+
shimast.KindConstructor,
|
|
338
|
+
shimast.KindMethodSignature,
|
|
339
|
+
shimast.KindPropertySignature,
|
|
340
|
+
shimast.KindIndexSignature:
|
|
341
|
+
// A class/interface/type-literal member: its header line sits at the
|
|
342
|
+
// current body depth (the enclosing frame already bumped it).
|
|
343
|
+
header(child, depth)
|
|
344
|
+
}
|
|
345
|
+
walkIndentFrames(child, childDepth, brace, header)
|
|
346
|
+
return false
|
|
347
|
+
})
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// blockCloseBracePos returns the byte offset of a block's closing `}`.
|
|
351
|
+
// A block's End() points just past the `}`, so the brace is the last
|
|
352
|
+
// non-whitespace byte before End(); returns -1 if it is not a `}`.
|
|
353
|
+
func blockCloseBracePos(src string, block *shimast.Node) int {
|
|
354
|
+
end := block.End()
|
|
355
|
+
if end <= 0 || end > len(src) {
|
|
356
|
+
return -1
|
|
357
|
+
}
|
|
358
|
+
for i := end - 1; i >= 0; i-- {
|
|
359
|
+
c := src[i]
|
|
360
|
+
if c == '}' {
|
|
361
|
+
return i
|
|
362
|
+
}
|
|
363
|
+
if c != ' ' && c != '\t' && c != '\n' && c != '\r' {
|
|
364
|
+
return -1
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return -1
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
func init() {
|
|
371
|
+
Register(formatIndent{})
|
|
372
|
+
}
|
|
@@ -5,7 +5,7 @@ import (
|
|
|
5
5
|
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
6
6
|
)
|
|
7
7
|
|
|
8
|
-
//
|
|
8
|
+
// formatJsdoc rewrites JSDoc blocks toward the prettier-plugin-jsdoc
|
|
9
9
|
// canonical shape. The MVP implementation handles tag-synonym
|
|
10
10
|
// normalization; future passes will fold in tag sorting, @param column
|
|
11
11
|
// alignment, and description wrapping under the same rule name so
|
|
@@ -19,7 +19,7 @@ import (
|
|
|
19
19
|
// - @virtual → @abstract
|
|
20
20
|
// - @func, @method → @function
|
|
21
21
|
//
|
|
22
|
-
// JSDoc tags only fire when the `@` is at the start of a JSDoc line
|
|
22
|
+
// JSDoc tags only fire when the `@` is at the start of a JSDoc line,
|
|
23
23
|
// preceded by `*`, whitespace, or a newline. Inline `@foo` references in
|
|
24
24
|
// prose text are left alone. The rule scans source bytes directly inside
|
|
25
25
|
// `/** ... */` blocks; it deliberately avoids relying on the JSDoc AST
|
|
@@ -65,7 +65,7 @@ func (formatJSDoc) Check(ctx *Context, node *shimast.Node) {
|
|
|
65
65
|
}
|
|
66
66
|
for k, v := range opts.TagSynonyms {
|
|
67
67
|
// Reject empty canonicals or canonicals carrying non-identifier
|
|
68
|
-
// bytes
|
|
68
|
+
// bytes, the fixer would otherwise emit malformed JSDoc like
|
|
69
69
|
// `@` or `@my tag`. Silently dropping the bad entry is the right
|
|
70
70
|
// failure mode: the rule already runs on every file in a project
|
|
71
71
|
// and a single typo'd entry should not poison every block.
|
|
@@ -82,7 +82,7 @@ func (formatJSDoc) Check(ctx *Context, node *shimast.Node) {
|
|
|
82
82
|
// `sortTags` is reserved for a follow-up that pulls in the
|
|
83
83
|
// prettier-plugin-jsdoc canonical order. The flag is parsed today so
|
|
84
84
|
// the type surface freezes, but the implementation lands in a future
|
|
85
|
-
// pass
|
|
85
|
+
// pass, projects that opt in get a no-op until then.
|
|
86
86
|
_ = opts.SortTags
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -122,7 +122,7 @@ func findJSDocBlocks(src string) []jsdocBlock {
|
|
|
122
122
|
if !(src[start] == '/' && src[start+1] == '*' && src[start+2] == '*') {
|
|
123
123
|
continue
|
|
124
124
|
}
|
|
125
|
-
// Skip
|
|
125
|
+
// Skip `/**/`, an empty doc block has no tags to rewrite.
|
|
126
126
|
if end-start == 4 && src[start+3] == '/' {
|
|
127
127
|
continue
|
|
128
128
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
package linthost
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
5
|
+
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// formatOrphanSemi merges a lone leading-semicolon ASI guard onto the
|
|
9
|
+
// statement it protects, matching Prettier under semi:false:
|
|
10
|
+
//
|
|
11
|
+
// ;
|
|
12
|
+
// (expr).method()
|
|
13
|
+
//
|
|
14
|
+
// becomes `;(expr).method()`. Authors write the standalone `;` so ASI
|
|
15
|
+
// does not glue a `(`/`[`/`` ` ``-leading statement onto the previous
|
|
16
|
+
// line; Prettier keeps the guard but pulls it onto the guarded
|
|
17
|
+
// statement's line.
|
|
18
|
+
//
|
|
19
|
+
// Scope is deliberately narrow and safe: it acts only under semi:false
|
|
20
|
+
// (the guard is a no-semicolon idiom) and only when the next statement
|
|
21
|
+
// begins with an ASI-hazard token, so the `;` is genuinely required and
|
|
22
|
+
// the edit just deletes the whitespace gap. Every other empty statement
|
|
23
|
+
// (trailing `;`, a non-hazard successor, a comment in between, semi:true)
|
|
24
|
+
// is left alone, dropping a redundant `;` safely depends on the
|
|
25
|
+
// surrounding semicolon policy and is out of scope here. Idempotent:
|
|
26
|
+
// once merged the gap holds no newline, so the rule finds nothing to do.
|
|
27
|
+
type formatOrphanSemi struct{}
|
|
28
|
+
|
|
29
|
+
// formatOrphanSemiOptions carries the effective `semi` setting, mirrored
|
|
30
|
+
// from format.semi by the config layer. Defaults to true (semicolons),
|
|
31
|
+
// in which case the rule never acts.
|
|
32
|
+
type formatOrphanSemiOptions struct {
|
|
33
|
+
Semi *bool `json:"semi"`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func (formatOrphanSemi) Name() string { return "format/orphan-semi" }
|
|
37
|
+
func (formatOrphanSemi) IsFormat() bool { return true }
|
|
38
|
+
|
|
39
|
+
func (formatOrphanSemi) Visits() []shimast.Kind {
|
|
40
|
+
return []shimast.Kind{shimast.KindEmptyStatement}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
func (formatOrphanSemi) Check(ctx *Context, node *shimast.Node) {
|
|
44
|
+
if ctx == nil || ctx.File == nil || node == nil {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
var opts formatOrphanSemiOptions
|
|
48
|
+
_ = ctx.DecodeOptions(&opts)
|
|
49
|
+
// Only the semi:false guard idiom is in scope.
|
|
50
|
+
if opts.Semi == nil || *opts.Semi {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
src := ctx.File.Text()
|
|
55
|
+
semiPos := shimscanner.SkipTrivia(src, node.Pos())
|
|
56
|
+
semiEnd := node.End()
|
|
57
|
+
if semiPos < 0 || semiEnd > len(src) || semiPos >= semiEnd || src[semiEnd-1] != ';' {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
// The `;` must be the first token on its line, a true orphan guard,
|
|
61
|
+
// not a trailing empty statement after other code.
|
|
62
|
+
lineStart := lineStartOffset(src, semiPos)
|
|
63
|
+
for i := lineStart; i < semiPos; i++ {
|
|
64
|
+
if src[i] != ' ' && src[i] != '\t' {
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Find the next significant byte. A comment in the gap is left alone
|
|
70
|
+
// (the merge would have to reposition it).
|
|
71
|
+
i := semiEnd
|
|
72
|
+
for i < len(src) {
|
|
73
|
+
c := src[i]
|
|
74
|
+
if c == ' ' || c == '\t' || c == '\r' || c == '\n' {
|
|
75
|
+
i++
|
|
76
|
+
continue
|
|
77
|
+
}
|
|
78
|
+
if c == '/' && i+1 < len(src) && (src[i+1] == '/' || src[i+1] == '*') {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
break
|
|
82
|
+
}
|
|
83
|
+
if i >= len(src) {
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
// Merge only when the next statement begins with an ASI-hazard token,
|
|
87
|
+
// so the `;` is genuinely the guard Prettier keeps.
|
|
88
|
+
switch src[i] {
|
|
89
|
+
case '(', '[', '`':
|
|
90
|
+
default:
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
if i <= semiEnd {
|
|
94
|
+
return // already adjacent (idempotent no-op)
|
|
95
|
+
}
|
|
96
|
+
ctx.ReportRangeFix(
|
|
97
|
+
semiEnd,
|
|
98
|
+
i,
|
|
99
|
+
"Merge the leading-semicolon ASI guard onto its statement.",
|
|
100
|
+
TextEdit{Pos: semiEnd, End: i, Text: ""},
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
func init() {
|
|
105
|
+
Register(formatOrphanSemi{})
|
|
106
|
+
}
|