001package de.monochromata.anaphors.ast.relatedexp.strategy; 002 003import static de.monochromata.anaphors.ast.AnaphorPartsStreaming.toVariableContentsAndAnaphors; 004import static java.util.Arrays.asList; 005 006import java.util.List; 007import java.util.function.Function; 008 009import org.apache.commons.lang3.tuple.Pair; 010 011import de.monochromata.anaphors.ast.ASTBasedAnaphora; 012import de.monochromata.anaphors.ast.AnaphorPart; 013import de.monochromata.anaphors.ast.RelatedExpressionPart; 014import de.monochromata.anaphors.ast.relatedexp.RelatedExpression; 015import de.monochromata.anaphors.ast.spi.RelatedExpressionsSpi; 016import de.monochromata.anaphors.perspectivation.Perspectivation; 017import de.monochromata.anaphors.preferences.Preferences; 018 019/** 020 * Abstract base class for related expressions whose realization introduces 021 * local temporary variables. 022 * 023 * @param <N> The node type in the AST 024 * @param <E> The expression type 025 * @param <T> The type type 026 * @param <B> The binding type 027 * @param <MB> The method binding type 028 * @param <TB> The type binding type 029 * @param <S> The scope type (optional) 030 * @param <I> The type used to represent identifiers 031 * @param <QI> The type used to represent qualified identifiers 032 * @param <EV> The type of the event contained in the condition that is 033 * evaluated to check when the perspectivations shall be applied. 034 * @param <PP> The type used for positions that carry perspectivations 035 * @param <R> The sub-type of related expression to use 036 * @param <A> The sub-type of AST-based anaphora to use 037 */ 038public abstract class AbstractLocalTempVariableIntroducingStrategy<N, E, T, 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>> 039 extends AbstractRelatedExpressionStrategy<N, E, T, B, MB, TB, S, I, QI, EV, PP, R> 040 implements LocalTempVariableIntroducingStrategy<N, E, T, B, TB, S, I, QI, R, A> { 041 042 /** 043 * Used in contract testing. 044 */ 045 @SuppressWarnings("unused") 046 protected AbstractLocalTempVariableIntroducingStrategy() { 047 } 048 049 public AbstractLocalTempVariableIntroducingStrategy( 050 final RelatedExpressionsSpi<N, E, T, B, MB, TB, S, I, QI, EV, PP, R> relatedExpressionsSpi, 051 final Preferences preferences) { 052 super(relatedExpressionsSpi, preferences); 053 } 054 055 @Override 056 public List<Perspectivation> underspecifyRelatedExpression(final R relatedExpression, 057 final List<Pair<LocalTempVariableContents, String>> variableContentsAndAnaphors, final S scope) { 058 return underspecifyRelatedExpressionForLocalTempVariable(relatedExpression, variableContentsAndAnaphors, scope); 059 } 060 061 public List<Perspectivation> underspecifyRelatedExpressionForLocalTempVariable(final R relatedExpression, 062 final List<Pair<LocalTempVariableContents, String>> variableContentsAndAnaphors, final S scope) { 063 final String optionalFinalModifierAndSpace = preferences.getAddFinalModifierToCreatedTemporaryVariables() 064 ? "final " 065 : ""; 066 final int lengthOfTypeName = getLengthOfTypeForTempVariable(relatedExpression, scope); 067 final I tempName = relatedExpressionsSpi.guessTempName(relatedExpression, variableContentsAndAnaphors, scope); 068 final int lengthOfTempName = relatedExpressionsSpi.getLength(tempName); 069 final int lengthToHide = optionalFinalModifierAndSpace.length() + lengthOfTypeName + " ".length() 070 + lengthOfTempName + " = ".length(); 071 return asList(new Perspectivation.Hide(0, lengthToHide)); 072 } 073 074 @Override 075 public int getLengthOfTypeForTempVariable( 076 final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpressionPart, final S scope) { 077 final R relatedExpression = relatedExpressionPart.getRelatedExpression(); 078 return getLengthOfTypeForTempVariable(relatedExpression, scope); 079 } 080 081 public int getLengthOfTypeForTempVariable(final R relatedExpression, final S scope) { 082 if (useLocalVariableTypeInference(scope)) { 083 final T type = relatedExpressionsSpi.getReservedTypeVar(scope); 084 return relatedExpressionsSpi.getLengthOfSimpleNameOfType(type); 085 } 086 return relatedExpression.getLengthOfTypeForTempVar(scope); 087 } 088 089 @Override 090 public T getTypeForTempVariable(final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpressionPart, 091 final S scope, final Function<TB, T> importRewrite) { 092 final R relatedExpression = relatedExpressionPart.getRelatedExpression(); 093 return getTypeForTempVariable(relatedExpression, scope, importRewrite); 094 } 095 096 public T getTypeForTempVariable(final R relatedExpression, final S scope, final Function<TB, T> importRewrite) { 097 if (useLocalVariableTypeInference(scope)) { 098 return relatedExpressionsSpi.getReservedTypeVar(scope); 099 } 100 return relatedExpression.getTypeForTempVar(scope, importRewrite); 101 } 102 103 protected boolean useLocalVariableTypeInference(final S scope) { 104 return preferences.getUseLocalVariableTypeInference() 105 && relatedExpressionsSpi.supportsLocalVariableTypeInference(scope); 106 } 107 108 @Override 109 public I getIdentifierForTempVariable( 110 final RelatedExpressionPart<N, E, T, B, TB, S, I, QI, R> relatedExpressionPart, 111 final List<AnaphorPart<N, E, T, B, TB, S, I, QI, R, A>> anaphorParts, final S scope) { 112 final List<Pair<LocalTempVariableContents, String>> variableContentsAndAnaphors = toVariableContentsAndAnaphors( 113 anaphorParts); 114 return relatedExpressionsSpi.guessTempName(relatedExpressionPart.getRelatedExpression(), 115 variableContentsAndAnaphors, scope); 116 } 117 118}