mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-dfa] GetQualifiedValueInstruction (part of IDEA-361818)
GitOrigin-RevId: d8a75de6784cae450640720a89271f88c9c46cb6
This commit is contained in:
committed by
intellij-monorepo-bot
parent
bace4cfa96
commit
9a5250258f
+1
-1
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+36
-9
@@ -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) {
|
||||
|
||||
+6
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -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();
|
||||
|
||||
+8
-5
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
-5
@@ -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());
|
||||
|
||||
@@ -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 && <warning descr="Condition 'p1.x == 1' is always 'true' when reached">p1.x == 1</warning>) {}
|
||||
}
|
||||
if (p1.x == 2 && p2.x == 2) {
|
||||
int x1 = (b ? p1 : p2).x;
|
||||
if (<warning descr="Condition 'x1 == 2' is always 'true'">x1 == 2</warning>) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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(); }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
- <init>(com.intellij.codeInspection.dataFlow.value.VariableDescriptor):V
|
||||
- <init>(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
|
||||
- <init>(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
|
||||
- <init>():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
|
||||
- <init>(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
|
||||
- <init>(com.intellij.codeInspection.dataFlow.types.DfType,com.intellij.codeInspection.dataFlow.value.DerivedVariableDescriptor):V
|
||||
|
||||
+14
-9
@@ -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<VariableDescriptor> getRequiredDescriptors(@NotNull DfaValueFactory factory) {
|
||||
return List.of(myDerivedVariableDescriptor);
|
||||
return List.of(myDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UNWRAP " + myDerivedVariableDescriptor;
|
||||
return "GET_FIELD " + myDescriptor;
|
||||
}
|
||||
}
|
||||
+12
-7
@@ -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))
|
||||
|
||||
+30
-13
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user