diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ObsoleteLibraryFilesRemover.kt b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ObsoleteLibraryFilesRemover.kt new file mode 100644 index 000000000000..08df1e3aae02 --- /dev/null +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ObsoleteLibraryFilesRemover.kt @@ -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() + + fun registerObsoleteLibraryRoots(roots: Collection) { + 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) + } + } + } + } + + } +} \ No newline at end of file diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java index e77353f4b6fa..fade3c4d9689 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java @@ -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("
Select a setting to view or edit its details here
", 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 roots) { + myObsoleteLibraryFilesRemover.registerObsoleteLibraryRoots(roots); + } + private void addConfigurable(Configurable configurable, boolean addToSidePanel) { myName2Config.add(configurable); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionBase.kt b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionBase.kt index 97abbc40d920..3454abf24a98 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionBase.kt +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionBase.kt @@ -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()