diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedCollectionQueryUpdateInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedCollectionQueryUpdateInspectionBase.java index 147117c186f9..69304714820a 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedCollectionQueryUpdateInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedCollectionQueryUpdateInspectionBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,10 @@ package com.siyeh.ig.bugs; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.Processor; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; @@ -236,7 +238,7 @@ public class MismatchedCollectionQueryUpdateInspectionBase extends BaseInspectio } private boolean collectionContentsAreUpdated(PsiVariable variable, PsiElement context) { - if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, UPDATE_EXCLUDES, context) || + if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, context, new UpdateCallProcessor()) || collectionUpdateCalled(variable, context)) { return true; } @@ -262,7 +264,7 @@ public class MismatchedCollectionQueryUpdateInspectionBase extends BaseInspectio } private boolean collectionContentsAreQueried(PsiVariable variable, PsiElement context) { - if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, QUERY_EXCLUDES, context) || + if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, context, new QueryCallProcessor()) || collectionQueryCalled(variable, context)) { return true; } @@ -285,4 +287,31 @@ public class MismatchedCollectionQueryUpdateInspectionBase extends BaseInspectio return visitor.isQueriedUpdated(); } } + + private static class QueryCallProcessor implements Processor { + @Override + public boolean process(PsiCall call) { + final PsiMethod method = call.resolveMethod(); + if (method == null) { + return false; + } + final PsiClass aClass = method.getContainingClass(); + return aClass != null && QUERY_EXCLUDES.contains(aClass.getQualifiedName()); + } + } + + private static class UpdateCallProcessor implements Processor { + @Override + public boolean process(PsiCall call) { + final PsiMethod method = call.resolveMethod(); + if (method == null) { + return false; + } + final PsiClass aClass = method.getContainingClass(); + if (aClass == null || !UPDATE_EXCLUDES.contains(aClass.getQualifiedName())) { + return false; + } + return !"drainTo".equals(method.getName()) || !InheritanceUtil.isInheritor(aClass, "java.util.concurrent.BlockingQueue"); + } + } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/StringBufferReplaceableByStringBuilderInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/StringBufferReplaceableByStringBuilderInspection.java index 1cc071352c8e..a1e002d5a987 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/StringBufferReplaceableByStringBuilderInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/StringBufferReplaceableByStringBuilderInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; @@ -205,10 +206,20 @@ public class StringBufferReplaceableByStringBuilderInspection extends BaseInspec if (VariableAccessUtils.variableIsReturned(variable, context, true)) { return false; } - if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, excludes, context, true)) { + if (VariableAccessUtils.variableIsUsedInInnerClass(variable, context)) { return false; } - if (VariableAccessUtils.variableIsUsedInInnerClass(variable, context)) { + if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, context, true, new Processor() { + @Override + public boolean process(PsiCall call) { + final PsiMethod method = call.resolveMethod(); + if (method == null) { + return false; + } + final PsiClass aClass = method.getContainingClass(); + return aClass != null && excludes.contains(aClass.getQualifiedName()); + } + })) { return false; } return true; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java index f42509bc060d..03bf5937d44f 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java @@ -17,6 +17,7 @@ package com.siyeh.ig.psiutils; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; +import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,16 +52,18 @@ public class VariableAccessUtils { return visitor.isPassed(); } - public static boolean variableIsPassedAsMethodArgument(@NotNull PsiVariable variable, Set excludes, @Nullable PsiElement context) { - return variableIsPassedAsMethodArgument(variable, excludes, context, false); + public static boolean variableIsPassedAsMethodArgument(@NotNull PsiVariable variable, @Nullable PsiElement context, + Processor callProcessor) { + return variableIsPassedAsMethodArgument(variable, context, false, callProcessor); } - public static boolean variableIsPassedAsMethodArgument(@NotNull PsiVariable variable, Set excludes, - @Nullable PsiElement context, boolean builderPattern) { + public static boolean variableIsPassedAsMethodArgument(@NotNull PsiVariable variable, @Nullable PsiElement context, + boolean builderPattern, Processor callProcessor) { if (context == null) { return false; } - final VariablePassedAsArgumentExcludedVisitor visitor = new VariablePassedAsArgumentExcludedVisitor(variable, excludes, builderPattern); + final VariablePassedAsArgumentExcludedVisitor visitor = + new VariablePassedAsArgumentExcludedVisitor(variable, builderPattern, callProcessor); context.accept(visitor); return visitor.isPassed(); } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java index f7778e0a89bc..61e84b686cb1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,22 +16,22 @@ package com.siyeh.ig.psiutils; import com.intellij.psi.*; +import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; -import java.util.Set; - class VariablePassedAsArgumentExcludedVisitor extends JavaRecursiveElementVisitor { @NotNull private final PsiVariable variable; - private final Set excludes; + private final Processor myCallProcessor; private final boolean myBuilderPattern; private boolean passed = false; - public VariablePassedAsArgumentExcludedVisitor(@NotNull PsiVariable variable, @NotNull Set excludes, boolean builderPattern) { + public VariablePassedAsArgumentExcludedVisitor(@NotNull PsiVariable variable, boolean builderPattern, + @NotNull Processor callProcessor) { this.variable = variable; - this.excludes = excludes; + myCallProcessor = callProcessor; myBuilderPattern = builderPattern; } @@ -70,17 +70,10 @@ class VariablePassedAsArgumentExcludedVisitor extends JavaRecursiveElementVisito if (!VariableAccessUtils.mayEvaluateToVariable(argument, variable, myBuilderPattern)) { continue; } - final PsiMethod method = call.resolveMethod(); - if (method != null) { - final PsiClass aClass = method.getContainingClass(); - if (aClass != null) { - final String name = aClass.getQualifiedName(); - if (excludes.contains(name)) { - continue; - } - } + if (!myCallProcessor.process(call)) { + passed = true; + break; } - passed = true; } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java index eede6c60116b..31ec6280cf77 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java @@ -2,6 +2,7 @@ package com.siyeh.igtest.bugs.mismatched_collection_query_update; import java.util.*; import java.io.FileInputStream; +import java.util.concurrent.BlockingQueue; public class MismatchedCollectionQueryUpdate { private Set foo = new HashSet(); @@ -268,6 +269,15 @@ class CollectionsUser { interface Supplier { T get(); } + + void draining(BlockingQueue queue) { + List objects = new ArrayList<>(); + queue.drainTo(objects); + // ... + for (Object obj : objects) { + // ... + } + } } class SimpleAdd { diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MismatchedCollectionQueryUpdateInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MismatchedCollectionQueryUpdateInspectionTest.java index a79ebec4a97f..0663329deadd 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MismatchedCollectionQueryUpdateInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MismatchedCollectionQueryUpdateInspectionTest.java @@ -25,7 +25,11 @@ public class MismatchedCollectionQueryUpdateInspectionTest extends LightInspecti "package java.util.concurrent;" + "public class LinkedBlockingDeque implements BlockingDeque {}", "package java.lang;" + - "public class InterruptedException extends Exception {}" + "public class InterruptedException extends Exception {}", + "package java.util.concurrent;" + + "public interface BlockingQueue {" + + " int drainTo(java.util.Collection c);" + + "}" }; }