Fork of daniellemaywood.uk/gleam — Wasm codegen work
20 kB
1167 lines
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2025 The Gleam contributors
3
4use lsp_types::{
5 DocumentHighlightParams, PartialResultParams, Position, Range, TextDocumentPositionParams,
6 WorkDoneProgressParams,
7};
8
9use super::{TestProject, find_position_of};
10
11fn find_highlights(tester: &TestProject<'_>, position: Position) -> Option<(String, Vec<Range>)> {
12 tester.at(position, |engine, params, _| {
13 let params = DocumentHighlightParams {
14 text_document_position_params: TextDocumentPositionParams {
15 text_document: params.text_document,
16 position,
17 },
18 work_done_progress_params: WorkDoneProgressParams::default(),
19 partial_result_params: PartialResultParams::default(),
20 };
21 let module_name = tester
22 .module_name_from_url(¶ms.text_document_position_params.text_document.uri)
23 .expect("Valid uri");
24 engine
25 .document_highlight(params)
26 .result
27 .unwrap()
28 .map(|highlights| {
29 highlights
30 .into_iter()
31 .map(|highlight| highlight.range)
32 .collect()
33 })
34 .map(|highlights| (module_name, highlights))
35 })
36}
37
38fn show_highlights(code: &str, position: Option<Position>, ranges: &[Range]) -> String {
39 let mut buffer = String::new();
40
41 for (line_number, line) in code.lines().enumerate() {
42 let mut underline = String::new();
43 let mut underline_empty = true;
44 let line_number = line_number as u32;
45
46 for (column_number, _) in line.chars().enumerate() {
47 let current_position = Position::new(line_number, column_number as u32);
48
49 // Check if any range covers this specific character
50 let is_in_range = ranges
51 .iter()
52 .any(|range| range.start <= current_position && current_position < range.end);
53
54 if Some(current_position) == position {
55 underline_empty = false;
56 underline.push('↑');
57 } else if is_in_range {
58 underline_empty = false;
59 underline.push('▔');
60 } else {
61 underline.push(' ');
62 }
63 }
64
65 buffer.push_str(line);
66 if !underline_empty {
67 buffer.push('\n');
68 buffer.push_str(&underline);
69 }
70 buffer.push('\n');
71 }
72
73 buffer
74}
75
76macro_rules! assert_highlights {
77 ($code:literal, $position:expr $(,)?) => {
78 assert_highlights!(TestProject::for_source($code), $position);
79 };
80
81 (($module_name:literal, $module_src:literal), $code:literal, $position:expr $(,)?) => {
82 assert_highlights!(
83 TestProject::for_source($code).add_module($module_name, $module_src),
84 $position
85 );
86 };
87
88 ($project:expr, $position:expr $(,)?) => {
89 let project = $project;
90 let src = project.src;
91 let position = $position.find_position(src);
92 let (module_name, result) =
93 find_highlights(&project, position).expect("Higlights not found");
94
95 let mut output = String::new();
96 for (name, src) in project.root_package_modules.iter() {
97 let highlights_in_module = if *name == module_name {
98 &result
99 } else {
100 &Vec::new()
101 };
102
103 output.push_str("-- ");
104 output.push_str(name);
105 output.push_str(".gleam\n");
106 output.push_str(&show_highlights(src, None, highlights_in_module));
107 output.push_str("\n\n");
108 }
109 let highlights_in_app_module = if module_name == "app" {
110 &result
111 } else {
112 &Vec::new()
113 };
114 output.push_str("-- app.gleam\n");
115 output.push_str(&show_highlights(
116 src,
117 Some(position),
118 highlights_in_app_module,
119 ));
120
121 insta::assert_snapshot!(insta::internals::AutoName, output, src);
122 };
123}
124
125macro_rules! assert_no_highlights {
126 ($code:literal, $position:expr $(,)?) => {
127 let project = TestProject::for_source($code);
128 assert_no_highlights!(&project, $position);
129 };
130
131 ($project:expr, $position:expr $(,)?) => {
132 let src = $project.src;
133 let position = $position.find_position(src);
134 let result = find_highlights($project, position);
135 assert_eq!(result, None);
136 };
137}
138
139#[test]
140fn highlights_for_local_variable() {
141 assert_highlights!(
142 "
143pub fn main() {
144 let wibble = 10
145 let wobble = wibble + 1
146 wibble + wobble
147}
148",
149 find_position_of("wibble").nth_occurrence(2),
150 );
151}
152
153#[test]
154fn highlights_for_local_variable_from_definition() {
155 assert_highlights!(
156 "
157pub fn main() {
158 let wibble = 10
159 let wobble = wibble + 1
160 wibble + wobble
161}
162",
163 find_position_of("wibble"),
164 );
165}
166
167#[test]
168fn highlights_for_private_function() {
169 assert_highlights!(
170 "
171fn wibble() {
172 wibble()
173}
174
175pub fn main() {
176 let _ = wibble()
177 wibble() + 4
178}
179
180fn wobble() {
181 wibble() || wobble()
182}
183",
184 find_position_of("wibble"),
185 );
186}
187
188#[test]
189fn highlights_for_private_function_from_reference() {
190 assert_highlights!(
191 "
192fn wibble() {
193 wibble()
194}
195
196pub fn main() {
197 let _ = wibble()
198 wibble() + 4
199}
200
201fn wobble() {
202 wibble() || wobble()
203}
204",
205 find_position_of("wibble").nth_occurrence(2),
206 );
207}
208
209#[test]
210fn highlights_for_public_function() {
211 assert_highlights!(
212 (
213 "mod",
214 "
215pub fn wibble() {
216 wibble()
217}
218"
219 ),
220 "
221import mod.{wibble}
222
223fn wobble() {
224 mod.wibble()
225}
226
227fn other() {
228 wibble()
229}
230",
231 find_position_of("wibble").nth_occurrence(2),
232 );
233}
234
235#[test]
236fn highlights_for_function_from_qualified_reference() {
237 assert_highlights!(
238 (
239 "mod",
240 "
241pub fn wibble() {
242 wibble()
243}
244"
245 ),
246 "
247import mod
248
249pub fn main() {
250 let value = mod.wibble()
251 mod.wibble()
252 value
253}
254",
255 find_position_of("wibble"),
256 );
257}
258
259#[test]
260fn highlights_for_function_from_unqualified_reference() {
261 assert_highlights!(
262 (
263 "mod",
264 "
265pub fn wibble() {
266 wibble()
267}
268"
269 ),
270 "
271import mod.{wibble}
272
273pub fn main() {
274 let value = wibble()
275 mod.wibble()
276 value
277}
278",
279 find_position_of("wibble()"),
280 );
281}
282
283#[test]
284fn highlights_for_function_from_unqualified_aliased_reference() {
285 assert_highlights!(
286 (
287 "mod",
288 "
289pub fn wibble() {
290 wibble()
291}
292"
293 ),
294 "
295import mod.{wibble as wobble}
296
297pub fn main() {
298 let value = wobble()
299 mod.wibble()
300 value
301}
302",
303 find_position_of("wobble()"),
304 );
305}
306
307#[test]
308fn highlights_for_private_constant() {
309 assert_highlights!(
310 "
311const wibble = 10
312
313pub fn main() {
314 let _ = wibble
315 wibble + 4
316}
317
318fn wobble() {
319 wibble + wobble()
320}
321",
322 find_position_of("wibble"),
323 );
324}
325
326#[test]
327fn highlights_for_private_constant_from_reference() {
328 assert_highlights!(
329 "
330const wibble = 10
331
332pub fn main() {
333 let _ = wibble
334 wibble + 4
335}
336
337fn wobble() {
338 wibble + wobble()
339}
340",
341 find_position_of("wibble").nth_occurrence(2),
342 );
343}
344
345#[test]
346fn highlights_for_public_constant() {
347 assert_highlights!(
348 (
349 "mod",
350 "
351pub const wibble = 10
352
353pub fn main() {
354 wibble
355}
356"
357 ),
358 "
359import mod.{wibble}
360
361fn wobble() {
362 mod.wibble
363}
364
365fn other() {
366 wibble
367}
368",
369 find_position_of("wibble").nth_occurrence(2),
370 );
371}
372
373#[test]
374fn highlights_for_constant_from_qualified_reference() {
375 assert_highlights!(
376 (
377 "mod",
378 "
379pub const wibble = 10
380
381fn wobble() {
382 wibble
383}
384"
385 ),
386 "
387import mod
388
389pub fn main() {
390 let value = mod.wibble
391 mod.wibble + value
392}
393",
394 find_position_of("wibble"),
395 );
396}
397
398#[test]
399fn highlights_for_constant_from_unqualified_reference() {
400 assert_highlights!(
401 (
402 "mod",
403 "
404pub const wibble = 10
405
406fn wobble() {
407 wibble
408}
409"
410 ),
411 "
412import mod.{wibble}
413
414pub fn main() {
415 let value = mod.wibble
416 wibble + value
417}
418",
419 find_position_of("wibble +"),
420 );
421}
422
423#[test]
424fn highlights_for_constant_from_unqualified_aliased_reference() {
425 assert_highlights!(
426 (
427 "mod",
428 "
429pub const wibble = 10
430
431fn wobble() {
432 wibble
433}
434"
435 ),
436 "
437import mod.{wibble as wobble}
438
439pub fn main() {
440 let value = mod.wibble
441 wobble + value
442}
443",
444 find_position_of("wobble +"),
445 );
446}
447
448#[test]
449fn higlights_for_private_type_variant() {
450 assert_highlights!(
451 "
452type Wibble { Wibble }
453
454fn main() {
455 let _ = Wibble
456 Wibble
457}
458
459fn wobble() {
460 Wibble
461 wobble()
462}
463",
464 find_position_of("Wibble }"),
465 );
466}
467
468#[test]
469fn higlights_for_private_type_variant_from_reference() {
470 assert_highlights!(
471 "
472type Wibble { Wibble }
473
474fn main() {
475 let _ = Wibble
476 Wibble
477}
478
479fn wobble() {
480 Wibble
481 wobble()
482}
483",
484 find_position_of(" = Wibble").under_char('W'),
485 );
486}
487
488#[test]
489fn higlights_for_public_type_variant() {
490 assert_highlights!(
491 (
492 "mod",
493 "
494pub type Wibble { Wibble }
495
496pub fn main() {
497 Wibble
498}
499"
500 ),
501 "
502import mod.{Wibble}
503
504fn wobble() {
505 mod.Wibble
506}
507
508fn other() {
509 Wibble
510}
511",
512 find_position_of("Wibble").nth_occurrence(3),
513 );
514}
515
516#[test]
517fn higlights_for_type_variant_from_qualified_reference() {
518 assert_highlights!(
519 (
520 "mod",
521 "
522pub type Wibble { Wibble }
523
524fn wobble() {
525 Wibble
526}
527"
528 ),
529 "
530import mod
531
532pub fn main() {
533 let value = mod.Wibble
534 mod.Wibble
535 value
536}
537",
538 find_position_of("Wibble"),
539 );
540}
541
542#[test]
543fn higlights_for_type_variant_from_unqualified_reference() {
544 assert_highlights!(
545 (
546 "mod",
547 "
548pub type Wibble { Wibble }
549
550fn wobble() {
551 Wibble
552}
553"
554 ),
555 "
556import mod.{Wibble}
557
558pub fn main() {
559 let value = mod.Wibble
560 Wibble
561}
562",
563 find_position_of("Wibble").nth_occurrence(3),
564 );
565}
566
567#[test]
568fn higlights_for_type_variant_from_unqualified_aliased_reference() {
569 assert_highlights!(
570 (
571 "mod",
572 "
573pub type Wibble { Wibble }
574
575fn wobble() {
576 Wibble
577}
578"
579 ),
580 "
581import mod.{Wibble as Wobble}
582
583pub fn main() {
584 let value = mod.Wibble
585 Wobble
586}
587",
588 find_position_of("Wobble").nth_occurrence(2),
589 );
590}
591
592#[test]
593fn no_higlights_for_keyword() {
594 assert_no_highlights!(
595 "
596pub fn wibble() {
597 todo
598}
599",
600 find_position_of("fn")
601 );
602}
603
604#[test]
605fn higlights_for_aliased_value() {
606 assert_highlights!(
607 (
608 "mod",
609 "
610pub type Wibble { Wibble }
611
612pub fn main() {
613 Wibble
614}
615"
616 ),
617 "
618import mod.{Wibble as Wobble}
619
620fn wobble() {
621 Wobble
622}
623",
624 find_position_of("Wobble").nth_occurrence(2),
625 );
626}
627
628#[test]
629fn higlights_for_private_type() {
630 assert_highlights!(
631 "
632type Wibble { Wibble }
633
634fn main() -> Wibble {
635 todo
636}
637
638fn wobble(w: Wibble) {
639 todo
640}
641",
642 find_position_of("Wibble"),
643 );
644}
645
646#[test]
647fn higlights_for_private_type_from_reference() {
648 assert_highlights!(
649 "
650type Wibble { Wibble }
651
652fn main() -> Wibble {
653 todo
654}
655
656fn wobble(w: Wibble) {
657 todo
658}
659",
660 find_position_of("-> Wibble").under_char('W'),
661 );
662}
663
664#[test]
665fn higlights_for_public_type() {
666 assert_highlights!(
667 (
668 "mod",
669 "
670pub type Wibble { Wibble }
671
672pub fn main() -> Wibble {
673 todo
674}
675"
676 ),
677 "
678import mod.{type Wibble}
679
680fn wobble() -> Wibble {
681 todo
682}
683
684fn other(w: mod.Wibble) {
685 todo
686}
687",
688 find_position_of("-> Wibble").under_char('W'),
689 );
690}
691
692#[test]
693fn higlights_for_type_from_qualified_reference() {
694 assert_highlights!(
695 (
696 "mod",
697 "
698pub type Wibble { Wibble }
699
700fn wobble() -> Wibble {
701 todo
702}
703"
704 ),
705 "
706import mod
707
708pub fn main() -> mod.Wibble {
709 let _: mod.Wibble = todo
710}
711",
712 find_position_of("Wibble"),
713 );
714}
715
716#[test]
717fn higlights_for_type_from_unqualified_reference() {
718 assert_highlights!(
719 (
720 "mod",
721 "
722pub type Wibble { Wibble }
723
724fn wobble() -> Wibble {
725 todo
726}
727"
728 ),
729 "
730import mod.{type Wibble}
731
732pub fn main() -> Wibble {
733 let _: mod.Wibble = todo
734}
735",
736 find_position_of("Wibble").nth_occurrence(2),
737 );
738}
739
740#[test]
741fn higlights_for_type_from_unqualified_aliased_reference() {
742 assert_highlights!(
743 (
744 "mod",
745 "
746pub type Wibble { Wibble }
747
748fn wobble() -> Wibble {
749 todo
750}
751"
752 ),
753 "
754import mod.{type Wibble as Wobble}
755
756pub fn main() -> Wobble {
757 let _: mod.Wibble = todo
758}
759",
760 find_position_of("Wobble").nth_occurrence(2),
761 );
762}
763
764#[test]
765fn higlights_for_aliased_type() {
766 assert_highlights!(
767 (
768 "mod",
769 "
770pub type Wibble { Wibble }
771
772pub fn main() -> Wibble {
773 todo
774}
775"
776 ),
777 "
778import mod.{type Wibble as Wobble}
779
780fn wobble() -> Wobble {
781 todo
782}
783
784fn other(w: mod.Wibble) {
785 todo
786}
787",
788 find_position_of("-> Wobble").under_char('W'),
789 );
790}
791
792#[test]
793fn higlights_for_type_from_let_annotation() {
794 assert_highlights!(
795 (
796 "mod",
797 "
798pub type Wibble { Wibble }
799
800fn wobble() -> Wibble {
801 todo
802}
803"
804 ),
805 "
806import mod.{type Wibble}
807
808pub fn main() -> Wibble {
809 let _: mod.Wibble = todo
810}
811",
812 find_position_of("mod.Wibble").under_char('W'),
813 );
814}
815
816#[test]
817fn higlights_for_prefix_string_suffix_variable_in_case() {
818 assert_highlights!(
819 "
820pub fn main() -> String {
821 let wibble = \"1-wibble\"
822 let rest = case wibble {
823 \"1\" <> rest -> rest
824 other -> other
825 }
826 rest
827}
828",
829 find_position_of("rest").nth_occurrence(2)
830 );
831}
832
833#[test]
834fn higlights_for_prefix_string_suffix_variable_in_case_triggered_from_usage() {
835 assert_highlights!(
836 "
837pub fn main() -> String {
838 let wibble = \"1-wibble\"
839 let rest = case wibble {
840 \"1\" <> rest -> rest
841 other -> other
842 }
843 rest
844}
845",
846 find_position_of("rest").nth_occurrence(3)
847 );
848}
849
850#[test]
851fn higlights_for_prefix_string_suffix_variable_with_alternative_definition_in_case() {
852 assert_highlights!(
853 "
854pub fn main() -> String {
855 let wibble = \"1-wibble\"
856 let rest = case wibble {
857 \"1\" <> rest | \"2\" <> rest -> rest
858 other -> other
859 }
860 rest
861}
862",
863 find_position_of("rest").nth_occurrence(2),
864 );
865}
866
867#[test]
868fn higlights_for_prefix_string_suffix_variable_with_alternative_definition_triggered_from_second_pattern()
869 {
870 assert_highlights!(
871 "
872pub fn main() -> String {
873 let wibble = \"1-wibble\"
874 let rest = case wibble {
875 \"1\" <> rest | \"2\" <> rest -> rest
876 other -> other
877 }
878 rest
879}
880",
881 find_position_of("rest").nth_occurrence(3),
882 );
883}
884
885#[test]
886fn higlights_for_prefix_string_suffix_variable_with_alternative_definition_triggered_from_usage() {
887 assert_highlights!(
888 "
889pub fn main() -> String {
890 let wibble = \"1-wibble\"
891 let rest = case wibble {
892 \"1\" <> rest | \"2\" <> rest -> rest
893 other -> other
894 }
895 rest
896}
897",
898 find_position_of("rest").nth_occurrence(4),
899 );
900}
901
902#[test]
903fn higlights_for_prefix_string_suffix_variable_in_let_assert() {
904 assert_highlights!(
905 "
906pub fn main() -> String {
907 let assert \"1\" <> rest = \"1-wibble\"
908 rest
909}
910",
911 find_position_of("rest").nth_occurrence(1),
912 );
913}
914
915#[test]
916fn higlights_for_prefix_string_suffix_variable_in_let_assert_triggered_from_usage() {
917 assert_highlights!(
918 "
919pub fn main() -> String {
920 let assert \"1\" <> rest = \"1-wibble\"
921 rest
922}
923",
924 find_position_of("rest").nth_occurrence(2),
925 );
926}
927
928#[test]
929fn higlights_for_prefix_string_alias_in_case() {
930 assert_highlights!(
931 "
932pub fn main() -> String {
933 let wibble = \"1-wibble\"
934 let digit = case wibble {
935 \"1\" as digit <> _rest -> digit
936 other -> other
937 }
938 digit
939}
940",
941 find_position_of("digit").nth_occurrence(2)
942 );
943}
944
945#[test]
946fn higlights_for_prefix_string_alias_in_case_triggered_from_usage() {
947 assert_highlights!(
948 "
949pub fn main() -> String {
950 let wibble = \"1-wibble\"
951 let digit = case wibble {
952 \"1\" as digit <> _rest -> digit
953 other -> other
954 }
955 digit
956}
957",
958 find_position_of("digit").nth_occurrence(3)
959 );
960}
961
962#[test]
963fn higlights_for_prefix_string_alias_with_alternative_definitions_in_case() {
964 assert_highlights!(
965 "
966pub fn main() -> String {
967 let wibble = \"1-wibble\"
968 let digit = case wibble {
969 \"1\" as digit <> _rest | \"2\" as digit <> _rest -> digit
970 other -> other
971 }
972 digit
973}
974",
975 find_position_of("digit").nth_occurrence(2)
976 );
977}
978
979#[test]
980fn higlights_for_prefix_string_alias_with_alternative_definitions_triggered_from_second_pattern() {
981 assert_highlights!(
982 "
983pub fn main() -> String {
984 let wibble = \"1-wibble\"
985 let digit = case wibble {
986 \"1\" as digit <> _rest | \"2\" as digit <> _rest -> digit
987 other -> other
988 }
989 digit
990}
991",
992 find_position_of("digit").nth_occurrence(3)
993 );
994}
995
996#[test]
997fn higlights_for_prefix_string_alias_with_alternative_definitions_triggered_from_usage() {
998 assert_highlights!(
999 "
1000pub fn main() -> String {
1001 let wibble = \"1-wibble\"
1002 let digit = case wibble {
1003 \"1\" as digit <> _rest | \"2\" as digit <> _rest -> digit
1004 other -> other
1005 }
1006 digit
1007}
1008",
1009 find_position_of("digit").nth_occurrence(4)
1010 );
1011}
1012
1013#[test]
1014fn higlights_for_prefix_string_alias_in_let_assert() {
1015 assert_highlights!(
1016 "
1017pub fn main() -> String {
1018 let assert \"1\" as digit <> _rest = \"1-wibble\"
1019 digit
1020}
1021",
1022 find_position_of("digit").nth_occurrence(1)
1023 );
1024}
1025
1026#[test]
1027fn higlights_for_prefix_string_alias_in_let_assert_triggered_from_usage() {
1028 assert_highlights!(
1029 "
1030pub fn main() -> String {
1031 let assert \"1\" as digit <> _rest = \"1-wibble\"
1032 digit
1033}
1034",
1035 find_position_of("digit").nth_occurrence(2)
1036 );
1037}
1038
1039#[test]
1040fn higlights_for_prefix_string_suffix_variable_nested_in_tuple() {
1041 assert_highlights!(
1042 "
1043fn main() {
1044 case #(\"1-wibble\", 0) {
1045 #(\"1\" <> rest, _) -> rest
1046 _ -> \"\"
1047 }
1048}
1049",
1050 find_position_of("rest").nth_occurrence(1)
1051 );
1052}
1053
1054#[test]
1055fn higlights_for_prefix_string_alias_used_in_guard() {
1056 assert_highlights!(
1057 "
1058fn main() {
1059 case \"1-wibble\" {
1060 \"1\" as digit <> _rest if digit == \"1\" -> digit
1061 _ -> \"\"
1062 }
1063}
1064",
1065 find_position_of("digit").nth_occurrence(1)
1066 );
1067}
1068
1069#[test]
1070fn higlights_for_prefix_string_suffix_used_in_guard() {
1071 assert_highlights!(
1072 "
1073fn main() {
1074 case \"1-wibble\" {
1075 \"1\" <> rest if rest == \"-wibble\" -> rest
1076 _ -> \"\"
1077 }
1078}
1079",
1080 find_position_of("rest").nth_occurrence(1)
1081 );
1082}
1083
1084#[test]
1085fn higlights_for_prefix_string_suffix_shadowing_outer_variable() {
1086 assert_highlights!(
1087 "
1088fn main() {
1089 let rest = \"outer\"
1090 case \"1-wibble\" {
1091 \"1\" <> rest -> rest
1092 _ -> rest
1093 }
1094}
1095",
1096 find_position_of("rest").nth_occurrence(2)
1097 );
1098}
1099
1100#[test]
1101fn higlights_for_prefix_string_alias_and_suffix_complex_guard() {
1102 assert_highlights!(
1103 "
1104fn main() {
1105 case \"1-wibble\" {
1106 \"1\" as digit <> rest if digit == \"1\" && rest == \"-wibble\" -> #(digit, rest)
1107 _ -> #(\"\", \"\")
1108 }
1109}
1110",
1111 find_position_of("digit").nth_occurrence(1)
1112 );
1113}
1114
1115#[test]
1116fn higlights_for_local_variable_from_guard() {
1117 assert_highlights!(
1118 "
1119pub fn main() {
1120 let wibble = True
1121 let wobble = False
1122 case wibble {
1123 True if wobble -> !wibble
1124 False if !wobble -> wibble
1125 _ -> wobble
1126 }
1127}
1128",
1129 find_position_of("wobble").nth_occurrence(2).under_char('o')
1130 );
1131}
1132
1133#[test]
1134fn higlights_for_module_select_from_guard() {
1135 assert_highlights!(
1136 ("mod", "pub const wibble = 10"),
1137 "
1138import mod
1139
1140pub fn main() {
1141 let wibble = True
1142 case wibble {
1143 True if mod.wibble < 5 -> !wibble
1144 False if mod.wibble != 10 -> wibble
1145 _ -> mod.wibble + 1
1146 }
1147}
1148",
1149 find_position_of("mod.wibble").under_char('w')
1150 );
1151}
1152
1153#[test]
1154fn highlights_for_record_field_ignored_by_record_update_spread() {
1155 assert_highlights!(
1156 "
1157type Wibble {
1158 Wibble(wibble: Int, wobble: Int)
1159}
1160
1161pub fn main(w: Wibble) {
1162 Wibble(..w, wibble: 2)
1163}
1164",
1165 find_position_of("wobble: Int").under_char('w'),
1166 );
1167}