diff --git a/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/TypeReplaceMarker.java b/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/TypeReplaceMarker.java index 224a1de..5ab1fdd 100644 --- a/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/TypeReplaceMarker.java +++ b/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/TypeReplaceMarker.java @@ -10,7 +10,7 @@ import de.dhbwstuttgart.typeinference.result.ResultPair; import de.dhbwstuttgart.typeinference.result.ResultSet; import typinferenzplugin.editor.JavEditor; -public class TypeReplaceMarker extends JavMarker { +public class TypeReplaceMarker extends JavMarker implements Comparable { private JavEditor editor; private CodePoint point; @@ -109,9 +109,20 @@ public class TypeReplaceMarker extends JavMarker { return false; } else { - return ((TypeReplaceMarker)obj).tip.equals(this.tip); + TypeReplaceMarker other = (TypeReplaceMarker)obj; + boolean samePos = this.getPositionInCode() == other.getPositionInCode(); + boolean sameInsert = this.getInsertPoint().getInsertString().equals(other.getInsertPoint().getInsertString()); + + return samePos && sameInsert; } } + + + + @Override + public int hashCode() { + return getPositionInCode() * 37 + getInsertPoint().getInsertString().hashCode(); + } public void adjustResultSet(TypeReplaceMarker typeReplaceMarker) { resultSets.removeIf(rs -> { @@ -125,4 +136,20 @@ public class TypeReplaceMarker extends JavMarker { }); } + + @Override + public int compareTo(Object o) { + if (o instanceof TypeReplaceMarker) { + TypeReplaceMarker other = (TypeReplaceMarker)o; + + if (this.getPositionInCode() == other.getPositionInCode()) { + return 0; + } else if (this.getPositionInCode() > other.getPositionInCode()) { + return 1; + } else { + return -1; + } + } + return -1; + } } diff --git a/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/Typinferenz.java b/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/Typinferenz.java index c37a5bd..e53d082 100644 --- a/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/Typinferenz.java +++ b/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/Typinferenz.java @@ -23,6 +23,8 @@ import org.apache.commons.io.output.NullOutputStream; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.Status; +import com.google.common.base.Strings; + import de.dhbwstuttgart.bytecode.BytecodeGen; import de.dhbwstuttgart.bytecode.Exception.BytecodeGeneratorError; import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; @@ -33,9 +35,11 @@ import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.typedeployment.TypeInsert; import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.unify.UnifyResultListener; import de.dhbwstuttgart.typeinference.unify.UnifyResultModel; +import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure; import typinferenzplugin.editor.JavEditor; import typinferenzplugin.error.ErrorOutput; @@ -63,6 +67,11 @@ public class Typinferenz { this.parsedSource = parsedSourceOrNull; } + // Keine Exception bei leerem Editor + if (Strings.isNullOrEmpty(editor.getSourceCode())) { + return new UnifyResultModel(new ConstraintSet<>(), new FiniteClosure(new HashSet<>(), new OutputStreamWriter(new NullOutputStream()))); + } + return compiler.typeInferenceAsync(resultListener, new OutputStreamWriter(new NullOutputStream())); } catch (ClassNotFoundException e) { LOG.log(new Status(ERROR, PLUGIN_ID, e.getMessage(), e)); diff --git a/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/editor/JavEditor.java b/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/editor/JavEditor.java index e7567b3..da77b5c 100644 --- a/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/editor/JavEditor.java +++ b/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/editor/JavEditor.java @@ -7,8 +7,15 @@ import static typinferenzplugin.Activator.PLUGIN_ID; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; import java.util.TreeSet; import java.util.Vector; @@ -288,90 +295,88 @@ public class JavEditor extends TextEditor implements UnifyResultListener { IDocument document = this.getDocumentProvider().getDocument(this.getEditorInput()); document.set(typeReplaceMarker.insertType(document.get())); - Collection additionalIdentityElimination = new HashSet<>(); - typeReplaceMarkers.removeIf(trm -> trm.getPoint().getPositionInCode() == typeReplaceMarker.getPoint().getPositionInCode()); typeReplaceMarkers.removeIf(trm -> !trm.isConsistent(typeReplaceMarker)); - - int lengthOfInsert = typeReplaceMarker.getInsertPoint().getInsertString().length(); - int postitionOfInsert = typeReplaceMarker.getPositionInCode(); - - for (TypeReplaceMarker toCheck : typeReplaceMarkers) { - if (toCheck.getPoint().getPositionInCode() > postitionOfInsert) { - toCheck.getInsertPoint().point.addExtraOffset(lengthOfInsert); - } - - // Add extra offset for the additional insert points of "typeReplaceMarker" - // to "toCheck" - // ... - for (TypeInsertPoint additionalPoint : typeReplaceMarker.getInsertPoint().getAdditionalPointsUnsorted()) { - int lengthAdditionalInsert = additionalPoint.getInsertString().length(); - int positionAdditionalInsert = additionalPoint.getPositionInCode(); - - if (additionalIdentityElimination.add(additionalPoint) && postitionOfInsert > positionAdditionalInsert) { - toCheck.getInsertPoint().point.addExtraOffset(lengthAdditionalInsert); - } - } - - for (TypeInsertPoint tip : typeReplaceMarker.getInsertPoint().getAdditionalPointsUnsorted()) { - // Add to all other type replace markers the extra offsets of the additional - // points of this type replace marker. - // ... - if (toCheck.getPoint().getPositionInCode() > tip.getPositionInCode()) { - toCheck.getInsertPoint().point.addExtraOffset(tip.getInsertString().length()); - } - } - - for (TypeInsertPoint toCheckAddi : toCheck.getInsertPoint().getAdditionalPointsUnsorted()) { - if (toCheckAddi.getPositionInCode() > postitionOfInsert) { - toCheckAddi.addExtraOffset(lengthOfInsert); - } - - for (TypeInsertPoint additionalPoint : typeReplaceMarker.getInsertPoint().getAdditionalPointsUnsorted()) { - int lengthAdditionalInsert = additionalPoint.getInsertString().length(); - int positionAdditionalInsert = additionalPoint.getPositionInCode(); - - if (toCheckAddi.getPositionInCode() > positionAdditionalInsert) { - toCheckAddi.addExtraOffset(lengthAdditionalInsert); - } - } - } - } + typeReplaceMarkers.remove(typeReplaceMarker); // Remove resultsets if not consistent. for (TypeReplaceMarker trm : typeReplaceMarkers) { trm.adjustResultSet(typeReplaceMarker); } - updateGuiWithNewMarkers(typeReplaceMarkers); - - MultiKeyMap alreadyInserted = new MultiKeyMap<>(); - for (TypeInsertPoint additionalPoint : typeReplaceMarker.getInsertPoint().getAdditionalPoints() ) { - if (!additionalPoint.isGenericClassInsertPoint()) { - org.antlr.v4.runtime.Token additionalPt = additionalPoint.point; - alreadyInserted.put(additionalPt.getLine(), additionalPt.getCharPositionInLine(), additionalPoint); + + for (TypeInsertPoint additionalPoint : typeReplaceMarker.getInsertPoint().getAdditionalPoints()) { + for (TypeReplaceMarker other : this.typeReplaceMarkers) { + other.getInsertPoint().getAdditionalPointsUnsorted().removeIf(otAddi -> otAddi.getInsertString().trim().equals(additionalPoint.getInsertString().trim())); } } + Map alreadyInserted = new HashMap<>(); + + for (TypeInsertPoint additionalPoint : typeReplaceMarker.getInsertPoint().getAdditionalPoints() ) { + if (!additionalPoint.isGenericClassInsertPoint()) { + alreadyInserted.put(additionalPoint.getInsertString(), additionalPoint); + } + } + boolean actualHasGenericClassInserts = typeReplaceMarker.getInsertPoint().getAdditionalPoints().stream().anyMatch(tip -> tip.isGenericClassInsertPoint()); - if (actualHasGenericClassInserts) { - for (TypeReplaceMarker marker : typeReplaceMarkers) { - Iterator addiPoints = marker.getInsertPoint().getAdditionalPointsUnsorted().iterator(); - while (addiPoints.hasNext()) { - TypeInsertPoint addiPoint = addiPoints.next(); - if (addiPoint.isGenericClassInsertPoint()) { - addiPoints.remove(); - } else if (alreadyInserted.get(addiPoint.point.getLine(), addiPoint.point.getCharPositionInLine()) != null) { - addiPoints.remove(); + + for (TypeReplaceMarker toCheck : typeReplaceMarkers) { + Iterator addiPoints = toCheck.getInsertPoint().getAdditionalPointsUnsorted().iterator(); + while (addiPoints.hasNext()) { + TypeInsertPoint addiPoint = addiPoints.next(); + if (addiPoint.isGenericClassInsertPoint() && actualHasGenericClassInserts) { + addiPoints.remove(); + } else if (alreadyInserted.get(addiPoint.getInsertString()) != null) { + addiPoints.remove(); + } + } + } + + int lengthOfInsert = typeReplaceMarker.getInsertPoint().getInsertString().length(); + int postitionOfInsert = typeReplaceMarker.getPositionInCode(); + + Set sortedMarkers = new TreeSet(typeReplaceMarkers); + + + Set> additionalAddiIdentityElimination = new HashSet<>(); + Map allShifts = new SummingMap(); + for (TypeReplaceMarker toCheck : sortedMarkers) { + Collection additionalIdentityElimination = new HashSet<>(); + if (toCheck.getPositionInCode() >= postitionOfInsert) { + allShifts.put(toCheck.getInsertPoint().point, lengthOfInsert); + } + + for (TypeInsertPoint additionalPoint : typeReplaceMarker.getInsertPoint().getAdditionalPoints()) { + int lengthAdditionalInsert = additionalPoint.getInsertString().length(); + int positionAdditionalInsert = additionalPoint.getPositionInCode(); + + if (additionalIdentityElimination.add(additionalPoint) && toCheck.getPositionInCode() >= positionAdditionalInsert) { + allShifts.put(toCheck.getInsertPoint().point, lengthAdditionalInsert); + } + } + + for (TypeInsertPoint toCheckAddi : toCheck.getInsertPoint().getAdditionalPoints()) { + if (toCheckAddi.getPositionInCode() >= postitionOfInsert) { + allShifts.put(toCheckAddi, lengthOfInsert); + } + + + for (TypeInsertPoint additionalPoint : typeReplaceMarker.getInsertPoint().getAdditionalPoints()) { + int lengthAdditionalInsert = additionalPoint.getInsertString().length(); + int positionAdditionalInsert = additionalPoint.getPositionInCode(); + + if (additionalAddiIdentityElimination.add(new Pair<>(toCheckAddi,additionalPoint)) && toCheckAddi.getPositionInCode() >= positionAdditionalInsert) { + allShifts.put(toCheckAddi, lengthAdditionalInsert); } } } } - for (TypeInsertPoint additionalPoint : typeReplaceMarker.getInsertPoint().getAdditionalPoints()) { - for (TypeReplaceMarker other : this.typeReplaceMarkers) { - other.getInsertPoint().getAdditionalPointsUnsorted().remove(additionalPoint); - } + for (Entry shift : allShifts.entrySet()) { + shift.getKey().addExtraOffset(shift.getValue()); } + + updateGuiWithNewMarkers(typeReplaceMarkers); } private void removeMarkers() { diff --git a/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/editor/Pair.java b/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/editor/Pair.java new file mode 100644 index 0000000..1369302 --- /dev/null +++ b/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/editor/Pair.java @@ -0,0 +1,37 @@ +package typinferenzplugin.editor; + +public class Pair { + + private final L left; + private final R right; + + public Pair(L left, R right) { + assert left != null; + assert right != null; + + this.left = left; + this.right = right; + } + + public L getLeft() { + return left; + } + + public R getRight() { + return right; + } + + @Override + public int hashCode() { + return left.hashCode() ^ right.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Pair)) + return false; + Pair pairo = (Pair) o; + return this.left.equals(pairo.getLeft()) && this.right.equals(pairo.getRight()); + } + +} \ No newline at end of file diff --git a/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/editor/SummingMap.java b/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/editor/SummingMap.java new file mode 100644 index 0000000..1ee43fd --- /dev/null +++ b/JavaCompilerPlugin/bundles/JavaCompilerPlugin.Plugin/src/typinferenzplugin/editor/SummingMap.java @@ -0,0 +1,33 @@ +package typinferenzplugin.editor; + +import static com.google.common.base.MoreObjects.firstNonNull; + +import java.util.HashMap; +import java.util.Map; + +public class SummingMap extends HashMapimplements Map { + + private static final long serialVersionUID = 5823300094585927813L; + + @Override + public Integer put(T key, Integer value) { + Integer sum = firstNonNull(get(key), 0) + value; + return super.put(key, sum); + } + + @Override + public void putAll(Map m) { + for (Entry me : m.entrySet()) { + put(me.getKey(), me.getValue()); + } + } + + @Override + public Integer putIfAbsent(T key, Integer value) { + return put(key, value); + } + + + + +}