From 5351111b7ee31e6d30315cea2dc37bf84e5d42c0 Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 4 Aug 2009 19:45:15 +0400 Subject: [PATCH] customizable value calculation --- .../intellij/psi/PsiConstantEvaluationHelper.java | 11 ++++++++ .../psi/impl/ConstantExpressionEvaluator.java | 31 +++++++++++++++++----- .../psi/impl/ConstantExpressionVisitor.java | 29 ++++++++++++++------ .../psi/impl/PsiConstantEvaluationHelperImpl.java | 12 ++++++--- 4 files changed, 64 insertions(+), 19 deletions(-) diff --git a/openapi/src/com/intellij/psi/PsiConstantEvaluationHelper.java b/openapi/src/com/intellij/psi/PsiConstantEvaluationHelper.java index 51eb804467..73c7153751 100644 --- a/openapi/src/com/intellij/psi/PsiConstantEvaluationHelper.java +++ b/openapi/src/com/intellij/psi/PsiConstantEvaluationHelper.java @@ -17,6 +17,8 @@ package com.intellij.psi; import org.jetbrains.annotations.Nullable; +import java.util.concurrent.ConcurrentMap; + /** * Service for evaluating values of constant expressions. * @@ -45,4 +47,13 @@ public abstract class PsiConstantEvaluationHelper { * @return the result of the evaluation, or null if the expression is not a constant expression. */ public abstract Object computeConstantExpression(PsiExpression expression, boolean throwExceptionOnOverflow); + + public abstract Object computeExpression(PsiExpression expression, boolean throwExceptionOnOverflow, + @Nullable final AuxEvaluator auxEvaluator); + + public interface AuxEvaluator { + Object computeExpression(final PsiExpression expression, final AuxEvaluator auxEvaluator); + + ConcurrentMap getCacheMap(final boolean overflow); + } } diff --git a/source/com/intellij/psi/impl/ConstantExpressionEvaluator.java b/source/com/intellij/psi/impl/ConstantExpressionEvaluator.java index e9838d9f0b..e0c2601681 100644 --- a/source/com/intellij/psi/impl/ConstantExpressionEvaluator.java +++ b/source/com/intellij/psi/impl/ConstantExpressionEvaluator.java @@ -1,6 +1,7 @@ package com.intellij.psi.impl; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Factory; import com.intellij.openapi.util.Key; import com.intellij.psi.*; import com.intellij.psi.util.CachedValue; @@ -15,7 +16,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentMap; public class ConstantExpressionEvaluator extends JavaRecursiveElementWalkingVisitor { - private final boolean myThrowExceptionOnOverflow; + private final Factory> myMapFactory; private final Project myProject; private static final Key>> CONSTANT_VALUE_WO_OVERFLOW_MAP_KEY = Key.create("CONSTANT_VALUE_WO_OVERFLOW_MAP_KEY"); @@ -23,10 +24,21 @@ public class ConstantExpressionEvaluator extends JavaRecursiveElementWalkingVisi private static final Object NO_VALUE = new Object(); private final ConstantExpressionVisitor myConstantExpressionVisitor; - private ConstantExpressionEvaluator(Set visitedVars, boolean throwExceptionOnOverflow, final Project project) { - myThrowExceptionOnOverflow = throwExceptionOnOverflow; + private ConstantExpressionEvaluator(Set visitedVars, final boolean throwExceptionOnOverflow, final Project project, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) { + myMapFactory = auxEvaluator != null ? new Factory>() { + public ConcurrentMap create() { + return auxEvaluator.getCacheMap(throwExceptionOnOverflow); + } + } : new Factory>() { + public ConcurrentMap create() { + final Key>> key = + throwExceptionOnOverflow ? CONSTANT_VALUE_WITH_OVERFLOW_MAP_KEY : CONSTANT_VALUE_WO_OVERFLOW_MAP_KEY; + return PsiManager.getInstance(myProject).getCachedValuesManager().getCachedValue(myProject, key, PROVIDER, false); + } + }; myProject = project; - myConstantExpressionVisitor = new ConstantExpressionVisitor(visitedVars, throwExceptionOnOverflow); + myConstantExpressionVisitor = new ConstantExpressionVisitor(visitedVars, throwExceptionOnOverflow, auxEvaluator); + } @Override @@ -70,14 +82,19 @@ public class ConstantExpressionEvaluator extends JavaRecursiveElementWalkingVisi @NotNull private ConcurrentMap map() { - Key>> key = myThrowExceptionOnOverflow ? CONSTANT_VALUE_WITH_OVERFLOW_MAP_KEY : CONSTANT_VALUE_WO_OVERFLOW_MAP_KEY; - return PsiManager.getInstance(myProject).getCachedValuesManager().getCachedValue(myProject, key, PROVIDER, false); + return myMapFactory.create(); } public static Object computeConstantExpression(PsiExpression expression, @Nullable Set visitedVars, boolean throwExceptionOnOverflow) { + return computeConstantExpression(expression, visitedVars, throwExceptionOnOverflow, null); + } + + public static Object computeConstantExpression(PsiExpression expression, @Nullable Set visitedVars, boolean throwExceptionOnOverflow, + final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) { if (expression == null) return null; - ConstantExpressionEvaluator evaluator = new ConstantExpressionEvaluator(visitedVars, throwExceptionOnOverflow, expression.getProject()); + ConstantExpressionEvaluator evaluator = new ConstantExpressionEvaluator(visitedVars, throwExceptionOnOverflow, expression.getProject(), + auxEvaluator); expression.accept(evaluator); Object cached = evaluator.getCached(expression); return cached == NO_VALUE ? null : cached; diff --git a/source/com/intellij/psi/impl/ConstantExpressionVisitor.java b/source/com/intellij/psi/impl/ConstantExpressionVisitor.java index a033916e1f..dba09dae07 100644 --- a/source/com/intellij/psi/impl/ConstantExpressionVisitor.java +++ b/source/com/intellij/psi/impl/ConstantExpressionVisitor.java @@ -9,8 +9,9 @@ import com.intellij.util.containers.StringInterner; import gnu.trove.THashSet; import java.util.Set; +import java.util.concurrent.ConcurrentMap; -class ConstantExpressionVisitor extends JavaElementVisitor { +class ConstantExpressionVisitor extends JavaElementVisitor implements PsiConstantEvaluationHelper.AuxEvaluator { private final StringInterner myInterner = new StringInterner(); private Set myVisitedVars; @@ -18,9 +19,12 @@ class ConstantExpressionVisitor extends JavaElementVisitor { private Object myResult; - ConstantExpressionVisitor(Set visitedVars, boolean throwExceptionOnOverflow) { + private final PsiConstantEvaluationHelper.AuxEvaluator myAuxEvaluator; + + ConstantExpressionVisitor(Set visitedVars, boolean throwExceptionOnOverflow, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) { myVisitedVars = visitedVars; myThrowExceptionOnOverflow = throwExceptionOnOverflow; + myAuxEvaluator = auxEvaluator; } Object handle(PsiElement element) { @@ -473,6 +477,11 @@ class ConstantExpressionVisitor extends JavaElementVisitor { myResult = getStoredValue(expression.getExpression()); } + @Override + public void visitMethodCallExpression(final PsiMethodCallExpression expression) { + myResult = myAuxEvaluator != null? myAuxEvaluator.computeExpression(expression, this) : null; + } + @Override public void visitReferenceExpression(PsiReferenceExpression expression) { PsiExpression qualifierExpression = expression.getQualifierExpression(); while (qualifierExpression != null) { @@ -504,12 +513,8 @@ class ConstantExpressionVisitor extends JavaElementVisitor { myVisitedVars.add(variable); try { - if (!(variable instanceof PsiVariableEx)) { - myResult = null; //? - return; - } - - myResult = ((PsiVariableEx) variable).computeConstantValue(myVisitedVars); + myResult = variable instanceof PsiVariableEx? ((PsiVariableEx) variable).computeConstantValue(myVisitedVars) : null; + if (myResult == null && myAuxEvaluator != null) myResult = myAuxEvaluator.computeExpression(expression, this); return; } finally { @@ -557,4 +562,12 @@ class ConstantExpressionVisitor extends JavaElementVisitor { if (result instanceof Float && ((Float) result).isInfinite()) throw new ConstantEvaluationOverflowException(expression); if (result instanceof Double && ((Double) result).isInfinite()) throw new ConstantEvaluationOverflowException(expression); } + + public Object computeExpression(final PsiExpression expression, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) { + return ConstantExpressionEvaluator.computeConstantExpression(expression, myVisitedVars, myThrowExceptionOnOverflow, auxEvaluator); + } + + public ConcurrentMap getCacheMap(final boolean overflow) { + throw new AssertionError("should not be called"); + } } \ No newline at end of file diff --git a/source/com/intellij/psi/impl/PsiConstantEvaluationHelperImpl.java b/source/com/intellij/psi/impl/PsiConstantEvaluationHelperImpl.java index 7e1654925e..8aa7c87368 100644 --- a/source/com/intellij/psi/impl/PsiConstantEvaluationHelperImpl.java +++ b/source/com/intellij/psi/impl/PsiConstantEvaluationHelperImpl.java @@ -1,9 +1,6 @@ package com.intellij.psi.impl; -import com.intellij.psi.PsiConstantEvaluationHelper; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiVariable; +import com.intellij.psi.*; import com.intellij.psi.util.ConstantExpressionUtil; import java.util.Set; @@ -20,6 +17,13 @@ public class PsiConstantEvaluationHelperImpl extends PsiConstantEvaluationHelper return ConstantExpressionEvaluator.computeConstantExpression(expression, throwExceptionOnOverflow); } + @Override + public Object computeExpression(final PsiExpression expression, + final boolean throwExceptionOnOverflow, + final AuxEvaluator auxEvaluator) { + return ConstantExpressionEvaluator.computeConstantExpression(expression, null, throwExceptionOnOverflow, auxEvaluator); + } + public static Object computeCastTo(PsiExpression expression, PsiType castTo, Set visitedVars) { Object value = ConstantExpressionEvaluator.computeConstantExpression(expression, visitedVars, false); if(value == null) return null; -- 2.11.4.GIT