summaryrefslogtreecommitdiff
path: root/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java
diff options
context:
space:
mode:
authorJean-Baptiste Queru <jbq@google.com>2013-01-08 11:11:20 -0800
committerJean-Baptiste Queru <jbq@google.com>2013-01-08 11:11:20 -0800
commitb56ea2a18f232d79481e778085fd64e8ae486fc3 (patch)
tree44e1f6eb4864a45033f865b74fe783e3d784dd6a /java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java
downloadidea-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.java195
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;
+ }
+}