From 7f29b3919565a74c2dbce859677ef58bd9d5530d Mon Sep 17 00:00:00 2001 From: Michael Uhl Date: Fri, 26 Jul 2019 10:12:53 +0200 Subject: [PATCH] Generic Method inserts. --- .../bytecode/utilities/SimplifyResult.java | 6 + .../de/dhbwstuttgart/core/JavaTXCompiler.java | 20 +- .../syntaxtree/GenericDeclarationList.java | 20 +- .../typedeployment/TypeInsertFactory.java | 177 +++++++++++++----- 4 files changed, 165 insertions(+), 58 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java index 6517c2bc..ef4e6087 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/SimplifyResult.java @@ -8,6 +8,7 @@ import java.util.HashMap; import java.util.HashSet; import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; /** @@ -34,6 +35,11 @@ public class SimplifyResult { public HashMap>> getMethodsConstraints() { return methodsConstraints; } + + public HashMap> getMethodsConstraints(String methodReturnType) { + + return methodsConstraints.get(methodReturnType); + } public ArrayList getTphsClass() { return tphsClass; diff --git a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java index e7af8af2..d06d3495 100644 --- a/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -58,6 +58,7 @@ import org.apache.commons.io.output.NullOutputStream; public class JavaTXCompiler { + public static JavaTXCompiler INSTANCE; final CompilationEnvironment environment; Boolean resultmodel = true; public final Map sourceFiles = new HashMap<>(); @@ -73,11 +74,13 @@ public class JavaTXCompiler { public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException { this(Arrays.asList(sourceFile)); + INSTANCE = this; } public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException { this(sourceFile); this.log = log; + INSTANCE = this; } public JavaTXCompiler(List sources) throws IOException, ClassNotFoundException { @@ -85,6 +88,7 @@ public class JavaTXCompiler { for (File s : sources) { sourceFiles.put(s, parse(s)); } + INSTANCE = this; } public ConstraintSet getConstraints() throws ClassNotFoundException { @@ -654,20 +658,26 @@ public class JavaTXCompiler { SourceFile ret = generator.convert(tree, environment.packageCrawler); return ret; } + // um pfad erweitern public void generateBytecode(String path) throws ClassNotFoundException, IOException, BytecodeGeneratorError { for(File f : sourceFiles.keySet()) { HashMap classFiles = new HashMap<>(); SourceFile sf = sourceFiles.get(f); List typeinferenceResult = this.typeInference(); - 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); + generateBytecodForFile(path, classFiles, sf, typeinferenceResult); } } + public void generateBytecodForFile(String path, HashMap classFiles, SourceFile sf, + List 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 classFiles, String path) throws IOException { FileOutputStream output; for(String name : classFiles.keySet()) { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java b/src/main/java/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java index 6a264684..426b57f3 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java @@ -2,6 +2,10 @@ package de.dhbwstuttgart.syntaxtree; import org.antlr.v4.runtime.Token; +import com.google.common.collect.Lists; + +import de.dhbwstuttgart.parser.NullToken; + import java.util.*; @@ -15,11 +19,21 @@ public class GenericDeclarationList extends SyntaxTreeNode implements Iterable gtvs = new ArrayList<>(); - - public GenericDeclarationList(List values, Token endOffset) { + + @SuppressWarnings("unchecked") + public GenericDeclarationList(Iterable values, Token endOffset) { + super(endOffset); + gtvs = isListOfGenericTypeVar(values) ? (List)values : Lists.newArrayList(values); + this.offsetOfLastElement = endOffset; + } + + public GenericDeclarationList(ArrayList values, Token endOffset) { super(endOffset); gtvs = values; - this.offsetOfLastElement = endOffset; + this.offsetOfLastElement = endOffset; } + + private boolean isListOfGenericTypeVar(Iterable values) { + return values instanceof List && ((List)values).size() > 0 && ((List)values).get(0) instanceof GenericTypeVar; } @Override diff --git a/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java b/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java index 3fee03f6..576c944e 100644 --- a/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java +++ b/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java @@ -1,11 +1,32 @@ 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.statement.NewArray; import de.dhbwstuttgart.syntaxtree.type.*; 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.Map.Entry; +import java.util.stream.Collectors; + +import javax.print.DocFlavor.STRING; +import javax.security.auth.kerberos.KerberosKey; /** * TODO: @@ -31,60 +52,116 @@ public class TypeInsertFactory { ResultSet resultSet) { ResolvedType resolvedType = resultSet.resolveType(type); TypeInsertPoint insertPoint = new TypeInsertPoint(offset, - new TypeToInsertString(resolvedType.resolvedType).insert); + new TypeToInsertString(resolvedType.resolvedType).insert); + + List>> simplifyResults = JavaTXCompiler.INSTANCE.getSimplifyResults(); + for (List> simplifyResultsEntries : simplifyResults) { + for (HashMap 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()); } - private static TypeInsertPoint createGenericInsert(Set toInsert, ClassOrInterface cl, Method m){ - //Momentan wird Methode ignoriert. Parameter werden immer als Klassenparameter angefügt: - //Offset zum Einstzen bestimmen: - Token offset; - String insert = ""; - String end; - if(cl.getGenerics().iterator().hasNext()){ - //offset = cl.getGenerics().iterator().next().getOffset(); - offset = cl.getGenerics().getOffset(); - end=","; - }else{ - offset = cl.getGenerics().getOffset(); - insert += "<"; - end = ">"; + private static Set createGenericInsert(SimplifyResult genericResult, ClassOrInterface cl, Method m, ResultSet resultSet){ + Set result = createGenericClassInserts(genericResult, cl); + + for (Method method : cl.getMethods()) { + + for (Entry>> resultFromApi : genericResult.getMethodsConstraints().entrySet()) { + createMethodConstraints(method, resultFromApi); + + } } - - //Alle einzusetzenden Generics und deren Bounds bestimmen: - HashMap> 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 it = genericsAndBounds.keySet().iterator(); - if(! it.hasNext())return new TypeInsertPoint(offset, ""); - while(it.hasNext()){ - TypePlaceholder tph = it.next(); - insert += tph.getName(); - Set bounds = genericsAndBounds.get(tph); - if(bounds.size() > 0){ - insert += " extends "; - Iterator 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); + + return result; } + + private static Set createMethodConstraints(Method method, Entry>> resultFromApi) { + Set result = new HashSet<>(); + Token offset = new GenericDeclarationList(method.getGenerics(), new NullToken()).getOffset(); + + if (! (resultFromApi.getKey().contains(method.getName()))) { + return result; + } + + List methodConstraints = new ArrayList<>(resultFromApi.getValue().keySet()); + List tphsMethod = + new ArrayList(((Collection>)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 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 createGenericClassInserts(SimplifyResult genericResult, ClassOrInterface cl) { + Set result = new HashSet<>(); + Token offset = cl.getGenerics().getOffset(); + + List classConstraints = new ArrayList(genericResult.getClassConstraints()); + List 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 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{