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