microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.22.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/compiler/qsc_formatter/src/formatter/tests.rs

1387lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![allow(clippy::unicode_not_nfc)]
5
6use expect_test::{Expect, expect};
7use indoc::indoc;
8
9fn check(input: &str, expect: &Expect) {
10 let actual = super::format_str(input);
11 expect.assert_eq(&actual);
12}
13
14fn check_edits(input: &str, expect: &Expect) {
15 let actual = super::calculate_format_edits(input);
16 expect.assert_debug_eq(&actual);
17}
18
19// Removing trailing whitespace from lines
20
21#[test]
22fn remove_trailing_spaces() {
23 let extra_spaces = " ";
24 let input = format!(
25 "/// Doc Comment with trailing spaces{extra_spaces}
26 operation Foo() : Unit {{
27 // Comment with trailing spaces{extra_spaces}
28 let x = 3; // In-line comment with trailing spaces{extra_spaces}
29 let y = 4;{extra_spaces}
30 }}
31"
32 );
33
34 check(
35 input.as_str(),
36 &expect![[r#"
37 /// Doc Comment with trailing spaces
38 operation Foo() : Unit {
39 // Comment with trailing spaces
40 let x = 3; // In-line comment with trailing spaces
41 let y = 4;
42 }
43 "#]],
44 );
45}
46
47#[test]
48fn preserve_string_trailing_spaces() {
49 let extra_spaces = " ";
50 let input = format!(
51 "\"Hello{extra_spaces}
52World\""
53 );
54
55 assert!(super::calculate_format_edits(input.as_str()).is_empty());
56}
57
58// Namespace items begin on their own lines
59
60#[test]
61fn namespace_items_begin_on_their_own_lines() {
62 check(
63 "operation Foo() : Unit {} function Bar() : Unit {}",
64 &expect![[r#"
65 operation Foo() : Unit {}
66 function Bar() : Unit {}"#]],
67 );
68}
69
70// Functor specializations begin on their own lines
71
72#[test]
73fn functor_specs_begin_on_their_own_lines() {
74 check(
75 "operation Foo() : Unit { body ... {} adjoint ... {} controlled (c, ...) {} controlled adjoint (c, ...) {}
76 }",
77 &expect![[r#"
78 operation Foo() : Unit {
79 body ... {}
80 adjoint ... {}
81 controlled (c, ...) {}
82 controlled adjoint (c, ...) {}
83 }"#]],
84 );
85}
86
87#[test]
88fn single_space_between_adjoint_controlled_func_spec_keywords() {
89 check(
90 indoc! {"
91 operation Foo() : Unit {
92 body ... {}
93 adjoint ... {}
94 controlled (c, ...) {}
95 controlled adjoint (c, ...) {}
96 }
97 operation Bar() : Unit {
98 body ... {}
99 adjoint ... {}
100 controlled (c, ...) {}
101 adjoint controlled (c, ...) {}
102 }"},
103 &expect![[r#"
104 operation Foo() : Unit {
105 body ... {}
106 adjoint ... {}
107 controlled (c, ...) {}
108 controlled adjoint (c, ...) {}
109 }
110 operation Bar() : Unit {
111 body ... {}
112 adjoint ... {}
113 controlled (c, ...) {}
114 adjoint controlled (c, ...) {}
115 }"#]],
116 );
117}
118
119// Single spaces before generator keywords
120
121#[test]
122fn single_spaces_before_generator_keywords() {
123 check(
124 indoc! {"
125 operation Foo() : Unit {
126 body ... intrinsic
127 adjoint ... invert
128 controlled (c, ...) distribute
129 controlled adjoint (c, ...) auto
130 adjoint ... self
131 }"},
132 &expect![[r#"
133 operation Foo() : Unit {
134 body ... intrinsic
135 adjoint ... invert
136 controlled (c, ...) distribute
137 controlled adjoint (c, ...) auto
138 adjoint ... self
139 }"#]],
140 );
141}
142
143// Single spaces around most binary operators
144
145#[test]
146fn singe_space_around_arithmetic_bin_ops() {
147 // Note that `-` is missing at this time due to it being unsupported for formatting.
148 check(
149 indoc! {"
150 1+2;
151 1 * 2;
152 4 /2;
153 3% 2;
154 "},
155 &expect![[r#"
156 1 + 2;
157 1 * 2;
158 4 / 2;
159 3 % 2;
160 "#]],
161 );
162}
163
164#[test]
165fn singe_space_around_bit_wise_bin_ops() {
166 check(
167 indoc! {"
168 1&&&2;
169 1 ||| 2;
170 4 ^^^2;
171 3<<< 2;
172 2 >>> 3;
173 "},
174 &expect![[r#"
175 1 &&& 2;
176 1 ||| 2;
177 4 ^^^ 2;
178 3 <<< 2;
179 2 >>> 3;
180 "#]],
181 );
182}
183
184#[test]
185fn singe_space_around_boolean_bin_ops() {
186 check(
187 indoc! {"
188 true and false;
189 true or false;
190 "},
191 &expect![[r#"
192 true and false;
193 true or false;
194 "#]],
195 );
196}
197
198#[test]
199fn singe_space_around_bin_op_equals() {
200 check(
201 indoc! {"
202 let x += y;
203 let x -=y;
204 let x*= y;
205 let x /= y;
206 let x %= y;
207 "},
208 &expect![[r#"
209 let x += y;
210 let x -= y;
211 let x *= y;
212 let x /= y;
213 let x %= y;
214 "#]],
215 );
216}
217
218#[test]
219fn singe_space_around_equals() {
220 check("let x = 3;", &expect!["let x = 3;"]);
221}
222
223#[test]
224fn singe_space_around_colon() {
225 check("let x : Int = 3;", &expect!["let x : Int = 3;"]);
226}
227
228#[test]
229fn singe_space_around_comp_ops() {
230 // Note that `<` and `>` are missing at this time due to them being unsupported for formatting.
231 check(
232 indoc! {"
233 x <=y;
234 x >= y;
235 x == y;
236 x != y;
237 "},
238 &expect![[r#"
239 x <= y;
240 x >= y;
241 x == y;
242 x != y;
243 "#]],
244 );
245}
246
247#[test]
248fn singe_space_around_ternary() {
249 check("x? 3| 4", &expect!["x ? 3 | 4"]);
250}
251
252#[test]
253fn singe_space_around_copy() {
254 check("x w/3 <- 4", &expect!["x w/ 3 <- 4"]);
255}
256
257#[test]
258fn singe_space_around_copy_and_update() {
259 check("x w/=3 <- 4", &expect!["x w/= 3 <- 4"]);
260}
261
262#[test]
263fn singe_space_around_lambda_ops() {
264 check(
265 indoc! {"
266 let x = () -> ();
267 let y = ()=>();
268 "},
269 &expect![[r#"
270 let x = () -> ();
271 let y = () => ();
272 "#]],
273 );
274}
275
276#[test]
277fn singe_space_around_characteristic_expr() {
278 check(
279 "operation Foo() : Unit is Adj+Ctl {}",
280 &expect!["operation Foo() : Unit is Adj + Ctl {}"],
281 );
282}
283
284#[test]
285fn singe_space_around_functors() {
286 check(
287 "Controlled Adjoint Foo()",
288 &expect!["Controlled Adjoint Foo()"],
289 );
290}
291
292#[test]
293fn singe_space_around_as() {
294 check(
295 "open thing as other;",
296 &expect!["open thing as other;"],
297 );
298}
299
300// No space between unary operators and their operand
301
302#[test]
303fn no_space_before_unwrap() {
304 check("let x = foo !;", &expect!["let x = foo!;"]);
305}
306
307#[test]
308fn no_space_after_bit_negation() {
309 check("let x = ~~~ 3;", &expect!["let x = ~~~3;"]);
310}
311
312#[test]
313fn single_space_around_boolean_negation() {
314 check("let x = not 3;", &expect!["let x = not 3;"]);
315}
316
317// No space after open parentheses and brackets and before close parentheses and brackets
318
319#[test]
320fn no_space_for_parentheses() {
321 check("( 12, 13, 14 )", &expect!["(12, 13, 14)"]);
322}
323
324#[test]
325fn no_space_for_brackets() {
326 check("[ 12 + 13 + 14 ]", &expect!["[12 + 13 + 14]"]);
327}
328
329// No space after open string-interpolation argument braces and before close string-interpolation argument braces
330
331#[test]
332fn no_space_for_string_interpolation_argument_braces() {
333 check(
334 r#"let x = $"First { 1 + 1 } Third";"#,
335 &expect![[r#"let x = $"First {1 + 1} Third";"#]],
336 );
337}
338
339// No space before commas or semicolons
340
341#[test]
342fn no_space_before_comma() {
343 check("(12 , 13 , 14)", &expect!["(12, 13, 14)"]);
344}
345
346#[test]
347fn no_space_before_semicolons() {
348 check("let x = 3 ;", &expect!["let x = 3;"]);
349}
350
351// Newline after semicolons
352
353#[test]
354fn newline_after_semicolon() {
355 check(
356 "let x = 3; let y = 2;",
357 &expect![[r#"
358 let x = 3;
359 let y = 2;"#]],
360 );
361}
362
363#[test]
364fn preserve_eol_comment() {
365 let input = indoc! {"let x = 3; // End-of-line Comment
366 let y = 2;
367 "};
368 assert!(super::calculate_format_edits(input).is_empty());
369}
370
371// Newline before declaration keywords
372
373#[test]
374fn newline_before_let() {
375 check(
376 "let x = 3; {} let y = 2;",
377 &expect![[r#"
378 let x = 3;
379 {}
380 let y = 2;"#]],
381 );
382}
383
384#[test]
385fn newline_before_mutable() {
386 check(
387 "mutable x = 3; {} mutable y = 2;",
388 &expect![[r#"
389 mutable x = 3;
390 {}
391 mutable y = 2;"#]],
392 );
393}
394
395#[test]
396fn newline_before_set() {
397 check(
398 "set x = 3; {} set y = 2;",
399 &expect![[r#"
400 set x = 3;
401 {}
402 set y = 2;"#]],
403 );
404}
405
406#[test]
407fn newline_before_use() {
408 check(
409 "use q = Qubit(); {} use w = Qubit();",
410 &expect![[r#"
411 use q = Qubit();
412 {}
413 use w = Qubit();"#]],
414 );
415}
416
417#[test]
418fn newline_before_borrow() {
419 check(
420 "borrow q = Qubit(); {} borrow w = Qubit();",
421 &expect![[r#"
422 borrow q = Qubit();
423 {}
424 borrow w = Qubit();"#]],
425 );
426}
427
428// Single space before control-flow-helper keywords
429
430#[test]
431fn single_space_before_in() {
432 check("for x in 0..2 {}", &expect![[r#"for x in 0..2 {}"#]]);
433}
434
435#[test]
436fn single_space_before_until() {
437 check(
438 "repeat {} until x fixup {}",
439 &expect![[r#"
440 repeat {} until x
441 fixup {}"#]],
442 );
443}
444
445#[test]
446fn single_space_before_elif_and_else() {
447 check(
448 "if x {} elif y {} else {}",
449 &expect!["if x {} elif y {} else {}"],
450 );
451}
452
453#[test]
454fn single_space_before_apply() {
455 check("within {} apply {}", &expect!["within {} apply {}"]);
456}
457
458// No space between caller expressions and argument tuple
459
460#[test]
461fn no_space_in_front_of_argument_tuple() {
462 check("Foo (1, 2, 3)", &expect!["Foo(1, 2, 3)"]);
463}
464
465#[test]
466fn no_space_in_front_of_parameter_tuple() {
467 check(
468 "operation Foo (x : Int, y : Int) : Unit {}",
469 &expect!["operation Foo(x : Int, y : Int) : Unit {}"],
470 );
471}
472
473// No space between array expressions and indexing brackets
474
475#[test]
476fn no_space_in_front_of_array_indexing() {
477 check("arr [4]", &expect!["arr[4]"]);
478}
479
480// No space around `.`, `..`, and `::` operators
481
482#[test]
483fn no_space_around_dot_operator() {
484 check("let x = thing . other;", &expect!["let x = thing.other;"]);
485}
486
487#[test]
488fn no_space_around_range_operator() {
489 check("let x = 1 .. 4;", &expect!["let x = 1..4;"]);
490}
491
492#[test]
493fn no_space_around_field_operator() {
494 check("let x = thing :: other;", &expect!["let x = thing::other;"]);
495}
496
497// No space between the `…` operator and any possible operands on either side
498
499#[test]
500fn no_space_around_full_range_in_slice() {
501 check("let x = y[ ... ];", &expect!["let x = y[...];"]);
502}
503
504#[test]
505fn no_space_between_open_end_range_and_operand() {
506 check("let x = 15 ...;", &expect!["let x = 15...;"]);
507}
508
509#[test]
510fn no_space_between_open_start_range_and_operand() {
511 check("let x = ... 15;", &expect!["let x = ...15;"]);
512}
513
514// Single space before open brace and newline after, except empty blocks have no space
515
516#[test]
517fn single_space_before_open_brace_and_newline_after() {
518 check(
519 indoc! {r#"
520 operation Foo() : Unit{ let x = 3; }
521 operation Bar() : Unit
522 { { let x = 3; }{ let x = 4; } }
523 "#},
524 &expect![[r#"
525 operation Foo() : Unit {
526 let x = 3;
527 }
528 operation Bar() : Unit { {
529 let x = 3;
530 }
531 {
532 let x = 4;
533 } }
534 "#]],
535 );
536}
537
538#[test]
539fn remove_spaces_between_empty_delimiters() {
540 check(
541 indoc! {r#"
542 operation Foo() : Unit {
543 }
544 operation Bar() : Unit {
545 operation Baz() : Unit { }
546 let x = {
547
548 };
549 let y : Int[] = [ ];
550 let z = (
551
552 );
553 }
554 "#},
555 &expect![[r#"
556 operation Foo() : Unit {}
557 operation Bar() : Unit {
558 operation Baz() : Unit {}
559 let x = {};
560 let y : Int[] = [];
561 let z = ();
562 }
563 "#]],
564 );
565}
566
567// Single space before literals
568
569#[test]
570fn single_space_before_literals() {
571 check(
572 indoc! {"
573 let x = 15;
574 let x = 0xF;
575 let x = 15.0;
576 let x = 15L;
577 let x = \"Fifteen\";
578 let x = $\"Fifteen\";
579 let x = PauliI;
580 let x = PauliX;
581 let x = PauliY;
582 let x = PauliZ;
583 let x = true;
584 let x = false;
585 let x = One;
586 let x = Zero;
587 "},
588 &expect![[r#"
589 let x = 15;
590 let x = 0xF;
591 let x = 15.0;
592 let x = 15L;
593 let x = "Fifteen";
594 let x = $"Fifteen";
595 let x = PauliI;
596 let x = PauliX;
597 let x = PauliY;
598 let x = PauliZ;
599 let x = true;
600 let x = false;
601 let x = One;
602 let x = Zero;
603 "#]],
604 );
605}
606
607// Single space before types
608
609#[test]
610fn single_space_before_types() {
611 check(
612 "let x : (Int, Double, String[], (BigInt, Unit), ('T, )) => 'T = foo;",
613 &expect![[r#"let x : (Int, Double, String[], (BigInt, Unit), ('T, )) => 'T = foo;"#]],
614 );
615}
616
617// Single space before variables
618
619#[test]
620fn single_space_before_idents() {
621 check("let x = foo;", &expect!["let x = foo;"]);
622}
623
624// Formatter continues after error token
625
626#[test]
627fn formatter_continues_after_error_token() {
628 check(
629 indoc! {"
630 let x : ' T = foo;
631 let x : ` T = foo;
632 let x : & T = foo;
633 let x : || T = foo;
634 let x : ^^ T = foo;
635 "},
636 &expect![[r#"
637 let x : ' T = foo;
638 let x : ` T = foo;
639 let x : & T = foo;
640 let x : || T = foo;
641 let x : ^^ T = foo;
642 "#]],
643 );
644}
645
646#[test]
647fn formatter_does_not_crash_on_non_terminating_string() {
648 let _ = super::calculate_format_edits("let x = \"Hello World");
649}
650
651// Correct indentation, which increases by four spaces when a delimited block is opened and decreases when block is closed
652
653#[test]
654fn formatting_corrects_indentation() {
655 check(
656 r#"
657 /// First
658/// Second
659 /// Third
660 namespace MyQuantumProgram {
661 import Std.Diagnostics.*;
662
663 @EntryPoint()
664 operation Main() : Int {
665 let x = 3;
666 let y = 4;
667
668 // Comment
669 return 5;
670 }
671 }
672"#,
673 &expect![[r#"
674 /// First
675 /// Second
676 /// Third
677 namespace MyQuantumProgram {
678 import Std.Diagnostics.*;
679
680 @EntryPoint()
681 operation Main() : Int {
682 let x = 3;
683 let y = 4;
684
685 // Comment
686 return 5;
687 }
688 }
689 "#]],
690 );
691}
692
693#[test]
694fn nested_delimiter_indentation() {
695 check(
696 indoc! {r#"
697 let x = [
698 (1)
699 ];
700 let y = 3;
701 "#},
702 &expect![[r#"
703 let x = [
704 (1)
705 ];
706 let y = 3;
707 "#]],
708 );
709}
710
711#[test]
712fn delimiter_comments() {
713 check(
714 indoc! {r#"
715 let x = [ // this is a comment
716 (1)
717 ];
718 let y = 3;
719 "#},
720 &expect![[r#"
721 let x = [
722 // this is a comment
723 (1)
724 ];
725 let y = 3;
726 "#]],
727 );
728}
729
730#[test]
731fn brace_no_newlines() {
732 check(
733 indoc! {r#"
734 { Foo();
735 Bar(); Baz()
736 }
737 "#},
738 &expect![[r#"
739 { Foo(); Bar(); Baz() }
740 "#]],
741 );
742}
743
744#[test]
745fn brace_newlines() {
746 check(
747 indoc! {r#"
748 {
749 Foo(); Bar(); Baz() }
750 "#},
751 &expect![[r#"
752 {
753 Foo();
754 Bar();
755 Baz()
756 }
757 "#]],
758 );
759}
760
761#[test]
762fn parens_no_newlines() {
763 check(
764 indoc! {r#"
765 ( Foo(),
766 Bar(), Baz()
767 )
768 "#},
769 &expect![[r#"
770 (Foo(), Bar(), Baz())
771 "#]],
772 );
773}
774
775#[test]
776fn parens_newlines() {
777 check(
778 indoc! {r#"
779 (
780 Foo(), Bar(), Baz() )
781 "#},
782 &expect![[r#"
783 (
784 Foo(),
785 Bar(),
786 Baz()
787 )
788 "#]],
789 );
790}
791
792#[test]
793fn bracket_no_newlines() {
794 check(
795 indoc! {r#"
796 [ Foo(),
797 Bar(), Baz()
798 ]
799 "#},
800 &expect![[r#"
801 [Foo(), Bar(), Baz()]
802 "#]],
803 );
804}
805
806#[test]
807fn bracket_newlines() {
808 check(
809 indoc! {r#"
810 [
811 Foo(), Bar(), Baz() ]
812 "#},
813 &expect![[r#"
814 [
815 Foo(),
816 Bar(),
817 Baz()
818 ]
819 "#]],
820 );
821}
822
823#[test]
824fn semi_no_context_uses_newlines() {
825 check(
826 indoc! {r#"
827 Foo(); Bar(); Baz()
828 "#},
829 &expect![[r#"
830 Foo();
831 Bar();
832 Baz()
833 "#]],
834 );
835}
836
837#[test]
838fn comma_no_context_uses_space() {
839 check(
840 indoc! {r#"
841 Foo(),
842 Bar(),
843 Baz()
844 "#},
845 &expect![[r#"
846 Foo(), Bar(), Baz()
847 "#]],
848 );
849}
850
851#[test]
852fn type_param_lists_have_no_spaces_around_delims() {
853 check(
854 indoc! {r#"
855 {
856 operation Foo < 'A,
857 'B, 'C > (a : 'A, b : 'B, c : 'C) : Unit {}
858 }
859 "#},
860 &expect![[r#"
861 {
862 operation Foo<'A, 'B, 'C>(a : 'A, b : 'B, c : 'C) : Unit {}
863 }
864 "#]],
865 );
866}
867
868#[test]
869fn greater_than_and_less_than_bin_ops_have_spaces() {
870 check(indoc! {r#"x<y>z;"#}, &expect!["x < y > z;"]);
871}
872
873#[test]
874fn delimiter_newlines_indentation() {
875 check(
876 r#"
877 let x = [ a, b, c ];
878 let y = [ a,
879 b, c ];
880 let z = [
881
882
883 a, b, c
884 ];
885"#,
886 &expect![[r#"
887 let x = [a, b, c];
888 let y = [a, b, c];
889 let z = [
890
891
892 a,
893 b,
894 c
895 ];
896 "#]],
897 );
898}
899
900#[test]
901fn preserve_string_indentation() {
902 let input = r#""Hello
903 World""#;
904
905 assert!(super::calculate_format_edits(input).is_empty());
906}
907
908// Will respect user new-lines and indentation added into expressions
909
910#[test]
911fn newline_after_brace_before_value() {
912 check(
913 indoc! {r#"
914 {
915 let x = 3;
916 } x
917 "#},
918 &expect![[r#"
919 {
920 let x = 3;
921 }
922 x
923 "#]],
924 );
925}
926
927#[test]
928fn newline_after_brace_before_functor() {
929 check(
930 indoc! {r#"
931 {
932 let x = 3;
933 } Adjoint Foo();
934 "#},
935 &expect![[r#"
936 {
937 let x = 3;
938 }
939 Adjoint Foo();
940 "#]],
941 );
942}
943
944#[test]
945fn newline_after_brace_before_not_keyword() {
946 check(
947 indoc! {r#"
948 {
949 let x = 3;
950 } not true
951 "#},
952 &expect![[r#"
953 {
954 let x = 3;
955 }
956 not true
957 "#]],
958 );
959}
960
961#[test]
962fn newline_after_brace_before_starter_keyword() {
963 check(
964 indoc! {r#"
965 {
966 let x = 3;
967 } if true {}
968 "#},
969 &expect![[r#"
970 {
971 let x = 3;
972 }
973 if true {}
974 "#]],
975 );
976}
977
978#[test]
979fn newline_after_brace_before_brace() {
980 check(
981 indoc! {r#"
982 {
983 let x = 3;
984 } {}
985 "#},
986 &expect![[r#"
987 {
988 let x = 3;
989 }
990 {}
991 "#]],
992 );
993}
994
995#[test]
996fn space_after_brace_before_operator() {
997 check(
998 indoc! {r#"
999 {
1000 let x = 3;
1001 } + {}
1002 "#},
1003 &expect![[r#"
1004 {
1005 let x = 3;
1006 } + {}
1007 "#]],
1008 );
1009}
1010
1011#[test]
1012fn newline_after_brace_before_delim() {
1013 check(
1014 indoc! {r#"
1015 {} ()
1016 {} []
1017 "#},
1018 &expect![[r#"
1019 {}
1020 () {}
1021 []
1022 "#]],
1023 );
1024}
1025
1026// Copy operator can have single space or newline
1027
1028#[test]
1029fn copy_operator_with_newline_is_indented() {
1030 check(
1031 indoc! {r#"
1032 let x = arr
1033 w/ 0 <- 10
1034 w/ 1 <- 11
1035 "#},
1036 &expect![[r#"
1037 let x = arr
1038 w/ 0 <- 10
1039 w/ 1 <- 11
1040 "#]],
1041 );
1042}
1043
1044#[test]
1045fn copy_operator_with_space_has_single_space() {
1046 check(
1047 indoc! {r#"
1048 let x = arr w/ 0 <- 10 w/ 1 <- 11
1049 "#},
1050 &expect![[r#"
1051 let x = arr w/ 0 <- 10 w/ 1 <- 11
1052 "#]],
1053 );
1054}
1055
1056#[test]
1057fn no_space_around_carrot() {
1058 check(
1059 indoc! {r#"
1060 {} ^ {}
1061 1 ^ 2
1062 "#},
1063 &expect![[r#"
1064 {}^{}
1065 1^2
1066 "#]],
1067 );
1068}
1069
1070#[test]
1071fn no_space_around_ellipse() {
1072 check(
1073 indoc! {r#"
1074 {} ... {}
1075 "#},
1076 &expect![[r#"
1077 {}...{}
1078 "#]],
1079 );
1080}
1081
1082#[test]
1083fn single_space_after_spec_decl_ellipse() {
1084 check(
1085 indoc! {r#"
1086 body ...auto
1087 adjoint ...{}
1088 "#},
1089 &expect![[r#"
1090 body ... auto
1091 adjoint ... {}
1092 "#]],
1093 );
1094}
1095
1096// Remove extra whitespace from start of code
1097
1098#[test]
1099fn remove_extra_whitespace_from_start_of_code() {
1100 let input = indoc! {r#"
1101
1102
1103
1104
1105 namespace Foo {}"#};
1106
1107 check(input, &expect!["namespace Foo {}"]);
1108}
1109
1110// Extra test cases for sanity
1111
1112#[test]
1113fn preserve_comments_at_start_of_file() {
1114 let input = indoc! {r#"
1115 // Initial Comment
1116 namespace Foo {}"#};
1117
1118 assert!(super::calculate_format_edits(input).is_empty());
1119}
1120
1121#[test]
1122fn format_with_crlf() {
1123 let content = indoc! {"//qsharp\r\n\r\noperation Foo() : Unit {\r\n\r\n}\r\n"};
1124 check_edits(
1125 content,
1126 &expect![[r#"
1127 [
1128 TextEdit {
1129 new_text: "",
1130 span: Span {
1131 lo: 36,
1132 hi: 40,
1133 },
1134 },
1135 ]
1136 "#]],
1137 );
1138 check(
1139 content,
1140 &expect![["//qsharp\r\n\r\noperation Foo() : Unit {}\r\n"]],
1141 );
1142}
1143
1144#[test]
1145fn format_does_not_edit_magic_comment() {
1146 let content = indoc! {"\r\n\r\n //qsharp \r\n\r\noperation Foo() : Unit {\r\n\r\n}\r\n"};
1147 check_edits(
1148 content,
1149 &expect![[r#"
1150 [
1151 TextEdit {
1152 new_text: "",
1153 span: Span {
1154 lo: 0,
1155 hi: 8,
1156 },
1157 },
1158 TextEdit {
1159 new_text: "//qsharp",
1160 span: Span {
1161 lo: 8,
1162 hi: 20,
1163 },
1164 },
1165 TextEdit {
1166 new_text: "",
1167 span: Span {
1168 lo: 48,
1169 hi: 52,
1170 },
1171 },
1172 ]
1173 "#]],
1174 );
1175 check(
1176 content,
1177 &expect![["//qsharp\r\n\r\noperation Foo() : Unit {}\r\n"]],
1178 );
1179}
1180
1181#[test]
1182fn sample_has_no_formatting_changes() {
1183 let input = indoc! {r#"
1184 /// # Sample
1185 /// Joint Measurement
1186 ///
1187 /// # Description
1188 /// Joint measurements, also known as Pauli measurements, are a generalization
1189 /// of 2-outcome measurements to multiple qubits and other bases.
1190 namespace Sample {
1191 import Std.Diagnostics.*;
1192
1193 @EntryPoint()
1194 operation Main() : (Result, Result[]) {
1195 // Prepare an entangled state.
1196 use qs = Qubit[2]; // |00〉
1197 H(qs[0]); // 1/sqrt(2)(|00〉 + |10〉)
1198 CNOT(qs[0], qs[1]); // 1/sqrt(2)(|00〉 + |11〉)
1199
1200 // Show the quantum state before performing the joint measurement.
1201 DumpMachine();
1202
1203 // The below code uses a joint measurement as a way to check the parity
1204 // of the first two qubits. In this case, the parity measurement result
1205 // will always be `Zero`.
1206 // Notice how the state was not collapsed by the joint measurement.
1207 let parityResult = Measure([PauliZ, PauliZ], qs[...1]);
1208 DumpMachine();
1209
1210 // However, if we perform a measurement just on the first qubit, we can
1211 // see how the state collapses.
1212 let firstQubitResult = M(qs[0]);
1213 DumpMachine();
1214
1215 // Measuring the last qubit does not change the quantum state
1216 // since the state of the second qubit collapsed when the first qubit
1217 // was measured because they were entangled.
1218 let secondQubitResult = M(qs[1]);
1219 DumpMachine();
1220
1221 ResetAll(qs);
1222 return (parityResult, [firstQubitResult, secondQubitResult]);
1223 }
1224 }
1225 "#};
1226 assert!(super::calculate_format_edits(input).is_empty());
1227}
1228
1229#[test]
1230fn format_export_statement_no_newlines() {
1231 let input = "export Microsoft.Quantum.Diagnostics, Foo.Bar.Baz;";
1232
1233 check(
1234 input,
1235 &expect![["export Microsoft.Quantum.Diagnostics, Foo.Bar.Baz;"]],
1236 );
1237}
1238
1239#[test]
1240fn format_glob_import() {
1241 let input = "import
1242 Microsoft.Quantum.*,
1243 Foo.Bar.Baz as SomethingElse,
1244 AnotherThing;";
1245
1246 check(
1247 input,
1248 &expect![[r#"
1249 import
1250 Microsoft.Quantum.*,
1251 Foo.Bar.Baz as SomethingElse,
1252 AnotherThing;"#]],
1253 );
1254}
1255#[test]
1256fn no_newlines_glob() {
1257 let input = "import foo, bar, baz.quux.*;";
1258
1259 check(input, &expect!["import foo, bar, baz.quux.*;"]);
1260}
1261
1262#[test]
1263fn format_export_statement_newlines() {
1264 let input = "export
1265 Microsoft.Quantum.Diagnostics,
1266 Foo.Bar.Baz;";
1267
1268 check(
1269 input,
1270 &expect![[r#"
1271 export
1272 Microsoft.Quantum.Diagnostics,
1273 Foo.Bar.Baz;"#]],
1274 );
1275}
1276
1277#[test]
1278#[allow(clippy::too_many_lines)]
1279fn export_fmt_within_namespace() {
1280 let input = r#"
1281
1282namespace Microsoft.Quantum.Arrays {
1283
1284
1285 export
1286 All,
1287 Any,
1288 Chunks,
1289 CircularlyShifted,
1290 ColumnAt,
1291 Count,
1292 Diagonal,
1293 DrawMany,
1294 Enumerated,
1295 Excluding,
1296 Filtered,
1297 FlatMapped,
1298 Flattened,
1299 Fold,
1300 ForEach,
1301 Head,
1302 HeadAndRest,
1303 IndexOf,
1304 IndexRange,
1305 Interleaved,
1306 IsEmpty,
1307 IsRectangularArray,
1308 IsSorted,
1309 IsSquareArray,
1310 Mapped,
1311 MappedByIndex,
1312 MappedOverRange,
1313 Most,
1314 MostAndTail,
1315 Padded,
1316 Partitioned,
1317 Rest,
1318 Reversed,
1319 SequenceI,
1320 SequenceL,
1321 Sorted,
1322 Subarray,
1323 Swapped,
1324 Transposed,
1325 Tail,
1326 Unzipped,
1327 Where,
1328 Windows,
1329 Zipped;
1330}
1331"#;
1332
1333 check(
1334 input,
1335 &expect![[r#"
1336 namespace Microsoft.Quantum.Arrays {
1337
1338
1339 export
1340 All,
1341 Any,
1342 Chunks,
1343 CircularlyShifted,
1344 ColumnAt,
1345 Count,
1346 Diagonal,
1347 DrawMany,
1348 Enumerated,
1349 Excluding,
1350 Filtered,
1351 FlatMapped,
1352 Flattened,
1353 Fold,
1354 ForEach,
1355 Head,
1356 HeadAndRest,
1357 IndexOf,
1358 IndexRange,
1359 Interleaved,
1360 IsEmpty,
1361 IsRectangularArray,
1362 IsSorted,
1363 IsSquareArray,
1364 Mapped,
1365 MappedByIndex,
1366 MappedOverRange,
1367 Most,
1368 MostAndTail,
1369 Padded,
1370 Partitioned,
1371 Rest,
1372 Reversed,
1373 SequenceI,
1374 SequenceL,
1375 Sorted,
1376 Subarray,
1377 Swapped,
1378 Transposed,
1379 Tail,
1380 Unzipped,
1381 Where,
1382 Windows,
1383 Zipped;
1384 }
1385 "#]],
1386 );
1387}
1388