From 905d9e25a2afdaaaa6e39a9ceb6f3fe217cdd377 Mon Sep 17 00:00:00 2001 From: Michael Uhl Date: Thu, 18 Apr 2019 09:42:34 +0200 Subject: [PATCH] [PLUGIN]: Filter type insert points after insertion. --- .../typedeployment/TypeInsertPlacer.java | 146 ++--- .../typedeployment/TypeInsertPoint.java | 111 ++-- .../typeinference/result/ResultPair.java | 92 ++- .../typeinference/result/ResultPairMap.java | 25 + .../typeinference/result/ResultSet.java | 557 +++++++++--------- 5 files changed, 502 insertions(+), 429 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/typeinference/result/ResultPairMap.java diff --git a/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPlacer.java b/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPlacer.java index 9e5ba545..6ccf5620 100644 --- a/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPlacer.java +++ b/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPlacer.java @@ -1,73 +1,73 @@ -package de.dhbwstuttgart.typedeployment; - -import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.syntaxtree.*; -import de.dhbwstuttgart.syntaxtree.statement.JavaInternalExpression; -import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; -import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; -import de.dhbwstuttgart.typeinference.result.ResultSet; - -import java.util.HashSet; -import java.util.Set; - -public class TypeInsertPlacer extends AbstractASTWalker{ - Set inserts = new HashSet<>(); - private ResultSet withResults; - - public Set getTypeInserts(SourceFile forSourceFile, ResultSet withResults){ - this.withResults = withResults; - forSourceFile.accept(this); - return inserts; - } - - @Override - public void visit(ClassOrInterface classOrInterface) { - TypeInsertPlacerClass cl = new TypeInsertPlacerClass(classOrInterface, withResults); - this.inserts.addAll(cl.inserts); - } -} - -class TypeInsertPlacerClass extends AbstractASTWalker{ - protected final ResultSet results; - protected final ClassOrInterface cl; - public final Set inserts = new HashSet<>(); - private Method method; - - TypeInsertPlacerClass(ClassOrInterface forClass, ResultSet withResults){ - this.cl = forClass; - this.method = null; - this.results = withResults; - forClass.accept(this); - } - - @Override - public void visit(Method method) { - this.method = method; - if(method.getReturnType() instanceof TypePlaceholder) - inserts.add(TypeInsertFactory.createInsertPoints( - method.getReturnType(), method.getReturnType().getOffset(), cl, method, results)); - super.visit(method); - } - - @Override - public void visit(Field field) { - if(field.getType() instanceof TypePlaceholder){ - inserts.add(TypeInsertFactory.createInsertPoints( - field.getType(), field.getType().getOffset(), cl, method, results)); - } - super.visit(field); - } - - @Override - public void visit(FormalParameter param) { - if(param.getType() instanceof TypePlaceholder) - inserts.add(TypeInsertFactory.createInsertPoints( - param.getType(), param.getType().getOffset(), cl, method, results)); - super.visit(param); - } - - @Override - public void visit(LambdaExpression lambdaExpression) { - //Lambda-Ausdrücke brauchen keine Typeinsetzungen - } -} +package de.dhbwstuttgart.typedeployment; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.statement.JavaInternalExpression; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import java.util.HashSet; +import java.util.Set; + +public class TypeInsertPlacer extends AbstractASTWalker{ + Set inserts = new HashSet<>(); + private ResultSet withResults; + + public Set getTypeInserts(SourceFile forSourceFile, ResultSet withResults){ + this.withResults = withResults; + forSourceFile.accept(this); + return inserts; + } + + @Override + public void visit(ClassOrInterface classOrInterface) { + TypeInsertPlacerClass cl = new TypeInsertPlacerClass(classOrInterface, withResults); + this.inserts.addAll(cl.inserts); + } +} + +class TypeInsertPlacerClass extends AbstractASTWalker{ + protected final ResultSet results; + protected final ClassOrInterface cl; + public final Set inserts = new HashSet<>(); + private Method method; + + TypeInsertPlacerClass(ClassOrInterface forClass, ResultSet withResults){ + this.cl = forClass; + this.method = null; + this.results = withResults; + forClass.accept(this); + } + + @Override + public void visit(Method method) { + this.method = method; + if(method.getReturnType() instanceof TypePlaceholder) + inserts.add(TypeInsertFactory.createInsertPoints( + method.getReturnType(), method.getReturnType().getOffset(), cl, method, results)); + super.visit(method); + } + + @Override + public void visit(Field field) { + if(field.getType() instanceof TypePlaceholder){ + inserts.add(TypeInsertFactory.createInsertPoints( + field.getType(), field.getType().getOffset(), cl, method, results)); + } + super.visit(field); + } + + @Override + public void visit(FormalParameter param) { + if(param.getType() instanceof TypePlaceholder) + inserts.add(TypeInsertFactory.createInsertPoints( + param.getType(), param.getType().getOffset(), cl, method, results)); + super.visit(param); + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + //Lambda-Ausdrücke brauchen keine Typeinsetzungen + } +} diff --git a/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java b/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java index 2551260b..13fdae63 100644 --- a/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java +++ b/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java @@ -1,57 +1,54 @@ -package de.dhbwstuttgart.typedeployment; - -import org.antlr.v4.runtime.Token; - -import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; - -import java.util.List; -import java.util.stream.Collectors; - -public class TypeInsertPoint { - public Token point; - private String insertString; - - public TypeInsertPoint(Token point, String toInsert){ - this.point = point; - this.insertString = (toInsert.endsWith(" ")) ? toInsert : toInsert + " " ; - } - - public String insert(String intoSource, List additionalOffset){ - int offset = additionalOffset.stream().filter((token -> - //token.point.getLine() != point.getLine() && token.point.getCharPositionInLine() <= point.getCharPositionInLine())) - token.point.getStartIndex() <= point.getStartIndex())) - .mapToInt((typeInsertPoint -> typeInsertPoint.insertString.length())).sum(); - return new StringBuilder(intoSource).insert(point.getStartIndex()+offset, insertString).toString(); - } - - public String getInsertString() { - return insertString; - } - - public Token getToken() { - return this.point; - } - - public void setToken(Token point) { - this.point = point; - } - - /* PL 2018-06-19 - * Zwei TypeInsertPoint's sind gleich, wenn ihre point's gleich sind - * eingefuegt damit man TypeReplaceMarker vergleichen kann - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object obj) { - if(!(obj instanceof TypeInsertPoint)) { - return false; - } - else { - return ((TypeInsertPoint)obj).point.equals(this.point) && - ((TypeInsertPoint)obj).insertString.equals(this.insertString); - } - } - - public String toString() { - return point.toString() + " " + insertString.toString(); - } -} +package de.dhbwstuttgart.typedeployment; + +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; + +import java.util.List; +import java.util.stream.Collectors; + +public class TypeInsertPoint { + public Token point; + private String insertString; + private int extraOffset = 0; + + public TypeInsertPoint(Token point, String toInsert){ + this.point = point; + this.insertString = (toInsert.endsWith(" ")) ? toInsert : toInsert + " " ; + } + + public String insert(String intoSource, List additionalOffset){ + int offset = additionalOffset.stream().filter((token -> + //token.point.getLine() != point.getLine() && token.point.getCharPositionInLine() <= point.getCharPositionInLine())) + token.point.getStartIndex() <= point.getStartIndex())) + .mapToInt((typeInsertPoint -> typeInsertPoint.insertString.length())).sum(); + return new StringBuilder(intoSource).insert(point.getStartIndex()+offset+extraOffset, insertString).toString(); + } + + public String getInsertString() { + return insertString; + } + + public void addExtraOffset(int toAdd) { + this.extraOffset += toAdd; + } + + /* PL 2018-06-19 + * Zwei TypeInsertPoint's sind gleich, wenn ihre point's gleich sind + * eingefuegt damit man TypeReplaceMarker vergleichen kann + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if(!(obj instanceof TypeInsertPoint)) { + return false; + } + else { + return ((TypeInsertPoint)obj).point.equals(this.point) && + ((TypeInsertPoint)obj).insertString.equals(this.insertString); + } + } + + public String toString() { + return point.toString() + " " + insertString.toString(); + } +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPair.java b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPair.java index 749f9c1c..552bf494 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPair.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPair.java @@ -1,30 +1,62 @@ -package de.dhbwstuttgart.typeinference.result; - -import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; - -/** - * Paare, welche das Unifikationsergebnis darstellen - */ -public abstract class ResultPair { - private final A left; - private final B right; - - public abstract void accept(ResultPairVisitor visitor); - - public ResultPair(A left, B right){ - this.left = left; - this.right = right; - } - - public A getLeft() { - return left; - } - - public B getRight() { - return right; - } - - public String toString() { - return "(" + left.toString() + ", " + right.toString() + ")"; - } -} +package de.dhbwstuttgart.typeinference.result; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +/** + * Paare, welche das Unifikationsergebnis darstellen + */ +public abstract class ResultPair { + private final A left; + private final B right; + + public abstract void accept(ResultPairVisitor visitor); + + public ResultPair(A left, B right){ + this.left = left; + this.right = right; + } + + public A getLeft() { + return left; + } + + public B getRight() { + return right; + } + + public String toString() { + return "(" + left.toString() + ", " + right.toString() + ")"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((left == null) ? 0 : left.getOffset().hashCode()); + result = prime * result + ((right == null) ? 0 : right.getOffset().hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ResultPair other = (ResultPair) obj; + if (left == null) { + if (other.left != null) + return false; + } else if (!left.getOffset().equals(other.left.getOffset())) + return false; + if (right == null) { + if (other.right != null) + return false; + } else if (!right.getOffset().equals(other.right.getOffset())) + return false; + return true; + } + +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPairMap.java b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPairMap.java new file mode 100644 index 00000000..4f2a7ebc --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPairMap.java @@ -0,0 +1,25 @@ +package de.dhbwstuttgart.typeinference.result; + +import java.util.HashMap; +import java.util.Map; + +import org.antlr.v4.runtime.Token; + +public class ResultPairMap { + + private Map> indexMap = new HashMap<>(); + + public static final ResultPairMap RESULT_PAIRS = new ResultPairMap(); + + private ResultPairMap() { + // Nothing to do here. + } + + public void put(Token tkn, ResultPair resultPair) { + indexMap.put(tkn, resultPair); + } + + public ResultPair get(Token tkn) { + return indexMap.get(tkn); + } +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java index eef72ab0..7af159d6 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java @@ -1,270 +1,289 @@ -package de.dhbwstuttgart.typeinference.result; - -import de.dhbwstuttgart.exceptions.NotImplementedException; -import de.dhbwstuttgart.syntaxtree.GenericTypeVar; -import de.dhbwstuttgart.syntaxtree.type.*; - -import java.util.HashSet; -import java.util.Set; - -public class ResultSet { - public final Set results; - public ResultSet(Set results){ - this.results = results; - } - - public ResolvedType resolveType(RefTypeOrTPHOrWildcardOrGeneric type) { - if(type instanceof TypePlaceholder) - return new Resolver(this).resolve((TypePlaceholder)type); - if(type instanceof GenericRefType)return new ResolvedType(type, new HashSet<>()); - if(type instanceof RefType){ - RelatedTypeWalker related = new RelatedTypeWalker(null, this); - type.accept(related); - return new ResolvedType(type, related.relatedTPHs); - }else{ - throw new NotImplementedException(); - //return new ResolvedType(type,new HashSet<>()); - } - } - - //TODO Beim Einsetzen eines Generics, müssen die new und Methodenaufrufe verändert werden - - public String toString() { - return results.toString(); - } - -} - -class Resolver implements ResultSetVisitor { - private final ResultSet result; - private TypePlaceholder toResolve; - private RefTypeOrTPHOrWildcardOrGeneric resolved; - private final Set additionalTPHs = new HashSet<>(); - - public Resolver(ResultSet resultPairs){ - this.result = resultPairs; - } - - public ResolvedType resolve(TypePlaceholder tph){ - toResolve = tph; - resolved = null; - System.out.println(tph.toString()); - for(ResultPair resultPair : result.results){ - if(resultPair instanceof PairTPHEqualTPH && ((PairTPHEqualTPH) resultPair).getLeft().equals(toResolve)){ - return resolve(((PairTPHEqualTPH) resultPair).getRight()); - } - } - for(ResultPair resultPair : result.results){ - resultPair.accept(this); - } - if(resolved==null){//TPH kommt nicht im Result vor: - resolved = tph; - } - - return new ResolvedType(resolved, additionalTPHs);//resolved; - } - - @Override - public void visit(PairTPHsmallerTPH p) { - if(p.left.equals(toResolve)){ - additionalTPHs.add(new GenericInsertPair(p.left, p.right)); - additionalTPHs.addAll(new RelatedTypeWalker(p.right, result).relatedTPHs); - } - if(p.right.equals(toResolve)) - additionalTPHs.addAll(new RelatedTypeWalker(p.left, result).relatedTPHs); - } - - @Override - public void visit(PairTPHequalRefTypeOrWildcardType p) { - if(p.left.equals(toResolve)){ - resolved = p.right; - RelatedTypeWalker related = new RelatedTypeWalker(null, result); - p.right.accept(related); - additionalTPHs.addAll(related.relatedTPHs); - } - } - - @Override - public void visit(PairTPHEqualTPH p) { - //Do nothing. Dieser Fall wird in der resolve-Methode abgefangen - } - - @Override - public void visit(RefType refType) { - - } - - @Override - public void visit(GenericRefType genericRefType) { - - } - - @Override - public void visit(SuperWildcardType superWildcardType) { - - } - - @Override - public void visit(TypePlaceholder typePlaceholder) { - - } - - @Override - public void visit(ExtendsWildcardType extendsWildcardType) { - - } - - - -} - -/** - * Sucht aus dem Result Set den Sub/supertyp für einen TPH - */ -class TPHResolver implements ResultSetVisitor { - - private final TypePlaceholder tph; - Set resolved = new HashSet<>(); - private final ResultSet resultSet; - - TPHResolver(TypePlaceholder tph, ResultSet resultSet){ - this.resultSet = resultSet; - this.tph = tph; - for(ResultPair p : resultSet.results){ - p.accept(this); - } - if(resolved.size() == 0){ - resolved.add(new GenericInsertPair(tph, null)); - } - } - - @Override - public void visit(PairTPHsmallerTPH p) { - if(p.left.equals(tph) || p.right.equals(tph)){ - resolved.add(new GenericInsertPair(p.left, p.right)); - } - } - - @Override - public void visit(PairTPHequalRefTypeOrWildcardType p) { - TypePlaceholder otherSide = null; - if(p.right.equals(tph)){ - otherSide = p.left; - } - if(otherSide != null){ - Set newResultSet = new HashSet<>(this.resultSet.results); - newResultSet.remove(p); - resolved.addAll(new TPHResolver(otherSide, new ResultSet(newResultSet)).resolved); - } - } - - @Override - public void visit(PairTPHEqualTPH p) { - //ignorieren. Wird vom Resolver behandelt - } - - @Override - public void visit(RefType refType) { - - } - - @Override - public void visit(GenericRefType genericRefType) { - - } - - @Override - public void visit(SuperWildcardType superWildcardType) { - - } - - @Override - public void visit(TypePlaceholder typePlaceholder) { - - } - - @Override - public void visit(ExtendsWildcardType extendsWildcardType) { - - } -} - -class RelatedTypeWalker implements ResultSetVisitor { - - final Set relatedTPHs = new HashSet<>(); - private final TypePlaceholder toResolve; - private final ResultSet resultSet; - - /** - * Läuft über das resultSet und speichert alle TPHs, welche mit start in Verbindung stehen - * @param start - kann null sein, wenn der Walker für einen RefType benutzt wird - * @param resultSet - */ - RelatedTypeWalker(TypePlaceholder start, ResultSet resultSet){ - this.toResolve = start; - this.resultSet = resultSet; - int resolved = 0; - do{ - resolved = relatedTPHs.size(); - for(ResultPair p : resultSet.results){ - p.accept(this); - p.accept(this); - } - }while(resolved - relatedTPHs.size() > 0); - } - - @Override - public void visit(PairTPHsmallerTPH p) { - if(p.getRight().equals(toResolve)){ - relatedTPHs.addAll(new TPHResolver(p.right, resultSet).resolved); - //relatedTPHs.addAll(new RelatedTypeWalker(p.right, resultSet).relatedTPHs); - } - if(p.getLeft().equals(toResolve)){ - relatedTPHs.addAll(new TPHResolver(p.left, resultSet).resolved); - //relatedTPHs.addAll(new RelatedTypeWalker(p.left, resultSet).relatedTPHs); - } - } - - @Override - public void visit(PairTPHequalRefTypeOrWildcardType p) { - if(p.getLeft().equals(toResolve)){ - p.getRight().accept(this); - } - } - - @Override - public void visit(PairTPHEqualTPH p) { - //Kann ignoriert werden. Diese Fälle werden vom Resolver behandelt - } - - /* - Die folgenden Funktionen fügen alle TPHs an die relatedTPHs an, denen sie begegnen: - Das wird verwendet, wenn alle relatedTPHs aus den Parametern eines RefTypes angefügt werden sollen - */ - - @Override - public void visit(RefType refType) { - for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ - param.accept(this); - } - } - - @Override - public void visit(SuperWildcardType superWildcardType) { - superWildcardType.getInnerType().accept(this); - } - - @Override - public void visit(TypePlaceholder typePlaceholder) { - relatedTPHs.addAll(new TPHResolver(typePlaceholder, resultSet).resolved); - } - - @Override - public void visit(ExtendsWildcardType extendsWildcardType) { - extendsWildcardType.getInnerType().accept(this); - } - - @Override - public void visit(GenericRefType genericRefType) { - } +package de.dhbwstuttgart.typeinference.result; + +import java.util.HashSet; +import java.util.Set; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +import static de.dhbwstuttgart.typeinference.result.ResultPairMap.RESULT_PAIRS; + +@SuppressWarnings("rawtypes") +public class ResultSet { + public final Set results; + public ResultSet(Set set){ + this.results = set; + } + + public boolean contains(ResultPair toCheck) { + return this.results.contains(toCheck); + } + + public void remove(ResultPair toCheck) { + results.remove(toCheck); + } + + public ResolvedType resolveType(RefTypeOrTPHOrWildcardOrGeneric type) { + if(type instanceof TypePlaceholder) + return new Resolver(this).resolve((TypePlaceholder)type); + if(type instanceof GenericRefType)return new ResolvedType(type, new HashSet<>()); + if(type instanceof RefType){ + RelatedTypeWalker related = new RelatedTypeWalker(null, this); + type.accept(related); + return new ResolvedType(type, related.relatedTPHs); + }else{ + throw new NotImplementedException(); + //return new ResolvedType(type,new HashSet<>()); + } + } + + //TODO Beim Einsetzen eines Generics, müssen die new und Methodenaufrufe verändert werden + + public String toString() { + return results.toString(); + } + +} + +class Resolver implements ResultSetVisitor { + private final ResultSet result; + private TypePlaceholder toResolve; + private RefTypeOrTPHOrWildcardOrGeneric resolved; + private final Set additionalTPHs = new HashSet<>(); + + public Resolver(ResultSet resultPairs){ + this.result = resultPairs; + } + + public ResolvedType resolve(TypePlaceholder tph){ + toResolve = tph; + resolved = null; + System.out.println(tph.toString()); + for(ResultPair resultPair : result.results) { + RESULT_PAIRS.put(resultPair.getRight().getOffset(), resultPair); + RESULT_PAIRS.put(resultPair.getLeft().getOffset(), resultPair); + if(resultPair instanceof PairTPHEqualTPH && ((PairTPHEqualTPH) resultPair).getLeft().equals(toResolve)){ + return resolve(((PairTPHEqualTPH) resultPair).getRight()); + } + } + for(ResultPair resultPair : result.results){ + resultPair.accept(this); + } + if(resolved==null){//TPH kommt nicht im Result vor: + resolved = tph; + } + + return new ResolvedType(resolved, additionalTPHs);//resolved; + } + + @Override + public void visit(PairTPHsmallerTPH p) { + if(p.left.equals(toResolve)){ + additionalTPHs.add(new GenericInsertPair(p.left, p.right)); + additionalTPHs.addAll(new RelatedTypeWalker(p.right, result).relatedTPHs); + } + if(p.right.equals(toResolve)) + additionalTPHs.addAll(new RelatedTypeWalker(p.left, result).relatedTPHs); + } + + @Override + public void visit(PairTPHequalRefTypeOrWildcardType p) { + if(p.left.equals(toResolve)){ + resolved = p.right; + RelatedTypeWalker related = new RelatedTypeWalker(null, result); + p.right.accept(related); + additionalTPHs.addAll(related.relatedTPHs); + } + } + + @Override + public void visit(PairTPHEqualTPH p) { + //Do nothing. Dieser Fall wird in der resolve-Methode abgefangen + } + + @Override + public void visit(RefType refType) { + + } + + @Override + public void visit(GenericRefType genericRefType) { + + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + + } + + + +} + +/** + * Sucht aus dem Result Set den Sub/supertyp für einen TPH + */ +@SuppressWarnings("rawtypes") +class TPHResolver implements ResultSetVisitor { + + private final TypePlaceholder tph; + Set resolved = new HashSet<>(); + private final ResultSet resultSet; + + TPHResolver(TypePlaceholder tph, ResultSet resultSet){ + this.resultSet = resultSet; + this.tph = tph; + for(ResultPair p : resultSet.results){ + p.accept(this); + } + if(resolved.size() == 0){ + resolved.add(new GenericInsertPair(tph, null)); + } + } + + @Override + public void visit(PairTPHsmallerTPH p) { + if(p.left.equals(tph) || p.right.equals(tph)){ + resolved.add(new GenericInsertPair(p.left, p.right)); + } + } + + @Override + public void visit(PairTPHequalRefTypeOrWildcardType p) { + TypePlaceholder otherSide = null; + if(p.right.equals(tph)){ + otherSide = p.left; + } + if(otherSide != null){ + Set newResultSet = new HashSet<>(this.resultSet.results); + newResultSet.remove(p); + resolved.addAll(new TPHResolver(otherSide, new ResultSet(newResultSet)).resolved); + } + } + + @Override + public void visit(PairTPHEqualTPH p) { + //ignorieren. Wird vom Resolver behandelt + } + + @Override + public void visit(RefType refType) { + + } + + @Override + public void visit(GenericRefType genericRefType) { + + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + + } +} + +@SuppressWarnings("rawtypes") +class RelatedTypeWalker implements ResultSetVisitor { + + final Set relatedTPHs = new HashSet<>(); + private final TypePlaceholder toResolve; + private final ResultSet resultSet; + + /** + * Läuft über das resultSet und speichert alle TPHs, welche mit start in Verbindung stehen + * @param start - kann null sein, wenn der Walker für einen RefType benutzt wird + * @param resultSet + */ + RelatedTypeWalker(TypePlaceholder start, ResultSet resultSet){ + this.toResolve = start; + this.resultSet = resultSet; + int resolved = 0; + do{ + resolved = relatedTPHs.size(); + for(ResultPair p : resultSet.results){ + p.accept(this); + p.accept(this); + } + }while(resolved - relatedTPHs.size() > 0); + } + + @Override + public void visit(PairTPHsmallerTPH p) { + if(p.getRight().equals(toResolve)){ + relatedTPHs.addAll(new TPHResolver(p.right, resultSet).resolved); + //relatedTPHs.addAll(new RelatedTypeWalker(p.right, resultSet).relatedTPHs); + } + if(p.getLeft().equals(toResolve)){ + relatedTPHs.addAll(new TPHResolver(p.left, resultSet).resolved); + //relatedTPHs.addAll(new RelatedTypeWalker(p.left, resultSet).relatedTPHs); + } + } + + @Override + public void visit(PairTPHequalRefTypeOrWildcardType p) { + if(p.getLeft().equals(toResolve)){ + p.getRight().accept(this); + } + } + + @Override + public void visit(PairTPHEqualTPH p) { + //Kann ignoriert werden. Diese Fälle werden vom Resolver behandelt + } + + /* + Die folgenden Funktionen fügen alle TPHs an die relatedTPHs an, denen sie begegnen: + Das wird verwendet, wenn alle relatedTPHs aus den Parametern eines RefTypes angefügt werden sollen + */ + + @Override + public void visit(RefType refType) { + for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ + param.accept(this); + } + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + superWildcardType.getInnerType().accept(this); + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + relatedTPHs.addAll(new TPHResolver(typePlaceholder, resultSet).resolved); + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + extendsWildcardType.getInnerType().accept(this); + } + + @Override + public void visit(GenericRefType genericRefType) { + } } \ No newline at end of file