From 22861a0f328ce2acefa6bee1e309ea872bb42f4d Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Fri, 2 Aug 2013 21:13:16 +0400 Subject: [PATCH] IDEA-111342 Gradle: if root project is renamed by means of gradle, it is shown twice in tool window - as root project and as sub-project 1. Correctly update cached data at ExternalSystemFacadeManager on project rename; 2. Minor refactoring (method rename); 3. Drop obsolete data from 'local external system settings' on project rename; 4. Update external tool window project node representation on project rename; --- .../AbstractExternalSystemLocalSettings.java | 20 +++++----- .../action/DetachExternalProjectAction.java | 2 +- .../service/ExternalSystemFacadeManager.java | 26 +++++++++---- .../service/task/ToolWindowModuleService.java | 39 ++++++++++++++++--- .../task/ui/ExternalSystemNodeDescriptor.java | 4 ++ .../task/ui/ExternalSystemTasksTreeModel.java | 20 ++++++---- .../util/ExternalSystemUtil.java | 9 +++-- .../project/GradleProjectResolver.java | 11 ++++-- 8 files changed, 93 insertions(+), 38 deletions(-) diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java index f2cea2f0a771..4f76d9780e30 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java @@ -73,11 +73,11 @@ public abstract class AbstractExternalSystemLocalSettings { } /** - * Asks current settings to drop all information related to external project which root config is located at the given path. + * Asks current settings to drop all information related to external projects which root configs are located at the given paths. * - * @param linkedProjectPathsToForget target root external project's path + * @param linkedProjectPathsToForget target root external project paths */ - public void forgetExternalProject(@NotNull Set linkedProjectPathsToForget) { + public void forgetExternalProjects(@NotNull Set linkedProjectPathsToForget) { Map> projects = myAvailableProjects.get(); for (Iterator>> it = projects.entrySet().iterator(); it.hasNext(); ) { Map.Entry> entry = it.next(); @@ -184,24 +184,24 @@ public abstract class AbstractExternalSystemLocalSettings { private void pruneOutdatedEntries() { ExternalSystemManager manager = ExternalSystemApiUtil.getManager(myExternalSystemId); assert manager != null; - Set toForget = ContainerUtilRt.newHashSet(); + Set pathsToForget = ContainerUtilRt.newHashSet(); for (ExternalProjectPojo pojo : myAvailableProjects.get().keySet()) { - toForget.add(pojo.getPath()); + pathsToForget.add(pojo.getPath()); } for (String path : myAvailableTasks.get().keySet()) { - toForget.add(path); + pathsToForget.add(path); } for (ExternalTaskExecutionInfo taskInfo : myRecentTasks.get()) { - toForget.add(taskInfo.getSettings().getExternalProjectPath()); + pathsToForget.add(taskInfo.getSettings().getExternalProjectPath()); } AbstractExternalSystemSettings settings = manager.getSettingsProvider().fun(myProject); for (ExternalProjectSettings projectSettings : settings.getLinkedProjectsSettings()) { - toForget.remove(projectSettings.getExternalProjectPath()); + pathsToForget.remove(projectSettings.getExternalProjectPath()); } - if (!toForget.isEmpty()) { - forgetExternalProject(toForget); + if (!pathsToForget.isEmpty()) { + forgetExternalProjects(pathsToForget); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java index 2a8b7467f0eb..114dac6078b6 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java @@ -86,7 +86,7 @@ public class DetachExternalProjectAction extends AnAction implements DumbAware { recentTasksList.getModel().forgetTasksFrom(info.externalProject.getPath()); } - info.localSettings.forgetExternalProject(Collections.singleton(info.externalProject.getPath())); + info.localSettings.forgetExternalProjects(Collections.singleton(info.externalProject.getPath())); info.settings.unlinkExternalProject(info.externalProject.getPath()); // Process orphan modules. diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java index 771075f39dd6..7136ca7fcfa6 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java @@ -45,6 +45,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.ShutDownTracker; import com.intellij.psi.PsiBundle; import com.intellij.util.Alarm; +import com.intellij.util.Consumer; import com.intellij.util.PathUtil; import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; @@ -244,8 +245,13 @@ public class ExternalSystemFacadeManager { key.getIdeProjectLocationHash(), key.getExternalSystemId(), key.getExternalProjectConfigPath()); - data.put(newKey, data.get(key)); + V value = data.get(key); + data.put(newKey, value); data.remove(key); + if (value instanceof Consumer) { + //noinspection unchecked + ((Consumer)value).consume(newKey); + } } } @@ -265,7 +271,7 @@ public class ExternalSystemFacadeManager { final RemoteExternalSystemFacade facade = myFacadeWrappers.get(key); if (facade == null) { final RemoteExternalSystemFacade newFacade = (RemoteExternalSystemFacade)Proxy.newProxyInstance( - ExternalSystemFacadeManager.class.getClassLoader(), new Class[]{RemoteExternalSystemFacade.class}, new MyHandler(key) + ExternalSystemFacadeManager.class.getClassLoader(), new Class[]{RemoteExternalSystemFacade.class, Consumer.class}, new MyHandler(key) ); myFacadeWrappers.putIfAbsent(key, newFacade); } @@ -408,16 +414,22 @@ public class ExternalSystemFacadeManager { } private class MyHandler implements InvocationHandler { - - @NotNull private final IntegrationKey myKey; + + @NotNull private final AtomicReference myKey = new AtomicReference(); MyHandler(@NotNull IntegrationKey key) { - myKey = key; + myKey.set(key); } - + + @Nullable @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - return doInvoke(myKey, findProject(myKey), method, args, REMOTE_FAIL_RECOVERY_ATTEMPTS_NUMBER); + if ("consume".equals(method.getName())) { + myKey.set((IntegrationKey)args[0]); + return null; + } + Project project = findProject(myKey.get()); + return doInvoke(myKey.get(), project, method, args, REMOTE_FAIL_RECOVERY_ATTEMPTS_NUMBER); } } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ToolWindowModuleService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ToolWindowModuleService.java index def355351f85..16ee28307629 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ToolWindowModuleService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ToolWindowModuleService.java @@ -34,10 +34,7 @@ import com.intellij.util.containers.ContainerUtilRt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Ensures that all external system sub-projects are correctly represented at the external system tool window. @@ -82,8 +79,40 @@ public class ToolWindowModuleService extends AbstractToolWindowService> projects = ContainerUtilRt.newHashMap(settings.getAvailableProjects()); + Set pathsToForget = detectRenamedProjects(data, settings.getAvailableProjects()); + if (!pathsToForget.isEmpty()) { + settings.forgetExternalProjects(pathsToForget); + } + Map> projects = ContainerUtilRt.newHashMap(settings.getAvailableProjects()); projects.putAll(data); settings.setAvailableProjects(projects); } + + @NotNull + private static Set detectRenamedProjects(@NotNull Map> currentInfo, + @NotNull Map> oldInfo) + { + Map map = ContainerUtilRt.newHashMap(); + for (Map.Entry> entry : currentInfo.entrySet()) { + map.put(entry.getKey().getPath(), entry.getKey().getName()); + for (ExternalProjectPojo pojo : entry.getValue()) { + map.put(pojo.getPath(), pojo.getName()); + } + } + + Set result = ContainerUtilRt.newHashSet(); + for (Map.Entry> entry : oldInfo.entrySet()) { + String newName = map.get(entry.getKey().getPath()); + if (newName != null && !newName.equals(entry.getKey().getName())) { + result.add(entry.getKey().getPath()); + } + for (ExternalProjectPojo pojo : entry.getValue()) { + newName = map.get(pojo.getPath()); + if (newName != null && !newName.equals(pojo.getName())) { + result.add(pojo.getPath()); + } + } + } + return result; + } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemNodeDescriptor.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemNodeDescriptor.java index b3f0f9031b3f..b24d09bd5acd 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemNodeDescriptor.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemNodeDescriptor.java @@ -37,6 +37,10 @@ public class ExternalSystemNodeDescriptor extends PresentableNodeDescriptor NODE_COMPARATOR = new Comparator() { @Override public int compare(TreeNode t1, TreeNode t2) { @@ -95,11 +92,18 @@ public class ExternalSystemTasksTreeModel extends DefaultTreeModel { // Remove outdated projects. for (int i = root.getChildCount() - 1; i >= 0; i--) { ExternalSystemNode child = root.getChildAt(i); - Object element = child.getDescriptor().getElement(); - if (element instanceof ExternalProjectPojo - && ((ExternalProjectPojo)element).getPath().equals(project.getPath())) - { - return (ExternalSystemNode)child; + ExternalSystemNodeDescriptor descriptor = child.getDescriptor(); + Object element = descriptor.getElement(); + if (element instanceof ExternalProjectPojo) { + ExternalProjectPojo pojo = (ExternalProjectPojo)element; + if (pojo.getPath().equals(project.getPath())) { + if (!pojo.getName().equals(project.getName())) { + pojo.setName(project.getName()); + descriptor.setName(project.getName()); + nodeChanged(child); + } + return (ExternalSystemNode)child; + } } } ExternalProjectPojo element = new ExternalProjectPojo(project.getName(), project.getPath()); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java index 396fb33f6fea..e4e7c616a8aa 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java @@ -206,7 +206,7 @@ public class ExternalSystemUtil { ExternalProjectRefreshCallback callback = new ExternalProjectRefreshCallback() { @NotNull - private final Set myExternalModuleNames = ContainerUtilRt.newHashSet(); + private final Set myExternalModulePaths = ContainerUtilRt.newHashSet(); @Override public void onSuccess(@Nullable final DataNode externalProject) { @@ -215,7 +215,7 @@ public class ExternalSystemUtil { } Collection> moduleNodes = ExternalSystemApiUtil.findAll(externalProject, ProjectKeys.MODULE); for (DataNode node : moduleNodes) { - myExternalModuleNames.add(node.getData().getName()); + myExternalModulePaths.add(node.getData().getLinkedExternalProjectPath()); } ExternalSystemApiUtil.executeProjectChangeAction(true, new Runnable() { @Override @@ -225,7 +225,7 @@ public class ExternalSystemUtil { public void run() { projectDataManager.importData(externalProject.getKey(), Collections.singleton(externalProject), project, true); } - }); + }); } }); if (--counter[0] <= 0) { @@ -245,7 +245,8 @@ public class ExternalSystemUtil { for (Module module : platformFacade.getModules(project)) { String s = module.getOptionValue(ExternalSystemConstants.EXTERNAL_SYSTEM_ID_KEY); - if (externalSystemIdAsString.equals(s) && !myExternalModuleNames.contains(module.getName())) { + String p = module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY); + if (externalSystemIdAsString.equals(s) && !myExternalModulePaths.contains(p)) { orphanIdeModules.add(module); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java index 2566c3325249..79010b8797ba 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java @@ -436,8 +436,9 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver> tasksByModule = ContainerUtilRt.newHashMap(); TObjectIntHashMap> rootProjectTaskCandidates = new TObjectIntHashMap>(); @@ -487,7 +488,11 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver> moduleNodes = ExternalSystemApiUtil.findAll(rootProjectNode, ProjectKeys.MODULE); for (DataNode moduleNode : moduleNodes) { - Collection tasks = tasksByModule.get(moduleNode.getData().getName()); + ModuleData moduleData = moduleNode.getData(); + if (rootProjectPath.equals(moduleData.getLinkedExternalProjectPath()) && !projectData.getName().equals(moduleData.getName())) { + moduleData.setName(projectData.getName()); + } + Collection tasks = tasksByModule.get(moduleData.getName()); if (tasks != null && !tasks.isEmpty()) { for (TaskData task : tasks) { moduleNode.createChild(ProjectKeys.TASK, task);