forked from JavaTX/JavaCompilerCore
113 lines
4.7 KiB
Java
113 lines
4.7 KiB
Java
|
package de.dhbwstuttgart.environment;
|
|||
|
|
|||
|
import java.io.File;
|
|||
|
import java.io.IOException;
|
|||
|
import java.net.MalformedURLException;
|
|||
|
import java.net.URL;
|
|||
|
import java.util.*;
|
|||
|
|
|||
|
import com.google.common.collect.Lists;
|
|||
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
|||
|
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
|||
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
|||
|
|
|||
|
import de.dhbwstuttgart.exceptions.DebugException;
|
|||
|
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
|||
|
import de.dhbwstuttgart.parser.JavaTXParser;
|
|||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.SourceFileContext;
|
|||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser.SrcfileContext;
|
|||
|
import de.dhbwstuttgart.parser.scope.GatherNames;
|
|||
|
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
|
|||
|
|
|||
|
/**
|
|||
|
* Stellt die Java-Environment dar und speichert alle Binarys, Librarys und Sourcefiles im zu kompilierenden Projekt Sie erstellt anhand dieser Informationen die JavaClassNameRegistry
|
|||
|
*
|
|||
|
* TODO: Zur Initialisierung der CompilationEnvironment sollten alle SourceFiles mit ANTLR geparst werden und alle Klassen Generics und Typen herausgefunden werden
|
|||
|
*/
|
|||
|
public class CompilationEnvironment {
|
|||
|
private final List<URL> librarys;
|
|||
|
private final List<File> sourceFiles;
|
|||
|
public final PackageCrawler packageCrawler;
|
|||
|
|
|||
|
/**
|
|||
|
* Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enth<EFBFBD>lt automatisch die Java Standard Library
|
|||
|
*
|
|||
|
* @param sourceFiles die zu kompilierenden Dateien
|
|||
|
*/
|
|||
|
public CompilationEnvironment(List<File> sourceFiles) {
|
|||
|
/**
|
|||
|
* Java 9 bringt einige Änderungen am Classloader So funktioniert der BootClassLoader nicht mehr. hier gibts ein paar Quellen zum nachlesen: http://java9.wtf/class-loading/ https://stackoverflow.com/questions/46494112/classloaders-hierarchy-in-java-9
|
|||
|
*
|
|||
|
*/
|
|||
|
// String bootClassPath = System.getProperty("sun.boot.class.path");
|
|||
|
// DirectoryClassLoader cl = DirectoryClassLoader.getPlatformClassLoader();
|
|||
|
String bootClassPath = System.getProperty("java.class.path");
|
|||
|
librarys = new ArrayList<>();
|
|||
|
for (String path : bootClassPath.split(File.pathSeparator)) {
|
|||
|
try {
|
|||
|
librarys.add(new URL("file:" + path));
|
|||
|
} catch (MalformedURLException e) {
|
|||
|
new DebugException("Fehler im Classpath auf diesem System");
|
|||
|
}
|
|||
|
}
|
|||
|
// URLClassLoader loader = new URLClassLoader(new URL[0], cl);
|
|||
|
// librarys = Arrays.asList(loader.getURLs());
|
|||
|
|
|||
|
this.sourceFiles = sourceFiles;
|
|||
|
this.packageCrawler = new PackageCrawler(librarys);
|
|||
|
}
|
|||
|
|
|||
|
public void addClassesToRegistry(JavaClassRegistry registry, SourceFileContext tree, File sourceFile, JavaTXCompiler compiler) throws ClassNotFoundException, IOException {
|
|||
|
Map<String, Integer> allNames;
|
|||
|
if (tree instanceof SrcfileContext srcfile) {
|
|||
|
allNames = GatherNames.getNames((SrcfileContext) tree, packageCrawler, compiler);
|
|||
|
for (Class c : loadDefaultPackageClasses(getPackageName(srcfile), sourceFile, compiler)) {
|
|||
|
allNames.put(c.getName(), c.getTypeParameters().length);
|
|||
|
}
|
|||
|
registry.addNames(allNames);
|
|||
|
} else {
|
|||
|
throw new NotImplementedException();
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public static List<Class> loadDefaultPackageClasses(String packageName, File sourceFile, JavaTXCompiler compiler) throws IOException, ClassNotFoundException {
|
|||
|
ClassLoader classLoader = compiler.getClassLoader();
|
|||
|
List<Class> ret = new ArrayList<>();
|
|||
|
// Set classLoader to include default package for this specific source file
|
|||
|
File dir = sourceFile.getAbsoluteFile().getParentFile();
|
|||
|
String dirPath = dir.toString() + "/";
|
|||
|
if (packageName.length() > 0)
|
|||
|
dirPath = dirPath.substring(0, dirPath.length() - packageName.length() - 1);
|
|||
|
String path = dirPath;
|
|||
|
ArrayList<File> defaultPath = Lists.newArrayList(new File(path));
|
|||
|
classLoader = new DirectoryClassLoader(defaultPath, 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);
|
|||
|
if (className.matches("Fun\\d+\\$\\$.*"))
|
|||
|
continue;
|
|||
|
ret.add(classLoader.loadClass(packageName + className));
|
|||
|
}
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
private static String getPackageName(SrcfileContext forTree) {
|
|||
|
String packageName = "";
|
|||
|
if (forTree.packageDeclaration() != null && !forTree.packageDeclaration().qualifiedName().identifier().isEmpty())
|
|||
|
packageName = forTree.packageDeclaration().qualifiedName().getText();
|
|||
|
return packageName;
|
|||
|
}
|
|||
|
|
|||
|
public List<ClassOrInterface> getAllAvailableClasses() {
|
|||
|
List<ClassOrInterface> ret = new ArrayList<>();
|
|||
|
for (Class c : new PackageCrawler(librarys).getAllAvailableClasses()) {
|
|||
|
ret.add(ASTFactory.createClass(c));
|
|||
|
}
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
}
|