Merge pull request #69590 from anvilfolk/enums

GDScript enum fixes & refactor
This commit is contained in:
Rémi Verschelde
2023-01-09 23:10:37 +01:00
61 changed files with 699 additions and 97 deletions

View File

@@ -0,0 +1,3 @@
enum { V }
func test():
V = 1

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot assign a new value to a constant.

View File

@@ -0,0 +1,3 @@
enum NamedEnum { V }
func test():
NamedEnum.V = 1

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot assign a new value to a constant.

View File

@@ -0,0 +1,5 @@
enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
enum MyOtherEnum { OTHER_ENUM_VALUE_1, OTHER_ENUM_VALUE_2, OTHER_ENUM_VALUE_3 }
func test():
print(MyOtherEnum.OTHER_ENUM_VALUE_3 as MyEnum)

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Invalid cast. Enum "cast_enum_bad_enum.gd::MyEnum" does not have value corresponding to "MyOtherEnum.OTHER_ENUM_VALUE_3" (2).

View File

@@ -0,0 +1,4 @@
enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
func test():
print(2 as MyEnum)

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Invalid cast. Enum "cast_enum_bad_int.gd::MyEnum" does not have enum value 2.

View File

@@ -0,0 +1,4 @@
enum Enum {V1, V2}
func test():
Enum.clear()

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-const Dictionary function "clear()" on enum "Enum".

View File

@@ -0,0 +1,4 @@
enum Enum {V1, V2}
func test():
var bad = Enum.V3

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot find member "V3" in base "enum_bad_value.gd::Enum".

View File

@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot assign a value of type "MyOtherEnum (enum)" to a target of type "MyEnum (enum)".
Value of type "enum_class_var_assign_with_wrong_enum_type.gd::MyOtherEnum" cannot be assigned to a variable of type "enum_class_var_assign_with_wrong_enum_type.gd::MyEnum".

View File

@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot assign a value of type MyOtherEnum (enum) to variable "class_var" with specified type MyEnum (enum).
Cannot assign a value of type enum_class_var_init_with_wrong_enum_type.gd::MyOtherEnum to variable "class_var" with specified type enum_class_var_init_with_wrong_enum_type.gd::MyEnum.

View File

@@ -0,0 +1,5 @@
enum Enum {V1, V2}
func test():
var Enum2 = Enum
Enum2.clear()

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-const Dictionary function "clear()" on enum "Enum".

View File

@@ -0,0 +1,8 @@
enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
enum MyOtherEnum { OTHER_ENUM_VALUE_1, OTHER_ENUM_VALUE_2 }
func enum_func(e : MyEnum) -> void:
print(e)
func test():
enum_func(MyOtherEnum.OTHER_ENUM_VALUE_1)

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Invalid argument for "enum_func()" function: argument 1 should be "enum_function_parameter_wrong_type.gd::MyEnum" but is "enum_function_parameter_wrong_type.gd::MyOtherEnum".

View File

@@ -0,0 +1,8 @@
enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
enum MyOtherEnum { OTHER_ENUM_VALUE_1, OTHER_ENUM_VALUE_2 }
func enum_func() -> MyEnum:
return MyOtherEnum.OTHER_ENUM_VALUE_1
func test():
print(enum_func())

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot return value of type "enum_function_return_wrong_type.gd::MyOtherEnum" because the function return type is "enum_function_return_wrong_type.gd::MyEnum".

View File

@@ -0,0 +1,10 @@
enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
class InnerClass:
enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
func test():
var local_var: MyEnum = MyEnum.ENUM_VALUE_1
print(local_var)
local_var = InnerClass.MyEnum.ENUM_VALUE_2
print(local_var)

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Value of type "enum_local_var_assign_outer_with_wrong_enum_type.gd::InnerClass::MyEnum" cannot be assigned to a variable of type "enum_local_var_assign_outer_with_wrong_enum_type.gd::MyEnum".

View File

@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot assign a value of type "MyOtherEnum (enum)" to a target of type "MyEnum (enum)".
Value of type "enum_local_var_assign_with_wrong_enum_type.gd::MyOtherEnum" cannot be assigned to a variable of type "enum_local_var_assign_with_wrong_enum_type.gd::MyEnum".

View File

@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot assign a value of type MyOtherEnum (enum) to variable "local_var" with specified type MyEnum (enum).
Cannot assign a value of type enum_local_var_init_with_wrong_enum_type.gd::MyOtherEnum to variable "local_var" with specified type enum_local_var_init_with_wrong_enum_type.gd::MyEnum.

View File

@@ -0,0 +1,2 @@
func test():
var _bad = TileSet.TileShape.THIS_DOES_NOT_EXIST

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot find member "THIS_DOES_NOT_EXIST" in base "TileSet::TileShape".

View File

@@ -0,0 +1,6 @@
enum MyEnum { VALUE_A, VALUE_B, VALUE_C = 42 }
func test():
const P = preload("../features/enum_value_from_parent.gd")
var local_var: MyEnum
local_var = P.VALUE_B
print(local_var)

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Value of type "enum_value_from_parent.gd::<anonymous enum>" cannot be assigned to a variable of type "enum_preload_unnamed_assign_to_named.gd::MyEnum".

View File

@@ -0,0 +1,8 @@
class A:
enum { V }
class B extends A:
enum { V }
func test():
pass

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
The member "V" already exists in parent class A.

View File

@@ -0,0 +1,7 @@
enum { V }
class InnerClass:
enum { V }
func test():
pass

View File

@@ -0,0 +1,2 @@
GDTEST_PARSER_ERROR
Name "V" is already used as a class enum value.

View File

@@ -0,0 +1,7 @@
enum { ENUM_VALUE_1, ENUM_VALUE_2 }
enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
func test():
var local_var: MyEnum = ENUM_VALUE_1
print(local_var)

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot assign a value of type enum_unnamed_assign_to_named.gd::<anonymous enum> to variable "local_var" with specified type enum_unnamed_assign_to_named.gd::MyEnum.

View File

@@ -0,0 +1,2 @@
func test():
TileSet.this_does_not_exist # Does not exist

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot find member "this_does_not_exist" in base "TileSet".

View File

@@ -0,0 +1,6 @@
enum LocalNamed { VALUE_A, VALUE_B, VALUE_C = 42 }
func test():
const P = preload("../features/enum_from_outer.gd")
var x : LocalNamed
x = P.Named.VALUE_A

View File

@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Value of type "enum_from_outer.gd::Named" cannot be assigned to a variable of type "preload_enum_error.gd::LocalNamed".

View File

@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot assign a value of type "String" to a target of type "int".
Value of type "String" cannot be assigned to a variable of type "int".

View File

@@ -0,0 +1,29 @@
class_name EnumAccessOuterClass
class InnerClass:
enum MyEnum { V0, V2, V1 }
static func print_enums():
print("Inner - Inner")
print(MyEnum.V0, MyEnum.V1, MyEnum.V2)
print(InnerClass.MyEnum.V0, InnerClass.MyEnum.V1, InnerClass.MyEnum.V2)
print(EnumAccessOuterClass.InnerClass.MyEnum.V0, EnumAccessOuterClass.InnerClass.MyEnum.V1, EnumAccessOuterClass.InnerClass.MyEnum.V2)
print("Inner - Outer")
print(EnumAccessOuterClass.MyEnum.V0, EnumAccessOuterClass.MyEnum.V1, EnumAccessOuterClass.MyEnum.V2)
enum MyEnum { V0, V1, V2 }
func print_enums():
print("Outer - Outer")
print(MyEnum.V0, MyEnum.V1, MyEnum.V2)
print(EnumAccessOuterClass.MyEnum.V0, EnumAccessOuterClass.MyEnum.V1, EnumAccessOuterClass.MyEnum.V2)
print("Outer - Inner")
print(InnerClass.MyEnum.V0, InnerClass.MyEnum.V1, InnerClass.MyEnum.V2)
print(EnumAccessOuterClass.InnerClass.MyEnum.V0, EnumAccessOuterClass.InnerClass.MyEnum.V1, EnumAccessOuterClass.InnerClass.MyEnum.V2)
func test():
print_enums()
InnerClass.print_enums()

View File

@@ -0,0 +1,13 @@
GDTEST_OK
Outer - Outer
012
012
Outer - Inner
021
021
Inner - Inner
021
021
021
Inner - Outer
012

View File

@@ -0,0 +1,13 @@
enum Enum {V1, V2}
func test():
var enumAsDict : Dictionary = Enum.duplicate()
var enumAsVariant = Enum.duplicate()
print(Enum.has("V1"))
print(enumAsDict.has("V1"))
print(enumAsVariant.has("V1"))
enumAsDict.clear()
enumAsVariant.clear()
print(Enum.has("V1"))
print(enumAsDict.has("V1"))
print(enumAsVariant.has("V1"))

View File

@@ -0,0 +1,7 @@
GDTEST_OK
true
true
true
true
false
false

View File

@@ -0,0 +1,13 @@
class A:
enum Named { VALUE_A, VALUE_B, VALUE_C = 42 }
class B extends A:
var a = Named.VALUE_A
var b = Named.VALUE_B
var c = Named.VALUE_C
func test():
var test_instance = B.new()
prints("a", test_instance.a, test_instance.a == A.Named.VALUE_A)
prints("b", test_instance.b, test_instance.b == A.Named.VALUE_B)
prints("c", test_instance.c, test_instance.c == B.Named.VALUE_C)

View File

@@ -1,5 +1,3 @@
extends Node
enum Named { VALUE_A, VALUE_B, VALUE_C = 42 }
class Test:

View File

@@ -0,0 +1,4 @@
GDTEST_OK
a 0 true
b 1 true
c 42 true

View File

@@ -0,0 +1,112 @@
class_name EnumFunctionTypecheckOuterClass
enum MyEnum { V0, V1, V2 }
class InnerClass:
enum MyEnum { V0, V2, V1 }
func inner_inner_no_class(e : MyEnum) -> MyEnum:
print(e)
return e
func inner_inner_class(e : InnerClass.MyEnum) -> InnerClass.MyEnum:
print(e)
return e
func inner_inner_class_class(e : EnumFunctionTypecheckOuterClass.InnerClass.MyEnum) -> EnumFunctionTypecheckOuterClass.InnerClass.MyEnum:
print(e)
return e
func inner_outer(e : EnumFunctionTypecheckOuterClass.MyEnum) -> EnumFunctionTypecheckOuterClass.MyEnum:
print(e)
return e
func test():
var _d
print("Inner")
var o := EnumFunctionTypecheckOuterClass.new()
_d = o.outer_outer_no_class(EnumFunctionTypecheckOuterClass.MyEnum.V1)
print()
_d = o.outer_outer_class(EnumFunctionTypecheckOuterClass.MyEnum.V1)
print()
_d = o.outer_inner_class(MyEnum.V1)
_d = o.outer_inner_class(InnerClass.MyEnum.V1)
_d = o.outer_inner_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
print()
_d = o.outer_inner_class_class(MyEnum.V1)
_d = o.outer_inner_class_class(InnerClass.MyEnum.V1)
_d = o.outer_inner_class_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
print()
print()
_d = inner_inner_no_class(MyEnum.V1)
_d = inner_inner_no_class(InnerClass.MyEnum.V1)
_d = inner_inner_no_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
print()
_d = inner_inner_class(MyEnum.V1)
_d = inner_inner_class(InnerClass.MyEnum.V1)
_d = inner_inner_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
print()
_d = inner_inner_class_class(MyEnum.V1)
_d = inner_inner_class_class(InnerClass.MyEnum.V1)
_d = inner_inner_class_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
print()
_d = inner_outer(EnumFunctionTypecheckOuterClass.MyEnum.V1)
print()
print()
func outer_outer_no_class(e : MyEnum) -> MyEnum:
print(e)
return e
func outer_outer_class(e : EnumFunctionTypecheckOuterClass.MyEnum) -> EnumFunctionTypecheckOuterClass.MyEnum:
print(e)
return e
func outer_inner_class(e : InnerClass.MyEnum) -> InnerClass.MyEnum:
print(e)
return e
func outer_inner_class_class(e : EnumFunctionTypecheckOuterClass.InnerClass.MyEnum) -> EnumFunctionTypecheckOuterClass.InnerClass.MyEnum:
print(e)
return e
func test():
var _d
print("Outer")
_d = outer_outer_no_class(MyEnum.V1)
_d = outer_outer_no_class(EnumFunctionTypecheckOuterClass.MyEnum.V1)
print()
_d = outer_outer_class(MyEnum.V1)
_d = outer_outer_class(EnumFunctionTypecheckOuterClass.MyEnum.V1)
print()
_d = outer_inner_class(InnerClass.MyEnum.V1)
_d = outer_inner_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
print()
_d = outer_inner_class_class(InnerClass.MyEnum.V1)
_d = outer_inner_class_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
print()
print()
var i := EnumFunctionTypecheckOuterClass.InnerClass.new()
_d = i.inner_inner_no_class(InnerClass.MyEnum.V1)
_d = i.inner_inner_no_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
print()
_d = i.inner_inner_class(InnerClass.MyEnum.V1)
_d = i.inner_inner_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
print()
_d = i.inner_inner_class_class(InnerClass.MyEnum.V1)
_d = i.inner_inner_class_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
print()
_d = i.inner_outer(MyEnum.V1)
_d = i.inner_outer(EnumFunctionTypecheckOuterClass.MyEnum.V1)
print()
print()
i.test()

View File

@@ -0,0 +1,55 @@
GDTEST_OK
Outer
1
1
1
1
2
2
2
2
2
2
2
2
2
2
1
1
Inner
1
1
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
1

View File

@@ -0,0 +1,16 @@
const A := 1
enum { B }
enum NamedEnum { C }
class Parent:
const D := 2
enum { E }
enum NamedEnum2 { F }
class Child extends Parent:
enum TestEnum { A, B, C, D, E, F, Node, Object, Child, Parent}
func test():
print(A, B, NamedEnum.C, Parent.D, Parent.E, Parent.NamedEnum2.F)
print(Child.TestEnum.A, Child.TestEnum.B, Child.TestEnum.C, Child.TestEnum.D, Child.TestEnum.E, Child.TestEnum.F)
print(Child.TestEnum.Node, Child.TestEnum.Object, Child.TestEnum.Child, Child.TestEnum.Parent)

View File

@@ -0,0 +1,4 @@
GDTEST_OK
100200
012345
6789

View File

@@ -0,0 +1,19 @@
func print_enum(e : TileSet.TileShape) -> TileSet.TileShape:
print(e)
return e
func test():
var v : TileSet.TileShape
v = TileSet.TILE_SHAPE_SQUARE
v = print_enum(v)
v = print_enum(TileSet.TILE_SHAPE_SQUARE)
v = TileSet.TileShape.TILE_SHAPE_SQUARE
v = print_enum(v)
v = print_enum(TileSet.TileShape.TILE_SHAPE_SQUARE)
v = TileSet.TILE_SHAPE_ISOMETRIC
v = print_enum(v)
v = print_enum(TileSet.TILE_SHAPE_ISOMETRIC)
v = TileSet.TileShape.TILE_SHAPE_ISOMETRIC
v = print_enum(v)
v = print_enum(TileSet.TileShape.TILE_SHAPE_ISOMETRIC)

View File

@@ -0,0 +1,9 @@
GDTEST_OK
0
0
0
0
1
1
1
1

View File

@@ -0,0 +1,86 @@
class_name EnumTypecheckOuterClass
enum MyEnum { V0, V1, V2 }
class InnerClass:
enum MyEnum { V0, V2, V1 }
static func test_inner_from_inner():
print("Inner - Inner")
var e1 : MyEnum
var e2 : InnerClass.MyEnum
var e3 : EnumTypecheckOuterClass.InnerClass.MyEnum
print("Self ", e1, e2, e3)
e1 = MyEnum.V1
e2 = MyEnum.V1
e3 = MyEnum.V1
print("MyEnum ", e1, e2, e3)
e1 = InnerClass.MyEnum.V1
e2 = InnerClass.MyEnum.V1
e3 = InnerClass.MyEnum.V1
print("Inner.MyEnum ", e1, e2, e3)
e1 = EnumTypecheckOuterClass.InnerClass.MyEnum.V1
e2 = EnumTypecheckOuterClass.InnerClass.MyEnum.V1
e3 = EnumTypecheckOuterClass.InnerClass.MyEnum.V1
print("Outer.Inner.MyEnum ", e1, e2, e3)
e1 = e2
e1 = e3
e2 = e1
e2 = e3
e3 = e1
e3 = e2
print()
static func test_outer_from_inner():
print("Inner - Outer")
var e : EnumTypecheckOuterClass.MyEnum
e = EnumTypecheckOuterClass.MyEnum.V1
print("Outer.MyEnum ", e)
print()
func test_outer_from_outer():
print("Outer - Outer")
var e1 : MyEnum
var e2 : EnumTypecheckOuterClass.MyEnum
print("Self ", e1, e2)
e1 = MyEnum.V1
e2 = MyEnum.V1
print("Outer ", e1, e2)
e1 = EnumTypecheckOuterClass.MyEnum.V1
e2 = EnumTypecheckOuterClass.MyEnum.V1
print("Outer.MyEnum ", e1, e2)
e1 = e2
e2 = e1
print()
func test_inner_from_outer():
print("Outer - Inner")
var e1 : InnerClass.MyEnum
var e2 : EnumTypecheckOuterClass.InnerClass.MyEnum
print("Inner ", e1, e2)
e1 = InnerClass.MyEnum.V1
e2 = InnerClass.MyEnum.V1
print("Outer.Inner ", e1, e2)
e1 = EnumTypecheckOuterClass.InnerClass.MyEnum.V1
e2 = EnumTypecheckOuterClass.InnerClass.MyEnum.V1
print("Outer.Inner.MyEnum ", e1, e2)
e1 = e2
e2 = e1
print()
func test():
test_outer_from_outer()
test_inner_from_outer()
InnerClass.test_outer_from_inner()
InnerClass.test_inner_from_inner()

View File

@@ -0,0 +1,19 @@
GDTEST_OK
Outer - Outer
Self 00
Outer 11
Outer.MyEnum 11
Outer - Inner
Inner 00
Outer.Inner 22
Outer.Inner.MyEnum 22
Inner - Outer
Outer.MyEnum 1
Inner - Inner
Self 000
MyEnum 222
Inner.MyEnum 222
Outer.Inner.MyEnum 222