batch inspections: don't remove refs on parameter multiple times (IDEA-175665)

base RefManager#removeRefElement removes also references on children, thus processing parameters separately is redundant
This commit is contained in:
Anna.Kozlova
2017-07-13 18:24:00 +02:00
parent d32baa1e28
commit c853af26f3
5 changed files with 91 additions and 26 deletions
@@ -246,15 +246,7 @@ public class RefJavaManagerImpl extends RefJavaManager {
}
@Override
public void removeReference(@NotNull final RefElement refElement) {
if (refElement instanceof RefMethod) {
RefMethod refMethod = (RefMethod)refElement;
RefParameter[] params = refMethod.getParameters();
for (RefParameter param : params) {
myRefManager.removeReference(param);
}
}
}
public void removeReference(@NotNull final RefElement refElement) { }
@Override
@Nullable
@@ -490,11 +490,6 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
for (RefMethod subMethod : getDerivedMethods()) {
subMethod.getSuperMethods().remove(this);
}
ArrayList<RefElement> deletedRefs = new ArrayList<>();
for (RefParameter parameter : getParameters()) {
getRefManager().removeRefElement(parameter, deletedRefs);
}
}
@Override
@@ -54,6 +54,7 @@ import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -234,20 +235,43 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
@Override
protected boolean applyFix(@NotNull final RefEntity[] refElements) {
if (!super.applyFix(refElements)) return false;
final PsiElement[] psiElements = Arrays
.stream(refElements)
.filter((obj) -> obj instanceof RefJavaElement && getFilter().accepts((RefJavaElement)obj))
.map(e -> ((RefElement) e).getElement())
.filter(e -> e != null)
.toArray(PsiElement[]::new);
if (psiElements.length == 0) return false;
//filter only elements applicable to be deleted (exclude entry points)
RefElement[] filteredRefElements = Arrays.stream(refElements)
.filter(entry -> entry instanceof RefJavaElement && getFilter().accepts((RefJavaElement)entry))
.toArray(RefElement[]::new);
ApplicationManager.getApplication().invokeLater(() -> {
final Project project = getContext().getProject();
if (isDisposed() || project.isDisposed()) return;
SafeDeleteHandler.invoke(project, psiElements, false,
List<PsiElement> psiElements = new ArrayList<>();
Set<PsiClass> classes = new THashSet<>();
for (RefEntity obj : filteredRefElements) {
PsiElement e = ((RefElement)obj).getElement();
if (e != null) {
psiElements.add(e);
if (e instanceof PsiClass) {
classes.add((PsiClass)e);
}
}
}
if (psiElements.size() == 0) return;
//filter out elements inside classes to be deleted
PsiElement[] elements = psiElements.stream().filter(e -> {
if (e instanceof PsiMember) {
PsiClass containingClass = ((PsiMember)e).getContainingClass();
if (containingClass != null && classes.contains(containingClass)) {
return false;
}
}
return true;
}).toArray(PsiElement[]::new);
SafeDeleteHandler.invoke(project, elements, false,
() -> {
removeElements(refElements, project, myToolWrapper);
for (RefEntity ref : refElements) {
removeElements(filteredRefElements, project, myToolWrapper);
for (RefEntity ref : filteredRefElements) {
myFixedElements.put(ref, UnusedDeclarationHint.DELETE);
}
});
@@ -0,0 +1,49 @@
/*
* Copyright 2000-2017 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.
* 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.intellij.java.codeInspection;
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.reference.RefElement;
import com.intellij.codeInspection.reference.RefEntity;
import com.intellij.codeInspection.reference.RefManagerImpl;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import java.util.ArrayList;
import java.util.List;
public class BatchModeInspectionTest extends LightCodeInsightFixtureTestCase {
public void testEnsureReferencesAreRemoved() throws Exception {
PsiClass aClass = myFixture.addClass("class Foo {public void bar(int i){}}");
Project project = myFixture.getProject();
RefManagerImpl refManager = new RefManagerImpl(project, new AnalysisScope(aClass.getContainingFile()), InspectionManager.getInstance(
project).createNewGlobalContext(false));
refManager.findAllDeclarations();
List<RefElement> sortedElements = refManager.getSortedElements();
RefElement refMethod = refManager.getReference(aClass.getMethods()[0]);
List<RefEntity> children = refMethod.getChildren();
ArrayList<RefElement> deletedRefs = new ArrayList<>();
refManager.removeRefElement(refMethod, deletedRefs);
assertTrue(deletedRefs.containsAll(children));
assertTrue(deletedRefs.contains(refMethod));
//check that table was not reinitialized due to full table traversal
assertTrue(sortedElements == refManager.getSortedElements());
}
}
@@ -381,7 +381,7 @@ public class RefManagerImpl extends RefManager {
}
@NotNull
List<RefElement> getSortedElements() {
public List<RefElement> getSortedElements() {
List<RefElement> answer = myCachedSortedRefs;
if (answer != null) return answer;
@@ -682,7 +682,12 @@ public class RefManagerImpl extends RefManager {
((RefManagerImpl)refElement.getRefManager()).removeReference(refElement);
((RefElementImpl)refElement).referenceRemoved();
if (!deletedRefs.contains(refElement)) deletedRefs.add(refElement);
if (!deletedRefs.contains(refElement)) {
deletedRefs.add(refElement);
}
else {
LOG.error("deleted second time");
}
}
boolean isValidPointForReference() {