gradle: build project preview w/o request to gradle, there are two main reasons for the change:

1. Slow project open - even the simplest project info provided by gradle can be gathered too long (mostly because of new gradle distribution download and downloading buildscript dependencies) (IDEA-136800)
2. Ability to open an invalid projects (e.g. with errors in build scripts) (IDEA-149593)
This commit is contained in:
Vladislav.Soroka
2016-10-20 16:55:52 +03:00
parent 7a97a7e3a5
commit 7502c6dbf3
4 changed files with 89 additions and 10 deletions
@@ -5,6 +5,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
@@ -34,6 +35,7 @@ import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -169,7 +171,7 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
if (dialog.hasMultipleDataToSelect()) {
dialog.showAndGet();
} else {
dialog.dispose();
Disposer.dispose(dialog.getDisposable());
}
}
@@ -192,8 +194,8 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
// resolve dependencies
final Runnable resolveDependenciesTask = () -> ExternalSystemUtil.refreshProject(
project, myExternalSystemId, projectSettings.getExternalProjectPath(), false,
ProgressExecutionMode.IN_BACKGROUND_ASYNC);
project, myExternalSystemId, projectSettings.getExternalProjectPath(),
createFinalImportCallback(project, projectSettings), false, ProgressExecutionMode.IN_BACKGROUND_ASYNC, true);
if (!isFromUI) {
resolveDependenciesTask.run();
}
@@ -217,6 +219,23 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
}
}
protected ExternalProjectRefreshCallback createFinalImportCallback(@NotNull Project project,
@NotNull ExternalProjectSettings projectSettings) {
return new ExternalProjectRefreshCallback() {
@Override
public void onSuccess(@Nullable final DataNode<ProjectData> externalProject) {
if (externalProject == null) {
return;
}
ServiceManager.getService(ProjectDataManager.class).importData(externalProject, project, false);
}
@Override
public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
}
};
}
@NotNull
private ExternalProjectSettings getCurrentExternalProjectSettings() {
ExternalProjectSettings result = myControl.getProjectSettings().clone();
@@ -238,11 +238,6 @@ public class ExternalProjectDataSelectorDialog extends DialogWrapper {
super.doCancelAction();
}
@Override
public void dispose() {
super.dispose();
}
private CheckboxTree createTree() {
final Couple<CheckedTreeNode> rootAndPreselectedNode = createRoot();
final CheckedTreeNode root = rootAndPreselectedNode.first;
@@ -103,12 +103,32 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
@Nullable final GradleExecutionSettings settings,
@NotNull final ExternalSystemTaskNotificationListener listener)
throws ExternalSystemException, IllegalArgumentException, IllegalStateException {
if (isPreviewMode) {
// Create project preview model w/o request to gradle, there are two main reasons for the it:
// * Slow project open - even the simplest project info provided by gradle can be gathered too long (mostly because of new gradle distribution download and downloading buildscript dependencies)
// * Ability to open an invalid projects (e.g. with errors in build scripts)
String projectName = new File(projectPath).getName();
ProjectData projectData = new ProjectData(GradleConstants.SYSTEM_ID, projectName, projectPath, projectPath);
DataNode<ProjectData> projectDataNode = new DataNode<>(ProjectKeys.PROJECT, projectData, null);
final String ideProjectPath = settings == null ? null : settings.getIdeProjectPath();
final String mainModuleFileDirectoryPath =
ideProjectPath == null ? projectPath : ideProjectPath + "/.idea/modules/";
projectDataNode
.createChild(ProjectKeys.MODULE, new ModuleData(projectName, GradleConstants.SYSTEM_ID, StdModuleTypes.JAVA.getId(),
projectName, mainModuleFileDirectoryPath, projectPath))
.createChild(ProjectKeys.CONTENT_ROOT, new ContentRootData(GradleConstants.SYSTEM_ID, projectPath));
return projectDataNode;
}
if (settings != null) {
myHelper.ensureInstalledWrapper(id, projectPath, settings, listener);
}
final GradleProjectResolverExtension projectResolverChain = createProjectResolverChain(settings);
DefaultProjectResolverContext resolverContext = new DefaultProjectResolverContext(id, projectPath, settings, listener, isPreviewMode);
DefaultProjectResolverContext resolverContext = new DefaultProjectResolverContext(id, projectPath, settings, listener, false);
final DataNode<ProjectData> resultProjectDataNode = myHelper.execute(
projectPath, settings, new ProjectConnectionDataNodeFunction(resolverContext, projectResolverChain, false)
);
@@ -116,7 +136,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
// auto-discover buildSrc project if needed
final String buildSrcProjectPath = projectPath + "/buildSrc";
DefaultProjectResolverContext buildSrcResolverCtx =
new DefaultProjectResolverContext(id, buildSrcProjectPath, settings, listener, isPreviewMode);
new DefaultProjectResolverContext(id, buildSrcProjectPath, settings, listener, false);
resolverContext.copyUserDataTo(buildSrcResolverCtx);
handleBuildSrcProject(resultProjectDataNode, new ProjectConnectionDataNodeFunction(buildSrcResolverCtx, projectResolverChain, true));
return resultProjectDataNode;
@@ -17,15 +17,22 @@ package org.jetbrains.plugins.gradle.service.project.wizard;
import com.intellij.externalSystem.JavaProjectData;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.internal.InternalExternalProjectInfo;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil;
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
import com.intellij.openapi.externalSystem.service.project.wizard.AbstractExternalProjectImportBuilder;
import com.intellij.openapi.externalSystem.service.ui.ExternalProjectDataSelectorDialog;
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.*;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -78,6 +85,44 @@ public class GradleProjectImportBuilder extends AbstractExternalProjectImportBui
}
}
@Override
protected ExternalProjectRefreshCallback createFinalImportCallback(@NotNull final Project project,
@NotNull ExternalProjectSettings projectSettings) {
return new ExternalProjectRefreshCallback() {
@Override
public void onSuccess(@Nullable final DataNode<ProjectData> externalProject) {
if (externalProject == null) return;
Runnable selectDataTask = () -> {
ExternalProjectDataSelectorDialog dialog = new ExternalProjectDataSelectorDialog(
project, new InternalExternalProjectInfo(
GradleConstants.SYSTEM_ID, projectSettings.getExternalProjectPath(), externalProject));
if (dialog.hasMultipleDataToSelect()) {
dialog.showAndGet();
}
else {
Disposer.dispose(dialog.getDisposable());
}
};
Runnable importTask = () -> ServiceManager.getService(ProjectDataManager.class).importData(externalProject, project, false);
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
ApplicationManager.getApplication().invokeLater(() -> {
selectDataTask.run();
ApplicationManager.getApplication().executeOnPooledThread(importTask);
});
}
else {
importTask.run();
}
}
@Override
public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
}
};
}
@Override
protected void beforeCommit(@NotNull DataNode<ProjectData> dataNode, @NotNull Project project) {
DataNode<JavaProjectData> javaProjectNode = ExternalSystemApiUtil.find(dataNode, JavaProjectData.KEY);