diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2013-01-08 11:11:20 -0800 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2013-01-08 11:11:20 -0800 |
commit | b56ea2a18f232d79481e778085fd64e8ae486fc3 (patch) | |
tree | 44e1f6eb4864a45033f865b74fe783e3d784dd6a /java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java | |
download | idea-b56ea2a18f232d79481e778085fd64e8ae486fc3.tar.gz |
Snapshot of commit d5ec1d5018ed24f1b4f32b1d09df6dbd7e2fc425
from branch master of git://git.jetbrains.org/idea/community.git
Diffstat (limited to 'java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java')
-rw-r--r-- | java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java new file mode 100644 index 000000000000..83c9f5efaafb --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java @@ -0,0 +1,195 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Created by IntelliJ IDEA. + * User: max + * Date: Feb 7, 2002 + * Time: 2:33:28 PM + * To change template for new class use + * Code Style | Class Templates options (Tools | IDE Options). + */ +package com.intellij.codeInspection.dataFlow.value; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.*; +import com.intellij.psi.impl.JavaConstantExpressionEvaluator; +import gnu.trove.TIntObjectHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class DfaValueFactory { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.value.DfaValueFactory"); + + private int myLastID; + private final TIntObjectHashMap<DfaValue> myValues; + + public DfaValueFactory() { + myValues = new TIntObjectHashMap<DfaValue>(); + myLastID = 0; + + myVarFactory = new DfaVariableValue.Factory(this); + myConstFactory = new DfaConstValue.Factory(this); + myBoxedFactory = new DfaBoxedValue.Factory(this); + myNotNullFactory = new DfaNotNullValue.Factory(this); + myTypeFactory = new DfaTypeValue.Factory(this); + myRelationFactory = new DfaRelationValue.Factory(this); + } + + public DfaValue createTypeValueWithNullability(@Nullable PsiType type, @Nullable Boolean nullability) { + return nullability == Boolean.FALSE ? getNotNullFactory().create(type) : getTypeFactory().create(type, nullability == Boolean.TRUE); + } + + int createID() { + myLastID++; + LOG.assertTrue(myLastID >= 0, "Overflow"); + return myLastID; + } + + void registerValue(DfaValue value) { + myValues.put(value.getID(), value); + } + + public DfaValue getValue(int id) { + return myValues.get(id); + } + + @Nullable + public DfaValue createValue(PsiExpression psiExpression) { + if (psiExpression instanceof PsiReferenceExpression) { + return createReferenceValue((PsiReferenceExpression)psiExpression); + } + + if (psiExpression instanceof PsiLiteralExpression) { + return createLiteralValue((PsiLiteralExpression)psiExpression); + } + + if (psiExpression instanceof PsiNewExpression) { + return getNotNullFactory().create(psiExpression.getType()); + } + + final Object value = JavaConstantExpressionEvaluator.computeConstantExpression(psiExpression, false); + PsiType type = psiExpression.getType(); + if (value != null && type != null) { + if (value instanceof String) { + return getNotNullFactory().create(type); // Non-null string literal. + } + return getConstFactory().createFromValue(value, type); + } + + return null; + } + + @Nullable + public DfaValue createLiteralValue(PsiLiteralExpression literal) { + if (literal.getValue() instanceof String) { + return getNotNullFactory().create(literal.getType()); // Non-null string literal. + } + return getConstFactory().create(literal); + } + + private static boolean isNotNullExpression(PsiExpression initializer, PsiType type) { + if (initializer instanceof PsiNewExpression) { + return true; + } + if (initializer instanceof PsiPolyadicExpression) { + if (type != null && type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) { + return true; + } + } + + return false; + } + + @Nullable + public DfaValue createReferenceValue(PsiReferenceExpression referenceExpression) { + PsiElement psiSource = referenceExpression.resolve(); + if (!(psiSource instanceof PsiVariable)) { + return null; + } + + final PsiVariable variable = (PsiVariable)psiSource; + if (variable.hasModifierProperty(PsiModifier.FINAL) && !variable.hasModifierProperty(PsiModifier.TRANSIENT)) { + DfaValue constValue = getConstFactory().create(variable); + if (constValue != null) return constValue; + + PsiExpression initializer = variable.getInitializer(); + PsiType type = initializer == null ? null : initializer.getType(); + if (initializer != null && type != null && isNotNullExpression(initializer, type)) { + return getNotNullFactory().create(type); + } + } + + if (isEffectivelyUnqualified(referenceExpression)) { + return getVarFactory().createVariableValue(variable, referenceExpression.getType(), false, null, false); + } + + return null; + } + + @Nullable + public static PsiVariable resolveUnqualifiedVariable(PsiReferenceExpression refExpression) { + if (isEffectivelyUnqualified(refExpression)) { + PsiElement resolved = refExpression.resolve(); + if (resolved instanceof PsiVariable) { + return (PsiVariable)resolved; + } + } + + return null; + } + + private static boolean isEffectivelyUnqualified(PsiReferenceExpression refExpression) { + PsiExpression qualifier = refExpression.getQualifierExpression(); + return qualifier == null || qualifier instanceof PsiThisExpression; + } + + private final DfaVariableValue.Factory myVarFactory; + private final DfaConstValue.Factory myConstFactory; + private final DfaBoxedValue.Factory myBoxedFactory; + private final DfaNotNullValue.Factory myNotNullFactory; + private final DfaTypeValue.Factory myTypeFactory; + private final DfaRelationValue.Factory myRelationFactory; + + @NotNull + public DfaVariableValue.Factory getVarFactory() { + return myVarFactory; + } + + @NotNull + public DfaConstValue.Factory getConstFactory() { + return myConstFactory; + } + @NotNull + public DfaBoxedValue.Factory getBoxedFactory() { + return myBoxedFactory; + } + + @NotNull + public DfaNotNullValue.Factory getNotNullFactory() { + return myNotNullFactory; + } + + @NotNull + public DfaTypeValue.Factory getTypeFactory() { + return myTypeFactory; + } + + @NotNull + public DfaRelationValue.Factory getRelationFactory() { + return myRelationFactory; + } +} |