Skip to content

Commit

Permalink
added ClassExpressionLookup to access classes declared later in the s…
Browse files Browse the repository at this point in the history
…cript
  • Loading branch information
wizzardo committed Jun 6, 2024
1 parent 740a58f commit c20e4ed
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.wizzardo.tools.evaluation;

import com.wizzardo.tools.misc.Unchecked;
import java.util.Map;

public class ClassExpressionLookup extends Expression {

protected final String className;
protected final String key;
protected ClassExpression ce;

public ClassExpressionLookup(String className, EvaluationContext context) {
super(context);
this.className = className;
this.key = "class " + className;
}

@Override
public void setVariable(Variable v) {
}

@Override
public Expression clone() {
return this;
}

@Override
protected Object doExecute(Map<String, Object> model) {
if (ce == null) {
ce = (ClassExpression) model.get(key);
}
if (ce == null) {
Unchecked.rethrow(new ClassNotFoundException("Can not find class '" + className + "'"));
}
return ce;
}

@Override
public String toString() {
return className;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package com.wizzardo.tools.evaluation;

import com.wizzardo.tools.misc.Pair;
import com.wizzardo.tools.misc.Unchecked;

import java.lang.reflect.*;
import java.util.*;
Expand Down Expand Up @@ -1938,8 +1937,11 @@ public static Expression prepare(String exp, int from, int to, EvaluationContext
methodName = CONSTRUCTOR;
from = start = expressionPart.start + m.end();
}
} else
Unchecked.rethrow(new ClassNotFoundException("Can not find class '" + className + "'"));
} else {
thatObject = new ClassExpressionLookup(className, model);
methodName = CONSTRUCTOR;
from = start = expressionPart.start + m.end();
}
}
}
}
Expand Down
65 changes: 61 additions & 4 deletions src/test/java/com/wizzardo/tools/evaluation/EvalToolsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@

import java.awt.*;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -1096,7 +1094,7 @@ public void test_imports_1() {
checkException(new Runnable() {
@Override
public void run() {
EvalTools.prepare(s);
EvalTools.prepare(s).get(model);
}
}, ClassNotFoundException.class, "Can not find class 'AtomicInteger'");

Expand Down Expand Up @@ -2221,6 +2219,65 @@ public void test_generate_class_2() throws InstantiationException, IllegalAccess
Assert.assertEquals(true, flagField.get(instance));
}

@Test
public void test_class_expression_lookup() throws InstantiationException, IllegalAccessException, InvocationTargetException {
Map<String, Object> model = new HashMap<String, Object>();

Expression e = EvalTools.prepare("" +
"class SimpleClass {\n" +
" public String get(){\n" +
" return new InternalClass().value+\"\";" +
" }\n" +
" static class InternalClass {\n" +
" int value = 1;" +
" }\n" +
"}\n" +
"");

Object result = e.get(new HashMap<>());

Assert.assertNotNull(result);
Assert.assertTrue(result instanceof ClassExpression);
Class<?> aClass = ((ClassExpression) result).getJavaClass();
Assert.assertEquals("SimpleClass", aClass.getSimpleName());
Method[] methods = ((Class<?>) aClass).getDeclaredMethods();
Assert.assertTrue(methods.length >= 1);
Method getMethod = Arrays.stream(methods).filter(it -> it.getName().equals("get")).findFirst().orElse(null);
Assert.assertNotNull(getMethod);
Object instance = ((ClassExpression) result).newInstance(new Object[0]);
Assert.assertEquals("1", getMethod.invoke(instance));
}

@Test
public void test_class_expression_lookup_2() throws InstantiationException, IllegalAccessException, InvocationTargetException {
Map<String, Object> model = new HashMap<String, Object>();

Expression e = EvalTools.prepare("" +
"class SimpleClass {\n" +
" public String get(){\n" +
" return new InternalClass(2).value+\"\";" +
" }\n" +
" static class InternalClass {\n" +
" int value = 1;" +
" InternalClass(int v){this.value=v;}" +
" }\n" +
"}\n" +
"");

Object result = e.get(new HashMap<>());

Assert.assertNotNull(result);
Assert.assertTrue(result instanceof ClassExpression);
Class<?> aClass = ((ClassExpression) result).getJavaClass();
Assert.assertEquals("SimpleClass", aClass.getSimpleName());
Method[] methods = ((Class<?>) aClass).getDeclaredMethods();
Assert.assertTrue(methods.length >= 1);
Method getMethod = Arrays.stream(methods).filter(it -> it.getName().equals("get")).findFirst().orElse(null);
Assert.assertNotNull(getMethod);
Object instance = ((ClassExpression) result).newInstance(new Object[0]);
Assert.assertEquals("2", getMethod.invoke(instance));
}

@Test
public void test_line_number() {
Map<String, Object> model = new HashMap<String, Object>();
Expand Down

0 comments on commit c20e4ed

Please sign in to comment.