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