Skip to content

Commit deff1f5

Browse files
authored
Merge pull request #183 from ZenCodeLang/feature/refactor-java-enums
Feature/refactor java enums
2 parents 3fea2d4 + 0fd9b7b commit deff1f5

File tree

4 files changed

+71
-55
lines changed

4 files changed

+71
-55
lines changed

JavaIntegration/src/main/java/org/openzen/zencode/java/module/JavaNativeTypeMembers.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ public Optional<StaticCallable> findStaticMethod(String name) {
7676

7777
@Override
7878
public Optional<StaticCallable> findStaticGetter(String name) {
79-
return loadStatic(MethodID.getter(name));
79+
return loadStatic(MethodID.staticGetter(name));
8080
}
8181

8282
@Override
8383
public Optional<StaticCallable> findStaticSetter(String name) {
84-
return loadStatic(MethodID.setter(name));
84+
return loadStatic(MethodID.staticSetter(name));
8585
}
8686

8787
@Override

JavaIntegration/src/main/java/org/openzen/zencode/java/module/JavaNativeTypeTemplate.java

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
import org.openzen.zenscript.codemodel.identifiers.instances.FieldInstance;
1919
import org.openzen.zenscript.codemodel.ssa.CodeBlockStatement;
2020
import org.openzen.zenscript.codemodel.ssa.SSAVariableCollector;
21+
import org.openzen.zenscript.codemodel.type.ArrayTypeID;
2122
import org.openzen.zenscript.codemodel.type.TypeID;
23+
import org.openzen.zenscript.codemodel.type.builtin.BuiltinMethodSymbol;
2224
import org.openzen.zenscript.javashared.JavaClass;
2325
import org.openzen.zenscript.javashared.JavaModifiers;
2426
import org.openzen.zenscript.javashared.JavaNativeField;
@@ -29,6 +31,7 @@
2931
import java.lang.reflect.Modifier;
3032
import java.util.*;
3133
import java.util.stream.Collectors;
34+
import java.util.stream.Stream;
3235

3336
public class JavaNativeTypeTemplate {
3437
protected final JavaRuntimeClass class_;
@@ -138,13 +141,16 @@ private void loadMethods() {
138141
for (Method method : class_.cls.getMethods()) {
139142
if (isNotAccessible(method) || isOverridden(class_.cls, method))
140143
continue;
144+
141145
if (expansion && !JavaModifiers.isStatic(method.getModifiers()))
142146
continue;
143147

144-
Collection<MethodID> ids = new LinkedList<>();
145-
boolean isStaticExpansion = false;
148+
Collection<MethodID> ids = new LinkedHashSet<>(); // LinkedHashSet to prevent collision if a static method has both @Global and @Method
149+
boolean isStaticExpansionMethod = expansion && method.isAnnotationPresent(ZenCodeType.StaticExpansionMethod.class);
150+
boolean isStaticMethodInsideZc = (!expansion || isStaticExpansionMethod) && JavaModifiers.isStatic(method.getModifiers());
151+
146152
boolean implicit = false;
147-
boolean isStaticMethod = false;
153+
148154
if (method.isAnnotationPresent(ZenCodeType.Operator.class)) {
149155
ZenCodeType.Operator operator = method.getAnnotation(ZenCodeType.Operator.class);
150156
MethodID id = MethodID.operator(OperatorType.valueOf(operator.value().toString()));
@@ -153,13 +159,13 @@ private void loadMethods() {
153159
if (method.isAnnotationPresent(ZenCodeType.Getter.class)) {
154160
ZenCodeType.Getter getter = method.getAnnotation(ZenCodeType.Getter.class);
155161
String name = getter.value().isEmpty() ? method.getName() : getter.value();
156-
MethodID id = MethodID.getter(name);
162+
MethodID id = isStaticMethodInsideZc ? MethodID.staticGetter(name) : MethodID.getter(name);
157163
ids.add(id);
158164
}
159165
if (method.isAnnotationPresent(ZenCodeType.Setter.class)) {
160166
ZenCodeType.Setter setter = method.getAnnotation(ZenCodeType.Setter.class);
161167
String name = setter.value().isEmpty() ? method.getName() : setter.value();
162-
MethodID id = MethodID.setter(name);
168+
MethodID id = isStaticMethodInsideZc ? MethodID.staticSetter(name) : MethodID.setter(name);
163169
ids.add(id);
164170
}
165171
if (method.isAnnotationPresent(ZenCodeType.Caster.class)) {
@@ -171,20 +177,17 @@ private void loadMethods() {
171177
if (method.isAnnotationPresent(ZenCodeType.Method.class)) {
172178
ZenCodeType.Method methodAnnotation = method.getAnnotation(ZenCodeType.Method.class);
173179
String name = methodAnnotation.value().isEmpty() ? method.getName() : methodAnnotation.value();
174-
boolean hasStaticModifier = JavaModifiers.isStatic(method.getModifiers());
175-
MethodID id = hasStaticModifier && !expansion ? MethodID.staticMethod(name) : MethodID.instanceMethod(name);
180+
MethodID id = isStaticMethodInsideZc ? MethodID.staticMethod(name) : MethodID.instanceMethod(name);
176181
implicit |= methodAnnotation.implicit();
177-
isStaticMethod |= hasStaticModifier;
178182
ids.add(id);
179183
}
180-
if (expansion && method.isAnnotationPresent(ZenCodeType.StaticExpansionMethod.class)) {
184+
if (isStaticExpansionMethod) {
181185
ZenCodeType.StaticExpansionMethod methodAnnotation = method.getAnnotation(ZenCodeType.StaticExpansionMethod.class);
182186
String name = methodAnnotation.value().isEmpty() ? method.getName() : methodAnnotation.value();
183187
MethodID id = MethodID.staticMethod(name);
184188
ids.add(id);
185-
isStaticExpansion = true;
186189
}
187-
if (!isStaticMethod && method.isAnnotationPresent(ZenCodeGlobals.Global.class) && JavaModifiers.isStatic(method.getModifiers())) {
190+
if (isStaticMethodInsideZc && method.isAnnotationPresent(ZenCodeGlobals.Global.class)) {
188191
ZenCodeGlobals.Global methodAnnotation = method.getAnnotation(ZenCodeGlobals.Global.class);
189192
String name = methodAnnotation.value().isEmpty() ? method.getName() : methodAnnotation.value();
190193
MethodID id = MethodID.staticMethod(name);
@@ -194,18 +197,42 @@ private void loadMethods() {
194197
continue;
195198

196199
FunctionHeader header = headerConverter.getHeader(typeVariableContext, method);
197-
198-
if (expansion && !isStaticExpansion) {
200+
if (expansion && !isStaticExpansionMethod) {
199201
FunctionParameter[] withoutFirst = Arrays.copyOfRange(header.parameters, 1, header.parameters.length);
200202
header = new FunctionHeader(header.typeParameters, header.getReturnType(), header.thrownType, withoutFirst);
201203
}
202204

203205
for (MethodID id : ids) {
204-
JavaRuntimeMethod runtimeMethod = new JavaRuntimeMethod(class_, target, method, id, header, implicit, expansion && !isStaticExpansion);
206+
JavaRuntimeMethod runtimeMethod = new JavaRuntimeMethod(class_, target, method, id, header, implicit, expansion && !isStaticExpansionMethod);
205207
methods.computeIfAbsent(id, x -> new ArrayList<>()).add(runtimeMethod);
206208
class_.module.getCompiled().setMethodInfo(runtimeMethod, runtimeMethod);
207209
}
208210
}
211+
212+
213+
if (class_.cls.isEnum()) {
214+
Stream.of(
215+
BuiltinMethodSymbol.ENUM_NAME,
216+
BuiltinMethodSymbol.ENUM_ORDINAL,
217+
//BuiltinMethodSymbol.ENUM_VALUES,
218+
BuiltinMethodSymbol.ENUM_COMPARE
219+
).forEach(method -> methods
220+
.computeIfAbsent(method.getID(), x -> new ArrayList<>())
221+
.add(method)
222+
);
223+
224+
try {
225+
MethodID id = MethodID.staticGetter("values");
226+
FunctionHeader header = new FunctionHeader(new ArrayTypeID(target));
227+
Method method = class_.cls.getMethod("values");
228+
JavaRuntimeMethod runtimeMethod = new JavaRuntimeMethod(class_, target, method, id, header, false, false);
229+
methods.computeIfAbsent(id, x -> new ArrayList<>()).add(runtimeMethod);
230+
class_.module.getCompiled().setMethodInfo(runtimeMethod, runtimeMethod);
231+
} catch (ReflectiveOperationException exception) {
232+
throw new IllegalStateException("We found an enum class without values() method: " + class_.cls.getCanonicalName(), exception);
233+
}
234+
235+
}
209236
}
210237

211238
private void loadInnerTypes() {

ScriptingExample/src/test/java/org/openzen/zenscript/scriptingexample/tests/actual_test/java_native/enums/EnumMemberTests.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,34 @@ void EnumMembersMustBeRetrievableByTypeHintAndName() {
2828
logger.assertPrintOutput(0, "A");
2929
}
3030

31+
@Test
32+
void EnumMembersMustBeRetrievableByFullName() {
33+
ScriptBuilder.create()
34+
.add("public class MyClass {")
35+
.add(" public this(thing as test_module.MyEnum) {")
36+
.add(" println(thing.name);")
37+
.add(" }")
38+
.add("}")
39+
.add("new MyClass(test_module.MyEnum.A);")
40+
.execute(this);
41+
42+
logger.assertPrintOutputSize(1);
43+
logger.assertPrintOutput(0, "A");
44+
}
45+
46+
@Test
47+
void EnumMembersMustHaveValuesGetter() {
48+
ScriptBuilder.create()
49+
.add("var values = test_module.MyEnum.values;")
50+
.add("var a = values[0];")
51+
.add("var name = a.name;")
52+
.add("println(a.name);")
53+
.execute(this);
54+
55+
logger.assertPrintOutputSize(1);
56+
logger.assertPrintOutput(0, "A");
57+
}
58+
3159

3260
@ZenCodeType.Name("test_module.MyEnum")
3361
public enum MyEnum {

ScriptingExample/src/test/java/org/openzen/zenscript/scriptingexample/tests/actual_test/joined_tests/TypeInferenceBlockingTest.java

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)