From d44d0e602ecd39159f26c6d4f514371b295eb5b7 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 24 Jun 2013 15:22:48 +0400 Subject: [PATCH] a number of inspection tools refactorings: to reduce confusion, InspectionToolWrapper no longer extends InspectionTool; InspectionToolWrapper and InspectionProfileManager moved to analysis; InspectionNode decoupled from InspectionTool - the former stored in the InspectionToolPresentation and the mapping InspectionToolWrapper->InspectionToolPresentation is stored in GlobalInspectionContext --- .../JavaAwareInspectionProfileCoverter.java | 2 +- .../RedundantSuppressInspection.java | 39 +- .../deadCode/DeadHTMLComposer.java | 12 +- .../DummyEntryPointsPresentation.java | 79 +++ .../deadCode/DummyEntryPointsTool.java | 55 +- .../deadCode/RefUnreachableFilter.java | 10 +- .../deadCode/UnreferencedFilter.java | 8 +- .../deadCode/UnusedDeclarationInspection.java | 400 ++------------ .../UnusedDeclarationPresentation.java | 521 ++++++++++++++++++ .../ex/FilteringInspectionTool.java | 179 ------ .../ex/GlobalJavaInspectionContextImpl.java | 21 +- .../reference/RefJavaManagerImpl.java | 2 +- .../codeInspection/ui/EntryPointsNode.java | 13 +- .../JavaAwareInspectionProfileManager.java | 5 +- .../GlobalInspectionContextTest.java | 17 +- .../codeInspection/InspectionProfileTest.java | 33 +- .../SingleInspectionProfilePanelTest.java | 2 +- .../daemon/DaemonAnalyzerTestCase.java | 9 +- .../codeInspection/InspectionProfile.java | 10 +- .../codeInspection/ModifiableModel.java | 25 +- .../ex/InspectionToolWrapper.java | 106 ++-- .../ex/InspectionToolsRegistrarCore.java | 54 ++ .../codeInspection/ex/ScopeToolState.java | 41 +- .../com/intellij/codeInspection/ex/Tools.java | 8 +- .../GlobalInspectionContextExtension.java | 5 +- .../codeInspection/reference/RefUtil.java | 13 + .../src/com/intellij/profile/Profile.java | 2 + .../daemon/InspectionProfileConvertor.java | 19 +- .../ex/GlobalInspectionToolWrapper.java | 74 +++ .../ex/InspectionProfileImpl.java | 232 ++++---- .../ex/InspectionProfileWrapper.java | 17 +- .../ex/InspectionToolRegistrar.java | 161 +----- .../ex/LocalInspectionToolWrapper.java | 111 ++++ .../ex/PairedUnfairLocalInspectionTool.java | 0 .../intellij/codeInspection/ex/ToolsImpl.java | 71 ++- .../src/com/intellij/profile/ProfileEx.java | 8 +- .../InspectionProjectProfileManagerImpl.java | 2 +- .../DaemonCodeAnalyzerSettingsImpl.java | 9 +- .../daemon/impl/HighlightInfo.java | 4 +- .../daemon/impl/LocalInspectionsPass.java | 22 +- .../InspectionDescriptionLinkHandler.java | 2 +- .../codeInspection/InspectionRunningUtil.java | 20 +- .../actions/CodeInspectionAction.java | 8 +- .../actions/GotoInspectionModel.java | 4 +- .../actions/RunInspectionIntention.java | 12 +- .../ex/CommonInspectionToolWrapper.java | 171 +----- .../codeInspection/ex/Descriptor.java | 17 +- .../codeInspection/ex/DescriptorComposer.java | 17 +- .../ex/DisableInspectionToolAction.java | 2 +- .../ex/GlobalInspectionContextImpl.java | 195 ++++--- .../ex/GlobalInspectionToolWrapper.java | 153 ----- .../ex/InspectionManagerEx.java | 62 +++ .../ex/InspectionPresentationProvider.java} | 15 +- .../ex/InspectionRVContentProvider.java | 48 +- .../ex/InspectionRVContentProviderImpl.java | 73 ++- .../codeInspection/ex/InspectionTool.java | 188 +------ .../ex/LocalDescriptorsUtil.java | 99 ++++ .../ex/LocalInspectionToolWrapper.java | 250 --------- .../ex/LocalQuickFixWrapper.java | 17 +- .../codeInspection/ex/PlainTextFormatter.java | 2 +- .../codeInspection/ex/QuickFixAction.java | 44 +- .../ex/SpecialToolsManager.java | 42 ++ .../export/HTMLExportFrameMaker.java | 19 +- .../OfflineInspectionRVContentProvider.java | 54 +- .../OfflineProblemDescriptorNode.java | 60 +- .../offlineViewer/OfflineRefElementNode.java | 9 +- .../intellij/codeInspection/ui/Browser.java | 234 ++++---- .../DefaultInspectionToolPresentation.java} | 304 ++++++++-- .../codeInspection/ui/InspectionNode.java | 13 +- .../ui/InspectionResultsView.java | 115 ++-- .../ui/InspectionToolPresentation.java | 89 +++ .../codeInspection/ui/InspectionTree.java | 25 +- .../ui/ProblemDescriptionNode.java | 30 +- .../codeInspection/ui/RefElementNode.java | 19 +- .../ui/actions/ExportHTMLAction.java | 54 +- .../InspectionsOptionsToolbarAction.java | 35 +- .../ui/actions/InvokeQuickFixAction.java | 12 +- .../ui/actions/SuppressActionWrapper.java | 15 +- .../InspectionProfileManagerImpl.java | 24 +- .../ui/InspectionConfigTreeNode.java | 12 +- .../ui/InspectionToolsConfigurable.java | 14 +- .../ui/InspectionsConfigTreeRenderer.java | 13 +- .../ui/SingleInspectionProfilePanel.java | 127 +++-- .../ui/actions/AddScopeAction.java | 16 +- .../ui/actions/DeleteScopeAction.java | 7 +- .../ui/actions/MoveScopeAction.java | 4 +- .../testFramework/InspectionTestUtil.java | 19 +- .../testFramework/LightPlatformTestCase.java | 4 +- .../impl/CodeInsightTestFixtureImpl.java | 90 ++- resources/src/META-INF/IdeaPlugin.xml | 1 + .../DomElementAnnotationsManagerImpl.java | 9 +- .../util/xml/DomHighlightingLiteTest.java | 6 +- .../xml/impl/ExternalDocumentValidator.java | 11 +- 93 files changed, 2696 insertions(+), 2590 deletions(-) create mode 100644 java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java create mode 100644 java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java delete mode 100644 java/java-impl/src/com/intellij/codeInspection/ex/FilteringInspectionTool.java rename platform/{lang-impl => analysis-api}/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java (72%) create mode 100644 platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolsRegistrarCore.java rename platform/{lang-impl => analysis-impl}/src/com/intellij/codeInsight/daemon/InspectionProfileConvertor.java (89%) create mode 100644 platform/analysis-impl/src/com/intellij/codeInspection/ex/GlobalInspectionToolWrapper.java rename platform/{lang-impl => analysis-impl}/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java (80%) rename platform/{lang-impl => analysis-impl}/src/com/intellij/codeInspection/ex/InspectionToolRegistrar.java (52%) create mode 100644 platform/analysis-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java rename platform/{lang-impl => analysis-impl}/src/com/intellij/codeInspection/ex/PairedUnfairLocalInspectionTool.java (100%) rename platform/{lang-impl => analysis-impl}/src/com/intellij/codeInspection/ex/ToolsImpl.java (87%) delete mode 100644 platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionToolWrapper.java rename platform/{lang-api/src/com/intellij/codeInspection/ex/ScopeToolStateUtil.java => lang-impl/src/com/intellij/codeInspection/ex/InspectionPresentationProvider.java} (57%) create mode 100644 platform/lang-impl/src/com/intellij/codeInspection/ex/LocalDescriptorsUtil.java delete mode 100644 platform/lang-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java create mode 100644 platform/lang-impl/src/com/intellij/codeInspection/ex/SpecialToolsManager.java rename platform/lang-impl/src/com/intellij/codeInspection/{ex/DescriptorProviderInspection.java => ui/DefaultInspectionToolPresentation.java} (64%) create mode 100644 platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionToolPresentation.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java b/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java index e411fc11add3..5caad6166995 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java @@ -52,7 +52,7 @@ public class JavaAwareInspectionProfileCoverter extends InspectionProfileConvert super.fillErrorLevels(profile); //javadoc attributes - final InspectionToolWrapper toolWrapper = (InspectionToolWrapper)profile.getInspectionTool(JavaDocLocalInspection.SHORT_NAME, null); + final InspectionToolWrapper toolWrapper = profile.getInspectionTool(JavaDocLocalInspection.SHORT_NAME, null); JavaDocLocalInspection inspection = (JavaDocLocalInspection)toolWrapper.getTool(); inspection.myAdditionalJavadocTags = myAdditionalJavadocTags; } diff --git a/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java b/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java index b2ce257425f5..354af57cf7d1 100644 --- a/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java @@ -19,10 +19,8 @@ import com.intellij.analysis.AnalysisScope; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.daemon.impl.RemoveSuppressWarningAction; import com.intellij.codeInspection.ex.*; -import com.intellij.codeInspection.reference.RefClass; -import com.intellij.codeInspection.reference.RefElement; -import com.intellij.codeInspection.reference.RefJavaVisitor; -import com.intellij.codeInspection.reference.RefManagerImpl; +import com.intellij.codeInspection.reference.*; +import com.intellij.codeInspection.ui.InspectionToolPresentation; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -116,7 +114,7 @@ public class RedundantSuppressInspection extends GlobalInspectionTool{ return checkElement(psiClass, manager, project); } - public CommonProblemDescriptor[] checkElement(@NotNull final PsiElement psiElement, @NotNull InspectionManager manager, @NotNull Project project) { + public CommonProblemDescriptor[] checkElement(@NotNull final PsiElement psiElement, @NotNull final InspectionManager manager, @NotNull Project project) { final Map> suppressedScopes = new THashMap>(); psiElement.accept(new JavaRecursiveElementWalkingVisitor() { @Override public void visitModifierList(PsiModifierList list) { @@ -193,7 +191,7 @@ public class RedundantSuppressInspection extends GlobalInspectionTool{ final AnalysisScope scope = new AnalysisScope(psiElement.getContainingFile()); final InspectionManagerEx inspectionManagerEx = (InspectionManagerEx)InspectionManager.getInstance(project); - GlobalInspectionContextImpl globalContext = inspectionManagerEx.createNewGlobalContext(false); + final GlobalInspectionContextImpl globalContext = inspectionManagerEx.createNewGlobalContext(false); globalContext.setCurrentScope(scope); final RefManagerImpl refManager = (RefManagerImpl)globalContext.getRefManager(); refManager.inspectionReadActionStarted(); @@ -204,19 +202,32 @@ public class RedundantSuppressInspection extends GlobalInspectionTool{ String toolId = toolWrapper instanceof LocalInspectionToolWrapper ? ((LocalInspectionToolWrapper)toolWrapper).getTool().getID() : toolWrapper.getShortName(); toolWrapper.initialize(globalContext); Collection descriptors; + final InspectionToolPresentation presentation = globalContext.getPresentation(toolWrapper); if (toolWrapper instanceof LocalInspectionToolWrapper) { LocalInspectionToolWrapper local = (LocalInspectionToolWrapper)toolWrapper; if (local.isUnfair()) continue; //cant't work with passes other than LocalInspectionPass - local.processFile(psiElement.getContainingFile(), false, manager); - descriptors = local.getProblemDescriptors(); + List results = local.getTool().processFile(psiElement.getContainingFile(), manager); + InspectionToolPresentation toolPresentation = globalContext.getPresentation(local); + LocalDescriptorsUtil.addProblemDescriptors(results, toolPresentation, false, globalContext, local.getTool()); + descriptors = presentation.getProblemDescriptors(); } else if (toolWrapper instanceof GlobalInspectionToolWrapper) { - GlobalInspectionToolWrapper global = (GlobalInspectionToolWrapper)toolWrapper; - if (global.getTool().isGraphNeeded()) { + final GlobalInspectionToolWrapper global = (GlobalInspectionToolWrapper)toolWrapper; + GlobalInspectionTool globalTool = global.getTool(); + if (globalTool.isGraphNeeded()) { refManager.findAllDeclarations(); } - global.processFile(scope, manager, globalContext, false); - descriptors = global.getProblemDescriptors(); + final InspectionToolPresentation toolPresentation = globalContext.getPresentation(global); + globalContext.getRefManager().iterate(new RefVisitor() { + @Override public void visitElement(@NotNull RefEntity refEntity) { + CommonProblemDescriptor[] + descriptors1 = global.getTool().checkElement(refEntity, scope, manager, globalContext, toolPresentation); + if (descriptors1 != null) { + toolPresentation.addProblemElement(refEntity, false, descriptors1); + } + } + }); + descriptors = presentation.getProblemDescriptors(); } else { continue; @@ -285,12 +296,12 @@ public class RedundantSuppressInspection extends GlobalInspectionTool{ return result.toArray(new ProblemDescriptor[result.size()]); } - protected InspectionToolWrapper[] getInspectionTools(PsiElement psiElement, InspectionManager manager) { + protected InspectionToolWrapper[] getInspectionTools(PsiElement psiElement, @NotNull InspectionManager manager) { ModifiableModel model = InspectionProjectProfileManager.getInstance(manager.getProject()).getInspectionProfile().getModifiableModel(); InspectionProfileWrapper profile = new InspectionProfileWrapper((InspectionProfile)model); profile.init(manager.getProject()); - return (InspectionToolWrapper[])profile.getInspectionTools(psiElement); + return profile.getInspectionTools(psiElement); } diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DeadHTMLComposer.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DeadHTMLComposer.java index 9b5cb309cc3b..88f56186fc8e 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/DeadHTMLComposer.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DeadHTMLComposer.java @@ -28,8 +28,8 @@ import com.intellij.codeInspection.HTMLJavaHTMLComposer; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.ex.DescriptorComposer; import com.intellij.codeInspection.ex.HTMLComposerImpl; -import com.intellij.codeInspection.ex.InspectionTool; import com.intellij.codeInspection.reference.*; +import com.intellij.codeInspection.ui.InspectionToolPresentation; import com.intellij.codeInspection.ui.InspectionTreeNode; import com.intellij.codeInspection.ui.RefElementNode; import org.jetbrains.annotations.NonNls; @@ -41,11 +41,11 @@ import java.util.Iterator; import java.util.Set; public class DeadHTMLComposer extends HTMLComposerImpl { - private final InspectionTool myTool; + private final InspectionToolPresentation myToolPresentation; private final HTMLJavaHTMLComposer myComposer; - public DeadHTMLComposer(@NotNull InspectionTool tool) { - myTool = tool; + public DeadHTMLComposer(@NotNull InspectionToolPresentation presentation) { + myToolPresentation = presentation; myComposer = getExtension(HTMLJavaHTMLComposer.COMPOSER); } @@ -64,7 +64,7 @@ public class DeadHTMLComposer extends HTMLComposerImpl { //noinspection HardCodedStringLiteral buf.append("

"); - appendResolution(buf, refElement, DescriptorComposer.quickFixTexts(refElement, myTool)); + appendResolution(buf, refElement, DescriptorComposer.quickFixTexts(refElement, myToolPresentation)); refElement.accept(new RefJavaVisitor() { @Override public void visitClass(@NotNull RefClass aClass) { appendClassInstantiations(buf, aClass); @@ -339,7 +339,7 @@ public class DeadHTMLComposer extends HTMLComposerImpl { } private void appendCallesList(RefElement element, StringBuffer buf, Set mentionedElements, boolean appendCallees){ - final Set possibleChildren = getPossibleChildren(new RefElementNode(element, myTool), element); + final Set possibleChildren = getPossibleChildren(new RefElementNode(element, myToolPresentation), element); if (!possibleChildren.isEmpty()) { if (appendCallees){ appendHeading(buf, InspectionsBundle.message("inspection.export.results.callees")); diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java new file mode 100644 index 000000000000..12b1cd9c3627 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2013 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.codeInspection.deadCode; + +import com.intellij.codeInspection.InspectionsBundle; +import com.intellij.codeInspection.ex.*; +import com.intellij.codeInspection.reference.RefElement; +import com.intellij.codeInspection.reference.RefEntity; +import com.intellij.codeInspection.ui.InspectionNode; +import com.intellij.codeInspection.ui.InspectionTreeNode; +import com.intellij.codeInspection.util.RefFilter; +import org.jetbrains.annotations.NotNull; + +public class DummyEntryPointsPresentation extends UnusedDeclarationPresentation { + private static final RefEntryPointFilter myFilter = new RefEntryPointFilter(); + private QuickFixAction[] myQuickFixActions; + + public DummyEntryPointsPresentation(UnusedDeclarationInspection inspection, @NotNull InspectionToolWrapper toolWrapper) { + super(toolWrapper); + } + + @Override + public RefFilter getFilter() { + return myFilter; + } + + @Override + public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements) { + if (myQuickFixActions == null) { + myQuickFixActions = new QuickFixAction[]{new MoveEntriesToSuspicious(getToolWrapper())}; + } + return myQuickFixActions; + } + + private class MoveEntriesToSuspicious extends QuickFixAction { + private MoveEntriesToSuspicious(@NotNull InspectionToolWrapper toolWrapper) { + super(InspectionsBundle.message("inspection.dead.code.remove.from.entry.point.quickfix"), null, null, toolWrapper); + } + + @Override + protected boolean applyFix(RefElement[] refElements) { + final EntryPointsManager entryPointsManager = + getContext().getExtension(GlobalJavaInspectionContextImpl.CONTEXT).getEntryPointsManager(getContext().getRefManager()); + for (RefElement refElement : refElements) { + entryPointsManager.removeEntryPoint(refElement); + } + + return true; + } + } + + @NotNull + @Override + public InspectionNode createToolNode(@NotNull GlobalInspectionContextImpl context, @NotNull InspectionNode node, + @NotNull InspectionRVContentProvider provider, + @NotNull InspectionTreeNode parentNode, + boolean showStructure) { + return node; + } + + @Override + @NotNull + public HTMLComposerImpl getComposer() { + return new DeadHTMLComposer(this); + } +} diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java index 1b8ef7435111..fcf375fd9194 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java @@ -19,36 +19,22 @@ import com.intellij.analysis.AnalysisScope; import com.intellij.codeInspection.GlobalInspectionContext; import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.InspectionsBundle; -import com.intellij.codeInspection.ex.*; -import com.intellij.codeInspection.reference.RefElement; -import com.intellij.codeInspection.reference.RefEntity; -import com.intellij.codeInspection.util.RefFilter; -import org.jdom.Element; +import com.intellij.codeInspection.ex.InspectionPresentationProvider; +import com.intellij.codeInspection.ex.InspectionToolWrapper; +import com.intellij.codeInspection.ex.JobDescriptor; +import com.intellij.codeInspection.ui.InspectionToolPresentation; import org.jetbrains.annotations.NotNull; /** * @author max */ -public class DummyEntryPointsTool extends FilteringInspectionTool { - private static final RefEntryPointFilter myFilter = new RefEntryPointFilter(); - private QuickFixAction[] myQuickFixActions; - - public DummyEntryPointsTool(@NotNull UnusedDeclarationInspection owner) { - initialize(owner.getContext()); - } - - @Override - public RefFilter getFilter() { - return myFilter; +public class DummyEntryPointsTool extends UnusedDeclarationInspection implements InspectionPresentationProvider { + public DummyEntryPointsTool() { } @Override public void runInspection(@NotNull AnalysisScope scope, @NotNull final InspectionManager manager) {} - @Override - public void exportResults(@NotNull Element parentNode, @NotNull RefEntity refEntity) { - } - @Override @NotNull public JobDescriptor[] getJobDescriptors(@NotNull GlobalInspectionContext globalInspectionContext) { @@ -73,34 +59,9 @@ public class DummyEntryPointsTool extends FilteringInspectionTool { return ""; } - @Override @NotNull - public HTMLComposerImpl getComposer() { - return new DeadHTMLComposer(this); - } - @Override - public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements) { - if (myQuickFixActions == null) { - myQuickFixActions = new QuickFixAction[]{new MoveEntriesToSuspicious()}; - } - return myQuickFixActions; - } - - private class MoveEntriesToSuspicious extends QuickFixAction { - private MoveEntriesToSuspicious() { - super(InspectionsBundle.message("inspection.dead.code.remove.from.entry.point.quickfix"), null, null, DummyEntryPointsTool.this); - } - - @Override - protected boolean applyFix(RefElement[] refElements) { - final EntryPointsManager entryPointsManager = - getContext().getExtension(GlobalJavaInspectionContextImpl.CONTEXT).getEntryPointsManager(getContext().getRefManager()); - for (RefElement refElement : refElements) { - entryPointsManager.removeEntryPoint(refElement); - } - - return true; - } + public InspectionToolPresentation createPresentation(@NotNull InspectionToolWrapper toolWrapper) { + return new DummyEntryPointsPresentation(this, toolWrapper); } } diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java index 5984cf16b71a..b00d7490ecc7 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java @@ -24,17 +24,19 @@ */ package com.intellij.codeInspection.deadCode; -import com.intellij.codeInspection.ex.InspectionTool; +import com.intellij.codeInspection.ex.GlobalInspectionContextImpl; import com.intellij.codeInspection.reference.*; import com.intellij.codeInspection.util.RefFilter; import org.jetbrains.annotations.NotNull; public class RefUnreachableFilter extends RefFilter { @NotNull - protected InspectionTool myTool; + protected UnusedDeclarationInspection myTool; + @NotNull protected final GlobalInspectionContextImpl myContext; - public RefUnreachableFilter(@NotNull InspectionTool tool) { + public RefUnreachableFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) { myTool = tool; + myContext = context; } @Override @@ -42,7 +44,7 @@ public class RefUnreachableFilter extends RefFilter { if (refElement instanceof RefParameter) return 0; if (refElement.isSyntheticJSP()) return 0; if (!(refElement instanceof RefMethod || refElement instanceof RefClass || refElement instanceof RefField)) return 0; - if (!myTool.getContext().isToCheckMember(refElement, myTool)) return 0; + if (!myContext.isToCheckMember(refElement, myTool)) return 0; return ((RefElementImpl)refElement).isSuspicious() ? 1 : 0; } } diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java index 32dc52252e95..923e5777f6d1 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java @@ -24,13 +24,13 @@ */ package com.intellij.codeInspection.deadCode; -import com.intellij.codeInspection.ex.InspectionTool; +import com.intellij.codeInspection.ex.GlobalInspectionContextImpl; import com.intellij.codeInspection.reference.*; import org.jetbrains.annotations.NotNull; public class UnreferencedFilter extends RefUnreachableFilter { - public UnreferencedFilter(@NotNull InspectionTool tool) { - super(tool); + public UnreferencedFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) { + super(tool, context); } @Override @@ -39,7 +39,7 @@ public class UnreferencedFilter extends RefUnreachableFilter { if (refElement.isEntry() || !((RefElementImpl)refElement).isSuspicious() || refElement.isSyntheticJSP()) return 0; if (!(refElement instanceof RefMethod || refElement instanceof RefClass || refElement instanceof RefField)) return 0; - if (!myTool.getContext().isToCheckMember(refElement, myTool)) return 0; + if (!myContext.isToCheckMember(refElement, myTool)) return 0; if (refElement instanceof RefField) { RefField refField = (RefField) refElement; diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java index 633a6089d6e2..9e2ca63a6585 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java @@ -31,27 +31,17 @@ import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.daemon.ImplicitUsageProvider; import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtilBase; -import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.*; import com.intellij.codeInspection.reference.*; -import com.intellij.codeInspection.ui.EntryPointsNode; -import com.intellij.codeInspection.ui.InspectionNode; -import com.intellij.codeInspection.ui.InspectionTreeNode; +import com.intellij.codeInspection.ui.InspectionToolPresentation; import com.intellij.codeInspection.util.RefFilter; -import com.intellij.icons.AllIcons; -import com.intellij.lang.annotation.HighlightSeverity; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.*; import com.intellij.psi.impl.PsiClassImplUtil; @@ -59,15 +49,9 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor; import com.intellij.psi.search.PsiSearchHelper; import com.intellij.psi.util.PsiMethodUtil; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtilCore; -import com.intellij.refactoring.safeDelete.SafeDeleteHandler; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.SeparatorFactory; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashMap; -import com.intellij.util.text.CharArrayUtil; -import com.intellij.util.text.DateFormatUtil; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -77,40 +61,26 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; import java.util.*; import java.util.List; -public class UnusedDeclarationInspection extends FilteringInspectionTool { +public class UnusedDeclarationInspection extends InspectionTool implements InspectionPresentationProvider { public boolean ADD_MAINS_TO_ENTRIES = true; public boolean ADD_APPLET_TO_ENTRIES = true; public boolean ADD_SERVLET_TO_ENTRIES = true; public boolean ADD_NONJAVA_TO_ENTRIES = true; - private HashSet myProcessedSuspicious = null; + private Set myProcessedSuspicious = null; private int myPhase; - private final QuickFixAction[] myQuickFixActions; public static final String DISPLAY_NAME = InspectionsBundle.message("inspection.dead.code.display.name"); - private WeakUnreferencedFilter myFilter; - private DeadHTMLComposer myComposer; @NonNls public static final String SHORT_NAME = "UnusedDeclaration"; @NonNls private static final String ALTERNATIVE_ID = "unused"; - private static final String COMMENT_OUT_QUICK_FIX = InspectionsBundle.message("inspection.dead.code.comment.quickfix"); - private static final String DELETE_QUICK_FIX = InspectionsBundle.message("inspection.dead.code.safe.delete.quickfix"); - - @NonNls private static final String DELETE = "delete"; - @NonNls private static final String COMMENT = "comment"; - @NonNls private static final String [] HINTS = {COMMENT, DELETE}; - public final EntryPoint[] myExtensions; private static final Logger LOG = Logger.getInstance("#" + UnusedDeclarationInspection.class.getName()); public UnusedDeclarationInspection() { - - myQuickFixActions = new QuickFixAction[]{new PermanentDeleteAction(), new CommentOutBin(), new MoveToEntries()}; ExtensionPoint point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.DEAD_CODE_TOOL); final EntryPoint[] deadCodeAddins = new EntryPoint[point.getExtensions().length]; EntryPoint[] extensions = point.getExtensions(); @@ -132,10 +102,8 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { myExtensions = deadCodeAddins; } - @Override - public void initialize(@NotNull final GlobalInspectionContextImpl context) { - super.initialize(context); - ((EntryPointsManagerImpl)getEntryPointsManager()).setAddNonJavaEntries(ADD_NONJAVA_TO_ENTRIES); + private GlobalInspectionContextImpl getContext() { + return myContext; } private class OptionsPanel extends JPanel { @@ -369,8 +337,9 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { @Override public void runInspection(@NotNull final AnalysisScope scope, @NotNull final InspectionManager manager) { - getRefManager().iterate(new RefJavaVisitor() { - @Override public void visitElement(@NotNull final RefEntity refEntity) { + getContext().getRefManager().iterate(new RefJavaVisitor() { + @Override + public void visitElement(@NotNull final RefEntity refEntity) { if (refEntity instanceof RefJavaElement) { final RefElementImpl refElement = (RefElementImpl)refEntity; if (!refElement.isSuspicious()) return; @@ -387,13 +356,15 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { } refElement.accept(new RefJavaVisitor() { - @Override public void visitMethod(@NotNull RefMethod method) { + @Override + public void visitMethod(@NotNull RefMethod method) { if (isAddMainsEnabled() && method.isAppMain()) { getEntryPointsManager().addEntryPoint(method, false); } } - @Override public void visitClass(@NotNull RefClass aClass) { + @Override + public void visitClass(@NotNull RefClass aClass) { if (isAddAppletEnabled() && aClass.isApplet() || isAddServletEnabled() && aClass.isServlet()) { getEntryPointsManager().addEntryPoint(aClass, false); @@ -406,19 +377,20 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { if (isAddNonJavaUsedEnabled()) { checkForReachables(); + final StrictUnreferencedFilter strictUnreferencedFilter = new StrictUnreferencedFilter(this, myContext); ProgressManager.getInstance().runProcess(new Runnable() { @Override public void run() { - final RefFilter filter = new StrictUnreferencedFilter(UnusedDeclarationInspection.this); - final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(getRefManager().getProject()); - getRefManager().iterate(new RefJavaVisitor() { - @Override public void visitElement(@NotNull final RefEntity refEntity) { - if (refEntity instanceof RefClass && filter.accepts((RefClass)refEntity)) { + final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(getContext().getRefManager().getProject()); + getContext().getRefManager().iterate(new RefJavaVisitor() { + @Override + public void visitElement(@NotNull final RefEntity refEntity) { + if (refEntity instanceof RefClass && strictUnreferencedFilter.accepts((RefClass)refEntity)) { findExternalClassReferences((RefClass)refEntity); } else if (refEntity instanceof RefMethod) { RefMethod refMethod = (RefMethod)refEntity; - if (refMethod.isConstructor() && filter.accepts(refMethod)) { + if (refMethod.isConstructor() && strictUnreferencedFilter.accepts(refMethod)) { findExternalClassReferences(refMethod.getOwnerClass()); } } @@ -514,9 +486,10 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { return false; } + private static class StrictUnreferencedFilter extends UnreferencedFilter { - private StrictUnreferencedFilter(@NotNull InspectionTool tool) { - super(tool); + private StrictUnreferencedFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) { + super(tool, context); } @Override @@ -527,34 +500,22 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { } } - private static class WeakUnreferencedFilter extends UnreferencedFilter { - private WeakUnreferencedFilter(@NotNull InspectionTool tool) { - super(tool); - } - - @Override - public int getElementProblemCount(final RefJavaElement refElement) { - final int problemCount = super.getElementProblemCount(refElement); - if (problemCount > - 1) return problemCount; - if (!((RefElementImpl)refElement).hasSuspiciousCallers() || ((RefJavaElementImpl)refElement).isSuspiciousRecursive()) return 1; - return 0; - } - } - @Override public boolean queryExternalUsagesRequests(@NotNull final InspectionManager manager) { checkForReachables(); - final RefFilter filter = myPhase == 1 ? new StrictUnreferencedFilter(this) : new RefUnreachableFilter(this); + final RefFilter filter = myPhase == 1 ? new StrictUnreferencedFilter(this, getContext()) : new RefUnreachableFilter(this, getContext()); final boolean[] requestAdded = {false}; - getRefManager().iterate(new RefJavaVisitor() { - @Override public void visitElement(@NotNull RefEntity refEntity) { + getContext().getRefManager().iterate(new RefJavaVisitor() { + @Override + public void visitElement(@NotNull RefEntity refEntity) { if (!(refEntity instanceof RefJavaElement)) return; if (refEntity instanceof RefClass && ((RefClass)refEntity).isAnonymous()) return; - RefJavaElement refElement= (RefJavaElement)refEntity; + RefJavaElement refElement = (RefJavaElement)refEntity; if (filter.accepts(refElement) && !myProcessedSuspicious.contains(refElement)) { refEntity.accept(new RefJavaVisitor() { - @Override public void visitField(@NotNull final RefField refField) { + @Override + public void visitField(@NotNull final RefField refField) { myProcessedSuspicious.add(refField); PsiField psiField = refField.getElement(); if (isSerializationImplicitlyUsedField(psiField)) { @@ -572,7 +533,8 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { } } - @Override public void visitMethod(@NotNull final RefMethod refMethod) { + @Override + public void visitMethod(@NotNull final RefMethod refMethod) { myProcessedSuspicious.add(refMethod); if (refMethod instanceof RefImplicitConstructor) { visitClass(refMethod.getOwnerClass()); @@ -593,7 +555,8 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { } } - @Override public void visitClass(@NotNull final RefClass refClass) { + @Override + public void visitClass(@NotNull final RefClass refClass) { myProcessedSuspicious.add(refClass); if (!refClass.isAnonymous()) { getJavaContext().enqueueDerivedClassesProcessor(refClass, new GlobalJavaInspectionContext.DerivedClassesProcessor() { @@ -654,69 +617,10 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { } } - public GlobalJavaInspectionContext getJavaContext() { + private GlobalJavaInspectionContext getJavaContext() { return getContext().getExtension(GlobalJavaInspectionContext.CONTEXT); } - @Override - public RefFilter getFilter() { - if (myFilter == null) { - myFilter = new WeakUnreferencedFilter(this); - } - return myFilter; - } - - @Override - @NotNull - public HTMLComposerImpl getComposer() { - if (myComposer == null) { - myComposer = new DeadHTMLComposer(this); - } - return myComposer; - } - - @Override - public void exportResults(@NotNull final Element parentNode, @NotNull RefEntity refEntity) { - if (!(refEntity instanceof RefJavaElement)) return; - final WeakUnreferencedFilter filter = new WeakUnreferencedFilter(this); - if (!getIgnoredRefElements().contains(refEntity) && filter.accepts((RefJavaElement)refEntity)) { - if (refEntity instanceof RefImplicitConstructor) refEntity = ((RefImplicitConstructor)refEntity).getOwnerClass(); - Element element = refEntity.getRefManager().export(refEntity, parentNode, -1); - if (element == null) return; - @NonNls Element problemClassElement = new Element(InspectionsBundle.message("inspection.export.results.problem.element.tag")); - - final RefElement refElement = (RefElement)refEntity; - final HighlightSeverity severity = getCurrentSeverity(refElement); - final String attributeKey = - getTextAttributeKey(refElement.getRefManager().getProject(), severity, ProblemHighlightType.LIKE_UNUSED_SYMBOL); - problemClassElement.setAttribute("severity", severity.myName); - problemClassElement.setAttribute("attribute_key", attributeKey); - - problemClassElement.addContent(InspectionsBundle.message("inspection.export.results.dead.code")); - element.addContent(problemClassElement); - - @NonNls Element hintsElement = new Element("hints"); - - for (String hint : HINTS) { - @NonNls Element hintElement = new Element("hint"); - hintElement.setAttribute("value", hint); - hintsElement.addContent(hintElement); - } - element.addContent(hintsElement); - - - Element descriptionElement = new Element(InspectionsBundle.message("inspection.export.results.description.tag")); - StringBuffer buf = new StringBuffer(); - DeadHTMLComposer.appendProblemSynopsis((RefElement)refEntity, buf); - descriptionElement.addContent(buf.toString()); - element.addContent(descriptionElement); - } - } - - @Override - public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements) { - return myQuickFixActions; - } @NotNull @Override @@ -725,224 +629,14 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { context.getStdJobDescriptors().FIND_EXTERNAL_USAGES}; } - private static void commentOutDead(PsiElement psiElement) { - PsiFile psiFile = psiElement.getContainingFile(); - if (psiFile != null) { - Document doc = PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(psiFile); - if (doc != null) { - TextRange textRange = psiElement.getTextRange(); - String date = DateFormatUtil.formatDateTime(new Date()); - - int startOffset = textRange.getStartOffset(); - CharSequence chars = doc.getCharsSequence(); - while (CharArrayUtil.regionMatches(chars, startOffset, InspectionsBundle.message("inspection.dead.code.comment"))) { - int line = doc.getLineNumber(startOffset) + 1; - if (line < doc.getLineCount()) { - startOffset = doc.getLineStartOffset(line); - startOffset = CharArrayUtil.shiftForward(chars, startOffset, " \t"); - } - } - - int endOffset = textRange.getEndOffset(); - - int line1 = doc.getLineNumber(startOffset); - int line2 = doc.getLineNumber(endOffset - 1); - - if (line1 == line2) { - doc.insertString(startOffset, InspectionsBundle.message("inspection.dead.code.date.comment", date)); - } - else { - for (int i = line1; i <= line2; i++) { - doc.insertString(doc.getLineStartOffset(i), "//"); - } - - doc.insertString(doc.getLineStartOffset(Math.min(line2 + 1, doc.getLineCount() - 1)), - InspectionsBundle.message("inspection.dead.code.stop.comment", date)); - doc.insertString(doc.getLineStartOffset(line1), InspectionsBundle.message("inspection.dead.code.start.comment", date)); - } - } - } - } - - @Override - @Nullable - public IntentionAction findQuickFixes(final CommonProblemDescriptor descriptor, final String hint) { - if (descriptor instanceof ProblemDescriptor) { - if (DELETE.equals(hint)) { - return new PermanentDeleteFix(((ProblemDescriptor)descriptor).getPsiElement()); - } - if (COMMENT.equals(hint)) { - return new CommentOutFix(((ProblemDescriptor)descriptor).getPsiElement()); - } - } - return null; - } - - private class PermanentDeleteAction extends QuickFixAction { - private PermanentDeleteAction() { - super(DELETE_QUICK_FIX, AllIcons.Actions.Cancel, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), UnusedDeclarationInspection.this); - } - - @Override - protected boolean applyFix(final RefElement[] refElements) { - if (!super.applyFix(refElements)) return false; - final ArrayList psiElements = new ArrayList(); - for (RefElement refElement : refElements) { - PsiElement psiElement = refElement.getElement(); - if (psiElement == null) continue; - if (getFilter().getElementProblemCount((RefJavaElement)refElement) == 0) continue; - psiElements.add(psiElement); - } - - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - final Project project = getContext().getProject(); - SafeDeleteHandler.invoke(project, PsiUtilCore.toPsiElementArray(psiElements), false, new Runnable() { - @Override - public void run() { - removeElements(refElements, project, UnusedDeclarationInspection.this); - } - }); - } - }); - - return false; //refresh after safe delete dialog is closed - } - } - - private static class PermanentDeleteFix implements IntentionAction { - private final PsiElement myElement; - - private PermanentDeleteFix(final PsiElement element) { - myElement = element; - } - - @Override - @NotNull - public String getText() { - return DELETE_QUICK_FIX; - } - - @Override - @NotNull - public String getFamilyName() { - return getText(); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return true; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - if (myElement != null && myElement.isValid()) { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - SafeDeleteHandler - .invoke(myElement.getProject(), new PsiElement[]{PsiTreeUtil.getParentOfType(myElement, PsiModifierListOwner.class)}, false); - } - }); - } - } - - @Override - public boolean startInWriteAction() { - return true; - } - } - - private class CommentOutBin extends QuickFixAction { - private CommentOutBin() { - super(COMMENT_OUT_QUICK_FIX, null, KeyStroke.getKeyStroke(KeyEvent.VK_SLASH, SystemInfo.isMac ? InputEvent.META_MASK : InputEvent.CTRL_MASK), - UnusedDeclarationInspection.this); - } - - @Override - protected boolean applyFix(RefElement[] refElements) { - if (!super.applyFix(refElements)) return false; - ArrayList deletedRefs = new ArrayList(1); - for (RefElement refElement : refElements) { - PsiElement psiElement = refElement.getElement(); - if (psiElement == null) continue; - if (getFilter().getElementProblemCount((RefJavaElement)refElement) == 0) continue; - commentOutDead(psiElement); - refElement.getRefManager().removeRefElement(refElement, deletedRefs); - } - - EntryPointsManager entryPointsManager = getEntryPointsManager(); - for (RefElement refElement : deletedRefs) { - entryPointsManager.removeEntryPoint(refElement); - } - - return true; - } - } - - private static class CommentOutFix implements IntentionAction { - private final PsiElement myElement; - - private CommentOutFix(final PsiElement element) { - myElement = element; - } - - @Override - @NotNull - public String getText() { - return COMMENT_OUT_QUICK_FIX; - } - - @Override - @NotNull - public String getFamilyName() { - return getText(); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return true; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - if (myElement != null && myElement.isValid()) { - commentOutDead(PsiTreeUtil.getParentOfType(myElement, PsiModifierListOwner.class)); - } - } - - @Override - public boolean startInWriteAction() { - return true; - } - } - - private class MoveToEntries extends QuickFixAction { - private MoveToEntries() { - super(InspectionsBundle.message("inspection.dead.code.entry.point.quickfix"), null, KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0), UnusedDeclarationInspection.this); - } - - @Override - protected boolean applyFix(RefElement[] refElements) { - final EntryPointsManager entryPointsManager = getEntryPointsManager(); - for (RefElement refElement : refElements) { - entryPointsManager.addEntryPoint(refElement, true); - } - - return true; - } - - - } - - private void checkForReachables() { + void checkForReachables() { CodeScanner codeScanner = new CodeScanner(); // Cleanup previous reachability information. - getRefManager().iterate(new RefJavaVisitor() { - @Override public void visitElement(@NotNull RefEntity refEntity) { + getContext().getRefManager().iterate(new RefJavaVisitor() { + @Override + public void visitElement(@NotNull RefEntity refEntity) { if (refEntity instanceof RefJavaElement) { final RefJavaElementImpl refElement = (RefJavaElementImpl)refEntity; if (!getContext().isToCheckMember(refElement, UnusedDeclarationInspection.this)) return; @@ -1094,18 +788,16 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { } } - @Override - public void updateContent() { - checkForReachables(); - super.updateContent(); - } @NotNull @Override - public InspectionNode createToolNode(@NotNull final InspectionRVContentProvider provider, @NotNull final InspectionTreeNode parentNode, final boolean showStructure) { - final InspectionNode toolNode = super.createToolNode(provider, parentNode, showStructure); - final EntryPointsNode entryPointsNode = new EntryPointsNode(this); - provider.appendToolNodeContent(entryPointsNode, toolNode, showStructure); - return entryPointsNode; + public InspectionToolPresentation createPresentation(@NotNull InspectionToolWrapper toolWrapper) { + myContext = (GlobalInspectionContextImpl)toolWrapper.getContext(); + return new UnusedDeclarationPresentation(toolWrapper); + } + + @Override + public boolean isGraphNeeded() { + return true; } } diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java new file mode 100644 index 000000000000..4602c3f09755 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java @@ -0,0 +1,521 @@ +/* + * Copyright 2000-2013 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.codeInspection.deadCode; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.ex.*; +import com.intellij.codeInspection.reference.*; +import com.intellij.codeInspection.ui.*; +import com.intellij.codeInspection.util.RefFilter; +import com.intellij.icons.AllIcons; +import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vcs.FileStatus; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiModifierListOwner; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.refactoring.safeDelete.SafeDeleteHandler; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.HashMap; +import com.intellij.util.containers.HashSet; +import com.intellij.util.text.CharArrayUtil; +import com.intellij.util.text.DateFormatUtil; +import org.jdom.Element; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.*; + +public class UnusedDeclarationPresentation extends DefaultInspectionToolPresentation { + private Map> myPackageContents = new HashMap>(); + + private Map> myOldPackageContents = null; + + private final Set myIgnoreElements = new HashSet(); + private WeakUnreferencedFilter myFilter; + private DeadHTMLComposer myComposer; + @NonNls private static final String DELETE = "delete"; + @NonNls private static final String COMMENT = "comment"; + @NonNls private static final String [] HINTS = {COMMENT, DELETE}; + + public UnusedDeclarationPresentation(@NotNull InspectionToolWrapper toolWrapper) { + super(toolWrapper); + myQuickFixActions = createQuickFixes(toolWrapper); + } + + public RefFilter getFilter() { + if (myFilter == null) { + myFilter = new WeakUnreferencedFilter(getTool(), getContext()); + } + return myFilter; + } + private static class WeakUnreferencedFilter extends UnreferencedFilter { + private WeakUnreferencedFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) { + super(tool, context); + } + + @Override + public int getElementProblemCount(final RefJavaElement refElement) { + final int problemCount = super.getElementProblemCount(refElement); + if (problemCount > - 1) return problemCount; + if (!((RefElementImpl)refElement).hasSuspiciousCallers() || ((RefJavaElementImpl)refElement).isSuspiciousRecursive()) return 1; + return 0; + } + } + + @NotNull + UnusedDeclarationInspection getTool() { + return (UnusedDeclarationInspection)getToolWrapper().getTool(); + } + + + @Override + @NotNull + public HTMLComposerImpl getComposer() { + if (myComposer == null) { + myComposer = new DeadHTMLComposer(this); + } + return myComposer; + } + + @Override + public void exportResults(@NotNull final Element parentNode, @NotNull RefEntity refEntity) { + if (!(refEntity instanceof RefJavaElement)) return; + final RefFilter filter = getFilter(); + if (!getIgnoredRefElements().contains(refEntity) && filter.accepts((RefJavaElement)refEntity)) { + refEntity = getRefManager().getRefinedElement(refEntity); + Element element = refEntity.getRefManager().export(refEntity, parentNode, -1); + if (element == null) return; + @NonNls Element problemClassElement = new Element(InspectionsBundle.message("inspection.export.results.problem.element.tag")); + + final RefElement refElement = (RefElement)refEntity; + final HighlightSeverity severity = getSeverity(refElement, getContext(), getToolWrapper()); + final String attributeKey = + getTextAttributeKey(refElement.getRefManager().getProject(), severity, ProblemHighlightType.LIKE_UNUSED_SYMBOL); + problemClassElement.setAttribute("severity", severity.myName); + problemClassElement.setAttribute("attribute_key", attributeKey); + + problemClassElement.addContent(InspectionsBundle.message("inspection.export.results.dead.code")); + element.addContent(problemClassElement); + + @NonNls Element hintsElement = new Element("hints"); + + for (String hint : HINTS) { + @NonNls Element hintElement = new Element("hint"); + hintElement.setAttribute("value", hint); + hintsElement.addContent(hintElement); + } + element.addContent(hintsElement); + + + Element descriptionElement = new Element(InspectionsBundle.message("inspection.export.results.description.tag")); + StringBuffer buf = new StringBuffer(); + DeadHTMLComposer.appendProblemSynopsis((RefElement)refEntity, buf); + descriptionElement.addContent(buf.toString()); + element.addContent(descriptionElement); + } + } + + @Override + public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements) { + return myQuickFixActions; + } + + final QuickFixAction[] myQuickFixActions; + + @NotNull + private QuickFixAction[] createQuickFixes(@NotNull InspectionToolWrapper toolWrapper) { + return new QuickFixAction[]{new PermanentDeleteAction(toolWrapper), new CommentOutBin(toolWrapper), new MoveToEntries(toolWrapper)}; + } + private static final String DELETE_QUICK_FIX = InspectionsBundle.message("inspection.dead.code.safe.delete.quickfix"); + + class PermanentDeleteAction extends QuickFixAction { + PermanentDeleteAction(@NotNull InspectionToolWrapper toolWrapper) { + super(DELETE_QUICK_FIX, AllIcons.Actions.Cancel, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), toolWrapper); + } + + @Override + protected boolean applyFix(final RefElement[] refElements) { + if (!super.applyFix(refElements)) return false; + final ArrayList psiElements = new ArrayList(); + for (RefElement refElement : refElements) { + PsiElement psiElement = refElement.getElement(); + if (psiElement == null) continue; + if (getFilter().getElementProblemCount((RefJavaElement)refElement) == 0) continue; + psiElements.add(psiElement); + } + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + final Project project = getContext().getProject(); + SafeDeleteHandler.invoke(project, PsiUtilCore.toPsiElementArray(psiElements), false, new Runnable() { + @Override + public void run() { + removeElements(refElements, project, myToolWrapper); + } + }); + } + }); + + return false; //refresh after safe delete dialog is closed + } + } + + private EntryPointsManager getEntryPointsManager() { + return getContext().getExtension(GlobalJavaInspectionContext.CONTEXT).getEntryPointsManager(getContext().getRefManager()); + } + + class MoveToEntries extends QuickFixAction { + MoveToEntries(@NotNull InspectionToolWrapper toolWrapper) { + super(InspectionsBundle.message("inspection.dead.code.entry.point.quickfix"), null, KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0), toolWrapper); + } + + @Override + protected boolean applyFix(RefElement[] refElements) { + final EntryPointsManager entryPointsManager = getEntryPointsManager(); + for (RefElement refElement : refElements) { + entryPointsManager.addEntryPoint(refElement, true); + } + + return true; + } + } + + class CommentOutBin extends QuickFixAction { + CommentOutBin(@NotNull InspectionToolWrapper toolWrapper) { + super(COMMENT_OUT_QUICK_FIX, null, KeyStroke.getKeyStroke(KeyEvent.VK_SLASH, SystemInfo.isMac ? InputEvent.META_MASK : InputEvent.CTRL_MASK), + toolWrapper); + } + + @Override + protected boolean applyFix(RefElement[] refElements) { + if (!super.applyFix(refElements)) return false; + ArrayList deletedRefs = new ArrayList(1); + for (RefElement refElement : refElements) { + PsiElement psiElement = refElement.getElement(); + if (psiElement == null) continue; + if (getFilter().getElementProblemCount((RefJavaElement)refElement) == 0) continue; + commentOutDead(psiElement); + refElement.getRefManager().removeRefElement(refElement, deletedRefs); + } + + EntryPointsManager entryPointsManager = getEntryPointsManager(); + for (RefElement refElement : deletedRefs) { + entryPointsManager.removeEntryPoint(refElement); + } + + return true; + } + } + + private static final String COMMENT_OUT_QUICK_FIX = InspectionsBundle.message("inspection.dead.code.comment.quickfix"); + private static class CommentOutFix implements IntentionAction { + private final PsiElement myElement; + + private CommentOutFix(final PsiElement element) { + myElement = element; + } + + @Override + @NotNull + public String getText() { + return COMMENT_OUT_QUICK_FIX; + } + + @Override + @NotNull + public String getFamilyName() { + return getText(); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return true; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (myElement != null && myElement.isValid()) { + commentOutDead(PsiTreeUtil.getParentOfType(myElement, PsiModifierListOwner.class)); + } + } + + @Override + public boolean startInWriteAction() { + return true; + } + } + private static void commentOutDead(PsiElement psiElement) { + PsiFile psiFile = psiElement.getContainingFile(); + + if (psiFile != null) { + Document doc = PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(psiFile); + if (doc != null) { + TextRange textRange = psiElement.getTextRange(); + String date = DateFormatUtil.formatDateTime(new Date()); + + int startOffset = textRange.getStartOffset(); + CharSequence chars = doc.getCharsSequence(); + while (CharArrayUtil.regionMatches(chars, startOffset, InspectionsBundle.message("inspection.dead.code.comment"))) { + int line = doc.getLineNumber(startOffset) + 1; + if (line < doc.getLineCount()) { + startOffset = doc.getLineStartOffset(line); + startOffset = CharArrayUtil.shiftForward(chars, startOffset, " \t"); + } + } + + int endOffset = textRange.getEndOffset(); + + int line1 = doc.getLineNumber(startOffset); + int line2 = doc.getLineNumber(endOffset - 1); + + if (line1 == line2) { + doc.insertString(startOffset, InspectionsBundle.message("inspection.dead.code.date.comment", date)); + } + else { + for (int i = line1; i <= line2; i++) { + doc.insertString(doc.getLineStartOffset(i), "//"); + } + + doc.insertString(doc.getLineStartOffset(Math.min(line2 + 1, doc.getLineCount() - 1)), + InspectionsBundle.message("inspection.dead.code.stop.comment", date)); + doc.insertString(doc.getLineStartOffset(line1), InspectionsBundle.message("inspection.dead.code.start.comment", date)); + } + } + } + } + + @NotNull + @Override + public InspectionNode createToolNode(@NotNull GlobalInspectionContextImpl context, + @NotNull InspectionNode node, + @NotNull InspectionRVContentProvider provider, + @NotNull InspectionTreeNode parentNode, + boolean showStructure) { + final EntryPointsNode entryPointsNode = new EntryPointsNode(getTool(), context); + InspectionToolWrapper dummyToolWrapper = entryPointsNode.getToolWrapper(); + InspectionToolPresentation presentation = context.getPresentation(dummyToolWrapper); + presentation.updateContent(); + provider.appendToolNodeContent(context, entryPointsNode, node, showStructure); + return entryPointsNode; + } + + @Override + public void initialize(@NotNull GlobalInspectionContextImpl context) { + super.initialize(context); + ((EntryPointsManagerImpl)getEntryPointsManager()).setAddNonJavaEntries(getTool().ADD_NONJAVA_TO_ENTRIES); + } + + @Override + public void updateContent() { + getTool().checkForReachables(); + myPackageContents = new HashMap>(); + getContext().getRefManager().iterate(new RefJavaVisitor() { + @Override public void visitElement(@NotNull RefEntity refEntity) { + if (!(refEntity instanceof RefJavaElement)) return;//dead code doesn't work with refModule | refPackage + RefJavaElement refElement = (RefJavaElement)refEntity; + if (!(getContext().getUIOptions().FILTER_RESOLVED_ITEMS && getIgnoredRefElements().contains(refElement)) && refElement.isValid() && getFilter().accepts(refElement)) { + String packageName = RefJavaUtil.getInstance().getPackageName(refEntity); + Set content = myPackageContents.get(packageName); + if (content == null) { + content = new HashSet(); + myPackageContents.put(packageName, content); + } + content.add(refEntity); + } + } + }); + } + + @Override + public boolean hasReportedProblems() { + final GlobalInspectionContextImpl context = getContext(); + if (context != null && context.getUIOptions().SHOW_ONLY_DIFF){ + return containsOnlyDiff(myPackageContents) || + myOldPackageContents != null && containsOnlyDiff(myOldPackageContents); + } + if (!myPackageContents.isEmpty()) return true; + return isOldProblemsIncluded() && !myOldPackageContents.isEmpty(); + } + + private boolean containsOnlyDiff(@NotNull Map> packageContents) { + for (String packageName : packageContents.keySet()) { + final Set refElements = packageContents.get(packageName); + if (refElements != null){ + for (RefEntity refElement : refElements) { + if (getElementStatus(refElement) != FileStatus.NOT_CHANGED){ + return true; + } + } + } + } + return false; + } + + @Override + public Map> getContent() { + return myPackageContents; + } + + @Override + public Map> getOldContent() { + return myOldPackageContents; + } + + @Override + public void ignoreCurrentElement(RefEntity refEntity) { + if (refEntity == null) return; + myIgnoreElements.add(refEntity); + } + + @Override + public void amnesty(RefEntity refEntity) { + myIgnoreElements.remove(refEntity); + } + + @Override + public void cleanup() { + super.cleanup(); + myOldPackageContents = null; + myPackageContents.clear(); + myIgnoreElements.clear(); + } + + + @Override + public void finalCleanup() { + super.finalCleanup(); + myOldPackageContents = null; + } + + @Override + public boolean isGraphNeeded() { + return true; + } + + @Override + public boolean isElementIgnored(final RefEntity element) { + for (RefEntity entity : myIgnoreElements) { + if (Comparing.equal(entity, element)) { + return true; + } + } + return false; + } + + + @NotNull + @Override + public FileStatus getElementStatus(final RefEntity element) { + final GlobalInspectionContextImpl context = getContext(); + if (context != null && context.getUIOptions().SHOW_DIFF_WITH_PREVIOUS_RUN){ + if (myOldPackageContents != null){ + final boolean old = RefUtil.contains(element, collectRefElements(myOldPackageContents)); + final boolean current = RefUtil.contains(element, collectRefElements(myPackageContents)); + return calcStatus(old, current); + } + return FileStatus.ADDED; + } + return FileStatus.NOT_CHANGED; + } + + @Override + @NotNull + public Collection getIgnoredRefElements() { + return myIgnoreElements; + } + + private static Set collectRefElements(Map> packageContents) { + Set allAvailable = new HashSet(); + for (Set elements : packageContents.values()) { + allAvailable.addAll(elements); + } + return allAvailable; + } + + @Override + @Nullable + public IntentionAction findQuickFixes(@NotNull final CommonProblemDescriptor descriptor, final String hint) { + if (descriptor instanceof ProblemDescriptor) { + if (DELETE.equals(hint)) { + return new PermanentDeleteFix(((ProblemDescriptor)descriptor).getPsiElement()); + } + if (COMMENT.equals(hint)) { + return new CommentOutFix(((ProblemDescriptor)descriptor).getPsiElement()); + } + } + return null; + } + + + private static class PermanentDeleteFix implements IntentionAction { + private final PsiElement myElement; + + private PermanentDeleteFix(final PsiElement element) { + myElement = element; + } + + @Override + @NotNull + public String getText() { + return DELETE_QUICK_FIX; + } + + @Override + @NotNull + public String getFamilyName() { + return getText(); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return true; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (myElement != null && myElement.isValid()) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + SafeDeleteHandler + .invoke(myElement.getProject(), new PsiElement[]{PsiTreeUtil.getParentOfType(myElement, PsiModifierListOwner.class)}, false); + } + }); + } + } + + @Override + public boolean startInWriteAction() { + return true; + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/FilteringInspectionTool.java b/java/java-impl/src/com/intellij/codeInspection/ex/FilteringInspectionTool.java deleted file mode 100644 index 71a49a4bed30..000000000000 --- a/java/java-impl/src/com/intellij/codeInspection/ex/FilteringInspectionTool.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2000-2009 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.codeInspection.ex; - -import com.intellij.codeInsight.daemon.HighlightDisplayKey; -import com.intellij.codeInspection.SuppressIntentionAction; -import com.intellij.codeInspection.SuppressManager; -import com.intellij.codeInspection.reference.RefEntity; -import com.intellij.codeInspection.reference.RefJavaElement; -import com.intellij.codeInspection.reference.RefJavaUtil; -import com.intellij.codeInspection.reference.RefJavaVisitor; -import com.intellij.codeInspection.util.RefFilter; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.vcs.FileStatus; -import com.intellij.util.containers.HashMap; -import com.intellij.util.containers.HashSet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -/** - * @author max - */ -public abstract class FilteringInspectionTool extends InspectionTool { - public abstract RefFilter getFilter(); - private Map> myPackageContents = new HashMap>(); - - private Map> myOldPackageContents = null; - - private final Set myIgnoreElements = new HashSet(); - - @Override - public void updateContent() { - myPackageContents = new HashMap>(); - getContext().getRefManager().iterate(new RefJavaVisitor() { - @Override public void visitElement(@NotNull RefEntity refEntity) { - if (!(refEntity instanceof RefJavaElement)) return;//dead code doesn't work with refModule | refPackage - RefJavaElement refElement = (RefJavaElement)refEntity; - if (!(getContext().getUIOptions().FILTER_RESOLVED_ITEMS && myIgnoreElements.contains(refElement)) && refElement.isValid() && getFilter().accepts(refElement)) { - String packageName = RefJavaUtil.getInstance().getPackageName(refEntity); - Set content = myPackageContents.get(packageName); - if (content == null) { - content = new HashSet(); - myPackageContents.put(packageName, content); - } - content.add(refEntity); - } - } - }); - } - - @Override - public boolean hasReportedProblems() { - final GlobalInspectionContextImpl context = getContext(); - if (context != null && context.getUIOptions().SHOW_ONLY_DIFF){ - return containsOnlyDiff(myPackageContents) || - myOldPackageContents != null && containsOnlyDiff(myOldPackageContents); - } - if (!myPackageContents.isEmpty()) return true; - return isOldProblemsIncluded() && !myOldPackageContents.isEmpty(); - } - - private boolean containsOnlyDiff(@NotNull Map> packageContents) { - for (String packageName : packageContents.keySet()) { - final Set refElements = packageContents.get(packageName); - if (refElements != null){ - for (RefEntity refElement : refElements) { - if (getElementStatus(refElement) != FileStatus.NOT_CHANGED){ - return true; - } - } - } - } - return false; - } - - @Override - public Map> getContent() { - return myPackageContents; - } - - @Override - public Map> getOldContent() { - return myOldPackageContents; - } - - @Override - public void ignoreCurrentElement(RefEntity refEntity) { - if (refEntity == null) return; - myIgnoreElements.add(refEntity); - } - - @Override - public void amnesty(RefEntity refEntity) { - myIgnoreElements.remove(refEntity); - } - - @Override - public void cleanup() { - super.cleanup(); - myOldPackageContents = null; - myPackageContents.clear(); - myIgnoreElements.clear(); - } - - - @Override - public void finalCleanup() { - super.finalCleanup(); - myOldPackageContents = null; - } - - @Override - public boolean isGraphNeeded() { - return true; - } - - @Override - public boolean isElementIgnored(final RefEntity element) { - for (RefEntity entity : myIgnoreElements) { - if (Comparing.equal(entity, element)) { - return true; - } - } - return false; - } - - - @NotNull - @Override - public FileStatus getElementStatus(final RefEntity element) { - final GlobalInspectionContextImpl context = getContext(); - if (context != null && context.getUIOptions().SHOW_DIFF_WITH_PREVIOUS_RUN){ - if (myOldPackageContents != null){ - final boolean old = contains(element, collectRefElements(myOldPackageContents)); - final boolean current = contains(element, collectRefElements(myPackageContents)); - return calcStatus(old, current); - } - return FileStatus.ADDED; - } - return FileStatus.NOT_CHANGED; - } - - @NotNull - @Override - public Collection getIgnoredRefElements() { - return myIgnoreElements; - } - - private static Set collectRefElements(Map> packageContents) { - Set allAvailable = new HashSet(); - for (Set elements : packageContents.values()) { - allAvailable.addAll(elements); - } - return allAvailable; - } - - @Override - @Nullable - public SuppressIntentionAction[] getSuppressActions() { - return SuppressManager.getInstance().createSuppressActions(HighlightDisplayKey.find(getShortName())); - } -} diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java index f3bdaf20aeea..6cd6599e452b 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java @@ -24,6 +24,7 @@ import com.intellij.CommonBundle; import com.intellij.analysis.AnalysisScope; import com.intellij.codeInspection.*; import com.intellij.codeInspection.reference.*; +import com.intellij.codeInspection.ui.InspectionToolPresentation; import com.intellij.lang.StdLanguages; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -67,8 +68,8 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext public void enqueueClassUsagesProcessor(RefClass refClass, UsagesProcessor p) { if (myClassUsagesRequests == null) myClassUsagesRequests = new THashMap>(); enqueueRequestImpl(refClass, myClassUsagesRequests, p); - } + } @Override public void enqueueDerivedClassesProcessor(RefClass refClass, DerivedClassesProcessor p) { if (myDerivedClassesRequests == null) myDerivedClassesRequests = new THashMap>(); @@ -421,17 +422,25 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext @Override - public void performPostRunActivities(@NotNull List needRepeatSearchRequest, @NotNull final GlobalInspectionContext context) { + public void performPostRunActivities(@NotNull List needRepeatSearchRequest, @NotNull final GlobalInspectionContext context) { JobDescriptor progress = context.getStdJobDescriptors().FIND_EXTERNAL_USAGES; progress.setTotalAmount(getRequestCount()); do { processSearchRequests(context); InspectionToolWrapper[] requestors = needRepeatSearchRequest.toArray(new InspectionToolWrapper[needRepeatSearchRequest.size()]); - for (InspectionToolWrapper wrapper : requestors) { - InspectionProfileEntry requestor = wrapper.getTool(); - if (requestor instanceof InspectionTool && !((InspectionTool)requestor).queryExternalUsagesRequests(InspectionManager.getInstance(context.getProject()))) { - needRepeatSearchRequest.remove(wrapper); + InspectionManager inspectionManager = InspectionManager.getInstance(context.getProject()); + for (InspectionToolWrapper toolWrapper : requestors) { + boolean result = false; + if (toolWrapper instanceof GlobalInspectionToolWrapper) { + InspectionToolPresentation presentation = ((GlobalInspectionContextImpl)context).getPresentation(toolWrapper); + result = ((GlobalInspectionToolWrapper)toolWrapper).getTool().queryExternalUsagesRequests(inspectionManager, context, presentation); + } + else if (toolWrapper instanceof CommonInspectionToolWrapper) { + result = ((CommonInspectionToolWrapper)toolWrapper).getTool().queryExternalUsagesRequests(inspectionManager); + } + if (!result) { + needRepeatSearchRequest.remove(toolWrapper); } } int oldSearchRequestCount = progress.getTotalAmount(); diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java index 66a4ec94a669..8ebd6ab6a87b 100644 --- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java @@ -110,7 +110,7 @@ public class RefJavaManagerImpl extends RefJavaManager { @Override protected Ref compute(PsiFile file, RefManagerImpl refManager) { Tools tools = ((GlobalInspectionContextImpl)refManager.getContext()).getTools().get(UnusedDeclarationInspection.SHORT_NAME); - InspectionToolWrapper toolWrapper = tools != null ? (InspectionToolWrapper)tools.getEnabledTool(file) : null; + InspectionToolWrapper toolWrapper = tools == null ? null : tools.getEnabledTool(file); InspectionProfileEntry tool = toolWrapper == null ? null : toolWrapper.getTool(); return Ref.create(tool instanceof UnusedDeclarationInspection ? (UnusedDeclarationInspection)tool : null); } diff --git a/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java b/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java index 51063602a763..78db5438a869 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java +++ b/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java @@ -17,6 +17,8 @@ package com.intellij.codeInspection.ui; import com.intellij.codeInspection.deadCode.DummyEntryPointsTool; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; +import com.intellij.codeInspection.ex.CommonInspectionToolWrapper; +import com.intellij.codeInspection.ex.GlobalInspectionContextImpl; import com.intellij.icons.AllIcons; import org.jetbrains.annotations.NotNull; @@ -26,9 +28,14 @@ import javax.swing.*; * @author max */ public class EntryPointsNode extends InspectionNode { - public EntryPointsNode(@NotNull UnusedDeclarationInspection tool) { - super(new DummyEntryPointsTool(tool)); - getTool().updateContent(); + public EntryPointsNode(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) { + super(createDummyWrapper(tool, context)); + } + + private static CommonInspectionToolWrapper createDummyWrapper(UnusedDeclarationInspection tool, GlobalInspectionContextImpl context) { + CommonInspectionToolWrapper wrapper = new CommonInspectionToolWrapper(new DummyEntryPointsTool()); + wrapper.initialize(context); + return wrapper; } @Override diff --git a/java/java-impl/src/com/intellij/profile/codeInspection/JavaAwareInspectionProfileManager.java b/java/java-impl/src/com/intellij/profile/codeInspection/JavaAwareInspectionProfileManager.java index e1d50a769090..e0cb4a029538 100644 --- a/java/java-impl/src/com/intellij/profile/codeInspection/JavaAwareInspectionProfileManager.java +++ b/java/java-impl/src/com/intellij/profile/codeInspection/JavaAwareInspectionProfileManager.java @@ -23,11 +23,12 @@ package com.intellij.profile.codeInspection; import com.intellij.codeInsight.daemon.InspectionProfileConvertor; import com.intellij.codeInsight.daemon.JavaAwareInspectionProfileCoverter; import com.intellij.codeInspection.ex.InspectionToolRegistrar; +import com.intellij.codeInspection.ex.SpecialToolsManager; import com.intellij.openapi.options.SchemesManagerFactory; public class JavaAwareInspectionProfileManager extends InspectionProfileManagerImpl { - public JavaAwareInspectionProfileManager(InspectionToolRegistrar registrar, SchemesManagerFactory schemesManagerFactory) { - super(registrar, schemesManagerFactory); + public JavaAwareInspectionProfileManager(InspectionToolRegistrar registrar, SchemesManagerFactory schemesManagerFactory, SpecialToolsManager specialToolsManager) { + super(registrar, schemesManagerFactory,specialToolsManager); } @Override diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/GlobalInspectionContextTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/GlobalInspectionContextTest.java index 803d325d8c3e..babdcff488a0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/GlobalInspectionContextTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/GlobalInspectionContextTest.java @@ -20,6 +20,7 @@ import com.intellij.analysis.AnalysisScope; import com.intellij.codeInsight.CodeInsightTestCase; import com.intellij.codeInspection.actions.RunInspectionIntention; import com.intellij.codeInspection.ex.*; +import com.intellij.codeInspection.ui.InspectionToolPresentation; import com.intellij.codeInspection.visibility.VisibilityInspection; import java.util.ArrayList; @@ -34,8 +35,8 @@ public class GlobalInspectionContextTest extends CodeInsightTestCase { public void testProblemDuplication() throws Exception { String shortName = new VisibilityInspection().getShortName(); InspectionProfileImpl profile = new InspectionProfileImpl("Foo"); - profile.disableAllTools(); - profile.enableTool(shortName); + profile.disableAllTools(getProject()); + profile.enableTool(shortName, getProject()); GlobalInspectionContextImpl context = ((InspectionManagerEx)InspectionManager.getInstance(getProject())).createNewGlobalContext(false); context.setExternalProfile(profile); @@ -45,18 +46,20 @@ public class GlobalInspectionContextTest extends CodeInsightTestCase { context.doInspections(scope, InspectionManager.getInstance(getProject())); Tools tools = context.getTools().get(shortName); - GlobalInspectionToolWrapper tool = (GlobalInspectionToolWrapper)tools.getTool(); - assertEquals(1, tool.getProblemDescriptors().size()); + GlobalInspectionToolWrapper toolWrapper = (GlobalInspectionToolWrapper)tools.getTool(); + InspectionToolPresentation presentation = context.getPresentation(toolWrapper); + assertEquals(1, presentation.getProblemDescriptors().size()); context.doInspections(scope, InspectionManager.getInstance(getProject())); tools = context.getTools().get(shortName); - tool = (GlobalInspectionToolWrapper)tools.getTool(); - assertEquals(1, tool.getProblemDescriptors().size()); + toolWrapper = (GlobalInspectionToolWrapper)tools.getTool(); + presentation = context.getPresentation(toolWrapper); + assertEquals(1, presentation.getProblemDescriptors().size()); } public void testRunInspectionContext() throws Exception { InspectionProfile profile = new InspectionProfileImpl("foo"); - InspectionToolWrapper[] tools = (InspectionToolWrapper[])profile.getInspectionTools(null); + InspectionToolWrapper[] tools = profile.getInspectionTools(null); for (InspectionToolWrapper toolWrapper : tools) { if (!toolWrapper.isEnabledByDefault()) { InspectionManagerEx instance = (InspectionManagerEx)InspectionManager.getInstance(myProject); diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java index a1630244c4d1..d0276c2fc3d0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java @@ -186,11 +186,10 @@ public class InspectionProfileTest extends LightIdeaTestCase { } public void testLockProfile() throws Exception { - final List list = new ArrayList(); list.add(createTool("foo", true)); - InspectionToolRegistrar registrar = new InspectionToolRegistrar(null) { + InspectionToolRegistrar registrar = new InspectionToolRegistrar() { @NotNull @Override public List createTools() { @@ -200,10 +199,10 @@ public class InspectionProfileTest extends LightIdeaTestCase { InspectionProfileImpl profile = createProfile(registrar); - List tools = profile.getAllTools(); + List tools = profile.getAllTools(getProject()); assertEquals(1, tools.size()); assertTrue(profile.isToolEnabled(HighlightDisplayKey.find("foo"))); - assertTrue(profile.getToolDefaultState("foo").isEnabled()); + assertTrue(profile.getToolDefaultState("foo", getProject()).isEnabled()); InspectionProfileImpl model = (InspectionProfileImpl)profile.getModifiableModel(); model.lockProfile(true); @@ -226,15 +225,15 @@ public class InspectionProfileTest extends LightIdeaTestCase { profile = createProfile(registrar); profile.readExternal(element); - tools = profile.getAllTools(); + tools = profile.getAllTools(getProject()); assertEquals(3, tools.size()); assertTrue(profile.isProfileLocked()); assertFalse(profile.isToolEnabled(HighlightDisplayKey.find("bar"))); assertFalse(profile.isToolEnabled(HighlightDisplayKey.find("disabled"))); - assertTrue(profile.getToolDefaultState("bar").isEnabled()); - assertFalse(profile.getToolDefaultState("disabled").isEnabled()); + assertTrue(profile.getToolDefaultState("bar", getProject()).isEnabled()); + assertFalse(profile.getToolDefaultState("disabled", getProject()).isEnabled()); assertEquals("\n" + "