diff --git a/.classpath b/.classpath index 38eed00a1..4f24f94b1 100755 --- a/.classpath +++ b/.classpath @@ -4,6 +4,6 @@ - + diff --git a/README.me b/README.me deleted file mode 100644 index dfe0d3180..000000000 --- a/README.me +++ /dev/null @@ -1,15 +0,0 @@ -# Typinferenz für Java 8 - -## Programmablauf - -1. SourceFile parst die Java-Dateien -2. SourceFile erstellt die Basic/Global Assumptions -3. Das Globale AssumptionSet wird anschließend jeder Klasse im Syntaxbaum mit dem TRProg aufruf übergeben -4. Jede Klasse verwaltet lokale Variablen in ihrem eigenen AssumptionSet. Das Globale ist Klassenübergreifend und jede AssumptionType darf darin nur einmalig gesetzt werden. -5. Haben alle Klassen ihrer Constraints erstellt können diese Unifiziert werden. - -## Overloading - -* Die Overloading Klasse generiert Constraints aus einem Methodenaufruf. - - diff --git a/Readme.md b/Readme.md deleted file mode 100644 index 641d10f18..000000000 --- a/Readme.md +++ /dev/null @@ -1,42 +0,0 @@ -# Typinferenz - -## ResultSet - -* Spezifisch für jedes SourceFile (nicht für jede Klasse) -* mehrere ResultSets pro Klasse -* - -* Enthält: - * constraintPairs - * unifiedConstraints - -## TypeInsertSet -* Stellt die Typeinsetzung für eine der generierten Lösungen dar -* Setzt alle Typen und generischen Variablen ein, welche zu dieser Lösung gehören - -## Ablauf Typinferenz: - -1. Parsen - * (Parser postProcessing) -2. Typinferenz - * Anfangspunkt SourceFile - * löst geparste Typen zu richtigen Typen auf (RefTypes, GenericVar) - * setzt TPHs ein - * bildet Constraints, welche in ResultSet gesammelt werden. ResultSet wird durch Syntaxbaum gereicht. - * Assumptions generieren - * Wird im Syntaxbaum für jeden Knoten ausgeführt und die Assumptions für darunterliegende Knoten gebildet - * -3. Unifizierung - * wird im SourceFile aufgerufen - * unifiziert Constraints aller im SourceFile vorkommenden Klassen - -4. Erstellen von TypeInsertSet - * Durchlaufen des Syntaxbaumes - * Jeder Knoten erstellt TypeInsertSets anhand des ResultSets. - * Bei Knoten, welche Generische Variablen beinhalten können werden GenericTypeInsertPoints erstellt - -5. Einsetzen eines TypeInsertSet (optional) - 1. Auf allen TypeInsertPoints die getUnresolvedTPHs-Methoden aufrufen - 2. Alle Abhängigkeiten dieser - - \ No newline at end of file diff --git a/doc/documentation.md b/doc/documentation.md new file mode 100644 index 000000000..0b88a6bc0 --- /dev/null +++ b/doc/documentation.md @@ -0,0 +1,71 @@ + +# Typinferenz + +## Generische Variablen +### GTVs in Constraints +* GTVs können in Constraints auf 2 Arten auftauchen. + * Als GTZ und als TPH +* In folgenden Fällen als TPH: + * Die Generische Variable ist nicht in dem Bereich definiert, in dem sie benutzt wird. + * Es kann auch vorkommen, dass die Generische Variable in der gleichen Klasse definiert wurde, aber für eine andere Methode gilt. + +* In folgenden Fällen als GTV: + * Die Generische Variable ist für den Bereich definiert, in dem der Constraint generiert wird. + * In der selben Methode oder der selben Klasse. Dies lässt sich überprüfen, indem man die Klasse in welcher die GTV deklariert wurde mit der Klasse in welcher deren Typ benutzt wird vergleicht. + * Ist die GTV als Klassenparameter definiert und aus der selben Klasse wird darauf zugegriffen. + * Die GTV ist in einer Methode oder FieldDeclaration definiert, aber nicht dem selben wie darauf zugegriffen wird. + +## ResultSet + +* Spezifisch für jedes SourceFile (nicht für jede Klasse) +* mehrere ResultSets pro Klasse +* + +* Enthält: + * constraintPairs + * unifiedConstraints + +## TypeInsertSet +* Stellt die Typeinsetzung für eine der generierten Lösungen dar +* Setzt alle Typen und generischen Variablen ein, welche zu dieser Lösung gehören + +## Ablauf Typinferenz: + +1. Parsen + * (Parser postProcessing) +2. Typinferenz + * Anfangspunkt SourceFile + * löst geparste Typen zu richtigen Typen auf (RefTypes, GenericVar) + * setzt TPHs ein + * bildet Constraints, welche in ResultSet gesammelt werden. ResultSet wird durch Syntaxbaum gereicht. + * Assumptions generieren + * Wird im Syntaxbaum für jeden Knoten ausgeführt und die Assumptions für darunterliegende Knoten gebildet + * +3. Unifizierung + * wird im SourceFile aufgerufen + * unifiziert Constraints aller im SourceFile vorkommenden Klassen + +4. Erstellen von TypeInsertSet + * Durchlaufen des Syntaxbaumes + * Jeder Knoten erstellt TypeInsertSets anhand des ResultSets. + * Bei Knoten, welche Generische Variablen beinhalten können werden GenericTypeInsertPoints erstellt + +5. Einsetzen eines TypeInsertSet (optional) + 1. Auf allen TypeInsertPoints die getUnresolvedTPHs-Methoden aufrufen + 2. Alle Abhängigkeiten dieser + +# Typinferenz für Java 8 + +## Programmablauf + +1. SourceFile parst die Java-Dateien +2. SourceFile erstellt die Basic/Global Assumptions +3. Das Globale AssumptionSet wird anschließend jeder Klasse im Syntaxbaum mit dem TRProg aufruf übergeben +4. Jede Klasse verwaltet lokale Variablen in ihrem eigenen AssumptionSet. Das Globale ist Klassenübergreifend und jede AssumptionType darf darin nur einmalig gesetzt werden. +5. Haben alle Klassen ihrer Constraints erstellt können diese Unifiziert werden. + +## Overloading + +* Die Overloading Klasse generiert Constraints aus einem Methodenaufruf. + + diff --git a/src/de/dhbwstuttgart/syntaxtree/Class.java b/src/de/dhbwstuttgart/syntaxtree/Class.java index 8e05b2d39..d0e0b24a9 100755 --- a/src/de/dhbwstuttgart/syntaxtree/Class.java +++ b/src/de/dhbwstuttgart/syntaxtree/Class.java @@ -36,7 +36,7 @@ import de.dhbwstuttgart.typeinference.unify.Unify; // ino.class.Class.23010.declaration -public class Class extends SyntaxTreeNode implements AClassOrInterface, IItemWithOffset, Generic, GenericTypeInsertable +public class Class extends GTVDeclarationContext implements AClassOrInterface, IItemWithOffset, Generic, GenericTypeInsertable // ino.end // ino.class.Class.23010.body { @@ -1298,5 +1298,9 @@ public class Class extends SyntaxTreeNode implements AClassOrInterface, IItemWit public Type getSuperClass(){ return this.superClass; } + @Override + public boolean isClass() { + return true; + } } // ino.end diff --git a/src/de/dhbwstuttgart/syntaxtree/Field.java b/src/de/dhbwstuttgart/syntaxtree/Field.java index 2ba3ce6b9..9b5a375cd 100644 --- a/src/de/dhbwstuttgart/syntaxtree/Field.java +++ b/src/de/dhbwstuttgart/syntaxtree/Field.java @@ -18,7 +18,7 @@ import de.dhbwstuttgart.typeinference.Typeable; import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; -public abstract class Field extends SyntaxTreeNode implements TypeInsertable, Typeable, Generic, GenericTypeInsertable{ +public abstract class Field extends GTVDeclarationContext implements TypeInsertable, Typeable, Generic, GenericTypeInsertable{ protected Vector declid = new Vector(); // Vector, da 'int a, b, c, ...' auch eingeparst werden muss @@ -166,4 +166,8 @@ public abstract class Field extends SyntaxTreeNode implements TypeInsertable, Ty public void setGenericParameter(GenericDeclarationList params) { this.genericParameters = params; } + @Override + public boolean isClass() { + return false; + } } diff --git a/src/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java b/src/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java index 3fb4cf61a..0ddb10b1b 100644 --- a/src/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java +++ b/src/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java @@ -137,6 +137,7 @@ public class FieldDeclaration extends Field{ //TypeCheck, falls es sich um einen RefType handelt: ConstraintType thisType = this.getType().TYPE(localAssumptions, this); + this.setType(thisType.getType()); /* if(this.getType()!=null && (this.getType() instanceof RefType)){ Type replaceType = null; diff --git a/src/de/dhbwstuttgart/syntaxtree/GTVDeclarationContext.java b/src/de/dhbwstuttgart/syntaxtree/GTVDeclarationContext.java new file mode 100644 index 000000000..e2ff91a78 --- /dev/null +++ b/src/de/dhbwstuttgart/syntaxtree/GTVDeclarationContext.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.syntaxtree; + +import java.util.Vector; + +/** + * Beischreibt eine SyntaxTreeNode, welcher die Eigenschaft besitzt, + * dass bei seiner Deklaration auch Generische Typvariablen deklariert wurden. + */ +public abstract class GTVDeclarationContext extends SyntaxTreeNode { + @Override + public GTVDeclarationContext getGTVDeclarationContext(){ + return this; + } + public abstract boolean isClass(); +} diff --git a/src/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java b/src/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java index 3eed701bb..d5e210631 100644 --- a/src/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java +++ b/src/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java @@ -110,4 +110,20 @@ public abstract class SyntaxTreeNode implements IItemWithOffset{ //TODO: Implementieren. Hier sollte ein Lookup in die Assumptions dieses Knotens erfolgen return false; } + + public SyntaxTreeNode getMatchingParentNode(SyntaxTreeNode inNode) { + SyntaxTreeNode node = inNode; + while(node!=null){ + if(node.equals(this))return this; + node = inNode.getParent(); + } + if(this.getParent()!=null)return this.getParent().getMatchingParentNode(inNode); + return null; + } + + public GTVDeclarationContext getGTVDeclarationContext(){ + if(this.getParent()==null)return null; + return this.getParent().getGTVDeclarationContext(); + } + } diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/LocalOrFieldVar.java b/src/de/dhbwstuttgart/syntaxtree/statement/LocalOrFieldVar.java index 3266d67a7..85a636a69 100755 --- a/src/de/dhbwstuttgart/syntaxtree/statement/LocalOrFieldVar.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/LocalOrFieldVar.java @@ -185,7 +185,6 @@ public class LocalOrFieldVar extends Expr public String getTypeInformation(){ return this.getType()+" "+this.get_Name(); - } @Override diff --git a/src/de/dhbwstuttgart/syntaxtree/type/GenericTypeVar.java b/src/de/dhbwstuttgart/syntaxtree/type/GenericTypeVar.java index 93516ef65..658e75361 100755 --- a/src/de/dhbwstuttgart/syntaxtree/type/GenericTypeVar.java +++ b/src/de/dhbwstuttgart/syntaxtree/type/GenericTypeVar.java @@ -20,6 +20,7 @@ import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; import de.dhbwstuttgart.parser.JavaClassName; import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.GTVDeclarationContext; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; // ino.class.GenericTypeVar.26505.description type=javadoc /** @@ -225,6 +226,10 @@ public class GenericTypeVar extends Type super.parserPostProcessing(parent); //if(parentTemp != null)this.parent = parentTemp; //Der Parenttype einer GenericVar soll sich nicht ändern können, falls einmal gesetzt. } + + public GTVDeclarationContext getDeclarationContext() { + return this.getGTVDeclarationContext(); + } } diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java index 11f7caa1b..fd226de34 100644 --- a/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java +++ b/src/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java @@ -4,6 +4,7 @@ import de.dhbwstuttgart.parser.JavaClassName; import de.dhbwstuttgart.syntaxtree.Class; import de.dhbwstuttgart.syntaxtree.Field; import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.Type; public class FieldAssumption extends Assumption { @@ -38,5 +39,4 @@ public class FieldAssumption extends Assumption { return true; } - } diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/GenericVarAssumption.java b/src/de/dhbwstuttgart/typeinference/assumptions/GenericVarAssumption.java index 3460bed97..02bcd8c02 100644 --- a/src/de/dhbwstuttgart/typeinference/assumptions/GenericVarAssumption.java +++ b/src/de/dhbwstuttgart/typeinference/assumptions/GenericVarAssumption.java @@ -1,10 +1,15 @@ package de.dhbwstuttgart.typeinference.assumptions; import de.dhbwstuttgart.parser.JavaClassName; +import de.dhbwstuttgart.syntaxtree.FieldDeclaration; +import de.dhbwstuttgart.syntaxtree.GTVDeclarationContext; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.Type; +import de.dhbwstuttgart.syntaxtree.Class; public class GenericVarAssumption extends Assumption{ diff --git a/src/de/dhbwstuttgart/typeinference/assumptions/TypeAssumptions.java b/src/de/dhbwstuttgart/typeinference/assumptions/TypeAssumptions.java index 14b2ab489..0d9804595 100755 --- a/src/de/dhbwstuttgart/typeinference/assumptions/TypeAssumptions.java +++ b/src/de/dhbwstuttgart/typeinference/assumptions/TypeAssumptions.java @@ -8,6 +8,7 @@ import de.dhbwstuttgart.logger.Logger; import de.dhbwstuttgart.logger.Section; import de.dhbwstuttgart.parser.JavaClassName; import de.dhbwstuttgart.syntaxtree.Class; +import de.dhbwstuttgart.syntaxtree.GTVDeclarationContext; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.RefType; @@ -327,7 +328,10 @@ public class TypeAssumptions { for(GenericVarAssumption ass : this.genericVarAssumptions){ //if(ass.inheritsType(t))return t; if(ass.getIdentifier().equals(t.getName())){ - if(! ass.getAssumedType().getParentClass().equals(inNode.getParentClass())){ //hier muss nach der ParentClass von inNode gefragt werden, da die ParentClass von t nicht immer korrekt ist! (TODO: Überprüfen) + //Generische Variable gefunden! + GTVDeclarationContext gtvDeclNode = ass.getAssumedType().getDeclarationContext(); + if(gtvDeclNode == null || gtvDeclNode.isClass() + || !gtvDeclNode.equals(inNode.getGTVDeclarationContext())){ //hier muss nach der ParentClass von inNode gefragt werden, da die ParentClass von t nicht immer korrekt ist! (TODO: Überprüfen) TypeAssumptions.log.debug(t+" ist NICHT in Klasse: "+ass.getAssumedType().getParentClass(), Section.ASSUMPTIONS); //Ist die Generische Variable nicht aus dieser Klasse, so muss sie zu einem TPH umgewandelt werden: return new ConstraintType(ass.getAssumedType().getTypePlaceHolder(inNode)); @@ -389,7 +393,6 @@ public class TypeAssumptions { */ public void addGenericVarAssumption( GenericTypeVar genericTypeVar) { - //TODO: Hier müssen alle Bounds einzeln geaddet werden. Die Bounds müssen hierbei nicht gespeichert werden, deren Constraints generiert die TYPE-Methode der GenericVarDeclarations this.genericVarAssumptions.add(new GenericVarAssumption(genericTypeVar)); } diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest26.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest26.jav new file mode 100644 index 000000000..a59e9ef3c --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest26.jav @@ -0,0 +1,12 @@ +class Test { + + String var; + + A m (A x) { + return x; + } + + m2(){ + return m(var); + } +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest26.java b/test/plugindevelopment/TypeInsertTests/LambdaTest26.java new file mode 100644 index 000000000..9b0c2e674 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest26.java @@ -0,0 +1,18 @@ +package plugindevelopment.TypeInsertTests; + +import java.util.Vector; + +import org.junit.Test; + +public class LambdaTest26 { + + private static final String TEST_FILE = "LambdaTest26.jav"; + + @Test + public void run(){ + Vector mustContain = new Vector(); + //mustContain.add("A a"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +} diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.jav b/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.jav new file mode 100644 index 000000000..898bc03d6 --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.jav @@ -0,0 +1,5 @@ +class LambdaTest{ + +op = (m) -> (f) -> f.apply(this,m); + +} \ No newline at end of file diff --git a/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.java b/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.java new file mode 100644 index 000000000..8625a71ef --- /dev/null +++ b/test/plugindevelopment/TypeInsertTests/LambdaTest2_2.java @@ -0,0 +1,23 @@ +package plugindevelopment.TypeInsertTests; + +import java.util.Vector; + +import org.junit.Test; + +import de.dhbwstuttgart.logger.Logger; +import de.dhbwstuttgart.logger.LoggerConfiguration; +import de.dhbwstuttgart.logger.Section; + +public class LambdaTest2_2 { + + private static final String TEST_FILE = "LambdaTest2_2.jav"; + + @Test + public void run(){ + Logger.getConfiguration().setOutput(Section.ASSUMPTIONS, System.out); + Vector mustContain = new Vector(); + //mustContain.add("S m"); + MultipleTypesInsertTester.test(this.TEST_FILE, mustContain); + } + +}