diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index 98626fde..658f0c65 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -14,6 +14,7 @@ import de.dhbwstuttgart.parser.antlr.Java8Parser.CompilationUnitContext; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.TypeScope; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; @@ -87,22 +88,27 @@ public class JavaTXCompiler { INSTANCE = this; } - public ConstraintSet getConstraints() throws ClassNotFoundException { + public ConstraintSet getConstraints() throws ClassNotFoundException, IOException { List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); - for (SourceFile sf : sourceFiles.values()) { + for (File f : this.sourceFiles.keySet()) { + SourceFile sf = sourceFiles.get(f); allClasses.addAll(sf.getClasses()); - } + } List importedClasses = new ArrayList<>(); //Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC - for (File forSourceFile : sourceFiles.keySet()) + for (File forSourceFile : sourceFiles.keySet()){ for (JavaClassName name : sourceFiles.get(forSourceFile).getImports()) { //TODO: Hier werden imports von eigenen (.jav) Klassen nicht beachtet ClassOrInterface importedClass = ASTFactory.createClass( classLoader.loadClass(name.toString())); importedClasses.add(importedClass); } + for(Class c : CompilationEnvironment.loadDefaultPackageClasses(forSourceFile, classLoader)){ + ClassOrInterface importedClass = ASTFactory.createClass(c); + importedClasses.add(importedClass); + } + } allClasses.addAll(importedClasses); - return new TYPE(sourceFiles.values(), allClasses).getConstraints(); } @@ -288,12 +294,14 @@ public class JavaTXCompiler { */ public UnifyResultModel typeInferenceAsync(UnifyResultListener resultListener, Writer logFile) - throws ClassNotFoundException { + throws ClassNotFoundException, IOException { List allClasses = new ArrayList<>();// environment.getAllAvailableClasses(); // Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC - for (SourceFile sf : this.sourceFiles.values()) { + for (File f : this.sourceFiles.keySet()) { + SourceFile sf = sourceFiles.get(f); allClasses.addAll(getAvailableClasses(sf)); allClasses.addAll(sf.getClasses()); + allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(f,classLoader).stream().map(ASTFactory::createClass).collect(Collectors.toList())); } final ConstraintSet cons = getConstraints(); @@ -456,12 +464,14 @@ public class JavaTXCompiler { return urm; } - public List typeInference() throws ClassNotFoundException { + public List typeInference() throws ClassNotFoundException, IOException { List allClasses = new ArrayList<>();// environment.getAllAvailableClasses(); // Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC - for (SourceFile sf : this.sourceFiles.values()) { + for (File f : this.sourceFiles.keySet()) { + SourceFile sf = sourceFiles.get(f); allClasses.addAll(getAvailableClasses(sf)); allClasses.addAll(sf.getClasses()); + allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(f,classLoader).stream().map(ASTFactory::createClass).collect(Collectors.toList())); } final ConstraintSet cons = getConstraints(); @@ -742,7 +752,7 @@ public class JavaTXCompiler { public List getGeneratedGenericResultsForAllSourceFiles() - throws ClassNotFoundException { + throws ClassNotFoundException, IOException { List result = new ArrayList<>(); for (File f : sourceFiles.keySet()) { SourceFile sf = sourceFiles.get(f); diff --git a/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java b/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java index 43196b6f..682e1eea 100644 --- a/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java +++ b/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java @@ -1,15 +1,18 @@ package de.dhbwstuttgart.environment; import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.*; +import com.google.common.collect.Lists; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import org.antlr.v4.runtime.tree.TerminalNode; import org.reflections.Reflections; import org.reflections.scanners.ResourcesScanner; import org.reflections.scanners.SubTypesScanner; @@ -70,9 +73,40 @@ public class CompilationEnvironment { Map allNames; CompilationUnitContext tree = JavaTXParser.parse(forSourceFile); allNames = GatherNames.getNames(tree, packageCrawler, classLoader); + for(Class c : loadDefaultPackageClasses(forSourceFile, classLoader)){ + allNames.put(c.getName(), c.getTypeParameters().length); + } return new JavaClassRegistry(allNames); } + public static List loadDefaultPackageClasses(File forSourceFile, ClassLoader classLoader) throws IOException, ClassNotFoundException { + List ret = new ArrayList<>(); + String packageName = getPackageName(JavaTXParser.parse(forSourceFile)); + //Set classLoader to include default package for this specific source file + File dir = new File(forSourceFile.getParent()); + String dirPath = dir.toString() + "/"; + if(packageName.length()>0)dirPath = dirPath.substring(0,dirPath.length() - packageName.length()); + String path = "file://" + dirPath; + ArrayList defaultPath = Lists.newArrayList(new URL(path)); + classLoader = new URLClassLoader(defaultPath.toArray(new URL[0]), classLoader); + //Gather all names in the default package for this source file (classes that are imported by default) + File [] files = dir.listFiles((dir1, name) -> name.endsWith(".class")); + if(files != null)for (File classFile : files) { + String className = classFile.getName().substring(0,classFile.getName().length()-6); + ret.add(classLoader.loadClass(packageName + className)); + } + return ret; + } + + private static String getPackageName(CompilationUnitContext forTree){ + String packageName = ""; + if(forTree.packageDeclaration() != null && forTree.packageDeclaration().Identifier() != null) + for(TerminalNode subPackage : forTree.packageDeclaration().Identifier()){ + packageName += subPackage.toString() + "."; + } + return packageName; + } + public List getAllAvailableClasses() { List ret = new ArrayList<>(); for(Class c : new PackageCrawler(librarys).getAllAvailableClasses()){ diff --git a/src/main/java/de/dhbwstuttgart/parser/scope/GatherNames.java b/src/main/java/de/dhbwstuttgart/parser/scope/GatherNames.java index 31c6d375..8e93355b 100644 --- a/src/main/java/de/dhbwstuttgart/parser/scope/GatherNames.java +++ b/src/main/java/de/dhbwstuttgart/parser/scope/GatherNames.java @@ -7,6 +7,7 @@ import java.util.*; import de.dhbwstuttgart.parser.antlr.Java8BaseListener; import de.dhbwstuttgart.syntaxtree.AbstractASTWalker; import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; +import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.antlr.v4.runtime.tree.TerminalNode; import de.dhbwstuttgart.environment.PackageCrawler; @@ -63,12 +64,11 @@ public class GatherNames { } } } - ret.putAll(getImports(ctx, packages, classLoader)); - return ret; + ret.putAll(getImports(ctx, packages, classLoader)); + return ret; } - - public static Map getImports(Java8Parser.CompilationUnitContext ctx, PackageCrawler packages, ClassLoader classLoader) throws ClassNotFoundException { + public static Map getImports(Java8Parser.CompilationUnitContext ctx, PackageCrawler packages, ClassLoader classLoader) throws ClassNotFoundException { Map ret = new HashMap<>(); //ret.putAll(packages.getClassNames("java.lang")); for(Java8Parser.ImportDeclarationContext importDeclCtx : ctx.importDeclaration()){ diff --git a/src/test/java/packages/ImportTest.java b/src/test/java/packages/ImportTest.java index b13918c6..4ae04779 100644 --- a/src/test/java/packages/ImportTest.java +++ b/src/test/java/packages/ImportTest.java @@ -25,6 +25,12 @@ public class ImportTest extends TestCase { File f = new File(rootDirectory + "output/de/test/ToImport.class"); assertTrue(f.exists()); + compiler = new JavaTXCompiler(new File(rootDirectory+"ToImport.jav")); + compiler.typeInference(); + compiler.generateBytecode(null); + f = new File(rootDirectory + "ToImport.class"); + assertTrue(f.exists()); + compiler = new JavaTXCompiler(new File(rootDirectory+"subpackage1/ToImport2.jav")); compiler.typeInference(); compiler.generateBytecode(rootDirectory + "output/"); @@ -83,4 +89,20 @@ public class ImportTest extends TestCase { f = new File(rootDirectory + "ImportTest2.class"); assertTrue(f.exists()); } + + @Test + public void testImportDefaultPackage() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler( + Lists.newArrayList(new File(rootDirectory+"ImportTestDefault.jav"))); + compiler.typeInference(); + File f = new File(rootDirectory + "ImportTestDefault.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(null); + f = new File(rootDirectory + "ImportTestDefault.class"); + assertTrue(f.exists()); + } + + } diff --git a/src/test/java/packages/LoadDefaultPackageClassesTest.java b/src/test/java/packages/LoadDefaultPackageClassesTest.java new file mode 100644 index 00000000..25af87ef --- /dev/null +++ b/src/test/java/packages/LoadDefaultPackageClassesTest.java @@ -0,0 +1,39 @@ +package packages; + +import com.google.common.collect.Lists; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.environment.CompilationEnvironment; +import junit.framework.TestCase; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; + +public class LoadDefaultPackageClassesTest extends TestCase { + + public static final String rootDirectory = System.getProperty("user.dir")+"/src/test/resources/javFiles/packageTest/"; + + + public LoadDefaultPackageClassesTest() throws ClassNotFoundException, IOException { + /* + Generate ToImport class in rootDirectory and in output-Directory + */ + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"Gen.jav")); + compiler.typeInference(); + compiler.generateBytecode(); + File f = new File(rootDirectory + "Gen.class"); + assertTrue(f.exists()); + } + + public void testLoadGenClass() throws IOException, ClassNotFoundException { + CompilationEnvironment.loadDefaultPackageClasses(new File( rootDirectory + "Test.jav"), ClassLoader.getSystemClassLoader()); + + } + public void testURLClassLoader() throws IOException, ClassNotFoundException { + URLClassLoader cl = new URLClassLoader(new URL[]{new URL("file://"+rootDirectory)}, ClassLoader.getSystemClassLoader()); + cl.loadClass("Gen"); + } + +} diff --git a/src/test/resources/javFiles/packageTest/Gen.jav b/src/test/resources/javFiles/packageTest/Gen.jav new file mode 100644 index 00000000..3b58b188 --- /dev/null +++ b/src/test/resources/javFiles/packageTest/Gen.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; +import java.util.Vector; + +public class Gen{ + Vector m(Vector v){ + return v; + } +} diff --git a/src/test/resources/javFiles/packageTest/Test.jav b/src/test/resources/javFiles/packageTest/Test.jav new file mode 100644 index 00000000..2f6429a1 --- /dev/null +++ b/src/test/resources/javFiles/packageTest/Test.jav @@ -0,0 +1,3 @@ + +public class Test{ +} diff --git a/src/test/resources/javFiles/packageTest/de/test/ImportTestDefault.jav b/src/test/resources/javFiles/packageTest/de/test/ImportTestDefault.jav new file mode 100644 index 00000000..ecd8d7c5 --- /dev/null +++ b/src/test/resources/javFiles/packageTest/de/test/ImportTestDefault.jav @@ -0,0 +1,7 @@ +package de.test; + +class ImportTestDefault{ + void methode(){ + new ToImport(); + } +} \ No newline at end of file diff --git a/src/test/resources/javFiles/packageTest/de/test/output/de/test/mathStrucVectoruse.java b/src/test/resources/javFiles/packageTest/de/test/output/de/test/mathStrucVectoruse.java new file mode 100644 index 00000000..54b9e45b --- /dev/null +++ b/src/test/resources/javFiles/packageTest/de/test/output/de/test/mathStrucVectoruse.java @@ -0,0 +1,10 @@ +package de.test; +import de.test.mathStrucVector; + + +class mathStrucVectorUse { + + public static void main(String[] args) { + new mathStrucVector().main(); + } +} diff --git a/src/test/resources/javFiles/packageTest/de/test/output/mathStrucVectoruse.java b/src/test/resources/javFiles/packageTest/de/test/output/mathStrucVectoruse.java new file mode 100644 index 00000000..9a9b2e75 --- /dev/null +++ b/src/test/resources/javFiles/packageTest/de/test/output/mathStrucVectoruse.java @@ -0,0 +1,8 @@ + + +class mathStrucVectorUse { + + public static void main(String[] args) { + new mathStrucVector().main(); + } +} diff --git a/vorgehen.md b/vorgehen.md index 0854c152..a83ca18f 100644 --- a/vorgehen.md +++ b/vorgehen.md @@ -32,6 +32,17 @@ * damit lässt sich ein andere ort zur Ausgabe der Class-files bestimmen # Tasks +* Es steht nur noch ein Task aus: +## Klassen aus Default Package laden +* Das kann für jede SourceFile anders sein +* Momentan funktioniert der Compiler sowieso nur mit einer SourceFile! +* an allen Stellen, an denen die Imports der SourceFile beachtet werden, müssen jetzt auch alle Klassen aus dem gleichen Ordner beachtet werden + +### Stand +* CompilationEnvironment wurde erweitert und kann alle Klassen aus einem Ordner laden +* Allerdings funktionieren manche Tests noch nicht +* Die Bytecode-Tests funktionieren nicht, da sich kaputte Klassen im Bytecode-Jav-Ordner befinden + ## Class files in richtigen Ordner legen ## * Wenn Pfad übergeben, dann in Pfad + packageName * Ohne Pfad, direkt neben die Source File legen