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}