Compare commits
9 Commits
37c58be1f3
...
LSP-Interf
Author | SHA1 | Date | |
---|---|---|---|
|
c9d38728af | ||
|
b7fad6e3c7 | ||
|
3cb9b74df1 | ||
|
effc31782f | ||
|
2a24eab9d3 | ||
|
b29eb71238 | ||
|
e9ce071e2b | ||
3567bae0d7 | |||
|
a314013f40 |
4
pom.xml
4
pom.xml
@@ -73,8 +73,8 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<version>3.14.0</version>
|
||||
<configuration>
|
||||
<compilerArgs>--enable-preview</compilerArgs>
|
||||
<source>23</source>
|
||||
<target>23</target>
|
||||
<source>24</source>
|
||||
<target>24</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
@@ -1778,7 +1778,7 @@ public class Codegen {
|
||||
|
||||
cw2.visitEnd();
|
||||
var bytes = cw2.toByteArray();
|
||||
converter.auxiliaries.put(className, bytes);
|
||||
compiler.auxiliaries.put(className, bytes);
|
||||
|
||||
// TODO These class loading shenanigans happen in a few places, the tests load the classes individually.
|
||||
// Instead we should just look at the folder.
|
||||
|
@@ -2,6 +2,7 @@
|
||||
package de.dhbwstuttgart.core;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.Codegen;
|
||||
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
||||
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
@@ -74,6 +75,11 @@ public class JavaTXCompiler {
|
||||
public final List<File> classPath;
|
||||
private final File outputPath;
|
||||
|
||||
public final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
|
||||
public final Set<Integer> usedFunNSuperTypes = new HashSet<>();
|
||||
|
||||
public Map<String, byte[]> auxiliaries = new HashMap<>();
|
||||
|
||||
public DirectoryClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
@@ -726,7 +732,7 @@ public class JavaTXCompiler {
|
||||
}
|
||||
generatedGenerics.put(sf, converter.javaGenerics());
|
||||
converter.generateFunNTypes();
|
||||
converter.auxiliaries.forEach((name, source) -> {
|
||||
auxiliaries.forEach((name, source) -> {
|
||||
generatedClasses.put(new JavaClassName(name), source);
|
||||
});
|
||||
return generatedClasses;
|
||||
|
@@ -5,6 +5,7 @@ import de.dhbwstuttgart.bytecode.Codegen;
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
||||
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.NameGenerator;
|
||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||
@@ -47,59 +48,28 @@ public class LanguageServerInterface {
|
||||
* You have to give the input as well as the path because of potential locks when the File is currently opened in an IDE.
|
||||
* Example: file:///c:/test/main.jav -> file:///c:/test/out/main.class
|
||||
*
|
||||
* @param path the URI of the File. See Example.
|
||||
* @param pathAsString the URI of the File. See Example.
|
||||
* @throws IOException
|
||||
* @throws ClassNotFoundException
|
||||
* @throws URISyntaxException
|
||||
*/
|
||||
public LanguageServerTransferObject getResultSetAndAbstractSyntax(String path) throws IOException, ClassNotFoundException, URISyntaxException {
|
||||
public LanguageServerTransferObject getResultSetAndAbstractSyntax(String pathAsString) throws IOException, ClassNotFoundException, URISyntaxException {
|
||||
System.setOut(new PrintStream(OutputStream.nullOutputStream()));
|
||||
|
||||
//
|
||||
// System.setOut(new PrintStream(OutputStream.nullOutputStream()));
|
||||
//
|
||||
//
|
||||
// URI uri = new URI(path);
|
||||
// ArrayList<String> pathWithoutName = new ArrayList<>(List.of(uri.getPath().split("/")));
|
||||
// pathWithoutName.remove(List.of(uri.getPath().split("/")).size() - 1);
|
||||
// String stringPathWithoutName = "";
|
||||
//
|
||||
// for (String i : pathWithoutName) {
|
||||
// stringPathWithoutName += "/" + i;
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// FileUtils.cleanDirectory(new File(stringPathWithoutName + "/out"));
|
||||
// } catch (Exception e) {
|
||||
//
|
||||
// }
|
||||
// try {
|
||||
// (new File(stringPathWithoutName + "/out")).mkdirs();
|
||||
// } catch (Exception e) {
|
||||
//
|
||||
// }
|
||||
// var test = getLanguageServerTransferObject(uri.getPath().split("/")[uri.getPath().split("/").length - 1], new ByteArrayClassLoader(), new File(stringPathWithoutName).getPath());
|
||||
// System.setOut(System.out);
|
||||
// return test;
|
||||
// File oldTempSourcefile = new File(stringPathWithoutName + "/out/" + uri.getPath().split("/")[uri.getPath().split("/").length - 1].replace(".jav", ".tmp"));
|
||||
// File oldTempOutFile = new File(stringPathWithoutName + "/out/" + uri.getPath().split("/")[uri.getPath().split("/").length - 1].replace(".jav", ".class"));
|
||||
// Files.deleteIfExists(oldTempSourcefile.toPath());
|
||||
// Files.deleteIfExists(oldTempOutFile.toPath());
|
||||
// FileUtils.deleteDirectory(oldTempSourcefile);
|
||||
//
|
||||
// File tempSourcefile = new File(stringPathWithoutName + "/out/" + uri.getPath().split("/")[uri.getPath().split("/").length - 1].replace(".jav", ".tmp"));
|
||||
// File tempOutFile = new File(stringPathWithoutName + "/out/");
|
||||
// FileUtils.writeStringToFile(tempSourcefile, input, "UTF-8");
|
||||
//
|
||||
// //TODO: Enable for multiple Class-Files
|
||||
// JavaTXCompiler tx = new JavaTXCompiler(new ArrayList<File>(List.of(tempSourcefile)), new ArrayList<File>(List.of((tempSourcefile))), tempOutFile);
|
||||
// var result = tx.getResultSetAndAbstractSyntax(tempSourcefile);
|
||||
// System.setOut(System.out);
|
||||
// tempSourcefile.delete();
|
||||
// tempOutFile.delete();
|
||||
// return result;
|
||||
var uri = new URI(pathAsString);
|
||||
var path = Path.of(uri);
|
||||
var file = path.toFile();
|
||||
Files.createDirectories(path.getParent().resolve("out"));
|
||||
var compiler = new JavaTXCompiler(List.of(file), List.of(path.getParent().toFile()), path.getParent().resolve("out").toFile());
|
||||
|
||||
var parsedSource = compiler.sourceFiles.get(file);
|
||||
var tiResults = compiler.typeInference(file);
|
||||
|
||||
return null;
|
||||
Map<JavaClassName, byte[]> bytecode = compiler.generateBytecode(parsedSource, tiResults);
|
||||
Files.createDirectories(path.getParent().resolve("out"));
|
||||
compiler.writeClassFile(bytecode, path.getParent().resolve("out").toFile(), false);
|
||||
|
||||
return new LanguageServerTransferObject(tiResults, parsedSource, "", compiler.getGeneratedGenerics());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,138 +112,9 @@ public class LanguageServerInterface {
|
||||
return test;
|
||||
}
|
||||
|
||||
private static void writeClassFile(String name, byte[] code, Path outputPath) throws IOException {
|
||||
Files.createDirectories(outputPath);
|
||||
Files.write(outputPath.resolve(name + ".class"), code);
|
||||
}
|
||||
|
||||
public static Map<String, ? extends Class<?>> generateClassFiles(IByteArrayClassLoader classLoader, Path path, Path outputPath, String... files) throws IOException, ClassNotFoundException {
|
||||
Files.createDirectories(outputPath);
|
||||
var filenames = Arrays.stream(files).map(filename -> Path.of(path.toString(), filename).toFile()).toList();
|
||||
var compiler = new JavaTXCompiler(filenames, List.of(path.toFile(), outputPath.toFile()), outputPath.toFile());
|
||||
|
||||
var result = new HashMap<String, Class<?>>();
|
||||
for (var file : filenames) {
|
||||
var resultSet = compiler.typeInference(file);
|
||||
|
||||
var sourceFile = compiler.sourceFiles.get(file);
|
||||
var converter = new ASTToTargetAST(compiler, resultSet, sourceFile, classLoader);
|
||||
var classes = compiler.sourceFiles.get(file).getClasses();
|
||||
|
||||
result.putAll(classes.stream().map(cli -> {
|
||||
try {
|
||||
return generateClass(converter.convert(cli), classLoader, converter, outputPath);
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}).collect(Collectors.toMap(Class::getName, Function.identity())));
|
||||
|
||||
converter.generateFunNTypes();
|
||||
|
||||
for (var entry : converter.auxiliaries.entrySet()) {
|
||||
writeClassFile(entry.getKey(), entry.getValue(), outputPath);
|
||||
}
|
||||
}
|
||||
|
||||
for (var entry : compiler.loadedClasses.entrySet()) {
|
||||
var name = entry.getKey().toString();
|
||||
result.put(name, classLoader.loadClass(Path.of(entry.getValue().classFile().toURI())));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Class<?> generateClass(TargetStructure clazz, IByteArrayClassLoader classLoader, ASTToTargetAST converter, Path outputPath) throws IOException {
|
||||
Codegen codegen = new Codegen(clazz, converter.compiler, converter);
|
||||
var code = codegen.generate();
|
||||
writeClassFile(clazz.qualifiedName().getClassName(), code, outputPath);
|
||||
return classLoader.loadClass(code);
|
||||
}
|
||||
|
||||
public static Map<String, ? extends Class<?>> generateClassFiles(String filename, IByteArrayClassLoader classLoader, String filePath) throws IOException, ClassNotFoundException {
|
||||
var file = Path.of(filePath, filename).toFile();
|
||||
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), Path.of(filePath + "/out").toFile());
|
||||
var resultSet = compiler.typeInference(file);
|
||||
|
||||
var sourceFile = compiler.sourceFiles.get(file);
|
||||
var converter = new ASTToTargetAST(compiler, resultSet, sourceFile, classLoader);
|
||||
var classes = compiler.sourceFiles.get(file).getClasses();
|
||||
|
||||
var result = classes.stream().map(cli -> {
|
||||
try {
|
||||
return generateClass(converter.convert(cli), classLoader, converter, Path.of(filePath + "/out/"));
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}).collect(Collectors.toMap(Class::getName, Function.identity()));
|
||||
|
||||
converter.generateFunNTypes();
|
||||
|
||||
for (var entry : converter.auxiliaries.entrySet()) {
|
||||
writeClassFile(entry.getKey(), entry.getValue(), Path.of(filePath + "/out/"));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SourceFile getAST(String filename, String filePath) throws IOException, ClassNotFoundException {
|
||||
var file = Path.of(filePath, filename).toFile();
|
||||
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), Path.of(filePath + "/out").toFile());
|
||||
return compiler.sourceFiles.get(file);
|
||||
}
|
||||
|
||||
public static LanguageServerTransferObject getLanguageServerTransferObject(String filename, IByteArrayClassLoader classLoader, String filePath) throws IOException, ClassNotFoundException {
|
||||
var file = Path.of(filePath, filename).toFile();
|
||||
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), Path.of(filePath + "/out").toFile());
|
||||
var resultSet = compiler.typeInference(file);
|
||||
|
||||
var sourceFile = compiler.sourceFiles.get(file);
|
||||
var converter = new ASTToTargetAST(compiler, resultSet, sourceFile, classLoader);
|
||||
compiler.generateBytecode();
|
||||
converter.generateFunNTypes();
|
||||
|
||||
var ta = converter.javaGenerics();
|
||||
var tb = converter.txGenerics();
|
||||
Map<SourceFile, List<GenericsResult>> generics = new HashMap<>();
|
||||
|
||||
ArrayList<GenericsResult> genericsResults = new ArrayList<>();
|
||||
genericsResults.addAll(ta);
|
||||
genericsResults.addAll(tb);
|
||||
generics.put(converter.compiler.sourceFiles.values().stream().findFirst().get(), ta);
|
||||
var test = new LanguageServerTransferObject(resultSet, converter.compiler.sourceFiles.values().stream().findFirst().get(), "", compiler.getGeneratedGenerics());
|
||||
return test;
|
||||
}
|
||||
|
||||
/**
|
||||
* generates Bytecode for the given Path of the File.
|
||||
* The Generated Bytecode can be found in the same place as the path, except the File lies in an /out/ Directory
|
||||
* Example: file:///c:/test/main.jav -> file:///c:/test/out/main.class
|
||||
*
|
||||
* @param uri the URI of the File. See Example.
|
||||
* @throws IOException
|
||||
* @throws ClassNotFoundException
|
||||
* @throws URISyntaxException
|
||||
*/
|
||||
public void generateBytecode(URI uri) throws IOException, ClassNotFoundException, URISyntaxException {
|
||||
|
||||
// System.setOut(new PrintStream(OutputStream.nullOutputStream()));
|
||||
//
|
||||
//
|
||||
// File inputDir = new File(uri.getPath());
|
||||
// File outFile = new File(uri.getPath() + "/out");
|
||||
// FileUtils.cleanDirectory(outFile);
|
||||
// String[] allowedEndings = {".jav"};
|
||||
// ArrayList<File> files = new ArrayList<>();
|
||||
//
|
||||
// try (Stream<Path> stream = Files.walk(Paths.get(inputDir.toURI()))) {
|
||||
// stream.filter(Files::isRegularFile)
|
||||
// .forEach(el -> files.add(el.toFile()));
|
||||
// }
|
||||
//
|
||||
//
|
||||
// List<String> javFiles = files.stream().filter(el -> el.getName().split("\\.").length >= 2 && el.getName().split("\\.")[el.getName().split("\\.").length - 1].contains("jav")).map(el -> el.getPath().replace(inputDir.getPath(), "").substring(1)).toList();
|
||||
// //TODO: Link between Files
|
||||
// generateClassFiles(new ByteArrayClassLoader(), Path.of(inputDir.toURI()), Path.of(outFile.toURI()), javFiles.toArray(new String[0]));
|
||||
// System.setOut(System.out);
|
||||
}
|
||||
}
|
||||
|
@@ -150,7 +150,7 @@ public class StatementGenerator {
|
||||
} else {
|
||||
type = methodparameters?
|
||||
TypePlaceholder.fresh(fp.getStart(), 1, false)
|
||||
: TypePlaceholder.fresh(fp.getStart());
|
||||
: TypePlaceholder.fresh(fp.getStart(), 1, false);
|
||||
}
|
||||
ret.add(new FormalParameter(paramName, type, fp.getStart()));
|
||||
localVars.put(paramName, type);
|
||||
@@ -1065,7 +1065,7 @@ public class StatementGenerator {
|
||||
List<Pattern> parameterList = new ArrayList<>();
|
||||
for (IdentifierContext identifier : lambdaParams.identifier()) {
|
||||
Token offset = identifier.getStart();
|
||||
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset), offset));
|
||||
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset, 1, false), offset));
|
||||
}
|
||||
params = new ParameterList(parameterList, lambdaParams.getStart());
|
||||
} else if (lambdaParams.formalParameterList() != null) {
|
||||
@@ -1075,7 +1075,7 @@ public class StatementGenerator {
|
||||
List<Pattern> parameterList = new ArrayList<>();
|
||||
for (LambdaLVTIParameterContext param : lambdaParams.lambdaLVTIList().lambdaLVTIParameter()) {
|
||||
Token offset = param.getStart();
|
||||
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset), offset));
|
||||
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset, 1, false), offset));
|
||||
}
|
||||
params = new ParameterList(parameterList, lambdaParams.getStart());
|
||||
} else {
|
||||
|
@@ -6,10 +6,12 @@ import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.target.tree.TargetGeneric;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
|
||||
@@ -31,6 +33,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
private List<RefType> implementedInterfaces;
|
||||
private List<RefType> permittedSubtypes;
|
||||
private List<Constructor> constructors;
|
||||
private Set<GenericTypeVar> userDefinedGenerics;
|
||||
|
||||
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset, String fileName) {
|
||||
super(offset);
|
||||
@@ -199,4 +202,22 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
public int hashCode() {
|
||||
return Objects.hash(name);
|
||||
}
|
||||
|
||||
public Set<GenericTypeVar> getUserDefinedGenerics() {
|
||||
if (this.userDefinedGenerics != null) return this.userDefinedGenerics;
|
||||
|
||||
var genericsIter = getGenerics().iterator();
|
||||
if (genericsIter.hasNext()) {
|
||||
// Add empty set of generics to cache so that it doesn't try to calculate it later
|
||||
this.userDefinedGenerics = new HashSet<>();
|
||||
while (genericsIter.hasNext()) {
|
||||
var next = genericsIter.next();
|
||||
userDefinedGenerics.add(next);
|
||||
}
|
||||
} else {
|
||||
this.userDefinedGenerics = new HashSet<>();
|
||||
}
|
||||
|
||||
return this.userDefinedGenerics;
|
||||
}
|
||||
}
|
||||
|
@@ -5,8 +5,10 @@ import java.util.*;
|
||||
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
//import sun.security.x509.X509CertInfo;
|
||||
|
||||
public class SourceFile extends SyntaxTreeNode {
|
||||
@@ -18,6 +20,7 @@ public class SourceFile extends SyntaxTreeNode {
|
||||
private boolean isGenerated;
|
||||
|
||||
public List<ClassOrInterface> availableClasses = new ArrayList<>();
|
||||
public List<ASTToTargetAST.Generics> generics = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei.
|
||||
@@ -40,6 +43,10 @@ public class SourceFile extends SyntaxTreeNode {
|
||||
this.imports = new HashSet<>(sf.imports);
|
||||
}
|
||||
|
||||
public void addResultSet(ResultSet rs) {
|
||||
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.pkgName = packageName;
|
||||
}
|
||||
|
@@ -37,7 +37,6 @@ public class ASTToTargetAST {
|
||||
public Generics generics;
|
||||
public List<Generics> currentMethodOverloads;
|
||||
|
||||
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
|
||||
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
|
||||
private Method currentMethod;
|
||||
|
||||
@@ -62,9 +61,11 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
|
||||
public Generics(JavaTXCompiler compiler, ResultSet set) {
|
||||
this(new JavaGenerics(compiler, set), new TxGenerics(compiler, set));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public IByteArrayClassLoader classLoader;
|
||||
protected SourceFile sourceFile;
|
||||
|
||||
@@ -82,9 +83,9 @@ public class ASTToTargetAST {
|
||||
|
||||
all = new ArrayList<>();
|
||||
for (var set : resultSets) {
|
||||
all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set)));
|
||||
all.add(new Generics(compiler, set));
|
||||
}
|
||||
this.generics = all.get(0);
|
||||
this.generics = all.getFirst();
|
||||
}
|
||||
|
||||
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
|
||||
@@ -94,9 +95,13 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList) {
|
||||
return findMethod(owner, name, argumentList, this.generics.javaGenerics, this.compiler);
|
||||
}
|
||||
|
||||
public static Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList, GenerateGenerics generics, JavaTXCompiler compiler) {
|
||||
Optional<Method> method = Optional.empty();
|
||||
while (method.isEmpty()) {
|
||||
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)).findFirst();
|
||||
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList, generics)).findFirst();
|
||||
if (owner.getClassName().toString().equals("java.lang.Object")) break;
|
||||
owner = compiler.getClass(owner.getSuperClass().getName());
|
||||
}
|
||||
@@ -104,16 +109,16 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
Optional<Constructor> findConstructor(ClassOrInterface owner, List<TargetType> argumentList) {
|
||||
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList)).findFirst();
|
||||
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList, generics.javaGenerics)).findFirst();
|
||||
}
|
||||
|
||||
boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments) {
|
||||
static boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments, GenerateGenerics generics) {
|
||||
var pars = parameterList.getFormalparalist();
|
||||
if (pars.size() != arguments.size())
|
||||
return false;
|
||||
|
||||
for (var i = 0; i < pars.size(); i++) {
|
||||
var type1 = convert(pars.get(i).getType(), generics.javaGenerics);
|
||||
var type1 = generics.getTargetType(pars.get(i).getType());
|
||||
var type2 = arguments.get(i);
|
||||
if (type1 instanceof TargetGenericType)
|
||||
return true;
|
||||
@@ -351,19 +356,14 @@ public class ASTToTargetAST {
|
||||
Set<TargetGeneric> javaGenerics = new HashSet<>();
|
||||
Set<TargetGeneric> txGenerics = new HashSet<>();
|
||||
|
||||
var genericsIter = input.getGenerics().iterator();
|
||||
if (genericsIter.hasNext()) {
|
||||
var userDefinedGenerics = input.getUserDefinedGenerics();
|
||||
if (!userDefinedGenerics.isEmpty()) {
|
||||
// Add empty set of generics to cache so that it doesn't try to calculate it later
|
||||
var userDefinedGenerics = new HashSet<GenericTypeVar>();
|
||||
this.userDefinedGenerics.put(input, userDefinedGenerics);
|
||||
while (genericsIter.hasNext()) {
|
||||
var next = genericsIter.next();
|
||||
userDefinedGenerics.add(next);
|
||||
// TODO Support multiple bounds
|
||||
javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().get(0))));
|
||||
for (var generic : userDefinedGenerics) {
|
||||
// TODO Support multiple bouds
|
||||
javaGenerics.add(new TargetGeneric(generic.getName(), convert(generic.getBounds().getFirst())));
|
||||
}
|
||||
} else {
|
||||
this.userDefinedGenerics.put(input, new HashSet<>());
|
||||
// Generate generics only if there are no user defined ones
|
||||
javaGenerics = convert(generics.javaGenerics.generics(input), generics.javaGenerics);
|
||||
txGenerics = convert(generics.txGenerics.generics(input), generics.txGenerics);
|
||||
@@ -425,7 +425,7 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
|
||||
generics = all.get(0);
|
||||
generics = all.getFirst();
|
||||
List<TargetConstructor> result = new ArrayList<>();
|
||||
Set<List<MethodParameter>> parameterSet = new HashSet<>();
|
||||
this.currentMethod = input;
|
||||
@@ -469,13 +469,6 @@ public class ASTToTargetAST {
|
||||
}
|
||||
}
|
||||
|
||||
private TargetType unwrap(TargetType type) {
|
||||
if (type instanceof TargetRefType ref) {
|
||||
if (!ref.params().isEmpty()) return new TargetRefType(ref.name());
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType) {
|
||||
if (methods.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
|
||||
if (methods.size() == 1) {
|
||||
@@ -746,11 +739,6 @@ public class ASTToTargetAST {
|
||||
return new TargetField(input.modifier, convert(input.getType(), generics.javaGenerics), input.getName());
|
||||
}
|
||||
|
||||
private final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
|
||||
private final Set<Integer> usedFunNSuperTypes = new HashSet<>();
|
||||
|
||||
public Map<String, byte[]> auxiliaries = new HashMap<>();
|
||||
|
||||
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
|
||||
return convert(input, generics.javaGenerics);
|
||||
}
|
||||
@@ -819,20 +807,24 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
public void generateFunNTypes() {
|
||||
for (var entry : usedFunN.entrySet()) {
|
||||
for (var entry : compiler.usedFunN.entrySet()) {
|
||||
var gep = entry.getValue();
|
||||
var superInterfaces = usedFunN.values().stream()
|
||||
var superInterfaces = compiler.usedFunN.values().stream()
|
||||
.filter(g -> !g.equals(gep))
|
||||
.filter(genericParameters -> isSubtype(gep, genericParameters))
|
||||
.map(FunNGenerator::getSpecializedClassName)
|
||||
.toList();
|
||||
|
||||
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces);
|
||||
auxiliaries.put(entry.getKey(), code);
|
||||
compiler.auxiliaries.put(entry.getKey(), code);
|
||||
}
|
||||
}
|
||||
|
||||
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
|
||||
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
|
||||
return convert(input, generics, compiler);
|
||||
}
|
||||
|
||||
public static TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics, JavaTXCompiler compiler) {
|
||||
return input.acceptTV(new TypeVisitor<>() {
|
||||
@Override
|
||||
public TargetType visit(RefType refType) {
|
||||
@@ -844,31 +836,31 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
var params = refType.getParaList().stream().map(type -> {
|
||||
return convert(type, generics);
|
||||
return convert(type, generics, compiler);
|
||||
}).toList();
|
||||
|
||||
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
|
||||
var returnType = FunNGenerator.getReturnType(params);
|
||||
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), returnType);
|
||||
if (!usedFunNSuperTypes.contains(params.size())) {
|
||||
usedFunNSuperTypes.add(params.size());
|
||||
if (!compiler.usedFunNSuperTypes.contains(params.size())) {
|
||||
compiler.usedFunNSuperTypes.add(params.size());
|
||||
var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
|
||||
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
|
||||
try {
|
||||
classLoader.findClass(superClassName);
|
||||
compiler.classLoader.findClass(superClassName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
classLoader.loadClass(superClassName, code);
|
||||
compiler.classLoader.loadClass(superClassName, code);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
auxiliaries.put(superClassName, code);
|
||||
compiler.auxiliaries.put(superClassName, code);
|
||||
}
|
||||
FunNGenerator.GenericParameters gep = null;
|
||||
if (!usedFunN.containsKey(className)) {
|
||||
if (!compiler.usedFunN.containsKey(className)) {
|
||||
gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0);
|
||||
usedFunN.put(className, gep);
|
||||
compiler.usedFunN.put(className, gep);
|
||||
} else {
|
||||
gep = usedFunN.get(className);
|
||||
gep = compiler.usedFunN.get(className);
|
||||
}
|
||||
return flattenFunNType(params, gep);
|
||||
}
|
||||
@@ -877,7 +869,7 @@ public class ASTToTargetAST {
|
||||
|
||||
@Override
|
||||
public TargetType visit(SuperWildcardType superWildcardType) {
|
||||
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics));
|
||||
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics, compiler));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -887,7 +879,7 @@ public class ASTToTargetAST {
|
||||
|
||||
@Override
|
||||
public TargetType visit(ExtendsWildcardType extendsWildcardType) {
|
||||
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics));
|
||||
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics, compiler));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.parser.JavaTXParser;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||
@@ -18,7 +20,7 @@ import java.util.stream.Stream;
|
||||
|
||||
public abstract class GenerateGenerics {
|
||||
|
||||
private final ASTToTargetAST astToTargetAST;
|
||||
private final JavaTXCompiler compiler;
|
||||
|
||||
public class TPH {
|
||||
private final TypePlaceholder wrap;
|
||||
@@ -134,8 +136,8 @@ public abstract class GenerateGenerics {
|
||||
Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
|
||||
Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
|
||||
|
||||
GenerateGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
|
||||
this.astToTargetAST = astToTargetAST;
|
||||
GenerateGenerics(JavaTXCompiler compiler, ResultSet constraints) {
|
||||
this.compiler = compiler;
|
||||
for (var constraint : constraints.results) {
|
||||
if (constraint instanceof PairTPHsmallerTPH p) {
|
||||
System.out.println(p.left + " " + p.left.getVariance());
|
||||
@@ -281,7 +283,7 @@ public abstract class GenerateGenerics {
|
||||
Set<TPH> typeVariablesOfClass,
|
||||
Set<Pair> result
|
||||
) {
|
||||
var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner);
|
||||
var userDefinedGenericsOfClass = owner.getUserDefinedGenerics();
|
||||
|
||||
// Type variables with bounds that are also type variables of the method
|
||||
for (var typeVariable : new HashSet<>(typeVariables)) {
|
||||
@@ -329,7 +331,7 @@ public abstract class GenerateGenerics {
|
||||
|
||||
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
|
||||
if (expressionReceiver.expr instanceof This) {
|
||||
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(astToTargetAST::convert).toList());
|
||||
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
|
||||
if (optMethod.isEmpty()) return;
|
||||
var method2 = optMethod.get();
|
||||
System.out.println("In: " + method.getName() + " Method: " + method2.getName());
|
||||
@@ -1005,8 +1007,8 @@ public abstract class GenerateGenerics {
|
||||
}
|
||||
var type = concreteTypes.get(new TPH(tph));
|
||||
if (type == null) return new TargetGenericType(tph.getName());
|
||||
return astToTargetAST.convert(type, this);
|
||||
return ASTToTargetAST.convert(type, this, compiler);
|
||||
}
|
||||
return astToTargetAST.convert(in, this);
|
||||
return ASTToTargetAST.convert(in, this, compiler);
|
||||
}
|
||||
}
|
||||
|
@@ -69,8 +69,4 @@ public class GenericsResult {
|
||||
return this.generics.getType(tph);
|
||||
return type;
|
||||
}
|
||||
|
||||
public TargetType resolveTarget(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||
return this.generics.getTargetType(type);
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.Method;
|
||||
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
@@ -7,8 +8,8 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
import java.util.Set;
|
||||
|
||||
final class JavaGenerics extends GenerateGenerics {
|
||||
JavaGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
|
||||
super(astToTargetAST, constraints);
|
||||
JavaGenerics(JavaTXCompiler compiler, ResultSet constraints) {
|
||||
super(compiler, constraints);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.Method;
|
||||
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
@@ -7,8 +8,8 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
import java.util.Set;
|
||||
|
||||
final class TxGenerics extends GenerateGenerics {
|
||||
TxGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
|
||||
super(astToTargetAST, constraints);
|
||||
TxGenerics(JavaTXCompiler compiler, ResultSet constraints) {
|
||||
super(compiler, constraints);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,51 +0,0 @@
|
||||
package languageServerInterfaceTest;
|
||||
|
||||
import de.dhbwstuttgart.core.ConsoleInterface;
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.NameGenerator;
|
||||
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import de.dhbwstuttgart.languageServerInterface.LanguageServerInterface;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class LangaugeServerInterfaceTest {
|
||||
@Test
|
||||
@Ignore
|
||||
public void consoleInterfaceTest() throws IOException, ClassNotFoundException, URISyntaxException {
|
||||
|
||||
|
||||
LanguageServerInterface languageServerInterface = new LanguageServerInterface();
|
||||
var resp = languageServerInterface.getResultSetAndAbstractSyntax("/home/ruben/code/JavaCompilerCore/src/test/java/languageServerInterfaceTest/test.jav");
|
||||
|
||||
System.out.println("\n-----------------------------------------\n");
|
||||
System.out.println(ASTPrinter.print(resp.getAst()));
|
||||
System.out.println("\n-----------------------------------------\n");
|
||||
|
||||
LanguageServerInterface languageServerInterface2 = new LanguageServerInterface();
|
||||
var ast = languageServerInterface2.getAst("/home/ruben/code/JavaCompilerCore/src/test/java/languageServerInterfaceTest/test.jav", "N");
|
||||
|
||||
System.out.println("\n-----------------------------------------\n");
|
||||
System.out.println(ASTPrinter.print(ast));
|
||||
System.out.println("\n-----------------------------------------\n");
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testBytecodeGen() throws IOException, ClassNotFoundException, URISyntaxException {
|
||||
|
||||
//TODO: Ordner und Datei löschen wenn sie bereits existieren
|
||||
LanguageServerInterface languageServerInterface = new LanguageServerInterface();
|
||||
languageServerInterface.generateBytecode(new URI("c%3A/Users/ruben/Neuer%20Ordner%20%282%29/LSP-Vortrag/images/"));
|
||||
}
|
||||
}
|
@@ -66,7 +66,7 @@ public class TestCodegen {
|
||||
|
||||
converter.generateFunNTypes();
|
||||
|
||||
for (var entry : converter.auxiliaries.entrySet()) {
|
||||
for (var entry : compiler.auxiliaries.entrySet()) {
|
||||
writeClassFile(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public class TestCodegen {
|
||||
|
||||
converter.generateFunNTypes();
|
||||
|
||||
for (var entry : converter.auxiliaries.entrySet()) {
|
||||
for (var entry : compiler.auxiliaries.entrySet()) {
|
||||
writeClassFile(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user