1use hexpm::version::Version;
2use rand::Rng;
3use type_::{AccessorsMap, FieldMap, RecordAccessor};
4
5use super::*;
6use crate::{
7 ast::{
8 BitArrayOption, BitArraySegment, CallArg, Constant, Publicity, SrcSpan, TypedConstant,
9 TypedConstantBitArraySegmentOption,
10 },
11 build::Origin,
12 line_numbers::LineNumbers,
13 reference::{Reference, ReferenceKind},
14 type_::{
15 self, Deprecation, ModuleInterface, Opaque, References, Type, TypeAliasConstructor,
16 TypeConstructor, TypeValueConstructor, TypeValueConstructorField, TypeVariantConstructors,
17 ValueConstructor, ValueConstructorVariant,
18 expression::{Implementations, Purity},
19 prelude,
20 },
21 uid::UniqueIdGenerator,
22};
23use std::{collections::HashMap, io::BufReader, sync::Arc};
24
25use pretty_assertions::assert_eq;
26
27fn roundtrip(input: &ModuleInterface) -> ModuleInterface {
28 let buffer = ModuleEncoder::new(input).encode().unwrap();
29 let ids = UniqueIdGenerator::new();
30 ModuleDecoder::new(ids)
31 .read(BufReader::new(buffer.as_slice()))
32 .unwrap()
33}
34
35fn constant_module(constant: TypedConstant) -> ModuleInterface {
36 ModuleInterface {
37 warnings: vec![],
38 is_internal: true,
39 package: "some_package".into(),
40 origin: Origin::Src,
41 name: "a".into(),
42 types: HashMap::new(),
43 types_value_constructors: HashMap::new(),
44 accessors: HashMap::new(),
45 values: [(
46 "one".into(),
47 ValueConstructor {
48 publicity: Publicity::Public,
49 deprecation: Deprecation::NotDeprecated,
50 type_: type_::int(),
51 variant: ValueConstructorVariant::ModuleConstant {
52 documentation: Some("Some documentation".into()),
53 literal: constant,
54 location: SrcSpan::default(),
55 module: "one/two".into(),
56 implementations: Implementations {
57 gleam: true,
58 uses_erlang_externals: false,
59 uses_javascript_externals: false,
60 can_run_on_erlang: true,
61 can_run_on_javascript: true,
62 },
63 name: "one".into(),
64 },
65 },
66 )]
67 .into(),
68 line_numbers: LineNumbers::new(""),
69 src_path: "some_path".into(),
70 minimum_required_version: Version::new(0, 1, 0),
71 type_aliases: HashMap::new(),
72 documentation: Vec::new(),
73 contains_echo: false,
74
75 references: References::default(),
76 }
77}
78
79fn bit_array_segment_option_module(option: TypedConstantBitArraySegmentOption) -> ModuleInterface {
80 constant_module(Constant::BitArray {
81 location: Default::default(),
82 segments: vec![BitArraySegment {
83 location: Default::default(),
84 value: Box::new(Constant::Int {
85 location: Default::default(),
86 value: "1".into(),
87 int_value: 1.into(),
88 }),
89 options: vec![option],
90 type_: type_::int(),
91 }],
92 })
93}
94
95#[test]
96fn empty_module() {
97 let module = ModuleInterface {
98 warnings: vec![],
99 is_internal: true,
100 package: "some_package".into(),
101 origin: Origin::Src,
102 name: "one/two".into(),
103 types: HashMap::new(),
104 types_value_constructors: HashMap::new(),
105 values: HashMap::new(),
106 accessors: HashMap::new(),
107 line_numbers: LineNumbers::new(""),
108 src_path: "some_path".into(),
109 minimum_required_version: Version::new(0, 1, 0),
110 type_aliases: HashMap::new(),
111 documentation: Vec::new(),
112 contains_echo: false,
113
114 references: References::default(),
115 };
116 assert_eq!(roundtrip(&module), module);
117}
118
119#[test]
120fn with_line_numbers() {
121 let module = ModuleInterface {
122 warnings: vec![],
123 is_internal: false,
124 package: "some_package".into(),
125 origin: Origin::Src,
126 name: "one/two".into(),
127 types: HashMap::new(),
128 types_value_constructors: HashMap::new(),
129 values: HashMap::new(),
130 accessors: HashMap::new(),
131 line_numbers: LineNumbers::new(
132 "const a = 1
133 const b = 2
134 const c = 3",
135 ),
136 src_path: "some_path".into(),
137 minimum_required_version: Version::new(0, 1, 0),
138 type_aliases: HashMap::new(),
139 documentation: Vec::new(),
140 contains_echo: false,
141
142 references: References::default(),
143 };
144 assert_eq!(roundtrip(&module), module);
145}
146
147#[test]
148fn module_with_private_type() {
149 let module = ModuleInterface {
150 warnings: vec![],
151 is_internal: false,
152 package: "some_package".into(),
153 origin: Origin::Src,
154 name: "a/b".into(),
155 types: [(
156 "ListIntType".into(),
157 TypeConstructor {
158 type_: type_::list(type_::int()),
159 publicity: Publicity::Private,
160 origin: Default::default(),
161 module: "the/module".into(),
162 parameters: vec![],
163 deprecation: Deprecation::NotDeprecated,
164 documentation: None,
165 },
166 )]
167 .into(),
168 types_value_constructors: HashMap::new(),
169 values: HashMap::new(),
170 accessors: HashMap::new(),
171 line_numbers: LineNumbers::new(""),
172 src_path: "some_path".into(),
173 minimum_required_version: Version::new(0, 1, 0),
174 type_aliases: HashMap::new(),
175 documentation: Vec::new(),
176 contains_echo: false,
177
178 references: References::default(),
179 };
180 assert_eq!(roundtrip(&module), module);
181}
182
183#[test]
184fn module_with_app_type() {
185 let module = ModuleInterface {
186 warnings: vec![],
187 is_internal: false,
188 package: "some_package".into(),
189 origin: Origin::Src,
190 name: "a/b".into(),
191 types: [(
192 "ListIntType".into(),
193 TypeConstructor {
194 type_: type_::list(type_::int()),
195 publicity: Publicity::Public,
196 origin: Default::default(),
197 module: "the/module".into(),
198 parameters: vec![],
199 deprecation: Deprecation::NotDeprecated,
200 documentation: None,
201 },
202 )]
203 .into(),
204 types_value_constructors: HashMap::new(),
205 values: HashMap::new(),
206 accessors: HashMap::new(),
207 line_numbers: LineNumbers::new(""),
208 src_path: "some_path".into(),
209 minimum_required_version: Version::new(0, 1, 0),
210 type_aliases: HashMap::new(),
211 documentation: Vec::new(),
212 contains_echo: false,
213
214 references: References::default(),
215 };
216 assert_eq!(roundtrip(&module), module);
217}
218
219#[test]
220fn module_with_fn_type() {
221 let module = ModuleInterface {
222 warnings: vec![],
223 is_internal: false,
224 package: "some_package".into(),
225 origin: Origin::Src,
226 name: "a/b".into(),
227 types: [(
228 "FnType".into(),
229 TypeConstructor {
230 type_: type_::fn_(vec![type_::nil(), type_::float()], type_::int()),
231 publicity: Publicity::Public,
232 origin: Default::default(),
233 module: "the/module".into(),
234 parameters: vec![],
235 deprecation: Deprecation::NotDeprecated,
236 documentation: None,
237 },
238 )]
239 .into(),
240 types_value_constructors: HashMap::new(),
241 values: HashMap::new(),
242 accessors: HashMap::new(),
243 line_numbers: LineNumbers::new(""),
244 src_path: "some_path".into(),
245 minimum_required_version: Version::new(0, 1, 0),
246 type_aliases: HashMap::new(),
247 documentation: Vec::new(),
248 contains_echo: false,
249
250 references: References::default(),
251 };
252 assert_eq!(roundtrip(&module), module);
253}
254
255#[test]
256fn module_with_tuple_type() {
257 let module = ModuleInterface {
258 warnings: vec![],
259 is_internal: false,
260 package: "some_package".into(),
261 origin: Origin::Src,
262 name: "a/b".into(),
263 types: [(
264 "TupleType".into(),
265 TypeConstructor {
266 type_: type_::tuple(vec![type_::nil(), type_::float(), type_::int()]),
267 publicity: Publicity::Public,
268 origin: Default::default(),
269 module: "the/module".into(),
270 parameters: vec![],
271 deprecation: Deprecation::NotDeprecated,
272 documentation: None,
273 },
274 )]
275 .into(),
276 types_value_constructors: HashMap::new(),
277 values: HashMap::new(),
278 accessors: HashMap::new(),
279 line_numbers: LineNumbers::new(""),
280 src_path: "some_path".into(),
281 minimum_required_version: Version::new(0, 1, 0),
282 type_aliases: HashMap::new(),
283 documentation: Vec::new(),
284 contains_echo: false,
285
286 references: References::default(),
287 };
288 assert_eq!(roundtrip(&module), module);
289}
290
291#[test]
292fn module_with_generic_type() {
293 let t0 = type_::generic_var(0);
294 let t1 = type_::generic_var(1);
295 let t7 = type_::generic_var(7);
296 let t8 = type_::generic_var(8);
297
298 fn make(t1: Arc<Type>, t2: Arc<Type>) -> ModuleInterface {
299 ModuleInterface {
300 warnings: vec![],
301 is_internal: false,
302 package: "some_package".into(),
303 origin: Origin::Src,
304 name: "a/b".into(),
305 types: [(
306 "TupleType".into(),
307 TypeConstructor {
308 type_: type_::tuple(vec![t1.clone(), t1.clone(), t2.clone()]),
309 publicity: Publicity::Public,
310 origin: Default::default(),
311 module: "the/module".into(),
312 parameters: vec![t1, t2],
313 deprecation: Deprecation::NotDeprecated,
314 documentation: None,
315 },
316 )]
317 .into(),
318 types_value_constructors: HashMap::new(),
319 values: HashMap::new(),
320 accessors: HashMap::new(),
321 line_numbers: LineNumbers::new(""),
322 src_path: "some_path".into(),
323 minimum_required_version: Version::new(0, 1, 0),
324 type_aliases: HashMap::new(),
325 documentation: Vec::new(),
326 contains_echo: false,
327 references: References::default(),
328 }
329 }
330
331 assert_eq!(roundtrip(&make(t7, t8)), make(t0, t1));
332}
333
334#[test]
335fn module_with_type_links() {
336 let linked_type = type_::link(type_::int());
337 let type_ = type_::int();
338
339 fn make(type_: Arc<Type>) -> ModuleInterface {
340 ModuleInterface {
341 warnings: vec![],
342 is_internal: false,
343 package: "some_package".into(),
344 origin: Origin::Src,
345 name: "a".into(),
346 types: [(
347 "SomeType".into(),
348 TypeConstructor {
349 type_,
350 publicity: Publicity::Public,
351 origin: Default::default(),
352 module: "a".into(),
353 parameters: vec![],
354 deprecation: Deprecation::NotDeprecated,
355 documentation: None,
356 },
357 )]
358 .into(),
359 types_value_constructors: HashMap::new(),
360 values: HashMap::new(),
361 accessors: HashMap::new(),
362 line_numbers: LineNumbers::new(""),
363 src_path: "some_path".into(),
364 minimum_required_version: Version::new(0, 1, 0),
365 type_aliases: HashMap::new(),
366 documentation: Vec::new(),
367 contains_echo: false,
368 references: References::default(),
369 }
370 }
371
372 assert_eq!(roundtrip(&make(linked_type)), make(type_));
373}
374
375#[test]
376fn module_with_type_constructor_documentation() {
377 let linked_type = type_::link(type_::int());
378 let type_ = type_::int();
379
380 fn make(type_: Arc<Type>) -> ModuleInterface {
381 ModuleInterface {
382 warnings: vec![],
383 is_internal: false,
384 package: "some_package".into(),
385 origin: Origin::Src,
386 name: "a".into(),
387 types: [(
388 "SomeType".into(),
389 TypeConstructor {
390 type_,
391 publicity: Publicity::Public,
392 origin: Default::default(),
393 module: "a".into(),
394 parameters: vec![],
395 deprecation: Deprecation::NotDeprecated,
396 documentation: Some("type documentation".into()),
397 },
398 )]
399 .into(),
400 types_value_constructors: HashMap::new(),
401 values: HashMap::new(),
402 accessors: HashMap::new(),
403 line_numbers: LineNumbers::new(""),
404 src_path: "some_path".into(),
405 minimum_required_version: Version::new(0, 1, 0),
406 type_aliases: HashMap::new(),
407 documentation: Vec::new(),
408 contains_echo: false,
409 references: References::default(),
410 }
411 }
412
413 assert_eq!(roundtrip(&make(linked_type)), make(type_));
414}
415
416#[test]
417fn module_with_type_constructor_origin() {
418 let linked_type = type_::link(type_::int());
419 let type_ = type_::int();
420
421 fn make(type_: Arc<Type>) -> ModuleInterface {
422 ModuleInterface {
423 warnings: vec![],
424 is_internal: false,
425 package: "some_package".into(),
426 origin: Origin::Src,
427 name: "a".into(),
428 types: [(
429 "SomeType".into(),
430 TypeConstructor {
431 type_,
432 publicity: Publicity::Public,
433 origin: SrcSpan {
434 start: 535,
435 end: 543,
436 },
437 module: "a".into(),
438 parameters: vec![],
439 deprecation: Deprecation::NotDeprecated,
440 documentation: None,
441 },
442 )]
443 .into(),
444 types_value_constructors: HashMap::new(),
445 values: HashMap::new(),
446 accessors: HashMap::new(),
447 line_numbers: LineNumbers::new(""),
448 src_path: "some_path".into(),
449 minimum_required_version: Version::new(0, 1, 0),
450 type_aliases: HashMap::new(),
451 documentation: Vec::new(),
452 contains_echo: false,
453 references: References::default(),
454 }
455 }
456
457 assert_eq!(roundtrip(&make(linked_type)), make(type_));
458}
459
460#[test]
461fn module_type_to_constructors_mapping() {
462 let module = ModuleInterface {
463 warnings: vec![],
464 is_internal: false,
465 package: "some_package".into(),
466 origin: Origin::Src,
467 name: "a".into(),
468 types: HashMap::new(),
469 types_value_constructors: [(
470 "SomeType".into(),
471 TypeVariantConstructors {
472 type_parameters_ids: vec![0, 1, 2],
473 variants: vec![TypeValueConstructor {
474 name: "One".into(),
475 parameters: vec![],
476 documentation: Some("Some documentation".into()),
477 }],
478 opaque: Opaque::NotOpaque,
479 },
480 )]
481 .into(),
482 accessors: HashMap::new(),
483 values: HashMap::new(),
484 line_numbers: LineNumbers::new(""),
485 src_path: "some_path".into(),
486 minimum_required_version: Version::new(0, 1, 0),
487 type_aliases: HashMap::new(),
488 documentation: Vec::new(),
489 contains_echo: false,
490
491 references: References::default(),
492 };
493
494 assert_eq!(roundtrip(&module), module);
495}
496
497#[test]
498fn module_fn_value() {
499 let module = ModuleInterface {
500 warnings: vec![],
501 is_internal: false,
502 package: "some_package".into(),
503 origin: Origin::Src,
504 name: "a".into(),
505 types: HashMap::new(),
506 types_value_constructors: HashMap::new(),
507 accessors: HashMap::new(),
508 values: [(
509 "one".into(),
510 ValueConstructor {
511 publicity: Publicity::Public,
512 deprecation: Deprecation::NotDeprecated,
513 type_: type_::int(),
514 variant: ValueConstructorVariant::ModuleFn {
515 documentation: Some("wobble!".into()),
516 name: "one".into(),
517 field_map: None,
518 module: "a".into(),
519 arity: 5,
520 location: SrcSpan {
521 start: 535,
522 end: 1100,
523 },
524 external_erlang: None,
525 external_javascript: None,
526 implementations: Implementations {
527 gleam: true,
528 uses_erlang_externals: false,
529 uses_javascript_externals: false,
530 can_run_on_erlang: true,
531 can_run_on_javascript: true,
532 },
533 purity: Purity::Pure,
534 },
535 },
536 )]
537 .into(),
538 line_numbers: LineNumbers::new(""),
539 src_path: "some_path".into(),
540 minimum_required_version: Version::new(0, 1, 0),
541 type_aliases: HashMap::new(),
542 documentation: Vec::new(),
543 contains_echo: false,
544
545 references: References::default(),
546 };
547 assert_eq!(roundtrip(&module), module);
548}
549
550#[test]
551fn deprecated_module_fn_value() {
552 let module = ModuleInterface {
553 warnings: vec![],
554 is_internal: false,
555 package: "some_package".into(),
556 origin: Origin::Src,
557 name: "a".into(),
558 types: HashMap::new(),
559 types_value_constructors: HashMap::new(),
560 accessors: HashMap::new(),
561 values: [(
562 "one".into(),
563 ValueConstructor {
564 publicity: Publicity::Public,
565 deprecation: Deprecation::Deprecated {
566 message: "wibble wobble".into(),
567 },
568 type_: type_::int(),
569 variant: ValueConstructorVariant::ModuleFn {
570 documentation: Some("wobble!".into()),
571 name: "one".into(),
572 field_map: None,
573 module: "a".into(),
574 arity: 5,
575 location: SrcSpan {
576 start: 535,
577 end: 1100,
578 },
579 external_erlang: None,
580 external_javascript: None,
581 implementations: Implementations {
582 gleam: true,
583 uses_erlang_externals: false,
584 uses_javascript_externals: false,
585 can_run_on_erlang: true,
586 can_run_on_javascript: true,
587 },
588 purity: Purity::Pure,
589 },
590 },
591 )]
592 .into(),
593 line_numbers: LineNumbers::new(""),
594 src_path: "some_path".into(),
595 minimum_required_version: Version::new(0, 1, 0),
596 type_aliases: HashMap::new(),
597 documentation: Vec::new(),
598 contains_echo: false,
599
600 references: References::default(),
601 };
602 assert_eq!(roundtrip(&module), module);
603}
604
605#[test]
606fn private_module_fn_value() {
607 let module = ModuleInterface {
608 warnings: vec![],
609 is_internal: false,
610 package: "some_package".into(),
611 origin: Origin::Src,
612 name: "a".into(),
613 types: HashMap::new(),
614 types_value_constructors: HashMap::new(),
615 accessors: HashMap::new(),
616 values: [(
617 "one".into(),
618 ValueConstructor {
619 publicity: Publicity::Private,
620 deprecation: Deprecation::NotDeprecated,
621 type_: type_::int(),
622 variant: ValueConstructorVariant::ModuleFn {
623 documentation: Some("wobble!".into()),
624 name: "one".into(),
625 field_map: None,
626 module: "a".into(),
627 arity: 5,
628 location: SrcSpan {
629 start: 535,
630 end: 1100,
631 },
632 external_erlang: None,
633 external_javascript: None,
634 implementations: Implementations {
635 gleam: true,
636 uses_erlang_externals: false,
637 uses_javascript_externals: false,
638 can_run_on_erlang: true,
639 can_run_on_javascript: true,
640 },
641 purity: Purity::Pure,
642 },
643 },
644 )]
645 .into(),
646 line_numbers: LineNumbers::new(""),
647 src_path: "some_path".into(),
648 minimum_required_version: Version::new(0, 1, 0),
649 type_aliases: HashMap::new(),
650 documentation: Vec::new(),
651 contains_echo: false,
652
653 references: References::default(),
654 };
655
656 assert_eq!(roundtrip(&module), module);
657}
658
659// https://github.com/gleam-lang/gleam/commit/c8f3bd0ddbf61c27ea35f37297058ecca7515f6c
660#[test]
661fn module_fn_value_regression() {
662 let module = ModuleInterface {
663 warnings: vec![],
664 is_internal: false,
665 package: "some_package".into(),
666 origin: Origin::Src,
667 name: "a/b/c".into(),
668 types: HashMap::new(),
669 types_value_constructors: HashMap::new(),
670 accessors: HashMap::new(),
671 values: [(
672 "one".into(),
673 ValueConstructor {
674 publicity: Publicity::Public,
675 deprecation: Deprecation::NotDeprecated,
676 type_: type_::int(),
677 variant: ValueConstructorVariant::ModuleFn {
678 documentation: Some("wabble!".into()),
679 name: "one".into(),
680 field_map: None,
681 module: "a".into(),
682 arity: 5,
683 location: SrcSpan {
684 start: 52,
685 end: 1100,
686 },
687 external_erlang: None,
688 external_javascript: None,
689 implementations: Implementations {
690 gleam: true,
691 uses_erlang_externals: false,
692 uses_javascript_externals: false,
693 can_run_on_erlang: true,
694 can_run_on_javascript: true,
695 },
696 purity: Purity::TrustedPure,
697 },
698 },
699 )]
700 .into(),
701 line_numbers: LineNumbers::new(""),
702 src_path: "some_path".into(),
703 minimum_required_version: Version::new(0, 1, 0),
704 type_aliases: HashMap::new(),
705 documentation: Vec::new(),
706 contains_echo: false,
707
708 references: References::default(),
709 };
710
711 assert_eq!(roundtrip(&module), module);
712}
713
714#[test]
715fn module_fn_value_with_field_map() {
716 let module = ModuleInterface {
717 warnings: vec![],
718 is_internal: false,
719 package: "some_package".into(),
720 origin: Origin::Src,
721 name: "a".into(),
722 types: HashMap::new(),
723 types_value_constructors: HashMap::new(),
724 accessors: HashMap::new(),
725 values: [(
726 "one".into(),
727 ValueConstructor {
728 publicity: Publicity::Public,
729 deprecation: Deprecation::NotDeprecated,
730 type_: type_::int(),
731 variant: ValueConstructorVariant::ModuleFn {
732 documentation: Some("wubble!".into()),
733 name: "one".into(),
734 field_map: Some(FieldMap {
735 arity: 20,
736 fields: [("ok".into(), 5), ("ko".into(), 7)].into(),
737 }),
738 external_erlang: None,
739 external_javascript: None,
740 module: "a".into(),
741 arity: 5,
742 location: SrcSpan { start: 2, end: 11 },
743 implementations: Implementations {
744 gleam: true,
745 uses_erlang_externals: false,
746 uses_javascript_externals: false,
747 can_run_on_erlang: true,
748 can_run_on_javascript: true,
749 },
750 purity: Purity::Pure,
751 },
752 },
753 )]
754 .into(),
755 line_numbers: LineNumbers::new(""),
756 src_path: "some_path".into(),
757 minimum_required_version: Version::new(0, 1, 0),
758 type_aliases: HashMap::new(),
759 documentation: Vec::new(),
760 contains_echo: false,
761
762 references: References::default(),
763 };
764
765 assert_eq!(roundtrip(&module), module);
766}
767
768#[test]
769fn record_value() {
770 let mut random = rand::rng();
771
772 let module = ModuleInterface {
773 warnings: vec![],
774 is_internal: false,
775 package: "some_package".into(),
776 origin: Origin::Src,
777 name: "a".into(),
778 types: HashMap::new(),
779 types_value_constructors: HashMap::new(),
780 accessors: HashMap::new(),
781 values: [(
782 "one".into(),
783 ValueConstructor {
784 publicity: Publicity::Public,
785 deprecation: Deprecation::NotDeprecated,
786 type_: type_::int(),
787 variant: ValueConstructorVariant::Record {
788 documentation: Some("webble!".into()),
789 name: "one".into(),
790 module: "themodule".into(),
791 field_map: None,
792 arity: random.random(),
793 variants_count: random.random(),
794 location: SrcSpan {
795 start: random.random(),
796 end: random.random(),
797 },
798 variant_index: random.random(),
799 },
800 },
801 )]
802 .into(),
803 line_numbers: LineNumbers::new(""),
804 src_path: "some_path".into(),
805 minimum_required_version: Version::new(0, 1, 0),
806 type_aliases: HashMap::new(),
807 documentation: Vec::new(),
808 contains_echo: false,
809
810 references: References::default(),
811 };
812
813 assert_eq!(roundtrip(&module), module);
814}
815
816#[test]
817fn record_value_with_field_map() {
818 let mut random = rand::rng();
819
820 let module = ModuleInterface {
821 warnings: vec![],
822 is_internal: false,
823 package: "some_package".into(),
824 origin: Origin::Src,
825 name: "a".into(),
826 types: HashMap::new(),
827 types_value_constructors: HashMap::new(),
828 accessors: HashMap::new(),
829 values: [(
830 "one".into(),
831 ValueConstructor {
832 publicity: Publicity::Public,
833 deprecation: Deprecation::NotDeprecated,
834 type_: type_::int(),
835 variant: ValueConstructorVariant::Record {
836 documentation: Some("wybble!".into()),
837 module: "themodule".into(),
838 name: "one".into(),
839 field_map: Some(FieldMap {
840 arity: random.random(),
841 fields: [
842 ("ok".into(), random.random()),
843 ("ko".into(), random.random()),
844 ]
845 .into(),
846 }),
847 arity: random.random(),
848 variants_count: random.random(),
849 variant_index: random.random(),
850 location: SrcSpan {
851 start: random.random(),
852 end: random.random(),
853 },
854 },
855 },
856 )]
857 .into(),
858 line_numbers: LineNumbers::new(""),
859 src_path: "some_path".into(),
860 minimum_required_version: Version::new(0, 1, 0),
861 type_aliases: HashMap::new(),
862 documentation: Vec::new(),
863 contains_echo: false,
864
865 references: References::default(),
866 };
867
868 assert_eq!(roundtrip(&module), module);
869}
870
871#[test]
872fn accessors() {
873 let accessors1 = [
874 (
875 "a".into(),
876 RecordAccessor {
877 index: 6,
878 label: "siiixxx".into(),
879 type_: type_::nil(),
880 },
881 ),
882 (
883 "a".into(),
884 RecordAccessor {
885 index: 5,
886 label: "fiveee".into(),
887 type_: type_::float(),
888 },
889 ),
890 ];
891
892 let accessors2 = [(
893 "a".into(),
894 RecordAccessor {
895 index: 1,
896 label: "ok".into(),
897 type_: type_::float(),
898 },
899 )];
900
901 let module = ModuleInterface {
902 warnings: vec![],
903 is_internal: false,
904 package: "some_package".into(),
905 origin: Origin::Src,
906 name: "a".into(),
907 types: HashMap::new(),
908 types_value_constructors: HashMap::new(),
909 values: HashMap::new(),
910 accessors: [
911 (
912 "one".into(),
913 AccessorsMap {
914 publicity: Publicity::Public,
915 type_: type_::int(),
916 shared_accessors: accessors1.clone().into(),
917 variant_specific_accessors: vec![accessors1.into()],
918 },
919 ),
920 (
921 "two".into(),
922 AccessorsMap {
923 publicity: Publicity::Public,
924 type_: type_::int(),
925 shared_accessors: accessors2.clone().into(),
926 variant_specific_accessors: vec![accessors2.into()],
927 },
928 ),
929 ]
930 .into(),
931 line_numbers: LineNumbers::new(""),
932 src_path: "some_path".into(),
933 minimum_required_version: Version::new(0, 1, 0),
934 type_aliases: HashMap::new(),
935 documentation: Vec::new(),
936 contains_echo: false,
937
938 references: References::default(),
939 };
940
941 assert_eq!(roundtrip(&module), module);
942}
943
944#[test]
945fn private_accessors() {
946 let accessors1 = [
947 (
948 "a".into(),
949 RecordAccessor {
950 index: 6,
951 label: "siiixxx".into(),
952 type_: type_::nil(),
953 },
954 ),
955 (
956 "a".into(),
957 RecordAccessor {
958 index: 5,
959 label: "fiveee".into(),
960 type_: type_::float(),
961 },
962 ),
963 ];
964
965 let accessors2 = [(
966 "a".into(),
967 RecordAccessor {
968 index: 1,
969 label: "ok".into(),
970 type_: type_::float(),
971 },
972 )];
973
974 let module = ModuleInterface {
975 warnings: vec![],
976 is_internal: false,
977 package: "some_package".into(),
978 origin: Origin::Src,
979 name: "a".into(),
980 types: HashMap::new(),
981 types_value_constructors: HashMap::new(),
982 contains_echo: false,
983 values: HashMap::new(),
984 accessors: [
985 (
986 "one".into(),
987 AccessorsMap {
988 publicity: Publicity::Private,
989 type_: type_::int(),
990 shared_accessors: accessors1.clone().into(),
991 variant_specific_accessors: vec![accessors1.into()],
992 },
993 ),
994 (
995 "two".into(),
996 AccessorsMap {
997 publicity: Publicity::Public,
998 type_: type_::int(),
999 shared_accessors: accessors2.clone().into(),
1000 variant_specific_accessors: vec![accessors2.into()],
1001 },
1002 ),
1003 ]
1004 .into(),
1005 line_numbers: LineNumbers::new(""),
1006 src_path: "some_path".into(),
1007 minimum_required_version: Version::new(0, 1, 0),
1008 type_aliases: HashMap::new(),
1009 documentation: Vec::new(),
1010 references: References::default(),
1011 };
1012
1013 assert_eq!(roundtrip(&module), module);
1014}
1015
1016#[test]
1017fn constant_int() {
1018 let module = constant_module(Constant::Int {
1019 location: Default::default(),
1020 value: "100".into(),
1021 int_value: 100.into(),
1022 });
1023
1024 assert_eq!(roundtrip(&module), module);
1025}
1026
1027#[test]
1028fn constant_float() {
1029 let module = constant_module(Constant::Float {
1030 location: Default::default(),
1031 value: "1.0".into(),
1032 });
1033
1034 assert_eq!(roundtrip(&module), module);
1035}
1036
1037#[test]
1038fn constant_string() {
1039 let module = constant_module(Constant::String {
1040 location: Default::default(),
1041 value: "hello".into(),
1042 });
1043
1044 assert_eq!(roundtrip(&module), module);
1045}
1046
1047#[test]
1048fn constant_tuple() {
1049 let module = constant_module(Constant::Tuple {
1050 location: Default::default(),
1051 elements: vec![
1052 Constant::Int {
1053 location: Default::default(),
1054 value: "1".into(),
1055 int_value: 1.into(),
1056 },
1057 Constant::Float {
1058 location: Default::default(),
1059 value: "1.0".into(),
1060 },
1061 Constant::Tuple {
1062 location: Default::default(),
1063 elements: vec![
1064 Constant::Int {
1065 location: Default::default(),
1066 value: "1".into(),
1067 int_value: 1.into(),
1068 },
1069 Constant::Float {
1070 location: Default::default(),
1071 value: "1.0".into(),
1072 },
1073 ],
1074 },
1075 ],
1076 });
1077
1078 assert_eq!(roundtrip(&module), module);
1079}
1080
1081#[test]
1082fn constant_list() {
1083 let module = constant_module(Constant::List {
1084 location: Default::default(),
1085 type_: type_::int(),
1086 elements: vec![
1087 Constant::Int {
1088 location: Default::default(),
1089 value: "1".into(),
1090 int_value: 1.into(),
1091 },
1092 Constant::Int {
1093 location: Default::default(),
1094 value: "2".into(),
1095 int_value: 2.into(),
1096 },
1097 Constant::Int {
1098 location: Default::default(),
1099 value: "3".into(),
1100 int_value: 3.into(),
1101 },
1102 ],
1103 });
1104
1105 assert_eq!(roundtrip(&module), module);
1106}
1107
1108#[test]
1109fn constant_record() {
1110 let module = constant_module(Constant::Record {
1111 location: Default::default(),
1112 module: None,
1113 name: "".into(),
1114 args: vec![
1115 CallArg {
1116 implicit: None,
1117 label: None,
1118 location: Default::default(),
1119 value: Constant::Float {
1120 location: Default::default(),
1121 value: "0.0".into(),
1122 },
1123 },
1124 CallArg {
1125 implicit: None,
1126 label: None,
1127 location: Default::default(),
1128 value: Constant::Int {
1129 location: Default::default(),
1130 value: "1".into(),
1131 int_value: 1.into(),
1132 },
1133 },
1134 ],
1135 tag: "thetag".into(),
1136 type_: type_::int(),
1137 field_map: None,
1138 record_constructor: None,
1139 });
1140
1141 assert_eq!(roundtrip(&module), module);
1142}
1143
1144#[test]
1145fn constant_var() {
1146 let one_original = Constant::Int {
1147 location: Default::default(),
1148 value: "1".into(),
1149 int_value: 1.into(),
1150 };
1151
1152 let one = Constant::Var {
1153 location: Default::default(),
1154 module: None,
1155 name: "one_original".into(),
1156 type_: type_::int(),
1157 constructor: Some(Box::from(ValueConstructor {
1158 publicity: Publicity::Public,
1159 deprecation: Deprecation::NotDeprecated,
1160 type_: type_::int(),
1161 variant: ValueConstructorVariant::ModuleConstant {
1162 documentation: Some("some doc".into()),
1163 literal: one_original.clone(),
1164 location: SrcSpan::default(),
1165 module: "one/two".into(),
1166 implementations: Implementations {
1167 gleam: true,
1168 uses_erlang_externals: false,
1169 uses_javascript_externals: false,
1170 can_run_on_erlang: true,
1171 can_run_on_javascript: true,
1172 },
1173 name: "one_original".into(),
1174 },
1175 })),
1176 };
1177
1178 let module = ModuleInterface {
1179 warnings: vec![],
1180 is_internal: false,
1181 package: "some_package".into(),
1182 origin: Origin::Src,
1183 name: "a".into(),
1184 types: HashMap::new(),
1185 types_value_constructors: HashMap::new(),
1186 accessors: HashMap::new(),
1187 values: [
1188 (
1189 "one".into(),
1190 ValueConstructor {
1191 publicity: Publicity::Public,
1192 deprecation: Deprecation::NotDeprecated,
1193 type_: type_::int(),
1194 variant: ValueConstructorVariant::ModuleConstant {
1195 documentation: Some("some doc!!!!!!!!!".into()),
1196 literal: one,
1197 location: SrcSpan::default(),
1198 module: "one/two".into(),
1199 implementations: Implementations {
1200 gleam: true,
1201 uses_erlang_externals: false,
1202 uses_javascript_externals: false,
1203 can_run_on_erlang: true,
1204 can_run_on_javascript: true,
1205 },
1206 name: "one".into(),
1207 },
1208 },
1209 ),
1210 (
1211 "one_original".into(),
1212 ValueConstructor {
1213 publicity: Publicity::Public,
1214 deprecation: Deprecation::NotDeprecated,
1215 type_: type_::int(),
1216 variant: ValueConstructorVariant::ModuleConstant {
1217 documentation: Some("some doc yeah".into()),
1218 literal: one_original,
1219 location: SrcSpan::default(),
1220 module: "one/two".into(),
1221 implementations: Implementations {
1222 gleam: true,
1223 uses_erlang_externals: false,
1224 uses_javascript_externals: false,
1225 can_run_on_erlang: true,
1226 can_run_on_javascript: true,
1227 },
1228 name: "one_original".into(),
1229 },
1230 },
1231 ),
1232 ]
1233 .into(),
1234 line_numbers: LineNumbers::new(""),
1235 src_path: "some_path".into(),
1236 minimum_required_version: Version::new(0, 1, 0),
1237 type_aliases: HashMap::new(),
1238 documentation: Vec::new(),
1239 contains_echo: false,
1240
1241 references: References::default(),
1242 };
1243
1244 assert_eq!(roundtrip(&module), module);
1245}
1246
1247#[test]
1248fn constant_bit_array() {
1249 let module = constant_module(Constant::BitArray {
1250 location: Default::default(),
1251 segments: vec![],
1252 });
1253 assert_eq!(roundtrip(&module), module);
1254}
1255
1256#[test]
1257fn constant_bit_array_unit() {
1258 let module = bit_array_segment_option_module(BitArrayOption::Unit {
1259 location: Default::default(),
1260 value: 234,
1261 });
1262 assert_eq!(roundtrip(&module), module);
1263}
1264
1265#[test]
1266fn constant_bit_array_float() {
1267 let module = bit_array_segment_option_module(BitArrayOption::Float {
1268 location: Default::default(),
1269 });
1270 assert_eq!(roundtrip(&module), module);
1271}
1272
1273#[test]
1274fn constant_bit_array_int() {
1275 let module = bit_array_segment_option_module(BitArrayOption::Int {
1276 location: Default::default(),
1277 });
1278 assert_eq!(roundtrip(&module), module);
1279}
1280
1281#[test]
1282fn constant_bit_array_size() {
1283 let module = bit_array_segment_option_module(BitArrayOption::Size {
1284 location: Default::default(),
1285 value: Box::new(Constant::Int {
1286 location: Default::default(),
1287 value: "1".into(),
1288 int_value: 1.into(),
1289 }),
1290 short_form: false,
1291 });
1292 assert_eq!(roundtrip(&module), module);
1293}
1294
1295#[test]
1296fn constant_bit_array_size_short_form() {
1297 let module = bit_array_segment_option_module(BitArrayOption::Size {
1298 location: Default::default(),
1299 value: Box::new(Constant::Int {
1300 location: Default::default(),
1301 value: "1".into(),
1302 int_value: 1.into(),
1303 }),
1304 short_form: true,
1305 });
1306 assert_eq!(roundtrip(&module), module);
1307}
1308
1309#[test]
1310fn constant_bit_array_bit_arry() {
1311 let module = bit_array_segment_option_module(BitArrayOption::Bits {
1312 location: Default::default(),
1313 });
1314 assert_eq!(roundtrip(&module), module);
1315}
1316
1317#[test]
1318fn constant_bit_array_utf8() {
1319 let module = bit_array_segment_option_module(BitArrayOption::Utf8 {
1320 location: Default::default(),
1321 });
1322 assert_eq!(roundtrip(&module), module);
1323}
1324
1325#[test]
1326fn constant_bit_array_utf16() {
1327 let module = bit_array_segment_option_module(BitArrayOption::Utf16 {
1328 location: Default::default(),
1329 });
1330 assert_eq!(roundtrip(&module), module);
1331}
1332
1333#[test]
1334fn constant_bit_array_utf32() {
1335 let module = bit_array_segment_option_module(BitArrayOption::Utf32 {
1336 location: Default::default(),
1337 });
1338 assert_eq!(roundtrip(&module), module);
1339}
1340
1341#[test]
1342fn constant_bit_array_utf8codepoint() {
1343 let module = bit_array_segment_option_module(BitArrayOption::Utf8Codepoint {
1344 location: Default::default(),
1345 });
1346 assert_eq!(roundtrip(&module), module);
1347}
1348
1349#[test]
1350fn constant_bit_array_utf16codepoint() {
1351 let module = bit_array_segment_option_module(BitArrayOption::Utf16Codepoint {
1352 location: Default::default(),
1353 });
1354 assert_eq!(roundtrip(&module), module);
1355}
1356
1357#[test]
1358fn constant_bit_array_utf32codepoint() {
1359 let module = bit_array_segment_option_module(BitArrayOption::Utf32Codepoint {
1360 location: Default::default(),
1361 });
1362 assert_eq!(roundtrip(&module), module);
1363}
1364
1365#[test]
1366fn constant_bit_array_signed() {
1367 let module = bit_array_segment_option_module(BitArrayOption::Signed {
1368 location: Default::default(),
1369 });
1370 assert_eq!(roundtrip(&module), module);
1371}
1372
1373#[test]
1374fn constant_bit_array_unsigned() {
1375 let module = bit_array_segment_option_module(BitArrayOption::Unsigned {
1376 location: Default::default(),
1377 });
1378 assert_eq!(roundtrip(&module), module);
1379}
1380
1381#[test]
1382fn constant_bit_array_big() {
1383 let module = bit_array_segment_option_module(BitArrayOption::Big {
1384 location: Default::default(),
1385 });
1386 assert_eq!(roundtrip(&module), module);
1387}
1388
1389#[test]
1390fn constant_bit_array_little() {
1391 let module = bit_array_segment_option_module(BitArrayOption::Little {
1392 location: Default::default(),
1393 });
1394 assert_eq!(roundtrip(&module), module);
1395}
1396
1397#[test]
1398fn constant_bit_array_native() {
1399 let module = bit_array_segment_option_module(BitArrayOption::Native {
1400 location: Default::default(),
1401 });
1402 assert_eq!(roundtrip(&module), module);
1403}
1404
1405#[test]
1406fn deprecated_type() {
1407 let module = ModuleInterface {
1408 warnings: vec![],
1409 is_internal: false,
1410 package: "some_package".into(),
1411 origin: Origin::Src,
1412 name: "a/b".into(),
1413 types: [(
1414 "ListIntType".into(),
1415 TypeConstructor {
1416 type_: type_::list(type_::int()),
1417 publicity: Publicity::Public,
1418 origin: Default::default(),
1419 module: "the/module".into(),
1420 parameters: vec![],
1421 deprecation: Deprecation::Deprecated {
1422 message: "oh no".into(),
1423 },
1424 documentation: None,
1425 },
1426 )]
1427 .into(),
1428 types_value_constructors: HashMap::new(),
1429 values: HashMap::new(),
1430 accessors: HashMap::new(),
1431 line_numbers: LineNumbers::new(""),
1432 src_path: "some_path".into(),
1433 minimum_required_version: Version::new(0, 1, 0),
1434 type_aliases: HashMap::new(),
1435 documentation: Vec::new(),
1436 contains_echo: false,
1437
1438 references: References::default(),
1439 };
1440 assert_eq!(roundtrip(&module), module);
1441}
1442
1443#[test]
1444fn module_fn_value_with_external_implementations() {
1445 let module = ModuleInterface {
1446 warnings: vec![],
1447 is_internal: false,
1448 package: "some_package".into(),
1449 origin: Origin::Src,
1450 name: "a/b/c".into(),
1451 types: HashMap::new(),
1452 types_value_constructors: HashMap::new(),
1453 accessors: HashMap::new(),
1454 values: [(
1455 "one".into(),
1456 ValueConstructor {
1457 publicity: Publicity::Public,
1458 deprecation: Deprecation::NotDeprecated,
1459 type_: type_::int(),
1460 variant: ValueConstructorVariant::ModuleFn {
1461 documentation: Some("wabble!".into()),
1462 name: "one".into(),
1463 field_map: None,
1464 module: "a".into(),
1465 arity: 5,
1466 location: SrcSpan {
1467 start: 52,
1468 end: 1100,
1469 },
1470 external_erlang: Some(("wibble".into(), "wobble".into())),
1471 external_javascript: Some(("wobble".into(), "wibble".into())),
1472 implementations: Implementations {
1473 gleam: false,
1474 uses_erlang_externals: true,
1475 uses_javascript_externals: true,
1476 can_run_on_erlang: false,
1477 can_run_on_javascript: true,
1478 },
1479 purity: Purity::Impure,
1480 },
1481 },
1482 )]
1483 .into(),
1484 line_numbers: LineNumbers::new(""),
1485 src_path: "some_path".into(),
1486 minimum_required_version: Version::new(0, 1, 0),
1487 type_aliases: HashMap::new(),
1488 documentation: Vec::new(),
1489 contains_echo: false,
1490 references: References::default(),
1491 };
1492
1493 assert_eq!(roundtrip(&module), module);
1494}
1495
1496#[test]
1497fn module_containing_echo() {
1498 let module = ModuleInterface {
1499 warnings: vec![],
1500 is_internal: false,
1501 package: "some_package".into(),
1502 origin: Origin::Src,
1503 name: "a/b/c".into(),
1504 types: HashMap::new(),
1505 types_value_constructors: HashMap::new(),
1506 accessors: HashMap::new(),
1507 values: [].into(),
1508 line_numbers: LineNumbers::new(""),
1509 src_path: "some_path".into(),
1510 minimum_required_version: Version::new(0, 1, 0),
1511 type_aliases: HashMap::new(),
1512 documentation: Vec::new(),
1513 contains_echo: true,
1514 references: References::default(),
1515 };
1516
1517 assert_eq!(roundtrip(&module), module);
1518}
1519
1520#[test]
1521fn internal_module_fn() {
1522 let module = ModuleInterface {
1523 warnings: vec![],
1524 is_internal: false,
1525 package: "some_package".into(),
1526 origin: Origin::Src,
1527 name: "a/b/c".into(),
1528 types: HashMap::new(),
1529 types_value_constructors: HashMap::new(),
1530 accessors: HashMap::new(),
1531 values: [(
1532 "one".into(),
1533 ValueConstructor {
1534 publicity: Publicity::Internal {
1535 attribute_location: None,
1536 },
1537 deprecation: Deprecation::NotDeprecated,
1538 type_: type_::int(),
1539 variant: ValueConstructorVariant::ModuleFn {
1540 documentation: Some("wabble!".into()),
1541 name: "one".into(),
1542 field_map: None,
1543 module: "a".into(),
1544 arity: 5,
1545 location: SrcSpan {
1546 start: 52,
1547 end: 1100,
1548 },
1549 external_erlang: Some(("wibble".into(), "wobble".into())),
1550 external_javascript: Some(("wobble".into(), "wibble".into())),
1551 implementations: Implementations {
1552 gleam: false,
1553 uses_erlang_externals: true,
1554 uses_javascript_externals: true,
1555 can_run_on_erlang: true,
1556 can_run_on_javascript: true,
1557 },
1558 purity: Purity::Unknown,
1559 },
1560 },
1561 )]
1562 .into(),
1563 line_numbers: LineNumbers::new(""),
1564 src_path: "some_path".into(),
1565 minimum_required_version: Version::new(0, 1, 0),
1566 type_aliases: HashMap::new(),
1567 documentation: Vec::new(),
1568 contains_echo: false,
1569
1570 references: References::default(),
1571 };
1572
1573 assert_eq!(roundtrip(&module), module);
1574}
1575
1576#[test]
1577fn internal_annotated_module_fn() {
1578 let module = ModuleInterface {
1579 warnings: vec![],
1580 is_internal: false,
1581 package: "some_package".into(),
1582 origin: Origin::Src,
1583 name: "a/b/c".into(),
1584 types: HashMap::new(),
1585 types_value_constructors: HashMap::new(),
1586 accessors: HashMap::new(),
1587 values: [(
1588 "one".into(),
1589 ValueConstructor {
1590 publicity: Publicity::Internal {
1591 attribute_location: Some(SrcSpan {
1592 start: 11,
1593 end: 111,
1594 }),
1595 },
1596 deprecation: Deprecation::NotDeprecated,
1597 type_: type_::int(),
1598 variant: ValueConstructorVariant::ModuleFn {
1599 documentation: Some("wabble!".into()),
1600 name: "one".into(),
1601 field_map: None,
1602 module: "a".into(),
1603 arity: 5,
1604 location: SrcSpan {
1605 start: 52,
1606 end: 1100,
1607 },
1608 external_erlang: Some(("wibble".into(), "wobble".into())),
1609 external_javascript: Some(("wobble".into(), "wibble".into())),
1610 implementations: Implementations {
1611 gleam: false,
1612 uses_erlang_externals: true,
1613 uses_javascript_externals: true,
1614 can_run_on_erlang: true,
1615 can_run_on_javascript: true,
1616 },
1617 purity: Purity::Impure,
1618 },
1619 },
1620 )]
1621 .into(),
1622 line_numbers: LineNumbers::new(""),
1623 src_path: "some_path".into(),
1624 minimum_required_version: Version::new(0, 1, 0),
1625 type_aliases: HashMap::new(),
1626 documentation: Vec::new(),
1627 contains_echo: false,
1628
1629 references: References::default(),
1630 };
1631
1632 assert_eq!(roundtrip(&module), module);
1633}
1634
1635// https://github.com/gleam-lang/gleam/issues/2599
1636#[test]
1637fn type_variable_ids_in_constructors_are_shared() {
1638 let module = ModuleInterface {
1639 warnings: vec![],
1640 is_internal: false,
1641 package: "some_package".into(),
1642 origin: Origin::Src,
1643 name: "a/b/c".into(),
1644 types: HashMap::new(),
1645 types_value_constructors: HashMap::from([(
1646 "SomeType".into(),
1647 TypeVariantConstructors {
1648 type_parameters_ids: vec![4, 5, 6],
1649 variants: vec![TypeValueConstructor {
1650 name: "One".into(),
1651 parameters: vec![
1652 TypeValueConstructorField {
1653 type_: type_::generic_var(6),
1654 label: None,
1655 },
1656 TypeValueConstructorField {
1657 type_: type_::int(),
1658 label: None,
1659 },
1660 TypeValueConstructorField {
1661 type_: type_::tuple(vec![type_::generic_var(4), type_::generic_var(5)]),
1662 label: None,
1663 },
1664 ],
1665 documentation: None,
1666 }],
1667 opaque: Opaque::NotOpaque,
1668 },
1669 )]),
1670 accessors: HashMap::new(),
1671 values: [].into(),
1672 line_numbers: LineNumbers::new(""),
1673 src_path: "some_path".into(),
1674 minimum_required_version: Version::new(0, 1, 0),
1675 type_aliases: HashMap::new(),
1676 documentation: Vec::new(),
1677 contains_echo: false,
1678
1679 references: References::default(),
1680 };
1681
1682 let expected = HashMap::from([(
1683 "SomeType".into(),
1684 TypeVariantConstructors {
1685 type_parameters_ids: vec![1, 2, 0],
1686 variants: vec![TypeValueConstructor {
1687 name: "One".into(),
1688 parameters: vec![
1689 TypeValueConstructorField {
1690 type_: type_::generic_var(0),
1691 label: None,
1692 },
1693 TypeValueConstructorField {
1694 type_: type_::int(),
1695 label: None,
1696 },
1697 TypeValueConstructorField {
1698 type_: type_::tuple(vec![type_::generic_var(1), type_::generic_var(2)]),
1699 label: None,
1700 },
1701 ],
1702 documentation: None,
1703 }],
1704 opaque: Opaque::NotOpaque,
1705 },
1706 )]);
1707
1708 assert_eq!(roundtrip(&module).types_value_constructors, expected);
1709}
1710
1711#[test]
1712fn type_with_inferred_variant() {
1713 let module = ModuleInterface {
1714 warnings: vec![],
1715 is_internal: false,
1716 package: "some_package".into(),
1717 contains_echo: false,
1718 origin: Origin::Src,
1719 name: "a/b".into(),
1720 types: [(
1721 "Wibble".into(),
1722 TypeConstructor {
1723 type_: Arc::new(Type::Named {
1724 publicity: Publicity::Public,
1725 package: "some_package".into(),
1726 module: "the/module".into(),
1727 name: "Wibble".into(),
1728 args: Vec::new(),
1729 inferred_variant: Some(1),
1730 }),
1731 publicity: Publicity::Public,
1732 origin: Default::default(),
1733 module: "the/module".into(),
1734 parameters: vec![],
1735 deprecation: Deprecation::NotDeprecated,
1736 documentation: None,
1737 },
1738 )]
1739 .into(),
1740 types_value_constructors: HashMap::new(),
1741 values: HashMap::new(),
1742 accessors: HashMap::new(),
1743 line_numbers: LineNumbers::new(""),
1744 src_path: "some_path".into(),
1745 minimum_required_version: Version::new(0, 1, 0),
1746 type_aliases: HashMap::new(),
1747 documentation: Vec::new(),
1748 references: References::default(),
1749 };
1750 assert_eq!(roundtrip(&module), module);
1751}
1752
1753#[test]
1754fn module_with_type_aliases() {
1755 let module = ModuleInterface {
1756 warnings: vec![],
1757 is_internal: false,
1758 package: "some_package".into(),
1759 origin: Origin::Src,
1760 name: "some_module".into(),
1761 types: HashMap::new(),
1762 types_value_constructors: HashMap::new(),
1763 values: HashMap::new(),
1764 accessors: HashMap::new(),
1765 line_numbers: LineNumbers::new(""),
1766 src_path: "some_path".into(),
1767 minimum_required_version: Version::new(0, 1, 0),
1768 type_aliases: [(
1769 "MyAlias".into(),
1770 TypeAliasConstructor {
1771 publicity: Publicity::Public,
1772 module: "some_module".into(),
1773 type_: prelude::int(),
1774 arity: 1,
1775 deprecation: Deprecation::NotDeprecated,
1776 documentation: Some("Some documentation".into()),
1777 origin: Default::default(),
1778 },
1779 )]
1780 .into(),
1781 documentation: Vec::new(),
1782 contains_echo: false,
1783
1784 references: References::default(),
1785 };
1786 assert_eq!(roundtrip(&module), module);
1787}
1788
1789#[test]
1790fn module_with_documentation() {
1791 let module = ModuleInterface {
1792 warnings: vec![],
1793 is_internal: false,
1794 package: "some_package".into(),
1795 origin: Origin::Src,
1796 name: "some_module".into(),
1797 types: HashMap::new(),
1798 types_value_constructors: HashMap::new(),
1799 values: HashMap::new(),
1800 accessors: HashMap::new(),
1801 line_numbers: LineNumbers::new(""),
1802 src_path: "some_path".into(),
1803 minimum_required_version: Version::new(0, 1, 0),
1804 type_aliases: HashMap::new(),
1805 documentation: vec![
1806 "This is a line of documentation".into(),
1807 "And here is another".into(),
1808 "And finally, a third".into(),
1809 ],
1810 contains_echo: false,
1811
1812 references: References::default(),
1813 };
1814 assert_eq!(roundtrip(&module), module);
1815}
1816
1817#[test]
1818fn module_with_opaque_type() {
1819 let module = ModuleInterface {
1820 warnings: vec![],
1821 is_internal: false,
1822 package: "some_package".into(),
1823 origin: Origin::Src,
1824 name: "a".into(),
1825 types: HashMap::new(),
1826 types_value_constructors: [(
1827 "SomeType".into(),
1828 TypeVariantConstructors {
1829 type_parameters_ids: vec![0, 1, 2],
1830 variants: vec![TypeValueConstructor {
1831 name: "One".into(),
1832 parameters: vec![],
1833 documentation: Some("Some documentation".into()),
1834 }],
1835 opaque: Opaque::Opaque,
1836 },
1837 )]
1838 .into(),
1839 accessors: HashMap::new(),
1840 values: HashMap::new(),
1841 line_numbers: LineNumbers::new(""),
1842 src_path: "some_path".into(),
1843 minimum_required_version: Version::new(0, 1, 0),
1844 type_aliases: HashMap::new(),
1845 documentation: Vec::new(),
1846 contains_echo: false,
1847 references: References::default(),
1848 };
1849
1850 assert_eq!(roundtrip(&module), module);
1851}
1852
1853#[test]
1854fn module_with_references() {
1855 let module = ModuleInterface {
1856 warnings: vec![],
1857 is_internal: false,
1858 package: "some_package".into(),
1859 origin: Origin::Src,
1860 name: "a".into(),
1861 types: HashMap::new(),
1862 types_value_constructors: HashMap::new(),
1863 accessors: HashMap::new(),
1864 values: HashMap::new(),
1865 line_numbers: LineNumbers::new(""),
1866 src_path: "some_path".into(),
1867 minimum_required_version: Version::new(0, 1, 0),
1868 type_aliases: HashMap::new(),
1869 documentation: Vec::new(),
1870 contains_echo: false,
1871 references: References {
1872 imported_modules: ["some_module".into(), "some_other_module".into()].into(),
1873 value_references: [
1874 (
1875 ("some_module".into(), "some_function".into()),
1876 vec![
1877 Reference {
1878 location: SrcSpan::new(1, 6),
1879 kind: ReferenceKind::Definition,
1880 },
1881 Reference {
1882 location: SrcSpan::new(7, 11),
1883 kind: ReferenceKind::Unqualified,
1884 },
1885 ],
1886 ),
1887 (
1888 ("some_other_module".into(), "some_constant".into()),
1889 vec![
1890 Reference {
1891 location: SrcSpan::new(6, 9),
1892 kind: ReferenceKind::Import,
1893 },
1894 Reference {
1895 location: SrcSpan::new(90, 108),
1896 kind: ReferenceKind::Unqualified,
1897 },
1898 ],
1899 ),
1900 (
1901 ("some_other_module".into(), "SomeTypeVariant".into()),
1902 vec![
1903 Reference {
1904 location: SrcSpan::new(26, 35),
1905 kind: ReferenceKind::Qualified,
1906 },
1907 Reference {
1908 location: SrcSpan::new(152, 204),
1909 kind: ReferenceKind::Qualified,
1910 },
1911 Reference {
1912 location: SrcSpan::new(0, 8),
1913 kind: ReferenceKind::Qualified,
1914 },
1915 ],
1916 ),
1917 ]
1918 .into(),
1919 type_references: [(
1920 ("some_other_module".into(), "TypeVariant".into()),
1921 vec![
1922 Reference {
1923 location: SrcSpan::new(26, 35),
1924 kind: ReferenceKind::Qualified,
1925 },
1926 Reference {
1927 location: SrcSpan::new(152, 204),
1928 kind: ReferenceKind::Unqualified,
1929 },
1930 Reference {
1931 location: SrcSpan::new(0, 8),
1932 kind: ReferenceKind::Definition,
1933 },
1934 ],
1935 )]
1936 .into(),
1937 },
1938 };
1939
1940 assert_eq!(roundtrip(&module), module);
1941}