001package de.monochromata.anaphors.ast.strategy; 002 003import static java.util.Arrays.asList; 004import static java.util.Collections.emptyList; 005import static java.util.Collections.singletonList; 006 007import java.util.List; 008import java.util.Optional; 009 010import de.monochromata.anaphors.ast.ASTBasedAnaphora; 011import de.monochromata.anaphors.ast.AnaphorPart; 012import de.monochromata.anaphors.ast.DefaultAnaphorPart; 013import de.monochromata.anaphors.ast.DefaultRelatedExpressionPart; 014import de.monochromata.anaphors.ast.RelatedExpressionPart; 015import de.monochromata.anaphors.ast.reference.AbstractReferent; 016import de.monochromata.anaphors.ast.reference.Referent; 017import de.monochromata.anaphors.ast.reference.strategy.ReferentializationStrategy; 018import de.monochromata.anaphors.ast.relatedexp.RelatedExpression; 019import de.monochromata.anaphors.ast.relatedexp.strategy.ClassInstanceCreationStrategy; 020import de.monochromata.anaphors.ast.relatedexp.strategy.LocalVariableDeclarationStrategy; 021import de.monochromata.anaphors.ast.relatedexp.strategy.ParameterDeclarationStrategy; 022import de.monochromata.anaphors.ast.relatedexp.strategy.RelatedExpressionStrategy; 023import de.monochromata.anaphors.ast.spi.AnaphoraResolutionSpi; 024import de.monochromata.anaphors.ast.spi.AnaphorsSpi; 025import de.monochromata.anaphors.ast.spi.RelatedExpressionsSpi; 026import de.monochromata.anaphors.perspectivation.Perspectivation; 027 028/** 029 * A simple direct anaphora resolution strategy that is based on the various 030 * forms of recurrence that can be implemented using the available 031 * {@link ReferentializationStrategy} implementations. 032 * 033 * @param <N> The node type in the AST 034 * @param <E> The expression type 035 * @param <T> The type type 036 * @param <B> The binding type 037 * @param <VB> The variable binding type 038 * @param <FB> The field binding type 039 * @param <MB> The method binding type 040 * @param <TB> The type binding type 041 * @param <S> The scope type (optional) 042 * @param <I> The type used to represent identifiers 043 * @param <QI> The type used to represent qualified identifiers 044 * @param <EV> The type of the event contained in the condition that is 045 * evaluated to check when the perspectivations shall be applied. 046 * @param <PP> The type used for positions that carry perspectivations 047 * @param <R> The sub-type of related expression to use 048 * @param <A> The sub-type of AST-based anaphora to use 049 */ 050public class DA1ReStrategy<N, E, T, B, VB extends B, FB extends B, MB extends B, TB extends B, S, I, QI, EV, PP, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>> 051 extends AbstractAnaphorResolutionStrategy<N, E, T, B, VB, FB, MB, TB, S, I, QI, EV, PP, R, A> 052 implements StoresReferentInLocalTempVariable<N, E, T, B, TB, S, I, QI, R, A> { 053 054 public static final String DA1Re_KIND = "DA1Re"; 055 public static final List<Class<? extends RelatedExpressionStrategy>> DA1Re_SUPPORTED_RELATED_EXPRESSION_STRATEGIES = asList( 056 ClassInstanceCreationStrategy.class, ParameterDeclarationStrategy.class, 057 LocalVariableDeclarationStrategy.class); 058 059 /** 060 * Used in contract testing. 061 */ 062 @SuppressWarnings("unused") 063 protected DA1ReStrategy() { 064 } 065 066 public DA1ReStrategy(final AnaphorsSpi<N, E, TB, S, I, QI, EV, PP> anaphorsSpi, 067 final RelatedExpressionsSpi<N, E, T, B, MB, TB, S, I, QI, EV, PP, R> relatedExpressionsSpi, 068 final AnaphoraResolutionSpi<N, E, T, B, VB, FB, MB, TB, S, I, QI, R, A> anaphoraResolutionSpi) { 069 super(DA1Re_SUPPORTED_RELATED_EXPRESSION_STRATEGIES, anaphorsSpi, relatedExpressionsSpi, anaphoraResolutionSpi); 070 } 071 072 @Override 073 protected List<Referent<TB, S, I, QI>> createPotentialReferents(final S scope, final R potentialRelatedExpression) { 074 return singletonList(createReferent(potentialRelatedExpression)); 075 } 076 077 @Override 078 public Referent<TB, S, I, QI> createReferent(final S scope, final R relatedExpression, final Object memento) { 079 return createReferent(relatedExpression); 080 } 081 082 protected Referent<TB, S, I, QI> createReferent(final R relatedExpression) { 083 return new DA1Referent<>(relatedExpression, relatedExpressionsSpi, anaphoraResolutionSpi); 084 } 085 086 @Override 087 public A createAnaphora(final S scope, final String anaphor, final E anaphorExpression, 088 final R potentialRelatedExpression, final Referent<TB, S, I, QI> potentialReferent, 089 final ReferentializationStrategy<E, TB, S, I, QI> refStrategy) { 090 final DefaultRelatedExpressionPart<N, E, T, B, VB, TB, S, I, QI, R> relatedExpressionPart = new DefaultRelatedExpressionPart<>( 091 potentialRelatedExpression); 092 final DefaultAnaphorPart<N, E, T, B, VB, TB, S, I, QI, R, A> anaphorPart = new DefaultAnaphorPart<>(anaphor, 093 anaphorExpression, potentialReferent, this, refStrategy, 094 potentialRelatedExpression.resolveNameBinding(scope)); 095 return anaphoraResolutionSpi.createDirectAnaphora(relatedExpressionPart, anaphorPart, false); 096 } 097 098 @Override 099 public E realize(final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpressionPart, 100 final AnaphorPart<N, E, T, B, TB, S, I, QI, R, A> anaphorPart, final E replacee, 101 final Optional<I> guessedTempName, final Object... support) { 102 return anaphoraResolutionSpi.realizeDA1Re(relatedExpressionPart, anaphorPart, replacee, guessedTempName, 103 support); 104 } 105 106 @Override 107 public String getKind() { 108 return DA1Re_KIND; 109 } 110 111 @Override 112 public List<Perspectivation> underspecifyAnaphor(final R relatedExpression, final String anaphor, 113 final E anaphorExpression, final Referent<TB, S, I, QI> referent, final S scope) { 114 // No perspectivation necessary 115 return emptyList(); 116 } 117 118 @Override 119 public String getAnaphorToBeRealized(final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpressionPart, 120 final List<AnaphorPart<N, E, T, B, TB, S, I, QI, R, A>> allAnaphorPartsRelatedToTheRelatedExpression, 121 final AnaphorPart<N, E, T, B, TB, S, I, QI, R, A> anaphorPart, final S scope) { 122 return AnaphorCreationForReferentInLocalTempVariable.getAnaphorToBeRealized(relatedExpressionPart, 123 allAnaphorPartsRelatedToTheRelatedExpression, anaphorPart, scope, relatedExpressionsSpi); 124 } 125 126 public static class DA1Referent<N, E, T, B, VB extends B, FB extends B, MB extends B, TB extends B, S, I, QI, EV, PP, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>> 127 extends AbstractReferent<N, E, T, B, VB, FB, MB, TB, S, I, QI, R, A> { 128 129 private QI name; 130 private TB typeBinding; 131 132 /** 133 * Used in contract testing. 134 */ 135 @SuppressWarnings("unused") 136 protected DA1Referent() { 137 } 138 139 public DA1Referent(final R relatedExpression, 140 final RelatedExpressionsSpi<N, E, T, B, MB, TB, S, I, QI, EV, PP, R> relatedExpressionsSpi, 141 final AnaphoraResolutionSpi<N, E, T, B, VB, FB, MB, TB, S, I, QI, R, A> anaphorResolutionSpi) { 142 super(relatedExpression, relatedExpression.getDescription(), relatedExpressionsSpi, anaphorResolutionSpi); 143 } 144 145 @Override 146 public boolean canBeUsedInsteadOf(final Referent<TB, S, I, QI> other) { 147 // TODO: improve alias analysis, maybe use 148 // org.eclipse.jdt.internal.corext.refactoring.code.flow 149 return false; 150 } 151 152 @Override 153 public boolean hasName() { 154 return getRelatedExpression().hasName(); 155 } 156 157 @Override 158 public QI getName() { 159 return getRelatedExpression().getName(); 160 } 161 162 @Override 163 public boolean hasMethodName() { 164 return false; 165 } 166 167 @Override 168 public I getMethodName() { 169 throw new UnsupportedOperationException("DA1Referent has no method name"); 170 } 171 172 @Override 173 public TB resolveType(final S scope) { 174 if (this.typeBinding == null) { 175 this.typeBinding = getRelatedExpression().resolveType(scope); 176 } 177 return this.typeBinding; 178 } 179 180 @Override 181 public Object getMemento() { 182 return ""; 183 } 184 185 @Override 186 public int hashCode() { 187 final int prime = 31; 188 int result = super.hashCode(); 189 result = prime * result + ((name == null) ? 0 : name.hashCode()); 190 result = prime * result + ((typeBinding == null) ? 0 : typeBinding.hashCode()); 191 return result; 192 } 193 194 @Override 195 public boolean equals(final Object obj) { 196 if (this == obj) { 197 return true; 198 } 199 if (!super.equals(obj)) { 200 return false; 201 } 202 if (getClass() != obj.getClass()) { 203 return false; 204 } 205 final DA1Referent other = (DA1Referent) obj; 206 if (name == null) { 207 if (other.name != null) { 208 return false; 209 } 210 } else if (!name.equals(other.name)) { 211 return false; 212 } 213 if (typeBinding == null) { 214 if (other.typeBinding != null) { 215 return false; 216 } 217 } else if (!typeBinding.equals(other.typeBinding)) { 218 return false; 219 } 220 return true; 221 } 222 223 @Override 224 public String toString() { 225 // The type binding is not output because it can be quite long. 226 return "DA1Referent [name=" + name + ", getDescription()=" + getDescription() + ", getFeatures()=" 227 + getFeatures() + "]"; 228 } 229 230 } 231}