Fork of daniellemaywood.uk/gleam — Wasm codegen work
29 kB
1725 lines
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2025 The Gleam contributors
3
4use std::collections::HashMap;
5
6use lsp_types::{
7 PartialResultParams, Position, Range, ReferenceContext, ReferenceParams,
8 TextDocumentPositionParams, WorkDoneProgressParams,
9};
10
11use super::{TestProject, find_position_of};
12
13fn find_references(
14 tester: &TestProject<'_>,
15 position: Position,
16) -> Option<HashMap<String, Vec<Range>>> {
17 let locations = tester.at(position, |engine, params, _| {
18 let params = ReferenceParams {
19 text_document_position_params: TextDocumentPositionParams {
20 text_document: params.text_document,
21 position,
22 },
23 work_done_progress_params: WorkDoneProgressParams::default(),
24 partial_result_params: PartialResultParams::default(),
25 context: ReferenceContext {
26 include_declaration: true,
27 },
28 };
29 engine.find_references(params).result.unwrap()
30 })?;
31 let mut references: HashMap<String, Vec<Range>> = HashMap::new();
32
33 for location in locations {
34 let module_name = tester
35 .module_name_from_url(&location.uri)
36 .expect("Valid uri");
37 _ = references
38 .entry(module_name)
39 .or_default()
40 .push(location.range);
41 }
42
43 Some(references)
44}
45
46fn show_references(code: &str, position: Option<Position>, ranges: &[Range]) -> String {
47 let mut buffer = String::new();
48
49 for (line_number, line) in code.lines().enumerate() {
50 let mut underline = String::new();
51 let mut underline_empty = true;
52 let line_number = line_number as u32;
53
54 for (column_number, _) in line.chars().enumerate() {
55 let current_position = Position::new(line_number, column_number as u32);
56
57 // Check if any range covers this specific character
58 let is_in_range = ranges
59 .iter()
60 .any(|range| range.start <= current_position && current_position < range.end);
61
62 if Some(current_position) == position {
63 underline_empty = false;
64 underline.push('↑');
65 } else if is_in_range {
66 underline_empty = false;
67 underline.push('▔');
68 } else {
69 underline.push(' ');
70 }
71 }
72
73 buffer.push_str(line);
74 if !underline_empty {
75 buffer.push('\n');
76 buffer.push_str(&underline);
77 }
78 buffer.push('\n');
79 }
80
81 buffer
82}
83
84macro_rules! assert_references {
85 ($code:literal, $position:expr $(,)?) => {
86 assert_references!(TestProject::for_source($code), $position);
87 };
88
89 (($module_name:literal, $module_src:literal), $code:literal, $position:expr $(,)?) => {
90 assert_references!(
91 TestProject::for_source($code).add_module($module_name, $module_src),
92 $position
93 );
94 };
95
96 ($project:expr, $position:expr $(,)?) => {
97 let project = $project;
98 let src = project.src;
99 let position = $position.find_position(src);
100 let result = find_references(&project, position).expect("References not found");
101
102 let mut output = String::new();
103 for (name, src) in project.root_package_modules.iter() {
104 output.push_str(&format!(
105 "-- {name}.gleam\n{}\n\n",
106 show_references(src, None, result.get(*name).unwrap_or(&Vec::new()))
107 ));
108 }
109 output.push_str(&format!(
110 "-- app.gleam\n{}",
111 show_references(
112 src,
113 Some(position),
114 result.get("app").unwrap_or(&Vec::new())
115 )
116 ));
117
118 insta::assert_snapshot!(insta::internals::AutoName, output, src);
119 };
120}
121
122macro_rules! assert_no_references {
123 ($code:literal, $position:expr $(,)?) => {
124 let project = TestProject::for_source($code);
125 assert_no_references!(&project, $position);
126 };
127
128 ($project:expr, $position:expr $(,)?) => {
129 let src = $project.src;
130 let position = $position.find_position(src);
131 let result = find_references($project, position);
132 assert_eq!(result, None);
133 };
134}
135
136#[test]
137fn references_for_local_variable() {
138 assert_references!(
139 "
140pub fn main() {
141 let wibble = 10
142 let wobble = wibble + 1
143 wibble + wobble
144}
145",
146 find_position_of("wibble").nth_occurrence(2),
147 );
148}
149
150#[test]
151fn references_for_local_variable_from_definition() {
152 assert_references!(
153 "
154pub fn main() {
155 let wibble = 10
156 let wobble = wibble + 1
157 wibble + wobble
158}
159",
160 find_position_of("wibble"),
161 );
162}
163
164#[test]
165fn references_for_private_function() {
166 assert_references!(
167 "
168fn wibble() {
169 wibble()
170}
171
172pub fn main() {
173 let _ = wibble()
174 wibble() + 4
175}
176
177fn wobble() {
178 wibble() || wobble()
179}
180",
181 find_position_of("wibble"),
182 );
183}
184
185#[test]
186fn references_for_private_function_from_reference() {
187 assert_references!(
188 "
189fn wibble() {
190 wibble()
191}
192
193pub fn main() {
194 let _ = wibble()
195 wibble() + 4
196}
197
198fn wobble() {
199 wibble() || wobble()
200}
201",
202 find_position_of("wibble").nth_occurrence(2),
203 );
204}
205
206#[test]
207fn references_for_public_function() {
208 assert_references!(
209 (
210 "mod",
211 "
212import app.{wibble}
213
214fn wobble() {
215 app.wibble()
216}
217
218fn other() {
219 wibble()
220}
221"
222 ),
223 "
224pub fn wibble() {
225 wibble()
226}
227",
228 find_position_of("wibble").nth_occurrence(2),
229 );
230}
231
232#[test]
233fn references_for_function_from_qualified_reference() {
234 assert_references!(
235 (
236 "mod",
237 "
238pub fn wibble() {
239 wibble()
240}
241"
242 ),
243 "
244import mod
245
246pub fn main() {
247 let value = mod.wibble()
248 mod.wibble()
249 value
250}
251",
252 find_position_of("wibble"),
253 );
254}
255
256#[test]
257fn references_for_function_from_unqualified_reference() {
258 assert_references!(
259 (
260 "mod",
261 "
262pub fn wibble() {
263 wibble()
264}
265"
266 ),
267 "
268import mod.{wibble}
269
270pub fn main() {
271 let value = wibble()
272 mod.wibble()
273 value
274}
275",
276 find_position_of("wibble()"),
277 );
278}
279
280#[test]
281fn references_for_function_from_unqualified_aliased_reference() {
282 assert_references!(
283 (
284 "mod",
285 "
286pub fn wibble() {
287 wibble()
288}
289"
290 ),
291 "
292import mod.{wibble as wobble}
293
294pub fn main() {
295 let value = wobble()
296 mod.wibble()
297 value
298}
299",
300 find_position_of("wobble()"),
301 );
302}
303
304#[test]
305fn references_for_function_from_import() {
306 assert_references!(
307 (
308 "mod",
309 "
310pub fn wibble() {
311 wibble()
312}
313"
314 ),
315 "
316import mod.{wibble}
317
318pub fn main() {
319 let value = wibble()
320 mod.wibble()
321 value
322}
323",
324 find_position_of("wibble"),
325 );
326}
327
328#[test]
329fn references_for_function_from_import_alias() {
330 assert_references!(
331 (
332 "mod",
333 "
334pub fn wibble() {
335 wibble()
336}
337"
338 ),
339 "
340import mod.{wibble as wobble}
341
342pub fn main() {
343 let value = wobble()
344 mod.wibble()
345 value
346}
347",
348 find_position_of("wobble"),
349 );
350}
351
352#[test]
353fn references_for_private_constant() {
354 assert_references!(
355 "
356const wibble = 10
357
358pub fn main() {
359 let _ = wibble
360 wibble + 4
361}
362
363fn wobble() {
364 wibble + wobble()
365}
366",
367 find_position_of("wibble"),
368 );
369}
370
371#[test]
372fn references_for_private_constant_from_reference() {
373 assert_references!(
374 "
375const wibble = 10
376
377pub fn main() {
378 let _ = wibble
379 wibble + 4
380}
381
382fn wobble() {
383 wibble + wobble()
384}
385",
386 find_position_of("wibble").nth_occurrence(2),
387 );
388}
389
390#[test]
391fn references_for_public_constant() {
392 assert_references!(
393 (
394 "mod",
395 "
396import app.{wibble}
397
398fn wobble() {
399 app.wibble
400}
401
402fn other() {
403 wibble
404}
405"
406 ),
407 "
408pub const wibble = 10
409
410pub fn main() {
411 wibble
412}
413",
414 find_position_of("wibble").nth_occurrence(2),
415 );
416}
417
418#[test]
419fn references_for_constant_from_qualified_reference() {
420 assert_references!(
421 (
422 "mod",
423 "
424pub const wibble = 10
425
426fn wobble() {
427 wibble
428}
429"
430 ),
431 "
432import mod
433
434pub fn main() {
435 let value = mod.wibble
436 mod.wibble + value
437}
438",
439 find_position_of("wibble"),
440 );
441}
442
443#[test]
444fn references_for_constant_from_unqualified_reference() {
445 assert_references!(
446 (
447 "mod",
448 "
449pub const wibble = 10
450
451fn wobble() {
452 wibble
453}
454"
455 ),
456 "
457import mod.{wibble}
458
459pub fn main() {
460 let value = mod.wibble
461 wibble + value
462}
463",
464 find_position_of("wibble +"),
465 );
466}
467
468#[test]
469fn references_for_constant_from_unqualified_aliased_referene() {
470 assert_references!(
471 (
472 "mod",
473 "
474pub const wibble = 10
475
476fn wobble() {
477 wibble
478}
479"
480 ),
481 "
482import mod.{wibble as wobble}
483
484pub fn main() {
485 let value = mod.wibble
486 wobble + value
487}
488",
489 find_position_of("wobble +"),
490 );
491}
492
493#[test]
494fn references_for_constant_from_import() {
495 assert_references!(
496 (
497 "mod",
498 "
499pub const wibble = 10
500
501fn wobble() {
502 wibble
503}
504"
505 ),
506 "
507import mod.{wibble}
508
509pub fn main() {
510 let value = mod.wibble
511 wibble + value
512}
513",
514 find_position_of("wibble"),
515 );
516}
517
518#[test]
519fn references_for_constant_from_import_alias() {
520 assert_references!(
521 (
522 "mod",
523 "
524pub const wibble = 10
525
526fn wobble() {
527 wibble
528}
529"
530 ),
531 "
532import mod.{wibble as wobble}
533
534pub fn main() {
535 let value = mod.wibble
536 wobble + value
537}
538",
539 find_position_of("wobble"),
540 );
541}
542
543#[test]
544fn references_for_private_type_variant() {
545 assert_references!(
546 "
547type Wibble { Wibble }
548
549fn main() {
550 let _ = Wibble
551 Wibble
552}
553
554fn wobble() {
555 Wibble
556 wobble()
557}
558",
559 find_position_of("Wibble }"),
560 );
561}
562
563#[test]
564fn references_for_private_type_variant_from_reference() {
565 assert_references!(
566 "
567type Wibble { Wibble }
568
569fn main() {
570 let _ = Wibble
571 Wibble
572}
573
574fn wobble() {
575 Wibble
576 wobble()
577}
578",
579 find_position_of(" = Wibble").under_char('W'),
580 );
581}
582
583#[test]
584fn references_for_public_type_variant() {
585 assert_references!(
586 (
587 "mod",
588 "
589import app.{Wibble}
590
591fn wobble() {
592 app.Wibble
593}
594
595fn other() {
596 Wibble
597}
598"
599 ),
600 "
601pub type Wibble { Wibble }
602
603pub fn main() {
604 Wibble
605}
606",
607 find_position_of("Wibble }"),
608 );
609}
610
611#[test]
612fn references_for_type_variant_from_qualified_reference() {
613 assert_references!(
614 (
615 "mod",
616 "
617pub type Wibble { Wibble }
618
619fn wobble() {
620 Wibble
621}
622"
623 ),
624 "
625import mod
626
627pub fn main() {
628 let value = mod.Wibble
629 mod.Wibble
630 value
631}
632",
633 find_position_of("Wibble"),
634 );
635}
636
637#[test]
638fn references_for_type_variant_from_unqualified_reference() {
639 assert_references!(
640 (
641 "mod",
642 "
643pub type Wibble { Wibble }
644
645fn wobble() {
646 Wibble
647}
648"
649 ),
650 "
651import mod.{Wibble}
652
653pub fn main() {
654 let value = mod.Wibble
655 Wibble
656}
657",
658 find_position_of("Wibble").nth_occurrence(3),
659 );
660}
661
662#[test]
663fn references_for_type_variant_from_unqualified_aliased_reference() {
664 assert_references!(
665 (
666 "mod",
667 "
668pub type Wibble { Wibble }
669
670fn wobble() {
671 Wibble
672}
673"
674 ),
675 "
676import mod.{Wibble as Wobble}
677
678pub fn main() {
679 let value = mod.Wibble
680 Wobble
681}
682",
683 find_position_of("Wobble").nth_occurrence(2),
684 );
685}
686
687#[test]
688fn references_for_type_variant_from_import() {
689 assert_references!(
690 (
691 "mod",
692 "
693pub type Wibble { Wibble }
694
695fn wobble() {
696 Wibble
697}
698"
699 ),
700 "
701import mod.{Wibble}
702
703pub fn main() {
704 let value = mod.Wibble
705 Wibble
706}
707",
708 find_position_of("Wibble"),
709 );
710}
711
712#[test]
713fn references_for_type_variant_from_import_alias() {
714 assert_references!(
715 (
716 "mod",
717 "
718pub type Wibble { Wibble }
719
720fn wobble() {
721 Wibble
722}
723"
724 ),
725 "
726import mod.{Wibble as Wobble}
727
728pub fn main() {
729 let value = mod.Wibble
730 Wobble
731}
732",
733 find_position_of("Wobble"),
734 );
735}
736
737#[test]
738fn no_references_for_keyword() {
739 assert_no_references!(
740 "
741pub fn wibble() {
742 todo
743}
744",
745 find_position_of("fn")
746 );
747}
748
749#[test]
750fn references_for_aliased_value() {
751 assert_references!(
752 (
753 "mod",
754 "
755import app.{Wibble as Wobble}
756
757fn wobble() {
758 Wobble
759}
760"
761 ),
762 "
763pub type Wibble { Wibble }
764
765pub fn main() {
766 Wibble
767}
768",
769 find_position_of("Wibble").nth_occurrence(2),
770 );
771}
772
773#[test]
774fn references_for_aliased_const() {
775 assert_references!(
776 (
777 "mod",
778 "
779import app.{wibble as other}
780
781fn wobble() {
782 other
783}
784"
785 ),
786 "
787pub const wibble = 123
788
789pub fn main() {
790 wibble
791}
792",
793 find_position_of("wibble").nth_occurrence(2),
794 );
795}
796
797#[test]
798fn references_for_aliased_function() {
799 assert_references!(
800 (
801 "mod",
802 "
803import app.{wibble as other}
804
805fn wobble() {
806 other()
807}
808"
809 ),
810 "
811pub fn wibble() {
812 123
813}
814
815pub fn main() {
816 wibble()
817}
818",
819 find_position_of("wibble").nth_occurrence(2),
820 );
821}
822
823#[test]
824fn references_for_private_type() {
825 assert_references!(
826 "
827type Wibble { Wibble }
828
829fn main() -> Wibble {
830 todo
831}
832
833fn wobble(w: Wibble) {
834 todo
835}
836",
837 find_position_of("Wibble"),
838 );
839}
840
841#[test]
842fn references_for_private_type_from_reference() {
843 assert_references!(
844 "
845type Wibble { Wibble }
846
847fn main() -> Wibble {
848 todo
849}
850
851fn wobble(w: Wibble) {
852 todo
853}
854",
855 find_position_of("-> Wibble").under_char('W'),
856 );
857}
858
859#[test]
860fn references_for_public_type() {
861 assert_references!(
862 (
863 "mod",
864 "
865import app.{type Wibble}
866
867fn wobble() -> Wibble {
868 todo
869}
870
871fn other(w: app.Wibble) {
872 todo
873}
874"
875 ),
876 "
877pub type Wibble { Wibble }
878
879pub fn main() -> Wibble {
880 todo
881}
882",
883 find_position_of("Wibble"),
884 );
885}
886
887#[test]
888fn references_for_type_from_qualified_reference() {
889 assert_references!(
890 (
891 "mod",
892 "
893pub type Wibble { Wibble }
894
895fn wobble() -> Wibble {
896 todo
897}
898"
899 ),
900 "
901import mod
902
903pub fn main() -> mod.Wibble {
904 let _: mod.Wibble = todo
905}
906",
907 find_position_of("Wibble"),
908 );
909}
910
911#[test]
912fn references_for_type_from_unqualified_reference() {
913 assert_references!(
914 (
915 "mod",
916 "
917pub type Wibble { Wibble }
918
919fn wobble() -> Wibble {
920 todo
921}
922"
923 ),
924 "
925import mod.{type Wibble}
926
927pub fn main() -> Wibble {
928 let _: mod.Wibble = todo
929}
930",
931 find_position_of("Wibble").nth_occurrence(2),
932 );
933}
934
935#[test]
936fn references_for_type_from_unqualified_aliased_reference() {
937 assert_references!(
938 (
939 "mod",
940 "
941pub type Wibble { Wibble }
942
943fn wobble() -> Wibble {
944 todo
945}
946"
947 ),
948 "
949import mod.{type Wibble as Wobble}
950
951pub fn main() -> Wobble {
952 let _: mod.Wibble = todo
953}
954",
955 find_position_of("-> Wobble").under_char('W'),
956 );
957}
958
959#[test]
960fn references_for_type_from_import() {
961 assert_references!(
962 (
963 "mod",
964 "
965pub type Wibble { Wibble }
966
967fn wobble() -> Wibble {
968 todo
969}
970"
971 ),
972 "
973import mod.{type Wibble}
974
975pub fn main() -> Wibble {
976 let _: mod.Wibble = todo
977}
978",
979 find_position_of("Wibble"),
980 );
981}
982
983#[test]
984fn references_for_type_from_import_alias() {
985 assert_references!(
986 (
987 "mod",
988 "
989pub type Wibble { Wibble }
990
991fn wobble() -> Wibble {
992 todo
993}
994"
995 ),
996 "
997import mod.{type Wibble as Wobble}
998
999pub fn main() -> Wobble {
1000 let _: mod.Wibble = todo
1001}
1002",
1003 find_position_of("Wobble"),
1004 );
1005}
1006
1007#[test]
1008fn references_for_aliased_type() {
1009 assert_references!(
1010 (
1011 "mod",
1012 "
1013import app.{type Wibble as Wobble}
1014
1015fn wobble() -> Wobble {
1016 todo
1017}
1018
1019fn other(w: app.Wibble) {
1020 todo
1021}
1022"
1023 ),
1024 "
1025pub type Wibble { Wibble }
1026
1027pub fn main() -> Wibble {
1028 todo
1029}
1030",
1031 find_position_of("-> Wibble").under_char('W'),
1032 );
1033}
1034
1035#[test]
1036fn references_for_type_from_let_annotation() {
1037 assert_references!(
1038 (
1039 "mod",
1040 "
1041pub type Wibble { Wibble }
1042
1043fn wobble() -> Wibble {
1044 todo
1045}
1046"
1047 ),
1048 "
1049import mod.{type Wibble}
1050
1051pub fn main() -> Wibble {
1052 let _: mod.Wibble = todo
1053}
1054",
1055 find_position_of("mod.Wibble").under_char('W'),
1056 );
1057}
1058
1059#[test]
1060fn references_for_prefix_string_suffix_variable_in_case() {
1061 assert_references!(
1062 "
1063pub fn main() -> String {
1064 let wibble = \"1-wibble\"
1065 let rest = case wibble {
1066 \"1\" <> rest -> rest
1067 other -> other
1068 }
1069 rest
1070}
1071",
1072 find_position_of("rest").nth_occurrence(2)
1073 );
1074}
1075
1076#[test]
1077fn references_for_prefix_string_suffix_variable_in_case_triggered_from_usage() {
1078 assert_references!(
1079 "
1080pub fn main() -> String {
1081 let wibble = \"1-wibble\"
1082 let rest = case wibble {
1083 \"1\" <> rest -> rest
1084 other -> other
1085 }
1086 rest
1087}
1088",
1089 find_position_of("rest").nth_occurrence(3)
1090 );
1091}
1092
1093#[test]
1094fn references_for_prefix_string_suffix_variable_with_alternative_definition_in_case() {
1095 assert_references!(
1096 "
1097pub fn main() -> String {
1098 let wibble = \"1-wibble\"
1099 let rest = case wibble {
1100 \"1\" <> rest | \"2\" <> rest -> rest
1101 other -> other
1102 }
1103 rest
1104}
1105",
1106 find_position_of("rest").nth_occurrence(2),
1107 );
1108}
1109
1110#[test]
1111fn references_for_prefix_string_suffix_variable_with_alternative_definition_triggered_from_second_pattern()
1112 {
1113 assert_references!(
1114 "
1115pub fn main() -> String {
1116 let wibble = \"1-wibble\"
1117 let rest = case wibble {
1118 \"1\" <> rest | \"2\" <> rest -> rest
1119 other -> other
1120 }
1121 rest
1122}
1123",
1124 find_position_of("rest").nth_occurrence(3),
1125 );
1126}
1127
1128#[test]
1129fn references_for_prefix_string_suffix_variable_with_alternative_definition_triggered_from_usage() {
1130 assert_references!(
1131 "
1132pub fn main() -> String {
1133 let wibble = \"1-wibble\"
1134 let rest = case wibble {
1135 \"1\" <> rest | \"2\" <> rest -> rest
1136 other -> other
1137 }
1138 rest
1139}
1140",
1141 find_position_of("rest").nth_occurrence(4),
1142 );
1143}
1144
1145#[test]
1146fn references_for_prefix_string_suffix_variable_in_let_assert() {
1147 assert_references!(
1148 "
1149pub fn main() -> String {
1150 let assert \"1\" <> rest = \"1-wibble\"
1151 rest
1152}
1153",
1154 find_position_of("rest").nth_occurrence(1),
1155 );
1156}
1157
1158#[test]
1159fn references_for_prefix_string_suffix_variable_in_let_assert_triggered_from_usage() {
1160 assert_references!(
1161 "
1162pub fn main() -> String {
1163 let assert \"1\" <> rest = \"1-wibble\"
1164 rest
1165}
1166",
1167 find_position_of("rest").nth_occurrence(2),
1168 );
1169}
1170
1171#[test]
1172fn references_for_prefix_string_alias_in_case() {
1173 assert_references!(
1174 "
1175pub fn main() -> String {
1176 let wibble = \"1-wibble\"
1177 let digit = case wibble {
1178 \"1\" as digit <> _rest -> digit
1179 other -> other
1180 }
1181 digit
1182}
1183",
1184 find_position_of("digit").nth_occurrence(2)
1185 );
1186}
1187
1188#[test]
1189fn references_for_prefix_string_alias_in_case_triggered_from_usage() {
1190 assert_references!(
1191 "
1192pub fn main() -> String {
1193 let wibble = \"1-wibble\"
1194 let digit = case wibble {
1195 \"1\" as digit <> _rest -> digit
1196 other -> other
1197 }
1198 digit
1199}
1200",
1201 find_position_of("digit").nth_occurrence(3)
1202 );
1203}
1204
1205#[test]
1206fn references_for_prefix_string_alias_with_alternative_definitions_in_case() {
1207 assert_references!(
1208 "
1209pub fn main() -> String {
1210 let wibble = \"1-wibble\"
1211 let digit = case wibble {
1212 \"1\" as digit <> _rest | \"2\" as digit <> _rest -> digit
1213 other -> other
1214 }
1215 digit
1216}
1217",
1218 find_position_of("digit").nth_occurrence(2)
1219 );
1220}
1221
1222#[test]
1223fn references_for_prefix_string_alias_with_alternative_definitions_triggered_from_second_pattern() {
1224 assert_references!(
1225 "
1226pub fn main() -> String {
1227 let wibble = \"1-wibble\"
1228 let digit = case wibble {
1229 \"1\" as digit <> _rest | \"2\" as digit <> _rest -> digit
1230 other -> other
1231 }
1232 digit
1233}
1234",
1235 find_position_of("digit").nth_occurrence(3)
1236 );
1237}
1238
1239#[test]
1240fn references_for_prefix_string_alias_with_alternative_definitions_triggered_from_usage() {
1241 assert_references!(
1242 "
1243pub fn main() -> String {
1244 let wibble = \"1-wibble\"
1245 let digit = case wibble {
1246 \"1\" as digit <> _rest | \"2\" as digit <> _rest -> digit
1247 other -> other
1248 }
1249 digit
1250}
1251",
1252 find_position_of("digit").nth_occurrence(4)
1253 );
1254}
1255
1256#[test]
1257fn references_for_prefix_string_alias_in_let_assert() {
1258 assert_references!(
1259 "
1260pub fn main() -> String {
1261 let assert \"1\" as digit <> _rest = \"1-wibble\"
1262 digit
1263}
1264",
1265 find_position_of("digit").nth_occurrence(1)
1266 );
1267}
1268
1269#[test]
1270fn references_for_prefix_string_alias_in_let_assert_triggered_from_usage() {
1271 assert_references!(
1272 "
1273pub fn main() -> String {
1274 let assert \"1\" as digit <> _rest = \"1-wibble\"
1275 digit
1276}
1277",
1278 find_position_of("digit").nth_occurrence(2)
1279 );
1280}
1281
1282#[test]
1283fn references_for_prefix_string_suffix_variable_nested_in_tuple() {
1284 assert_references!(
1285 "
1286fn main() {
1287 case #(\"1-wibble\", 0) {
1288 #(\"1\" <> rest, _) -> rest
1289 _ -> \"\"
1290 }
1291}
1292",
1293 find_position_of("rest").nth_occurrence(1)
1294 );
1295}
1296
1297#[test]
1298fn references_for_prefix_string_alias_used_in_guard() {
1299 assert_references!(
1300 "
1301fn main() {
1302 case \"1-wibble\" {
1303 \"1\" as digit <> _rest if digit == \"1\" -> digit
1304 _ -> \"\"
1305 }
1306}
1307",
1308 find_position_of("digit").nth_occurrence(1)
1309 );
1310}
1311
1312#[test]
1313fn references_for_prefix_string_suffix_used_in_guard() {
1314 assert_references!(
1315 "
1316fn main() {
1317 case \"1-wibble\" {
1318 \"1\" <> rest if rest == \"-wibble\" -> rest
1319 _ -> \"\"
1320 }
1321}
1322",
1323 find_position_of("rest").nth_occurrence(1)
1324 );
1325}
1326
1327#[test]
1328fn references_for_prefix_string_suffix_shadowing_outer_variable() {
1329 assert_references!(
1330 "
1331fn main() {
1332 let rest = \"outer\"
1333 case \"1-wibble\" {
1334 \"1\" <> rest -> rest
1335 _ -> rest
1336 }
1337}
1338",
1339 find_position_of("rest").nth_occurrence(2)
1340 );
1341}
1342
1343#[test]
1344fn references_for_prefix_string_alias_and_suffix_complex_guard() {
1345 assert_references!(
1346 "
1347fn main() {
1348 case \"1-wibble\" {
1349 \"1\" as digit <> rest if digit == \"1\" && rest == \"-wibble\" -> #(digit, rest)
1350 _ -> #(\"\", \"\")
1351 }
1352}
1353",
1354 find_position_of("digit").nth_occurrence(1)
1355 );
1356}
1357
1358#[test]
1359fn references_for_local_variable_from_guard() {
1360 assert_references!(
1361 "
1362pub fn main() {
1363 let wibble = True
1364 let wobble = False
1365 case wibble {
1366 True if wobble -> !wibble
1367 False if !wobble -> wibble
1368 _ -> wobble
1369 }
1370}
1371",
1372 find_position_of("wobble").nth_occurrence(2).under_char('o')
1373 );
1374}
1375
1376#[test]
1377fn references_for_module_select_from_guard() {
1378 assert_references!(
1379 ("mod", "pub const wibble = 10"),
1380 "
1381import mod
1382
1383pub fn main() {
1384 let wibble = True
1385 case wibble {
1386 True if mod.wibble < 5 -> !wibble
1387 False if mod.wibble != 10 -> wibble
1388 _ -> mod.wibble + 1
1389 }
1390}
1391",
1392 find_position_of("mod.wibble").under_char('w')
1393 );
1394}
1395
1396#[test]
1397fn references_for_invalid_constant_todo_message_still_works() {
1398 assert_references!(
1399 "
1400const wibble = 1
1401const wobble = todo as wibble
1402",
1403 find_position_of("wibble")
1404 );
1405}
1406
1407#[test]
1408fn references_for_invalid_constant_todo_message_still_works_2() {
1409 assert_references!(
1410 "
1411const wibble = 1
1412const wobble = todo as [wibble]
1413",
1414 find_position_of("wibble")
1415 );
1416}
1417
1418#[test]
1419fn references_for_record_field() {
1420 assert_references!(
1421 "
1422type Wibble {
1423 Wibble(wibble: Int)
1424}
1425
1426pub fn main() {
1427 let value = Wibble(wibble: 1)
1428 value.wibble
1429}
1430",
1431 find_position_of("value.wibble").under_char('i')
1432 );
1433}
1434
1435#[test]
1436fn references_for_record_field_in_module_not_importing_the_type_module() {
1437 assert_references!(
1438 TestProject::for_source(
1439 "
1440import wobble
1441
1442pub fn main() {
1443 wobble.make().wibble
1444}
1445"
1446 )
1447 .add_module("wibble", "pub type Wibble {\n Wibble(wibble: Int)\n}")
1448 .add_module(
1449 "wobble",
1450 "import wibble\n\npub fn make() -> wibble.Wibble {\n wibble.Wibble(wibble: 1)\n}"
1451 ),
1452 find_position_of("().wibble").under_char('b')
1453 );
1454}
1455
1456#[test]
1457fn references_for_record_field_ignored_by_record_update_spread() {
1458 // https://github.com/gleam-lang/gleam/pull/5533#pullrequestreview-4475156690
1459 assert_references!(
1460 "
1461type Wibble {
1462 Wibble(wibble: Int, wobble: Int)
1463}
1464
1465pub fn main(w: Wibble) {
1466 Wibble(..w, wibble: 2)
1467}
1468",
1469 find_position_of("wobble: Int").under_char('w')
1470 );
1471}
1472
1473#[test]
1474fn references_for_record_field_ignored_by_constant_record_update_spread() {
1475 assert_references!(
1476 "
1477type Wibble {
1478 Wibble(wibble: Int, wobble: Int)
1479}
1480
1481const base = Wibble(wibble: 1, wobble: 2)
1482
1483const updated = Wibble(..base, wibble: 3)
1484",
1485 find_position_of("wobble: Int").under_char('w')
1486 );
1487}
1488
1489#[test]
1490fn references_for_record_field_ignored_by_record_update_with_record_access_spread() {
1491 assert_references!(
1492 "
1493type Container {
1494 Container(inner: Wibble)
1495}
1496
1497type Wibble {
1498 Wibble(wibble: Int, wobble: Int)
1499}
1500
1501pub fn main(c: Container) {
1502 Wibble(..c.inner, wibble: 2)
1503}
1504",
1505 find_position_of("wobble: Int").under_char('w')
1506 );
1507}
1508
1509#[test]
1510fn references_for_record_field_ignored_by_nested_record_update_spread() {
1511 assert_references!(
1512 "
1513type Wibble {
1514 Wibble(wibble: Int, wobble: Int)
1515}
1516
1517pub fn main(w: Wibble) {
1518 Wibble(..Wibble(..w, wibble: 1), wobble: 2)
1519}
1520",
1521 find_position_of("wibble: Int").under_char('w')
1522 );
1523}
1524
1525#[test]
1526fn references_for_record_field_ignored_by_pipe_into_constructor() {
1527 assert_references!(
1528 "
1529type Wibble {
1530 Wibble(name: Int, age: Int)
1531}
1532
1533pub fn main() {
1534 1 |> Wibble(age: 2)
1535}
1536",
1537 find_position_of("name: Int").under_char('n')
1538 );
1539}
1540
1541#[test]
1542fn references_for_record_field_ignored_by_pattern_spread() {
1543 assert_references!(
1544 "
1545type Wibble {
1546 Wibble(wibble: Int, wobble: Int)
1547}
1548
1549pub fn main(w: Wibble) {
1550 case w {
1551 Wibble(wibble: a, ..) -> a
1552 }
1553}
1554",
1555 find_position_of("wobble: Int").under_char('w')
1556 );
1557}
1558
1559#[test]
1560fn references_for_value_from_import_imported_name() {
1561 assert_references!(
1562 (
1563 "mod",
1564 "
1565pub fn wibble() {
1566 wibble()
1567}
1568"
1569 ),
1570 "
1571import mod.{wibble as wobble}
1572
1573pub fn main() {
1574 let value = wobble()
1575 mod.wibble()
1576 value
1577}
1578",
1579 find_position_of("wibble"),
1580 );
1581}
1582
1583#[test]
1584fn references_for_value_from_import_as() {
1585 assert_references!(
1586 (
1587 "mod",
1588 "
1589pub fn wibble() {
1590 wibble()
1591}
1592"
1593 ),
1594 "
1595import mod.{wibble as wobble}
1596
1597pub fn main() {
1598 let value = wobble()
1599 mod.wibble()
1600 value
1601}
1602",
1603 find_position_of("as"),
1604 );
1605}
1606
1607#[test]
1608fn references_for_value_from_import_alias_name() {
1609 assert_references!(
1610 (
1611 "mod",
1612 "
1613pub fn wibble() {
1614 wibble()
1615}
1616"
1617 ),
1618 "
1619import mod.{wibble as wobble}
1620
1621pub fn main() {
1622 let value = wobble()
1623 mod.wibble()
1624 value
1625}
1626",
1627 find_position_of("wobble"),
1628 );
1629}
1630
1631#[test]
1632fn references_for_type_from_import_type() {
1633 assert_references!(
1634 (
1635 "mod",
1636 "
1637pub type Wibble { Wibble }
1638
1639fn wobble() -> Wibble {
1640 todo
1641}
1642"
1643 ),
1644 "
1645import mod.{type Wibble as Wobble}
1646
1647pub fn main() -> Wobble {
1648 let _: mod.Wibble = todo
1649}
1650",
1651 find_position_of("type"),
1652 );
1653}
1654
1655#[test]
1656fn references_for_type_from_import_imported_name() {
1657 assert_references!(
1658 (
1659 "mod",
1660 "
1661pub type Wibble { Wibble }
1662
1663fn wobble() -> Wibble {
1664 todo
1665}
1666"
1667 ),
1668 "
1669import mod.{type Wibble as Wobble}
1670
1671pub fn main() -> Wobble {
1672 let _: mod.Wibble = todo
1673}
1674",
1675 find_position_of("Wibble"),
1676 );
1677}
1678
1679#[test]
1680fn references_for_type_from_import_as() {
1681 assert_references!(
1682 (
1683 "mod",
1684 "
1685pub type Wibble { Wibble }
1686
1687fn wobble() -> Wibble {
1688 todo
1689}
1690"
1691 ),
1692 "
1693import mod.{type Wibble as Wobble}
1694
1695pub fn main() -> Wobble {
1696 let _: mod.Wibble = todo
1697}
1698",
1699 find_position_of("as"),
1700 );
1701}
1702
1703#[test]
1704fn references_for_type_from_import_clias_name() {
1705 assert_references!(
1706 (
1707 "mod",
1708 "
1709pub type Wibble { Wibble }
1710
1711fn wobble() -> Wibble {
1712 todo
1713}
1714"
1715 ),
1716 "
1717import mod.{type Wibble as Wobble}
1718
1719pub fn main() -> Wobble {
1720 let _: mod.Wibble = todo
1721}
1722",
1723 find_position_of("Wobble"),
1724 );
1725}