diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/CFGBuilder.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/CFGBuilder.java
index 1c88cccf17a3..bc6aa446b8a5 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/CFGBuilder.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/CFGBuilder.java
@@ -132,7 +132,7 @@ public class CFGBuilder {
*/
@Contract("_ -> this")
public @NotNull CFGBuilder unwrap(@NotNull DerivedVariableDescriptor descriptor) {
- return add(new UnwrapDerivedVariableInstruction(descriptor));
+ return add(new GetQualifiedValueInstruction(descriptor));
}
/**
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/ControlFlowAnalyzer.java
index 1b465ffa2290..7d071693bda4 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/ControlFlowAnalyzer.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/ControlFlowAnalyzer.java
@@ -540,7 +540,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
length = SpecialField.COLLECTION_SIZE;
}
if (length != null) {
- addInstruction(new UnwrapDerivedVariableInstruction(length));
+ addInstruction(new GetQualifiedValueInstruction(length));
addInstruction(new ConditionalGotoInstruction(loopEndOffset, DfTypes.intValue(0)));
hasSizeCheck = true;
} else {
@@ -875,7 +875,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
}
DfaControlTransferValue transferValue = exception != null ? createTransfer(exception) : null;
addInstruction(new DupInstruction());
- addInstruction(new UnwrapDerivedVariableInstruction(SpecialField.CONSUMED_STREAM));
+ addInstruction(new GetQualifiedValueInstruction(SpecialField.CONSUMED_STREAM));
addInstruction(new EnsureInstruction(new ConsumedStreamProblem(reference), RelationType.NE, DfStreamStateType.CONSUMED, transferValue));
addInstruction(new PopInstruction());
}
@@ -1900,7 +1900,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
if (TypeConversionUtil.isPrimitiveAndNotNull(expectedType) &&
TypeConversionUtil.isAssignableFromPrimitiveWrapper(toBound(actualType))) {
- addInstruction(new UnwrapDerivedVariableInstruction(SpecialField.UNBOX));
+ addInstruction(new GetQualifiedValueInstruction(SpecialField.UNBOX));
actualType = PsiPrimitiveType.getUnboxedType(actualType);
}
expectedType = toBound(expectedType);
@@ -2487,22 +2487,49 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
@Override public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
startElement(expression);
+ pushReferenceExpression(expression);
+ addNullCheck(expression);
+ finishElement(expression);
+ }
+ private void pushReferenceExpression(@NotNull PsiReferenceExpression expression) {
+ JavaExpressionAnchor anchor = new JavaExpressionAnchor(expression);
+ PsiVariable var = ObjectUtils.tryCast(expression.resolve(), PsiVariable.class);
+ // complex assignments (e.g. "|=") are both reading and writing
+ boolean writing = PsiUtil.isAccessedForWriting(expression) && !PsiUtil.isAccessedForReading(expression);
+ if (!writing && var != null && !PlainDescriptor.hasInitializationHacks(var)) {
+ DfaValue constValue = JavaDfaValueFactory.getConstantFromVariable(myFactory, var);
+ if (constValue != null && !JavaDfaValueFactory.maybeUninitializedConstant(constValue, expression, var)) {
+ addInstruction(new JvmPushInstruction(constValue, anchor));
+ return;
+ }
+ }
final PsiExpression qualifierExpression = expression.getQualifierExpression();
+ if (var instanceof PsiField field && !field.hasModifierProperty(PsiModifier.STATIC) && !writing) {
+ DfaValue effectiveQualifier = JavaDfaValueFactory.getQualifierOrThisValue(myFactory, expression);
+ if (qualifierExpression == null) {
+ addInstruction(new JvmPushInstruction(effectiveQualifier == null ? myFactory.getUnknown() : effectiveQualifier, null));
+ } else {
+ qualifierExpression.accept(this);
+ }
+ VariableDescriptor descriptor = Objects.requireNonNull(JavaDfaValueFactory.getAccessedVariableOrGetter(field));
+ if (effectiveQualifier instanceof DfaVariableValue qualifierVar &&
+ JavaDfaHelpers.mayLeakFromType(descriptor.getDfType(qualifierVar)) &&
+ JavaDfaHelpers.mayLeakFromExpression(expression)) {
+ addInstruction(new EscapeInstruction(List.of(qualifierVar.getDescriptor())));
+ }
+ addInstruction(new GetQualifiedValueInstruction(descriptor, anchor));
+ return;
+ }
if (qualifierExpression != null && !(qualifierExpression instanceof PsiReferenceExpression ref && ref.resolve() instanceof PsiClass)) {
qualifierExpression.accept(this);
addInstruction(new PopInstruction());
}
- // complex assignments (e.g. "|=") are both reading and writing
- boolean writing = PsiUtil.isAccessedForWriting(expression) && !PsiUtil.isAccessedForReading(expression);
DfaValue value = JavaDfaValueFactory.getExpressionDfaValue(myFactory, expression);
addInstruction(new JvmPushInstruction(value == null ? myFactory.getUnknown() : value,
- writing ? null : new JavaExpressionAnchor(expression),
+ writing ? null : anchor,
writing));
- addNullCheck(expression);
-
- finishElement(expression);
}
@Override public void visitLiteralExpression(@NotNull PsiLiteralExpression expression) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/JavaDfaHelpers.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/JavaDfaHelpers.java
index a149c1c26dea..a10ddd8f1677 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/JavaDfaHelpers.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/JavaDfaHelpers.java
@@ -13,6 +13,7 @@ import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.codeInspection.dataFlow.value.DfaWrappedValue;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
+import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -73,4 +74,9 @@ public final class JavaDfaHelpers {
}
return (psiType == null ? DfType.TOP : TypeConstraints.exactSubtype(expression, psiType).asDfType()).meet(DfTypes.NOT_NULL_OBJECT);
}
+
+ static boolean mayLeakFromExpression(@NotNull PsiExpression expression) {
+ PsiElement parent = ExpressionUtils.getPassThroughParent(expression);
+ return !(parent instanceof PsiInstanceOfExpression) && !(parent instanceof PsiPolyadicExpression);
+ }
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/JavaDfaValueFactory.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/JavaDfaValueFactory.java
index 0a21157e50d6..378ac8a51eaf 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/JavaDfaValueFactory.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/JavaDfaValueFactory.java
@@ -184,9 +184,9 @@ public final class JavaDfaValueFactory {
return qualifierValue;
}
- private static boolean maybeUninitializedConstant(DfaValue constValue,
- @NotNull PsiReferenceExpression refExpr,
- PsiModifierListOwner var) {
+ static boolean maybeUninitializedConstant(DfaValue constValue,
+ @NotNull PsiReferenceExpression refExpr,
+ PsiModifierListOwner var) {
// If static final field is referred from the same or inner/nested class,
// we consider that it might be uninitialized yet as some class initializers may call its methods or
// even instantiate objects of this class and call their methods
@@ -252,7 +252,7 @@ public final class JavaDfaValueFactory {
* @return a value that represents a constant created from variable; null if variable cannot be represented as a constant
*/
@Nullable
- private static DfaValue getConstantFromVariable(DfaValueFactory factory, PsiVariable variable) {
+ static DfaValue getConstantFromVariable(DfaValueFactory factory, PsiVariable variable) {
if (!variable.hasModifierProperty(PsiModifier.FINAL) || ignoreInitializer(variable)) return null;
Object value = variable.computeConstantValue();
PsiType type = variable.getType();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/PlainDescriptor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/PlainDescriptor.java
index c51b0ab73b8f..a0370d72b267 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/PlainDescriptor.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/PlainDescriptor.java
@@ -10,10 +10,7 @@ import com.intellij.codeInspection.dataFlow.JavaMethodContractUtil;
import com.intellij.codeInspection.dataFlow.NullabilityUtil;
import com.intellij.codeInspection.dataFlow.jvm.FieldChecker;
import com.intellij.codeInspection.dataFlow.types.DfTypes;
-import com.intellij.codeInspection.dataFlow.value.DfaValue;
-import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
-import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
-import com.intellij.codeInspection.dataFlow.value.VariableDescriptor;
+import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.psi.*;
import com.intellij.psi.util.*;
import com.intellij.util.JavaPsiConstructorUtil;
@@ -41,7 +38,7 @@ public final class PlainDescriptor extends PsiVarDescriptor {
@NotNull
@Override
public String toString() {
- return String.valueOf(myVariable.getName());
+ return PsiFormatUtil.formatVariable(myVariable, PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME, PsiSubstitutor.EMPTY);
}
@Override
@@ -75,6 +72,12 @@ public final class PlainDescriptor extends PsiVarDescriptor {
(myVariable instanceof PsiField && myVariable.hasModifierProperty(PsiModifier.STATIC))) {
return factory.getVarFactory().createVariableValue(this);
}
+ if (qualifier instanceof DfaTypeValue typeValue) {
+ PsiField field = typeValue.getDfType().getConstantOfType(PsiField.class);
+ if (field != null) {
+ qualifier = factory.getVarFactory().createVariableValue(new PlainDescriptor(field));
+ }
+ }
return super.createValue(factory, qualifier);
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/ThisDescriptor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/ThisDescriptor.java
index 2c2f6c352c72..4089f8eb2498 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/ThisDescriptor.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/ThisDescriptor.java
@@ -64,11 +64,6 @@ public final class ThisDescriptor extends PsiVarDescriptor {
return true;
}
- @Override
- public boolean isImplicitReadPossible() {
- return true;
- }
-
@Override
public int hashCode() {
return Objects.hashCode(myQualifier.getQualifiedName());
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/GetTernary.java b/java/java-tests/testData/inspection/dataFlow/fixture/GetTernary.java
new file mode 100644
index 000000000000..26e4c4991a0a
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/GetTernary.java
@@ -0,0 +1,26 @@
+import java.io.IOException;
+import java.io.InputStream;
+
+public class GetTernary {
+ static class Point {
+ int x, y;
+
+ Point(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+ }
+
+ void test(boolean b, Point p1, Point p2) {
+ int x = (b ? p1 : p2).x;
+ if (x == 1) {
+ if (b && p1.x == 1) {}
+ }
+ if (p1.x == 2 && p2.x == 2) {
+ int x1 = (b ? p1 : p2).x;
+ if (x1 == 2) {
+
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java
index 3665eb000e76..0f362ed9a8aa 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java
@@ -762,4 +762,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
public void testFieldAliasing() { doTest();}
public void testFieldLocalNoAliasing() { doTest();}
public void testIoContracts() { doTest(); }
+ public void testGetTernary() { doTest(); }
}
diff --git a/platform/analysis-impl/api-dump-unreviewed.txt b/platform/analysis-impl/api-dump-unreviewed.txt
index ab811f7d322a..e3698b66f914 100644
--- a/platform/analysis-impl/api-dump-unreviewed.txt
+++ b/platform/analysis-impl/api-dump-unreviewed.txt
@@ -1936,6 +1936,12 @@ c:com.intellij.codeInspection.dataFlow.lang.ir.FlushVariableInstruction
- accept(com.intellij.codeInspection.dataFlow.interpreter.DataFlowInterpreter,com.intellij.codeInspection.dataFlow.memory.DfaMemoryState):com.intellij.codeInspection.dataFlow.lang.ir.DfaInstructionState[]
- bindToFactory(com.intellij.codeInspection.dataFlow.value.DfaValueFactory):com.intellij.codeInspection.dataFlow.lang.ir.Instruction
- getVariable():com.intellij.codeInspection.dataFlow.value.DfaVariableValue
+c:com.intellij.codeInspection.dataFlow.lang.ir.GetQualifiedValueInstruction
+- com.intellij.codeInspection.dataFlow.lang.ir.EvalInstruction
+- (com.intellij.codeInspection.dataFlow.value.VariableDescriptor):V
+- (com.intellij.codeInspection.dataFlow.value.VariableDescriptor,com.intellij.codeInspection.dataFlow.lang.DfaAnchor):V
+- eval(com.intellij.codeInspection.dataFlow.value.DfaValueFactory,com.intellij.codeInspection.dataFlow.memory.DfaMemoryState,com.intellij.codeInspection.dataFlow.value.DfaValue[]):com.intellij.codeInspection.dataFlow.value.DfaValue
+- getRequiredDescriptors(com.intellij.codeInspection.dataFlow.value.DfaValueFactory):java.util.List
c:com.intellij.codeInspection.dataFlow.lang.ir.GotoInstruction
- com.intellij.codeInspection.dataFlow.lang.ir.Instruction
- (com.intellij.codeInspection.dataFlow.lang.ir.ControlFlow$ControlFlowOffset):V
@@ -1997,11 +2003,6 @@ c:com.intellij.codeInspection.dataFlow.lang.ir.SwapInstruction
- com.intellij.codeInspection.dataFlow.lang.ir.Instruction
- ():V
- accept(com.intellij.codeInspection.dataFlow.interpreter.DataFlowInterpreter,com.intellij.codeInspection.dataFlow.memory.DfaMemoryState):com.intellij.codeInspection.dataFlow.lang.ir.DfaInstructionState[]
-c:com.intellij.codeInspection.dataFlow.lang.ir.UnwrapDerivedVariableInstruction
-- com.intellij.codeInspection.dataFlow.lang.ir.EvalInstruction
-- (com.intellij.codeInspection.dataFlow.value.DerivedVariableDescriptor):V
-- eval(com.intellij.codeInspection.dataFlow.value.DfaValueFactory,com.intellij.codeInspection.dataFlow.memory.DfaMemoryState,com.intellij.codeInspection.dataFlow.value.DfaValue[]):com.intellij.codeInspection.dataFlow.value.DfaValue
-- getRequiredDescriptors(com.intellij.codeInspection.dataFlow.value.DfaValueFactory):java.util.List
c:com.intellij.codeInspection.dataFlow.lang.ir.WrapDerivedVariableInstruction
- com.intellij.codeInspection.dataFlow.lang.ir.EvalInstruction
- (com.intellij.codeInspection.dataFlow.types.DfType,com.intellij.codeInspection.dataFlow.value.DerivedVariableDescriptor):V
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/dataFlow/lang/ir/UnwrapDerivedVariableInstruction.java b/platform/analysis-impl/src/com/intellij/codeInspection/dataFlow/lang/ir/GetQualifiedValueInstruction.java
similarity index 58%
rename from platform/analysis-impl/src/com/intellij/codeInspection/dataFlow/lang/ir/UnwrapDerivedVariableInstruction.java
rename to platform/analysis-impl/src/com/intellij/codeInspection/dataFlow/lang/ir/GetQualifiedValueInstruction.java
index 208c9e324f62..7e6649f6515a 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/dataFlow/lang/ir/UnwrapDerivedVariableInstruction.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/dataFlow/lang/ir/GetQualifiedValueInstruction.java
@@ -1,38 +1,43 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInspection.dataFlow.lang.ir;
+import com.intellij.codeInspection.dataFlow.lang.DfaAnchor;
import com.intellij.codeInspection.dataFlow.memory.DfaMemoryState;
-import com.intellij.codeInspection.dataFlow.value.DerivedVariableDescriptor;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
import com.intellij.codeInspection.dataFlow.value.VariableDescriptor;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* Instruction to push a field qualified by the value on the stack
*/
-public class UnwrapDerivedVariableInstruction extends EvalInstruction {
- private final @NotNull DerivedVariableDescriptor myDerivedVariableDescriptor;
+public class GetQualifiedValueInstruction extends EvalInstruction {
+ private final @NotNull VariableDescriptor myDescriptor;
- public UnwrapDerivedVariableInstruction(@NotNull DerivedVariableDescriptor derivedVariable) {
- super(null, 1);
- myDerivedVariableDescriptor = derivedVariable;
+ public GetQualifiedValueInstruction(@NotNull VariableDescriptor descriptor) {
+ this(descriptor, null);
+ }
+
+ public GetQualifiedValueInstruction(@NotNull VariableDescriptor descriptor, @Nullable DfaAnchor anchor) {
+ super(anchor, 1);
+ myDescriptor = descriptor;
}
@Override
public @NotNull DfaValue eval(@NotNull DfaValueFactory factory, @NotNull DfaMemoryState state, @NotNull DfaValue @NotNull ... arguments) {
- return myDerivedVariableDescriptor.createValue(factory, arguments[0]);
+ return myDescriptor.createValue(factory, arguments[0]);
}
@Override
public List getRequiredDescriptors(@NotNull DfaValueFactory factory) {
- return List.of(myDerivedVariableDescriptor);
+ return List.of(myDescriptor);
}
@Override
public String toString() {
- return "UNWRAP " + myDerivedVariableDescriptor;
+ return "GET_FIELD " + myDescriptor;
}
}
diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtControlFlowBuilder.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtControlFlowBuilder.kt
index bc9adc458865..f6b2d8abcc6b 100644
--- a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtControlFlowBuilder.kt
+++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtControlFlowBuilder.kt
@@ -349,7 +349,8 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
if (typeReference != null) {
val castType = typeReference.type
if (castType.toDfType() is DfPrimitiveType) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.UNBOX))
+ addInstruction(
+ GetQualifiedValueInstruction(SpecialField.UNBOX))
}
}
}
@@ -515,9 +516,11 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
val leftConstraint = TypeConstraint.fromDfType(leftDfType)
val rightConstraint = TypeConstraint.fromDfType(rightDfType)
if (leftConstraint.isEnum && rightConstraint.isEnum && leftConstraint.meet(rightConstraint) != TypeConstraints.BOTTOM) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.ENUM_ORDINAL))
+ addInstruction(
+ GetQualifiedValueInstruction(SpecialField.ENUM_ORDINAL))
processExpression(right)
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.ENUM_ORDINAL))
+ addInstruction(
+ GetQualifiedValueInstruction(SpecialField.ENUM_ORDINAL))
addInstruction(BooleanBinaryInstruction(relation, forceEqualityByContent, KotlinExpressionAnchor(expr)))
} else if (leftConstraint.isExact(CommonClassNames.JAVA_LANG_STRING) &&
rightConstraint.isExact(CommonClassNames.JAVA_LANG_STRING)
@@ -854,7 +857,7 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
if (expression?.getKotlinType()?.canBeNull() == true) {
addInstruction(CheckNotNullInstruction(NullabilityProblemKind.unboxingNullable.problem(expression, null)!!,
trapTracker.maybeTransferValue("java.lang.NullPointerException")))
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.UNBOX))
+ addInstruction(GetQualifiedValueInstruction(SpecialField.UNBOX))
}
}
@@ -1357,7 +1360,8 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
if (!pushJavaClassField(receiver, selector, expr)) {
val specialField = (selector.mainReference?.resolveToSymbol() as? KaVariableSymbol)?.toSpecialField()
if (specialField != null) {
- addInstruction(UnwrapDerivedVariableInstruction(specialField))
+ addInstruction(
+ GetQualifiedValueInstruction(specialField))
if (expr is KtSafeQualifiedExpression) {
addInstruction(WrapDerivedVariableInstruction(expr.getKotlinType().toDfType(), SpecialField.UNBOX))
}
@@ -1571,7 +1575,8 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
if (name == "isEmpty" || name == "isNotEmpty") {
val callableId = target.callableId
if (callableId != null && callableId.packageName.asString() == "kotlin.collections") {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.COLLECTION_SIZE))
+ addInstruction(GetQualifiedValueInstruction(
+ SpecialField.COLLECTION_SIZE))
addInstruction(PushValueInstruction(DfTypes.intValue(0)))
addInstruction(
BooleanBinaryInstruction(
@@ -1817,7 +1822,7 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
addInstruction(PushValueInstruction(actualDfType))
}
if (actualDfType !is DfPrimitiveType && expectedDfType is DfPrimitiveType) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.UNBOX))
+ addInstruction(GetQualifiedValueInstruction(SpecialField.UNBOX))
} else if (expectedDfType !is DfPrimitiveType && actualDfType is DfPrimitiveType) {
val dfType = actualType.withNullability(KaTypeNullability.NULLABLE).toDfType().meet(DfTypes.NOT_NULL_OBJECT)
addInstruction(WrapDerivedVariableInstruction(expectedType.toDfType().meet(dfType), SpecialField.UNBOX))
diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/dfa/KtControlFlowBuilder.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/dfa/KtControlFlowBuilder.kt
index 74d12a34a3e4..060da85791af 100644
--- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/dfa/KtControlFlowBuilder.kt
+++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/dfa/KtControlFlowBuilder.kt
@@ -40,7 +40,6 @@ import org.jetbrains.kotlin.contracts.description.ContractProviderKey
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.resolve.analyze
-import org.jetbrains.kotlin.idea.caches.resolve.resolveMainReference
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.caches.resolve.safeAnalyzeNonSourceRootCode
import org.jetbrains.kotlin.idea.codeInsight.hints.RangeKtExpressionType.*
@@ -72,7 +71,6 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.*
-import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.concurrent.ConcurrentHashMap
class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpression) {
@@ -351,7 +349,9 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
if (typeReference != null) {
val castType = typeReference.getAbbreviatedTypeOrType(typeReference.safeAnalyzeNonSourceRootCode(BodyResolveMode.FULL))
if (castType.toDfType() is DfPrimitiveType) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.UNBOX))
+ addInstruction(
+ GetQualifiedValueInstruction(SpecialField.UNBOX)
+ )
}
}
}
@@ -390,7 +390,9 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
}
if (curType != null && KotlinBuiltIns.isArrayOrPrimitiveArray(curType)) {
if (indexType.canBeNull()) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.UNBOX))
+ addInstruction(
+ GetQualifiedValueInstruction(SpecialField.UNBOX)
+ )
}
val transfer = trapTracker.maybeTransferValue("kotlin.IndexOutOfBoundsException")
val elementType = expr.builtIns.getArrayElementType(curType)
@@ -407,7 +409,10 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
when {
KotlinBuiltIns.isString(kotlinType) -> {
if (indexType.canBeNull()) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.UNBOX))
+ addInstruction(
+ GetQualifiedValueInstruction(
+ SpecialField.UNBOX)
+ )
}
val transfer = trapTracker.maybeTransferValue("kotlin.IndexOutOfBoundsException")
addInstruction(EnsureIndexInBoundsInstruction(KotlinArrayIndexProblem(SpecialField.STRING_LENGTH, idx), transfer))
@@ -419,7 +424,10 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
}
isList(kotlinType) -> {
if (indexType.canBeNull()) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.UNBOX))
+ addInstruction(
+ GetQualifiedValueInstruction(
+ SpecialField.UNBOX)
+ )
}
val transfer = trapTracker.maybeTransferValue("kotlin.IndexOutOfBoundsException")
addInstruction(EnsureIndexInBoundsInstruction(KotlinArrayIndexProblem(SpecialField.COLLECTION_SIZE, idx), transfer))
@@ -632,7 +640,10 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
val containingPackage = if (containingDeclaration is PackageFragmentDescriptor) containingDeclaration.fqName
else (containingDeclaration as? ClassDescriptor)?.containingPackage()
if (containingPackage?.asString() == "kotlin.collections") {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.COLLECTION_SIZE))
+ addInstruction(
+ GetQualifiedValueInstruction(
+ SpecialField.COLLECTION_SIZE)
+ )
addInstruction(PushValueInstruction(DfTypes.intValue(0)))
addInstruction(
BooleanBinaryInstruction(
@@ -816,7 +827,7 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
if (!pushJavaClassField(receiver, selector, expr)) {
val specialField = findSpecialField(expr)
if (specialField != null) {
- addInstruction(UnwrapDerivedVariableInstruction(specialField))
+ addInstruction(GetQualifiedValueInstruction(specialField))
if (expr is KtSafeQualifiedExpression) {
addInstruction(WrapDerivedVariableInstruction(expr.getKotlinType().toDfType(), SpecialField.UNBOX))
}
@@ -1523,7 +1534,7 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
addInstruction(PushValueInstruction(actualDfType))
}
if (actualDfType !is DfPrimitiveType && expectedDfType is DfPrimitiveType) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.UNBOX))
+ addInstruction(GetQualifiedValueInstruction(SpecialField.UNBOX))
}
else if (expectedDfType !is DfPrimitiveType && actualDfType is DfPrimitiveType) {
val dfType = actualType.makeNullable().toDfType().meet(DfTypes.NOT_NULL_OBJECT)
@@ -1562,9 +1573,13 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
val leftConstraint = TypeConstraint.fromDfType(leftDfType)
val rightConstraint = TypeConstraint.fromDfType(rightDfType)
if (leftConstraint.isEnum && rightConstraint.isEnum && leftConstraint.meet(rightConstraint) != TypeConstraints.BOTTOM) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.ENUM_ORDINAL))
+ addInstruction(
+ GetQualifiedValueInstruction(SpecialField.ENUM_ORDINAL)
+ )
processExpression(right)
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.ENUM_ORDINAL))
+ addInstruction(
+ GetQualifiedValueInstruction(SpecialField.ENUM_ORDINAL)
+ )
addInstruction(BooleanBinaryInstruction(relation, forceEqualityByContent, KotlinExpressionAnchor(expr)))
} else if (leftConstraint.isExact(CommonClassNames.JAVA_LANG_STRING) &&
rightConstraint.isExact(CommonClassNames.JAVA_LANG_STRING)) {
@@ -1685,7 +1700,9 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
addImplicitConversion(dfVarType, balancedType)
addInstruction(BooleanBinaryInstruction(RelationType.EQ, true, KotlinWhenConditionAnchor(condition)))
} else if (exprType?.canBeNull() == true) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.UNBOX))
+ addInstruction(
+ GetQualifiedValueInstruction(SpecialField.UNBOX)
+ )
}
}
is KtWhenConditionIsPattern -> {
@@ -1736,7 +1753,7 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi
val condition = ifExpression.condition
processExpression(condition)
if (condition?.getKotlinType()?.canBeNull() == true) {
- addInstruction(UnwrapDerivedVariableInstruction(SpecialField.UNBOX))
+ addInstruction(GetQualifiedValueInstruction(SpecialField.UNBOX))
}
val skipThenOffset = DeferredOffset()
val thenStatement = ifExpression.then