Generic Method inserts.

This commit is contained in:
Michael Uhl 2019-07-26 10:12:53 +02:00
parent f6669f8c13
commit 7f29b39195
4 changed files with 165 additions and 58 deletions

View File

@ -8,6 +8,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
/** /**
@ -34,6 +35,11 @@ public class SimplifyResult {
public HashMap<String, HashMap<TPHConstraint, HashSet<String>>> getMethodsConstraints() { public HashMap<String, HashMap<TPHConstraint, HashSet<String>>> getMethodsConstraints() {
return methodsConstraints; return methodsConstraints;
} }
public HashMap<TPHConstraint, HashSet<String>> getMethodsConstraints(String methodReturnType) {
return methodsConstraints.get(methodReturnType);
}
public ArrayList<String> getTphsClass() { public ArrayList<String> getTphsClass() {
return tphsClass; return tphsClass;

View File

@ -58,6 +58,7 @@ import org.apache.commons.io.output.NullOutputStream;
public class JavaTXCompiler { public class JavaTXCompiler {
public static JavaTXCompiler INSTANCE;
final CompilationEnvironment environment; final CompilationEnvironment environment;
Boolean resultmodel = true; Boolean resultmodel = true;
public final Map<File, SourceFile> sourceFiles = new HashMap<>(); public final Map<File, SourceFile> sourceFiles = new HashMap<>();
@ -73,11 +74,13 @@ public class JavaTXCompiler {
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException { public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
this(Arrays.asList(sourceFile)); this(Arrays.asList(sourceFile));
INSTANCE = this;
} }
public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException { public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException {
this(sourceFile); this(sourceFile);
this.log = log; this.log = log;
INSTANCE = this;
} }
public JavaTXCompiler(List<File> sources) throws IOException, ClassNotFoundException { public JavaTXCompiler(List<File> sources) throws IOException, ClassNotFoundException {
@ -85,6 +88,7 @@ public class JavaTXCompiler {
for (File s : sources) { for (File s : sources) {
sourceFiles.put(s, parse(s)); sourceFiles.put(s, parse(s));
} }
INSTANCE = this;
} }
public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException { public ConstraintSet<Pair> getConstraints() throws ClassNotFoundException {
@ -654,20 +658,26 @@ public class JavaTXCompiler {
SourceFile ret = generator.convert(tree, environment.packageCrawler); SourceFile ret = generator.convert(tree, environment.packageCrawler);
return ret; return ret;
} }
// um pfad erweitern // um pfad erweitern
public void generateBytecode(String path) throws ClassNotFoundException, IOException, BytecodeGeneratorError { public void generateBytecode(String path) throws ClassNotFoundException, IOException, BytecodeGeneratorError {
for(File f : sourceFiles.keySet()) { for(File f : sourceFiles.keySet()) {
HashMap<String,byte[]> classFiles = new HashMap<>(); HashMap<String,byte[]> classFiles = new HashMap<>();
SourceFile sf = sourceFiles.get(f); SourceFile sf = sourceFiles.get(f);
List<ResultSet> typeinferenceResult = this.typeInference(); List<ResultSet> typeinferenceResult = this.typeInference();
BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult,sf,path); generateBytecodForFile(path, classFiles, sf, typeinferenceResult);
// BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult.get(0));
bytecodeGen.visit(sf);
this.simplifyResultsSF.add(bytecodeGen.getSimplifyResultsList());
this.writeClassFile(bytecodeGen.getClassFiles(), path);
} }
} }
public void generateBytecodForFile(String path, HashMap<String, byte[]> classFiles, SourceFile sf,
List<ResultSet> typeinferenceResult) throws IOException {
BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult,sf,path);
// BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult.get(0));
bytecodeGen.visit(sf);
this.simplifyResultsSF.add(bytecodeGen.getSimplifyResultsList());
this.writeClassFile(bytecodeGen.getClassFiles(), path);
}
private void writeClassFile(HashMap<String, byte[]> classFiles, String path) throws IOException { private void writeClassFile(HashMap<String, byte[]> classFiles, String path) throws IOException {
FileOutputStream output; FileOutputStream output;
for(String name : classFiles.keySet()) { for(String name : classFiles.keySet()) {

View File

@ -2,6 +2,10 @@ package de.dhbwstuttgart.syntaxtree;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import com.google.common.collect.Lists;
import de.dhbwstuttgart.parser.NullToken;
import java.util.*; import java.util.*;
@ -15,11 +19,21 @@ public class GenericDeclarationList extends SyntaxTreeNode implements Iterable<G
private Token offsetOfLastElement; private Token offsetOfLastElement;
private List<GenericTypeVar> gtvs = new ArrayList<>(); private List<GenericTypeVar> gtvs = new ArrayList<>();
public GenericDeclarationList(List<GenericTypeVar> values, Token endOffset) { @SuppressWarnings("unchecked")
public GenericDeclarationList(Iterable<? extends GenericTypeVar> values, Token endOffset) {
super(endOffset);
gtvs = isListOfGenericTypeVar(values) ? (List<GenericTypeVar>)values : Lists.newArrayList(values);
this.offsetOfLastElement = endOffset;
}
public GenericDeclarationList(ArrayList<GenericTypeVar> values, Token endOffset) {
super(endOffset); super(endOffset);
gtvs = values; gtvs = values;
this.offsetOfLastElement = endOffset; this.offsetOfLastElement = endOffset; }
private boolean isListOfGenericTypeVar(Iterable<? extends GenericTypeVar> values) {
return values instanceof List && ((List<?>)values).size() > 0 && ((List<?>)values).get(0) instanceof GenericTypeVar;
} }
@Override @Override

View File

@ -1,11 +1,32 @@
package de.dhbwstuttgart.typedeployment; package de.dhbwstuttgart.typedeployment;
import de.dhbwstuttgart.bytecode.Exception.BytecodeGeneratorError;
import de.dhbwstuttgart.bytecode.constraint.TPHConstraint;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.utilities.SimplifyResult;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.NewArray;
import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.typeinference.result.*; import de.dhbwstuttgart.typeinference.result.*;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.parse.ANTLRParser.action_return;
import org.antlr.v4.parse.ANTLRParser.block_return;
import org.antlr.v4.parse.ANTLRParser.labeledAlt_return;
import org.antlr.v4.parse.ANTLRParser.parserRule_return;
import org.antlr.v4.runtime.Token;
import org.stringtemplate.v4.compiler.STParser.ifstat_return;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.*; import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import javax.print.DocFlavor.STRING;
import javax.security.auth.kerberos.KerberosKey;
/** /**
* TODO: * TODO:
@ -31,60 +52,116 @@ public class TypeInsertFactory {
ResultSet resultSet) { ResultSet resultSet) {
ResolvedType resolvedType = resultSet.resolveType(type); ResolvedType resolvedType = resultSet.resolveType(type);
TypeInsertPoint insertPoint = new TypeInsertPoint(offset, TypeInsertPoint insertPoint = new TypeInsertPoint(offset,
new TypeToInsertString(resolvedType.resolvedType).insert); new TypeToInsertString(resolvedType.resolvedType).insert);
List<List<HashMap<String, SimplifyResult>>> simplifyResults = JavaTXCompiler.INSTANCE.getSimplifyResults();
for (List<HashMap<String, SimplifyResult>> simplifyResultsEntries : simplifyResults) {
for (HashMap<String, SimplifyResult> simplifyResultsEntriesEntries : simplifyResultsEntries) {
if (simplifyResultsEntriesEntries.get(cl.getClassName().toString()) != null) {
SimplifyResult genericResult = simplifyResultsEntriesEntries.get(cl.getClassName().toString());
return new TypeInsert(insertPoint, createGenericInsert(genericResult, cl, m, resultSet), resolvedType.getResultPair());
}
}
}
return new TypeInsert(insertPoint, new HashSet<>(), resolvedType.getResultPair()); return new TypeInsert(insertPoint, new HashSet<>(), resolvedType.getResultPair());
} }
private static TypeInsertPoint createGenericInsert(Set<GenericInsertPair> toInsert, ClassOrInterface cl, Method m){ private static Set<TypeInsertPoint> createGenericInsert(SimplifyResult genericResult, ClassOrInterface cl, Method m, ResultSet resultSet){
//Momentan wird Methode ignoriert. Parameter werden immer als Klassenparameter angefügt: Set<TypeInsertPoint> result = createGenericClassInserts(genericResult, cl);
//Offset zum Einstzen bestimmen:
Token offset; for (Method method : cl.getMethods()) {
String insert = "";
String end; for (Entry<String, HashMap<TPHConstraint, HashSet<String>>> resultFromApi : genericResult.getMethodsConstraints().entrySet()) {
if(cl.getGenerics().iterator().hasNext()){ createMethodConstraints(method, resultFromApi);
//offset = cl.getGenerics().iterator().next().getOffset();
offset = cl.getGenerics().getOffset(); }
end=",";
}else{
offset = cl.getGenerics().getOffset();
insert += "<";
end = ">";
} }
//Alle einzusetzenden Generics und deren Bounds bestimmen: return result;
HashMap<TypePlaceholder, HashSet<TypePlaceholder>> genericsAndBounds = new HashMap<>();
for(GenericInsertPair p : toInsert){
if(!genericsAndBounds.containsKey(p.TA1)){
genericsAndBounds.put((TypePlaceholder) p.TA1, new HashSet<>());
}
if(p.TA2 != null){
genericsAndBounds.get(p.TA1).add((TypePlaceholder) p.TA2);
if(!genericsAndBounds.containsKey(p.TA2)){
genericsAndBounds.put((TypePlaceholder) p.TA2, new HashSet<>());
}
}
}
//String zum Einsetzen (Generics mit bounds) generieren:
Iterator<TypePlaceholder> it = genericsAndBounds.keySet().iterator();
if(! it.hasNext())return new TypeInsertPoint(offset, "");
while(it.hasNext()){
TypePlaceholder tph = it.next();
insert += tph.getName();
Set<TypePlaceholder> bounds = genericsAndBounds.get(tph);
if(bounds.size() > 0){
insert += " extends ";
Iterator<TypePlaceholder> boundIt = bounds.iterator();
while(boundIt.hasNext()){
TypePlaceholder bound = boundIt.next();
insert += bound.getName();
if(boundIt.hasNext())insert += " & ";
}
}
if(it.hasNext())insert+=",";
}
return new TypeInsertPoint(offset, insert + end);
} }
private static Set<TypeInsertPoint> createMethodConstraints(Method method, Entry<String, HashMap<TPHConstraint, HashSet<String>>> resultFromApi) {
Set<TypeInsertPoint> result = new HashSet<>();
Token offset = new GenericDeclarationList(method.getGenerics(), new NullToken()).getOffset();
if (! (resultFromApi.getKey().contains(method.getName()))) {
return result;
}
List<TPHConstraint> methodConstraints = new ArrayList<>(resultFromApi.getValue().keySet());
List<String> tphsMethod =
new ArrayList<String>(((Collection<HashSet<String>>)resultFromApi.getValue().values()).stream().map(a -> a.stream()).flatMap(n -> n).collect(Collectors.toList()));
if (methodConstraints.size() == 0 && tphsMethod.size() == 0) {
result.add(new TypeInsertPoint(offset, ""));
return result;
}
String insert = " <";
for (TPHConstraint genericInsertConstraint : methodConstraints) {
insert += genericInsertConstraint.getLeft() + " extends " + genericInsertConstraint.getRight() + ", ";
}
List<String> notExtendedConstraints = tphsMethod;
for (TPHConstraint genericInsertConstraint : methodConstraints) {
for (String gen : tphsMethod) {
if (genericInsertConstraint.getLeft().equals(gen)) {
notExtendedConstraints.remove(gen);
}
}
}
for (String notExtendedConstraint : notExtendedConstraints) {
insert += notExtendedConstraint + ", ";
}
insert = insert.substring(0, insert.length() -2);
insert += ">";
result.add(new TypeInsertPoint(offset, insert));
return result;
}
private static Set<TypeInsertPoint> createGenericClassInserts(SimplifyResult genericResult, ClassOrInterface cl) {
Set<TypeInsertPoint> result = new HashSet<>();
Token offset = cl.getGenerics().getOffset();
List<TPHConstraint> classConstraints = new ArrayList<TPHConstraint>(genericResult.getClassConstraints());
List<String> tphsClass = new ArrayList<>(genericResult.getTphsClass());
if (classConstraints.size() == 0 && tphsClass.size() == 0) {
result.add(new TypeInsertPoint(offset, ""));
return result;
}
String insert = " <";
for (TPHConstraint genericInsertConstraint : classConstraints) {
insert += genericInsertConstraint.getLeft() + " extends " + genericInsertConstraint.getRight() + ", ";
}
Set<String> notExtendedConstraints = new HashSet<>(genericResult.getTphsClass());
for (TPHConstraint genericInsertConstraint : classConstraints) {
for (String gen : tphsClass) {
if (genericInsertConstraint.getLeft().equals(gen)) {
notExtendedConstraints.remove(gen);
}
}
}
for (String notExtendedConstraint : notExtendedConstraints) {
insert += notExtendedConstraint + ", ";
}
insert = insert.substring(0, insert.length() -2);
insert += ">";
result.add(new TypeInsertPoint(offset, insert));
return result;
}
} }
class TypeToInsertString implements ResultSetVisitor{ class TypeToInsertString implements ResultSetVisitor{