blob: 5f9fbff6d33603e9559d79b43bd3b642a201e1df [file] [log] [blame]
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001" Test Vim9 enums
2
3source check.vim
4import './vim9.vim' as v9
5
6" Test for parsing an enum definition
7def Test_enum_parse()
8 # enum supported only in a Vim9 script
9 var lines =<< trim END
10 enum Foo
11 endenum
12 END
13 v9.CheckSourceFailure(lines, 'E1414: Enum can only be defined in Vim9 script', 1)
14
15 # First character in an enum name should be capitalized.
16 lines =<< trim END
17 vim9script
18 enum foo
19 endenum
20 END
21 v9.CheckSourceFailure(lines, 'E1415: Enum name must start with an uppercase letter: foo', 2)
22
23 # Only alphanumeric characters are supported in an enum name
24 lines =<< trim END
25 vim9script
26 enum Foo@bar
27 endenum
28 END
29 v9.CheckSourceFailure(lines, 'E1315: White space required after name: Foo@bar', 2)
30
31 # Unsupported keyword (instead of enum)
32 lines =<< trim END
33 vim9script
34 noenum Something
35 endenum
36 END
37 v9.CheckSourceFailure(lines, 'E492: Not an editor command: noenum Something', 2)
38
39 # Only the complete word "enum" should be recognized
40 lines =<< trim END
41 vim9script
42 enums Something
43 endenum
44 END
45 v9.CheckSourceFailure(lines, 'E492: Not an editor command: enums Something', 2)
46
47 # The complete "endenum" should be specified.
48 lines =<< trim END
49 vim9script
50 enum Something
51 enden
52 END
53 v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: enden', 3)
54
55 # Only the complete word "endenum" should be recognized
56 lines =<< trim END
57 vim9script
58 enum Something
59 endenums
60 END
61 v9.CheckSourceFailure(lines, 'E1420: Missing :endenum', 4)
62
63 # all lower case should be used for "enum"
64 lines =<< trim END
65 vim9script
66 Enum Something
67 endenum
68 END
69 v9.CheckSourceFailure(lines, 'E492: Not an editor command: Enum Something', 2)
70
71 # all lower case should be used for "endenum"
72 lines =<< trim END
73 vim9script
74 enum Something
75 Endenum
76 END
77 v9.CheckSourceFailure(lines, 'E1420: Missing :endenum', 4)
78
79 # Additional words after "endenum"
80 lines =<< trim END
81 vim9script
82 enum Something
83 endenum school's out
84 END
85 v9.CheckSourceFailure(lines, "E488: Trailing characters: school's out", 3)
86
87 # Additional commands after "endenum"
88 lines =<< trim END
89 vim9script
90 enum Something
91 endenum | echo 'done'
92 END
93 v9.CheckSourceFailure(lines, "E488: Trailing characters: | echo 'done'", 3)
94
95 # Try to define enum in a single command
96 lines =<< trim END
97 vim9script
98 enum Something | endenum
99 END
100 v9.CheckSourceFailure(lines, 'E1420: Missing :endenum', 3)
101
102 # Try to define an enum with the same name as an existing variable
103 lines =<< trim END
104 vim9script
105 var Something: list<number> = [1]
106 enum Something
107 endenum
108 END
109 v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "Something"', 3)
110
111 # Unsupported special character following enum name
112 lines =<< trim END
113 vim9script
114 enum Foo
115 first,
116 second : 20
117 endenum
118 END
119 v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: : 20', 4)
120
121 # Try initializing an enum item with a number
122 lines =<< trim END
123 vim9script
124 enum Foo
125 first,
126 second = 2
127 endenum
128 END
129 v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: = 2', 4)
130
131 # Try initializing an enum item with a String
132 lines =<< trim END
133 vim9script
134 enum Foo
135 first,
136 second = 'second'
137 endenum
138 defcompile
139 END
140 v9.CheckSourceFailure(lines, "E1123: Missing comma before argument: = 'second'", 4)
141
142 # Try initializing an enum item with a List
143 lines =<< trim END
144 vim9script
145 enum Foo
146 first,
147 second = []
148 endenum
149 END
150 v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: = []', 4)
151
152 # Use a colon after name
153 lines =<< trim END
154 vim9script
155 enum Foo
156
157 # first
158 first:
159 second
160 endenum
161 END
162 v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: :', 5)
163
164 # Use a '=='
165 lines =<< trim END
166 vim9script
167 enum Foo
168 first == 1
169 endenum
170 defcompile
171 END
172 v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: == 1', 3)
173
174 # Missing comma after an enum item
175 lines =<< trim END
176 vim9script
177 enum Planet
178 mercury
179 venus
180 endenum
181 END
182 v9.CheckSourceFailure(lines, 'E1419: Not a valid command in an Enum: venus', 4)
183
184 # Comma at the beginning of an item
185 lines =<< trim END
186 vim9script
187 enum Planet
188 mercury
189 ,venus
190 endenum
191 END
192 v9.CheckSourceFailure(lines, 'E1419: Not a valid command in an Enum: ,venus', 4)
193 # Space before comma
194 lines =<< trim END
195 vim9script
196 enum Planet
197 mercury ,
198 venus
199 endenum
200 END
201 v9.CheckSourceFailure(lines, "E1068: No white space allowed before ','", 3)
202
203 # No space after comma
204 lines =<< trim END
205 vim9script
206 enum Planet
207 mercury,venus
208 endenum
209 END
210 v9.CheckSourceFailure(lines, "E1069: White space required after ',': mercury,venus", 3)
211
212 # no comma between items in the same line
213 lines =<< trim END
214 vim9script
215 enum Planet
216 mercury venus earth
217 endenum
218 defcompile
219 END
220 v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: venus earth', 3)
221
222 # No space after an item and comment between items
223 lines =<< trim END
224 vim9script
225 enum Planet
226 mercury
227
228 # Venus
229 venus
230 endenum
231 END
232 v9.CheckSourceFailure(lines, 'E1419: Not a valid command in an Enum: venus', 6)
233
234 # Comma is supported for the last item
235 lines =<< trim END
236 vim9script
237 enum Planet
238 mercury,
239 venus,
240 endenum
241 var p: Planet
242 p = Planet.mercury
243 p = Planet.venus
244 END
245 v9.CheckSourceSuccess(lines)
246
247 # invalid enum value declaration
248 lines =<< trim END
249 vim9script
250 enum Fruit
251 Apple,
252 $%@
253 endenum
254 defcompile
255 END
256 v9.CheckSourceFailure(lines, 'E1418: Invalid enum value declaration: $%@', 4)
257
258 # Duplicate enum value
259 lines =<< trim END
260 vim9script
261 enum A
262 Foo,
263 Bar,
264 Foo
265 endenum
266 END
267 v9.CheckSourceFailure(lines, 'E1428: Duplicate enum value: Foo', 5)
268
269 # Duplicate enum value in the same line
270 lines =<< trim END
271 vim9script
272 enum A
273 Foo, Bar, Foo,
274 Bar
275 endenum
276 END
277 v9.CheckSourceFailure(lines, 'E1428: Duplicate enum value: Foo', 3)
278
279 # Try extending a class when defining an enum
280 lines =<< trim END
281 vim9script
282 class Foo
283 endclass
284 enum Bar extends Foo
285 endenum
286 END
287 v9.CheckSourceFailure(lines, 'E1416: Enum cannot extend a class or enum', 4)
288
289 # Try extending an enum
290 lines =<< trim END
291 vim9script
292 enum Foo
293 endenum
294 enum Bar extends Foo
295 endenum
296 END
297 v9.CheckSourceFailure(lines, 'E1416: Enum cannot extend a class or enum', 4)
298
299 # Try extending an enum using a class
300 lines =<< trim END
301 vim9script
302 enum Foo
303 endenum
304 class Bar extends Foo
305 endclass
306 END
307 v9.CheckSourceFailure(lines, 'E1354: Cannot extend Foo', 5)
308
309 # Try implementing an enum using a class
310 lines =<< trim END
311 vim9script
312 enum Foo
313 endenum
314 class Bar implements Foo
315 endclass
316 END
317 v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: Foo', 5)
318
319 # abstract method is not supported in an enum
320 lines =<< trim END
321 vim9script
322 enum Foo
323 Apple
324 abstract def Bar()
325 endenum
326 END
327 v9.CheckSourceFailure(lines, 'E1417: Abstract cannot be used in an Enum', 4)
328
329 # Define an enum without any enum values but only with an object variable
330 lines =<< trim END
331 vim9script
332 enum Foo
333 final n: number = 10
334 endenum
335 END
336 v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: n: number = 10', 3)
337enddef
338
339def Test_basic_enum()
340 # Declare a simple enum
341 var lines =<< trim END
342 vim9script
343 enum Foo
344 apple,
345 orange
346 endenum
347 var a: Foo = Foo.apple
348 var b: Foo = Foo.orange
349 assert_equal(a, Foo.apple)
350 assert_equal(b, Foo.orange)
351 END
352 v9.CheckSourceSuccess(lines)
353
354 # Multiple enums in a single line
355 lines =<< trim END
356 vim9script
357 enum Foo
358 apple, orange
359 endenum
360 assert_equal('enum<Foo>', typename(Foo.apple))
361 assert_equal('enum<Foo>', typename(Foo.orange))
362 END
363 v9.CheckSourceSuccess(lines)
364
365 # Comments and empty lines are supported between enum items
366 lines =<< trim END
367 vim9script
368 enum Foo
369 # Apple
370 apple,
371
372 # Orange
373 orange
374 endenum
375 def Fn()
376 var a: Foo = Foo.apple
377 var b: Foo = Foo.orange
378 assert_equal(a, Foo.apple)
379 assert_equal(b, Foo.orange)
380 enddef
381 END
382 v9.CheckSourceSuccess(lines)
383
384 # Try using a non-existing enum value
385 lines =<< trim END
386 vim9script
387 enum Foo
388 apple,
389 orange
390 endenum
391 var a: Foo = Foo.pear
392 END
393 v9.CheckSourceFailure(lines, 'E1422: Enum value "pear" not found in enum "Foo"', 6)
394
395 # Enum function argument
396 lines =<< trim END
397 vim9script
398 enum Foo
399 apple,
400 orange
401 endenum
402 def Fn(a: Foo): Foo
403 return a
404 enddef
405 assert_equal(Foo.apple, Fn(Foo.apple))
406 END
407 v9.CheckSourceSuccess(lines)
408
409 # Enum function argument
410 lines =<< trim END
411 vim9script
412 enum Foo
413 apple,
414 orange
415 endenum
416 def Fn(a: Foo): Foo
417 return a
418 enddef
419 Fn({})
420 END
421 v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected enum<Foo> but got dict<any>', 9)
422
423 # Returning an enum in a function returning number
424 lines =<< trim END
425 vim9script
426 enum Foo
427 apple,
428 orange
429 endenum
430 def Fn(): number
431 return Foo.orange
432 enddef
433 Fn()
434 END
435 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got enum<Foo>', 1)
436
437 # Returning a number in a function returning enum
438 lines =<< trim END
439 vim9script
440 enum Foo
441 apple,
442 orange
443 endenum
444 def Fn(): Foo
445 return 20
446 enddef
447 Fn()
448 END
449 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected enum<Foo> but got number', 1)
450
451 # Use a List of enums
452 lines =<< trim END
453 vim9script
454 enum Planet
455 Mercury,
456 Venus,
457 Earth
458 endenum
459 var l1: list<Planet> = [Planet.Mercury, Planet.Venus]
460 assert_equal(Planet.Venus, l1[1])
461 def Fn()
462 var l2: list<Planet> = [Planet.Mercury, Planet.Venus]
463 assert_equal(Planet.Venus, l2[1])
464 enddef
465 END
466 v9.CheckSourceSuccess(lines)
467
468 # Try using an enum as a value
469 lines =<< trim END
470 vim9script
471 enum Fruit
472 Apple,
473 Orange
474 endenum
475 var a = Fruit
476 END
477 v9.CheckSourceFailure(lines, 'E1421: Enum "Fruit" cannot be used as a value', 6)
478enddef
479
480" Test for type() and typename() of an enum
481def Test_enum_type()
482 var lines =<< trim END
483 vim9script
484 enum Fruit
485 Apple,
486 Orange
487 endenum
488 assert_equal('enum<Fruit>', typename(Fruit))
489 assert_equal('enum<Fruit>', typename(Fruit.Apple))
490 assert_equal(v:t_enum, type(Fruit))
491 assert_equal(v:t_enumvalue, type(Fruit.Apple))
492 assert_equal(15, type(Fruit))
493 assert_equal(16, type(Fruit.Apple))
494 END
495 v9.CheckSourceSuccess(lines)
496
497 # Assign an enum to a variable with any type
498 lines =<< trim END
499 vim9script
500 enum Fruit
501 Apple,
502 Orange
503 endenum
504 var a = Fruit.Apple
505 var b: any = Fruit.Orange
506 assert_equal('enum<Fruit>', typename(a))
507 assert_equal('enum<Fruit>', typename(b))
508 END
509 v9.CheckSourceSuccess(lines)
510enddef
511
512" Try modifying an enum or an enum item
513def Test_enum_modify()
514 # Try assigning an unsupported value to an enum
515 var lines =<< trim END
516 vim9script
517 enum Foo
518 apple
519 endenum
520 var a: Foo = 30
521 END
522 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected enum<Foo> but got number', 5)
523
524 # Try assigning an unsupported value to an enum in a function
525 lines =<< trim END
526 vim9script
527 enum Foo
528 apple
529 endenum
530 def Fn()
531 var a: Foo = 30
532 enddef
533 defcompile
534 END
535 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected enum<Foo> but got number', 1)
536
537 # Try assigning a number to an enum
538 lines =<< trim END
539 vim9script
540 enum Foo
541 apple,
542 orange
543 endenum
544 Foo = 10
545 END
546 v9.CheckSourceFailure(lines, 'E1421: Enum "Foo" cannot be used as a value', 6)
547
548 # Try assigning a number to an enum in a function
549 lines =<< trim END
550 vim9script
551 enum Foo
552 apple
553 endenum
554 def Fn()
555 Foo = 10
556 enddef
557 defcompile
558 END
559 v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected enum<Foo> but got number', 1)
560
561 # Try assigning a number to an enum value
562 lines =<< trim END
563 vim9script
564 enum Foo
565 apple
566 endenum
567 Foo.apple = 20
568 END
569 v9.CheckSourceFailure(lines, 'E1423: Enum value "Foo.apple" cannot be modified', 5)
570
571 # Try assigning a number to an enum value in a function
572 lines =<< trim END
573 vim9script
574 enum Foo
575 apple
576 endenum
577 def Fn()
578 Foo.apple = 20
579 enddef
580 defcompile
581 END
582 v9.CheckSourceFailure(lines, 'E1423: Enum value "Foo.apple" cannot be modified', 1)
583
584 # Try assigning one enum to another
585 lines =<< trim END
586 vim9script
587 enum Foo
588 endenum
589 enum Bar
590 endenum
591 Foo = Bar
592 END
593 v9.CheckSourceFailure(lines, 'E1421: Enum "Bar" cannot be used as a value', 6)
594
595 # Try assigning one enum to another in a function
596 lines =<< trim END
597 vim9script
598 enum Foo
599 endenum
600 enum Bar
601 endenum
602 def Fn()
603 Foo = Bar
604 enddef
605 defcompile
606 END
607 v9.CheckSourceFailure(lines, 'E1421: Enum "Bar" cannot be used as a value', 1)
608
609 # Try assigning one enum item to another enum item
610 lines =<< trim END
611 vim9script
612 enum Foo
613 Apple
614 endenum
615 enum Bar
616 Orange
617 endenum
618 Foo.Apple = Bar.Orange
619 END
620 v9.CheckSourceFailure(lines, 'E1423: Enum value "Foo.Apple" cannot be modified', 8)
621
622 # Try assigning one enum item to another enum item in a function
623 lines =<< trim END
624 vim9script
625 enum Foo
626 Apple
627 endenum
628 enum Bar
629 Orange
630 endenum
631 def Fn()
632 Foo.Apple = Bar.Orange
633 enddef
634 defcompile
635 END
636 v9.CheckSourceFailure(lines, 'E1423: Enum value "Foo.Apple" cannot be modified', 1)
637enddef
638
639" Test for using enum in an expression
640def Test_enum_expr()
641 var lines =<< trim END
642 vim9script
643 enum Color
644 Red, Blue, Green
645 endenum
646 var a: number = 1 + Color
647 END
648 v9.CheckSourceFailure(lines, 'E1421: Enum "Color" cannot be used as a value', 5)
649
650 lines =<< trim END
651 vim9script
652 enum Color
653 Red, Blue, Green
654 endenum
655 var a: number = 1 + Color.Red
656 END
657 v9.CheckSourceFailure(lines, 'E1424: Using an Enum "Color" as a Number', 5)
658
659 lines =<< trim END
660 vim9script
661 enum Color
662 Red, Blue, Green
663 endenum
664 var s: string = "abc" .. Color
665 END
666 v9.CheckSourceFailure(lines, 'E1421: Enum "Color" cannot be used as a value', 5)
667
668 lines =<< trim END
669 vim9script
670 enum Color
671 Red, Blue, Green
672 endenum
673 var s: string = "abc" .. Color.Red
674 END
675 v9.CheckSourceFailure(lines, 'E1425: Using an Enum "Color" as a String', 5)
676enddef
677
678" Using an enum in a lambda function
679def Test_enum_lambda()
680 var lines =<< trim END
681 vim9script
682 enum Planet
683 Mercury,
684 Venus,
685 Earth,
686 endenum
687 var Fn = (p: Planet): Planet => p
688 for [idx, v] in items([Planet.Mercury, Planet.Venus, Planet.Earth])
689 assert_equal(idx, Fn(v).ordinal)
690 endfor
691 END
692 v9.CheckSourceSuccess(lines)
693enddef
694
695" Comparison using enums
696def Test_enum_compare()
697 var lines =<< trim END
698 vim9script
699 enum Planet
700 Mercury,
701 Venus,
702 Earth,
703 endenum
704 enum Fruit
705 Apple,
706 Orange
707 endenum
708
709 var p: Planet = Planet.Venus
710 var f: Fruit = Fruit.Orange
711 assert_equal(true, p == Planet.Venus)
712 assert_equal(false, p == Planet.Earth)
713 assert_equal(false, p == f)
714 assert_equal(true, Planet.Mercury == Planet.Mercury)
715 assert_equal(true, Planet.Venus != Planet.Earth)
716 assert_equal(true, Planet.Mercury != Fruit.Apple)
717
718 def Fn1()
719 var p2: Planet = Planet.Venus
720 var f2: Fruit = Fruit.Orange
721 assert_equal(true, p2 == Planet.Venus)
722 assert_equal(false, p2 == Planet.Earth)
723 assert_equal(false, p2 == f2)
724 enddef
725 Fn1()
726
727 # comparison using "is" and "isnot"
728 assert_equal(true, p is Planet.Venus)
729 assert_equal(true, p isnot Planet.Earth)
730 assert_equal(false, p is Fruit.Orange)
731 assert_equal(true, p isnot Fruit.Orange)
732 def Fn2(arg: Planet)
733 assert_equal(true, arg is Planet.Venus)
734 assert_equal(true, arg isnot Planet.Earth)
735 assert_equal(false, arg is Fruit.Orange)
736 assert_equal(true, arg isnot Fruit.Orange)
737 enddef
738 Fn2(p)
739
740 class A
741 endclass
742 var o: A = A.new()
743 assert_equal(false, p == o)
744 END
745 v9.CheckSourceSuccess(lines)
746enddef
747
748" Test for using an enum as a default argument to a function
749def Test_enum_default_arg()
750 var lines =<< trim END
751 vim9script
752 enum Day
753 Monday, Tuesday, Wednesday
754 endenum
755 def Fn(d: Day = Day.Tuesday): Day
756 return d
757 enddef
758 assert_equal(Day.Tuesday, Fn())
759 assert_equal(Day.Wednesday, Fn(Day.Wednesday))
760 END
761 v9.CheckSourceSuccess(lines)
762enddef
763
764" Test for enum garbage collection
765func Test_enum_garbagecollect()
766 let lines =<< trim END
767 vim9script
768 enum Car
769 Honda, Ford, Tesla
770 endenum
771 assert_equal(1, Car.Ford.ordinal)
772 call test_garbagecollect_now()
773 assert_equal(1, Car.Ford.ordinal)
774 var c: Car = Car.Tesla
775 assert_equal(2, c.ordinal)
776 call test_garbagecollect_now()
777 assert_equal(2, c.ordinal)
778 END
779 call v9.CheckSourceSuccess(lines)
780
781 " garbage collection with a variable of type any
782 let lines =<< trim END
783 vim9script
784 enum Car
785 Honda, Ford, Tesla
786 endenum
787 call test_garbagecollect_now()
788 var c: any = Car.Tesla
789 call test_garbagecollect_now()
790 assert_equal(Car.Tesla, c)
791 END
792 call v9.CheckSourceSuccess(lines)
793
794 " garbage collection with function arguments and return types
795 let lines =<< trim END
796 vim9script
797 enum Car
798 Honda, Ford, Tesla
799 endenum
800 def Fn(a: Car): Car
801 assert_equal(Car.Ford, a)
802 return Car.Tesla
803 enddef
804 call test_garbagecollect_now()
805 var b: Car = Car.Ford
806 call test_garbagecollect_now()
807 assert_equal(Car.Tesla, Fn(b))
808 call test_garbagecollect_now()
809 END
810 call v9.CheckSourceSuccess(lines)
811endfunc
812
813" Test for the enum values class variable
814def Test_enum_values()
815 var lines =<< trim END
816 vim9script
817 enum Car
818 Honda, Ford, Tesla
819 endenum
820 var l: list<Car> = Car.values
821 assert_equal(Car.Ford, l[1])
822 END
823 v9.CheckSourceSuccess(lines)
824
825 # empty enum
826 lines =<< trim END
827 vim9script
828 enum Car
829 endenum
830 assert_equal([], Car.values)
831 END
832 v9.CheckSourceSuccess(lines)
833
834 # single value
835 lines =<< trim END
836 vim9script
837 enum Car
838 Honda
839 endenum
840 assert_equal([Car.Honda], Car.values)
841 END
842 v9.CheckSourceSuccess(lines)
843
844 lines =<< trim END
845 vim9script
846 enum A
847 Red,
848 Blue
849 static def GetValues(): list<A>
850 return values
851 enddef
852 endenum
853 assert_equal([A.Red, A.Blue], A.GetValues())
854 END
855 v9.CheckSourceSuccess(lines)
856
857 # Other class variables in an enum should not be added to 'values'
858 lines =<< trim END
859 vim9script
860 enum LogLevel
861 Error, Warn
862 static const x: number = 22
863 endenum
864 assert_equal([LogLevel.Error, LogLevel.Warn], LogLevel.values)
865 END
866 v9.CheckSourceSuccess(lines)
867
868 # Other class variable of enum type should not be added to 'values'
869 lines =<< trim END
870 vim9script
871 enum LogLevel
872 Error, Warn
873 static const x: LogLevel = LogLevel.Warn
874 endenum
875 assert_equal([LogLevel.Error, LogLevel.Warn], LogLevel.values)
876 END
877 v9.CheckSourceSuccess(lines)
878enddef
879
880" Test comments in enums
881def Test_enum_comments()
882 var lines =<< trim END
883 vim9script
884 enum Car # cars
885 # before enum
886 Honda, # honda
887 # before enum
888 Ford # ford
889 endenum
890 assert_equal(1, Car.Ford.ordinal)
891 END
892 v9.CheckSourceSuccess(lines)
893
894 # Test for using an unsupported comment
895 lines =<< trim END
896 vim9script
897 enum Car
898 Honda,
899 Ford,
900 #{
901 endenum
902 defcompile
903 END
904 v9.CheckSourceFailure(lines, 'E1170: Cannot use #{ to start a comment', 4)
905enddef
906
907" Test string() with enums
908def Test_enum_string()
909 var lines =<< trim END
910 vim9script
911 enum Car
912 Honda,
913 Ford
914 endenum
915 assert_equal("enum Car", string(Car))
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +0200916 assert_equal("enum Car.Honda {name: 'Honda', ordinal: 0}", string(Car.Honda))
917 END
918 v9.CheckSourceSuccess(lines)
919
920 # customized string function
921 lines =<< trim END
922 vim9script
923 enum Dir
924 North,
925 South
926
927 def string(): string
928 return $'Dir.{this.name}'
929 enddef
930 endenum
931 assert_equal('Dir.North', string(Dir.North))
932 assert_equal('Dir.South', string(Dir.South))
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100933 END
934 v9.CheckSourceSuccess(lines)
935enddef
936
937" Test for importing an enum
938def Test_enum_import()
939 var lines =<< trim END
940 vim9script
941 export enum Star
942 Gemini,
943 Orion,
944 Pisces
945 endenum
946 END
947 writefile(lines, 'Xenumexport.vim', 'D')
948
949 lines =<< trim END
950 vim9script
951 import './Xenumexport.vim' as mod
952
953 var s1: mod.Star = mod.Star.Orion
954 assert_equal(true, s1 == mod.Star.Orion)
955 assert_equal(2, mod.Star.Pisces.ordinal)
956 var l1: list<mod.Star> = mod.Star.values
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +0200957 assert_equal("enum Star.Orion {name: 'Orion', ordinal: 1}", string(l1[1]))
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100958 assert_equal(s1, l1[1])
959
960 def Fn()
961 var s2: mod.Star = mod.Star.Orion
962 assert_equal(true, s2 == mod.Star.Orion)
963 assert_equal(2, mod.Star.Pisces.ordinal)
964 var l2: list<mod.Star> = mod.Star.values
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +0200965 assert_equal("enum Star.Orion {name: 'Orion', ordinal: 1}", string(l2[1]))
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100966 assert_equal(s2, l2[1])
967 enddef
968 Fn()
969 END
970 v9.CheckScriptSuccess(lines)
971enddef
972
973" Test for using test_refcount() with enum
974def Test_enum_refcount()
975 var lines =<< trim END
976 vim9script
977 enum Foo
978 endenum
979 assert_equal(1, test_refcount(Foo))
980
981 enum Star
982 Gemini,
Yegappan Lakshmananabedca92024-03-29 10:08:23 +0100983 Orion
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100984 endenum
985 assert_equal(3, test_refcount(Star))
986 assert_equal(2, test_refcount(Star.Gemini))
987 assert_equal(2, test_refcount(Star.Orion))
988
989 var s: Star
990 assert_equal(3, test_refcount(Star))
991 assert_equal(-1, test_refcount(s))
992 s = Star.Orion
993 assert_equal(3, test_refcount(Star))
994 assert_equal(3, test_refcount(s))
995 assert_equal(2, test_refcount(Star.Gemini))
996 var t = s
997 assert_equal(3, test_refcount(Star))
998 assert_equal(4, test_refcount(s))
999 assert_equal(4, test_refcount(Star.Orion))
1000 END
1001 v9.CheckSourceSuccess(lines)
1002enddef
1003
1004" Test for defining an enum with additional object variables and methods
1005def Test_enum_enhanced()
1006 var lines =<< trim END
1007 vim9script
1008 enum Vehicle
1009 car(4, 5, 400),
1010 bus(6, 50, 800),
1011 bicycle(2, 1, 0)
1012
1013 final tires: number
1014 final passengers: number
1015 final carbonPerKilometer: number
1016
1017 def new(t: number, p: number, cpk: number)
1018 this.tires = t
1019 this.passengers = p
1020 this.carbonPerKilometer = cpk
1021 enddef
1022
1023 def CarbonFootprint(): float
1024 return round(this.carbonPerKilometer / this.passengers)
1025 enddef
1026
1027 def IsTwoWheeled(): bool
1028 return this == Vehicle.bicycle
1029 enddef
1030
1031 def CompareTo(other: Vehicle): float
1032 return this.CarbonFootprint() - other.CarbonFootprint()
1033 enddef
1034 endenum
1035
1036 var v: Vehicle = Vehicle.bus
1037 assert_equal([6, 50, 800], [v.tires, v.passengers, v.carbonPerKilometer])
1038 assert_equal(true, Vehicle.bicycle.IsTwoWheeled())
1039 assert_equal(false, Vehicle.car.IsTwoWheeled())
1040 assert_equal(16.0, Vehicle.bus.CarbonFootprint())
1041 END
1042 v9.CheckSourceSuccess(lines)
1043enddef
1044
1045" Test for the enum value 'name' variable
1046def Test_enum_name()
1047 # Check the names of enum values
1048 var lines =<< trim END
1049 vim9script
1050 enum Planet
1051 Mercury,
1052 Venus,
1053 Earth
1054 endenum
1055 assert_equal('Mercury', Planet.Mercury.name)
1056 assert_equal('Venus', Planet.Venus.name)
1057 assert_equal('Earth', Planet.Earth.name)
1058 assert_equal('string', typename(Planet.Earth.name))
1059 END
1060 v9.CheckSourceSuccess(lines)
1061
1062 # Check the name of enum items in the constructor
1063 lines =<< trim END
1064 vim9script
1065 enum Planet
1066 Mercury("Mercury"),
1067 Venus("Venus"),
1068 Earth("Earth")
1069
1070 def new(s: string)
1071 assert_equal(s, this.name)
1072 enddef
1073 endenum
1074 defcompile
1075 END
1076 v9.CheckSourceSuccess(lines)
1077
1078 # Try assigning to the name of an enum
1079 lines =<< trim END
1080 vim9script
1081 enum Fruit
1082 Apple
1083 endenum
1084 Fruit.Apple.name = 'foo'
1085 END
1086 v9.CheckSourceFailure(lines, 'E1335: Variable "name" in class "Fruit" is not writable', 5)
1087
1088 # Try assigning to the name of an enum in a function
1089 lines =<< trim END
1090 vim9script
1091 enum Fruit
1092 Apple
1093 endenum
1094 def Fn()
1095 Fruit.Apple.name = 'bar'
1096 enddef
1097 defcompile
1098 END
1099 v9.CheckSourceFailure(lines, 'E1423: Enum value "Fruit.name" cannot be modified', 1)
1100
1101 # Try to overwrite an enum value name in the enum constructor
1102 lines =<< trim END
1103 vim9script
1104 enum Planet
1105 Mercury,
1106 Venus
1107
1108 def new()
1109 this.name = 'foo'
1110 enddef
1111 endenum
1112 END
1113 v9.CheckSourceFailure(lines, 'E1427: Enum "Planet" name cannot be modified', 1)
1114
1115 # Try to declare an object variable named 'name'
1116 lines =<< trim END
1117 vim9script
1118 enum Planet
1119 Mercury
1120 var name: string
1121 endenum
1122 END
1123 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: name', 4)
1124enddef
1125
1126" Test for the enum value 'ordinal' variable
1127def Test_enum_ordinal()
1128 # Check the ordinal values of enum items
1129 var lines =<< trim END
1130 vim9script
1131 enum Planet
1132 Mercury,
1133 Venus,
1134 Earth
1135 endenum
1136 assert_equal(0, Planet.Mercury.ordinal)
1137 assert_equal(1, Planet.Venus.ordinal)
1138 assert_equal(2, Planet.Earth.ordinal)
1139 assert_equal('number', typename(Planet.Earth.ordinal))
1140 END
1141 v9.CheckSourceSuccess(lines)
1142
1143 # Check the ordinal value of enum items in the constructor
1144 lines =<< trim END
1145 vim9script
1146 enum Planet
1147 Mercury(0),
1148 Venus(1),
1149 Earth(2)
1150
1151 def new(v: number)
1152 assert_equal(v, this.ordinal)
1153 enddef
1154 endenum
1155 defcompile
1156 END
1157 v9.CheckSourceSuccess(lines)
1158
1159 # Try assigning to the ordinal value of an enum
1160 lines =<< trim END
1161 vim9script
1162 enum Fruit
1163 Apple
1164 endenum
1165 Fruit.Apple.ordinal = 20
1166 END
1167 v9.CheckSourceFailure(lines, 'E1335: Variable "ordinal" in class "Fruit" is not writable', 5)
1168
1169 # Try assigning to the ordinal value of an enum in a function
1170 lines =<< trim END
1171 vim9script
1172 enum Fruit
1173 Apple
1174 endenum
1175 def Fn()
1176 Fruit.Apple.ordinal = 20
1177 enddef
1178 defcompile
1179 END
1180 v9.CheckSourceFailure(lines, 'E1423: Enum value "Fruit.ordinal" cannot be modified', 1)
1181
1182 # Try to overwrite an enum value ordinal in the enum constructor
1183 lines =<< trim END
1184 vim9script
1185 enum Planet
1186 Mercury,
1187 Venus
1188
1189 def new()
1190 this.ordinal = 20
1191 enddef
1192 endenum
1193 END
1194 v9.CheckSourceFailure(lines, 'E1426: Enum "Planet" ordinal value cannot be modified', 1)
1195
1196 # Try to declare an object variable named 'ordinal'
1197 lines =<< trim END
1198 vim9script
1199 enum Planet
1200 Mercury
1201 var ordinal: number
1202 endenum
1203 END
1204 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: ordinal', 4)
1205enddef
1206
1207" Test for trying to create a new enum object using the constructor
1208def Test_enum_invoke_constructor()
1209 var lines =<< trim END
1210 vim9script
1211 enum Foo
1212 endenum
1213 var f: Foo = Foo.new()
1214 END
1215 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Foo"', 4)
1216
1217 lines =<< trim END
1218 vim9script
1219 enum Fruit
1220 Apple,
1221 Orange
1222 endenum
1223 var f: Fruit = Fruit.new()
1224 END
1225 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Fruit"', 6)
1226
1227 lines =<< trim END
1228 vim9script
1229 enum Fruit
1230 Apple,
1231 Orange
1232 def newFruit()
1233 enddef
1234 endenum
1235 var f: Fruit = Fruit.newFruit()
1236 END
1237 v9.CheckSourceFailure(lines, 'E1325: Method "newFruit" not found in class "Fruit"', 8)
1238
1239 lines =<< trim END
1240 vim9script
1241 enum Fruit
1242 Apple,
1243 Orange
1244 endenum
1245 def Fn()
1246 var f: Fruit = Fruit.new()
1247 enddef
1248 Fn()
1249 END
1250 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Fruit"', 1)
1251
1252 # error in the enum constructor
1253 lines =<< trim END
1254 vim9script
1255 enum Planet
1256 earth
1257 def new()
1258 x = 123
1259 enddef
1260 endenum
1261 END
1262 v9.CheckSourceFailureList(lines, ['E1100:', 'E1100:'], 1)
1263enddef
1264
1265" Test for checking "this" in an enum constructor
1266def Test_enum_this_in_constructor()
1267 var lines =<< trim END
1268 vim9script
1269 enum A
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +02001270 Red("enum A.Red {name: 'Red', ordinal: 0}"),
1271 Blue("enum A.Blue {name: 'Blue', ordinal: 1}"),
1272 Green("enum A.Green {name: 'Green', ordinal: 2}")
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001273
1274 def new(s: string)
1275 assert_equal(s, string(this))
1276 enddef
1277 endenum
1278 defcompile
1279 END
1280 v9.CheckSourceSuccess(lines)
1281enddef
1282
1283" Test for using member variables in an enum object
1284def Test_enum_object_variable()
1285 var lines =<< trim END
1286 vim9script
1287 enum Planet
1288 Jupiter(95),
1289 Saturn(146)
1290
1291 var moons: number
1292 endenum
1293 assert_equal(95, Planet.Jupiter.moons)
1294 assert_equal(146, Planet.Saturn.moons)
1295 END
1296 v9.CheckSourceSuccess(lines)
1297
1298 # Use a final object variable
1299 lines =<< trim END
1300 vim9script
1301 enum Planet
1302 Jupiter(95),
1303 Saturn(146)
1304
1305 final moons: number
1306 def new(n: number)
1307 this.moons = n
1308 enddef
1309 endenum
1310 assert_equal(95, Planet.Jupiter.moons)
1311 assert_equal(146, Planet.Saturn.moons)
1312 END
1313 v9.CheckSourceSuccess(lines)
1314
1315 # Use a const object variable
1316 lines =<< trim END
1317 vim9script
1318 enum Planet
1319 Mars(false),
1320 Jupiter(true)
1321
1322 const has_ring: bool
1323 def new(r: bool)
1324 this.has_ring = r
1325 enddef
1326 endenum
1327 assert_equal(false, Planet.Mars.has_ring)
1328 assert_equal(true, Planet.Jupiter.has_ring)
1329 END
1330 v9.CheckSourceSuccess(lines)
1331
1332 # Use a regular object variable
1333 lines =<< trim END
1334 vim9script
1335 enum Fruit
1336 Apple,
1337 Orange
1338
1339 final farm: string = 'SunValley'
1340 endenum
1341 assert_equal('SunValley', Fruit.Apple.farm)
1342 assert_equal('SunValley', Fruit.Apple.farm)
1343 END
1344 v9.CheckSourceSuccess(lines)
1345
1346 # Invoke the default constructor with an object variable
1347 lines =<< trim END
1348 vim9script
1349 enum Fruit
1350 Apple('foo'),
1351 Orange('bar')
1352
1353 final t: string
1354 endenum
1355 assert_equal('foo', Fruit.Apple.t)
1356 assert_equal('bar', Fruit.Orange.t)
1357 END
1358 v9.CheckSourceSuccess(lines)
1359
1360 # Invoke the default constructor with an argument but without the object
1361 # variable
1362 lines =<< trim END
1363 vim9script
1364 enum Fruit
1365 Apple,
1366 Orange('bar')
1367 endenum
1368 defcompile
1369 END
1370 v9.CheckSourceFailure(lines, 'E118: Too many arguments for function: new', 5)
1371
1372 # Define a default constructor with an argument, but don't pass it in when
1373 # defining the enum value
1374 lines =<< trim END
1375 vim9script
1376 enum Fruit
1377 Apple(5),
1378 Orange
1379
1380 def new(t: number)
1381 enddef
1382 endenum
1383 defcompile
1384 END
1385 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: new', 8)
1386enddef
1387
1388" Test for using a custom constructor with an enum
1389def Test_enum_custom_constructor()
1390 # space before "("
1391 var lines =<< trim END
1392 vim9script
1393 enum Fruit
1394 Apple(10),
1395 Orange (20)
1396
1397 def new(t: number)
1398 enddef
1399 endenum
1400 defcompile
1401 END
1402 v9.CheckSourceFailure(lines, "E1068: No white space allowed before '(': Orange (20)", 4)
1403
1404 # no closing ")"
1405 lines =<< trim END
1406 vim9script
1407 enum Fruit
1408 Apple(10),
1409 Orange (20
1410
1411 def new(t: number)
1412 enddef
1413 endenum
1414 defcompile
1415 END
1416 v9.CheckSourceFailure(lines, "E1068: No white space allowed before '(': Orange (20", 4)
1417
1418 # Specify constructor arguments split across multiple lines
1419 lines =<< trim END
1420 vim9script
1421 enum Fruit
1422 Apple(10,
1423 'foo'), Orange(20,
1424 'bar'),
1425 Pear(30,
1426 'baz'), Mango(40,
1427 'qux')
1428
1429 final n: number
1430 final s: string
1431 def new(t: number, str: string)
1432 this.n = t
1433 this.s = str
1434 enddef
1435 endenum
1436 defcompile
1437 assert_equal([10, 'foo'], [Fruit.Apple.n, Fruit.Apple.s])
1438 assert_equal([20, 'bar'], [Fruit.Orange.n, Fruit.Orange.s])
1439 assert_equal([30, 'baz'], [Fruit.Pear.n, Fruit.Pear.s])
1440 assert_equal([40, 'qux'], [Fruit.Mango.n, Fruit.Mango.s])
1441 END
1442 v9.CheckSourceSuccess(lines)
1443
1444 # specify multiple enums with constructor arguments in a single line
1445 lines =<< trim END
1446 vim9script
1447 enum Fruit
1448 Apple(10, 'foo'), Orange(20, 'bar'), Pear(30, 'baz'), Mango(40, 'qux')
1449 const n: number
1450 const s: string
1451 endenum
1452 defcompile
1453 assert_equal([10, 'foo'], [Fruit.Apple.n, Fruit.Apple.s])
1454 assert_equal([20, 'bar'], [Fruit.Orange.n, Fruit.Orange.s])
1455 assert_equal([30, 'baz'], [Fruit.Pear.n, Fruit.Pear.s])
1456 assert_equal([40, 'qux'], [Fruit.Mango.n, Fruit.Mango.s])
1457 END
1458 v9.CheckSourceSuccess(lines)
1459enddef
1460
1461" Test for using class variables in an enum class
1462def Test_enum_class_variable()
1463 var lines =<< trim END
1464 vim9script
1465 enum Fruit
1466 Apple,
1467 Orange
1468
1469 static var farm: string = 'SunValley'
1470 endenum
1471 assert_equal('SunValley', Fruit.farm)
1472 END
1473 v9.CheckSourceSuccess(lines)
1474enddef
1475
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +02001476" Test for converting a string to an enum value
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001477def Test_enum_eval()
1478 var lines =<< trim END
1479 vim9script
1480 enum Color
1481 Red,
1482 Blue
1483 endenum
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +02001484 var e = eval('Color.Blue')
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001485 assert_equal(Color.Blue, e)
1486 assert_equal(1, e.ordinal)
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +02001487 assert_fails("eval('Color.Green')", 'E1422: Enum value "Green" not found in enum "Color"')
1488 assert_fails("var x = eval('Color')", 'E1421: Enum "Color" cannot be used as a value')
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001489 END
1490 v9.CheckSourceSuccess(lines)
1491enddef
1492
Yegappan Lakshmananabedca92024-03-29 10:08:23 +01001493" Test for using "values" in an enum class variable
1494def Test_use_enum_values_in_class_variable()
1495 var lines =<< trim END
1496 vim9script
1497 enum Dir
1498 North, South
1499 static const dirs: list<Dir> = Dir.values
1500 endenum
1501 assert_equal([Dir.North, Dir.South], Dir.dirs)
1502 END
1503 v9.CheckSourceSuccess(lines)
1504enddef
1505
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001506" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker