mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-05-06 13:20:53 +07:00
RedundantUnmodifiableInspection created: IDEA-202309
GitOrigin-RevId: d5a5e1f45ba0f6e0af786ca588caaa192cd4b554
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a89e02f7f0
commit
6fbd744430
@@ -1389,6 +1389,12 @@
|
||||
bundle="messages.JavaBundle"
|
||||
key="inspection.redundant.file.creation.display.name"
|
||||
implementationClass="com.intellij.codeInspection.RedundantFileCreationInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="RedundantUnmodifiable"
|
||||
groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.verbose.or.redundant.code.constructs" enabledByDefault="true" level="WARNING"
|
||||
bundle="messages.JavaBundle"
|
||||
key="inspection.redundant.unmodifiable.call.description"
|
||||
implementationClass="com.intellij.codeInspection.RedundantUnmodifiableInspection"/>
|
||||
<localInspection groupPathKey="group.path.names.java.language.level.specific.issues.and.migration.aids" language="JAVA" shortName="TextBlockMigration"
|
||||
groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.language.level.specific.issues.and.migration.aids15" enabledByDefault="true" level="WARNING"
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 2000-2020 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.
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.CommonDataflow;
|
||||
import com.intellij.codeInspection.dataFlow.Mutability;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfType;
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_UTIL_COLLECTIONS;
|
||||
import static com.siyeh.ig.callMatcher.CallMatcher.anyOf;
|
||||
import static com.siyeh.ig.callMatcher.CallMatcher.staticCall;
|
||||
|
||||
public class RedundantUnmodifiableInspection extends AbstractBaseJavaLocalInspectionTool {
|
||||
private static final CallMatcher COLLECTIONS_UNMODIFIABLE_COLLECTION =
|
||||
staticCall(JAVA_UTIL_COLLECTIONS, "unmodifiableCollection").parameterCount(1);
|
||||
private static final CallMatcher COLLECTIONS_UNMODIFIABLE_LIST =
|
||||
staticCall(JAVA_UTIL_COLLECTIONS, "unmodifiableList").parameterCount(1);
|
||||
private static final CallMatcher COLLECTIONS_UNMODIFIABLE_SET =
|
||||
staticCall(JAVA_UTIL_COLLECTIONS, "unmodifiableSet").parameterCount(1);
|
||||
private static final CallMatcher COLLECTIONS_UNMODIFIABLE_MAP =
|
||||
staticCall(JAVA_UTIL_COLLECTIONS, "unmodifiableMap").parameterCount(1);
|
||||
|
||||
private static final CallMatcher COLLECTIONS_UNMODIFIABLE_SORTED_SET =
|
||||
staticCall(JAVA_UTIL_COLLECTIONS, "unmodifiableSortedSet").parameterCount(1);
|
||||
private static final CallMatcher COLLECTIONS_UNMODIFIABLE_SORTED_MAP =
|
||||
staticCall(JAVA_UTIL_COLLECTIONS, "unmodifiableSortedMap").parameterCount(1);
|
||||
|
||||
private static final CallMatcher COLLECTIONS_UNMODIFIABLE_NAVIGABLE_MAP =
|
||||
staticCall(JAVA_UTIL_COLLECTIONS, "unmodifiableNavigableMap").parameterCount(1);
|
||||
private static final CallMatcher COLLECTIONS_UNMODIFIABLE_NAVIGABLE_SET =
|
||||
staticCall(JAVA_UTIL_COLLECTIONS, "unmodifiableNavigableSet").parameterCount(1);
|
||||
|
||||
private static final CallMatcher COLLECTIONS_UNMODIFIABLE =
|
||||
anyOf(COLLECTIONS_UNMODIFIABLE_COLLECTION, COLLECTIONS_UNMODIFIABLE_SET,
|
||||
COLLECTIONS_UNMODIFIABLE_MAP, COLLECTIONS_UNMODIFIABLE_LIST,
|
||||
COLLECTIONS_UNMODIFIABLE_SORTED_SET, COLLECTIONS_UNMODIFIABLE_SORTED_MAP,
|
||||
COLLECTIONS_UNMODIFIABLE_NAVIGABLE_MAP, COLLECTIONS_UNMODIFIABLE_NAVIGABLE_SET);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
|
||||
return new JavaElementVisitor() {
|
||||
|
||||
@Override
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression call) {
|
||||
super.visitMethodCallExpression(call);
|
||||
|
||||
if (COLLECTIONS_UNMODIFIABLE.test(call)) {
|
||||
PsiExpression arg = ArrayUtil.getFirstElement(call.getArgumentList().getExpressions());
|
||||
if (arg == null) return;
|
||||
|
||||
DfType dfType = CommonDataflow.getDfType(arg);
|
||||
if (!Mutability.fromDfType(dfType).isUnmodifiable()) return;
|
||||
|
||||
String methodName = call.getMethodExpression().getReferenceName();
|
||||
if (methodName == null) return;
|
||||
|
||||
holder.registerProblem(call,
|
||||
JavaBundle.message("inspection.redundant.unmodifiable.call.display.name", methodName),
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||
new TextRange(0, call.getArgumentList().getStartOffsetInParent()),
|
||||
new UnwrapUnmodifiableFix());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class UnwrapUnmodifiableFix implements LocalQuickFix {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return JavaBundle.message("inspection.redundant.unmodifiable.call.replace.with.arg.quickfix");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
PsiMethodCallExpression call = ObjectUtils.tryCast(element, PsiMethodCallExpression.class);
|
||||
if (call == null) return;
|
||||
|
||||
final PsiExpressionList argList = call.getArgumentList();
|
||||
final PsiExpression[] args = argList.getExpressions();
|
||||
if (args.length != 1) return;
|
||||
|
||||
CommentTracker commentTracker = new CommentTracker();
|
||||
commentTracker.replaceAndRestoreComments(element, commentTracker.text(args[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports redundant calls to unmodifiable collection factories within the Collections class.
|
||||
If the argument that is passed to an unmodifiable collection factory is already immutable, such wrapping becomes pointless.
|
||||
<p>Example:</p>
|
||||
<pre>
|
||||
<code>Collections.unmodifiableList(Collections.singletonList("abc"));
|
||||
</code>
|
||||
</pre>
|
||||
In order to detect the methods that return unmodifiable collections, the inspection uses the <code>@Unmodifiable</code> annotation. Use this annotation if you want to extend the inspection to your own unmodifiable collection factories.
|
||||
<!-- tooltip end -->
|
||||
<p><small>New in 2020.3</small></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,35 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
getEmptyList();
|
||||
|
||||
getEmptyList();
|
||||
getEmptySet();
|
||||
getEmptyMap();
|
||||
|
||||
getEmptySet();
|
||||
getEmptyMap();
|
||||
|
||||
getEmptySet();
|
||||
getEmptyMap();
|
||||
}
|
||||
|
||||
static List getEmptyList() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
static Set getEmptySet() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
static Map getEmptyMap() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
List list = new ArrayList();
|
||||
list = Collections.emptyList();
|
||||
|
||||
Set set = new HashSet();
|
||||
set = Collections.emptySet();
|
||||
|
||||
Map map = new HashMap();
|
||||
map = Collections.emptyMap();
|
||||
|
||||
list;
|
||||
|
||||
list;
|
||||
set;
|
||||
map;
|
||||
|
||||
set;
|
||||
map;
|
||||
|
||||
set;
|
||||
map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Collections.EMPTY_LIST;
|
||||
|
||||
Collections.EMPTY_LIST;
|
||||
Collections.EMPTY_SET;
|
||||
Collections.EMPTY_MAP;
|
||||
|
||||
Collections.EMPTY_SET;
|
||||
Collections.EMPTY_MAP;
|
||||
|
||||
Collections.EMPTY_SET;
|
||||
Collections.EMPTY_MAP;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Collections.emptyList();
|
||||
|
||||
Collections.emptyList();
|
||||
Collections.emptySet();
|
||||
Collections.emptyMap();
|
||||
|
||||
Collections.emptySet();
|
||||
Collections.emptyMap();
|
||||
|
||||
Collections.emptySet();
|
||||
Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
/*empty*/
|
||||
/*empty too*/
|
||||
/*blah blah blah*/
|
||||
Collections.emptyList();
|
||||
|
||||
/*empty*/
|
||||
/*empty too*/
|
||||
/*blah blah blah*/
|
||||
Collections.emptyList();
|
||||
/*empty*/
|
||||
/*empty too*/
|
||||
/*blah blah blah*/
|
||||
Collections.emptySet();
|
||||
/*empty*/
|
||||
/*empty too*/
|
||||
/*blah blah blah*/
|
||||
Collections.emptyMap();
|
||||
|
||||
/*empty*/
|
||||
/*empty too*/
|
||||
/*blah blah blah*/
|
||||
Collections.emptySet();
|
||||
/*empty*/
|
||||
/*empty too*/
|
||||
/*blah blah blah*/
|
||||
Collections.emptyMap();
|
||||
|
||||
/*empty*/
|
||||
/*empty too*/
|
||||
/*blah blah blah*/
|
||||
Collections.emptySet();
|
||||
/*empty*/
|
||||
/*empty too*/
|
||||
/*blah blah blah*/
|
||||
Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
((Collections.emptyList()));
|
||||
|
||||
((Collections.emptyList()));
|
||||
((Collections.emptySet()));
|
||||
((Collections.emptyMap()));
|
||||
|
||||
((Collections.emptySet()));
|
||||
((Collections.emptyMap()));
|
||||
|
||||
((Collections.emptySet()));
|
||||
((Collections.emptyMap()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Collections.unmodifiableCollecti<caret>on(getEmptyList());
|
||||
|
||||
Collections.unmodifiableList(getEmptyList());
|
||||
Collections.unmodifiableSet(getEmptySet());
|
||||
Collections.unmodifiableMap(getEmptyMap());
|
||||
|
||||
Collections.unmodifiableSortedSet(getEmptySet());
|
||||
Collections.unmodifiableSortedMap(getEmptyMap());
|
||||
|
||||
Collections.unmodifiableNavigableSet(getEmptySet());
|
||||
Collections.unmodifiableNavigableMap(getEmptyMap());
|
||||
}
|
||||
|
||||
static List getEmptyList() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
static Set getEmptySet() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
static Map getEmptyMap() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
List list = new ArrayList();
|
||||
list = Collections.emptyList();
|
||||
|
||||
Set set = new HashSet();
|
||||
set = Collections.emptySet();
|
||||
|
||||
Map map = new HashMap();
|
||||
map = Collections.emptyMap();
|
||||
|
||||
Collections.unmodifiableCollecti<caret>on(list);
|
||||
|
||||
Collections.unmodifiableList(list);
|
||||
Collections.unmodifiableSet(set);
|
||||
Collections.unmodifiableMap(map);
|
||||
|
||||
Collections.unmodifiableSortedSet(set);
|
||||
Collections.unmodifiableSortedMap(map);
|
||||
|
||||
Collections.unmodifiableNavigableSet(set);
|
||||
Collections.unmodifiableNavigableMap(map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Collections.unmodifiableCollecti<caret>on(Collections.EMPTY_LIST);
|
||||
|
||||
Collections.unmodifiableList(Collections.EMPTY_LIST);
|
||||
Collections.unmodifiableSet(Collections.EMPTY_SET);
|
||||
Collections.unmodifiableMap(Collections.EMPTY_MAP);
|
||||
|
||||
Collections.unmodifiableSortedSet(Collections.EMPTY_SET);
|
||||
Collections.unmodifiableSortedMap(Collections.EMPTY_MAP);
|
||||
|
||||
Collections.unmodifiableNavigableSet(Collections.EMPTY_SET);
|
||||
Collections.unmodifiableNavigableMap(Collections.EMPTY_MAP);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Collections.unmodifiableCollecti<caret>on(Collections.emptyList());
|
||||
|
||||
Collections.unmodifiableList(Collections.emptyList());
|
||||
Collections.unmodifiableSet(Collections.emptySet());
|
||||
Collections.unmodifiableMap(Collections.emptyMap());
|
||||
|
||||
Collections.unmodifiableSortedSet(Collections.emptySet());
|
||||
Collections.unmodifiableSortedMap(Collections.emptyMap());
|
||||
|
||||
Collections.unmodifiableNavigableSet(Collections.emptySet());
|
||||
Collections.unmodifiableNavigableMap(Collections.emptyMap());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Collections/*empty*/./*empty too*/unmodifiableCollecti<caret>on/*blah blah blah*/(Collections.emptyList());
|
||||
|
||||
Collections/*empty*/./*empty too*/unmodifiableList/*blah blah blah*/(Collections.emptyList());
|
||||
Collections/*empty*/./*empty too*/unmodifiableSet/*blah blah blah*/(Collections.emptySet());
|
||||
Collections/*empty*/./*empty too*/unmodifiableMap/*blah blah blah*/(Collections.emptyMap());
|
||||
|
||||
Collections/*empty*/./*empty too*/unmodifiableSortedSet/*blah blah blah*/(Collections.emptySet());
|
||||
Collections/*empty*/./*empty too*/unmodifiableSortedMap/*blah blah blah*/(Collections.emptyMap());
|
||||
|
||||
Collections/*empty*/./*empty too*/unmodifiableNavigableSet/*blah blah blah*/(Collections.emptySet());
|
||||
Collections/*empty*/./*empty too*/unmodifiableNavigableMap/*blah blah blah*/(Collections.emptyMap());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// "Fix all 'Redundant usage of unmodifiable collection factories' problems in file" "true"
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Collections.unmodifiableCollecti<caret>on(((Collections.emptyList())));
|
||||
|
||||
Collections.unmodifiableList(((Collections.emptyList())));
|
||||
Collections.unmodifiableSet(((Collections.emptySet())));
|
||||
Collections.unmodifiableMap(((Collections.emptyMap())));
|
||||
|
||||
Collections.unmodifiableSortedSet(((Collections.emptySet())));
|
||||
Collections.unmodifiableSortedMap(((Collections.emptyMap())));
|
||||
|
||||
Collections.unmodifiableNavigableSet(((Collections.emptySet())));
|
||||
Collections.unmodifiableNavigableMap(((Collections.emptyMap())));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2000-2020 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.
|
||||
package com.intellij.java.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.RedundantUnmodifiableInspection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class RedundantUnmodifiableInspectionTest extends LightQuickFixParameterizedTestCase {
|
||||
@Override
|
||||
protected LocalInspectionTool @NotNull [] configureLocalInspectionTools() {
|
||||
return new LocalInspectionTool[]{
|
||||
new RedundantUnmodifiableInspection()
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/redundantUnmodifiable";
|
||||
}
|
||||
}
|
||||
@@ -1551,3 +1551,6 @@ postfix.template.condition.boolean.name=boolean
|
||||
postfix.template.condition.number.name=number
|
||||
postfix.template.condition.not.primitive.type.name=not primitive type
|
||||
postfix.template.condition.array.name=array
|
||||
inspection.redundant.unmodifiable.call.display.name=Redundant usage of the ''{0}'' factory
|
||||
inspection.redundant.unmodifiable.call.description=Redundant usage of unmodifiable collection factories
|
||||
inspection.redundant.unmodifiable.call.replace.with.arg.quickfix=Unwrap argument
|
||||
|
||||
Reference in New Issue
Block a user