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