diff --git a/bin/.gitignore b/bin/.gitignore index 200b7277..5774d208 100644 --- a/bin/.gitignore +++ b/bin/.gitignore @@ -1 +1,8 @@ /mycompiler +/typinferenz +/userinterface +/bytecode +/myJvmDisassembler +/parser +/plugindevelopment +/syntaxTree diff --git a/src/mycompiler/SyntaxTreeNode.java b/src/mycompiler/SyntaxTreeNode.java index 108639be..53e24e5a 100644 --- a/src/mycompiler/SyntaxTreeNode.java +++ b/src/mycompiler/SyntaxTreeNode.java @@ -105,4 +105,9 @@ public abstract class SyntaxTreeNode{ } + + public boolean seesType(Type tA2) { + //TODO: Implementieren. Hier sollte ein Lookup in die Assumptions dieses Knotens erfolgen + return false; + } } diff --git a/src/mycompiler/myclass/Field.java b/src/mycompiler/myclass/Field.java index 74364fd1..b6a497f4 100644 --- a/src/mycompiler/myclass/Field.java +++ b/src/mycompiler/myclass/Field.java @@ -112,7 +112,7 @@ public abstract class Field extends SyntaxTreeNode implements TypeInsertable, Ty @Override public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph, ResultSet resultSet) { - return new TypeInsertPoint(this, resultSet.getTypeEqualTo(tph), resultSet); + return new TypeInsertPoint(this, this, resultSet.getTypeEqualTo(tph), resultSet); } /** diff --git a/src/mycompiler/myclass/FormalParameter.java b/src/mycompiler/myclass/FormalParameter.java index f30a394c..c3ef09f7 100755 --- a/src/mycompiler/myclass/FormalParameter.java +++ b/src/mycompiler/myclass/FormalParameter.java @@ -267,7 +267,7 @@ public class FormalParameter extends SyntaxTreeNode implements ITypeReplacementL ResultSet resultSet) { if(this.getOffset()<=0)return null; Type t = resultSet.getTypeEqualTo(tph); - return new TypeInsertPoint(this, t, resultSet); + return new TypeInsertPoint(this, this, t, resultSet); } diff --git a/src/mycompiler/mystatement/LocalVarDecl.java b/src/mycompiler/mystatement/LocalVarDecl.java index 487c5657..bfcc8563 100755 --- a/src/mycompiler/mystatement/LocalVarDecl.java +++ b/src/mycompiler/mystatement/LocalVarDecl.java @@ -519,7 +519,7 @@ public class LocalVarDecl extends Statement implements TypeInsertable @Override public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph, ResultSet resultSet) { - return new TypeInsertPoint(this, resultSet.getTypeEqualTo(tph),resultSet); + return new TypeInsertPoint(this, this, resultSet.getTypeEqualTo(tph),resultSet); } } // ino.end diff --git a/src/typinferenz/typedeployment/GenericTypeInsertPoint.java b/src/typinferenz/typedeployment/GenericTypeInsertPoint.java index 7f566ef7..43a2eea4 100644 --- a/src/typinferenz/typedeployment/GenericTypeInsertPoint.java +++ b/src/typinferenz/typedeployment/GenericTypeInsertPoint.java @@ -27,12 +27,6 @@ public class GenericTypeInsertPoint extends SourcePatchPoint { private GenericVarPatch patch; private GenericTypeInsertable genericInsertPoint; - - /* - * TODO: Der Generic Type Insert Point sollte mit Generics konstruiert werden. - * Dabei hält jeder InsertPoint nur ein Generic. Die <>-Klammern fügt das insertSet in den Quellcode ein. - * Die Reihenfolge der GenericTIPs ist beim Einsetzen dann egal. - */ public GenericTypeInsertPoint(GenericTypeInsertable syntaxTreeNode, GenericVarPatch gtv ,ResultSet resultSet) { this.resultSet = resultSet; @@ -177,40 +171,56 @@ public class GenericTypeInsertPoint extends SourcePatchPoint { */ class GenericVarPatch { + private Vector genericVarExtendDeclarations = new Vector(); private Vector genericVarDeclarations = new Vector(); - + /** * Fügt eine generische Variable in Form eines Pairs an. * @param p */ public void add(Pair p){ - GenericVarDeclarationPatch toAdd = new GenericVarDeclarationPatch(p); + GenericVarExtendsDeclarationPatch toAdd = new GenericVarExtendsDeclarationPatch(p); + if(!this.genericVarExtendDeclarations.contains(toAdd))this.genericVarExtendDeclarations.add(toAdd); + } + + public void addTPH(TypePlaceholder tph){ + GenericVarDeclarationPatch toAdd = new GenericVarDeclarationPatch(tph); if(!this.genericVarDeclarations.contains(toAdd))this.genericVarDeclarations.add(toAdd); } public String getInsertString(ResultSet rs){ String ret = ""; - Iterator it = this.genericVarDeclarations.iterator(); - while(it.hasNext()){ - GenericVarDeclarationPatch p = it.next(); + Iterator it1 = this.genericVarDeclarations.iterator(); + while(it1.hasNext()){ + GenericVarDeclarationPatch p = it1.next(); ret += p.getInsertString(rs); - if(it.hasNext())ret += ", "; + if(it1.hasNext())ret += ", "; + } + if(this.genericVarDeclarations.size()>0)ret+=", "; + Iterator it2 = this.genericVarExtendDeclarations.iterator(); + while(it2.hasNext()){ + GenericVarExtendsDeclarationPatch p = it2.next(); + ret += p.getInsertString(rs); + if(it2.hasNext())ret += ", "; } return ret; } + + public void add(TypePlaceholder tph) { + } } /** - * Eine Hilfsklasse zur Einsetzung einer Generischen Variable. + * Eine Hilfsklasse zur Einsetzung einer Generischen Variable mit extend Bedingung. * @author janulrich * */ -class GenericVarDeclarationPatch { +class GenericVarExtendsDeclarationPatch { private Pair genericPair; - public GenericVarDeclarationPatch(Pair p) { + public GenericVarExtendsDeclarationPatch(Pair p) { this.genericPair = p; } @@ -224,11 +234,39 @@ class GenericVarDeclarationPatch { return ret; } + @Override + public boolean equals(Object o){ + if(!(o instanceof GenericVarExtendsDeclarationPatch))return false; + if(!(this.genericPair.equals(((GenericVarExtendsDeclarationPatch)o).genericPair)))return false; + return true; + } +} + +/** + * Eine Hilfsklasse zur Einsetzung einer Generischen Variable. + * @author janulrich + * + */ +class GenericVarDeclarationPatch { + + private TypePlaceholder genericPair; + + public GenericVarDeclarationPatch(TypePlaceholder p) { + this.genericPair = p; + } + + public String getInsertString(ResultSet resultSet){ + String ret = ""; + if(this.genericPair != null){ + ret += this.genericPair.printJavaCode(resultSet); + } + return ret; + } + @Override public boolean equals(Object o){ if(!(o instanceof GenericVarDeclarationPatch))return false; if(!(this.genericPair.equals(((GenericVarDeclarationPatch)o).genericPair)))return false; return true; } - } diff --git a/src/typinferenz/typedeployment/TypeInsertPoint.java b/src/typinferenz/typedeployment/TypeInsertPoint.java index 1dca872a..c26959c5 100644 --- a/src/typinferenz/typedeployment/TypeInsertPoint.java +++ b/src/typinferenz/typedeployment/TypeInsertPoint.java @@ -25,18 +25,21 @@ public class TypeInsertPoint extends SourcePatchPoint { public Type type; private TypeInsertable point; + private SyntaxTreeNode node; /** * Dieser Konstruktor erstellt einen TypInsertPoint * @param insertPoint + * @param insertNode - muss das gleiche sein wie "insertPoint" * @param insertType * @param resultSet * @param generics - die generischen Parameter des einzusetzenden Typs */ - public TypeInsertPoint(TypeInsertable insertPoint, Type insertType, ResultSet resultSet){ + public TypeInsertPoint(TypeInsertable insertPoint, SyntaxTreeNode insertNode, Type insertType, ResultSet resultSet){ this.point = insertPoint; this.type = insertType; this.resultSet = resultSet; + this.node = insertNode; } /** @@ -46,9 +49,9 @@ public class TypeInsertPoint extends SourcePatchPoint { * @return */ public JavaCodeResult patch(String fileContent, int additionalOffset) { - String anfang = fileContent.substring(0, this.getInsertNode().getOffset()+additionalOffset); + String anfang = fileContent.substring(0, this.getInsertPoint().getOffset()+additionalOffset); JavaCodeResult mitte = this.getTypeInsertString(); - String ende = fileContent.substring(this.getInsertNode().getOffset()+additionalOffset); + String ende = fileContent.substring(this.getInsertPoint().getOffset()+additionalOffset); return new JavaCodeResult(anfang).attach(mitte).attach(ende); } @@ -67,7 +70,7 @@ public class TypeInsertPoint extends SourcePatchPoint { * @return Der Offset des TypeInsertPoints in dem geparsten Source für dessen Klasse er erstellt wurde. */ public int getOffset(){ - return this.getInsertNode().getOffset(); + return this.getInsertPoint().getOffset(); } protected Type getInsertType(){ @@ -86,15 +89,19 @@ public class TypeInsertPoint extends SourcePatchPoint { /** * @return - Der Punkt (Knoten) im Syntaxbaum, für den dieser TypeInsertPoint gilt. */ - public IItemWithOffset getInsertNode(){ + public IItemWithOffset getInsertPoint(){ return this.point; } + public SyntaxTreeNode getInsertNode(){ + return this.node; + } + @Override public boolean equals(Object obj){ if(! (obj instanceof TypeInsertPoint))return false; TypeInsertPoint equals = (TypeInsertPoint) obj; - if(!(equals.getInsertNode().equals(this.getInsertNode())))return false; + if(!(equals.getInsertPoint().equals(this.getInsertPoint())))return false; if(!(equals.getResultSet().equals(this.getResultSet())))return false; //ResultSet spielt bei Equals keine Rolle if(!(equals.getInsertType().equals(this.getInsertType())))return false; @@ -108,7 +115,7 @@ public class TypeInsertPoint extends SourcePatchPoint { while(!(ret instanceof Field || ret instanceof Class)){ ret = ret.getParent(); if(ret == null){ - throw new DebugException(this.getInsertNode().toString()+" hat kein Feld oder Klasse als Elternelement"); + throw new DebugException(this.getInsertPoint().toString()+" hat kein Feld oder Klasse als Elternelement"); } } return (GenericTypeInsertable) ret; diff --git a/src/typinferenz/typedeployment/TypeInsertSet.java b/src/typinferenz/typedeployment/TypeInsertSet.java index 802d4100..0596ea50 100644 --- a/src/typinferenz/typedeployment/TypeInsertSet.java +++ b/src/typinferenz/typedeployment/TypeInsertSet.java @@ -75,16 +75,35 @@ public class TypeInsertSet { * @param tip * @param tpj */ - public void insertType(TypeInsertPoint tip, TypePatchJob tpj){ + private void insertType(TypeInsertPoint tip, TypePatchJob tpj){ GenericVarPatch gPatch = new GenericVarPatch();//Set der Einzusetzenden generischen Variablendeklarationen + Vector pairs = new Vector<>(); for(Pair pair : this.resultSet.getConstraintsFor(tip.getInsertType().getInvolvedTypePlaceholder())){ gPatch.add(pair); + pairs.add(pair); + } + //Kontrollieren ob alle in den Paaren vorhandenen Generischen Variablen in dem Bereich vorkommen: + for(Pair pair : pairs){ + if(! tip.getInsertNode().seesType(pair.TA2)){ + for(TypePlaceholder tph : pair.getTypePlaceholder()){ + if(! pairsDeclareTPH(pairs, tph)){ + gPatch.addTPH(tph); + } + } + } } GenericTypeInsertPoint gip = new GenericTypeInsertPoint(tip.getGenericTypeVarInsertNode(), gPatch, resultSet); tpj.add(tip); tpj.add(gip); } + private boolean pairsDeclareTPH(Vector ps, TypePlaceholder tph){ + for(Pair p : ps){ + if(p.TA1.equals(tph))return true; + } + return false; + } + /** * Fügt alle Typen dieses TypeInsertSets in den übergebenen Quellcode ein * @param fileContent @@ -140,7 +159,7 @@ public class TypeInsertSet { */ public TypeInsertPoint getInsertPointFor(TypeInsertable node){ for(TypeInsertPoint point : points){ - if(point.getInsertNode().equals(node))return point; + if(point.getInsertPoint().equals(node))return point; } return null; } diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest13.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest13.jav new file mode 100644 index 00000000..e11264c8 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest13.jav @@ -0,0 +1,5 @@ +class Matrix{ + op(m){ + return (f) -> f.apply(m,this); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest13.java b/test/plugindevelopment/TypeInsertTests/LambdaTest13.java new file mode 100644 index 00000000..44f02d9b --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest13.java @@ -0,0 +1,16 @@ +package plugindevelopment.TypeInsertTests; + +import java.util.Vector; + +import org.junit.Test; + +public class LambdaTest13 { + private static final String TEST_FILE = "LambdaTest13.jav"; + + @Test + public void run(){ + Vector mustContain = new Vector(); + //mustContain.add("A a"); + MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java b/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java index 16229e7b..2c897b04 100644 --- a/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java +++ b/test/plugindevelopment/TypeInsertTests/MultipleTypesInsertTester.java @@ -10,6 +10,7 @@ import mycompiler.MyCompiler; import mycompiler.MyCompilerAPI; import mycompiler.myparser.JavaParser.yyException; import mycompiler.mytypereconstruction.TypeinferenceResultSet; +import typinferenz.typedeployment.TypeInsertPoint; import typinferenz.typedeployment.TypeInsertSet; public class MultipleTypesInsertTester extends TypeInsertTester{ @@ -46,4 +47,34 @@ public class MultipleTypesInsertTester extends TypeInsertTester{ } } + public static void testSingleInsert(String sourceFileToInfere, Vector mustContain){ + String gesamterSrc = ""; + String inferedSource = ""; + MyCompilerAPI compiler = MyCompiler.getAPI(); + try { + compiler.parse(new File(rootDirectory + sourceFileToInfere)); + Vector results = compiler.typeReconstruction(); + //TestCase.assertTrue("Es darf nicht mehr als eine Lösungsmöglichkeit geben und nicht "+results.size(), results.size()==1); + for(TypeinferenceResultSet result : results){ + TypeInsertSet point = result.getTypeInsertionPoints(); + //TestCase.assertTrue("Es muss mindestens ein TypeInsertSet vorhanden sein", points.size()>0); + + //TestCase.assertTrue("Es muss mindestens ein TypeInsertPoint vorhanden sein", point.points.size()>0); + if(point.points.size()>0){ + for(TypeInsertPoint tip : point.points){ + System.out.println("Setze " + tip + " ein:"); + inferedSource = point.insertType(tip, TypeInsertTester.getFileContent(rootDirectory + sourceFileToInfere)); + System.out.println(inferedSource); + } + gesamterSrc += inferedSource; + } + } + } catch (IOException | yyException e) { + e.printStackTrace(); + TestCase.fail(); + } + for(String containString : mustContain){ + TestCase.assertTrue("\""+containString+"\" muss in den inferierten Lösungen vorkommen",gesamterSrc.contains(containString)); + } + } }