@ttsc/lint 0.14.0-dev.20260529.2 → 0.14.0
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 +21 -23
- package/lib/defaultFormat.d.ts +10 -6
- package/lib/defaultFormat.js +10 -6
- package/lib/defaultFormat.js.map +1 -1
- package/lib/structures/ITtscLintConfig.d.ts +5 -5
- package/lib/structures/TtscLintRuleSetting.d.ts +19 -19
- package/lib/structures/{ITtscLintFormat.d.ts → format/ITtscLintFormat.d.ts} +45 -70
- package/lib/structures/format/ITtscLintFormat.js.map +1 -0
- package/lib/structures/format/ITtscLintFormatJsDoc.d.ts +15 -0
- package/lib/structures/format/ITtscLintFormatJsDoc.js +3 -0
- 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 +1 -1
- package/lib/structures/index.js +1 -1
- package/lib/structures/index.js.map +1 -1
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +18 -27
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +4 -5
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -1
- package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +29 -33
- package/lib/structures/rules/ITtscLintContributorRules.d.ts +6 -7
- package/lib/structures/rules/ITtscLintCoreRules.d.ts +380 -408
- package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +5 -5
- package/lib/structures/rules/ITtscLintCypressRuleOptions.js +2 -2
- package/lib/structures/rules/ITtscLintCypressRules.d.ts +34 -38
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +21 -24
- package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +2 -2
- package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +51 -56
- package/lib/structures/rules/ITtscLintJestRules.d.ts +63 -74
- package/lib/structures/rules/ITtscLintJsdocRules.d.ts +47 -54
- package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +94 -102
- package/lib/structures/rules/ITtscLintNextjsRules.d.ts +50 -55
- package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +104 -122
- package/lib/structures/rules/ITtscLintPromiseRules.d.ts +62 -71
- package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +4 -4
- package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +17 -19
- package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +8 -10
- package/lib/structures/rules/ITtscLintReactRuleOptions.js +1 -2
- package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -1
- package/lib/structures/rules/ITtscLintReactRules.d.ts +91 -104
- package/lib/structures/rules/ITtscLintRegexpRules.d.ts +46 -54
- package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +7 -8
- package/lib/structures/rules/ITtscLintSecurityRules.d.ts +45 -52
- package/lib/structures/rules/ITtscLintSolidRules.d.ts +53 -56
- package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +3 -4
- package/lib/structures/rules/ITtscLintStorybookRules.d.ts +60 -69
- package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +31 -37
- package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +2 -3
- package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +102 -119
- package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +460 -518
- package/lib/structures/rules/ITtscLintVitestRules.d.ts +43 -51
- package/linthost/config.go +89 -72
- package/linthost/config_format.go +265 -99
- package/linthost/directives.go +5 -1
- package/linthost/display_width.go +72 -0
- package/linthost/fix.go +26 -1
- package/linthost/format.go +222 -25
- package/linthost/format_editor_settings.go +262 -0
- package/linthost/lsp.go +8 -4
- package/linthost/print_dispatch.go +3 -0
- package/linthost/print_doc.go +13 -0
- package/linthost/print_engine.go +68 -11
- package/linthost/print_nodes_array.go +108 -5
- package/linthost/print_nodes_call.go +515 -74
- package/linthost/print_nodes_function.go +25 -0
- package/linthost/print_nodes_imports.go +47 -14
- package/linthost/print_nodes_list.go +191 -8
- package/linthost/print_nodes_object.go +12 -6
- package/linthost/print_nodes_ternary.go +106 -0
- package/linthost/rules_boundaries.go +400 -400
- package/linthost/rules_camelcase.go +81 -81
- package/linthost/rules_complexity.go +52 -51
- package/linthost/rules_consistent_return.go +81 -81
- package/linthost/rules_core_extra.go +472 -472
- package/linthost/rules_curly.go +43 -43
- package/linthost/rules_default_case.go +15 -15
- package/linthost/rules_default_case_last.go +22 -22
- 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 +664 -0
- package/linthost/rules_format_indent.go +616 -0
- package/linthost/rules_format_jsdoc.go +4 -4
- 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 +185 -69
- package/linthost/rules_format_quote_props.go +169 -0
- package/linthost/rules_format_quotes.go +75 -29
- package/linthost/rules_format_semi.go +185 -10
- package/linthost/rules_format_sort_imports.go +456 -121
- package/linthost/rules_format_statement_split.go +368 -0
- package/linthost/rules_format_ternary_nullish_parens.go +77 -0
- package/linthost/rules_format_trailing_comma.go +21 -2
- package/linthost/rules_format_whitespace.go +336 -0
- package/linthost/rules_functional.go +688 -688
- package/linthost/rules_gap.go +146 -11
- package/linthost/rules_grouped_accessor_pairs.go +60 -60
- package/linthost/rules_guard_for_in.go +122 -122
- package/linthost/rules_id_length.go +44 -44
- package/linthost/rules_imports.go +11 -3
- package/linthost/rules_init_declarations.go +25 -25
- package/linthost/rules_jsx_a11y.go +844 -844
- package/linthost/rules_max_classes_per_file.go +24 -24
- package/linthost/rules_max_depth.go +43 -43
- package/linthost/rules_max_lines.go +53 -53
- package/linthost/rules_max_lines_per_function.go +28 -28
- package/linthost/rules_max_nested_callbacks.go +26 -26
- package/linthost/rules_max_params.go +20 -20
- package/linthost/rules_max_statements.go +29 -29
- package/linthost/rules_nextjs.go +5 -5
- package/linthost/rules_no_else_return.go +38 -38
- package/linthost/rules_no_empty_named_blocks.go +45 -45
- package/linthost/rules_no_import_assign.go +96 -96
- package/linthost/rules_no_invalid_this.go +19 -19
- package/linthost/rules_no_loop_func.go +43 -43
- package/linthost/rules_no_magic_numbers.go +60 -60
- package/linthost/rules_no_mixed_operators.go +44 -44
- package/linthost/rules_no_param_reassign.go +64 -64
- package/linthost/rules_no_restricted_imports.go +45 -45
- package/linthost/rules_no_restricted_syntax.go +17 -17
- package/linthost/rules_no_shadow.go +112 -112
- package/linthost/rules_no_unreachable.go +36 -36
- package/linthost/rules_no_useless_assignment.go +79 -79
- package/linthost/rules_no_useless_constructor.go +167 -167
- package/linthost/rules_no_useless_return.go +28 -28
- package/linthost/rules_prefer_arrow_callback.go +74 -74
- package/linthost/rules_prefer_destructuring.go +61 -61
- package/linthost/rules_prefer_named_capture_group.go +87 -87
- package/linthost/rules_prefer_rest_params.go +61 -61
- package/linthost/rules_promise.go +800 -800
- package/linthost/rules_react.go +600 -600
- package/linthost/rules_react_extras.go +162 -162
- package/linthost/rules_react_hooks.go +2 -2
- package/linthost/rules_react_perf.go +231 -231
- package/linthost/rules_regexp.go +293 -293
- package/linthost/rules_security.go +613 -613
- package/linthost/rules_sort_imports.go +37 -37
- package/linthost/rules_sort_keys.go +88 -88
- package/linthost/rules_suggestions.go +13 -0
- package/linthost/rules_ts.go +2 -2
- package/linthost/rules_ts_async.go +247 -247
- package/linthost/rules_ts_class_literal_property_style.go +64 -64
- package/linthost/rules_ts_consistent_type_exports.go +209 -209
- package/linthost/rules_ts_explicit_function_return_type.go +35 -35
- package/linthost/rules_ts_extra.go +6 -2
- package/linthost/rules_ts_no_base_to_string.go +140 -140
- package/linthost/rules_ts_no_confusing_void.go +28 -28
- package/linthost/rules_ts_no_deprecated.go +110 -110
- package/linthost/rules_ts_no_for_in_array.go +45 -45
- package/linthost/rules_ts_no_magic_numbers.go +67 -67
- package/linthost/rules_ts_no_meaningless_void_operator.go +44 -44
- package/linthost/rules_ts_no_misused_spread.go +64 -64
- package/linthost/rules_ts_no_redundant_type_constituents.go +72 -72
- package/linthost/rules_ts_no_restricted_types.go +28 -28
- package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +87 -87
- package/linthost/rules_ts_no_unnecessary_condition.go +184 -184
- package/linthost/rules_ts_no_unnecessary_qualifier.go +72 -72
- package/linthost/rules_ts_no_unnecessary_template_expression.go +120 -120
- package/linthost/rules_ts_no_unnecessary_type_arguments.go +171 -171
- package/linthost/rules_ts_no_unnecessary_type_assertion.go +90 -90
- package/linthost/rules_ts_no_unsafe_argument.go +50 -50
- package/linthost/rules_ts_no_unsafe_assignment.go +60 -60
- package/linthost/rules_ts_no_unsafe_call.go +40 -40
- package/linthost/rules_ts_no_unsafe_enum_comparison.go +147 -147
- package/linthost/rules_ts_no_unsafe_member_access.go +29 -29
- package/linthost/rules_ts_no_unsafe_return.go +64 -64
- package/linthost/rules_ts_no_unsafe_unary_minus.go +42 -42
- package/linthost/rules_ts_no_useless_constructor.go +20 -20
- package/linthost/rules_ts_non_nullable_type_assertion_style.go +60 -60
- package/linthost/rules_ts_parameter_properties.go +10 -10
- package/linthost/rules_ts_prefer_find.go +116 -116
- package/linthost/rules_ts_prefer_includes.go +173 -173
- package/linthost/rules_ts_prefer_nullish_coalescing.go +54 -54
- package/linthost/rules_ts_prefer_optional_chain.go +156 -156
- package/linthost/rules_ts_prefer_promise_reject_errors.go +104 -104
- package/linthost/rules_ts_prefer_readonly.go +31 -31
- package/linthost/rules_ts_prefer_reduce_type_parameter.go +74 -74
- package/linthost/rules_ts_prefer_regexp_exec.go +69 -69
- package/linthost/rules_ts_prefer_return_this_type.go +79 -79
- package/linthost/rules_ts_prefer_string_starts_ends_with.go +237 -237
- package/linthost/rules_ts_promise_function_async.go +41 -41
- package/linthost/rules_ts_related_getter_setter_pairs.go +61 -61
- package/linthost/rules_ts_require_array_sort_compare.go +58 -58
- package/linthost/rules_ts_restrict_plus_operands.go +82 -82
- package/linthost/rules_ts_restrict_template_expressions.go +50 -50
- package/linthost/rules_ts_simple.go +249 -249
- package/linthost/rules_ts_sort_type_constituents.go +88 -88
- package/linthost/rules_ts_strict_boolean_expressions.go +103 -103
- package/linthost/rules_ts_switch_exhaustiveness_check.go +90 -90
- package/linthost/rules_ts_unbound_method.go +65 -65
- package/linthost/rules_tsdoc.go +88 -88
- package/linthost/rules_unicorn_better_regex.go +1 -1
- package/linthost/rules_unicorn_catch_error_name.go +19 -19
- package/linthost/rules_unicorn_consistent_assert.go +20 -20
- package/linthost/rules_unicorn_consistent_date_clone.go +27 -27
- package/linthost/rules_unicorn_consistent_destructuring.go +3 -3
- package/linthost/rules_unicorn_consistent_empty_array_spread.go +34 -34
- package/linthost/rules_unicorn_consistent_existence_index_check.go +42 -42
- package/linthost/rules_unicorn_consistent_function_scoping.go +3 -3
- package/linthost/rules_unicorn_consistent_template_literal_escape.go +3 -3
- package/linthost/rules_unicorn_custom_error_definition.go +92 -92
- package/linthost/rules_unicorn_empty_brace_spaces.go +47 -47
- package/linthost/rules_unicorn_error_message.go +34 -34
- package/linthost/rules_unicorn_escape_case.go +14 -14
- package/linthost/rules_unicorn_expiring_todo_comments.go +36 -36
- package/linthost/rules_unicorn_explicit_length_check.go +51 -51
- package/linthost/rules_unicorn_filename_case.go +1 -1
- package/linthost/rules_unicorn_import_style.go +1 -1
- package/linthost/rules_unicorn_isolated_functions.go +2 -2
- package/linthost/rules_unicorn_new_for_builtins.go +49 -49
- package/linthost/rules_unicorn_no_abusive_eslint_disable.go +31 -31
- package/linthost/rules_unicorn_no_accessor_recursion.go +69 -69
- package/linthost/rules_unicorn_no_anonymous_default_export.go +40 -40
- package/linthost/rules_unicorn_no_array_callback_reference.go +33 -33
- package/linthost/rules_unicorn_no_array_for_each.go +14 -14
- package/linthost/rules_unicorn_no_array_method_this_argument.go +29 -29
- package/linthost/rules_unicorn_no_array_reduce.go +15 -15
- package/linthost/rules_unicorn_no_array_reverse.go +17 -17
- package/linthost/rules_unicorn_no_array_sort.go +17 -17
- package/linthost/rules_unicorn_no_await_expression_member.go +12 -12
- package/linthost/rules_unicorn_no_await_in_promise_methods.go +38 -38
- package/linthost/rules_unicorn_no_console_spaces.go +30 -30
- package/linthost/rules_unicorn_no_document_cookie.go +13 -13
- package/linthost/rules_unicorn_no_empty_file.go +16 -16
- package/linthost/rules_unicorn_no_for_loop.go +58 -58
- package/linthost/rules_unicorn_no_hex_escape.go +11 -11
- package/linthost/rules_unicorn_no_immediate_mutation.go +55 -55
- package/linthost/rules_unicorn_no_instanceof_builtins.go +34 -34
- package/linthost/rules_unicorn_no_invalid_fetch_options.go +52 -52
- package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +25 -25
- package/linthost/rules_unicorn_no_keyword_prefix.go +56 -56
- package/linthost/rules_unicorn_no_lonely_if.go +21 -21
- package/linthost/rules_unicorn_no_magic_array_flat_depth.go +22 -22
- package/linthost/rules_unicorn_no_named_default.go +25 -25
- package/linthost/rules_unicorn_no_negated_condition.go +54 -54
- package/linthost/rules_unicorn_no_negation_in_equality_check.go +23 -23
- package/linthost/rules_unicorn_no_nested_ternary.go +15 -15
- package/linthost/rules_unicorn_no_new_array.go +5 -5
- package/linthost/rules_unicorn_no_new_buffer.go +5 -5
- package/linthost/rules_unicorn_no_null.go +2 -2
- package/linthost/rules_unicorn_no_object_as_default_parameter.go +19 -19
- package/linthost/rules_unicorn_no_process_exit.go +17 -17
- package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +29 -29
- package/linthost/rules_unicorn_no_static_only_class.go +27 -27
- package/linthost/rules_unicorn_no_thenable.go +47 -47
- package/linthost/rules_unicorn_no_this_assignment.go +10 -10
- package/linthost/rules_unicorn_no_typeof_undefined.go +31 -31
- package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +23 -23
- package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +37 -37
- package/linthost/rules_unicorn_no_unnecessary_await.go +24 -24
- package/linthost/rules_unicorn_no_unnecessary_slice_end.go +22 -22
- package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +67 -67
- package/linthost/rules_unicorn_no_unreadable_iife.go +22 -22
- package/linthost/rules_unicorn_no_useless_collection_argument.go +34 -34
- package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +18 -18
- package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +49 -49
- package/linthost/rules_unicorn_no_useless_iterator_to_array.go +41 -41
- package/linthost/rules_unicorn_no_useless_length_check.go +82 -82
- package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +42 -42
- package/linthost/rules_unicorn_no_useless_spread.go +38 -38
- package/linthost/rules_unicorn_no_useless_switch_case.go +29 -29
- package/linthost/rules_unicorn_no_useless_undefined.go +25 -25
- package/linthost/rules_unicorn_no_zero_fractions.go +17 -17
- package/linthost/rules_unicorn_number_literal_case.go +33 -33
- package/linthost/rules_unicorn_numeric_separators_style.go +36 -36
- package/linthost/rules_unicorn_prefer_add_event_listener.go +30 -30
- package/linthost/rules_unicorn_prefer_array_find.go +27 -27
- package/linthost/rules_unicorn_prefer_array_flat.go +25 -25
- package/linthost/rules_unicorn_prefer_array_flat_map.go +37 -37
- package/linthost/rules_unicorn_prefer_array_index_of.go +108 -108
- package/linthost/rules_unicorn_prefer_array_some.go +43 -43
- package/linthost/rules_unicorn_prefer_at.go +42 -42
- package/linthost/rules_unicorn_prefer_bigint_literals.go +42 -42
- package/linthost/rules_unicorn_prefer_blob_reading_methods.go +15 -15
- package/linthost/rules_unicorn_prefer_class_fields.go +57 -57
- package/linthost/rules_unicorn_prefer_classlist_toggle.go +76 -76
- package/linthost/rules_unicorn_prefer_code_point.go +21 -21
- package/linthost/rules_unicorn_prefer_date_now.go +47 -47
- package/linthost/rules_unicorn_prefer_default_parameters.go +96 -96
- package/linthost/rules_unicorn_prefer_dom_node_append.go +14 -14
- package/linthost/rules_unicorn_prefer_dom_node_dataset.go +27 -27
- package/linthost/rules_unicorn_prefer_dom_node_remove.go +17 -17
- package/linthost/rules_unicorn_prefer_dom_node_text_content.go +11 -11
- package/linthost/rules_unicorn_prefer_event_target.go +10 -10
- package/linthost/rules_unicorn_prefer_export_from.go +99 -99
- package/linthost/rules_unicorn_prefer_global_this.go +91 -91
- package/linthost/rules_unicorn_prefer_import_meta_properties.go +38 -38
- package/linthost/rules_unicorn_prefer_includes.go +108 -108
- package/linthost/rules_unicorn_prefer_json_parse_buffer.go +37 -37
- package/linthost/rules_unicorn_prefer_keyboard_event_key.go +10 -10
- package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +20 -20
- package/linthost/rules_unicorn_prefer_math_min_max.go +33 -33
- package/linthost/rules_unicorn_prefer_math_trunc.go +32 -32
- package/linthost/rules_unicorn_prefer_modern_dom_apis.go +18 -18
- package/linthost/rules_unicorn_prefer_modern_math_apis.go +38 -38
- package/linthost/rules_unicorn_prefer_module.go +22 -22
- package/linthost/rules_unicorn_prefer_native_coercion_functions.go +73 -73
- package/linthost/rules_unicorn_prefer_negative_index.go +46 -46
- package/linthost/rules_unicorn_prefer_node_protocol.go +90 -90
- package/linthost/rules_unicorn_prefer_number_properties.go +57 -57
- package/linthost/rules_unicorn_prefer_object_from_entries.go +26 -26
- package/linthost/rules_unicorn_prefer_optional_catch_binding.go +24 -24
- package/linthost/rules_unicorn_prefer_prototype_methods.go +25 -25
- package/linthost/rules_unicorn_prefer_query_selector.go +25 -25
- package/linthost/rules_unicorn_prefer_reflect_apply.go +10 -10
- package/linthost/rules_unicorn_prefer_regexp_test_rule.go +47 -47
- package/linthost/rules_unicorn_prefer_response_static_json.go +26 -26
- package/linthost/rules_unicorn_prefer_set_has.go +16 -16
- package/linthost/rules_unicorn_prefer_set_size.go +22 -22
- package/linthost/rules_unicorn_prefer_simple_condition_first.go +3 -3
- package/linthost/rules_unicorn_prefer_single_call.go +59 -59
- package/linthost/rules_unicorn_prefer_spread.go +24 -24
- package/linthost/rules_unicorn_prefer_string_raw.go +12 -12
- package/linthost/rules_unicorn_prefer_string_replace_all.go +46 -46
- package/linthost/rules_unicorn_prefer_string_slice.go +17 -17
- package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +104 -104
- package/linthost/rules_unicorn_prefer_string_trim_start_end.go +21 -21
- package/linthost/rules_unicorn_prefer_structured_clone.go +36 -36
- package/linthost/rules_unicorn_prefer_switch.go +65 -65
- package/linthost/rules_unicorn_prefer_ternary.go +35 -35
- package/linthost/rules_unicorn_prefer_top_level_await.go +34 -34
- package/linthost/rules_unicorn_prefer_type_error.go +84 -84
- package/linthost/rules_unicorn_prevent_abbreviations.go +68 -68
- package/linthost/rules_unicorn_relative_url_style.go +19 -19
- package/linthost/rules_unicorn_require_array_join_separator.go +18 -18
- package/linthost/rules_unicorn_require_module_attributes.go +25 -25
- package/linthost/rules_unicorn_require_module_specifiers.go +28 -28
- package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +18 -18
- package/linthost/rules_unicorn_require_post_message_target_origin.go +18 -18
- package/linthost/rules_unicorn_string_content.go +1 -1
- package/linthost/rules_unicorn_switch_case_braces.go +16 -16
- package/linthost/rules_unicorn_switch_case_break_position.go +3 -3
- package/linthost/rules_unicorn_template_indent.go +1 -1
- package/linthost/rules_unicorn_text_encoding_identifier_case.go +36 -36
- package/linthost/rules_unicorn_throw_new_error.go +30 -30
- package/linthost/rules_var.go +273 -3
- package/package.json +3 -3
- package/src/defaultFormat.ts +11 -7
- package/src/structures/ITtscLintConfig.ts +5 -5
- package/src/structures/TtscLintRuleSetting.ts +19 -19
- package/src/structures/{ITtscLintFormat.ts → format/ITtscLintFormat.ts} +48 -75
- package/src/structures/format/ITtscLintFormatJsDoc.ts +16 -0
- package/src/structures/format/ITtscLintFormatSortImports.ts +62 -0
- package/src/structures/format/index.ts +3 -0
- package/src/structures/index.ts +1 -1
- package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +20 -31
- package/src/structures/rules/ITtscLintBoundariesRules.ts +32 -36
- package/src/structures/rules/ITtscLintContributorRules.ts +6 -7
- package/src/structures/rules/ITtscLintCoreRules.ts +380 -408
- package/src/structures/rules/ITtscLintCypressRuleOptions.ts +5 -5
- package/src/structures/rules/ITtscLintCypressRules.ts +34 -38
- package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +28 -41
- package/src/structures/rules/ITtscLintFunctionalRules.ts +51 -56
- package/src/structures/rules/ITtscLintJestRules.ts +63 -74
- package/src/structures/rules/ITtscLintJsdocRules.ts +47 -54
- package/src/structures/rules/ITtscLintJsxA11yRules.ts +94 -102
- package/src/structures/rules/ITtscLintNextjsRules.ts +50 -55
- package/src/structures/rules/ITtscLintPlaywrightRules.ts +104 -122
- package/src/structures/rules/ITtscLintPromiseRules.ts +62 -71
- package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +4 -4
- package/src/structures/rules/ITtscLintReactPerfRules.ts +17 -19
- package/src/structures/rules/ITtscLintReactRuleOptions.ts +8 -10
- package/src/structures/rules/ITtscLintReactRules.ts +91 -104
- package/src/structures/rules/ITtscLintRegexpRules.ts +46 -54
- package/src/structures/rules/ITtscLintRuleOptionsMap.ts +7 -8
- package/src/structures/rules/ITtscLintSecurityRules.ts +45 -52
- package/src/structures/rules/ITtscLintSolidRules.ts +53 -56
- package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +3 -4
- package/src/structures/rules/ITtscLintStorybookRules.ts +60 -69
- package/src/structures/rules/ITtscLintTanstackQueryRules.ts +31 -37
- package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +2 -3
- package/src/structures/rules/ITtscLintTestingLibraryRules.ts +102 -119
- package/src/structures/rules/ITtscLintTypeScriptRules.ts +460 -518
- package/src/structures/rules/ITtscLintVitestRules.ts +43 -51
- package/lib/structures/ITtscLintFormat.js.map +0 -1
- /package/lib/structures/{ITtscLintFormat.js → format/ITtscLintFormat.js} +0 -0
|
@@ -2,6 +2,7 @@ package linthost
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
5
|
+
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
5
6
|
)
|
|
6
7
|
|
|
7
8
|
// printCallExpression renders a CallExpression with width-aware
|
|
@@ -46,12 +47,22 @@ func printCallExpression(ctx *PrintContext, node *shimast.Node) (Doc, bool) {
|
|
|
46
47
|
}
|
|
47
48
|
if call.TypeArguments != nil {
|
|
48
49
|
// Verbatim range covering `<A, B>` punctuation and members.
|
|
49
|
-
parts = append(parts, verbatimRange(ctx.Source,
|
|
50
|
+
parts = append(parts, verbatimRange(ctx.Source, typeArgsStart(ctx.Source, call.TypeArguments), typeArgsEnd(ctx.Source, call.TypeArguments)))
|
|
50
51
|
}
|
|
51
52
|
if hasNilEntry(call.Arguments) {
|
|
52
53
|
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
+
// Prettier never appends a trailing comma inside a dynamic
|
|
56
|
+
// `import(...)`, so the printer's reflow must agree with
|
|
57
|
+
// format/trailing-comma's same exception (see isDynamicImportCall).
|
|
58
|
+
addComma := ctx.allowsCallArgumentTrailingComma() && !isDynamicImportCall(call)
|
|
59
|
+
// A decorator's call hugs its last argument even past leading callbacks
|
|
60
|
+
// (`@OneToMany(() => P, (p) => p.c, { … })`); a plain call explodes there.
|
|
61
|
+
decoratorCall := node.Parent != nil && node.Parent.Kind == shimast.KindDecorator
|
|
62
|
+
// A test-framework call (`test("desc", () => { … })`) hugs its callback even
|
|
63
|
+
// when the description string pushes the opening line past printWidth, so the
|
|
64
|
+
// exploded fallback is dropped for it. See isTestCall.
|
|
65
|
+
argDoc, argCovered := printArgList(ctx, call.Arguments, addComma, decoratorCall, isTestCall(node))
|
|
55
66
|
parts = append(parts, argDoc)
|
|
56
67
|
return Concat(parts...), covered && argCovered
|
|
57
68
|
}
|
|
@@ -77,13 +88,13 @@ func printNewExpression(ctx *PrintContext, node *shimast.Node) (Doc, bool) {
|
|
|
77
88
|
covered = covered && !nodeSpansMultipleLines(ctx, ne.Expression)
|
|
78
89
|
}
|
|
79
90
|
if ne.TypeArguments != nil {
|
|
80
|
-
parts = append(parts, verbatimRange(ctx.Source,
|
|
91
|
+
parts = append(parts, verbatimRange(ctx.Source, typeArgsStart(ctx.Source, ne.TypeArguments), typeArgsEnd(ctx.Source, ne.TypeArguments)))
|
|
81
92
|
}
|
|
82
93
|
if ne.Arguments != nil {
|
|
83
94
|
if hasNilEntry(ne.Arguments) {
|
|
84
95
|
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
85
96
|
}
|
|
86
|
-
argDoc, argCovered := printArgList(ctx, ne.Arguments)
|
|
97
|
+
argDoc, argCovered := printArgList(ctx, ne.Arguments, ctx.allowsCallArgumentTrailingComma(), false, false)
|
|
87
98
|
parts = append(parts, argDoc)
|
|
88
99
|
covered = covered && argCovered
|
|
89
100
|
}
|
|
@@ -116,7 +127,14 @@ func hasNilEntry(list *shimast.NodeList) bool {
|
|
|
116
127
|
// layout, so the parens stay attached and the preceding arguments are
|
|
117
128
|
// not exploded onto their own lines. This is the Prettier behavior for
|
|
118
129
|
// `foo(x, () => { … })`.
|
|
119
|
-
|
|
130
|
+
// `addComma` is supplied by the caller (which honors `format.trailingComma`
|
|
131
|
+
// and the dynamic-import exception) rather than read here, so call and new
|
|
132
|
+
// expressions can diverge on the comma without printArgList knowing the
|
|
133
|
+
// callee. Call / new argument lists accepted trailing commas only in
|
|
134
|
+
// ES2017+, so Prettier's "es5" and "none" modes pass false; otherwise the
|
|
135
|
+
// printer would oscillate against format/trailing-comma on every cascade
|
|
136
|
+
// pass (rxjs hit this on ajax.ts and several operators / testing helpers).
|
|
137
|
+
func printArgList(ctx *PrintContext, list *shimast.NodeList, addComma bool, decoratorCall bool, forceHugLast bool) (Doc, bool) {
|
|
120
138
|
if list == nil {
|
|
121
139
|
return Text("()"), true
|
|
122
140
|
}
|
|
@@ -127,24 +145,290 @@ func printArgList(ctx *PrintContext, list *shimast.NodeList) (Doc, bool) {
|
|
|
127
145
|
covered = covered && childCovered
|
|
128
146
|
items = append(items, doc)
|
|
129
147
|
}
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
//
|
|
148
|
+
// Last-argument hugging wins when both predicates match; first-arg
|
|
149
|
+
// hugging only applies to the two-argument `callback, simpleArg` shape.
|
|
150
|
+
// Decline last-arg hugging when a leading argument forces the call
|
|
151
|
+
// multi-line on its own, so Prettier explodes the whole call rather than
|
|
152
|
+
// hugging the last argument. Two leading shapes trigger that: a function
|
|
153
|
+
// or arrow expression (`useMemo(() => x, [deps])`, even with an inline
|
|
154
|
+
// expression body Prettier never hugs after it), and any argument whose
|
|
155
|
+
// doc carries hard breaks (a block-bodied callback). A leading object or
|
|
156
|
+
// array that merely fits flat does NOT decline — Prettier still hugs the
|
|
157
|
+
// last argument there (`doConfigure({ … }, () => { … })`).
|
|
158
|
+
// A decorator's call hugs its last argument even past leading callbacks
|
|
159
|
+
// (`@OneToMany(() => P, (p) => p.c, { … })` keeps the arrows inline and
|
|
160
|
+
// breaks only the object); a plain call with two or more leading callbacks
|
|
161
|
+
// explodes instead, so the function-arg gate applies only off a decorator.
|
|
162
|
+
hugLast := shouldHugLastArgument(list.Nodes) &&
|
|
163
|
+
!anyLeadingItemBreaks(items) &&
|
|
164
|
+
(decoratorCall || !anyLeadingArgIsFunctionLike(list.Nodes))
|
|
165
|
+
// Two or more function/arrow arguments force the list to explode, one per
|
|
166
|
+
// line, even when it would fit flat: Prettier always breaks a call carrying
|
|
167
|
+
// multiple callbacks (`promise.then(() => a, () => b)`), the
|
|
168
|
+
// function-composition rule. The sole exception is a decorator hugging a
|
|
169
|
+
// huggable trailing argument (`@OneToMany(() => P, (p) => p.c, { … })`),
|
|
170
|
+
// where the leading arrows stay inline and only the object breaks — so the
|
|
171
|
+
// gate defers to hugLast off a decorator. See argListForcesFunctionBreak.
|
|
172
|
+
forceFnBreak := argListForcesFunctionBreak(list.Nodes, decoratorCall)
|
|
173
|
+
if forceFnBreak {
|
|
174
|
+
hugLast = false
|
|
175
|
+
}
|
|
176
|
+
// A test-framework call always hugs its trailing callback (the description
|
|
177
|
+
// string may overflow the open line); force the hug and drop the exploded
|
|
178
|
+
// fallback via HugLastForce.
|
|
179
|
+
if forceHugLast {
|
|
180
|
+
hugLast = true
|
|
181
|
+
forceFnBreak = false
|
|
182
|
+
}
|
|
137
183
|
shape := listShape{
|
|
138
|
-
OpenTok:
|
|
139
|
-
CloseTok:
|
|
140
|
-
Items:
|
|
141
|
-
Space:
|
|
142
|
-
AddComma:
|
|
143
|
-
HugLast:
|
|
184
|
+
OpenTok: "(",
|
|
185
|
+
CloseTok: ")",
|
|
186
|
+
Items: items,
|
|
187
|
+
Space: false,
|
|
188
|
+
AddComma: addComma,
|
|
189
|
+
HugLast: hugLast,
|
|
190
|
+
HugLastForce: forceHugLast,
|
|
191
|
+
HugFirst: !hugLast && !forceFnBreak && shouldHugFirstArgument(ctx, list.Nodes),
|
|
192
|
+
ForceBreak: forceFnBreak,
|
|
193
|
+
BlankBefore: blankBeforeItems(ctx.Source, list.Nodes),
|
|
144
194
|
}
|
|
145
195
|
return printList(ctx, shape), covered
|
|
146
196
|
}
|
|
147
197
|
|
|
198
|
+
// testCalleePatterns is Prettier's exact testCallCalleePatterns set (the dotted
|
|
199
|
+
// callee chains its isTestCallCallee matches). Matching the precise set, rather
|
|
200
|
+
// than "any base with a {only,skip,…} tail", avoids both over-matching
|
|
201
|
+
// (`test.each`, `it.todo` are NOT test calls) and under-matching (`test.fixme`,
|
|
202
|
+
// `test.describe.only` ARE).
|
|
203
|
+
var testCalleePatterns = map[string]bool{
|
|
204
|
+
"it": true, "it.only": true, "it.skip": true,
|
|
205
|
+
"describe": true, "describe.only": true, "describe.skip": true,
|
|
206
|
+
"test": true, "test.only": true, "test.skip": true,
|
|
207
|
+
"test.fixme": true, "test.step": true,
|
|
208
|
+
"test.describe": true, "test.describe.only": true,
|
|
209
|
+
"test.describe.skip": true, "test.describe.fixme": true,
|
|
210
|
+
"test.describe.parallel": true, "test.describe.parallel.only": true,
|
|
211
|
+
"test.describe.serial": true, "test.describe.serial.only": true,
|
|
212
|
+
"skip": true, "xit": true, "xdescribe": true, "xtest": true,
|
|
213
|
+
"fit": true, "fdescribe": true, "ftest": true,
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// calleeChain builds the dotted member-access chain of a callee rooted at a
|
|
217
|
+
// plain identifier (`test.describe.only` becomes "test.describe.only"), or ""
|
|
218
|
+
// when the callee is not a pure identifier / property-access chain (a computed
|
|
219
|
+
// access, a call, `this`, etc.).
|
|
220
|
+
func calleeChain(node *shimast.Node) string {
|
|
221
|
+
switch node.Kind {
|
|
222
|
+
case shimast.KindIdentifier:
|
|
223
|
+
return identifierText(node)
|
|
224
|
+
case shimast.KindPropertyAccessExpression:
|
|
225
|
+
pa := node.AsPropertyAccessExpression()
|
|
226
|
+
if pa == nil || pa.Name() == nil || pa.Name().Kind != shimast.KindIdentifier {
|
|
227
|
+
return ""
|
|
228
|
+
}
|
|
229
|
+
base := calleeChain(pa.Expression)
|
|
230
|
+
if base == "" {
|
|
231
|
+
return ""
|
|
232
|
+
}
|
|
233
|
+
return base + "." + identifierText(pa.Name())
|
|
234
|
+
}
|
|
235
|
+
return ""
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// testCalleeName reports whether `callee` is one of Prettier's recognized
|
|
239
|
+
// test-framework callees (see testCalleePatterns).
|
|
240
|
+
func testCalleeName(callee *shimast.Node) bool {
|
|
241
|
+
return callee != nil && testCalleePatterns[calleeChain(callee)]
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// isTestCall reports whether `node` is a test-framework call Prettier prints
|
|
245
|
+
// with its callback hugged regardless of width: `it(...)` / `test(...)` /
|
|
246
|
+
// `describe(...)` (and focus/skip variants) called with a string or template
|
|
247
|
+
// description and a trailing function/arrow. Prettier never explodes such a
|
|
248
|
+
// call's arguments, so the printer keeps the callback on the open-paren line
|
|
249
|
+
// even when the description string overflows printWidth (the callback's
|
|
250
|
+
// parameter count does not matter, verified against Prettier). Scoped to the
|
|
251
|
+
// two-argument form (the overwhelming shape); a three-argument timeout variant
|
|
252
|
+
// falls through to ordinary hugging.
|
|
253
|
+
func isTestCall(node *shimast.Node) bool {
|
|
254
|
+
if node == nil || node.Kind != shimast.KindCallExpression {
|
|
255
|
+
return false
|
|
256
|
+
}
|
|
257
|
+
call := node.AsCallExpression()
|
|
258
|
+
if call == nil || call.QuestionDotToken != nil || call.Arguments == nil {
|
|
259
|
+
return false
|
|
260
|
+
}
|
|
261
|
+
args := call.Arguments.Nodes
|
|
262
|
+
// Prettier accepts a two- or three-argument test call (the third is a numeric
|
|
263
|
+
// timeout): `it("name", () => { … })` and `it("name", () => { … }, 2500)`.
|
|
264
|
+
if len(args) != 2 && len(args) != 3 {
|
|
265
|
+
return false
|
|
266
|
+
}
|
|
267
|
+
if args[0] == nil || args[1] == nil {
|
|
268
|
+
return false
|
|
269
|
+
}
|
|
270
|
+
switch args[0].Kind {
|
|
271
|
+
case shimast.KindStringLiteral,
|
|
272
|
+
shimast.KindNoSubstitutionTemplateLiteral,
|
|
273
|
+
shimast.KindTemplateExpression:
|
|
274
|
+
default:
|
|
275
|
+
return false
|
|
276
|
+
}
|
|
277
|
+
if !testCalleeName(call.Expression) {
|
|
278
|
+
return false
|
|
279
|
+
}
|
|
280
|
+
if len(args) == 3 {
|
|
281
|
+
// The timeout argument must be numeric, and the callback a block-bodied
|
|
282
|
+
// function/arrow taking at most one parameter (Prettier's
|
|
283
|
+
// isFunctionOrArrowExpressionWithBody + parameter-count gate).
|
|
284
|
+
if args[2] == nil || args[2].Kind != shimast.KindNumericLiteral {
|
|
285
|
+
return false
|
|
286
|
+
}
|
|
287
|
+
return isBlockBodiedCallback(args[1]) && len(args[1].Parameters()) <= 1
|
|
288
|
+
}
|
|
289
|
+
return isFunctionLikeArg(args[1])
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// isBlockBodiedCallback reports whether a node is a function expression or an
|
|
293
|
+
// arrow with a block body (Prettier's isFunctionOrArrowExpressionWithBody).
|
|
294
|
+
func isBlockBodiedCallback(node *shimast.Node) bool {
|
|
295
|
+
if node == nil {
|
|
296
|
+
return false
|
|
297
|
+
}
|
|
298
|
+
switch node.Kind {
|
|
299
|
+
case shimast.KindFunctionExpression:
|
|
300
|
+
return true
|
|
301
|
+
case shimast.KindArrowFunction:
|
|
302
|
+
a := node.AsArrowFunction()
|
|
303
|
+
return a != nil && a.Body != nil && a.Body.Kind == shimast.KindBlock
|
|
304
|
+
}
|
|
305
|
+
return false
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// isFunctionLikeArg reports whether an argument is a function or arrow
|
|
309
|
+
// expression, the two shapes Prettier counts as "function" arguments.
|
|
310
|
+
func isFunctionLikeArg(node *shimast.Node) bool {
|
|
311
|
+
if node == nil {
|
|
312
|
+
return false
|
|
313
|
+
}
|
|
314
|
+
switch node.Kind {
|
|
315
|
+
case shimast.KindArrowFunction, shimast.KindFunctionExpression:
|
|
316
|
+
return true
|
|
317
|
+
}
|
|
318
|
+
return false
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// callArgsContainFunctionLike reports whether a CALL expression's own argument
|
|
322
|
+
// list carries a function/arrow argument. Prettier's function-composition test
|
|
323
|
+
// treats `foo.map((x) => x)` as a composed call, so a call carrying it
|
|
324
|
+
// alongside any second argument explodes. Only a call counts: Prettier's
|
|
325
|
+
// isCallExpression matches CallExpression / OptionalCallExpression but NOT a
|
|
326
|
+
// NewExpression, so `foo(new Bar(() => x), other)` is left inline.
|
|
327
|
+
func callArgsContainFunctionLike(node *shimast.Node) bool {
|
|
328
|
+
if node == nil || node.Kind != shimast.KindCallExpression {
|
|
329
|
+
return false
|
|
330
|
+
}
|
|
331
|
+
c := node.AsCallExpression()
|
|
332
|
+
if c == nil || c.Arguments == nil {
|
|
333
|
+
return false
|
|
334
|
+
}
|
|
335
|
+
for _, a := range c.Arguments.Nodes {
|
|
336
|
+
if isFunctionLikeArg(a) {
|
|
337
|
+
return true
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return false
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// isFunctionCompositionArgs mirrors Prettier's predicate of the same name: a
|
|
344
|
+
// call with two or more arguments is "function composition" when either two of
|
|
345
|
+
// them are themselves functions/arrows, or one is a call/new whose own
|
|
346
|
+
// arguments include a function/arrow (`stream.pipe(map((x) => x), other)`).
|
|
347
|
+
// Prettier breaks such a list onto one-argument-per-line unconditionally.
|
|
348
|
+
func isFunctionCompositionArgs(args []*shimast.Node) bool {
|
|
349
|
+
if len(args) <= 1 {
|
|
350
|
+
return false
|
|
351
|
+
}
|
|
352
|
+
fnCount := 0
|
|
353
|
+
for _, a := range args {
|
|
354
|
+
if isFunctionLikeArg(a) {
|
|
355
|
+
fnCount++
|
|
356
|
+
if fnCount > 1 {
|
|
357
|
+
return true
|
|
358
|
+
}
|
|
359
|
+
} else if callArgsContainFunctionLike(a) {
|
|
360
|
+
return true
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return false
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// argListForcesFunctionBreak reports whether a call's argument list must
|
|
367
|
+
// explode under Prettier's function-composition rule (see
|
|
368
|
+
// isFunctionCompositionArgs), which fires even when the call would fit on one
|
|
369
|
+
// line. A DECORATOR is exempt entirely: Prettier guards the rule with
|
|
370
|
+
// `path.parent.type !== "Decorator"` (printCallArguments in call-arguments.js),
|
|
371
|
+
// so `@ManyToOne(() => User, (u) => u.addresses)` stays flat when it fits and
|
|
372
|
+
// breaks only on width. Shared by printArgList (which sets ForceBreak) and the
|
|
373
|
+
// print-width rule (whose fit fast-path must not skip such a call when it is
|
|
374
|
+
// written flat in source).
|
|
375
|
+
func argListForcesFunctionBreak(args []*shimast.Node, decoratorCall bool) bool {
|
|
376
|
+
if decoratorCall {
|
|
377
|
+
return false
|
|
378
|
+
}
|
|
379
|
+
return isFunctionCompositionArgs(args)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// callForcesFunctionBreak reports whether a node is a CallExpression that the
|
|
383
|
+
// multiple-callback rule forces to explode. The print-width rule consults it
|
|
384
|
+
// so its flat-fit fast path does not leave such a call inline when the source
|
|
385
|
+
// wrote it on one line.
|
|
386
|
+
func callForcesFunctionBreak(node *shimast.Node) bool {
|
|
387
|
+
if node == nil || node.Kind != shimast.KindCallExpression {
|
|
388
|
+
return false
|
|
389
|
+
}
|
|
390
|
+
call := node.AsCallExpression()
|
|
391
|
+
if call == nil || call.Arguments == nil {
|
|
392
|
+
return false
|
|
393
|
+
}
|
|
394
|
+
decoratorCall := node.Parent != nil && node.Parent.Kind == shimast.KindDecorator
|
|
395
|
+
return argListForcesFunctionBreak(call.Arguments.Nodes, decoratorCall)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// anyLeadingArgIsFunctionLike reports whether any argument before the last
|
|
399
|
+
// is a function or arrow expression. Prettier declines last-argument
|
|
400
|
+
// hugging when a non-last argument is itself a function/arrow, regardless
|
|
401
|
+
// of its body, so `useMemo(() => compute(), [deps])` explodes rather than
|
|
402
|
+
// hugging the trailing array. This complements anyLeadingItemBreaks, which
|
|
403
|
+
// only catches leads with hard line breaks (a block body) and so misses an
|
|
404
|
+
// expression-bodied arrow.
|
|
405
|
+
func anyLeadingArgIsFunctionLike(args []*shimast.Node) bool {
|
|
406
|
+
for i := 0; i+1 < len(args); i++ {
|
|
407
|
+
if args[i] == nil {
|
|
408
|
+
continue
|
|
409
|
+
}
|
|
410
|
+
switch args[i].Kind {
|
|
411
|
+
case shimast.KindArrowFunction, shimast.KindFunctionExpression:
|
|
412
|
+
return true
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return false
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// anyLeadingItemBreaks reports whether any item before the last carries a
|
|
419
|
+
// hard line break — it cannot render flat. Such an item (a block-bodied
|
|
420
|
+
// callback) forces the call multi-line on its own, so last-argument
|
|
421
|
+
// hugging must decline and let the whole list explode, matching Prettier's
|
|
422
|
+
// willBreak gate on the non-last arguments.
|
|
423
|
+
func anyLeadingItemBreaks(items []Doc) bool {
|
|
424
|
+
for i := 0; i+1 < len(items); i++ {
|
|
425
|
+
if _, ok := flatten(items[i]); !ok {
|
|
426
|
+
return true
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return false
|
|
430
|
+
}
|
|
431
|
+
|
|
148
432
|
// shouldHugLastArgument reports whether the final entry of `args` is a
|
|
149
433
|
// shape Prettier keeps hugging the closing paren: an object or array
|
|
150
434
|
// literal, a function expression, or an arrow function whose body is a
|
|
@@ -164,9 +448,28 @@ func shouldHugLastArgument(args []*shimast.Node) bool {
|
|
|
164
448
|
return false
|
|
165
449
|
}
|
|
166
450
|
last := args[len(args)-1]
|
|
167
|
-
if last == nil {
|
|
451
|
+
if last == nil || !lastArgHuggableShape(last) {
|
|
168
452
|
return false
|
|
169
453
|
}
|
|
454
|
+
// Prettier's shouldGroupLastArg declines only when the penultimate argument
|
|
455
|
+
// is the SAME node kind as the last: two objects or two arrays compete for
|
|
456
|
+
// the break, so `new Sash(x, { … }, { … })` and `bar({ … }, { … })` explode.
|
|
457
|
+
// A different-kind penultimate (an arrow before an object, `@OneToMany(() =>
|
|
458
|
+
// P, (p) => p.c, { … })`, or a plain `foo(a, b, { … })`) still hugs.
|
|
459
|
+
if len(args) >= 2 {
|
|
460
|
+
if pen := args[len(args)-2]; pen != nil && pen.Kind == last.Kind {
|
|
461
|
+
return false
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return true
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// lastArgHuggableShape reports whether `node` is the shape Prettier keeps
|
|
468
|
+
// hugging the closing paren: an object/array literal, a function expression,
|
|
469
|
+
// or an arrow whose body is a block, object, or array. An expression-bodied
|
|
470
|
+
// arrow (`(x) => x.id`) is excluded: it has no internal break point, so the
|
|
471
|
+
// flat hugging Concat would pin an overflowing call to one line.
|
|
472
|
+
func lastArgHuggableShape(last *shimast.Node) bool {
|
|
170
473
|
switch last.Kind {
|
|
171
474
|
case shimast.KindFunctionExpression,
|
|
172
475
|
shimast.KindObjectLiteralExpression,
|
|
@@ -186,15 +489,191 @@ func shouldHugLastArgument(args []*shimast.Node) bool {
|
|
|
186
489
|
}
|
|
187
490
|
}
|
|
188
491
|
switch body.Kind {
|
|
189
|
-
case shimast.KindBlock
|
|
190
|
-
|
|
492
|
+
case shimast.KindBlock:
|
|
493
|
+
// A block-bodied arrow hugs regardless of any return-type annotation.
|
|
494
|
+
return true
|
|
495
|
+
case shimast.KindObjectLiteralExpression,
|
|
191
496
|
shimast.KindArrayLiteralExpression:
|
|
497
|
+
// An expression-bodied arrow with an explicit return type is not hugged:
|
|
498
|
+
// Prettier's couldGroupArg excludes it ("avoid breaking inside composite
|
|
499
|
+
// return types"), so `map((r): T => ({ … }))` explodes the whole list
|
|
500
|
+
// while `map((r) => ({ … }))` hugs.
|
|
501
|
+
return arrow.Type == nil
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return false
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// shouldHugFirstArgument reports whether a call's argument list takes
|
|
508
|
+
// Prettier's "first-argument hugging" shape: exactly two arguments where
|
|
509
|
+
// the first is a block-bodied callback and the second is a short, simple
|
|
510
|
+
// value. `foo(() => { … }, target)` keeps the callback attached to the
|
|
511
|
+
// open paren and flows `, target)` after its closing brace, instead of
|
|
512
|
+
// exploding both arguments onto their own lines.
|
|
513
|
+
//
|
|
514
|
+
// Mirrors Prettier's shouldGroupFirstArg: it declines when the second
|
|
515
|
+
// argument is itself a function, arrow, conditional, or any expandable
|
|
516
|
+
// shape, so `both(() => {}, () => {})` falls through to the exploded
|
|
517
|
+
// list rather than hugging.
|
|
518
|
+
func shouldHugFirstArgument(ctx *PrintContext, args []*shimast.Node) bool {
|
|
519
|
+
if len(args) != 2 {
|
|
520
|
+
return false
|
|
521
|
+
}
|
|
522
|
+
first, second := args[0], args[1]
|
|
523
|
+
if first == nil || second == nil {
|
|
524
|
+
return false
|
|
525
|
+
}
|
|
526
|
+
return isFirstArgHuggableCallback(first) && isSimpleTrailingArg(ctx, second)
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// isFirstArgHuggableCallback reports whether `node` is the callback shape
|
|
530
|
+
// Prettier hugs in the first-argument position: a function expression or
|
|
531
|
+
// an arrow with a block body. An expression-bodied arrow is excluded
|
|
532
|
+
// because it carries no internal break point.
|
|
533
|
+
func isFirstArgHuggableCallback(node *shimast.Node) bool {
|
|
534
|
+
switch node.Kind {
|
|
535
|
+
case shimast.KindFunctionExpression:
|
|
536
|
+
return true
|
|
537
|
+
case shimast.KindArrowFunction:
|
|
538
|
+
arrow := node.AsArrowFunction()
|
|
539
|
+
return arrow != nil && arrow.Body != nil && arrow.Body.Kind == shimast.KindBlock
|
|
540
|
+
}
|
|
541
|
+
return false
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// isSimpleTrailingArg reports whether `node` is a value that may trail a
|
|
545
|
+
// hugged first-argument callback. Prettier hugs the leading callback when
|
|
546
|
+
// the trailing argument is an identifier, member access, literal, `this`,
|
|
547
|
+
// or an array literal — most notably the `useEffect(() => { … }, [deps])`
|
|
548
|
+
// idiom. It also accepts an empty object literal, a short call/new, and a
|
|
549
|
+
// short arithmetic/logical expression (`setTimeout(fn, 1000 - x)`). A function,
|
|
550
|
+
// arrow, conditional, or a non-empty object literal is excluded so
|
|
551
|
+
// first-argument hugging declines and the whole list explodes.
|
|
552
|
+
//
|
|
553
|
+
// A call expression is deliberately NOT included: the conditional-group
|
|
554
|
+
// fit check only measures an option's first line, so a hugged-first option
|
|
555
|
+
// whose trailing call overflows the closing line (`}, deeplyNested(…))`)
|
|
556
|
+
// would still be selected, where Prettier explodes. The array case shares
|
|
557
|
+
// that limitation in principle, but dependency arrays are short in
|
|
558
|
+
// practice, the same way the identifier/member cases already are.
|
|
559
|
+
func isSimpleTrailingArg(ctx *PrintContext, node *shimast.Node) bool {
|
|
560
|
+
switch node.Kind {
|
|
561
|
+
case shimast.KindIdentifier,
|
|
562
|
+
shimast.KindStringLiteral,
|
|
563
|
+
shimast.KindNumericLiteral,
|
|
564
|
+
shimast.KindBigIntLiteral,
|
|
565
|
+
shimast.KindTrueKeyword,
|
|
566
|
+
shimast.KindFalseKeyword,
|
|
567
|
+
shimast.KindNullKeyword,
|
|
568
|
+
shimast.KindThisKeyword,
|
|
569
|
+
shimast.KindPropertyAccessExpression,
|
|
570
|
+
shimast.KindElementAccessExpression,
|
|
571
|
+
shimast.KindArrayLiteralExpression:
|
|
572
|
+
return true
|
|
573
|
+
case shimast.KindAsExpression:
|
|
574
|
+
// `[] as string[]`: the `reduce(fn, [] as T[])` idiom. Hug when the cast
|
|
575
|
+
// wraps a value that is itself a simple trailing arg AND the target type is
|
|
576
|
+
// simple. A type carrying an object type literal (`[] as Array<{ … }>`) is
|
|
577
|
+
// not simple, Prettier expands and explodes the list there, so exclude any
|
|
578
|
+
// type whose source contains a `{` (a type literal).
|
|
579
|
+
if as := node.AsAsExpression(); as != nil && as.Expression != nil {
|
|
580
|
+
return isSimpleTrailingArg(ctx, as.Expression) && !typeHasObjectLiteral(ctx.Source, as.Type)
|
|
581
|
+
}
|
|
582
|
+
case shimast.KindCallExpression, shimast.KindNewExpression:
|
|
583
|
+
// `reduce(fn, Object.create(null))` / `reduce(fn, new Map<…>())`: Prettier
|
|
584
|
+
// hugs the first arg when the trailing call/new has at most one value
|
|
585
|
+
// argument, regardless of its length, type arguments and long names do not
|
|
586
|
+
// matter and the close line is allowed to overflow. A call with two or more
|
|
587
|
+
// arguments explodes the whole list instead. Mirrors Prettier's
|
|
588
|
+
// isHopefullyShortCallArgument for call-like nodes.
|
|
589
|
+
return callValueArgCount(node) <= 1
|
|
590
|
+
case shimast.KindObjectLiteralExpression:
|
|
591
|
+
// `reduce(fn, {})`: an EMPTY object literal hugs (Prettier's couldGroupArg
|
|
592
|
+
// excludes a property-less object); an object with properties expands and
|
|
593
|
+
// explodes the list instead (`f(fn, { a: 1 })`).
|
|
594
|
+
if obj := node.AsObjectLiteralExpression(); obj != nil {
|
|
595
|
+
return obj.Properties == nil || len(obj.Properties.Nodes) == 0
|
|
596
|
+
}
|
|
597
|
+
case shimast.KindBinaryExpression:
|
|
598
|
+
// `setTimeout(fn, 1000 - ellapsed)`: a SINGLE arithmetic/logical operation
|
|
599
|
+
// whose two operands are simple leaves rides the close line and hugs. A
|
|
600
|
+
// chained binary (`60 * 60 * 1000`, an operand itself a binary) is not
|
|
601
|
+
// simple and explodes the list, matching Prettier's isHopefullyShortCallArgument
|
|
602
|
+
// (which only treats a binaryish short when both sides are themselves short).
|
|
603
|
+
if bin := node.AsBinaryExpression(); bin != nil {
|
|
604
|
+
return isSimpleBinaryOperand(bin.Left) && isSimpleBinaryOperand(bin.Right)
|
|
605
|
+
}
|
|
606
|
+
case shimast.KindPrefixUnaryExpression:
|
|
607
|
+
// `reduce(fn, -1)`: a unary applied to a simple leaf rides the close line.
|
|
608
|
+
if u := node.AsPrefixUnaryExpression(); u != nil {
|
|
609
|
+
return isSimpleBinaryOperand(u.Operand)
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return false
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// isSimpleBinaryOperand reports whether a node is a short, non-recursive
|
|
616
|
+
// operand, an identifier, a literal, `this`, or a member access. A binary,
|
|
617
|
+
// call, conditional, or other compound expression is not, so a binary built
|
|
618
|
+
// from such operands is treated as too complex to ride a hugged close line.
|
|
619
|
+
func isSimpleBinaryOperand(node *shimast.Node) bool {
|
|
620
|
+
if node == nil {
|
|
621
|
+
return false
|
|
622
|
+
}
|
|
623
|
+
switch node.Kind {
|
|
624
|
+
case shimast.KindIdentifier,
|
|
625
|
+
shimast.KindNumericLiteral,
|
|
626
|
+
shimast.KindStringLiteral,
|
|
627
|
+
shimast.KindBigIntLiteral,
|
|
628
|
+
shimast.KindTrueKeyword,
|
|
629
|
+
shimast.KindFalseKeyword,
|
|
630
|
+
shimast.KindNullKeyword,
|
|
631
|
+
shimast.KindThisKeyword,
|
|
632
|
+
shimast.KindPropertyAccessExpression,
|
|
633
|
+
shimast.KindElementAccessExpression:
|
|
634
|
+
return true
|
|
635
|
+
}
|
|
636
|
+
return false
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// typeHasObjectLiteral reports whether a type node's source contains a `{`,
|
|
640
|
+
// the mark of an object type literal (`{ a: 1 }`, `Array<{ … }>`). Prettier's
|
|
641
|
+
// isSimpleType rejects such a type; a flat type (`string[]`, `Foo<Bar>`,
|
|
642
|
+
// `number[][]`) has none and stays simple.
|
|
643
|
+
func typeHasObjectLiteral(src string, typeNode *shimast.Node) bool {
|
|
644
|
+
if typeNode == nil {
|
|
645
|
+
return false
|
|
646
|
+
}
|
|
647
|
+
start := shimscanner.SkipTrivia(src, typeNode.Pos())
|
|
648
|
+
end := typeNode.End()
|
|
649
|
+
if start < 0 || end < start || end > len(src) {
|
|
650
|
+
return true // unmeasurable: be conservative and decline the hug
|
|
651
|
+
}
|
|
652
|
+
for i := start; i < end; i++ {
|
|
653
|
+
if src[i] == '{' {
|
|
192
654
|
return true
|
|
193
655
|
}
|
|
194
656
|
}
|
|
195
657
|
return false
|
|
196
658
|
}
|
|
197
659
|
|
|
660
|
+
// callValueArgCount returns the number of value arguments on a call or new
|
|
661
|
+
// expression (type arguments are not counted). A new expression with no
|
|
662
|
+
// argument list (`new Foo`) counts as zero.
|
|
663
|
+
func callValueArgCount(node *shimast.Node) int {
|
|
664
|
+
switch node.Kind {
|
|
665
|
+
case shimast.KindCallExpression:
|
|
666
|
+
if c := node.AsCallExpression(); c != nil && c.Arguments != nil {
|
|
667
|
+
return len(c.Arguments.Nodes)
|
|
668
|
+
}
|
|
669
|
+
case shimast.KindNewExpression:
|
|
670
|
+
if n := node.AsNewExpression(); n != nil && n.Arguments != nil {
|
|
671
|
+
return len(n.Arguments.Nodes)
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return 0
|
|
675
|
+
}
|
|
676
|
+
|
|
198
677
|
// forceBreakFirstGroup returns `doc` with the first Group found in a
|
|
199
678
|
// left-to-right walk of its subtree forced broken, and reports whether
|
|
200
679
|
// one was found. printListHuggingLast uses it to commit a hugged
|
|
@@ -225,72 +704,34 @@ func forceBreakFirstGroup(doc Doc) (Doc, bool) {
|
|
|
225
704
|
|
|
226
705
|
// Type-argument byte-range helpers. The shim's NodeList.End() points
|
|
227
706
|
// past the last argument; the surrounding `<` and `>` are not part of
|
|
228
|
-
// the list's range, so we have to scan around it.
|
|
707
|
+
// the list's range, so we have to scan around it. Call and new
|
|
708
|
+
// expressions share these — only the field holding the list differs.
|
|
229
709
|
|
|
230
|
-
//
|
|
231
|
-
// type-argument list
|
|
232
|
-
func
|
|
233
|
-
if
|
|
234
|
-
return -1
|
|
235
|
-
}
|
|
236
|
-
first := call.TypeArguments.Nodes[0]
|
|
237
|
-
if first == nil {
|
|
710
|
+
// typeArgsStart returns the byte offset of the `<` that opens a
|
|
711
|
+
// type-argument list. Returns -1 when absent.
|
|
712
|
+
func typeArgsStart(src string, list *shimast.NodeList) int {
|
|
713
|
+
if list == nil || len(list.Nodes) == 0 || list.Nodes[0] == nil {
|
|
238
714
|
return -1
|
|
239
715
|
}
|
|
240
716
|
// `<` is the byte immediately before the first type argument
|
|
241
717
|
// (modulo whitespace).
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if ctx.Source[i] == '<' {
|
|
245
|
-
return i
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return -1
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// callTypeArgsEnd returns the byte offset one past the closing `>` of a
|
|
252
|
-
// CallExpression's type-argument list. Returns -1 when absent.
|
|
253
|
-
func callTypeArgsEnd(ctx *PrintContext, call *shimast.CallExpression) int {
|
|
254
|
-
if call.TypeArguments == nil {
|
|
255
|
-
return -1
|
|
256
|
-
}
|
|
257
|
-
end := call.TypeArguments.End()
|
|
258
|
-
for i := end; i < len(ctx.Source); i++ {
|
|
259
|
-
if ctx.Source[i] == '>' {
|
|
260
|
-
return i + 1
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return end
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// newTypeArgsStart returns the byte offset of the `<` that opens the
|
|
267
|
-
// type-argument list of a NewExpression. Returns -1 when absent.
|
|
268
|
-
func newTypeArgsStart(ctx *PrintContext, ne *shimast.NewExpression) int {
|
|
269
|
-
if ne.TypeArguments == nil || len(ne.TypeArguments.Nodes) == 0 {
|
|
270
|
-
return -1
|
|
271
|
-
}
|
|
272
|
-
first := ne.TypeArguments.Nodes[0]
|
|
273
|
-
if first == nil {
|
|
274
|
-
return -1
|
|
275
|
-
}
|
|
276
|
-
pos := first.Pos()
|
|
277
|
-
for i := pos - 1; i >= 0; i-- {
|
|
278
|
-
if ctx.Source[i] == '<' {
|
|
718
|
+
for i := list.Nodes[0].Pos() - 1; i >= 0; i-- {
|
|
719
|
+
if src[i] == '<' {
|
|
279
720
|
return i
|
|
280
721
|
}
|
|
281
722
|
}
|
|
282
723
|
return -1
|
|
283
724
|
}
|
|
284
725
|
|
|
285
|
-
//
|
|
286
|
-
//
|
|
287
|
-
func
|
|
288
|
-
if
|
|
726
|
+
// typeArgsEnd returns the byte offset one past the closing `>` of a
|
|
727
|
+
// type-argument list. Returns -1 when the list is absent.
|
|
728
|
+
func typeArgsEnd(src string, list *shimast.NodeList) int {
|
|
729
|
+
if list == nil {
|
|
289
730
|
return -1
|
|
290
731
|
}
|
|
291
|
-
end :=
|
|
292
|
-
for i := end; i < len(
|
|
293
|
-
if
|
|
732
|
+
end := list.End()
|
|
733
|
+
for i := end; i < len(src); i++ {
|
|
734
|
+
if src[i] == '>' {
|
|
294
735
|
return i + 1
|
|
295
736
|
}
|
|
296
737
|
}
|