mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-dfa] Better support for array component nullability
GitOrigin-RevId: 6536838ee1349aae389da59b7b4c878616309b20
This commit is contained in:
committed by
intellij-monorepo-bot
parent
fa62fec763
commit
e85a88956e
+2
-1
@@ -1,4 +1,4 @@
|
||||
// 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.
|
||||
// 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.java.inst;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.TypeConstraint;
|
||||
@@ -57,6 +57,7 @@ public class ArrayAccessInstruction extends ExpressionPushingInstruction {
|
||||
}
|
||||
else {
|
||||
DfType type = TypeConstraint.fromDfType(stateBefore.getDfType(array)).getArrayComponentType();
|
||||
type = type.meet(ArrayElementDescriptor.getArrayComponentType(array));
|
||||
result = type == DfType.BOTTOM ? interpreter.getFactory().getUnknown() : interpreter.getFactory().fromDfType(type);
|
||||
}
|
||||
if (!(result instanceof DfaVariableValue) && array instanceof DfaVariableValue) {
|
||||
|
||||
+28
-8
@@ -7,10 +7,7 @@ import com.intellij.codeInspection.dataFlow.java.JavaDfaValueFactory;
|
||||
import com.intellij.codeInspection.dataFlow.jvm.SpecialField;
|
||||
import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet;
|
||||
import com.intellij.codeInspection.dataFlow.types.*;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaTypeValue;
|
||||
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.*;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
@@ -46,13 +43,22 @@ public final class ArrayElementDescriptor extends JvmVariableDescriptor {
|
||||
DfaVariableValue qualifier = thisValue.getQualifier();
|
||||
DfType dfType = getDfType(qualifier);
|
||||
if (qualifier != null && dfType instanceof DfReferenceType) {
|
||||
PsiVarDescriptor descriptor = ObjectUtils.tryCast(qualifier.getDescriptor(), PsiVarDescriptor.class);
|
||||
VariableDescriptor qualDescriptor = qualifier.getDescriptor();
|
||||
int depth = 1;
|
||||
while (qualDescriptor instanceof ArrayElementDescriptor) {
|
||||
depth++;
|
||||
qualifier = qualifier.getQualifier();
|
||||
if (qualifier == null) break;
|
||||
qualDescriptor = qualifier.getDescriptor();
|
||||
}
|
||||
PsiVarDescriptor descriptor = ObjectUtils.tryCast(qualDescriptor, PsiVarDescriptor.class);
|
||||
if (descriptor != null) {
|
||||
PsiType psiType = descriptor.getType(qualifier);
|
||||
if (psiType instanceof PsiArrayType) {
|
||||
PsiType componentType = ((PsiArrayType)psiType).getComponentType();
|
||||
return dfType.meet(DfaNullability.fromNullability(DfaPsiUtil.getTypeNullability(componentType)).asDfType());
|
||||
for (int i = 0; i < depth; i++) {
|
||||
if (!(psiType instanceof PsiArrayType arrayType)) return dfType;
|
||||
psiType = arrayType.getComponentType();
|
||||
}
|
||||
return dfType.meet(DfaNullability.fromNullability(DfaPsiUtil.getTypeNullability(psiType)).asDfType());
|
||||
}
|
||||
}
|
||||
return dfType;
|
||||
@@ -179,4 +185,18 @@ public final class ArrayElementDescriptor extends JvmVariableDescriptor {
|
||||
}
|
||||
return DfaUtil.boxUnbox(factory.fromDfType(dfType), targetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array array value
|
||||
* @return inherent type of array component
|
||||
*/
|
||||
public static @NotNull DfType getArrayComponentType(@NotNull DfaValue array) {
|
||||
DfType componentType = TypeConstraint.fromDfType(array.getDfType()).getArrayComponentType();
|
||||
if (componentType instanceof DfReferenceType &&
|
||||
array instanceof DfaVariableValue var && var.getDescriptor() instanceof PsiVarDescriptor varDescriptor &&
|
||||
varDescriptor.getType(var.getQualifier()) instanceof PsiArrayType arrayType) {
|
||||
return componentType.meet(DfaNullability.fromNullability(DfaPsiUtil.getTypeNullability(arrayType.getComponentType())).asDfType());
|
||||
}
|
||||
return componentType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,4 +39,20 @@ class TestCompilerWarnings {
|
||||
}
|
||||
}
|
||||
|
||||
void multidim(@Nullable String @NotNull[] @NotNull[] a1,
|
||||
@NotNull String @NotNull[] @Nullable[] a2,
|
||||
@NotNull String @Nullable [] @NotNull[] a3) {
|
||||
System.out.println(a1[0][0].<warning descr="Method invocation 'length' may produce 'NullPointerException'">length</warning>());
|
||||
System.out.println(<warning descr="Array access 'a2[0][0]' may produce 'NullPointerException'">a2[0][0]</warning>.length());
|
||||
System.out.println(<warning descr="Array access 'a3[0]' may produce 'NullPointerException'">a3[0]</warning>[0].length());
|
||||
}
|
||||
|
||||
void multidimParam(@Nullable String @NotNull[] @NotNull[] a1,
|
||||
@NotNull String @NotNull[] @Nullable[] a2,
|
||||
@NotNull String @Nullable [] @NotNull[] a3,
|
||||
int i) {
|
||||
System.out.println(a1[i][i].length()); // Should warn here as well but not supported yet
|
||||
System.out.println(<warning descr="Array access 'a2[i][i]' may produce 'NullPointerException'">a2[i][i]</warning>.length());
|
||||
System.out.println(<warning descr="Array access 'a3[i]' may produce 'NullPointerException'">a3[i]</warning>[i].length());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user