blob: a5fb26fcf393856d523518675611b904804e947c [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
911 # Test for using an unsupported comment
912 lines =<< trim END
913 vim9script
914 enum Car
915 Honda,
916 Ford,
917 #{
918 endenum
919 defcompile
920 END
921 v9.CheckSourceFailure(lines, 'E1170: Cannot use #{ to start a comment', 4)
922enddef
923
924" Test string() with enums
925def Test_enum_string()
926 var lines =<< trim END
927 vim9script
928 enum Car
929 Honda,
930 Ford
931 endenum
932 assert_equal("enum Car", string(Car))
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +0200933 assert_equal("enum Car.Honda {name: 'Honda', ordinal: 0}", string(Car.Honda))
934 END
935 v9.CheckSourceSuccess(lines)
936
937 # customized string function
938 lines =<< trim END
939 vim9script
940 enum Dir
941 North,
942 South
943
944 def string(): string
945 return $'Dir.{this.name}'
946 enddef
947 endenum
948 assert_equal('Dir.North', string(Dir.North))
949 assert_equal('Dir.South', string(Dir.South))
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100950 END
951 v9.CheckSourceSuccess(lines)
952enddef
953
954" Test for importing an enum
955def Test_enum_import()
956 var lines =<< trim END
957 vim9script
958 export enum Star
959 Gemini,
960 Orion,
961 Pisces
962 endenum
963 END
964 writefile(lines, 'Xenumexport.vim', 'D')
965
966 lines =<< trim END
967 vim9script
968 import './Xenumexport.vim' as mod
969
970 var s1: mod.Star = mod.Star.Orion
971 assert_equal(true, s1 == mod.Star.Orion)
972 assert_equal(2, mod.Star.Pisces.ordinal)
973 var l1: list<mod.Star> = mod.Star.values
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +0200974 assert_equal("enum Star.Orion {name: 'Orion', ordinal: 1}", string(l1[1]))
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100975 assert_equal(s1, l1[1])
976
977 def Fn()
978 var s2: mod.Star = mod.Star.Orion
979 assert_equal(true, s2 == mod.Star.Orion)
980 assert_equal(2, mod.Star.Pisces.ordinal)
981 var l2: list<mod.Star> = mod.Star.values
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +0200982 assert_equal("enum Star.Orion {name: 'Orion', ordinal: 1}", string(l2[1]))
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +0100983 assert_equal(s2, l2[1])
984 enddef
985 Fn()
986 END
987 v9.CheckScriptSuccess(lines)
988enddef
989
990" Test for using test_refcount() with enum
991def Test_enum_refcount()
992 var lines =<< trim END
993 vim9script
994 enum Foo
995 endenum
996 assert_equal(1, test_refcount(Foo))
997
998 enum Star
999 Gemini,
Yegappan Lakshmananabedca92024-03-29 10:08:23 +01001000 Orion
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001001 endenum
1002 assert_equal(3, test_refcount(Star))
1003 assert_equal(2, test_refcount(Star.Gemini))
1004 assert_equal(2, test_refcount(Star.Orion))
1005
1006 var s: Star
1007 assert_equal(3, test_refcount(Star))
1008 assert_equal(-1, test_refcount(s))
1009 s = Star.Orion
1010 assert_equal(3, test_refcount(Star))
1011 assert_equal(3, test_refcount(s))
1012 assert_equal(2, test_refcount(Star.Gemini))
1013 var t = s
1014 assert_equal(3, test_refcount(Star))
1015 assert_equal(4, test_refcount(s))
1016 assert_equal(4, test_refcount(Star.Orion))
1017 END
1018 v9.CheckSourceSuccess(lines)
1019enddef
1020
1021" Test for defining an enum with additional object variables and methods
1022def Test_enum_enhanced()
1023 var lines =<< trim END
1024 vim9script
1025 enum Vehicle
1026 car(4, 5, 400),
1027 bus(6, 50, 800),
1028 bicycle(2, 1, 0)
1029
1030 final tires: number
1031 final passengers: number
1032 final carbonPerKilometer: number
1033
1034 def new(t: number, p: number, cpk: number)
1035 this.tires = t
1036 this.passengers = p
1037 this.carbonPerKilometer = cpk
1038 enddef
1039
1040 def CarbonFootprint(): float
1041 return round(this.carbonPerKilometer / this.passengers)
1042 enddef
1043
1044 def IsTwoWheeled(): bool
1045 return this == Vehicle.bicycle
1046 enddef
1047
1048 def CompareTo(other: Vehicle): float
1049 return this.CarbonFootprint() - other.CarbonFootprint()
1050 enddef
1051 endenum
1052
1053 var v: Vehicle = Vehicle.bus
1054 assert_equal([6, 50, 800], [v.tires, v.passengers, v.carbonPerKilometer])
1055 assert_equal(true, Vehicle.bicycle.IsTwoWheeled())
1056 assert_equal(false, Vehicle.car.IsTwoWheeled())
1057 assert_equal(16.0, Vehicle.bus.CarbonFootprint())
1058 END
1059 v9.CheckSourceSuccess(lines)
1060enddef
1061
1062" Test for the enum value 'name' variable
1063def Test_enum_name()
1064 # Check the names of enum values
1065 var lines =<< trim END
1066 vim9script
1067 enum Planet
1068 Mercury,
1069 Venus,
1070 Earth
1071 endenum
1072 assert_equal('Mercury', Planet.Mercury.name)
1073 assert_equal('Venus', Planet.Venus.name)
1074 assert_equal('Earth', Planet.Earth.name)
1075 assert_equal('string', typename(Planet.Earth.name))
1076 END
1077 v9.CheckSourceSuccess(lines)
1078
1079 # Check the name of enum items in the constructor
1080 lines =<< trim END
1081 vim9script
1082 enum Planet
1083 Mercury("Mercury"),
1084 Venus("Venus"),
1085 Earth("Earth")
1086
1087 def new(s: string)
1088 assert_equal(s, this.name)
1089 enddef
1090 endenum
1091 defcompile
1092 END
1093 v9.CheckSourceSuccess(lines)
1094
1095 # Try assigning to the name of an enum
1096 lines =<< trim END
1097 vim9script
1098 enum Fruit
1099 Apple
1100 endenum
1101 Fruit.Apple.name = 'foo'
1102 END
1103 v9.CheckSourceFailure(lines, 'E1335: Variable "name" in class "Fruit" is not writable', 5)
1104
1105 # Try assigning to the name of an enum in a function
1106 lines =<< trim END
1107 vim9script
1108 enum Fruit
1109 Apple
1110 endenum
1111 def Fn()
1112 Fruit.Apple.name = 'bar'
1113 enddef
1114 defcompile
1115 END
1116 v9.CheckSourceFailure(lines, 'E1423: Enum value "Fruit.name" cannot be modified', 1)
1117
1118 # Try to overwrite an enum value name in the enum constructor
1119 lines =<< trim END
1120 vim9script
1121 enum Planet
1122 Mercury,
1123 Venus
1124
1125 def new()
1126 this.name = 'foo'
1127 enddef
1128 endenum
1129 END
1130 v9.CheckSourceFailure(lines, 'E1427: Enum "Planet" name cannot be modified', 1)
1131
1132 # Try to declare an object variable named 'name'
1133 lines =<< trim END
1134 vim9script
1135 enum Planet
1136 Mercury
1137 var name: string
1138 endenum
1139 END
1140 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: name', 4)
1141enddef
1142
1143" Test for the enum value 'ordinal' variable
1144def Test_enum_ordinal()
1145 # Check the ordinal values of enum items
1146 var lines =<< trim END
1147 vim9script
1148 enum Planet
1149 Mercury,
1150 Venus,
1151 Earth
1152 endenum
1153 assert_equal(0, Planet.Mercury.ordinal)
1154 assert_equal(1, Planet.Venus.ordinal)
1155 assert_equal(2, Planet.Earth.ordinal)
1156 assert_equal('number', typename(Planet.Earth.ordinal))
1157 END
1158 v9.CheckSourceSuccess(lines)
1159
1160 # Check the ordinal value of enum items in the constructor
1161 lines =<< trim END
1162 vim9script
1163 enum Planet
1164 Mercury(0),
1165 Venus(1),
1166 Earth(2)
1167
1168 def new(v: number)
1169 assert_equal(v, this.ordinal)
1170 enddef
1171 endenum
1172 defcompile
1173 END
1174 v9.CheckSourceSuccess(lines)
1175
1176 # Try assigning to the ordinal value of an enum
1177 lines =<< trim END
1178 vim9script
1179 enum Fruit
1180 Apple
1181 endenum
1182 Fruit.Apple.ordinal = 20
1183 END
1184 v9.CheckSourceFailure(lines, 'E1335: Variable "ordinal" in class "Fruit" is not writable', 5)
1185
1186 # Try assigning to the ordinal value of an enum in a function
1187 lines =<< trim END
1188 vim9script
1189 enum Fruit
1190 Apple
1191 endenum
1192 def Fn()
1193 Fruit.Apple.ordinal = 20
1194 enddef
1195 defcompile
1196 END
1197 v9.CheckSourceFailure(lines, 'E1423: Enum value "Fruit.ordinal" cannot be modified', 1)
1198
1199 # Try to overwrite an enum value ordinal in the enum constructor
1200 lines =<< trim END
1201 vim9script
1202 enum Planet
1203 Mercury,
1204 Venus
1205
1206 def new()
1207 this.ordinal = 20
1208 enddef
1209 endenum
1210 END
1211 v9.CheckSourceFailure(lines, 'E1426: Enum "Planet" ordinal value cannot be modified', 1)
1212
1213 # Try to declare an object variable named 'ordinal'
1214 lines =<< trim END
1215 vim9script
1216 enum Planet
1217 Mercury
1218 var ordinal: number
1219 endenum
1220 END
1221 v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: ordinal', 4)
1222enddef
1223
1224" Test for trying to create a new enum object using the constructor
1225def Test_enum_invoke_constructor()
1226 var lines =<< trim END
1227 vim9script
1228 enum Foo
1229 endenum
1230 var f: Foo = Foo.new()
1231 END
1232 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Foo"', 4)
1233
1234 lines =<< trim END
1235 vim9script
1236 enum Fruit
1237 Apple,
1238 Orange
1239 endenum
1240 var f: Fruit = Fruit.new()
1241 END
1242 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Fruit"', 6)
1243
1244 lines =<< trim END
1245 vim9script
1246 enum Fruit
1247 Apple,
1248 Orange
1249 def newFruit()
1250 enddef
1251 endenum
1252 var f: Fruit = Fruit.newFruit()
1253 END
1254 v9.CheckSourceFailure(lines, 'E1325: Method "newFruit" not found in class "Fruit"', 8)
1255
1256 lines =<< trim END
1257 vim9script
1258 enum Fruit
1259 Apple,
1260 Orange
1261 endenum
1262 def Fn()
1263 var f: Fruit = Fruit.new()
1264 enddef
1265 Fn()
1266 END
1267 v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Fruit"', 1)
1268
1269 # error in the enum constructor
1270 lines =<< trim END
1271 vim9script
1272 enum Planet
1273 earth
1274 def new()
1275 x = 123
1276 enddef
1277 endenum
1278 END
1279 v9.CheckSourceFailureList(lines, ['E1100:', 'E1100:'], 1)
1280enddef
1281
1282" Test for checking "this" in an enum constructor
1283def Test_enum_this_in_constructor()
1284 var lines =<< trim END
1285 vim9script
1286 enum A
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +02001287 Red("enum A.Red {name: 'Red', ordinal: 0}"),
1288 Blue("enum A.Blue {name: 'Blue', ordinal: 1}"),
1289 Green("enum A.Green {name: 'Green', ordinal: 2}")
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001290
1291 def new(s: string)
1292 assert_equal(s, string(this))
1293 enddef
1294 endenum
1295 defcompile
1296 END
1297 v9.CheckSourceSuccess(lines)
1298enddef
1299
1300" Test for using member variables in an enum object
1301def Test_enum_object_variable()
1302 var lines =<< trim END
1303 vim9script
1304 enum Planet
1305 Jupiter(95),
1306 Saturn(146)
1307
1308 var moons: number
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 final object variable
1316 lines =<< trim END
1317 vim9script
1318 enum Planet
1319 Jupiter(95),
1320 Saturn(146)
1321
1322 final moons: number
1323 def new(n: number)
1324 this.moons = n
1325 enddef
1326 endenum
1327 assert_equal(95, Planet.Jupiter.moons)
1328 assert_equal(146, Planet.Saturn.moons)
1329 END
1330 v9.CheckSourceSuccess(lines)
1331
1332 # Use a const object variable
1333 lines =<< trim END
1334 vim9script
1335 enum Planet
1336 Mars(false),
1337 Jupiter(true)
1338
1339 const has_ring: bool
1340 def new(r: bool)
1341 this.has_ring = r
1342 enddef
1343 endenum
1344 assert_equal(false, Planet.Mars.has_ring)
1345 assert_equal(true, Planet.Jupiter.has_ring)
1346 END
1347 v9.CheckSourceSuccess(lines)
1348
1349 # Use a regular object variable
1350 lines =<< trim END
1351 vim9script
1352 enum Fruit
1353 Apple,
1354 Orange
1355
1356 final farm: string = 'SunValley'
1357 endenum
1358 assert_equal('SunValley', Fruit.Apple.farm)
1359 assert_equal('SunValley', Fruit.Apple.farm)
1360 END
1361 v9.CheckSourceSuccess(lines)
1362
1363 # Invoke the default constructor with an object variable
1364 lines =<< trim END
1365 vim9script
1366 enum Fruit
1367 Apple('foo'),
1368 Orange('bar')
1369
1370 final t: string
1371 endenum
1372 assert_equal('foo', Fruit.Apple.t)
1373 assert_equal('bar', Fruit.Orange.t)
1374 END
1375 v9.CheckSourceSuccess(lines)
1376
1377 # Invoke the default constructor with an argument but without the object
1378 # variable
1379 lines =<< trim END
1380 vim9script
1381 enum Fruit
1382 Apple,
1383 Orange('bar')
1384 endenum
1385 defcompile
1386 END
1387 v9.CheckSourceFailure(lines, 'E118: Too many arguments for function: new', 5)
1388
1389 # Define a default constructor with an argument, but don't pass it in when
1390 # defining the enum value
1391 lines =<< trim END
1392 vim9script
1393 enum Fruit
1394 Apple(5),
1395 Orange
1396
1397 def new(t: number)
1398 enddef
1399 endenum
1400 defcompile
1401 END
1402 v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: new', 8)
1403enddef
1404
1405" Test for using a custom constructor with an enum
1406def Test_enum_custom_constructor()
1407 # space before "("
1408 var lines =<< trim END
1409 vim9script
1410 enum Fruit
1411 Apple(10),
1412 Orange (20)
1413
1414 def new(t: number)
1415 enddef
1416 endenum
1417 defcompile
1418 END
1419 v9.CheckSourceFailure(lines, "E1068: No white space allowed before '(': Orange (20)", 4)
1420
1421 # no closing ")"
1422 lines =<< trim END
1423 vim9script
1424 enum Fruit
1425 Apple(10),
1426 Orange (20
1427
1428 def new(t: number)
1429 enddef
1430 endenum
1431 defcompile
1432 END
1433 v9.CheckSourceFailure(lines, "E1068: No white space allowed before '(': Orange (20", 4)
1434
1435 # Specify constructor arguments split across multiple lines
1436 lines =<< trim END
1437 vim9script
1438 enum Fruit
1439 Apple(10,
1440 'foo'), Orange(20,
1441 'bar'),
1442 Pear(30,
1443 'baz'), Mango(40,
1444 'qux')
1445
1446 final n: number
1447 final s: string
1448 def new(t: number, str: string)
1449 this.n = t
1450 this.s = str
1451 enddef
1452 endenum
1453 defcompile
1454 assert_equal([10, 'foo'], [Fruit.Apple.n, Fruit.Apple.s])
1455 assert_equal([20, 'bar'], [Fruit.Orange.n, Fruit.Orange.s])
1456 assert_equal([30, 'baz'], [Fruit.Pear.n, Fruit.Pear.s])
1457 assert_equal([40, 'qux'], [Fruit.Mango.n, Fruit.Mango.s])
1458 END
1459 v9.CheckSourceSuccess(lines)
1460
1461 # specify multiple enums with constructor arguments in a single line
1462 lines =<< trim END
1463 vim9script
1464 enum Fruit
1465 Apple(10, 'foo'), Orange(20, 'bar'), Pear(30, 'baz'), Mango(40, 'qux')
1466 const n: number
1467 const s: string
1468 endenum
1469 defcompile
1470 assert_equal([10, 'foo'], [Fruit.Apple.n, Fruit.Apple.s])
1471 assert_equal([20, 'bar'], [Fruit.Orange.n, Fruit.Orange.s])
1472 assert_equal([30, 'baz'], [Fruit.Pear.n, Fruit.Pear.s])
1473 assert_equal([40, 'qux'], [Fruit.Mango.n, Fruit.Mango.s])
1474 END
1475 v9.CheckSourceSuccess(lines)
1476enddef
1477
1478" Test for using class variables in an enum class
1479def Test_enum_class_variable()
1480 var lines =<< trim END
1481 vim9script
1482 enum Fruit
1483 Apple,
1484 Orange
1485
1486 static var farm: string = 'SunValley'
1487 endenum
1488 assert_equal('SunValley', Fruit.farm)
1489 END
1490 v9.CheckSourceSuccess(lines)
1491enddef
1492
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +02001493" Test for converting a string to an enum value
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001494def Test_enum_eval()
1495 var lines =<< trim END
1496 vim9script
1497 enum Color
1498 Red,
1499 Blue
1500 endenum
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +02001501 var e = eval('Color.Blue')
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001502 assert_equal(Color.Blue, e)
1503 assert_equal(1, e.ordinal)
Yegappan Lakshmanan3cf121e2024-03-31 18:45:35 +02001504 assert_fails("eval('Color.Green')", 'E1422: Enum value "Green" not found in enum "Color"')
1505 assert_fails("var x = eval('Color')", 'E1421: Enum "Color" cannot be used as a value')
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001506 END
1507 v9.CheckSourceSuccess(lines)
1508enddef
1509
Yegappan Lakshmananabedca92024-03-29 10:08:23 +01001510" Test for using "values" in an enum class variable
1511def Test_use_enum_values_in_class_variable()
1512 var lines =<< trim END
1513 vim9script
1514 enum Dir
1515 North, South
1516 static const dirs: list<Dir> = Dir.values
1517 endenum
1518 assert_equal([Dir.North, Dir.South], Dir.dirs)
1519 END
1520 v9.CheckSourceSuccess(lines)
1521enddef
1522
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +02001523" Test for using lambda block in enums
1524def Test_lambda_block_in_enum()
1525 # This used to crash Vim
1526 var lines =<< trim END
1527 vim9script
1528 enum IdEnum1
1529 ID1
1530 const Id: func(number): number = (num: number): number => {
1531 # Return a ID
1532 return num / 2
1533 }
1534 endenum
1535 assert_equal(5, IdEnum1.ID1.Id(10))
1536 END
1537 v9.CheckScriptSuccess(lines)
1538
1539 # This used to crash Vim
1540 lines =<< trim END
1541 vim9script
1542 enum IdEnum2
1543 ID1
1544 static const Id: func(number): number = (num: number): number => {
1545 # Return a ID
1546 return num + 2
1547 }
1548 endenum
1549 assert_equal(12, IdEnum2.Id(10))
1550 END
1551 v9.CheckScriptSuccess(lines)
1552enddef
1553
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001554" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker