IDEA-170602 Gradle plugin may store enormous amount of data in workspace.xml

This commit is contained in:
Vladislav.Soroka
2017-03-30 13:22:52 +03:00
parent bac5927169
commit a36992fae4
6 changed files with 91 additions and 33 deletions
@@ -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<ExternalProjectsState>, 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<Externa
}
public void init() {
synchronized (isInitialized) {
if (isInitialized.getAndSet(true)) return;
synchronized (isInitializationWasStarted) {
if (isInitializationWasStarted.getAndSet(true)) return;
myWatcher = new ExternalSystemProjectsWatcher(myProject);
myWatcher.start();
@@ -143,6 +146,20 @@ public class ExternalProjectsManager implements PersistentStateComponent<Externa
}
// init task activation info
myTaskActivator.init();
isInitializationFinished.set(true);
ApplicationManager.getApplication().executeOnPooledThread(() -> {
myPostInitializationActivities.run();
myPostInitializationActivities.clear();
});
}
}
public void runWhenInitialized(Runnable runnable) {
if (isInitializationFinished.get()){
ApplicationManager.getApplication().executeOnPooledThread(runnable);
} else {
myPostInitializationActivities.add(runnable);
}
}
@@ -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<Runnable> implements Runnable {
@Override
public void run() {
for (Runnable runnable : this) {
runnable.run();
}
}
}
@@ -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<Runnable> implements Runnable {
@Override
public void run() {
for (Runnable runnable : this) {
runnable.run();
}
}
}
}
@@ -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() {
@@ -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<Grad
if (projectData == null || toImport.isEmpty()) {
return;
}
Map<String, GradleExtensions> extensionMap = ContainerUtil.newHashMap();
for (DataNode<GradleExtensions> 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);
}
}
@@ -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<GradleExtensionsSettings.Settings> {
private static final Logger LOG = Logger.getInstance(GradleExtensionsSettings.class);
@@ -61,17 +67,13 @@ public class GradleExtensionsSettings implements PersistentStateComponent<Gradle
@Nullable
@Override
public Settings getState() {
// cleanup GradleExtensions entries created by previous version from workspace file
// TODO remove PersistentStateComponent implementation in future version
return myState;
}
@Override
public void loadState(Settings state) {
XmlSerializerUtil.copyBean(state, myState);
for (GradleProject gradleProject : myState.projects.values()) {
for (GradleExtensionsData extensionsData : gradleProject.extensions.values()) {
extensionsData.myGradleProject = gradleProject;
}
}
}
@NotNull
@@ -79,12 +81,41 @@ public class GradleExtensionsSettings implements PersistentStateComponent<Gradle
return ServiceManager.getService(project, GradleExtensionsSettings.class).myState;
}
public static void load(Project project) {
final Collection<ExternalProjectInfo> projectsData =
ProjectDataManager.getInstance().getExternalProjectsData(project, GradleConstants.SYSTEM_ID);
for (ExternalProjectInfo projectInfo : projectsData) {
DataNode<ProjectData> projectDataNode = projectInfo.getExternalProjectStructure();
if (projectDataNode == null) continue;
Collection<DataNode<GradleExtensions>> nodes = new SmartList<>();
for (DataNode<ModuleData> 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<String, GradleProject> projects = new HashMap<>();
public void add(@NotNull String rootPath,
@NotNull Collection<DataNode<GradleExtensions>> extensionsData) {
Map<String, GradleExtensions> extensionMap = ContainerUtil.newHashMap();
for (DataNode<GradleExtensions> 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<String, GradleExtensions> extensions) {
GradleProject gradleProject = new GradleProject();
for (Map.Entry<String, GradleExtensions> entry : extensions.entrySet()) {