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