diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java index 5d25ed43f1c2..d59acd8c23b4 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java @@ -105,13 +105,17 @@ public class UnusedLibrariesInspection extends GlobalInspectionTool { boolean allRootsUnused = usedRoots == null || !files.removeAll(usedRoots); if (allRootsUnused) { String message = InspectionsBundle.message("unused.library.problem.descriptor", entry.getPresentableName()); - result.add(manager.createProblemDescriptor(message, new RemoveUnusedLibrary(refModule, entry, null))); + result.add(manager.createProblemDescriptor(message, module, new RemoveUnusedLibrary(entry.getPresentableName(), null))); } else if (!files.isEmpty() && !IGNORE_LIBRARY_PARTS) { final String unusedLibraryRoots = StringUtil.join(files, file -> file.getPresentableName(), ","); String message = InspectionsBundle.message("unused.library.roots.problem.descriptor", unusedLibraryRoots, entry.getPresentableName()); - result.add(((LibraryOrderEntry)entry).isModuleLevel() ? manager.createProblemDescriptor(message, new RemoveUnusedLibrary(refModule, entry, files)) : manager.createProblemDescriptor(message)); + CommonProblemDescriptor descriptor = + ((LibraryOrderEntry)entry).isModuleLevel() + ? manager.createProblemDescriptor(message, module, new RemoveUnusedLibrary(entry.getPresentableName(), files)) + : manager.createProblemDescriptor(message); + result.add(descriptor); } } } @@ -213,14 +217,27 @@ public class UnusedLibrariesInspection extends GlobalInspectionTool { return "UnusedLibrary"; } - private static class RemoveUnusedLibrary implements QuickFix { - private final RefModule myRefModule; - private final OrderEntry myOrderEntry; - private final Set myFiles; + @Nullable + @Override + public QuickFix getQuickFix(String hint) { + return new RemoveUnusedLibrary(hint, null); + } - public RemoveUnusedLibrary(final RefModule refModule, final OrderEntry orderEntry, final Set files) { - myRefModule = refModule; - myOrderEntry = orderEntry; + @Nullable + @Override + public String getHint(@NotNull QuickFix fix) { + if (fix instanceof RemoveUnusedLibrary && ((RemoveUnusedLibrary)fix).myFiles == null) { + return ((RemoveUnusedLibrary)fix).myLibraryName; + } + return null; + } + + private static class RemoveUnusedLibrary implements QuickFix { + private final Set myFiles; + private String myLibraryName; + + public RemoveUnusedLibrary(String libraryName, final Set files) { + myLibraryName = libraryName; myFiles = files; } @@ -231,12 +248,12 @@ public class UnusedLibrariesInspection extends GlobalInspectionTool { } @Override - public void applyFix(@NotNull final Project project, @NotNull final CommonProblemDescriptor descriptor) { - final Module module = myRefModule.getModule(); + public void applyFix(@NotNull final Project project, @NotNull final ModuleProblemDescriptor descriptor) { + final Module module = descriptor.getModule(); final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); for (OrderEntry entry : model.getOrderEntries()) { - if (entry instanceof LibraryOrderEntry && Comparing.strEqual(entry.getPresentableName(), myOrderEntry.getPresentableName())) { + if (entry instanceof LibraryOrderEntry && Comparing.strEqual(entry.getPresentableName(), myLibraryName)) { if (myFiles == null) { model.removeOrderEntry(entry); } diff --git a/platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java b/platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java index 81deb2dc9dc8..82593624717a 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/InspectionManager.java @@ -17,6 +17,7 @@ package com.intellij.codeInspection; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.TextRange; @@ -43,6 +44,10 @@ public abstract class InspectionManager { @Contract(pure = true) public abstract CommonProblemDescriptor createProblemDescriptor(@NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String descriptionTemplate, QuickFix... fixes); + @NotNull + @Contract(pure = true) + public abstract ModuleProblemDescriptor createProblemDescriptor(@NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String descriptionTemplate, Module module, QuickFix... fixes); + /** * Factory method for ProblemDescriptor. Should be called from LocalInspectionTool.checkXXX() methods. * @param psiElement problem is reported against diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ModuleProblemDescriptor.java b/platform/analysis-api/src/com/intellij/codeInspection/ModuleProblemDescriptor.java new file mode 100644 index 000000000000..3548cd0ccd67 --- /dev/null +++ b/platform/analysis-api/src/com/intellij/codeInspection/ModuleProblemDescriptor.java @@ -0,0 +1,22 @@ +/* + * 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.codeInspection; + +import com.intellij.openapi.module.Module; + +public interface ModuleProblemDescriptor extends CommonProblemDescriptor { + Module getModule(); +} diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/InspectionManagerBase.java b/platform/analysis-impl/src/com/intellij/codeInspection/InspectionManagerBase.java index 68dcab432fb4..291db3525e2d 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/InspectionManagerBase.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/InspectionManagerBase.java @@ -15,11 +15,13 @@ */ package com.intellij.codeInspection; +import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.ProjectInspectionProfileManager; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -43,6 +45,12 @@ public abstract class InspectionManagerBase extends InspectionManager { return new CommonProblemDescriptorImpl(fixes, descriptionTemplate); } + @NotNull + @Override + public ModuleProblemDescriptor createProblemDescriptor(@Nls @NotNull String descriptionTemplate, Module module, QuickFix... fixes) { + return new ModuleProblemDescriptorImpl(fixes, descriptionTemplate, module); + } + @Override @NotNull public ProblemDescriptor createProblemDescriptor(@NotNull PsiElement psiElement, diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ModuleProblemDescriptorImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ModuleProblemDescriptorImpl.java new file mode 100644 index 000000000000..5908ca5d8cfc --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ModuleProblemDescriptorImpl.java @@ -0,0 +1,33 @@ +/* + * 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.codeInspection; + +import com.intellij.openapi.module.Module; +import org.jetbrains.annotations.NotNull; + +public class ModuleProblemDescriptorImpl extends CommonProblemDescriptorImpl implements ModuleProblemDescriptor { + private final Module myModule; + + public ModuleProblemDescriptorImpl(QuickFix[] fixes, @NotNull String descriptionTemplate, Module module) { + super(fixes, descriptionTemplate); + myModule = module; + } + + @Override + public Module getModule() { + return myModule; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java index 880b492c8d42..6354fbd9551b 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineDescriptorResolveResult.java @@ -28,6 +28,7 @@ import com.intellij.codeInspection.ex.QuickFixWrapper; import com.intellij.codeInspection.offline.OfflineProblemDescriptor; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefEntity; +import com.intellij.codeInspection.reference.RefModule; import com.intellij.codeInspection.ui.InspectionToolPresentation; import com.intellij.lang.Language; import com.intellij.openapi.application.ReadAction; @@ -38,6 +39,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtilCore; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,6 +48,7 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; /** * @author Dmitry Batkovich @@ -197,7 +200,9 @@ class OfflineDescriptorResolveResult { private static CommonProblemDescriptor createRerunGlobalToolDescriptor(@NotNull GlobalInspectionToolWrapper wrapper, @Nullable RefEntity entity, OfflineProblemDescriptor offlineDescriptor) { - return new CommonProblemDescriptorImpl(new QuickFix[]{new QuickFix() { + + + QuickFix rerunFix = new QuickFix() { @Nls @NotNull @Override @@ -217,6 +222,13 @@ class OfflineDescriptorResolveResult { } RunInspectionAction.runInspection(project, wrapper.getShortName(), file, null, psiFile); } - }}, offlineDescriptor.getDescription()); + }; + List hints = offlineDescriptor.getHints(); + if (hints != null && entity instanceof RefModule) { + List fixes = + hints.stream().map(hint -> wrapper.getTool().getQuickFix(hint)).filter(f -> f != null).collect(Collectors.toList()); + return new ModuleProblemDescriptorImpl(ArrayUtil.append(fixes.toArray(QuickFix.EMPTY_ARRAY), rerunFix), offlineDescriptor.getDescription(), ((RefModule)entity).getModule()); + } + return new CommonProblemDescriptorImpl(new QuickFix[]{rerunFix}, offlineDescriptor.getDescription()); } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java index 9fa4b0d2cae9..24ebf01ce190 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java @@ -88,7 +88,10 @@ public class DefaultInspectionToolPresentation implements InspectionToolPresenta } public void resolveProblem(@NotNull CommonProblemDescriptor descriptor) { - myResolvedElements.put(myProblemElements.removeValue(descriptor), descriptor); + RefEntity entity = myProblemElements.removeValue(descriptor); + if (entity != null) { + myResolvedElements.put(entity, descriptor); + } } public boolean isProblemResolved(@Nullable CommonProblemDescriptor descriptor) {