Bufix in CompilerEnvironment.
Build correct java name from passed array. Fixes compilation of
'import static x.y.Z.*;'
--- a/experiments/java/src/stx/libjava/tools/compiler/ecj/CompilationUnit.java Sun Mar 31 19:25:00 2013 +0100
+++ b/experiments/java/src/stx/libjava/tools/compiler/ecj/CompilationUnit.java Tue Apr 02 23:08:51 2013 +0100
@@ -63,4 +63,10 @@
}
return packagename;
}
+
+ @Override
+ public boolean ignoreOptionalProblems() {
+ // TODO Auto-generated method stub
+ return false;
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/experiments/java/src/stx/libjava/tools/compiler/ecj/CompilerAdapter.java Tue Apr 02 23:08:51 2013 +0100
@@ -0,0 +1,86 @@
+package stx.libjava.tools.compiler.ecj;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.eclipse.jdt.internal.compiler.ClassFile;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
+import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
+import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+
+public class CompilerAdapter implements ICompilerRequestor {
+ protected CompilerTypeRegistry types = new CompilerTypeRegistry();
+ protected INameEnvironment environment = new CompilerEnvironment(types);
+ protected CompilationResult result;
+
+
+ public CompilationResult getResult() {
+ return result;
+ }
+
+ /**
+ * Compiles classes in given source. The resulting .class files are added
+ * to an internal list which can be later retrieved by getClassFiles().
+ *
+ * @param name fully qualified java name of class being compiled.
+ * @param source source code of the class as String.
+ * @return true, if compilation succeeded, false otherwise.
+ */
+ public boolean compile(String name, String source) {
+ ICompilerRequestor requestor = this;
+ IErrorHandlingPolicy policy = DefaultErrorHandlingPolicies.exitAfterAllProblems();
+ IProblemFactory problemFactory = new DefaultProblemFactory(Locale.getDefault());
+ ICompilationUnit[] units = new ICompilationUnit[1];
+ units[0] = new CompilationUnit(name, source);
+
+ org.eclipse.jdt.internal.compiler.Compiler compiler = new org.eclipse.jdt.internal.compiler.Compiler(environment, policy, getDefaultCompilerOptions(), requestor, problemFactory);
+ compiler.compile(units);
+ return getResult().hasErrors();
+ }
+
+ /**
+ * Returns a list of JavaClassFiles that contains results of the compilation.
+ *
+ * @return resulting class files
+ */
+ public ClassFile[] getClassFiles() {
+ return getResult().getClassFiles();
+ }
+
+ public static Map<String, Object> getDefaultCompilerSettings() {
+ String javaSpecVersion = System.getProperty("java.specification.version");
+ Map<String, Object> settings = new HashMap<String, Object>();
+ settings.put(CompilerOptions.OPTION_Source, javaSpecVersion);
+ settings.put(CompilerOptions.OPTION_TargetPlatform, javaSpecVersion);
+ settings.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
+ return settings;
+ }
+
+ public static CompilerOptions getDefaultCompilerOptions() {
+ return new CompilerOptions(getDefaultCompilerSettings());
+ }
+
+ @Override
+ public void acceptResult(CompilationResult result) {
+ this.result = result;
+ for (ClassFile cf : this.result.getClassFiles()) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < cf.getCompoundName().length; i++) {
+ sb.append(cf.getCompoundName()[i]);
+ if (i < cf.getCompoundName().length - 1) {
+ sb.append('.');
+ }
+ }
+ types.put(sb.toString(), cf.getBytes());
+ }
+ }
+
+
+}
--- a/experiments/java/src/stx/libjava/tools/compiler/ecj/CompilerEnvironment.java Sun Mar 31 19:25:00 2013 +0100
+++ b/experiments/java/src/stx/libjava/tools/compiler/ecj/CompilerEnvironment.java Tue Apr 02 23:08:51 2013 +0100
@@ -1,14 +1,28 @@
package stx.libjava.tools.compiler.ecj;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
public class CompilerEnvironment implements INameEnvironment {
+ protected CompilerTypeRegistry types;
+
+ public CompilerEnvironment() {
+ types = new CompilerTypeRegistry();
+ }
+
+ public CompilerEnvironment(CompilerTypeRegistry types) {
+ this.types = types;
+ }
+
/**
* Find a type with the given compound name.
* Answer the binary form of the type if it is known to be consistent.
@@ -28,29 +42,47 @@
if (compoundTypeName.length > 1) {
for (int i = 0; i < compoundTypeName.length - 1; i++) {
sb.append(compoundTypeName[i]);
+ sb.append('.');
}
}
sb.append(compoundTypeName[compoundTypeName.length-1]);
return findType(sb.toString());
}
- protected NameEnvironmentAnswer findType(String javaname) {
+ /**
+ * Returns a IBinaryType for class with given name or null
+ * if there's no such class.
+ * @param name
+ * @return binary type or null (if no type is found)
+ */
+ protected IBinaryType findTypeForClassNamed(String name) {
+ IBinaryType type;
+
+ type = types.get(name);
+ if (type != null) return type;
+
try {
- Class<?> c = Class.forName(javaname);
- ClassLoader cl = c.getClassLoader();
- if (cl == null) {
- cl = ClassLoader.getSystemClassLoader();
+ Class<?> c = Class.forName(name);
+ InputStream cfs = findClassFileForClass(c);
+ if (cfs == null) {
+ return null;
+ } else {
+ types.put(name, cfs);
+ return types.get(name);
}
- String cfilename = (new String(c.getName())).replace('.', '/') + ".class";
- InputStream cfs = cl.getResourceAsStream(cfilename);
- return new NameEnvironmentAnswer(ClassFileReader.read(cfs, cfilename), null);
} catch (ClassNotFoundException cnfe) {
return null;
- } catch (ClassFormatException e) {
+ } catch (RuntimeException e) {
e.printStackTrace();
return null;
- } catch (IOException e) {
- e.printStackTrace();
+ }
+ }
+
+ protected NameEnvironmentAnswer findType(String name) {
+ IBinaryType type = findTypeForClassNamed(name);
+ if (type != null) {
+ return new NameEnvironmentAnswer(type, null);
+ } else {
return null;
}
}
@@ -100,7 +132,30 @@
* the code which created it to decide when it is a good time to clean it up.
*/
public void cleanup() {
-
+
}
-
+
+ /**
+ * Given a class, return an InputStream on corresponding .class file.
+ * @return InputStream or null
+ */
+ public InputStream findClassFileForClass(Class<?> c) {
+ /* STX:LIBJAVA specific: ask the class for its classfile bytes... */
+ if (System.getProperty("java.vm.name").equals("Smalltalk/X")) {
+ byte[] bytes = findClassBytesForClass0(c);
+ if (bytes != null) {
+ return new ByteArrayInputStream(bytes);
+ }
+ }
+
+ ClassLoader cl = c.getClassLoader();
+ if (cl == null) {
+ cl = ClassLoader.getSystemClassLoader();
+ }
+ String cfilename = (new String(c.getName())).replace('.', '/') + ".class";
+ return cl.getResourceAsStream(cfilename);
+ }
+
+ public native byte[] findClassBytesForClass0(Class<?> c);
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/experiments/java/src/stx/libjava/tools/compiler/ecj/CompilerTypeRegistry.java Tue Apr 02 23:08:51 2013 +0100
@@ -0,0 +1,45 @@
+package stx.libjava.tools.compiler.ecj;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+
+/**
+ * A registry for binary types. Eventually will do some caching in the future...
+ * @author Jan Vrany
+ *
+ */
+public class CompilerTypeRegistry {
+ protected Map<String, IBinaryType> typeMap = new HashMap<String, IBinaryType>();
+
+ public IBinaryType get(String name) {
+ return typeMap.get(name);
+ }
+
+ public void put(String name, IBinaryType type) {
+ typeMap.put(name,type);
+ }
+
+ public void put(String name, InputStream classfile) {
+ try {
+ put(name, ClassFileReader.read(classfile, (new String(name).replace('.', '/') + ".class")));
+ } catch (ClassFormatException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void put(String name, byte[] classfile) {
+ put(name, new ByteArrayInputStream(classfile));
+ }
+
+
+
+}
--- a/experiments/java/src/stx/libjava/tools/compiler/ecj/tests/CompilerTests.java Sun Mar 31 19:25:00 2013 +0100
+++ b/experiments/java/src/stx/libjava/tools/compiler/ecj/tests/CompilerTests.java Tue Apr 02 23:08:51 2013 +0100
@@ -4,7 +4,7 @@
import java.lang.reflect.InvocationTargetException;
-import stx.libjava.tools.compiler.ecj.Compiler;
+import stx.libjava.tools.compiler.ecj.CompilerAdapter;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.junit.Test;
@@ -21,7 +21,7 @@
@Test
public void test_01() {
- Compiler c = new Compiler();
+ CompilerAdapter c = new CompilerAdapter();
ClassLoader l = new ClassLoader();
c.compile("test.pkg.Foo", "package test.pkg; public class Foo {}");
@@ -43,7 +43,7 @@
*/
@Test
public void test_02() {
- Compiler c = new Compiler();
+ CompilerAdapter c = new CompilerAdapter();
ClassLoader l = new ClassLoader();
c.compile("test.pkg.Foo", "package test.pkg; public class Foo { public void f() { g(); } }");
@@ -68,5 +68,40 @@
}
}
+ /**
+ * Tests compilation of depending classes
+ */
+ @Test
+ public void test_03() {
+ CompilerAdapter c = new CompilerAdapter();
+ ClassLoader l = new ClassLoader();
+
+ c.compile("test.pkg.Foo", "package test.pkg; public class Foo { public void f() { } }");
+ assertEquals(1, c.getClassFiles().length);
+ assertFalse(c.getResult().hasErrors());
+
+ c.compile("test.pkg.Bar", "package test.pkg; public class Bar { public void f() { new Foo(); } }");
+ assertEquals(1, c.getClassFiles().length);
+ assertFalse(c.getResult().hasErrors());
+
+ }
+ @Test
+ public void test_04() {
+ CompilerAdapter c = new CompilerAdapter();
+ ClassLoader l = new ClassLoader();
+
+ c.compile("test.pkg.Foo", "package test.pkg; import static java.lang.System.*; public class Foo {}");
+
+ assertFalse(c.getResult().hasErrors());
+
+ ClassFile[] classfiles = c.getResult().getClassFiles();
+
+ assertEquals(1, classfiles.length);
+
+ Class<?> clazz = l.load(classfiles[0].getBytes());
+
+ assertEquals("test.pkg.Foo" , clazz.getName());
+ }
+
}