Fehler bei der Einsetzung von GenericVarDeclarations beheben

This commit is contained in:
JanUlrich 2014-07-23 17:24:08 +02:00
parent f51b5d5b7c
commit dbf493424e
11 changed files with 156 additions and 28 deletions

7
bin/.gitignore vendored
View File

@ -1 +1,8 @@
/mycompiler /mycompiler
/typinferenz
/userinterface
/bytecode
/myJvmDisassembler
/parser
/plugindevelopment
/syntaxTree

View File

@ -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;
}
} }

View File

@ -112,7 +112,7 @@ public abstract class Field extends SyntaxTreeNode implements TypeInsertable, Ty
@Override @Override
public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph, public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph,
ResultSet resultSet) { ResultSet resultSet) {
return new TypeInsertPoint(this, resultSet.getTypeEqualTo(tph), resultSet); return new TypeInsertPoint(this, this, resultSet.getTypeEqualTo(tph), resultSet);
} }
/** /**

View File

@ -267,7 +267,7 @@ public class FormalParameter extends SyntaxTreeNode implements ITypeReplacementL
ResultSet resultSet) { ResultSet resultSet) {
if(this.getOffset()<=0)return null; if(this.getOffset()<=0)return null;
Type t = resultSet.getTypeEqualTo(tph); Type t = resultSet.getTypeEqualTo(tph);
return new TypeInsertPoint(this, t, resultSet); return new TypeInsertPoint(this, this, t, resultSet);
} }

View File

@ -519,7 +519,7 @@ public class LocalVarDecl extends Statement implements TypeInsertable
@Override @Override
public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph, public TypeInsertPoint createTypeInsertPoint(TypePlaceholder tph,
ResultSet resultSet) { ResultSet resultSet) {
return new TypeInsertPoint(this, resultSet.getTypeEqualTo(tph),resultSet); return new TypeInsertPoint(this, this, resultSet.getTypeEqualTo(tph),resultSet);
} }
} }
// ino.end // ino.end

View File

@ -27,12 +27,6 @@ public class GenericTypeInsertPoint extends SourcePatchPoint {
private GenericVarPatch patch; private GenericVarPatch patch;
private GenericTypeInsertable genericInsertPoint; 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, public GenericTypeInsertPoint(GenericTypeInsertable syntaxTreeNode,
GenericVarPatch gtv ,ResultSet resultSet) { GenericVarPatch gtv ,ResultSet resultSet) {
this.resultSet = resultSet; this.resultSet = resultSet;
@ -177,40 +171,56 @@ public class GenericTypeInsertPoint extends SourcePatchPoint {
*/ */
class GenericVarPatch { class GenericVarPatch {
private Vector<GenericVarExtendsDeclarationPatch> genericVarExtendDeclarations = new Vector<GenericVarExtendsDeclarationPatch>();
private Vector<GenericVarDeclarationPatch> genericVarDeclarations = new Vector<GenericVarDeclarationPatch>(); private Vector<GenericVarDeclarationPatch> genericVarDeclarations = new Vector<GenericVarDeclarationPatch>();
/** /**
* Fügt eine generische Variable in Form eines Pairs an. * Fügt eine generische Variable in Form eines Pairs an.
* @param p * @param p
*/ */
public void add(Pair 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); if(!this.genericVarDeclarations.contains(toAdd))this.genericVarDeclarations.add(toAdd);
} }
public String getInsertString(ResultSet rs){ public String getInsertString(ResultSet rs){
String ret = ""; String ret = "";
Iterator<GenericVarDeclarationPatch> it = this.genericVarDeclarations.iterator(); Iterator<GenericVarDeclarationPatch> it1 = this.genericVarDeclarations.iterator();
while(it.hasNext()){ while(it1.hasNext()){
GenericVarDeclarationPatch p = it.next(); GenericVarDeclarationPatch p = it1.next();
ret += p.getInsertString(rs); ret += p.getInsertString(rs);
if(it.hasNext())ret += ", "; if(it1.hasNext())ret += ", ";
}
if(this.genericVarDeclarations.size()>0)ret+=", ";
Iterator<GenericVarExtendsDeclarationPatch> it2 = this.genericVarExtendDeclarations.iterator();
while(it2.hasNext()){
GenericVarExtendsDeclarationPatch p = it2.next();
ret += p.getInsertString(rs);
if(it2.hasNext())ret += ", ";
} }
return 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 * @author janulrich
* *
*/ */
class GenericVarDeclarationPatch { class GenericVarExtendsDeclarationPatch {
private Pair genericPair; private Pair genericPair;
public GenericVarDeclarationPatch(Pair p) { public GenericVarExtendsDeclarationPatch(Pair p) {
this.genericPair = p; this.genericPair = p;
} }
@ -224,11 +234,39 @@ class GenericVarDeclarationPatch {
return ret; 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 @Override
public boolean equals(Object o){ public boolean equals(Object o){
if(!(o instanceof GenericVarDeclarationPatch))return false; if(!(o instanceof GenericVarDeclarationPatch))return false;
if(!(this.genericPair.equals(((GenericVarDeclarationPatch)o).genericPair)))return false; if(!(this.genericPair.equals(((GenericVarDeclarationPatch)o).genericPair)))return false;
return true; return true;
} }
} }

View File

@ -25,18 +25,21 @@ public class TypeInsertPoint extends SourcePatchPoint {
public Type type; public Type type;
private TypeInsertable point; private TypeInsertable point;
private SyntaxTreeNode node;
/** /**
* Dieser Konstruktor erstellt einen TypInsertPoint * Dieser Konstruktor erstellt einen TypInsertPoint
* @param insertPoint * @param insertPoint
* @param insertNode - muss das gleiche sein wie "insertPoint"
* @param insertType * @param insertType
* @param resultSet * @param resultSet
* @param generics - die generischen Parameter des einzusetzenden Typs * @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.point = insertPoint;
this.type = insertType; this.type = insertType;
this.resultSet = resultSet; this.resultSet = resultSet;
this.node = insertNode;
} }
/** /**
@ -46,9 +49,9 @@ public class TypeInsertPoint extends SourcePatchPoint {
* @return * @return
*/ */
public JavaCodeResult patch(String fileContent, int additionalOffset) { 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(); 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); 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. * @return Der Offset des TypeInsertPoints in dem geparsten Source für dessen Klasse er erstellt wurde.
*/ */
public int getOffset(){ public int getOffset(){
return this.getInsertNode().getOffset(); return this.getInsertPoint().getOffset();
} }
protected Type getInsertType(){ protected Type getInsertType(){
@ -86,15 +89,19 @@ public class TypeInsertPoint extends SourcePatchPoint {
/** /**
* @return - Der Punkt (Knoten) im Syntaxbaum, für den dieser TypeInsertPoint gilt. * @return - Der Punkt (Knoten) im Syntaxbaum, für den dieser TypeInsertPoint gilt.
*/ */
public IItemWithOffset getInsertNode(){ public IItemWithOffset getInsertPoint(){
return this.point; return this.point;
} }
public SyntaxTreeNode getInsertNode(){
return this.node;
}
@Override @Override
public boolean equals(Object obj){ public boolean equals(Object obj){
if(! (obj instanceof TypeInsertPoint))return false; if(! (obj instanceof TypeInsertPoint))return false;
TypeInsertPoint equals = (TypeInsertPoint) obj; 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.getResultSet().equals(this.getResultSet())))return false; //ResultSet spielt bei Equals keine Rolle
if(!(equals.getInsertType().equals(this.getInsertType())))return false; if(!(equals.getInsertType().equals(this.getInsertType())))return false;
@ -108,7 +115,7 @@ public class TypeInsertPoint extends SourcePatchPoint {
while(!(ret instanceof Field || ret instanceof Class)){ while(!(ret instanceof Field || ret instanceof Class)){
ret = ret.getParent(); ret = ret.getParent();
if(ret == null){ 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; return (GenericTypeInsertable) ret;

View File

@ -75,16 +75,35 @@ public class TypeInsertSet {
* @param tip * @param tip
* @param tpj * @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 GenericVarPatch gPatch = new GenericVarPatch();//Set der Einzusetzenden generischen Variablendeklarationen
Vector<Pair> pairs = new Vector<>();
for(Pair pair : this.resultSet.getConstraintsFor(tip.getInsertType().getInvolvedTypePlaceholder())){ for(Pair pair : this.resultSet.getConstraintsFor(tip.getInsertType().getInvolvedTypePlaceholder())){
gPatch.add(pair); 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); GenericTypeInsertPoint gip = new GenericTypeInsertPoint(tip.getGenericTypeVarInsertNode(), gPatch, resultSet);
tpj.add(tip); tpj.add(tip);
tpj.add(gip); tpj.add(gip);
} }
private boolean pairsDeclareTPH(Vector<Pair> 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 * Fügt alle Typen dieses TypeInsertSets in den übergebenen Quellcode ein
* @param fileContent * @param fileContent
@ -140,7 +159,7 @@ public class TypeInsertSet {
*/ */
public TypeInsertPoint getInsertPointFor(TypeInsertable node){ public TypeInsertPoint getInsertPointFor(TypeInsertable node){
for(TypeInsertPoint point : points){ for(TypeInsertPoint point : points){
if(point.getInsertNode().equals(node))return point; if(point.getInsertPoint().equals(node))return point;
} }
return null; return null;
} }

View File

@ -0,0 +1,5 @@
class Matrix{
op(m){
return (f) -> f.apply(m,this);
}
}

View File

@ -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<String> mustContain = new Vector<String>();
//mustContain.add("A a");
MultipleTypesInsertTester.testSingleInsert(this.TEST_FILE, mustContain);
}
}

View File

@ -10,6 +10,7 @@ import mycompiler.MyCompiler;
import mycompiler.MyCompilerAPI; import mycompiler.MyCompilerAPI;
import mycompiler.myparser.JavaParser.yyException; import mycompiler.myparser.JavaParser.yyException;
import mycompiler.mytypereconstruction.TypeinferenceResultSet; import mycompiler.mytypereconstruction.TypeinferenceResultSet;
import typinferenz.typedeployment.TypeInsertPoint;
import typinferenz.typedeployment.TypeInsertSet; import typinferenz.typedeployment.TypeInsertSet;
public class MultipleTypesInsertTester extends TypeInsertTester{ public class MultipleTypesInsertTester extends TypeInsertTester{
@ -46,4 +47,34 @@ public class MultipleTypesInsertTester extends TypeInsertTester{
} }
} }
public static void testSingleInsert(String sourceFileToInfere, Vector<String> mustContain){
String gesamterSrc = "";
String inferedSource = "";
MyCompilerAPI compiler = MyCompiler.getAPI();
try {
compiler.parse(new File(rootDirectory + sourceFileToInfere));
Vector<TypeinferenceResultSet> 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));
}
}
} }