replace references in modules and artifacts when project or global library level is changed (IDEA-34285)

This commit is contained in:
nik
2011-07-06 13:19:32 +04:00
parent 16b181532d
commit 125302a9a4
9 changed files with 118 additions and 39 deletions
@@ -40,6 +40,8 @@ public interface ArtifactEditorEx extends ArtifactEditor, Disposable {
void removePackagingElement(@NotNull String pathToParent, @NotNull PackagingElement<?> element);
void replacePackagingElement(@NotNull String pathToParent, @NotNull PackagingElement<?> element, @NotNull PackagingElement<?> replacement);
LayoutTreeComponent getLayoutTreeComponent();
Artifact getArtifact();
@@ -365,6 +365,17 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
@Override
public void removePackagingElement(@NotNull final String pathToParent, @NotNull final PackagingElement<?> element) {
doReplaceElement(pathToParent, element, null);
}
@Override
public void replacePackagingElement(@NotNull final String pathToParent,
@NotNull final PackagingElement<?> element,
@NotNull final PackagingElement<?> replacement) {
doReplaceElement(pathToParent, element, replacement);
}
private void doReplaceElement(final @NotNull String pathToParent, final @NotNull PackagingElement<?> element, final @Nullable PackagingElement replacement) {
myLayoutTreeComponent.editLayout(new Runnable() {
@Override
public void run() {
@@ -373,6 +384,9 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
for (PackagingElement<?> child : parent.getChildren()) {
if (child.isEqualTo(element)) {
parent.removeChild(child);
if (replacement != null) {
parent.addOrFindChild(replacement);
}
break;
}
}
@@ -52,10 +52,17 @@ public class UsageInArtifact extends ProjectStructureElementUsage {
}
public void removeElement() {
final ArtifactEditorEx editor = (ArtifactEditorEx)myContext.getOrCreateEditor(myOriginalArtifact);
editor.removePackagingElement(myParentPath, myPackagingElement);
getOrCreateEditor().removePackagingElement(myParentPath, myPackagingElement);
}
private ArtifactEditorEx getOrCreateEditor() {
return (ArtifactEditorEx)myContext.getOrCreateEditor(myOriginalArtifact);
}
public void replaceElement(PackagingElement<?> replacement) {
getOrCreateEditor().replacePackagingElement(myParentPath, myPackagingElement, replacement);
}
@Override
public String getPresentableName() {
return myOriginalArtifact.getName();
@@ -57,27 +57,27 @@ public abstract class ChangeLibraryLevelActionBase extends AnAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.ui.configuration.classpath.ChangeLibraryLevelActionBase");
protected final Project myProject;
protected final String myTargetTableLevel;
protected final boolean myCopy;
public ChangeLibraryLevelActionBase(@NotNull Project project, @NotNull String targetTableName, @NotNull String targetTableLevel) {
public ChangeLibraryLevelActionBase(@NotNull Project project, @NotNull String targetTableName, @NotNull String targetTableLevel, boolean copy) {
myProject = project;
myTargetTableLevel = targetTableLevel;
myCopy = copy;
getTemplatePresentation().setText(getActionName() + " to " + targetTableName + "...");
}
protected abstract boolean isCopy();
protected abstract LibraryTableModifiableModelProvider getModifiableTableModelProvider();
protected abstract JComponent getParentComponent();
@Nullable
protected Library doAction(LibraryEx library) {
protected Library doCopy(LibraryEx library) {
final VirtualFile baseDir = getBaseDir();
final String libPath = baseDir != null ? baseDir.getPath() + "/lib" : "";
boolean allowEmptyName = isConvertingToModuleLibrary() && library.getFiles(OrderRootType.CLASSES).length == 1;
final String libraryName = allowEmptyName ? "" : StringUtil.notNullize(library.getName(), "Unnamed");
final LibraryTableModifiableModelProvider provider = getModifiableTableModelProvider();
final ChangeLibraryLevelDialog dialog = new ChangeLibraryLevelDialog(getParentComponent(), myProject, isCopy(),
final ChangeLibraryLevelDialog dialog = new ChangeLibraryLevelDialog(getParentComponent(), myProject, myCopy,
libraryName, libPath, allowEmptyName, provider);
dialog.show();
if (!dialog.isOK()) {
@@ -115,9 +115,8 @@ public abstract class ChangeLibraryLevelActionBase extends AnAction {
private boolean copyOrMoveFiles(final Set<File> filesToProcess,
@NotNull final String targetDirPath,
final Map<String, String> copiedFiles) {
final boolean copy = isCopy();
final Ref<Boolean> finished = Ref.create(false);
new Task.Modal(myProject, (copy ? "Copying" : "Moving") + " Library Files", true) {
new Task.Modal(myProject, (myCopy ? "Copying" : "Moving") + " Library Files", true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
final File targetDir = new File(FileUtil.toSystemDependentName(targetDirPath));
@@ -127,7 +126,7 @@ public abstract class ChangeLibraryLevelActionBase extends AnAction {
FileUtil.getExtension(from.getName()));
try {
if (from.isDirectory()) {
if (copy) {
if (myCopy) {
FileUtil.copyDir(from, to);
}
else {
@@ -135,7 +134,7 @@ public abstract class ChangeLibraryLevelActionBase extends AnAction {
}
}
else {
if (copy) {
if (myCopy) {
FileUtil.copy(from, to);
}
else {
@@ -158,7 +157,7 @@ public abstract class ChangeLibraryLevelActionBase extends AnAction {
if (virtualTo != null) {
copiedFiles.put(FileUtil.toSystemIndependentName(from.getAbsolutePath()), virtualTo.getPath());
}
if (!copy) {
if (!myCopy) {
final VirtualFile parent = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(from.getParentFile());
if (parent != null) {
parent.refresh(false, false);
@@ -185,7 +184,7 @@ public abstract class ChangeLibraryLevelActionBase extends AnAction {
}
private String getActionName() {
return isCopy() ? "Copy" : "Move";
return myCopy ? "Copy" : "Move";
}
@Nullable
@@ -19,6 +19,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.OrderEntry;
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.LibraryTableModifiableModelProvider;
import com.intellij.openapi.vfs.VirtualFile;
@@ -34,7 +35,7 @@ class ChangeLibraryLevelInClasspathAction extends ChangeLibraryLevelActionBase {
private final ClasspathPanel myPanel;
public ChangeLibraryLevelInClasspathAction(@NotNull ClasspathPanel panel, final @NotNull String targetTableName, @NotNull String targetTableLevel) {
super(panel.getProject(), targetTableName, targetTableLevel);
super(panel.getProject(), targetTableName, targetTableLevel, targetTableLevel.equals(LibraryTableImplUtil.MODULE_LEVEL));
myPanel = panel;
}
@@ -45,7 +46,7 @@ class ChangeLibraryLevelInClasspathAction extends ChangeLibraryLevelActionBase {
final LibraryEx library = (LibraryEx)((LibraryOrderEntry)entry).getLibrary();
if (library == null) return;
final Library copied = doAction(library);
final Library copied = doCopy(library);
if (copied == null) return;
myPanel.getRootModel().removeOrderEntry(entry);
@@ -79,11 +80,6 @@ class ChangeLibraryLevelInClasspathAction extends ChangeLibraryLevelActionBase {
return myPanel.getComponent();
}
@Override
protected boolean isCopy() {
return isConvertingToModuleLibrary();
}
@Override
@Nullable
protected VirtualFile getBaseDir() {
@@ -30,10 +30,7 @@ import com.intellij.openapi.roots.ui.configuration.artifacts.UsageInArtifact;
import com.intellij.openapi.roots.ui.configuration.libraries.LibraryEditingUtil;
import com.intellij.openapi.roots.ui.configuration.libraryEditor.CreateNewLibraryAction;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.*;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.ui.NonEmptyInputValidator;
import com.intellij.openapi.ui.*;
import com.intellij.openapi.util.Comparing;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NonNls;
@@ -208,6 +205,13 @@ public abstract class BaseLibrariesConfigurable extends BaseStructureConfigurabl
}
}
public void removeLibraryNode(@NotNull Library library) {
final MyNode node = findNodeByObject(myRoot, library);
if (node != null) {
removePaths(TreeUtil.getPathFromRoot(node));
}
}
protected boolean removeLibrary(final Library library) {
final LibraryTable table = library.getTable();
if (table != null) {
@@ -17,13 +17,25 @@ package com.intellij.openapi.roots.ui.configuration.projectRoot;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.impl.OrderEntryUtil;
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.LibraryTableModifiableModelProvider;
import com.intellij.openapi.roots.ui.configuration.ModuleEditor;
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.roots.ui.configuration.artifacts.UsageInArtifact;
import com.intellij.openapi.roots.ui.configuration.classpath.ChangeLibraryLevelActionBase;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.*;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.elements.PackagingElementFactory;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Collection;
/**
* @author nik
@@ -37,7 +49,8 @@ public class ChangeLibraryLevelAction extends ChangeLibraryLevelActionBase {
public ChangeLibraryLevelAction(@NotNull Project project, @NotNull JComponent parentComponent,
@NotNull BaseLibrariesConfigurable sourceConfigurable,
@NotNull BaseLibrariesConfigurable targetConfigurable) {
super(project, targetConfigurable.getLibraryTablePresentation().getDisplayName(true), targetConfigurable.getLevel());
super(project, targetConfigurable.getLibraryTablePresentation().getDisplayName(true), targetConfigurable.getLevel(),
sourceConfigurable instanceof GlobalLibrariesConfigurable);
myParentComponent = parentComponent;
mySourceConfigurable = sourceConfigurable;
myTargetConfigurable = targetConfigurable;
@@ -45,22 +58,45 @@ public class ChangeLibraryLevelAction extends ChangeLibraryLevelActionBase {
@Override
public void actionPerformed(AnActionEvent e) {
final Object selected = mySourceConfigurable.getSelectedObject();
if (!(selected instanceof LibraryEx)) return;
final LibraryEx library = (LibraryEx)selected;
final LibraryEx actualLibrary = (LibraryEx)mySourceConfigurable.myContext.getLibrary(library.getName(), mySourceConfigurable.getLevel());
LOG.assertTrue(actualLibrary != null);
doAction(library);
final ProjectStructureElement selectedElement = mySourceConfigurable.getSelectedElement();
if (!(selectedElement instanceof LibraryProjectStructureElement)) return;
final StructureConfigurableContext context = mySourceConfigurable.myContext;
final Library originalLibrary = ((LibraryProjectStructureElement)selectedElement).getLibrary();
final LibraryEx oldLibrary = (LibraryEx)context.getLibrary(originalLibrary.getName(), mySourceConfigurable.getLevel());
LOG.assertTrue(oldLibrary != null);
final Library newLibrary = doCopy(oldLibrary);
if (newLibrary == null) return;
final ModulesConfigurator configurator = context.getModulesConfigurator();
final Collection<ProjectStructureElementUsage> usages = context.getDaemonAnalyzer().getUsages(selectedElement);
for (ProjectStructureElementUsage usage : usages) {
if (usage instanceof UsageInModuleClasspath) {
final Module module = ((UsageInModuleClasspath)usage).getModule();
final ModuleEditor editor = configurator.getModuleEditor(module);
if (editor != null) {
final ModifiableRootModel rootModel = editor.getModifiableRootModelProxy();
OrderEntryUtil.replaceLibrary(rootModel, oldLibrary, newLibrary);
context.getDaemonAnalyzer().queueUpdate(new ModuleProjectStructureElement(context, module));
}
}
else if (usage instanceof UsageInArtifact) {
final PackagingElement<?> libraryElement = PackagingElementFactory.getInstance().createLibraryFiles(newLibrary.getName(),
newLibrary.getTable().getTableLevel(), null);
((UsageInArtifact)usage).replaceElement(libraryElement);
}
}
if (!myCopy) {
mySourceConfigurable.getModelProvider().getModifiableModel().removeLibrary(originalLibrary);
context.getDaemonAnalyzer().removeElement(selectedElement);
mySourceConfigurable.removeLibraryNode(originalLibrary);
}
ProjectStructureConfigurable.getInstance(myProject).selectProjectOrGlobalLibrary(newLibrary, true);
}
@Override
protected boolean isEnabled() {
return mySourceConfigurable.getSelectedObject() instanceof LibraryEx;
}
@Override
protected boolean isCopy() {
return true;
return mySourceConfigurable.getSelectedElement() instanceof LibraryProjectStructureElement;
}
@Override
@@ -34,10 +34,14 @@ public class UsageInModuleClasspath extends ProjectStructureElementUsage {
}
@Override
public ProjectStructureElement getContainingElement() {
public ModuleProjectStructureElement getContainingElement() {
return myContainingElement;
}
public Module getModule() {
return myModule;
}
@Override
public String getPresentableName() {
return myModule.getName();
@@ -150,4 +150,21 @@ public class OrderEntryUtil {
}
rootModel.commit();
}
public static void replaceLibrary(@NotNull ModifiableRootModel model, @NotNull Library oldLibrary, @NotNull Library newLibrary) {
OrderEntry[] entries = model.getOrderEntries();
for (int i = 0; i < entries.length; i++) {
OrderEntry orderEntry = entries[i];
if (orderEntry instanceof LibraryOrderEntry && oldLibrary.equals(((LibraryOrderEntry)orderEntry).getLibrary())) {
model.removeOrderEntry(orderEntry);
final LibraryOrderEntry newEntry = model.addLibraryEntry(newLibrary);
final OrderEntry[] newEntries = new OrderEntry[entries.length];
System.arraycopy(entries, 0, newEntries, 0, i);
newEntries[i] = newEntry;
System.arraycopy(entries, i, newEntries, i+1, entries.length - i - 1);
model.rearrangeOrderEntries(newEntries);
return;
}
}
}
}