disable for->foreach inspection if iterator is used in method reference qualifier (IDEA-136642)

This commit is contained in:
Anna Kozlova
2015-02-20 13:09:27 +01:00
parent 2eb4d637f0
commit 4b80f8009a
3 changed files with 56 additions and 45 deletions
@@ -178,14 +178,12 @@ public class ForCanBeForeachInspectionBase extends BaseInspection {
return visitor.isIndexVariableUsedOnlyAsIndex();
}
static boolean isCollectionLoopStatement(
PsiForStatement forStatement, boolean ignoreUntypedCollections) {
static boolean isCollectionLoopStatement(PsiForStatement forStatement, boolean ignoreUntypedCollections) {
final PsiStatement initialization = forStatement.getInitialization();
if (!(initialization instanceof PsiDeclarationStatement)) {
return false;
}
final PsiDeclarationStatement declaration =
(PsiDeclarationStatement)initialization;
final PsiDeclarationStatement declaration = (PsiDeclarationStatement)initialization;
final PsiElement[] declaredElements = declaration.getDeclaredElements();
if (declaredElements.length != 1) {
return false;
@@ -195,9 +193,7 @@ public class ForCanBeForeachInspectionBase extends BaseInspection {
return false;
}
final PsiVariable variable = (PsiVariable)declaredElement;
if (!TypeUtils.variableHasTypeOrSubtype(variable,
CommonClassNames.JAVA_UTIL_ITERATOR,
"java.util.ListIterator")) {
if (!TypeUtils.variableHasTypeOrSubtype(variable, CommonClassNames.JAVA_UTIL_ITERATOR, "java.util.ListIterator")) {
return false;
}
final PsiExpression initialValue = variable.getInitializer();
@@ -207,14 +203,10 @@ public class ForCanBeForeachInspectionBase extends BaseInspection {
if (!(initialValue instanceof PsiMethodCallExpression)) {
return false;
}
final PsiMethodCallExpression initialCall =
(PsiMethodCallExpression)initialValue;
final PsiReferenceExpression initialMethodExpression =
initialCall.getMethodExpression();
@NonNls final String initialCallName =
initialMethodExpression.getReferenceName();
if (!HardcodedMethodConstants.ITERATOR.equals(initialCallName) &&
!"listIterator".equals(initialCallName)) {
final PsiMethodCallExpression initialCall = (PsiMethodCallExpression)initialValue;
final PsiReferenceExpression initialMethodExpression = initialCall.getMethodExpression();
@NonNls final String initialCallName = initialMethodExpression.getReferenceName();
if (!HardcodedMethodConstants.ITERATOR.equals(initialCallName) && !"listIterator".equals(initialCallName)) {
return false;
}
final PsiExpressionList argumentList = initialCall.getArgumentList();
@@ -222,12 +214,10 @@ public class ForCanBeForeachInspectionBase extends BaseInspection {
if (arguments.length != 0) {
return false;
}
final PsiExpression qualifier =
initialMethodExpression.getQualifierExpression();
final PsiExpression qualifier = initialMethodExpression.getQualifierExpression();
final PsiClass qualifierClass;
if (qualifier == null) {
qualifierClass =
ClassUtils.getContainingClass(initialMethodExpression);
qualifierClass = ClassUtils.getContainingClass(initialMethodExpression);
if (ignoreUntypedCollections) {
final PsiClassType type = (PsiClassType)variable.getType();
final PsiType[] parameters = type.getParameters();
@@ -255,10 +245,8 @@ public class ForCanBeForeachInspectionBase extends BaseInspection {
if (qualifierClass == null) {
return false;
}
if (!InheritanceUtil.isInheritor(qualifierClass,
CommonClassNames.JAVA_LANG_ITERABLE) &&
!InheritanceUtil.isInheritor(qualifierClass,
CommonClassNames.JAVA_UTIL_COLLECTION)) {
if (!InheritanceUtil.isInheritor(qualifierClass, CommonClassNames.JAVA_LANG_ITERABLE) &&
!InheritanceUtil.isInheritor(qualifierClass, CommonClassNames.JAVA_UTIL_COLLECTION)) {
return false;
}
final PsiExpression condition = forStatement.getCondition();
@@ -289,16 +277,13 @@ public class ForCanBeForeachInspectionBase extends BaseInspection {
if (body == null) {
return 0;
}
final NumCallsToIteratorNextVisitor visitor =
new NumCallsToIteratorNextVisitor(iterator);
final NumCallsToIteratorNextVisitor visitor = new NumCallsToIteratorNextVisitor(iterator);
body.accept(visitor);
return visitor.getNumCallsToIteratorNext();
}
private static boolean isIteratorMethodCalled(PsiVariable iterator,
PsiStatement body) {
final IteratorMethodCallVisitor visitor =
new IteratorMethodCallVisitor(iterator);
private static boolean isIteratorMethodCalled(PsiVariable iterator, PsiStatement body) {
final IteratorMethodCallVisitor visitor = new IteratorMethodCallVisitor(iterator);
body.accept(visitor);
return visitor.isMethodCalled();
}
@@ -308,29 +293,25 @@ public class ForCanBeForeachInspectionBase extends BaseInspection {
if (!(condition instanceof PsiMethodCallExpression)) {
return false;
}
final PsiMethodCallExpression call =
(PsiMethodCallExpression)condition;
final PsiMethodCallExpression call = (PsiMethodCallExpression)condition;
final PsiExpressionList argumentList = call.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
if (arguments.length != 0) {
return false;
}
final PsiReferenceExpression methodExpression =
call.getMethodExpression();
final PsiReferenceExpression methodExpression = call.getMethodExpression();
final String methodName = methodExpression.getReferenceName();
if (!HardcodedMethodConstants.HAS_NEXT.equals(methodName)) {
return false;
}
final PsiExpression qualifier =
methodExpression.getQualifierExpression();
final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (qualifier == null) {
return true;
}
if (!(qualifier instanceof PsiReferenceExpression)) {
return false;
}
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression)qualifier;
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
final PsiElement target = referenceExpression.resolve();
return iterator.equals(target);
}
@@ -636,31 +617,39 @@ public class ForCanBeForeachInspectionBase extends BaseInspection {
}
@Override
public void visitMethodCallExpression(
@NotNull PsiMethodCallExpression expression) {
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
if (methodCalled) {
return;
}
super.visitMethodCallExpression(expression);
final PsiReferenceExpression methodExpression =
expression.getMethodExpression();
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
final String name = methodExpression.getReferenceName();
if (HardcodedMethodConstants.NEXT.equals(name)) {
return;
}
final PsiExpression qualifier =
methodExpression.getQualifierExpression();
final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (!(qualifier instanceof PsiReferenceExpression)) {
return;
}
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression)qualifier;
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
final PsiElement target = referenceExpression.resolve();
if (iterator.equals(target)) {
methodCalled = true;
}
}
@Override
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
if (methodCalled) {
return;
}
super.visitMethodReferenceExpression(expression);
final PsiExpression qualifierExpression = expression.getQualifierExpression();
if (qualifierExpression instanceof PsiReferenceExpression && iterator.equals(((PsiReferenceExpression)qualifierExpression).resolve())) {
methodCalled = true;
}
}
public boolean isMethodCalled() {
return methodCalled;
}
@@ -273,6 +273,20 @@ public class ForCanBeForEach {
}
}
}
static class WithMethodRefs {
private static final List<String> STRINGS = new ArrayList<>(Arrays.asList("Hello", "World"));
public void test3() {
for (ListIterator<String> stringListIterator = STRINGS.listIterator(); stringListIterator.hasNext(); ) {
System.out.println(stringListIterator.next());
List<String> strings2 = new ArrayList<>(Collections.singletonList("!"));
strings2.forEach(stringListIterator::add);
}
}
}
}
class OuterClass
{
@@ -1,7 +1,9 @@
package com.siyeh.ig.migration;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.testFramework.LightProjectDescriptor;
import com.siyeh.ig.LightInspectionTestCase;
import org.jetbrains.annotations.NotNull;
public class ForCanBeForeachInspectionTest extends LightInspectionTestCase {
@@ -18,4 +20,10 @@ public class ForCanBeForeachInspectionTest extends LightInspectionTestCase {
protected String getBasePath() {
return "/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach";
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JAVA_8;
}
}