[java-dfa] Basic support for Unmodifiable type annotation

GitOrigin-RevId: 4bc07e2533efa45356ba26b89c065b453a40d253
This commit is contained in:
Tagir Valeev
2024-09-18 20:27:35 +00:00
committed by intellij-monorepo-bot
parent ffd5d01482
commit 35c9c6ca5a
4 changed files with 34 additions and 1 deletions
@@ -404,6 +404,12 @@ public class MethodCallInstruction extends ExpressionPushingInstruction {
} else {
mutable = Mutability.getMutability(myTargetMethod);
}
if (type.hasAnnotation(Mutability.UNMODIFIABLE_ANNOTATION)) {
mutable = Mutability.UNMODIFIABLE;
}
else if (type.hasAnnotation(Mutability.UNMODIFIABLE_VIEW_ANNOTATION)) {
mutable = Mutability.UNMODIFIABLE_VIEW;
}
PsiType qualifierType = DfaPsiUtil.dfTypeToPsiType(factory.getProject(), state.getDfType(qualifierValue));
type = narrowReturnType(type, qualifierType, realMethod);
}
@@ -434,8 +434,15 @@ public final class DfTypes {
if (constraint.isSingleton() && nullability == Nullability.NOT_NULL) {
return new DfReferenceConstantType(constraint, constraint, false);
}
Mutability mutability = Mutability.UNKNOWN;
if (type.hasAnnotation(Mutability.UNMODIFIABLE_ANNOTATION)) {
mutability = Mutability.UNMODIFIABLE;
}
else if (type.hasAnnotation(Mutability.UNMODIFIABLE_VIEW_ANNOTATION)) {
mutability = Mutability.UNMODIFIABLE_VIEW;
}
return new DfGenericObjectType(Set.of(), constraint,
DfaNullability.fromNullability(nullability), Mutability.UNKNOWN, null, DfType.BOTTOM, false);
DfaNullability.fromNullability(nullability), mutability, null, DfType.BOTTOM, false);
}
/**
@@ -0,0 +1,16 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;
import java.util.Map;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class MethodReturnTypeUnmodifiableAnnotation {
void test() {
Collector<String, ?, @NotNull @Unmodifiable Map<@NotNull Integer, @NotNull String>> unmodifiableMap = Collectors.toUnmodifiableMap(Integer::parseInt, xx -> xx);
Stream.of("1", "2", "3").collect(unmodifiableMap).<warning descr="Immutable object is modified">put</warning>(1, "2");
var map = Stream.of("1", "2", "3").collect(unmodifiableMap);
map.<warning descr="Immutable object is modified">put</warning>(1, "3");
}
}
@@ -24,4 +24,8 @@ public class DataFlowInspection11Test extends DataFlowInspectionTestCase {
public void testAvoidWarningAtNotInferredType() { doTest();}
public void testSameArguments() { doTest(); }
public void testMethodReturnTypeUnmodifiableAnnotation() {
doTest();
}
}