blob: 5c8d7ca276d5f9a510b204c88e47803ad3ef2019 [file] [log] [blame]
/*
* 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: Jan 28, 2002
* Time: 6:31:23 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.psi.*;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public class DfaConstValue extends DfaValue {
private static final Throwable ourThrowable = new Throwable();
public static class Factory {
private final DfaConstValue dfaNull;
private final DfaConstValue dfaFalse;
private final DfaConstValue dfaTrue;
private final DfaConstValue dfaFail;
private final DfaValueFactory myFactory;
private final Map<Object, DfaConstValue> myValues = ContainerUtil.newHashMap();
Factory(DfaValueFactory factory) {
myFactory = factory;
dfaNull = new DfaConstValue(null, factory, null);
dfaFalse = new DfaConstValue(Boolean.FALSE, factory, null);
dfaTrue = new DfaConstValue(Boolean.TRUE, factory, null);
dfaFail = new DfaConstValue(ourThrowable, factory, null);
}
@Nullable
public DfaValue create(PsiLiteralExpression expr) {
PsiType type = expr.getType();
if (PsiType.NULL.equals(type)) return dfaNull;
Object value = expr.getValue();
if (value == null) return null;
return createFromValue(value, type, null);
}
@Nullable
public DfaValue create(PsiVariable variable) {
Object value = variable.computeConstantValue();
PsiType type = variable.getType();
if (value == null) {
Boolean boo = computeJavaLangBooleanFieldReference(variable);
if (boo != null) {
DfaConstValue unboxed = createFromValue(boo, PsiType.BOOLEAN, variable);
return myFactory.getBoxedFactory().createBoxed(unboxed);
}
return null;
}
return createFromValue(value, type, variable);
}
@Nullable
private static Boolean computeJavaLangBooleanFieldReference(final PsiVariable variable) {
if (!(variable instanceof PsiField)) return null;
PsiClass psiClass = ((PsiField)variable).getContainingClass();
if (psiClass == null || !CommonClassNames.JAVA_LANG_BOOLEAN.equals(psiClass.getQualifiedName())) return null;
@NonNls String name = variable.getName();
return "TRUE".equals(name) ? Boolean.TRUE : "FALSE".equals(name) ? Boolean.FALSE : null;
}
@NotNull
public DfaConstValue createFromValue(Object value, final PsiType type, @Nullable PsiVariable constant) {
if (value == Boolean.TRUE) return dfaTrue;
if (value == Boolean.FALSE) return dfaFalse;
if (TypeConversionUtil.isNumericType(type) && !TypeConversionUtil.isFloatOrDoubleType(type)) {
value = TypeConversionUtil.computeCastTo(value, PsiType.LONG);
}
if (value instanceof Double || value instanceof Float) {
double doubleValue = ((Number)value).doubleValue();
if (doubleValue == -0.0) doubleValue = +0.0;
value = new Double(doubleValue);
}
DfaConstValue instance = myValues.get(value);
if (instance == null) {
instance = new DfaConstValue(value, myFactory, constant);
myValues.put(value, instance);
}
return instance;
}
public DfaConstValue getContractFail() {
return dfaFail;
}
public DfaConstValue getFalse() {
return dfaFalse;
}
public DfaConstValue getTrue() {
return dfaTrue;
}
public DfaConstValue getNull() {
return dfaNull;
}
}
private final Object myValue;
@Nullable private final PsiVariable myConstant;
private DfaConstValue(Object value, DfaValueFactory factory, @Nullable PsiVariable constant) {
super(factory);
myValue = value;
myConstant = constant;
}
@SuppressWarnings({"HardCodedStringLiteral"})
public String toString() {
if (myValue == null) return "null";
return myValue.toString();
}
public Object getValue() {
return myValue;
}
@Nullable
public PsiVariable getConstant() {
return myConstant;
}
@Override
public DfaValue createNegated() {
if (this == myFactory.getConstFactory().getTrue()) return myFactory.getConstFactory().getFalse();
if (this == myFactory.getConstFactory().getFalse()) return myFactory.getConstFactory() .getTrue();
return DfaUnknownValue.getInstance();
}
}