Constant methods: boxing support

GitOrigin-RevId: 6fa28da7fe823d2e5bea0ecabe1e49e34e55d7b6
This commit is contained in:
Tagir Valeev
2019-12-14 03:44:42 +00:00
committed by intellij-monorepo-bot
parent e413982fdf
commit 916cc45005
7 changed files with 38 additions and 5 deletions
@@ -46,7 +46,15 @@ class CustomMethodHandlers {
staticCall(JAVA_LANG_FLOAT, "toString", "toHexString").parameterTypes("float"),
staticCall(JAVA_LANG_BYTE, "toString").parameterTypes("byte"),
staticCall(JAVA_LANG_SHORT, "toString").parameterTypes("short"),
staticCall(JAVA_LANG_BOOLEAN, "parseBoolean").parameterTypes("java.lang.String")
staticCall(JAVA_LANG_BOOLEAN, "parseBoolean").parameterTypes("java.lang.String"),
exactInstanceCall(JAVA_LANG_INTEGER, "toString").parameterCount(0),
exactInstanceCall(JAVA_LANG_LONG, "toString").parameterCount(0),
exactInstanceCall(JAVA_LANG_DOUBLE, "toString").parameterCount(0),
exactInstanceCall(JAVA_LANG_FLOAT, "toString").parameterCount(0),
exactInstanceCall(JAVA_LANG_BYTE, "toString").parameterCount(0),
exactInstanceCall(JAVA_LANG_SHORT, "toString").parameterCount(0),
exactInstanceCall(JAVA_LANG_CHARACTER, "toString").parameterCount(0),
exactInstanceCall(JAVA_LANG_BOOLEAN, "toString").parameterCount(0)
);
static final int MAX_STRING_CONSTANT_LENGTH_TO_TRACK = 256;
@@ -352,7 +360,7 @@ class CustomMethodHandlers {
}
private static Object getConstantValue(DfaMemoryState memoryState, DfaValue value) {
DfType type = memoryState.getDfType(value);
DfType type = memoryState.getUnboxedDfType(value);
Object constant = DfConstantType.getConstantOfType(type, Object.class);
if (constant instanceof String && ((String)constant).length() > MAX_STRING_CONSTANT_LENGTH_TO_TRACK) return null;
return constant;
@@ -1172,6 +1172,12 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
if (value instanceof DfaVariableValue && TypeConversionUtil.isPrimitiveWrapper(value.getType())) {
return getDfType(SpecialField.UNBOX.createValue(myFactory, value));
}
if (value instanceof DfaTypeValue) {
DfReferenceType refType = ObjectUtils.tryCast(value.getDfType(), DfReferenceType.class);
if (refType != null && refType.getSpecialField() == SpecialField.UNBOX) {
return refType.getSpecialFieldType();
}
}
return getDfType(value);
}
@@ -562,6 +562,10 @@ public class StandardInstructionVisitor extends InstructionVisitor {
if (precalculated != null) {
return getPrecalculatedResult(qualifierValue, state, factory, precalculated);
}
SpecialField field = SpecialField.findSpecialField(instruction.getTargetMethod());
if (field != null) {
return factory.fromDfType(field.getFromQualifier(state.getDfType(qualifierValue)));
}
PsiType type = instruction.getResultType();
@@ -18,6 +18,7 @@ package com.intellij.codeInspection.dataFlow.instructions;
import com.intellij.codeInsight.Nullability;
import com.intellij.codeInspection.dataFlow.*;
import com.intellij.codeInspection.dataFlow.value.DfaTypeValue;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.psi.*;
import com.intellij.util.ObjectUtils;
@@ -96,7 +97,7 @@ public class MethodCallInstruction extends ExpressionPushingInstruction<PsiExpre
}
myShouldFlushFields = !(call instanceof PsiNewExpression && myType != null && myType.getArrayDimensions() > 0 || isPureCall());
myPrecalculatedReturnValue = precalculatedReturnValue;
myPrecalculatedReturnValue = DfaTypeValue.isUnknown(precalculatedReturnValue) ? null : precalculatedReturnValue;
myReturnNullability = call instanceof PsiNewExpression ? Nullability.NOT_NULL : DfaPsiUtil.getElementNullability(myType, myTargetMethod);
}
@@ -15,7 +15,7 @@ public class MethodReferenceConstantValue {
Boolean aBoolean = opt.map(s -> false)
.map(o1 -> true)
.map(o -> false)
.orElse(false);
.orElse(new Random().nextBoolean());
if (opt.isPresent()) {
Stream.generate(() -> true)
.limit(10)
@@ -15,7 +15,7 @@ public class MethodReferenceConstantValue {
Boolean aBoolean = opt.map(th<caret>is::strangeMethod)
.map(Objects::nonNull)
.map(Objects::isNull)
.orElse(false);
.orElse(new Random().nextBoolean());
if (opt.isPresent()) {
Stream.generate(opt::isPresent)
.limit(10)
@@ -22,4 +22,18 @@ class Test {
System.out.println("Impossible");
}
}
void test4() {
boolean b1 = <warning descr="Result of 'Boolean.valueOf(false).booleanValue()' is always 'false'">Boolean.valueOf(false).booleanValue()</warning>;
boolean b2 = <warning descr="Result of 'Boolean.FALSE.booleanValue()' is always 'false'">Boolean.FALSE.booleanValue()</warning>;
boolean b3 = <warning descr="Result of 'Boolean.parseBoolean(\"false\")' is always 'false'">Boolean.parseBoolean("false")</warning>;
boolean b4 = <warning descr="Result of 'Boolean.valueOf(false).toString().startsWith(\"t\")' is always 'false'">Boolean.valueOf(false).toString().startsWith("t")</warning>;
}
void test5(double x) {
if (x == 5 || x == 7) {
Double y = x;
System.out.println(<warning descr="Condition 'y.toString().length() == 3' is always 'true'">y.toString().length() == 3</warning>);
}
}
}