⭐️ A friendly language for building type-safe, scalable systems!
at main 1941 lines 62 kB view raw
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}