HaxeFoundation / haxe

Haxe - The Cross-Platform Toolkit
https://haxe.org
6.18k stars 655 forks source link

(JVM) `Type.allEnums` fails on native enums #10508

Closed TheDrawingCoder-Gamer closed 2 years ago

TheDrawingCoder-Gamer commented 2 years ago

Type.allEnums fails on native enums, even though there is a native way to access them (Enum.values()).

Native enums are also considered haxe enums, which messes up maps.

Note: this is being built and tested using gradle.

TODO: Write test case

TheDrawingCoder-Gamer commented 2 years ago

https://github.com/TheDrawingCoder-Gamer/hxjava-enum-jank working example I've noticed that this is JVM exclusive; this doesn't happen on java

Simn commented 2 years ago

Is that really about allEnums or does getEnumConstructs (man I hate these names...) also have this problem?

TheDrawingCoder-Gamer commented 2 years ago

I have to test it.

TheDrawingCoder-Gamer commented 2 years ago

Yep, it's getEnumConstructs. And yes, the error traces down to getEnumConstructs on the allEnums one too:

PS C:\Users\benha\Documents\GitHub\hxjava-enum-jank> java -jar ./bin/main.jar
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "haxe.jvm.annotation.EnumReflectionInformation.constructorNames()" because "annotation" is null
        at haxe.root.Type.getEnumConstructs(C:\HaxeToolkit\haxe\std/jvm/_std/Type.hx:244)
        at haxe.root.Type.allEnums(C:\HaxeToolkit\haxe\std/jvm/_std/Type.hx:302)
        at haxe.root.Example.main(haxe-src/Example.hx:5)
        at haxe.root.Example.main(haxe-src/Example.hx:1)
Simn commented 2 years ago

Right, that looks like a bit of an oversight because getEnumConstructs relies on a Haxe-specific annotation. We need a branch for when that annotation isn't present, which can probably do the same thing as the Java implementation does: https://github.com/HaxeFoundation/haxe/blob/development/std/java/_std/Type.hx#L277-L281

TheDrawingCoder-Gamer commented 2 years ago

Yep, that should work. Manually doing that worked so generizing it should be fine.

public static function colors():Array<DyeColor> {
        var vals:java.NativeArray<java.lang.Enum<DyeColor>> = untyped DyeColor.values(),
            ctors = [];
        for (i in 0...vals.length) {
            ctors[i] = vals[i].name();
        }
        var ret = [];
        for (ctor in ctors) {
            var v = Reflect.field(DyeColor, ctor);
            if (Std.isOfType(v, DyeColor)) {
                ret.push(v);
            }
        }
        return ret;

    }
TheDrawingCoder-Gamer commented 2 years ago

nevermind it's empty

Simn commented 2 years ago

I don't know how the JVM target reacts to untyped in cases like that. Although I'd expect a compilation or verification error if that went horribly wrong. Maybe the Reflect.field or the Std.isOfType fails?

TheDrawingCoder-Gamer commented 2 years ago

I think the reason it's empty is because of a issue related to dealing with obfuscated code.

TheDrawingCoder-Gamer commented 2 years ago

untyped e.values() still returns the unobfuscated values which is very unhelpful but I don't know how you would fix that/why you would fix that because it's very niche.

Simn commented 2 years ago

Are we still talking native enums? Because then there's nothing we can do anyway given that the values function is added by the Java compiler. Although that also means that your obfuscation is pointless, at least in this specific regard.

TheDrawingCoder-Gamer commented 2 years ago

Yep native, it's not my obfuscation though. This is a minecraft mod. I worked around it by just using the raw types.