mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Add several tests for metaprogramming
This commit is contained in:
parent
3e562aa08a
commit
518e13cf07
|
@ -2,7 +2,7 @@
|
||||||
<configuration default="false" name="run-tests" type="JUnit" factoryName="JUnit">
|
<configuration default="false" name="run-tests" type="JUnit" factoryName="JUnit">
|
||||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea">
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea">
|
||||||
<pattern>
|
<pattern>
|
||||||
<option name="PATTERN" value="org.teavm.classlib.java.lang.*" />
|
<option name="PATTERN" value="org.teavm.*" />
|
||||||
<option name="ENABLED" value="true" />
|
<option name="ENABLED" value="true" />
|
||||||
</pattern>
|
</pattern>
|
||||||
</extension>
|
</extension>
|
||||||
|
|
|
@ -28,17 +28,25 @@ import org.teavm.metaprogramming.impl.reflect.ReflectClassImpl;
|
||||||
import org.teavm.metaprogramming.impl.reflect.ReflectContext;
|
import org.teavm.metaprogramming.impl.reflect.ReflectContext;
|
||||||
import org.teavm.metaprogramming.impl.reflect.ReflectFieldImpl;
|
import org.teavm.metaprogramming.impl.reflect.ReflectFieldImpl;
|
||||||
import org.teavm.metaprogramming.impl.reflect.ReflectMethodImpl;
|
import org.teavm.metaprogramming.impl.reflect.ReflectMethodImpl;
|
||||||
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.CallLocation;
|
import org.teavm.model.CallLocation;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.Instruction;
|
||||||
import org.teavm.model.InstructionLocation;
|
import org.teavm.model.InstructionLocation;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
|
import org.teavm.model.instructions.DoubleConstantInstruction;
|
||||||
import org.teavm.model.instructions.ExitInstruction;
|
import org.teavm.model.instructions.ExitInstruction;
|
||||||
|
import org.teavm.model.instructions.FloatConstantInstruction;
|
||||||
|
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||||
import org.teavm.model.instructions.InvocationType;
|
import org.teavm.model.instructions.InvocationType;
|
||||||
import org.teavm.model.instructions.InvokeInstruction;
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
|
import org.teavm.model.instructions.LongConstantInstruction;
|
||||||
|
import org.teavm.model.instructions.NullConstantInstruction;
|
||||||
|
import org.teavm.model.util.InstructionTransitionExtractor;
|
||||||
|
|
||||||
public final class MetaprogrammingImpl {
|
public final class MetaprogrammingImpl {
|
||||||
static ClassLoader classLoader;
|
static ClassLoader classLoader;
|
||||||
|
@ -217,6 +225,62 @@ public final class MetaprogrammingImpl {
|
||||||
agent.submitClass(cls);
|
agent.submitClass(cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void close() {
|
||||||
|
InstructionTransitionExtractor transitionExtractor = new InstructionTransitionExtractor();
|
||||||
|
BasicBlock block = generator.currentBlock();
|
||||||
|
Instruction lastInstruction = block.getLastInstruction();
|
||||||
|
if (lastInstruction != null) {
|
||||||
|
lastInstruction.acceptVisitor(transitionExtractor);
|
||||||
|
}
|
||||||
|
if (transitionExtractor.getTargets() != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable var;
|
||||||
|
if (returnType instanceof ValueType.Void) {
|
||||||
|
var = null;
|
||||||
|
} else if (returnType instanceof ValueType.Primitive) {
|
||||||
|
var = generator.program.createVariable();
|
||||||
|
switch (((ValueType.Primitive) returnType).getKind()) {
|
||||||
|
case BOOLEAN:
|
||||||
|
case BYTE:
|
||||||
|
case SHORT:
|
||||||
|
case CHARACTER:
|
||||||
|
case INTEGER: {
|
||||||
|
IntegerConstantInstruction constantInsn = new IntegerConstantInstruction();
|
||||||
|
constantInsn.setReceiver(var);
|
||||||
|
generator.add(constantInsn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LONG: {
|
||||||
|
LongConstantInstruction constantInsn = new LongConstantInstruction();
|
||||||
|
constantInsn.setReceiver(var);
|
||||||
|
generator.add(constantInsn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FLOAT: {
|
||||||
|
FloatConstantInstruction constantInsn = new FloatConstantInstruction();
|
||||||
|
constantInsn.setReceiver(var);
|
||||||
|
generator.add(constantInsn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DOUBLE: {
|
||||||
|
DoubleConstantInstruction constantInsn = new DoubleConstantInstruction();
|
||||||
|
constantInsn.setReceiver(var);
|
||||||
|
generator.add(constantInsn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NullConstantInstruction constantInsn = new NullConstantInstruction();
|
||||||
|
var = generator.program.createVariable();
|
||||||
|
constantInsn.setReceiver(var);
|
||||||
|
generator.add(constantInsn);
|
||||||
|
}
|
||||||
|
|
||||||
|
returnValue(var);
|
||||||
|
}
|
||||||
|
|
||||||
private static void unsupported() {
|
private static void unsupported() {
|
||||||
throw new UnsupportedOperationException("This operation is only supported from TeaVM compile-time "
|
throw new UnsupportedOperationException("This operation is only supported from TeaVM compile-time "
|
||||||
+ "environment");
|
+ "environment");
|
||||||
|
|
|
@ -146,6 +146,7 @@ class UsageGenerator {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
proxyMethod.invoke(null, proxyArgs);
|
proxyMethod.invoke(null, proxyArgs);
|
||||||
|
MetaprogrammingImpl.close();
|
||||||
Program program = MetaprogrammingImpl.generator.getProgram();
|
Program program = MetaprogrammingImpl.generator.getProgram();
|
||||||
//new BoxingEliminator().optimize(program);
|
//new BoxingEliminator().optimize(program);
|
||||||
|
|
||||||
|
|
|
@ -18,5 +18,5 @@ package org.teavm.metaprogramming;
|
||||||
import org.teavm.metaprogramming.reflect.ReflectMethod;
|
import org.teavm.metaprogramming.reflect.ReflectMethod;
|
||||||
|
|
||||||
public interface InvocationHandler<T> {
|
public interface InvocationHandler<T> {
|
||||||
void invoke(Value<T> proxy, ReflectMethod method, Value<Object>[] args);
|
Computation<?> invoke(Value<T> proxy, ReflectMethod method, Value<Object>[] args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,8 +71,7 @@ public final class Metaprogramming {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ReflectClass<T[]> arrayClass(ReflectClass<T> componentType) {
|
public static <T> ReflectClass<T[]> arrayClass(ReflectClass<T> componentType) {
|
||||||
unsupported();
|
throw new UnsupportedOperationException();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReflectClass<?> createClass(byte[] bytecode) {
|
public static ReflectClass<?> createClass(byte[] bytecode) {
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.metaprogramming.test;
|
||||||
|
|
||||||
|
import static org.teavm.metaprogramming.Metaprogramming.emit;
|
||||||
|
import org.teavm.metaprogramming.CompileTime;
|
||||||
|
import org.teavm.metaprogramming.Value;
|
||||||
|
|
||||||
|
@CompileTime
|
||||||
|
public class MetaprogrammingGenerator2 {
|
||||||
|
public Value<String> addParentheses(String value) {
|
||||||
|
return emit(() -> "[" + value + "]");
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,13 @@
|
||||||
package org.teavm.metaprogramming.test;
|
package org.teavm.metaprogramming.test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.teavm.metaprogramming.Metaprogramming.arrayClass;
|
||||||
|
import static org.teavm.metaprogramming.Metaprogramming.emit;
|
||||||
import static org.teavm.metaprogramming.Metaprogramming.exit;
|
import static org.teavm.metaprogramming.Metaprogramming.exit;
|
||||||
|
import static org.teavm.metaprogramming.Metaprogramming.findClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.teavm.junit.SkipJVM;
|
import org.teavm.junit.SkipJVM;
|
||||||
|
@ -25,12 +31,15 @@ import org.teavm.metaprogramming.CompileTime;
|
||||||
import org.teavm.metaprogramming.Meta;
|
import org.teavm.metaprogramming.Meta;
|
||||||
import org.teavm.metaprogramming.ReflectClass;
|
import org.teavm.metaprogramming.ReflectClass;
|
||||||
import org.teavm.metaprogramming.Value;
|
import org.teavm.metaprogramming.Value;
|
||||||
|
import org.teavm.metaprogramming.reflect.ReflectField;
|
||||||
|
import org.teavm.metaprogramming.reflect.ReflectMethod;
|
||||||
|
import org.teavm.metaprogramming.test.subpackage.MetaprogrammingGenerator;
|
||||||
|
|
||||||
@CompileTime
|
@CompileTime
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@SkipJVM
|
||||||
public class MetaprogrammingTest {
|
public class MetaprogrammingTest {
|
||||||
@Test
|
@Test
|
||||||
@SkipJVM
|
|
||||||
public void works() {
|
public void works() {
|
||||||
assertEquals("java.lang.Object".length() + 2, classNameLength(Object.class, 2));
|
assertEquals("java.lang.Object".length() + 2, classNameLength(Object.class, 2));
|
||||||
assertEquals("java.lang.Integer".length() + 3, classNameLength(Integer.valueOf(5).getClass(), 3));
|
assertEquals("java.lang.Integer".length() + 3, classNameLength(Integer.valueOf(5).getClass(), 3));
|
||||||
|
@ -42,4 +51,299 @@ public class MetaprogrammingTest {
|
||||||
int length = cls.getName().length();
|
int length = cls.getName().length();
|
||||||
exit(() -> length + add.get());
|
exit(() -> length + add.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getsField() {
|
||||||
|
Context ctx = new Context();
|
||||||
|
ctx.a = 2;
|
||||||
|
ctx.b = 3;
|
||||||
|
|
||||||
|
assertEquals(2, getField(ctx.getClass(), ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native Object getField(Class<?> cls, Object obj);
|
||||||
|
private static void getField(ReflectClass<Object> cls, Value<Object> obj) {
|
||||||
|
ReflectField field = cls.getField("a");
|
||||||
|
exit(() -> field.get(obj));
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void setsField() {
|
||||||
|
Context ctx = new Context();
|
||||||
|
setField(ctx.getClass(), ctx, 3);
|
||||||
|
|
||||||
|
assertEquals(3, ctx.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native void setField(Class<?> cls, Object obj, Object value);
|
||||||
|
private static void setField(ReflectClass<Object> cls, Value<Object> obj, Value<Object> value) {
|
||||||
|
ReflectField field = cls.getField("a");
|
||||||
|
emit(() -> field.set(obj, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void methodInvoked() {
|
||||||
|
assertEquals("debug!", callDebug(A.class, new A()));
|
||||||
|
assertEquals("missing", callDebug(B.class, new B()));
|
||||||
|
assertEquals("missing", callDebug(A.class, new A(), "foo", 23));
|
||||||
|
assertEquals("debug!foo:23", callDebug(B.class, new B(), "foo", 23));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native String callDebug(Class<?> cls, Object obj);
|
||||||
|
private static void callDebug(ReflectClass<?> cls, Value<Object> obj) {
|
||||||
|
ReflectMethod method = cls.getMethod("debug");
|
||||||
|
if (method == null) {
|
||||||
|
exit(() -> "missing");
|
||||||
|
} else {
|
||||||
|
exit(() -> method.invoke(obj.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native String callDebug(Class<?> cls, Object obj, String a, int b);
|
||||||
|
private static void callDebug(ReflectClass<?> cls, Value<Object> obj, Value<String> a, Value<Integer> b) {
|
||||||
|
ReflectClass<String> stringClass = findClass(String.class);
|
||||||
|
ReflectClass<Integer> intClass = findClass(int.class);
|
||||||
|
ReflectMethod method = cls.getMethod("debug", stringClass, intClass);
|
||||||
|
if (method == null) {
|
||||||
|
exit(() -> "missing");
|
||||||
|
} else {
|
||||||
|
exit(() -> method.invoke(obj.get(), a.get(), b.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorInvoked() {
|
||||||
|
assertEquals(C.class.getName(), callConstructor(C.class).getClass().getName());
|
||||||
|
assertNull(callConstructor(D.class));
|
||||||
|
|
||||||
|
assertNull(callConstructor(C.class, "foo", 23));
|
||||||
|
|
||||||
|
D instance = (D) callConstructor(D.class, "foo", 23);
|
||||||
|
assertEquals(D.class.getName(), instance.getClass().getName());
|
||||||
|
assertEquals("foo", instance.a);
|
||||||
|
assertEquals(23, instance.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native Object callConstructor(Class<?> type);
|
||||||
|
private static void callConstructor(ReflectClass<?> type) {
|
||||||
|
ReflectMethod ctor = type.getMethod("<init>");
|
||||||
|
if (ctor != null) {
|
||||||
|
exit(() -> ctor.construct());
|
||||||
|
} else {
|
||||||
|
exit(() -> null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native Object callConstructor(Class<?> type, String a, int b);
|
||||||
|
private static void callConstructor(ReflectClass<?> type, Value<String> a, Value<Integer> b) {
|
||||||
|
ReflectClass<String> stringClass = findClass(String.class);
|
||||||
|
ReflectClass<Integer> intClass = findClass(int.class);
|
||||||
|
ReflectMethod ctor = type.getMethod("<init>", stringClass, intClass);
|
||||||
|
if (ctor != null) {
|
||||||
|
exit(() -> ctor.construct(a, b));
|
||||||
|
} else {
|
||||||
|
exit(() -> null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void capturesArray() {
|
||||||
|
assertEquals("23:foo", captureArray(23, "foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native String captureArray(int a, String b);
|
||||||
|
private static void captureArray(Value<Integer> a, Value<String> b) {
|
||||||
|
Value<?>[] array = { a, emit(() -> ":"), b };
|
||||||
|
exit(() -> String.valueOf(array[0].get()) + array[1].get() + array[2].get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isInstanceWorks() {
|
||||||
|
assertTrue(isInstance("foo", String.class));
|
||||||
|
assertFalse(isInstance(23, String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native boolean isInstance(Object obj, Class<?> type);
|
||||||
|
private static void isInstance(Value<Object> obj, ReflectClass<?> type) {
|
||||||
|
exit(() -> type.isInstance(obj.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void capturesNull() {
|
||||||
|
assertEquals("foo:", captureArgument("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native String captureArgument(String a);
|
||||||
|
private static void captureArgument(Value<String> a) {
|
||||||
|
exit(() -> a.get() + ":");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void annotationsWork() {
|
||||||
|
assertEquals(""
|
||||||
|
+ "foo:23:Object\n"
|
||||||
|
+ "foo=!:42:String:int\n"
|
||||||
|
+ "f=!:23\n",
|
||||||
|
readAnnotations(WithAnnotations.class, new WithAnnotations()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native String readAnnotations(Class<?> cls, Object obj);
|
||||||
|
private static void readAnnotations(ReflectClass<Object> cls, Value<Object> obj) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(describeAnnotation(cls.getAnnotation(TestAnnotation.class))).append('\n');
|
||||||
|
for (ReflectMethod method : cls.getDeclaredMethods()) {
|
||||||
|
TestAnnotation annot = method.getAnnotation(TestAnnotation.class);
|
||||||
|
if (annot == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sb.append(method.getName()).append('=').append(describeAnnotation(annot)).append('\n');
|
||||||
|
}
|
||||||
|
for (ReflectField field : cls.getDeclaredFields()) {
|
||||||
|
TestAnnotation annot = field.getAnnotation(TestAnnotation.class);
|
||||||
|
if (annot == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sb.append(field.getName()).append('=').append(describeAnnotation(annot)).append('\n');
|
||||||
|
}
|
||||||
|
String result = sb.toString();
|
||||||
|
exit(() -> result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String describeAnnotation(TestAnnotation annot) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(annot.a()).append(':').append(annot.b());
|
||||||
|
for (Class<?> cls : annot.c()) {
|
||||||
|
sb.append(':').append(cls.getSimpleName());
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void compileTimeAnnotationRespectsPackage() {
|
||||||
|
assertEquals("(foo)", compileTimePackage(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native String compileTimePackage(boolean ignoreMe);
|
||||||
|
private static void compileTimePackage(Value<Boolean> ignoreMe) {
|
||||||
|
Value<String> result = new MetaprogrammingGenerator().addParentheses("foo");
|
||||||
|
exit(() -> result.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void compileTimeAnnotationRespectsClass() {
|
||||||
|
assertEquals("[foo]", compileTimeClass(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native String compileTimeClass(boolean ignoreMe);
|
||||||
|
private static void compileTimeClass(Value<Boolean> ignoreMe) {
|
||||||
|
Value<String> result = new MetaprogrammingGenerator2().addParentheses("foo");
|
||||||
|
exit(() -> result.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void compileTimeAnnotationRespectsNestedClass() {
|
||||||
|
assertEquals("{foo}", compileTimeNestedClass(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native String compileTimeNestedClass(boolean ignoreMe);
|
||||||
|
private static void compileTimeNestedClass(Value<Boolean> ignoreMe) {
|
||||||
|
Value<String> result = new MetaprogrammingGenerator3().addParentheses("foo");
|
||||||
|
exit(() -> result.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void emitsClassLiteralFromReflectClass() {
|
||||||
|
assertEquals(String[].class.getName(), emitClassLiteral(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native String emitClassLiteral(Class<?> cls);
|
||||||
|
private static void emitClassLiteral(ReflectClass<?> cls) {
|
||||||
|
ReflectClass<?> arrayClass = arrayClass(cls);
|
||||||
|
exit(() -> arrayClass.asJavaClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createsArrayViaReflection() {
|
||||||
|
Object array = createArrayOfType(String.class, 10);
|
||||||
|
assertEquals(String[].class, array.getClass());
|
||||||
|
assertEquals(10, ((String[]) array).length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native Object createArrayOfType(Class<?> cls, int size);
|
||||||
|
private static void createArrayOfType(ReflectClass<?> cls, Value<Integer> size) {
|
||||||
|
exit(() -> cls.createArray(size.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getsArrayElementViaReflection() {
|
||||||
|
assertEquals("foo", getArrayElement(String[].class, new String[] { "foo" }, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Meta
|
||||||
|
private static native Object getArrayElement(Class<?> type, Object array, int index);
|
||||||
|
private static void getArrayElement(ReflectClass<?> type, Value<Object> array, Value<Integer> index) {
|
||||||
|
exit(() -> type.getArrayElement(array.get(), index.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Context {
|
||||||
|
public int a;
|
||||||
|
public int b;
|
||||||
|
}
|
||||||
|
|
||||||
|
class A {
|
||||||
|
public String debug() {
|
||||||
|
return "debug!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
public String debug(String a, int b) {
|
||||||
|
return "debug!" + a + ":" + b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static class C {
|
||||||
|
public C() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class D {
|
||||||
|
String a;
|
||||||
|
int b;
|
||||||
|
|
||||||
|
public D(String a, int b) {
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestAnnotation(a = "foo", c = Object.class)
|
||||||
|
static class WithAnnotations {
|
||||||
|
@TestAnnotation(c = {})
|
||||||
|
int f;
|
||||||
|
|
||||||
|
@TestAnnotation(b = 42, c = { String.class, int.class })
|
||||||
|
int foo() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MetaprogrammingGenerator3 {
|
||||||
|
public Value<String> addParentheses(String value) {
|
||||||
|
return emit(() -> "{" + value + "}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.metaprogramming.test;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface TestAnnotation {
|
||||||
|
String a() default "!";
|
||||||
|
|
||||||
|
int b() default 23;
|
||||||
|
|
||||||
|
Class<?>[] c();
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.metaprogramming.test.subpackage;
|
||||||
|
|
||||||
|
import static org.teavm.metaprogramming.Metaprogramming.emit;
|
||||||
|
import org.teavm.metaprogramming.Value;
|
||||||
|
|
||||||
|
public class MetaprogrammingGenerator {
|
||||||
|
public Value<String> addParentheses(String value) {
|
||||||
|
return emit(() -> "(" + value + ")");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
@CompileTime
|
||||||
|
package org.teavm.metaprogramming.test.subpackage;
|
||||||
|
|
||||||
|
import org.teavm.metaprogramming.CompileTime;
|
Loading…
Reference in New Issue
Block a user