diff --git a/jOOR/src/main/java/org/joor/CompileUnit.java b/jOOR/src/main/java/org/joor/MultiCompile.java similarity index 94% rename from jOOR/src/main/java/org/joor/CompileUnit.java rename to jOOR/src/main/java/org/joor/MultiCompile.java index 746e0c6..2b09195 100644 --- a/jOOR/src/main/java/org/joor/CompileUnit.java +++ b/jOOR/src/main/java/org/joor/MultiCompile.java @@ -35,13 +35,11 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Deque; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.stream.Stream; import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; @@ -50,8 +48,15 @@ * * @author Lukas Eder */ -public class CompileUnit { - +public class MultiCompile { + + /** + * Compiles multiple files as one unit + * + * @param unit the files to compile in the same unit + * @param compileOptions compile options + * @return the compilation result + */ public static CompilationUnit.Result compileUnit(CompilationUnit unit, CompileOptions compileOptions) { CompilationUnit.Result result = CompilationUnit.result(); @@ -130,24 +135,15 @@ public static CompilationUnit.Result compileUnit(CompilationUnit unit, CompileOp // This method is called by client code from two levels up the current stack frame // We need a private-access lookup from the class in that stack frame in order to get // private-access to any local interfaces at that location. -// Class caller = StackWalker -// .getInstance(RETAIN_CLASS_REFERENCE) -// .walk(s -> s -// .skip(2) -// .findFirst() -// .get() -// .getDeclaringClass()); - int index = 2; for (CharSequenceJavaFileObject f : files) { String className = f.getClassName(); - Class caller = getClassFromIndex(index); - index++; + Class caller = getClassFromIndex(index++); // If the compiled class is in the same package as the caller class, then // we can use the private-access Lookup of the caller class - if (className.startsWith(caller.getPackageName() + ".") && + if (caller != null && className.startsWith(caller.getPackageName() + ".") && // [#74] This heuristic is necessary to prevent classes in subpackages of the caller to be loaded // this way, as subpackages cannot access private content in super packages. @@ -185,13 +181,13 @@ public static CompilationUnit.Result compileUnit(CompilationUnit unit, CompileOp } private static Class getClassFromIndex(int index) { - return StackWalker + StackWalker.StackFrame sf = StackWalker .getInstance(RETAIN_CLASS_REFERENCE) .walk(s -> s .skip(index) .findFirst() - .get() - .getDeclaringClass()); + .orElse(null)); + return sf != null ? sf.getDeclaringClass() : null; } /* [java-9] */ diff --git a/jOOR/src/main/java/org/joor/Reflect.java b/jOOR/src/main/java/org/joor/Reflect.java index 8aa9713..1da139a 100644 --- a/jOOR/src/main/java/org/joor/Reflect.java +++ b/jOOR/src/main/java/org/joor/Reflect.java @@ -25,7 +25,6 @@ import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.Optional; @@ -52,7 +51,7 @@ public class Reflect { public static CompilationUnit.Result compileUnit(CompilationUnit unit) throws ReflectException { - return CompileUnit.compileUnit(unit, new CompileOptions()); + return MultiCompile.compileUnit(unit, new CompileOptions()); } // --------------------------------------------------------------------- diff --git a/jOOR/src/test/java/org/joor/test/CompileUnitTest.java b/jOOR/src/test/java/org/joor/test/MultiCompileTest.java similarity index 68% rename from jOOR/src/test/java/org/joor/test/CompileUnitTest.java rename to jOOR/src/test/java/org/joor/test/MultiCompileTest.java index 8d95c57..d0feacc 100644 --- a/jOOR/src/test/java/org/joor/test/CompileUnitTest.java +++ b/jOOR/src/test/java/org/joor/test/MultiCompileTest.java @@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals; -public class CompileUnitTest { +public class MultiCompileTest { @Test public void testSingleUnit() throws Exception { @@ -72,4 +72,38 @@ public void testDualUnit() throws Exception { assertEquals("Hi World!", out3); } + @Test + public void testClassLoadingOrder() throws Exception { + CompilationUnit unit = CompilationUnit.input() + .addClass("pm.A", "package pm; public class A extends B {}") + .addClass("pm.B", "package pm; public class B {}" + ); + + CompilationUnit.Result result = Reflect.compileUnit(unit); + assertEquals(2, result.size()); + + Class a = Reflect.onClass(result.getClass("pm.A")).type(); + Class b = Reflect.onClass(result.getClass("pm.B")).type(); + assertEquals("pm.A", a.getName()); + assertEquals("pm.B", a.getSuperclass().getName()); + assertEquals("pm.B", b.getName()); + } + + @Test + public void testClassLoadingOrderReverse() throws Exception { + CompilationUnit unit = CompilationUnit.input() + .addClass("pm.C", "package pm; public class C {}") + .addClass("pm.D", "package pm; public class D extends C {}" + ); + + CompilationUnit.Result result = Reflect.compileUnit(unit); + assertEquals(2, result.size()); + + Class c = Reflect.onClass(result.getClass("pm.C")).type(); + Class d = Reflect.onClass(result.getClass("pm.D")).type(); + assertEquals("pm.C", c.getName()); + assertEquals("pm.D", d.getName()); + assertEquals("pm.C", d.getSuperclass().getName()); + } + }