Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

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