project configuration: suggest to remove obsolete library files

When a library is converted to a repository library its JAR files may become obsolete so IDEA suggests to remove them.
This commit is contained in:
nik
2017-11-27 12:52:47 +03:00
parent 827b8594b2
commit f481f3e845
3 changed files with 57 additions and 0 deletions
@@ -0,0 +1,44 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.roots.ui.configuration
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectFileIndex
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import java.util.*
/**
* @author nik
*/
class ObsoleteLibraryFilesRemover(private val project: Project) {
private val oldRoots = LinkedHashSet<VirtualFile>()
fun registerObsoleteLibraryRoots(roots: Collection<VirtualFile>) {
oldRoots += roots
}
fun deleteFiles() {
val index = ProjectFileIndex.getInstance(project)
//do not suggest to delete library files located outside project roots: they may be used in other projects or aren't stored in VCS
val toDelete = oldRoots.filter { it.isValid && !index.isInLibrary(it) && index.isInContent(VfsUtil.getLocalFile(it)) }
oldRoots.clear()
if (toDelete.isNotEmpty()) {
val many = toDelete.size > 1
if (Messages.showYesNoDialog(project, "The following ${if (many) "files aren't" else "file isn't"} used anymore:\n" +
"${toDelete.joinToString("\n") { it.presentableUrl }}\n" +
"Do you want to delete ${if (many) "them" else "it"}?\n" +
"You might not be able to fully undo this operation!",
"Delete Unused Files", null) == Messages.YES) {
runWriteAction {
toDelete.forEach {
VfsUtil.getLocalFile(it).delete(this)
}
}
}
}
}
}
@@ -43,6 +43,7 @@ import com.intellij.openapi.ui.DetailsComponent;
import com.intellij.openapi.ui.MasterDetailsComponent;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.ui.JBSplitter;
@@ -63,6 +64,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurableFilter.ConfigurableId;
@@ -115,6 +117,8 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
private final JLabel myEmptySelection = new JLabel("<html><body><center>Select a setting to view or edit its details here</center></body></html>",
SwingConstants.CENTER);
private final ObsoleteLibraryFilesRemover myObsoleteLibraryFilesRemover;
public ProjectStructureConfigurable(final Project project,
final ProjectLibrariesConfigurable projectLibrariesConfigurable,
final GlobalLibrariesConfigurable globalLibrariesConfigurable,
@@ -147,6 +151,7 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
myUiState.proportion = proportion != null ? Float.parseFloat(proportion) : 0;
final String sideProportion = propertiesComponent.getValue("project.structure.side.proportion");
myUiState.sideProportion = sideProportion != null ? Float.parseFloat(sideProportion) : 0;
myObsoleteLibraryFilesRemover = new ObsoleteLibraryFilesRemover(project);
}
@Override
@@ -336,6 +341,7 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
throw exceptionRef.get();
}
myObsoleteLibraryFilesRemover.deleteFiles();
myContext.getDaemonAnalyzer().clearCaches();
BuildManager.getInstance().scheduleAutoMake();
}
@@ -611,6 +617,10 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
return myProjectConfig;
}
public void registerObsoleteLibraryRoots(@NotNull Collection<VirtualFile> roots) {
myObsoleteLibraryFilesRemover.registerObsoleteLibraryRoots(roots);
}
private void addConfigurable(Configurable configurable, boolean addToSidePanel) {
myName2Config.add(configurable);
@@ -36,6 +36,7 @@ import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.roots.libraries.LibraryUtil
import com.intellij.openapi.roots.libraries.NewLibraryConfiguration
import com.intellij.openapi.roots.libraries.ui.OrderRoot
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable
import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditor
import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditorBase
import com.intellij.openapi.ui.DialogWrapper
@@ -155,6 +156,8 @@ abstract class ConvertToRepositoryLibraryActionBase(protected val context: Struc
private fun replaceByLibrary(library: Library, configuration: NewLibraryConfiguration) {
val annotationUrls = library.getUrls(AnnotationOrderRootType.getInstance())
ProjectStructureConfigurable.getInstance(project).registerObsoleteLibraryRoots((library.getFiles(OrderRootType.CLASSES) +
library.getFiles(OrderRootType.SOURCES)).asList())
replaceLibrary(library) { editor ->
editor.properties = configuration.properties
editor.removeAllRoots()