mago_formatter/settings.rs
1use std::str::FromStr;
2
3use schemars::JsonSchema;
4use serde::Deserialize;
5use serde::Serialize;
6
7/// Format settings for the PHP printer.
8#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, JsonSchema)]
9#[serde(rename_all = "kebab-case", deny_unknown_fields)]
10pub struct FormatSettings {
11 /// Maximum line length that the printer will wrap on.
12 ///
13 /// Default: 120
14 #[serde(default = "default_print_width")]
15 pub print_width: usize,
16
17 /// Number of spaces per indentation level.
18 ///
19 /// Default: 4
20 #[serde(default = "default_tab_width")]
21 pub tab_width: usize,
22
23 /// Whether to use tabs instead of spaces for indentation.
24 ///
25 /// Default: false
26 #[serde(default = "default_false")]
27 pub use_tabs: bool,
28
29 /// End-of-line characters to use.
30 ///
31 /// Default: "lf"
32 #[serde(default)]
33 pub end_of_line: EndOfLine,
34
35 /// Whether to use single quotes instead of double quotes for strings.
36 ///
37 /// The formatter automatically determines which quotes to use based on the string content,
38 /// with a preference for single quotes if this option is enabled.
39 ///
40 /// Decision logic:
41 /// - If the string contains more single quotes than double quotes, double quotes are used
42 /// - If the string contains more double quotes than single quotes, single quotes are used
43 /// - If equal number of both, single quotes are used if this option is true
44 ///
45 /// Default: true
46 #[serde(default = "default_true")]
47 pub single_quote: bool,
48
49 /// Whether to add a trailing comma to the last element in multi-line syntactic structures.
50 ///
51 /// When enabled, trailing commas are added to lists, arrays, parameter lists,
52 /// argument lists, and other similar structures when they span multiple lines.
53 ///
54 /// Default: true
55 #[serde(default = "default_true")]
56 pub trailing_comma: bool,
57
58 /// Whether to remove the trailing PHP close tag (`?>`) from files.
59 ///
60 /// Default: true
61 #[serde(default = "default_true")]
62 pub remove_trailing_close_tag: bool,
63
64 /// Brace placement for control structures (if, for, while, etc.).
65 ///
66 /// Example with `same_line`:
67 /// ```php
68 /// if ($expr) {
69 /// return 'Hello, world!';
70 /// }
71 /// ```
72 ///
73 /// Example with `next_line`:
74 /// ```php
75 /// if ($expr)
76 /// {
77 /// return 'Hello, world!';
78 /// }
79 /// ```
80 ///
81 /// Default: `same_line`
82 #[serde(default = "BraceStyle::same_line")]
83 pub control_brace_style: BraceStyle,
84
85 /// Brace placement for closures.
86 ///
87 /// Example with `same_line`:
88 /// ```php
89 /// $closure = function() {
90 /// return 'Hello, world!';
91 /// };
92 /// ```
93 ///
94 /// Example with `next_line`:
95 /// ```php
96 /// $closure = function()
97 /// {
98 /// return 'Hello, world!';
99 /// };
100 /// ```
101 ///
102 /// Default: `same_line`
103 #[serde(default = "BraceStyle::same_line")]
104 pub closure_brace_style: BraceStyle,
105
106 /// Brace placement for function declarations.
107 ///
108 /// Example with `same_line`:
109 /// ```php
110 /// function foo() {
111 /// return 'Hello, world!';
112 /// }
113 /// ```
114 ///
115 /// Example with `next_line`:
116 /// ```php
117 /// function foo()
118 /// {
119 /// return 'Hello, world!';
120 /// }
121 /// ```
122 ///
123 /// Default: `next_line`
124 #[serde(default = "BraceStyle::next_line")]
125 pub function_brace_style: BraceStyle,
126
127 /// Brace placement for method declarations.
128 ///
129 /// Example with `same_line`:
130 /// ```php
131 /// class Foo
132 /// {
133 /// public function bar() {
134 /// return 'Hello, world!';
135 /// }
136 /// }
137 /// ```
138 ///
139 /// Example with `next_line`:
140 /// ```php
141 /// class Foo
142 /// {
143 /// public function bar()
144 /// {
145 /// return 'Hello, world!';
146 /// }
147 /// }
148 /// ```
149 ///
150 /// Default: `next_line`
151 #[serde(default = "BraceStyle::next_line")]
152 pub method_brace_style: BraceStyle,
153
154 /// Brace placement for class-like structures (classes, interfaces, traits, enums).
155 ///
156 /// Example with `same_line`:
157 /// ```php
158 /// class Foo {
159 /// }
160 /// ```
161 ///
162 /// Example with `next_line`:
163 /// ```php
164 /// class Foo
165 /// {
166 /// }
167 /// ```
168 ///
169 /// Default: `next_line`
170 #[serde(default = "BraceStyle::next_line")]
171 pub classlike_brace_style: BraceStyle,
172
173 /// Place empty control structure bodies on the same line.
174 ///
175 /// Example with `false`:
176 /// ```php
177 /// if ($expr)
178 /// {
179 /// }
180 /// ```
181 ///
182 /// Example with `true`:
183 /// ```php
184 /// if ($expr) {}
185 /// ```
186 ///
187 /// Default: false
188 #[serde(default = "default_false")]
189 pub inline_empty_control_braces: bool,
190
191 /// Place empty closure bodies on the same line.
192 ///
193 /// Example with `false`:
194 /// ```php
195 /// $closure = function()
196 /// {
197 /// };
198 /// ```
199 ///
200 /// Example with `true`:
201 /// ```php
202 /// $closure = function() {};
203 /// ```
204 ///
205 /// Default: true
206 #[serde(default = "default_true")]
207 pub inline_empty_closure_braces: bool,
208
209 /// Place empty function bodies on the same line.
210 ///
211 /// Example with `false`:
212 /// ```php
213 /// function foo()
214 /// {
215 /// }
216 /// ```
217 ///
218 /// Example with `true`:
219 /// ```php
220 /// function foo() {}
221 /// ```
222 ///
223 /// Default: false
224 #[serde(default = "default_false")]
225 pub inline_empty_function_braces: bool,
226
227 /// Place empty method bodies on the same line.
228 ///
229 /// Example with `false`:
230 /// ```php
231 /// class Foo
232 /// {
233 /// public function bar()
234 /// {
235 /// }
236 /// }
237 /// ```
238 ///
239 /// Example with `true`:
240 /// ```php
241 /// class Foo
242 /// {
243 /// public function bar() {}
244 /// }
245 /// ```
246 ///
247 /// Default: false
248 #[serde(default = "default_false")]
249 pub inline_empty_method_braces: bool,
250
251 /// Place empty constructor bodies on the same line.
252 ///
253 /// Example with `false`:
254 /// ```php
255 /// class Foo {
256 /// public function __construct()
257 /// {
258 /// }
259 /// }
260 /// ```
261 ///
262 /// Example with `true`:
263 /// ```php
264 /// class Foo {
265 /// public function __construct() {}
266 /// }
267 /// ```
268 ///
269 /// Default: true
270 #[serde(default = "default_true")]
271 pub inline_empty_constructor_braces: bool,
272
273 /// Place empty class-like bodies on the same line.
274 ///
275 /// Example with `false`:
276 /// ```php
277 /// class Foo
278 /// {
279 /// }
280 /// ```
281 ///
282 /// Example with `true`:
283 /// ```php
284 /// class Foo {}
285 /// ```
286 ///
287 /// Default: true
288 #[serde(default = "default_true")]
289 pub inline_empty_classlike_braces: bool,
290
291 /// Place empty anonymous class bodies on the same line.
292 ///
293 /// Example with `false`:
294 /// ```php
295 /// $anon = new class
296 /// {
297 /// };
298 /// ```
299 ///
300 /// Example with `true`:
301 /// ```php
302 /// $anon = new class {};
303 /// ```
304 ///
305 /// Default: true
306 #[serde(default = "default_true")]
307 pub inline_empty_anonymous_class_braces: bool,
308
309 /// How to format broken method/property chains.
310 ///
311 /// When `next_line`, the first method/property starts on a new line:
312 /// ```php
313 /// $foo
314 /// ->bar()
315 /// ->baz();
316 /// ```
317 ///
318 /// When `same_line`, the first method/property stays on the same line:
319 /// ```php
320 /// $foo->bar()
321 /// ->baz();
322 /// ```
323 ///
324 /// Default: `next_line`
325 #[serde(default)]
326 pub method_chain_breaking_style: MethodChainBreakingStyle,
327
328 /// When method chaining breaks across lines, place the first method on a new line.
329 ///
330 /// This follows PER-CS 4.7: "When [method chaining is] put on separate lines, [...] the first method MUST be on the next line."
331 ///
332 /// When enabled:
333 /// ```php
334 /// $this
335 /// ->getCache()
336 /// ->forget();
337 /// ```
338 ///
339 /// When disabled:
340 /// ```php
341 /// $this->getCache()
342 /// ->forget();
343 /// ```
344 ///
345 /// Default: `true`
346 #[serde(default = "default_true")]
347 pub first_method_chain_on_new_line: bool,
348
349 /// Whether to preserve line breaks in method chains, even if they could fit on a single line.
350 ///
351 /// Default: false
352 #[serde(default = "default_false")]
353 pub preserve_breaking_member_access_chain: bool,
354
355 /// Whether to preserve line breaks in argument lists, even if they could fit on a single line.
356 ///
357 /// Default: false
358 #[serde(default = "default_false")]
359 pub preserve_breaking_argument_list: bool,
360
361 /// Whether to preserve line breaks in array-like structures, even if they could fit on a single line.
362 ///
363 /// Default: true
364 #[serde(default = "default_true")]
365 pub preserve_breaking_array_like: bool,
366
367 /// Whether to preserve line breaks in parameter lists, even if they could fit on a single line.
368 ///
369 /// Default: false
370 #[serde(default = "default_false")]
371 pub preserve_breaking_parameter_list: bool,
372
373 /// Whether to preserve line breaks in attribute lists, even if they could fit on a single line.
374 ///
375 /// Default: false
376 #[serde(default = "default_false")]
377 pub preserve_breaking_attribute_list: bool,
378
379 /// Whether to preserve line breaks in conditional (ternary) expressions.
380 ///
381 /// Default: false
382 #[serde(default = "default_false")]
383 pub preserve_breaking_conditional_expression: bool,
384
385 /// Whether to break a parameter list with one or more promoted properties into multiple lines.
386 ///
387 /// When enabled, parameter lists with promoted properties are always multi-line:
388 /// ```php
389 /// class User {
390 /// public function __construct(
391 /// public string $name,
392 /// public string $email,
393 /// ) {}
394 /// }
395 /// ```
396 ///
397 /// When disabled, they may be kept on a single line if space allows:
398 /// ```php
399 /// class User {
400 /// public function __construct(public string $name, public string $email) {}
401 /// }
402 /// ```
403 ///
404 /// Default: true
405 #[serde(default = "default_true")]
406 pub break_promoted_properties_list: bool,
407
408 /// Whether to add a line before binary operators or after when breaking.
409 ///
410 /// When true:
411 /// ```php
412 /// $foo = 'Hello, '
413 /// . 'world!';
414 /// ```
415 ///
416 /// When false:
417 /// ```php
418 /// $foo = 'Hello, ' .
419 /// 'world!';
420 /// ```
421 ///
422 /// Note: If the right side has a leading comment, this setting is always false.
423 ///
424 /// Default: true
425 #[serde(default = "default_true")]
426 pub line_before_binary_operator: bool,
427
428 /// Whether to always break named argument lists into multiple lines.
429 ///
430 /// When enabled:
431 /// ```php
432 /// $foo = some_function(
433 /// argument1: 'value1',
434 /// argument2: 'value2',
435 /// );
436 /// ```
437 ///
438 /// Default: false
439 #[serde(default = "default_false")]
440 pub always_break_named_arguments_list: bool,
441
442 /// Whether to always break named argument lists in attributes into multiple lines.
443 ///
444 /// When enabled:
445 /// ```php
446 /// #[SomeAttribute(
447 /// argument1: 'value1',
448 /// argument2: 'value2',
449 /// )]
450 /// class Foo {}
451 /// ```
452 ///
453 /// Default: false
454 #[serde(default = "default_false")]
455 pub always_break_attribute_named_argument_lists: bool,
456
457 /// Whether to use table-style alignment for arrays.
458 ///
459 /// When enabled, array elements are aligned in a table-like format:
460 /// ```php
461 /// $array = [
462 /// ['foo', 1.2, 123, false],
463 /// ['bar', 52.4, 456, true],
464 /// ['baz', 3.6, 789, false],
465 /// ['qux', 4.8, 1, true],
466 /// ['quux', 5.0, 12, false],
467 /// ];
468 /// ```
469 ///
470 /// Default: true
471 #[serde(default = "default_true")]
472 pub array_table_style_alignment: bool,
473
474 /// Whether to align consecutive assignment-like constructs in columns.
475 ///
476 /// When enabled, consecutive variable assignments, class properties, class constants,
477 /// global constants, array key-value pairs, and backed enum cases are column-aligned.
478 ///
479 /// Example with `true`:
480 /// ```php
481 /// $foo = 1;
482 /// $b = 2;
483 /// $ccccccc = 3;
484 ///
485 /// class X {
486 /// public string $foo = 1;
487 /// public readonly int $barrrr = 2;
488 /// }
489 /// ```
490 ///
491 /// Example with `false`:
492 /// ```php
493 /// $foo = 1;
494 /// $b = 2;
495 /// $ccccccc = 3;
496 /// ```
497 ///
498 /// Note: Blank lines and comments break alignment runs. In class bodies,
499 /// different member types (properties vs constants) are aligned separately.
500 ///
501 /// Default: false
502 #[serde(default = "default_false")]
503 pub align_assignment_like: bool,
504
505 /// Whether to sort use statements alphabetically.
506 ///
507 /// Default: true
508 #[serde(default = "default_true")]
509 pub sort_uses: bool,
510
511 /// Whether to sort class methods by visibility and name.
512 ///
513 /// When enabled, methods in class-like structures are automatically reordered:
514 /// 1. Constructor (`__construct`) - always first
515 /// 2. Static methods (by visibility: public, protected, private)
516 /// - Abstract methods before concrete methods
517 /// - Alphabetically by name within each group
518 /// 3. Instance methods (by visibility: public, protected, private)
519 /// - Abstract methods before concrete methods
520 /// - Alphabetically by name within each group
521 /// 4. Other magic methods (e.g., `__toString`, `__get`, `__set`)
522 /// - Sorted alphabetically by name
523 /// 5. Destructor (`__destruct`) - always last
524 ///
525 /// This applies to all class-like structures: classes, traits, interfaces, and enums.
526 /// Other members (constants, properties, trait uses, enum cases) remain in their original positions.
527 ///
528 /// Default: false
529 #[serde(default = "default_false")]
530 pub sort_class_methods: bool,
531
532 /// Whether to insert a blank line between different types of use statements.
533 ///
534 /// When enabled:
535 /// ```php
536 /// use Foo\Bar;
537 /// use Foo\Baz;
538 ///
539 /// use function Foo\bar;
540 /// use function Foo\baz;
541 ///
542 /// use const Foo\A;
543 /// use const Foo\B;
544 /// ```
545 ///
546 /// When disabled:
547 /// ```php
548 /// use Foo\Bar;
549 /// use Foo\Baz;
550 /// use function Foo\bar;
551 /// use function Foo\baz;
552 /// use const Foo\A;
553 /// use const Foo\B;
554 /// ```
555 ///
556 /// Default: true
557 #[serde(default = "default_true")]
558 pub separate_use_types: bool,
559
560 /// Whether to expand grouped use statements into individual statements.
561 ///
562 /// When enabled:
563 /// ```php
564 /// use Foo\Bar;
565 /// use Foo\Baz;
566 /// ```
567 ///
568 /// When disabled:
569 /// ```php
570 /// use Foo\{Bar, Baz};
571 /// ```
572 ///
573 /// Default: true
574 #[serde(default = "default_true")]
575 pub expand_use_groups: bool,
576
577 /// How to format null type hints.
578 ///
579 /// With `Question`:
580 /// ```php
581 /// function foo(?string $bar) {
582 /// return $bar;
583 /// }
584 /// ```
585 ///
586 /// With `NullPipe`:
587 /// ```php
588 /// function foo(null|string $bar) {
589 /// return $bar;
590 /// }
591 /// ```
592 ///
593 /// Default: `Question`
594 #[serde(default)]
595 pub null_type_hint: NullTypeHint,
596
597 /// Whether to include parentheses around `new` when followed by a member access.
598 ///
599 /// Controls whether to use PHP 8.4's shorthand syntax for new expressions
600 /// followed by member access. If PHP version is earlier than 8.4, this is always true.
601 ///
602 /// When enabled:
603 /// ```php
604 /// $foo = (new Foo)->bar();
605 /// ```
606 ///
607 /// When disabled (PHP 8.4+ only):
608 /// ```php
609 /// $foo = new Foo->bar();
610 /// ```
611 ///
612 /// Default: false
613 #[serde(default = "default_false")]
614 pub parentheses_around_new_in_member_access: bool,
615
616 /// Whether to include parentheses in `new` expressions when no arguments are provided.
617 ///
618 /// When enabled:
619 /// ```php
620 /// $foo = new Foo();
621 /// ```
622 ///
623 /// When disabled:
624 /// ```php
625 /// $foo = new Foo;
626 /// ```
627 ///
628 /// Default: true
629 #[serde(default = "default_true")]
630 pub parentheses_in_new_expression: bool,
631
632 /// Whether to include parentheses in `exit` and `die` constructs.
633 ///
634 /// When enabled:
635 /// ```php
636 /// exit();
637 /// die();
638 /// ```
639 ///
640 /// When disabled:
641 /// ```php
642 /// exit;
643 /// die;
644 /// ```
645 ///
646 /// Default: true
647 #[serde(default = "default_true")]
648 pub parentheses_in_exit_and_die: bool,
649
650 /// Whether to include parentheses in attributes with no arguments.
651 ///
652 /// When enabled:
653 /// ```php
654 /// #[SomeAttribute()]
655 /// class Foo {}
656 /// ```
657 ///
658 /// When disabled:
659 /// ```php
660 /// #[SomeAttribute]
661 /// class Foo {}
662 /// ```
663 ///
664 /// Default: false
665 #[serde(default = "default_false")]
666 pub parentheses_in_attribute: bool,
667
668 /// Whether to add a space before the opening parameters in arrow functions.
669 ///
670 /// When enabled: `fn ($x) => $x * 2`
671 /// When disabled: `fn($x) => $x * 2`
672 ///
673 /// Default: false
674 #[serde(default = "default_false")]
675 pub space_before_arrow_function_parameter_list_parenthesis: bool,
676
677 /// Whether to add a space before the opening parameters in closures.
678 ///
679 /// When enabled: `function ($x) use ($y)`
680 /// When disabled: `function($x) use ($y)`
681 ///
682 /// Default: true
683 #[serde(default = "default_true")]
684 pub space_before_closure_parameter_list_parenthesis: bool,
685
686 /// Whether to add a space before the opening parameters in hooks.
687 ///
688 /// When enabled: `$hook ($param)`
689 /// When disabled: `$hook($param)`
690 ///
691 /// Default: false
692 #[serde(default = "default_false")]
693 pub space_before_hook_parameter_list_parenthesis: bool,
694
695 /// Whether to add a space before the opening parenthesis in closure use clause.
696 ///
697 /// When enabled: `function() use ($var)`
698 /// When disabled: `function() use($var)`
699 ///
700 /// Default: true
701 #[serde(default = "default_true")]
702 pub space_before_closure_use_clause_parenthesis: bool,
703
704 /// Whether to add a space after cast operators (int, float, string, etc.).
705 ///
706 /// When enabled: `(int) $foo`
707 /// When disabled: `(int)$foo`
708 ///
709 /// Default: true
710 #[serde(default = "default_true")]
711 pub space_after_cast_unary_prefix_operators: bool,
712
713 /// Whether to add a space after the reference operator (&).
714 ///
715 /// When enabled: `& $foo`
716 /// When disabled: `&$foo`
717 ///
718 /// Default: false
719 #[serde(default = "default_false")]
720 pub space_after_reference_unary_prefix_operator: bool,
721
722 /// Whether to add a space after the error control operator (@).
723 ///
724 /// When enabled: `@ $foo`
725 /// When disabled: `@$foo`
726 ///
727 /// Default: false
728 #[serde(default = "default_false")]
729 pub space_after_error_control_unary_prefix_operator: bool,
730
731 /// Whether to add a space after the logical not operator (!).
732 ///
733 /// When enabled: `! $foo`
734 /// When disabled: `!$foo`
735 ///
736 /// Default: false
737 #[serde(default = "default_false")]
738 pub space_after_logical_not_unary_prefix_operator: bool,
739
740 /// Whether to add a space after the bitwise not operator (~).
741 ///
742 /// When enabled: `~ $foo`
743 /// When disabled: `~$foo`
744 ///
745 /// Default: false
746 #[serde(default = "default_false")]
747 pub space_after_bitwise_not_unary_prefix_operator: bool,
748
749 /// Whether to add a space after the increment prefix operator (++).
750 ///
751 /// When enabled: `++ $i`
752 /// When disabled: `++$i`
753 ///
754 /// Default: false
755 #[serde(default = "default_false")]
756 pub space_after_increment_unary_prefix_operator: bool,
757
758 /// Whether to add a space after the decrement prefix operator (--).
759 ///
760 /// When enabled: `-- $i`
761 /// When disabled: `--$i`
762 ///
763 /// Default: false
764 #[serde(default = "default_false")]
765 pub space_after_decrement_unary_prefix_operator: bool,
766
767 /// Whether to add a space after the additive unary operators (+ and -).
768 ///
769 /// When enabled: `+ $i`
770 /// When disabled: `+$i`
771 ///
772 /// Default: false
773 #[serde(default = "default_false")]
774 pub space_after_additive_unary_prefix_operator: bool,
775
776 /// Whether to add spaces around the concatenation operator (.)
777 ///
778 /// When enabled: `$a . $b`
779 /// When disabled: `$a.$b`
780 ///
781 /// Default: true
782 #[serde(default = "default_true")]
783 pub space_around_concatenation_binary_operator: bool,
784
785 /// Whether to add spaces around the assignment in declare statements.
786 ///
787 /// When enabled: `declare(strict_types = 1)`
788 /// When disabled: `declare(strict_types=1)`
789 ///
790 /// Default: false
791 #[serde(default = "default_false")]
792 pub space_around_assignment_in_declare: bool,
793
794 /// Whether to add spaces within grouping parentheses.
795 ///
796 /// When enabled: `( $expr ) - $expr`
797 /// When disabled: `($expr) - $expr`
798 ///
799 /// Default: false
800 #[serde(default = "default_false")]
801 pub space_within_grouping_parenthesis: bool,
802
803 /// Whether to add an empty line after control structures (if, for, foreach, while, do, switch).
804 ///
805 /// Note: if an empty line already exists, it will be preserved regardless of this
806 /// settings value.
807 ///
808 /// Default: false
809 #[serde(default = "default_false")]
810 pub empty_line_after_control_structure: bool,
811
812 /// Whether to add an empty line after opening tag.
813 ///
814 /// Note: if an empty line already exists, it will be preserved regardless of this
815 /// settings value.
816 ///
817 /// Default: true
818 #[serde(default = "default_true")]
819 pub empty_line_after_opening_tag: bool,
820
821 /// Whether to add an empty line after declare statement.
822 ///
823 /// Note: if an empty line already exists, it will be preserved regardless of this
824 /// settings value.
825 ///
826 /// Default: true
827 #[serde(default = "default_true")]
828 pub empty_line_after_declare: bool,
829
830 /// Whether to add an empty line after namespace.
831 ///
832 /// Note: if an empty line already exists, it will be preserved regardless of this
833 /// settings value.
834 ///
835 /// Default: true
836 #[serde(default = "default_true")]
837 pub empty_line_after_namespace: bool,
838
839 /// Whether to add an empty line after use statements.
840 ///
841 /// Note: if an empty line already exists, it will be preserved regardless of this
842 /// settings value.
843 ///
844 /// Default: true
845 #[serde(default = "default_true")]
846 pub empty_line_after_use: bool,
847
848 /// Whether to add an empty line after symbols (class, enum, interface, trait, function, const).
849 ///
850 /// Note: if an empty line already exists, it will be preserved regardless of this
851 /// settings value.
852 ///
853 /// Default: true
854 #[serde(default = "default_true")]
855 pub empty_line_after_symbols: bool,
856
857 /// Whether to add an empty line between consecutive symbols of the same type.
858 ///
859 /// Only applies when `empty_line_after_symbols` is true.
860 ///
861 /// Default: true
862 #[serde(default = "default_true")]
863 pub empty_line_between_same_symbols: bool,
864
865 /// Whether to add an empty line after class-like constant.
866 ///
867 /// Note: if an empty line already exists, it will be preserved regardless of this
868 /// settings value.
869 ///
870 /// Default: false
871 #[serde(default = "default_false")]
872 pub empty_line_after_class_like_constant: bool,
873
874 /// Whether to add an empty line after enum case.
875 ///
876 /// Note: if an empty line already exists, it will be preserved regardless of this
877 /// settings value.
878 ///
879 /// Default: false
880 #[serde(default = "default_false")]
881 pub empty_line_after_enum_case: bool,
882
883 /// Whether to add an empty line after trait use.
884 ///
885 /// Note: if an empty line already exists, it will be preserved regardless of this
886 /// settings value.
887 ///
888 /// Default: false
889 #[serde(default = "default_false")]
890 pub empty_line_after_trait_use: bool,
891
892 /// Whether to add an empty line after property.
893 ///
894 /// Note: if an empty line already exists, it will be preserved regardless of this
895 /// settings value.
896 ///
897 /// Default: false
898 #[serde(default = "default_false")]
899 pub empty_line_after_property: bool,
900
901 /// Whether to add an empty line after method.
902 ///
903 /// Note: if an empty line already exists, it will be preserved regardless of this
904 /// settings value.
905 ///
906 /// Default: true
907 #[serde(default = "default_true")]
908 pub empty_line_after_method: bool,
909
910 /// Whether to add an empty line before return statements.
911 ///
912 /// Default: false
913 #[serde(default = "default_false")]
914 pub empty_line_before_return: bool,
915
916 /// Whether to add an empty line before dangling comments.
917 ///
918 /// Default: true
919 #[serde(default = "default_true")]
920 pub empty_line_before_dangling_comments: bool,
921
922 /// Whether to separate class-like members of different kinds with a blank line.
923 ///
924 /// Default: true
925 #[serde(default = "default_true")]
926 pub separate_class_like_members: bool,
927}
928
929impl Default for FormatSettings {
930 /// Sets default values to align with best practices.
931 fn default() -> Self {
932 Self {
933 print_width: default_print_width(),
934 tab_width: default_tab_width(),
935 use_tabs: false,
936 end_of_line: EndOfLine::default(),
937 single_quote: true,
938 trailing_comma: true,
939 closure_brace_style: BraceStyle::SameLine,
940 function_brace_style: BraceStyle::NextLine,
941 method_brace_style: BraceStyle::NextLine,
942 classlike_brace_style: BraceStyle::NextLine,
943 control_brace_style: BraceStyle::SameLine,
944 inline_empty_control_braces: false,
945 inline_empty_closure_braces: true,
946 inline_empty_function_braces: false,
947 inline_empty_method_braces: false,
948 inline_empty_constructor_braces: true,
949 inline_empty_classlike_braces: true,
950 inline_empty_anonymous_class_braces: true,
951 null_type_hint: NullTypeHint::default(),
952 break_promoted_properties_list: true,
953 method_chain_breaking_style: MethodChainBreakingStyle::NextLine,
954 first_method_chain_on_new_line: true,
955 line_before_binary_operator: true,
956 sort_uses: true,
957 sort_class_methods: false,
958 separate_use_types: true,
959 expand_use_groups: true,
960 remove_trailing_close_tag: true,
961 parentheses_around_new_in_member_access: false,
962 parentheses_in_new_expression: true,
963 parentheses_in_exit_and_die: true,
964 parentheses_in_attribute: false,
965 array_table_style_alignment: true,
966 align_assignment_like: false,
967 always_break_named_arguments_list: false,
968 always_break_attribute_named_argument_lists: false,
969 preserve_breaking_member_access_chain: false,
970 preserve_breaking_argument_list: false,
971 preserve_breaking_array_like: true,
972 preserve_breaking_parameter_list: false,
973 preserve_breaking_attribute_list: false,
974 preserve_breaking_conditional_expression: false,
975 space_before_arrow_function_parameter_list_parenthesis: false,
976 space_before_closure_parameter_list_parenthesis: true,
977 space_before_closure_use_clause_parenthesis: true,
978 space_around_assignment_in_declare: false,
979 space_within_grouping_parenthesis: false,
980 space_before_hook_parameter_list_parenthesis: false,
981 space_around_concatenation_binary_operator: true,
982 space_after_cast_unary_prefix_operators: true,
983 space_after_reference_unary_prefix_operator: false,
984 space_after_error_control_unary_prefix_operator: false,
985 space_after_logical_not_unary_prefix_operator: false,
986 space_after_bitwise_not_unary_prefix_operator: false,
987 space_after_increment_unary_prefix_operator: false,
988 space_after_decrement_unary_prefix_operator: false,
989 space_after_additive_unary_prefix_operator: false,
990 empty_line_after_control_structure: false,
991 empty_line_after_opening_tag: true,
992 empty_line_after_declare: true,
993 empty_line_after_namespace: true,
994 empty_line_after_use: true,
995 empty_line_after_symbols: true,
996 empty_line_between_same_symbols: true,
997 empty_line_after_class_like_constant: false,
998 empty_line_after_enum_case: false,
999 empty_line_after_trait_use: false,
1000 empty_line_after_property: false,
1001 empty_line_after_method: true,
1002 empty_line_before_return: false,
1003 empty_line_before_dangling_comments: true,
1004 separate_class_like_members: true,
1005 }
1006 }
1007}
1008
1009#[cfg(test)]
1010mod tests {
1011 use super::*;
1012
1013 #[test]
1014 fn consistent_default() {
1015 let default_settings = FormatSettings::default();
1016 let default_deserialized: FormatSettings = serde_json::from_str("{}").unwrap();
1017 assert_eq!(default_settings, default_deserialized);
1018 }
1019}
1020
1021/// Specifies the style of line endings.
1022#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, JsonSchema)]
1023pub enum EndOfLine {
1024 #[default]
1025 #[serde(alias = "auto")]
1026 Auto,
1027 #[serde(alias = "lf")]
1028 Lf,
1029 #[serde(alias = "crlf")]
1030 Crlf,
1031 #[serde(alias = "cr")]
1032 Cr,
1033}
1034
1035/// Specifies the style of line endings.
1036#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, JsonSchema)]
1037pub enum BraceStyle {
1038 #[serde(alias = "same_line")]
1039 SameLine,
1040 #[serde(alias = "next_line")]
1041 NextLine,
1042}
1043
1044#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, JsonSchema)]
1045pub enum MethodChainBreakingStyle {
1046 #[serde(alias = "same_line")]
1047 SameLine,
1048 #[default]
1049 #[serde(alias = "next_line")]
1050 NextLine,
1051}
1052
1053impl BraceStyle {
1054 #[must_use]
1055 pub fn same_line() -> Self {
1056 Self::SameLine
1057 }
1058
1059 #[must_use]
1060 pub fn next_line() -> Self {
1061 Self::NextLine
1062 }
1063
1064 #[inline]
1065 #[must_use]
1066 pub fn is_next_line(&self) -> bool {
1067 *self == Self::NextLine
1068 }
1069}
1070
1071impl MethodChainBreakingStyle {
1072 #[inline]
1073 #[must_use]
1074 pub fn is_next_line(&self) -> bool {
1075 *self == Self::NextLine
1076 }
1077}
1078
1079impl EndOfLine {
1080 #[inline]
1081 #[must_use]
1082 pub const fn as_str(&self) -> &'static str {
1083 match self {
1084 Self::Crlf => "\r\n",
1085 Self::Cr => "\r",
1086 Self::Lf | Self::Auto => "\n",
1087 }
1088 }
1089}
1090
1091impl FromStr for EndOfLine {
1092 type Err = ();
1093
1094 fn from_str(s: &str) -> Result<Self, Self::Err> {
1095 Ok(match s {
1096 "crlf" => Self::Crlf,
1097 "cr" => Self::Cr,
1098 "auto" => Self::Auto,
1099 "lf" => Self::Lf,
1100 _ => Self::default(),
1101 })
1102 }
1103}
1104
1105/// Specifies null type hint style.
1106#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, JsonSchema)]
1107pub enum NullTypeHint {
1108 #[serde(alias = "null_pipe", alias = "pipe", alias = "long", alias = "|")]
1109 NullPipe,
1110 #[default]
1111 #[serde(alias = "question", alias = "short", alias = "?")]
1112 Question,
1113}
1114
1115impl NullTypeHint {
1116 #[must_use]
1117 pub fn is_question(&self) -> bool {
1118 *self == Self::Question
1119 }
1120}
1121
1122fn default_print_width() -> usize {
1123 120
1124}
1125
1126fn default_tab_width() -> usize {
1127 4
1128}
1129
1130fn default_false() -> bool {
1131 false
1132}
1133
1134fn default_true() -> bool {
1135 true
1136}