IDEA-75999 (False positive "MismatchedQueryAndUpdateOfCollection")

This commit is contained in:
Bas Leijdekkers
2011-11-09 15:18:09 +01:00
parent 1179dd8dc4
commit 57f32e911c
4 changed files with 120 additions and 23 deletions

View File

@@ -16,11 +16,11 @@
package com.siyeh.ig.bugs;
import com.intellij.psi.*;
import com.siyeh.ig.psiutils.CollectionUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.Set;
class CollectionUpdateCalledVisitor extends JavaRecursiveElementVisitor {
@@ -29,8 +29,7 @@ class CollectionUpdateCalledVisitor extends JavaRecursiveElementVisitor {
private boolean updated = false;
private final PsiVariable variable;
CollectionUpdateCalledVisitor(PsiVariable variable,
Set<String> updateNames) {
CollectionUpdateCalledVisitor(@Nullable PsiVariable variable, Set<String> updateNames) {
this.variable = variable;
this.updateNames = updateNames;
}
@@ -68,28 +67,15 @@ class CollectionUpdateCalledVisitor extends JavaRecursiveElementVisitor {
return;
}
}
final PsiExpression qualifier =
methodExpression.getQualifierExpression();
if (qualifier == null || qualifier instanceof PsiThisExpression) {
final PsiMethod method = call.resolveMethod();
if (method == null) {
return;
}
final PsiClass aClass = method.getContainingClass();
if (CollectionUtils.isCollectionClassOrInterface(aClass)) {
updated = true;
}
}
else {
checkQualifier(qualifier);
}
final PsiExpression qualifier = methodExpression.getQualifierExpression();
checkQualifier(qualifier);
}
private void checkQualifier(PsiExpression expression) {
if (updated) {
return;
}
if (expression instanceof PsiReferenceExpression) {
if (variable != null && expression instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression)expression;
final PsiElement referent = referenceExpression.resolve();
@@ -115,6 +101,11 @@ class CollectionUpdateCalledVisitor extends JavaRecursiveElementVisitor {
conditionalExpression.getElseExpression();
checkQualifier(elseExpression);
}
else if (variable == null) {
if (expression == null || expression instanceof PsiThisExpression || expression instanceof PsiSuperExpression) {
updated = true;
}
}
}
public boolean isUpdated() {

View File

@@ -32,6 +32,7 @@ import com.siyeh.ig.psiutils.VariableAccessUtils;
import com.siyeh.ig.ui.ExternalizableStringSet;
import com.siyeh.ig.ui.UiUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -215,7 +216,12 @@ public class MismatchedCollectionQueryUpdateInspection
final PsiNewExpression newExpression = (PsiNewExpression)initializer;
final PsiAnonymousClass anonymousClass = newExpression.getAnonymousClass();
if (anonymousClass != null) {
if (collectionUpdateCalled(variable, anonymousClass)) {
if (collectionUpdateCalled(null, anonymousClass)) {
return true;
}
final ThisPassedAsArgumentVisitor visitor = new ThisPassedAsArgumentVisitor();
anonymousClass.accept(visitor);
if (visitor.isPassed()) {
return true;
}
}
@@ -240,7 +246,7 @@ public class MismatchedCollectionQueryUpdateInspection
return visitor.isQueried();
}
private boolean collectionUpdateCalled(PsiVariable variable, PsiElement context) {
private boolean collectionUpdateCalled(@Nullable PsiVariable variable, PsiElement context) {
final CollectionUpdateCalledVisitor visitor = new CollectionUpdateCalledVisitor(variable, updateNames);
context.accept(visitor);
return visitor.isUpdated();

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2011 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.bugs;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
class ThisPassedAsArgumentVisitor extends JavaRecursiveElementVisitor {
private boolean passed = false;
public ThisPassedAsArgumentVisitor() {}
@Override
public void visitElement(@NotNull PsiElement element) {
if (!passed) {
super.visitElement(element);
}
}
@Override
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
if (passed) {
return;
}
super.visitMethodCallExpression(call);
final PsiExpressionList argumentList = call.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
for (PsiExpression argument : arguments) {
if (isThisExpression(argument)) {
passed = true;
break;
}
}
}
@Override
public void visitNewExpression(@NotNull PsiNewExpression newExpression) {
if (passed) {
return;
}
super.visitNewExpression(newExpression);
final PsiExpressionList argumentList = newExpression.getArgumentList();
if (argumentList == null) {
return;
}
final PsiExpression[] arguments = argumentList.getExpressions();
for (PsiExpression argument : arguments) {
if (isThisExpression(argument)) {
passed = true;
break;
}
}
}
private static boolean isThisExpression(PsiExpression expression) {
if (expression instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
return isThisExpression(parenthesizedExpression.getExpression());
}
return expression instanceof PsiThisExpression;
}
public boolean isPassed() {
return passed;
}
}

View File

@@ -129,7 +129,7 @@ public class MismatchedCollectionQueryUpdate {
return "not " + bar + "";
}
private Set foo = new HashSet();
public void foo()
{
@@ -146,4 +146,24 @@ public class MismatchedCollectionQueryUpdate {
}
}
class MyClass {
private List<String> ourValues = new ArrayList<String>() {{
Collections.addAll((this), "A", "B", "C");
}};
public void foo() {
for (final String value : ourValues) {}
}
}
class MyClass2 {
private List<String> ourValues = new ArrayList<String>() {{
(this).add("");
}};
public void foo() {
for (final String value : ourValues) {}
}
}
}