@ttsc/lint 0.14.0-dev.20260529.1 → 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 +85 -87
- 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
|
@@ -180,6 +180,16 @@ func printBlock(ctx *PrintContext, node *shimast.Node) (Doc, bool) {
|
|
|
180
180
|
bodyParts := make([]Doc, 0, len(items)*2)
|
|
181
181
|
for i, item := range items {
|
|
182
182
|
if i > 0 {
|
|
183
|
+
// A lone leading-semicolon ASI guard stays glued to the statement
|
|
184
|
+
// it protects (`;(expr)`): when the previous statement is an empty
|
|
185
|
+
// `;` sitting directly against this one in the source, emit no line
|
|
186
|
+
// break, so the reflow agrees with format/orphan-semi instead of
|
|
187
|
+
// ping-ponging it back onto two lines every cascade pass.
|
|
188
|
+
if stmts[i-1].Kind == shimast.KindEmptyStatement &&
|
|
189
|
+
!rangeHasNewline(ctx.Source, stmts[i-1].End(), shimscanner.SkipTrivia(ctx.Source, stmts[i].Pos())) {
|
|
190
|
+
bodyParts = append(bodyParts, item)
|
|
191
|
+
continue
|
|
192
|
+
}
|
|
183
193
|
if blankLineBetweenStatements(ctx.Source, stmts[i-1].End(), stmts[i].Pos()) {
|
|
184
194
|
bodyParts = append(bodyParts, Literalline())
|
|
185
195
|
}
|
|
@@ -196,6 +206,21 @@ func printBlock(ctx *PrintContext, node *shimast.Node) (Doc, bool) {
|
|
|
196
206
|
return doc, covered
|
|
197
207
|
}
|
|
198
208
|
|
|
209
|
+
// rangeHasNewline reports whether src[start:end) contains a newline. Used
|
|
210
|
+
// to detect whether a leading-semicolon guard sits on the same line as
|
|
211
|
+
// the statement it protects.
|
|
212
|
+
func rangeHasNewline(src string, start, end int) bool {
|
|
213
|
+
if start < 0 || end > len(src) || end <= start {
|
|
214
|
+
return false
|
|
215
|
+
}
|
|
216
|
+
for i := start; i < end; i++ {
|
|
217
|
+
if src[i] == '\n' {
|
|
218
|
+
return true
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return false
|
|
222
|
+
}
|
|
223
|
+
|
|
199
224
|
// blankLineBetweenStatements reports whether the source gap between the
|
|
200
225
|
// end of one block statement and the start of the next contains a blank
|
|
201
226
|
// line — two or more newlines. printBlock uses it to keep a single
|
|
@@ -115,39 +115,72 @@ func printImportDeclaration(ctx *PrintContext, node *shimast.Node) (Doc, bool) {
|
|
|
115
115
|
if clauseData == nil || clauseData.NamedBindings == nil {
|
|
116
116
|
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
117
117
|
}
|
|
118
|
-
|
|
118
|
+
nb := clauseData.NamedBindings
|
|
119
|
+
if nb.Kind != shimast.KindNamedImports {
|
|
119
120
|
// Namespace imports (`import * as ns from "x"`) have no
|
|
120
121
|
// reflow surface; leave them alone.
|
|
121
122
|
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
122
123
|
}
|
|
123
|
-
if clause.Name() != nil {
|
|
124
|
-
// `import Default, { … } from "x"` — keep verbatim for v1.
|
|
125
|
-
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
126
|
-
}
|
|
127
124
|
// AttributeClause (`with { ... }` / `assert { ... }`) lives after
|
|
128
125
|
// the module specifier. Fall back to verbatim when present so we
|
|
129
126
|
// don't drop attributes silently.
|
|
130
127
|
if imp.Attributes != nil {
|
|
131
128
|
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
132
129
|
}
|
|
130
|
+
// A comment between specifiers would be dropped by the fresh separators.
|
|
131
|
+
if listHasInterItemComments(ctx, nb) {
|
|
132
|
+
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
133
|
+
}
|
|
134
|
+
ni := nb.AsNamedImports()
|
|
135
|
+
if ni == nil || ni.Elements == nil {
|
|
136
|
+
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
137
|
+
}
|
|
133
138
|
|
|
134
|
-
// Bracketed clause prefix: `import `
|
|
139
|
+
// Bracketed clause prefix: `import `, `import type `, or — when a default
|
|
140
|
+
// binding precedes the named clause — `import Default, `. A default never
|
|
141
|
+
// combines with `type` (TS forbids `import type D, { … }`), so the two
|
|
142
|
+
// prefix forms are exclusive.
|
|
135
143
|
prefix := "import "
|
|
136
144
|
if clause.IsTypeOnly() {
|
|
137
145
|
prefix = "import type "
|
|
138
146
|
}
|
|
139
|
-
|
|
147
|
+
if name := clause.Name(); name != nil {
|
|
148
|
+
prefix = "import " + identifierText(name) + ", "
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
items := make([]Doc, 0, len(ni.Elements.Nodes))
|
|
152
|
+
covered := true
|
|
153
|
+
for _, spec := range ni.Elements.Nodes {
|
|
154
|
+
if spec == nil {
|
|
155
|
+
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
156
|
+
}
|
|
157
|
+
doc, childCovered := PrintNode(ctx, spec)
|
|
158
|
+
covered = covered && childCovered
|
|
159
|
+
items = append(items, doc)
|
|
160
|
+
}
|
|
161
|
+
|
|
140
162
|
moduleSpec := verbatim(ctx, imp.ModuleSpecifier)
|
|
141
163
|
covered = covered && !nodeSpansMultipleLines(ctx, imp.ModuleSpecifier)
|
|
142
|
-
|
|
164
|
+
suffixParts := []Doc{Text(" from "), moduleSpec}
|
|
143
165
|
if sourceHasStatementTerminator(ctx.Source, node.End()) {
|
|
144
|
-
// Preserve the user's terminator decision. Emitting `;`
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
// `;;` — `format/semi` owns terminator placement.
|
|
148
|
-
parts = append(parts, Text(";"))
|
|
166
|
+
// Preserve the user's terminator decision. Emitting `;` unconditionally
|
|
167
|
+
// would collide with `format/semi`'s zero-width insert and produce `;;`.
|
|
168
|
+
suffixParts = append(suffixParts, Text(";"))
|
|
149
169
|
}
|
|
150
|
-
|
|
170
|
+
|
|
171
|
+
// The whole declaration renders as one Group via Prefix/Suffix, so the
|
|
172
|
+
// named-brace break decision counts the ` from "..."` tail: a brace that
|
|
173
|
+
// fits but whose declaration line overflows still breaks, and a
|
|
174
|
+
// default-combined import breaks its brace too.
|
|
175
|
+
return printList(ctx, listShape{
|
|
176
|
+
Prefix: Text(prefix),
|
|
177
|
+
OpenTok: "{",
|
|
178
|
+
CloseTok: "}",
|
|
179
|
+
Items: items,
|
|
180
|
+
Space: true,
|
|
181
|
+
AddComma: ctx.allowsEs5TrailingComma(),
|
|
182
|
+
Suffix: Concat(suffixParts...),
|
|
183
|
+
}), covered
|
|
151
184
|
}
|
|
152
185
|
|
|
153
186
|
// sourceHasStatementTerminator reports whether the last non-trivia
|
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
package linthost
|
|
2
2
|
|
|
3
|
+
import (
|
|
4
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
5
|
+
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// listHasInterItemComments reports whether `node` (an object / array literal)
|
|
9
|
+
// carries a comment in a gap between its items or brackets. The list printers
|
|
10
|
+
// mint fresh comma/line separators that have no slot for such trivia, so a
|
|
11
|
+
// reflow would silently delete the comment. When a node nested inside a
|
|
12
|
+
// reflowing parent (an array argument of a call) carries one, the parent's
|
|
13
|
+
// own top-level comment guard cannot see it (it lives inside a child range),
|
|
14
|
+
// so each list printer must check itself and bail to verbatim — reporting the
|
|
15
|
+
// span uncovered so the enclosing reflow abstains and the source round-trips.
|
|
16
|
+
func listHasInterItemComments(ctx *PrintContext, node *shimast.Node) bool {
|
|
17
|
+
if node == nil {
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
start := shimscanner.SkipTrivia(ctx.Source, node.Pos())
|
|
21
|
+
end := node.End()
|
|
22
|
+
if start < 0 || end < start || end > len(ctx.Source) {
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
return hasNonChildComments(node, ctx.Source, start, end)
|
|
26
|
+
}
|
|
27
|
+
|
|
3
28
|
// Shared helpers for comma-separated list printers.
|
|
4
29
|
//
|
|
5
30
|
// Object literals, array literals, call arguments, parameter lists,
|
|
@@ -35,11 +60,71 @@ type listShape struct {
|
|
|
35
60
|
// multi-line callback body does not force every preceding argument
|
|
36
61
|
// onto its own line.
|
|
37
62
|
HugLast bool
|
|
63
|
+
// HugFirst keeps the FIRST item attached to the open paren and flows
|
|
64
|
+
// the remaining simple items after it, the mirror of HugLast. The
|
|
65
|
+
// call-argument printer sets it for the two-argument
|
|
66
|
+
// `callback, simpleArg` shape Prettier hugs (`foo(() => { … }, x)`).
|
|
67
|
+
// HugLast and HugFirst are mutually exclusive.
|
|
68
|
+
HugFirst bool
|
|
69
|
+
// HugLastForce drops the exploded fallback from a HugLast list: the hugged
|
|
70
|
+
// shape is chosen even when its opening line overflows printWidth. The
|
|
71
|
+
// call-argument printer sets it for a test-framework call
|
|
72
|
+
// (`test("very long description", () => { … })`), which Prettier never
|
|
73
|
+
// explodes — the callback always rides the open paren. Requires HugLast.
|
|
74
|
+
HugLastForce bool
|
|
38
75
|
// ForceBreak commits the list to its broken, one-item-per-line shape
|
|
39
76
|
// even when it would fit flat. The object-literal printer sets it to
|
|
40
77
|
// mirror Prettier's objectWrap:"preserve" — an object the source
|
|
41
78
|
// wrote with a newline after `{` stays expanded.
|
|
42
79
|
ForceBreak bool
|
|
80
|
+
// Fill packs the items with Prettier's fill layout — as many per line as
|
|
81
|
+
// fit — instead of one item per line when the list breaks. The array
|
|
82
|
+
// printer sets it for a concisely-printed numeric array. Mutually
|
|
83
|
+
// exclusive with HugLast / HugFirst.
|
|
84
|
+
Fill bool
|
|
85
|
+
// Prefix and Suffix are emitted inside the list's Group, before OpEN and
|
|
86
|
+
// after CLOSE respectively. They let a caller fold surrounding tokens into
|
|
87
|
+
// the same fit-or-break decision: an import declaration sets Prefix to
|
|
88
|
+
// `import ` (or `import D, `) and Suffix to ` from "..."` so the named-brace
|
|
89
|
+
// group's flat-fit check counts the whole declaration line — Prettier never
|
|
90
|
+
// breaks a brace that fits but whose `from` tail overflows is measured here,
|
|
91
|
+
// not in a separate group. Only used on the plain (non-hugging) path.
|
|
92
|
+
Prefix Doc
|
|
93
|
+
Suffix Doc
|
|
94
|
+
// BlankBefore[i] reports whether the source had a blank line before item i
|
|
95
|
+
// (i.e. between item i-1 and item i). When any entry is set the list is
|
|
96
|
+
// forced broken and a single blank line is preserved before that item,
|
|
97
|
+
// mirroring Prettier. Length, when non-nil, equals len(Items); index 0 is
|
|
98
|
+
// ignored (no item precedes the first).
|
|
99
|
+
BlankBefore []bool
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// blankBeforeItems computes BlankBefore for a node list: entry i is true when
|
|
103
|
+
// the source had a blank line (two or more newlines) between item i-1 and
|
|
104
|
+
// item i. Returns nil for a list too short to carry one, so callers pass it
|
|
105
|
+
// through unconditionally.
|
|
106
|
+
func blankBeforeItems(src string, elems []*shimast.Node) []bool {
|
|
107
|
+
if len(elems) < 2 {
|
|
108
|
+
return nil
|
|
109
|
+
}
|
|
110
|
+
out := make([]bool, len(elems))
|
|
111
|
+
for i := 1; i < len(elems); i++ {
|
|
112
|
+
if elems[i-1] == nil || elems[i] == nil {
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
out[i] = blankLineBetweenStatements(src, elems[i-1].End(), elems[i].Pos())
|
|
116
|
+
}
|
|
117
|
+
return out
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// hasBlankBefore reports whether any item carries a preserved blank line.
|
|
121
|
+
func (s listShape) hasBlankBefore() bool {
|
|
122
|
+
for _, b := range s.BlankBefore {
|
|
123
|
+
if b {
|
|
124
|
+
return true
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return false
|
|
43
128
|
}
|
|
44
129
|
|
|
45
130
|
// printList renders the list shape as a Doc tree. Empty lists collapse
|
|
@@ -50,19 +135,33 @@ func printList(ctx *PrintContext, shape listShape) Doc {
|
|
|
50
135
|
return Text(shape.OpenTok + shape.CloseTok)
|
|
51
136
|
}
|
|
52
137
|
plain := printListPlain(ctx, shape)
|
|
53
|
-
|
|
138
|
+
// A source blank line forces the plain broken layout (Prettier never hugs or
|
|
139
|
+
// packs flat across a blank line), so skip the hugging ConditionalGroup.
|
|
140
|
+
if (!shape.HugLast && !shape.HugFirst) || shape.hasBlankBefore() {
|
|
54
141
|
return plain
|
|
55
142
|
}
|
|
56
|
-
// A
|
|
143
|
+
// A hugging list offers the engine up to three shapes, in preference
|
|
57
144
|
// order:
|
|
58
145
|
// 1. allFlat — every item on one line, chosen when it fits;
|
|
59
|
-
// 2. hugged —
|
|
60
|
-
// committed to its multi-line shape
|
|
61
|
-
// line fits but the all-flat form does not;
|
|
146
|
+
// 2. hugged — the callback (last for HugLast, first for HugFirst)
|
|
147
|
+
// committed to its multi-line shape with the other items inline,
|
|
148
|
+
// chosen when its opening line fits but the all-flat form does not;
|
|
62
149
|
// 3. plain — every item exploded onto its own indented line.
|
|
63
150
|
// The all-flat option is dropped when the list cannot render flat
|
|
64
151
|
// (a block-bodied callback argument carries hard line breaks).
|
|
65
152
|
hugged := printListHuggingLast(ctx, shape)
|
|
153
|
+
if shape.HugFirst {
|
|
154
|
+
hugged = printListHuggingFirst(ctx, shape)
|
|
155
|
+
}
|
|
156
|
+
// A test-framework call hugs its callback unconditionally — Prettier never
|
|
157
|
+
// explodes its arguments — so drop the exploded fallback. The all-flat
|
|
158
|
+
// option still wins when the whole call fits (an empty-body callback).
|
|
159
|
+
if shape.HugLastForce {
|
|
160
|
+
if allFlat, ok := flatten(plain); ok {
|
|
161
|
+
return ConditionalGroup(allFlat, hugged)
|
|
162
|
+
}
|
|
163
|
+
return hugged
|
|
164
|
+
}
|
|
66
165
|
if allFlat, ok := flatten(plain); ok {
|
|
67
166
|
return ConditionalGroup(allFlat, hugged, plain)
|
|
68
167
|
}
|
|
@@ -75,7 +174,6 @@ func printList(ctx *PrintContext, shape listShape) Doc {
|
|
|
75
174
|
// comma — when it does not.
|
|
76
175
|
func printListPlain(ctx *PrintContext, shape listShape) Doc {
|
|
77
176
|
sep := Concat(Text(","), Line())
|
|
78
|
-
body := Join(sep, shape.Items)
|
|
79
177
|
|
|
80
178
|
flatPad := Doc{Kind: docNil}
|
|
81
179
|
if shape.Space {
|
|
@@ -87,6 +185,50 @@ func printListPlain(ctx *PrintContext, shape listShape) Doc {
|
|
|
87
185
|
trailing = IfBreak(Text(","), Doc{Kind: docNil})
|
|
88
186
|
}
|
|
89
187
|
|
|
188
|
+
hasBlank := shape.hasBlankBefore()
|
|
189
|
+
|
|
190
|
+
var body Doc
|
|
191
|
+
if hasBlank {
|
|
192
|
+
// Per-item body that preserves a single source blank line before an item:
|
|
193
|
+
// `,` then a Literalline (the empty line, no indent, mirroring printBlock)
|
|
194
|
+
// then the normal Line. A blank line forces the group broken.
|
|
195
|
+
parts := make([]Doc, 0, len(shape.Items)*3)
|
|
196
|
+
for i, it := range shape.Items {
|
|
197
|
+
if i > 0 {
|
|
198
|
+
parts = append(parts, Text(","))
|
|
199
|
+
if i < len(shape.BlankBefore) && shape.BlankBefore[i] {
|
|
200
|
+
parts = append(parts, Literalline())
|
|
201
|
+
}
|
|
202
|
+
parts = append(parts, Line())
|
|
203
|
+
}
|
|
204
|
+
parts = append(parts, it)
|
|
205
|
+
}
|
|
206
|
+
body = Concat(parts...)
|
|
207
|
+
} else if shape.Fill {
|
|
208
|
+
// Each non-last fill content carries its own comma — `[el, ","]` — and the
|
|
209
|
+
// separator is just a Line. Prettier measures the pack/break decision on
|
|
210
|
+
// `[content_i, line, content_{i+1}]`, so the next element's comma must be
|
|
211
|
+
// part of its content or the line would pack one element too many. The
|
|
212
|
+
// last element carries no comma here; the trailing comma is the shared
|
|
213
|
+
// ifBreak appended after the body so it tracks the GROUP's break mode (a
|
|
214
|
+
// fill-mode ifBreak would drop the comma when the last item packs flat,
|
|
215
|
+
// making the format non-idempotent).
|
|
216
|
+
parts := make([]Doc, 0, len(shape.Items)*2-1)
|
|
217
|
+
for i, it := range shape.Items {
|
|
218
|
+
if i > 0 {
|
|
219
|
+
parts = append(parts, Line())
|
|
220
|
+
}
|
|
221
|
+
if i < len(shape.Items)-1 {
|
|
222
|
+
parts = append(parts, Concat(it, Text(",")))
|
|
223
|
+
} else {
|
|
224
|
+
parts = append(parts, it)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
body = Fill(parts...)
|
|
228
|
+
} else {
|
|
229
|
+
body = Join(sep, shape.Items)
|
|
230
|
+
}
|
|
231
|
+
|
|
90
232
|
openTok := Text(shape.OpenTok)
|
|
91
233
|
closeTok := Text(shape.CloseTok)
|
|
92
234
|
|
|
@@ -96,11 +238,19 @@ func printListPlain(ctx *PrintContext, shape listShape) Doc {
|
|
|
96
238
|
trailingSep := IfBreak(Hardline(), flatPad)
|
|
97
239
|
|
|
98
240
|
bodyBlock := Indent(ctx.indentUnit(), leadingSep, body, trailing)
|
|
99
|
-
|
|
241
|
+
prefix := shape.Prefix
|
|
242
|
+
if prefix.Kind == 0 {
|
|
243
|
+
prefix = Doc{Kind: docNil}
|
|
244
|
+
}
|
|
245
|
+
suffix := shape.Suffix
|
|
246
|
+
if suffix.Kind == 0 {
|
|
247
|
+
suffix = Doc{Kind: docNil}
|
|
248
|
+
}
|
|
249
|
+
doc := Concat(prefix, openTok, bodyBlock, trailingSep, closeTok, suffix)
|
|
100
250
|
group := Group(doc)
|
|
101
251
|
// ForceBreak (object-literal newline preservation) commits the group
|
|
102
252
|
// to its broken shape regardless of fit.
|
|
103
|
-
group.Break = shape.ForceBreak
|
|
253
|
+
group.Break = shape.ForceBreak || hasBlank
|
|
104
254
|
return group
|
|
105
255
|
}
|
|
106
256
|
|
|
@@ -143,3 +293,36 @@ func printListHuggingLast(ctx *PrintContext, shape listShape) Doc {
|
|
|
143
293
|
parts = append(parts, last, Text(shape.CloseTok))
|
|
144
294
|
return Concat(parts...)
|
|
145
295
|
}
|
|
296
|
+
|
|
297
|
+
// printListHuggingFirst renders the "first-argument hugging" shape
|
|
298
|
+
// Prettier uses for `foo(() => { … }, target)`: the first item stays
|
|
299
|
+
// attached to the open paren and the remaining simple items flow inline
|
|
300
|
+
// after it, so a multi-line callback body does not explode the trailing
|
|
301
|
+
// arguments onto their own lines.
|
|
302
|
+
//
|
|
303
|
+
// hugged: OPEN OPEN-of-first … CLOSE-of-first, b, c CLOSE
|
|
304
|
+
//
|
|
305
|
+
// Like printListHuggingLast it returns a plain Concat (the callback's own
|
|
306
|
+
// printer owns its body's break) and forces the hugged item's first Group
|
|
307
|
+
// broken when the item has no hard line breaks of its own, so the hugged
|
|
308
|
+
// option stays distinct from the all-flat option.
|
|
309
|
+
func printListHuggingFirst(ctx *PrintContext, shape listShape) Doc {
|
|
310
|
+
first := shape.Items[0]
|
|
311
|
+
rest := shape.Items[1:]
|
|
312
|
+
if _, flat := flatten(first); flat {
|
|
313
|
+
first, _ = forceBreakFirstGroup(first)
|
|
314
|
+
}
|
|
315
|
+
parts := []Doc{Text(shape.OpenTok), first}
|
|
316
|
+
for _, item := range rest {
|
|
317
|
+
// The trailing simple arguments ride the close line flat — Prettier keeps
|
|
318
|
+
// them on one line even when that line overflows (a long zero/one-argument
|
|
319
|
+
// trailing call `}, makeAccumulator(single))` is not broken). Force each
|
|
320
|
+
// flat so its own Group does not break against the close-line width.
|
|
321
|
+
if flat, ok := flatten(item); ok {
|
|
322
|
+
item = flat
|
|
323
|
+
}
|
|
324
|
+
parts = append(parts, Text(", "), item)
|
|
325
|
+
}
|
|
326
|
+
parts = append(parts, Text(shape.CloseTok))
|
|
327
|
+
return Concat(parts...)
|
|
328
|
+
}
|
|
@@ -35,6 +35,11 @@ func printObjectLiteral(ctx *PrintContext, node *shimast.Node) (Doc, bool) {
|
|
|
35
35
|
if obj == nil || obj.Properties == nil {
|
|
36
36
|
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
37
37
|
}
|
|
38
|
+
// A comment between properties (or after `{`) would be dropped by the fresh
|
|
39
|
+
// separators; bail to verbatim so the enclosing reflow abstains.
|
|
40
|
+
if listHasInterItemComments(ctx, node) {
|
|
41
|
+
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
42
|
+
}
|
|
38
43
|
items := make([]Doc, 0, len(obj.Properties.Nodes))
|
|
39
44
|
covered := true
|
|
40
45
|
for _, prop := range obj.Properties.Nodes {
|
|
@@ -60,12 +65,13 @@ func printObjectLiteral(ctx *PrintContext, node *shimast.Node) (Doc, bool) {
|
|
|
60
65
|
// "none" suppresses. Pairs with the call/array branches so the printer
|
|
61
66
|
// never disagrees with the trailing-comma rule on the same setting.
|
|
62
67
|
return printList(ctx, listShape{
|
|
63
|
-
OpenTok:
|
|
64
|
-
CloseTok:
|
|
65
|
-
Items:
|
|
66
|
-
Space:
|
|
67
|
-
AddComma:
|
|
68
|
-
ForceBreak:
|
|
68
|
+
OpenTok: "{",
|
|
69
|
+
CloseTok: "}",
|
|
70
|
+
Items: items,
|
|
71
|
+
Space: true,
|
|
72
|
+
AddComma: ctx.allowsEs5TrailingComma(),
|
|
73
|
+
ForceBreak: forceBreak,
|
|
74
|
+
BlankBefore: blankBeforeItems(ctx.Source, obj.Properties.Nodes),
|
|
69
75
|
}), covered
|
|
70
76
|
}
|
|
71
77
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
package linthost
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
// printConditionalExpression renders a (possibly chained) ternary with
|
|
8
|
+
// Prettier 3's "indent nested ternaries" staircase. A conditional whose
|
|
9
|
+
// consequent or alternate is itself a conditional is printed inline
|
|
10
|
+
// under the same break group, but its arms indent one extra level:
|
|
11
|
+
//
|
|
12
|
+
// aaaaaaaaaa
|
|
13
|
+
// ? bbbbbbbbbb
|
|
14
|
+
// : cccccccccc
|
|
15
|
+
// ? dddddddddd
|
|
16
|
+
// : eeeeeeeeee
|
|
17
|
+
//
|
|
18
|
+
// The whole chain shares one fit-or-break decision (a single outer
|
|
19
|
+
// Group), matching Prettier: either the entire chain fits flat
|
|
20
|
+
// (`a ? b : c ? d : e`) or every rung breaks onto its own line. Nesting
|
|
21
|
+
// is expressed by recursing the chain builder without wrapping the
|
|
22
|
+
// nested conditional in its own Group. The outermost chain indents its arms
|
|
23
|
+
// by `tabWidth`, but each nested chain indents by a FIXED 2 columns (not
|
|
24
|
+
// `tabWidth`), matching Prettier 3: at tabWidth 4 the outer arms sit at
|
|
25
|
+
// column 4 and the nested arms at column 6, not 8.
|
|
26
|
+
//
|
|
27
|
+
// The second return value is the coverage flag (see PrintNode): the AND
|
|
28
|
+
// of the test and both branches, so a multi-line verbatim node anywhere
|
|
29
|
+
// in the chain makes formatPrintWidth abstain rather than emit a
|
|
30
|
+
// half-reflowed shape.
|
|
31
|
+
func printConditionalExpression(ctx *PrintContext, node *shimast.Node) (Doc, bool) {
|
|
32
|
+
body, covered := buildConditionalChain(ctx, node, ctx.indentUnit())
|
|
33
|
+
if body.IsNil() {
|
|
34
|
+
return verbatim(ctx, node), !nodeSpansMultipleLines(ctx, node)
|
|
35
|
+
}
|
|
36
|
+
return Group(body), covered
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// buildConditionalChain returns the chain body for `node` WITHOUT a
|
|
40
|
+
// surrounding Group, so a nested conditional recursed from here shares
|
|
41
|
+
// the caller's group and its arms indent one level deeper. The top-level
|
|
42
|
+
// printConditionalExpression wraps the outermost body in the single
|
|
43
|
+
// Group that owns the break decision.
|
|
44
|
+
func buildConditionalChain(ctx *PrintContext, node *shimast.Node, indentCols int) (Doc, bool) {
|
|
45
|
+
cond := node.AsConditionalExpression()
|
|
46
|
+
if cond == nil || cond.Condition == nil || cond.WhenTrue == nil || cond.WhenFalse == nil {
|
|
47
|
+
return Doc{}, true
|
|
48
|
+
}
|
|
49
|
+
testDoc, c1 := PrintNode(ctx, cond.Condition)
|
|
50
|
+
consDoc, c2 := ternaryArm(ctx, cond.WhenTrue, true)
|
|
51
|
+
altDoc, c3 := ternaryArm(ctx, cond.WhenFalse, false)
|
|
52
|
+
doc := Concat(
|
|
53
|
+
testDoc,
|
|
54
|
+
Indent(indentCols,
|
|
55
|
+
Line(), Text("? "), consDoc,
|
|
56
|
+
Line(), Text(": "), altDoc,
|
|
57
|
+
),
|
|
58
|
+
)
|
|
59
|
+
return doc, c1 && c2 && c3
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ternaryArm prints a ternary consequent/alternate. A nested conditional
|
|
63
|
+
// continues the chain inline (no new Group) so the staircase
|
|
64
|
+
// accumulates; every other arm prints through the normal dispatcher (an
|
|
65
|
+
// arm that is a `??` expression is already parenthesized in valid
|
|
66
|
+
// source, so it round-trips its parens via the ParenthesizedExpression
|
|
67
|
+
// printer).
|
|
68
|
+
//
|
|
69
|
+
// A non-conditional arm is wrapped in Align so that, when it breaks
|
|
70
|
+
// internally, its continuation hangs under the arm expression's own
|
|
71
|
+
// column (one level past the `? `/`: ` marker) rather than under the
|
|
72
|
+
// chain's rung indent. Prettier hangs a broken call/object arm there:
|
|
73
|
+
//
|
|
74
|
+
// cond
|
|
75
|
+
// ? foo(
|
|
76
|
+
// arg, // arm-column + one level, not rung + one level
|
|
77
|
+
// )
|
|
78
|
+
// : bar
|
|
79
|
+
//
|
|
80
|
+
// Align is a no-op for an arm that stays flat, and a nested conditional
|
|
81
|
+
// is deliberately NOT aligned — it keeps the Indent-based staircase.
|
|
82
|
+
//
|
|
83
|
+
// A nested conditional in the CONSEQUENT (`? `) position is wrapped in
|
|
84
|
+
// parentheses, but only when the chain renders flat: Prettier's ternary-old
|
|
85
|
+
// printer emits `consequent.type === node.type ? ifBreak("", "(") : ""` around
|
|
86
|
+
// the consequent (`a ? (b ? c : d) : e` on one line), and drops the parens for
|
|
87
|
+
// the broken staircase. A nested conditional in the ALTERNATE (`: `) position
|
|
88
|
+
// is never wrapped — it chains. `isConsequent` selects between the two.
|
|
89
|
+
func ternaryArm(ctx *PrintContext, node *shimast.Node, isConsequent bool) (Doc, bool) {
|
|
90
|
+
if node != nil && node.Kind == shimast.KindConditionalExpression {
|
|
91
|
+
// A nested chain indents a fixed 2 columns past its parent rung,
|
|
92
|
+
// independent of tabWidth (Prettier 3's nested-ternary rule).
|
|
93
|
+
chain, covered := buildConditionalChain(ctx, node, 2)
|
|
94
|
+
if isConsequent {
|
|
95
|
+
// `ifBreak("", "(")` … `ifBreak("", ")")`: parens in flat mode only.
|
|
96
|
+
chain = Concat(
|
|
97
|
+
IfBreak(Doc{Kind: docNil}, Text("(")),
|
|
98
|
+
chain,
|
|
99
|
+
IfBreak(Doc{Kind: docNil}, Text(")")),
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
return chain, covered
|
|
103
|
+
}
|
|
104
|
+
doc, covered := PrintNode(ctx, node)
|
|
105
|
+
return Align(doc), covered
|
|
106
|
+
}
|