diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java index 6223bc5b0da5..079b111a0b22 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java @@ -40,6 +40,7 @@ import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable; import com.intellij.openapi.roots.ui.configuration.dependencyAnalysis.AnalyzeDependenciesDialog; import com.intellij.openapi.roots.ui.configuration.libraries.LibraryEditingUtil; import com.intellij.openapi.roots.ui.configuration.libraryEditor.EditExistingLibraryDialog; +import com.intellij.openapi.roots.ui.configuration.projectRoot.ConvertModuleLibraryToRepositoryLibraryAction; import com.intellij.openapi.roots.ui.configuration.projectRoot.FindUsagesInProjectStructureActionBase; import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureConfigurable; import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext; @@ -288,6 +289,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { addChangeLibraryLevelAction(actionGroup, LibraryTablesRegistrar.PROJECT_LEVEL); addChangeLibraryLevelAction(actionGroup, LibraryTablesRegistrar.APPLICATION_LEVEL); addChangeLibraryLevelAction(actionGroup, LibraryTableImplUtil.MODULE_LEVEL); + actionGroup.add(new ConvertModuleLibraryToRepositoryLibraryAction(this, getStructureConfigurableContext())); PopupHandler.installPopupHandler(myEntryTable, actionGroup, ActionPlaces.UNKNOWN, ActionManager.getInstance()); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertModuleLibraryToRepositoryLibraryAction.kt b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertModuleLibraryToRepositoryLibraryAction.kt new file mode 100644 index 000000000000..cdea9c98d8c8 --- /dev/null +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertModuleLibraryToRepositoryLibraryAction.kt @@ -0,0 +1,51 @@ +/* + * 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.openapi.roots.ui.configuration.projectRoot + +import com.intellij.jarRepository.RepositoryLibraryType +import com.intellij.openapi.roots.LibraryOrderEntry +import com.intellij.openapi.roots.impl.OrderEntryUtil +import com.intellij.openapi.roots.impl.libraries.LibraryEx +import com.intellij.openapi.roots.impl.libraries.LibraryTableImplUtil +import com.intellij.openapi.roots.libraries.Library +import com.intellij.openapi.roots.ui.configuration.classpath.ClasspathPanel +import com.intellij.openapi.roots.ui.configuration.libraryEditor.ExistingLibraryEditor +import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditorBase + +/** + * @author nik + */ +class ConvertModuleLibraryToRepositoryLibraryAction(private val classpathPanel: ClasspathPanel, + context: StructureConfigurableContext) + : ConvertToRepositoryLibraryActionBase(context) { + + override fun getSelectedLibrary(): LibraryEx? { + val entry = classpathPanel.selectedEntry as? LibraryOrderEntry + if (entry == null || !entry.isModuleLevel) return null + return entry.library as? LibraryEx + } + + override fun replaceLibrary(library: Library, configureNewLibrary: (LibraryEditorBase) -> Unit) { + val name = library.name + val modifiableModel = classpathPanel.getModifiableModelProvider(LibraryTableImplUtil.MODULE_LEVEL).modifiableModel + val newLibrary = modifiableModel.createLibrary(name, RepositoryLibraryType.getInstance().kind, null) + OrderEntryUtil.replaceLibraryEntryByAdded(classpathPanel.rootModel, classpathPanel.rootModel.findLibraryOrderEntry(library)!!) + + val editor = ExistingLibraryEditor(newLibrary, null) + configureNewLibrary(editor) + editor.commit() + } +} \ No newline at end of file diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertProjectLibraryToRepositoryLibraryAction.kt b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertProjectLibraryToRepositoryLibraryAction.kt new file mode 100644 index 000000000000..6c244ab4babc --- /dev/null +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertProjectLibraryToRepositoryLibraryAction.kt @@ -0,0 +1,47 @@ +/* + * 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.openapi.roots.ui.configuration.projectRoot + +import com.intellij.jarRepository.RepositoryLibraryType +import com.intellij.openapi.roots.impl.libraries.LibraryEx +import com.intellij.openapi.roots.libraries.Library +import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable +import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditorBase +import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.LibraryProjectStructureElement + +/** + * @author nik + */ +class ConvertProjectLibraryToRepositoryLibraryAction(private val librariesConfigurable: BaseLibrariesConfigurable, + context: StructureConfigurableContext) + : ConvertToRepositoryLibraryActionBase(context) { + + override fun getSelectedLibrary() = (librariesConfigurable.selectedElement as? LibraryProjectStructureElement)?.library as? LibraryEx + + override fun replaceLibrary(library: Library, configureNewLibrary: (LibraryEditorBase) -> Unit) { + val name = library.name + val modifiableModel = librariesConfigurable.modelProvider.modifiableModel + + val usages = context.daemonAnalyzer.getUsages(LibraryProjectStructureElement(context, library)) + modifiableModel.removeLibrary(library) + val newLibrary = modifiableModel.createLibrary(name, RepositoryLibraryType.getInstance().kind, null) + usages.forEach { it.replaceElement(LibraryProjectStructureElement(context, newLibrary)) } + + val editor = modifiableModel.getLibraryEditor(newLibrary) + configureNewLibrary(editor) + ProjectStructureConfigurable.getInstance(project).selectProjectOrGlobalLibrary(newLibrary, true) + } +} \ No newline at end of file diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryAction.kt b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionBase.kt similarity index 87% rename from java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryAction.kt rename to java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionBase.kt index 4fb194ebe046..ce9d441b3b69 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryAction.kt +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionBase.kt @@ -32,10 +32,12 @@ import com.intellij.openapi.roots.AnnotationOrderRootType import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.impl.libraries.LibraryEx 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.roots.ui.configuration.projectRoot.daemon.LibraryProjectStructureElement import com.intellij.openapi.ui.Messages import com.intellij.openapi.util.io.FileUtil @@ -55,20 +57,23 @@ import java.util.* /** * @author nik */ -private val LOG = logger() +private val LOG = logger() -class ConvertToRepositoryLibraryAction(private val librariesConfigurable: BaseLibrariesConfigurable, private val project: Project) : DumbAwareAction( +abstract class ConvertToRepositoryLibraryActionBase(protected val context: StructureConfigurableContext) : DumbAwareAction( "Convert to Repository Library...", "Convert a regular library to a repository library which additionally stores its Maven coordinates, so the IDE can automatically download the library JARs if they are missing", null) { + protected val project = context.project + + protected abstract fun getSelectedLibrary(): LibraryEx? override fun update(e: AnActionEvent) { - val library = (librariesConfigurable.selectedElement as? LibraryProjectStructureElement)?.library as? LibraryEx + val library = getSelectedLibrary() e.presentation.isEnabledAndVisible = library != null && library.kind == null } override fun actionPerformed(e: AnActionEvent) { - val library = (librariesConfigurable.selectedElement as LibraryProjectStructureElement).library + val library = getSelectedLibrary() ?: return val mavenCoordinates = detectOrSpecifyMavenCoordinates(library) ?: return val libraryProperties = RepositoryLibraryProperties(mavenCoordinates.groupId, mavenCoordinates.artifactId, mavenCoordinates.version) @@ -85,14 +90,14 @@ class ConvertToRepositoryLibraryAction(private val librariesConfigurable: BaseLi if (task.cancelled) return if (!task.filesAreTheSame) { - val ok = LibraryJarsDiffDialog(task.libraryFileToCompare!!, task.downloadedFileToCompare!!, mavenCoordinates, library.name!!, project).showAndGet() + val ok = LibraryJarsDiffDialog(task.libraryFileToCompare!!, task.downloadedFileToCompare!!, mavenCoordinates, LibraryUtil.getPresentableName(library), project).showAndGet() task.deleteTemporaryFiles() if (!ok) { return } } ApplicationManager.getApplication().invokeLater { - replaceByLibrary(library, object : NewLibraryConfiguration(library.name!!, RepositoryLibraryType.getInstance(), libraryProperties) { + replaceByLibrary(library, object : NewLibraryConfiguration(library.name ?: "", RepositoryLibraryType.getInstance(), libraryProperties) { override fun addRoots(editor: LibraryEditor) { editor.addRoots(roots) } @@ -102,7 +107,7 @@ class ConvertToRepositoryLibraryAction(private val librariesConfigurable: BaseLi private fun detectOrSpecifyMavenCoordinates(library: Library): JpsMavenRepositoryLibraryDescriptor? { val detectedCoordinates = detectMavenCoordinates(library.getFiles(OrderRootType.CLASSES)) - LOG.debug("Maven coordinates for ${library.name} JARs: $detectedCoordinates") + LOG.debug("Maven coordinates for ${LibraryUtil.getPresentableName(library)} JARs: $detectedCoordinates") if (detectedCoordinates.size == 1) { return detectedCoordinates[0] } @@ -120,23 +125,16 @@ class ConvertToRepositoryLibraryAction(private val librariesConfigurable: BaseLi private fun replaceByLibrary(library: Library, configuration: NewLibraryConfiguration) { val annotationUrls = library.getUrls(AnnotationOrderRootType.getInstance()) - val name = library.name - val modifiableModel = librariesConfigurable.modelProvider.modifiableModel - val context = librariesConfigurable.myContext - - val usages = context.daemonAnalyzer.getUsages(LibraryProjectStructureElement(context, library)) - modifiableModel.removeLibrary(library) - val newLibrary = modifiableModel.createLibrary(name, RepositoryLibraryType.getInstance().kind, null) - usages.forEach { it.replaceElement(LibraryProjectStructureElement(context, newLibrary)) } - - val editor = modifiableModel.getLibraryEditor(newLibrary) - editor.properties = configuration.properties - editor.removeAllRoots() - configuration.addRoots(editor) - annotationUrls.forEach { editor.addRoot(it, AnnotationOrderRootType.getInstance()) } - ProjectStructureConfigurable.getInstance(project).selectProjectOrGlobalLibrary(newLibrary, true) + replaceLibrary(library) { editor -> + editor.properties = configuration.properties + editor.removeAllRoots() + configuration.addRoots(editor) + annotationUrls.forEach { editor.addRoot(it, AnnotationOrderRootType.getInstance()) } + } } + protected abstract fun replaceLibrary(library: Library, configureNewLibrary: (LibraryEditorBase) -> Unit) + companion object { fun detectMavenCoordinates(libraryRoots: Array): List = libraryRoots.flatMap { root -> diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectLibrariesConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectLibrariesConfigurable.java index f7738c333621..83b8b54125d0 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectLibrariesConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectLibrariesConfigurable.java @@ -77,7 +77,7 @@ public class ProjectLibrariesConfigurable extends BaseLibrariesConfigurable { protected List createCopyActions(boolean fromPopup) { List actions = super.createCopyActions(fromPopup); if (fromPopup) { - return ContainerUtil.concat(actions, Collections.singletonList(new ConvertToRepositoryLibraryAction(this, myProject))); + return ContainerUtil.concat(actions, Collections.singletonList(new ConvertProjectLibraryToRepositoryLibraryAction(this, myContext))); } return actions; } diff --git a/java/idea-ui/testSrc/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionTest.kt b/java/idea-ui/testSrc/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionTest.kt index 2ac2cba49696..80657c7ef4ad 100644 --- a/java/idea-ui/testSrc/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionTest.kt +++ b/java/idea-ui/testSrc/com/intellij/openapi/roots/ui/configuration/projectRoot/ConvertToRepositoryLibraryActionTest.kt @@ -16,13 +16,9 @@ package com.intellij.openapi.roots.ui.configuration.projectRoot import com.intellij.openapi.application.PathManager -import com.intellij.openapi.projectRoots.ex.JavaSdkUtil -import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.testFramework.LightPlatformTestCase -import junit.framework.TestCase -import java.io.File /** * @author nik @@ -32,7 +28,7 @@ class ConvertToRepositoryLibraryActionTest : LightPlatformTestCase() { val jarFile = PathManager.findFileInLibDirectory("commons-codec-1.9.jar") val file = VirtualFileManager.getInstance().refreshAndFindFileByUrl(VfsUtil.getUrlForLibraryRoot(jarFile)) assertNotNull(jarFile.absolutePath, file) - val coordinates = assertOneElement(ConvertToRepositoryLibraryAction.detectMavenCoordinates(arrayOf(file!!))) + val coordinates = assertOneElement(ConvertToRepositoryLibraryActionBase.detectMavenCoordinates(arrayOf(file!!))) assertEquals("commons-codec", coordinates.groupId) assertEquals("commons-codec", coordinates.artifactId) assertEquals("1.9", coordinates.version)