From a36992fae4773e81d7f715294f2cc54fe45f799d Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Thu, 30 Mar 2017 13:21:53 +0300 Subject: [PATCH] IDEA-170602 Gradle plugin may store enormous amount of data in workspace.xml --- .../manage/ExternalProjectsManager.java | 23 +++++++-- .../util/CompositeRunnable.java | 27 +++++++++++ .../test/runner/events/AfterTestEvent.java | 11 +---- .../project/GradleStartupActivity.java | 3 ++ .../data/GradleExtensionsDataService.java | 13 +---- .../settings/GradleExtensionsSettings.java | 47 +++++++++++++++---- 6 files changed, 91 insertions(+), 33 deletions(-) create mode 100644 platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/CompositeRunnable.java diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java index b90f10c5e182..87b9c3ac01ca 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java @@ -26,6 +26,7 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.model.task.TaskData; import com.intellij.openapi.externalSystem.service.project.autoimport.ExternalSystemProjectsWatcher; +import com.intellij.openapi.externalSystem.util.CompositeRunnable; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.externalSystem.view.ExternalProjectsView; @@ -56,7 +57,9 @@ import static com.intellij.openapi.externalSystem.model.ProjectKeys.TASK; public class ExternalProjectsManager implements PersistentStateComponent, Disposable { private static final Logger LOG = Logger.getInstance(ExternalProjectsManager.class); - private final AtomicBoolean isInitialized = new AtomicBoolean(); + private final AtomicBoolean isInitializationFinished = new AtomicBoolean(); + private final AtomicBoolean isInitializationWasStarted = new AtomicBoolean(); + private final CompositeRunnable myPostInitializationActivities = new CompositeRunnable(); @NotNull private ExternalProjectsState myState = new ExternalProjectsState(); @@ -115,8 +118,8 @@ public class ExternalProjectsManager implements PersistentStateComponent { + myPostInitializationActivities.run(); + myPostInitializationActivities.clear(); + }); + } + } + + public void runWhenInitialized(Runnable runnable) { + if (isInitializationFinished.get()){ + ApplicationManager.getApplication().executeOnPooledThread(runnable); + } else { + myPostInitializationActivities.add(runnable); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/CompositeRunnable.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/CompositeRunnable.java new file mode 100644 index 000000000000..132c96662832 --- /dev/null +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/CompositeRunnable.java @@ -0,0 +1,27 @@ +/* + * 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.externalSystem.util; + +import com.intellij.util.SmartList; + +public class CompositeRunnable extends SmartList implements Runnable { + @Override + public void run() { + for (Runnable runnable : this) { + runnable.run(); + } + } +} \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/AfterTestEvent.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/AfterTestEvent.java index 68054efc9086..ea21fe98f3b8 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/AfterTestEvent.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/AfterTestEvent.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.gradle.execution.test.runner.events; import com.intellij.execution.testframework.sm.runner.SMTestProxy; +import com.intellij.openapi.externalSystem.util.CompositeRunnable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.text.StringUtil; @@ -23,7 +24,6 @@ import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestsExecutionConsole; -import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -125,13 +125,4 @@ public class AfterTestEvent extends AbstractTestEvent { } return null; } - - private static class CompositeRunnable extends ArrayList implements Runnable { - @Override - public void run() { - for (Runnable runnable : this) { - runnable.run(); - } - } - } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java index 0b967c9b83bf..3569832846c2 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java @@ -28,6 +28,7 @@ import com.intellij.openapi.compiler.CompileTask; import com.intellij.openapi.compiler.CompilerManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupActivity; @@ -38,6 +39,7 @@ import org.jetbrains.plugins.gradle.config.GradleResourceCompilerConfigurationGe import org.jetbrains.plugins.gradle.service.GradleBuildClasspathManager; import org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectImportBuilder; import org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectImportProvider; +import org.jetbrains.plugins.gradle.settings.GradleExtensionsSettings; import org.jetbrains.plugins.gradle.settings.GradleSettings; import org.jetbrains.plugins.gradle.util.GradleBundle; import org.jetbrains.plugins.gradle.util.GradleConstants; @@ -59,6 +61,7 @@ public class GradleStartupActivity implements StartupActivity { public void runActivity(@NotNull final Project project) { configureBuildClasspath(project); showNotificationForUnlinkedGradleProject(project); + ExternalProjectsManager.getInstance(project).runWhenInitialized(() -> GradleExtensionsSettings.load(project)); final GradleResourceCompilerConfigurationGenerator buildConfigurationGenerator = new GradleResourceCompilerConfigurationGenerator(project); CompilerManager.getInstance(project).addBeforeTask(new CompileTask() { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/GradleExtensionsDataService.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/GradleExtensionsDataService.java index 4228a525c82c..ee320a0117ab 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/GradleExtensionsDataService.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/GradleExtensionsDataService.java @@ -17,7 +17,6 @@ package org.jetbrains.plugins.gradle.service.project.data; import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.Key; -import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider; import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService; @@ -25,7 +24,6 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; import com.intellij.openapi.externalSystem.util.Order; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.model.GradleExtensions; @@ -33,7 +31,6 @@ import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData; import org.jetbrains.plugins.gradle.settings.GradleExtensionsSettings; import java.util.Collection; -import java.util.Map; /** * @author Vladislav.Soroka @@ -60,15 +57,7 @@ public class GradleExtensionsDataService extends AbstractProjectDataService extensionMap = ContainerUtil.newHashMap(); - for (DataNode node : toImport) { - DataNode parent = node.getParent(); - if (parent == null) continue; - if (!(parent.getData() instanceof ModuleData)) continue; - String projectPath = ((ModuleData)parent.getData()).getLinkedExternalProjectPath(); - extensionMap.put(projectPath, node.getData()); - } - GradleExtensionsSettings.getInstance(project).add(projectData.getLinkedExternalProjectPath(), extensionMap); + GradleExtensionsSettings.getInstance(project).add(projectData.getLinkedExternalProjectPath(), toImport); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java index 6ea3befef3a8..038c9e73e670 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExtensionsSettings.java @@ -17,13 +17,18 @@ package org.jetbrains.plugins.gradle.settings; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.externalSystem.model.DataNode; +import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; +import com.intellij.openapi.externalSystem.model.ProjectKeys; +import com.intellij.openapi.externalSystem.model.project.ModuleData; +import com.intellij.openapi.externalSystem.model.project.ProjectData; +import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.psi.CommonClassNames; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.xmlb.XmlSerializerUtil; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.*; import org.jetbrains.annotations.NotNull; @@ -32,6 +37,7 @@ import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter; import org.jetbrains.plugins.gradle.model.ExternalTask; import org.jetbrains.plugins.gradle.model.GradleExtensions; import org.jetbrains.plugins.gradle.model.GradleProperty; +import org.jetbrains.plugins.gradle.service.project.data.GradleExtensionsDataService; import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames; import org.jetbrains.plugins.gradle.util.GradleConstants; @@ -43,7 +49,7 @@ import java.util.*; * @author Vladislav.Soroka * @since 11/16/2016 */ -@State(name = "GradleExtensions", storages = {@Storage(StoragePathMacros.WORKSPACE_FILE)}) +@State(name = "GradleExtensions", storages = {@Storage(value = StoragePathMacros.WORKSPACE_FILE, deprecated = true)}) public class GradleExtensionsSettings implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance(GradleExtensionsSettings.class); @@ -61,17 +67,13 @@ public class GradleExtensionsSettings implements PersistentStateComponent projectsData = + ProjectDataManager.getInstance().getExternalProjectsData(project, GradleConstants.SYSTEM_ID); + for (ExternalProjectInfo projectInfo : projectsData) { + DataNode projectDataNode = projectInfo.getExternalProjectStructure(); + if (projectDataNode == null) continue; + + Collection> nodes = new SmartList<>(); + for (DataNode moduleNode : ExternalSystemApiUtil.findAll(projectDataNode, ProjectKeys.MODULE)) { + ContainerUtil.addIfNotNull(nodes, ExternalSystemApiUtil.find(moduleNode, GradleExtensionsDataService.KEY)); + } + getInstance(project).add(projectInfo.getExternalProjectPath(), nodes); + } + } + public static class Settings { @Property(surroundWithTag = false) @MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false, entryTagName = "project", keyAttributeName = "path") @NotNull public Map projects = new HashMap<>(); + public void add(@NotNull String rootPath, + @NotNull Collection> extensionsData) { + Map extensionMap = ContainerUtil.newHashMap(); + for (DataNode node : extensionsData) { + DataNode parent = node.getParent(); + if (parent == null) continue; + if (!(parent.getData() instanceof ModuleData)) continue; + String projectPath = ((ModuleData)parent.getData()).getLinkedExternalProjectPath(); + extensionMap.put(projectPath, node.getData()); + } + + add(rootPath, extensionMap); + } + public void add(@NotNull String rootPath, @NotNull Map extensions) { GradleProject gradleProject = new GradleProject(); for (Map.Entry entry : extensions.entrySet()) {