mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-dfa] Restrict the result of CustomMethodHandler when qualifier is restricted
Fixes EA-1080132 - ISE: MethodCallInstruction.getMethodResultValue (String.trim, Enum.name) GitOrigin-RevId: 3ab2fe4fac1d9333d0a61198d2614eead74a173c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
8b5e8b8f6d
commit
d50f41f7ae
+15
-4
@@ -1,10 +1,7 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInspection.dataFlow.jvm.descriptors;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.DfaNullability;
|
||||
import com.intellij.codeInspection.dataFlow.DfaPsiUtil;
|
||||
import com.intellij.codeInspection.dataFlow.TypeConstraint;
|
||||
import com.intellij.codeInspection.dataFlow.TypeConstraints;
|
||||
import com.intellij.codeInspection.dataFlow.*;
|
||||
import com.intellij.codeInspection.dataFlow.memory.DfaMemoryState;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfAntiConstantType;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfConstantType;
|
||||
@@ -91,6 +88,20 @@ public final class GetterDescriptor extends PsiVarDescriptor {
|
||||
return super.createValue(factory, qualifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DfType restrictFromState(@NotNull DfaVariableValue qualifier, @NotNull DfaMemoryState state) {
|
||||
CustomMethodHandlers.CustomMethodHandler handler = CustomMethodHandlers.find(myGetter);
|
||||
if (handler != null) {
|
||||
DfaValue value = handler.getMethodResultValue(
|
||||
new DfaCallArguments(qualifier, DfaValue.EMPTY_ARRAY, MutationSignature.pure()),
|
||||
state, qualifier.getFactory(), myGetter);
|
||||
if (value != null) {
|
||||
return state.getDfType(value);
|
||||
}
|
||||
}
|
||||
return super.restrictFromState(qualifier, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(myGetter.getName());
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
class Scratch {
|
||||
void test(String codeblock) {
|
||||
if (codeblock.trim().equals("{")) {
|
||||
if (<warning descr="Condition 'codeblock.equals(\"}\")' is always 'false'">codeblock.equals("}")</warning>) {
|
||||
System.out.println(codeblock.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum E {A, B, C}
|
||||
|
||||
void test(E e) {
|
||||
if (e.name().equals("C")) {
|
||||
if (<warning descr="Condition 'e == E.A' is always 'false'">e == E.A</warning>) {
|
||||
System.out.println(e.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -760,4 +760,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
|
||||
public void testInitializedViaSuperCall() { doTest(); }
|
||||
public void testBoxedBooleanMethodWithCast() { doTest(); }
|
||||
public void testAssignAndReturnVolatile() { doTest(); }
|
||||
public void testQualifiedValueFromConstant() { doTest();}
|
||||
}
|
||||
|
||||
@@ -2626,6 +2626,7 @@ com.intellij.codeInspection.dataFlow.value.VariableDescriptor
|
||||
- isCall():Z
|
||||
- isImplicitReadPossible():Z
|
||||
- a:isStable():Z
|
||||
- restrictFromState(com.intellij.codeInspection.dataFlow.value.DfaVariableValue,com.intellij.codeInspection.dataFlow.memory.DfaMemoryState):com.intellij.codeInspection.dataFlow.types.DfType
|
||||
c:com.intellij.codeInspection.ex.ApplicationInspectionProfileManagerBase
|
||||
- com.intellij.profile.codeInspection.BaseInspectionProfileManager
|
||||
- sf:Companion:com.intellij.codeInspection.ex.ApplicationInspectionProfileManagerBase$Companion
|
||||
|
||||
+8
-1
@@ -19,7 +19,6 @@ import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -794,6 +793,14 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (Map.Entry<DfaVariableValue, DfType> entry : new ArrayList<>(myVariableTypes.entrySet())) {
|
||||
DfaVariableValue knownVar = entry.getKey();
|
||||
if (knownVar.getQualifier() == var) {
|
||||
if (!meetDfType(knownVar, knownVar.getDescriptor().restrictFromState(var, this))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!updateDependentVariables(var, newType)) return false;
|
||||
if (!correctRelatedValues(var, newType)) return false;
|
||||
if (newType instanceof DfConstantType && !propagateConstant(var, (DfConstantType<?>)newType)) return false;
|
||||
|
||||
+10
@@ -72,6 +72,16 @@ public interface VariableDescriptor {
|
||||
@NotNull
|
||||
DfType getDfType(@Nullable DfaVariableValue qualifier);
|
||||
|
||||
/**
|
||||
* @param qualifier qualifier
|
||||
* @param state memory state
|
||||
* @return DfType of this value, which might be more precise than the result of {@link #getDfType(DfaVariableValue)} if the
|
||||
* qualifier type is known to be more precise, and this information restricts the type of this value
|
||||
*/
|
||||
default @NotNull DfType restrictFromState(@NotNull DfaVariableValue qualifier, @NotNull DfaMemoryState state) {
|
||||
return getDfType(qualifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DfType the value with this descriptor has at the beginning of the interpretation in a given context.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user