[java-inspections] Java9CollectionFactoryInspection: copyOf: respect declared nullity of source collection

Fixes IDEA-349386 Don't suggest List/Set/Map.copyOf when elements are annotated @Nullable

GitOrigin-RevId: f2c1298394f204732437d304f68272f6cf406cc0
This commit is contained in:
Tagir Valeev
2024-08-29 18:27:57 +00:00
committed by intellij-monorepo-bot
parent 8e179a0a46
commit cd2be32f62
8 changed files with 72 additions and 6 deletions
@@ -6,6 +6,7 @@ import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.RemoveRedundantTypeArgumentsUtil;
import com.intellij.codeInspection.dataFlow.DfaPsiUtil;
import com.intellij.codeInspection.dataFlow.NullabilityUtil;
import com.intellij.codeInspection.options.OptPane;
import com.intellij.codeInspection.util.IntentionName;
@@ -202,6 +203,11 @@ public final class Java9CollectionFactoryInspection extends AbstractBaseJavaLoca
PsiType sourceType = arg.getType();
PsiType targetType = newExpression.getType();
if (targetType != null && sourceType != null && sourceType.isAssignableFrom(targetType)) {
PsiType keyType = PsiUtil.substituteTypeParameter(sourceType, JAVA_UTIL_MAP, 0, false);
PsiType valueType = PsiUtil.substituteTypeParameter(sourceType, JAVA_UTIL_MAP, 1, false);
if (DfaPsiUtil.getTypeNullability(keyType) == Nullability.NULLABLE || DfaPsiUtil.getTypeNullability(valueType) == Nullability.NULLABLE) {
return null;
}
return new PrepopulatedCollectionModel(Collections.singletonList(arg), Collections.emptyList(), "Map", true);
}
}
@@ -295,6 +301,10 @@ public final class Java9CollectionFactoryInspection extends AbstractBaseJavaLoca
if (arg != null &&
PsiUtil.getLanguageLevel(arg).isAtLeast(LanguageLevel.JDK_10) &&
InheritanceUtil.isInheritor(arg.getType(), JAVA_UTIL_COLLECTION)) {
PsiType elementType = PsiUtil.substituteTypeParameter(arg.getType(), JAVA_UTIL_COLLECTION, 0, false);
if (DfaPsiUtil.getTypeNullability(elementType) == Nullability.NULLABLE) {
return null;
}
return new PrepopulatedCollectionModel(Collections.singletonList(arg), Collections.emptyList(), type, true);
}
}
@@ -10,10 +10,10 @@ class Main {
Main(Collection<String> list, Map<? extends String, ? extends String> map,
Set<String> set) {
myList = List.<String>copyOf(list);
myList2 = List.<String>copyOf(set);
myMap = Map.<String, String>copyOf(map);
mySet = Set.<String>copyOf(set);
mySet2 = Set.<String>copyOf(list);
myList = List.copyOf(list);
myList2 = List.copyOf(set);
myMap = Map.copyOf(map);
mySet = Set.copyOf(set);
mySet2 = Set.copyOf(list);
}
}
@@ -0,0 +1,10 @@
// "Replace with 'Map.copyOf()' call" "true"
import org.jetbrains.annotations.*;
import java.util.*;
class Scratch {
public static void main(HashMap<String, String> data) {
Map<String, String> map = Map.copyOf(data);
System.out.println(map);
}
}
@@ -0,0 +1,10 @@
// "Replace with 'Map.copyOf()' call" "true"
import org.jetbrains.annotations.*;
import java.util.*;
class Scratch {
public static void main(HashMap<String, String> data) {
Map<String, String> map = Collections.<caret>unmodifiableMap(new HashMap<>(data));
System.out.println(map);
}
}
@@ -0,0 +1,16 @@
// "Replace with 'List.copyOf()' call" "false"
import org.jetbrains.annotations.*;
import java.util.*;
class Scratch {
public static void main(String[] args) {
var data = new ArrayList<@Nullable String>();
data.add("foo");
data.add("bar");
data.add(null);
var list = Collections.<caret>unmodifiableList(new ArrayList<>(data));
System.out.println(list);
}
}
@@ -0,0 +1,10 @@
// "Replace with 'Map.copyOf()' call" "false"
import org.jetbrains.annotations.*;
import java.util.*;
class Scratch {
public static void main(HashMap<@Nullable String, String> data) {
var map = Collections.<caret>unmodifiableMap(new HashMap<>(data));
System.out.println(map);
}
}
@@ -0,0 +1,10 @@
// "Replace with 'Map.copyOf()' call" "false"
import org.jetbrains.annotations.*;
import java.util.*;
class Scratch {
public static void main(HashMap<String, @Nullable String> data) {
var map = Collections.<caret>unmodifiableMap(new HashMap<>(data));
System.out.println(map);
}
}
@@ -36,7 +36,7 @@ public class Java9CollectionFactoryInspectionTest extends LightQuickFixParameter
@Override
protected Sdk getProjectJDK() {
return IdeaTestUtil.getMockJdk9();
return IdeaTestUtil.getMockJdk11();
}
@Override