microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.8.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_formatter/src/formatter/tests.rs

1384lines · modecode

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