mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-83595 Allow adding more than one gradle project
1. Don't modify project-level settings (e.g. language level) on importing a module from external system; 2. Ensure that ProjectDataService implementations preserve 'importData()' contract (don't re-create an existing project entity);
This commit is contained in:
@@ -48,11 +48,14 @@ public class JavaProjectDataService implements ProjectDataService<JavaProjectDat
|
||||
|
||||
@Override
|
||||
public void importData(@NotNull Collection<DataNode<JavaProjectData>> toImport, @NotNull Project project, boolean synchronous) {
|
||||
if (!ExternalSystemApiUtil.isNewProjectConstruction()) {
|
||||
return;
|
||||
}
|
||||
if (toImport.size() != 1) {
|
||||
throw new IllegalArgumentException(String.format("Expected to get a single project but got %d: %s", toImport.size(), toImport));
|
||||
}
|
||||
JavaProjectData projectData = toImport.iterator().next().getData();
|
||||
|
||||
|
||||
// JDK.
|
||||
JavaSdkVersion version = projectData.getJdkVersion();
|
||||
JavaSdk javaSdk = JavaSdk.getInstance();
|
||||
|
||||
+18
@@ -24,6 +24,7 @@ import com.intellij.openapi.externalSystem.model.Key;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.fileTypes.FileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.util.AtomicNotNullLazyValue;
|
||||
@@ -355,4 +356,21 @@ public class ExternalSystemApiUtil {
|
||||
public static String normalizePath(@Nullable String s) {
|
||||
return StringUtil.isEmpty(s) ? null : s;
|
||||
}
|
||||
|
||||
/**
|
||||
* We can divide all 'import from external system' use-cases into at least as below:
|
||||
* <pre>
|
||||
* <ul>
|
||||
* <li>this is a new project being created (import project from external model);</li>
|
||||
* <li>a new module is being imported from an external project into an existing ide project;</li>
|
||||
* </ul>
|
||||
* </pre>
|
||||
* This method allows to differentiate between them (e.g. we don't want to change language level when new module is imported to
|
||||
* an existing project).
|
||||
*
|
||||
* @return <code>true</code> if new project is being imported; <code>false</code> if new module is being imported
|
||||
*/
|
||||
public static boolean isNewProjectConstruction() {
|
||||
return ProjectManager.getInstance().getOpenProjects().length == 0;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -236,10 +236,8 @@ public class ExternalSystemFacadeImpl<S extends ExternalSystemExecutionSettings>
|
||||
public void applyProgressManager(@NotNull RemoteExternalSystemProgressNotificationManager progressManager) throws RemoteException {
|
||||
ExternalSystemTaskNotificationListener listener = new SwallowingNotificationListener(progressManager);
|
||||
myNotificationListener.set(listener);
|
||||
List<RemoteExternalSystemService> services = new ArrayList<RemoteExternalSystemService>(myRemotes.values());
|
||||
for (RemoteExternalSystemService service : services) {
|
||||
service.setNotificationListener(listener);
|
||||
}
|
||||
myProjectResolver.setNotificationListener(listener);
|
||||
myBuildManager.setNotificationListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.service;
|
||||
|
||||
import com.intellij.openapi.externalSystem.ExternalSystemManager;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.startup.StartupActivity;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.util.SystemProperties;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 5/2/13 9:23 PM
|
||||
*/
|
||||
public class ExternalSystemStartupActivity implements StartupActivity {
|
||||
|
||||
@Override
|
||||
public void runActivity(final Project project) {
|
||||
Runnable task = new Runnable() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void run() {
|
||||
if (SystemProperties.getBooleanProperty(ExternalSystemConstants.NEWLY_IMPORTED_PROJECT, false)) {
|
||||
System.setProperty(ExternalSystemConstants.NEWLY_IMPORTED_PROJECT, Boolean.toString(false));
|
||||
}
|
||||
else {
|
||||
for (ExternalSystemManager manager : ExternalSystemManager.EP_NAME.getExtensions()) {
|
||||
ExternalSystemUtil.refreshProjects(project, manager.getSystemId());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (project.isInitialized()) {
|
||||
task.run();
|
||||
}
|
||||
else {
|
||||
StartupManager.getInstance(project).registerPostStartupActivity(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.service.project;
|
||||
|
||||
import com.intellij.openapi.externalSystem.model.DataNode;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.model.settings.ExternalSystemExecutionSettings;
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalSystemProjectResolver;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 5/2/13 10:37 PM
|
||||
*/
|
||||
public interface ExternalProjectRefreshCallback {
|
||||
|
||||
/**
|
||||
* Is expected to be called when
|
||||
* {@link ExternalSystemProjectResolver#resolveProjectInfo(ExternalSystemTaskId, String, boolean, ExternalSystemExecutionSettings)}
|
||||
* returns without exception.
|
||||
*
|
||||
* @param externalProject target external project (if available)
|
||||
*/
|
||||
void onSuccess(@Nullable DataNode<ProjectData> externalProject);
|
||||
|
||||
void onFailure(@NotNull String errorMessage, @Nullable String errorDetails);
|
||||
}
|
||||
+91
-19
@@ -15,10 +15,9 @@ 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.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -87,28 +86,16 @@ public class ContentRootDataService implements ProjectDataService<ContentRootDat
|
||||
try {
|
||||
for (DataNode<ContentRootData> data : datas) {
|
||||
ContentRootData contentRoot = data.getData();
|
||||
ContentEntry contentEntry = model.addContentEntry(toVfsUrl(contentRoot.getRootPath()));
|
||||
ContentEntry contentEntry = findOrCreateContentRoot(model, contentRoot.getRootPath());
|
||||
LOG.info(String.format("Importing content root '%s' for module '%s'", contentRoot.getRootPath(), module.getName()));
|
||||
for (String path : contentRoot.getPaths(ExternalSystemSourceType.SOURCE)) {
|
||||
contentEntry.addSourceFolder(toVfsUrl(path), false);
|
||||
LOG.info(String.format(
|
||||
"Importing source root '%s' for content root '%s' of module '%s'",
|
||||
path, contentRoot.getRootPath(), module.getName()
|
||||
));
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName());
|
||||
}
|
||||
for (String path : contentRoot.getPaths(ExternalSystemSourceType.TEST)) {
|
||||
contentEntry.addSourceFolder(toVfsUrl(path), true);
|
||||
LOG.info(String.format(
|
||||
"Importing test root '%s' for content root '%s' of module '%s'",
|
||||
path, contentRoot.getRootPath(), module.getName()
|
||||
));
|
||||
createTestRootIfAbsent(contentEntry, path, module.getName());
|
||||
}
|
||||
for (String path : contentRoot.getPaths(ExternalSystemSourceType.EXCLUDED)) {
|
||||
contentEntry.addExcludeFolder(toVfsUrl(path));
|
||||
LOG.info(String.format(
|
||||
"Importing excluded root '%s' for content root '%s' of module '%s'",
|
||||
path, contentRoot.getRootPath(), module.getName()
|
||||
));
|
||||
createExcludedRootIfAbsent(contentEntry, path, module.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,6 +106,91 @@ public class ContentRootDataService implements ProjectDataService<ContentRootDat
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ContentEntry findOrCreateContentRoot(@NotNull ModifiableRootModel model, @NotNull String path) {
|
||||
ContentEntry[] entries = model.getContentEntries();
|
||||
if (entries == null) {
|
||||
return model.addContentEntry(toVfsUrl(path));
|
||||
}
|
||||
|
||||
for (ContentEntry entry : entries) {
|
||||
VirtualFile file = entry.getFile();
|
||||
if (file == null) {
|
||||
continue;
|
||||
}
|
||||
if (ExternalSystemApiUtil.getLocalFileSystemPath(file).equals(path)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return model.addContentEntry(toVfsUrl(path));
|
||||
}
|
||||
|
||||
private static void createSourceRootIfAbsent(@NotNull ContentEntry entry, @NotNull String path, @NotNull String moduleName) {
|
||||
SourceFolder[] folders = entry.getSourceFolders();
|
||||
if (folders == null) {
|
||||
LOG.info(String.format("Importing source root '%s' for content root '%s' of module '%s'", path, entry.getUrl(), moduleName));
|
||||
entry.addSourceFolder(toVfsUrl(path), false);
|
||||
return;
|
||||
}
|
||||
for (SourceFolder folder : folders) {
|
||||
if (folder.isTestSource()) {
|
||||
continue;
|
||||
}
|
||||
VirtualFile file = folder.getFile();
|
||||
if (file == null) {
|
||||
continue;
|
||||
}
|
||||
if (ExternalSystemApiUtil.getLocalFileSystemPath(file).equals(path)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG.info(String.format("Importing source root '%s' for content root '%s' of module '%s'", path, entry.getUrl(), moduleName));
|
||||
entry.addSourceFolder(toVfsUrl(path), false);
|
||||
}
|
||||
|
||||
private static void createExcludedRootIfAbsent(@NotNull ContentEntry entry, @NotNull String path, @NotNull String moduleName) {
|
||||
ExcludeFolder[] folders = entry.getExcludeFolders();
|
||||
if (folders == null) {
|
||||
LOG.info(String.format("Importing excluded root '%s' for content root '%s' of module '%s'", path, entry.getUrl(), moduleName));
|
||||
entry.addExcludeFolder(toVfsUrl(path));
|
||||
return;
|
||||
}
|
||||
for (ExcludeFolder folder : folders) {
|
||||
VirtualFile file = folder.getFile();
|
||||
if (file == null) {
|
||||
continue;
|
||||
}
|
||||
if (ExternalSystemApiUtil.getLocalFileSystemPath(file).equals(path)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG.info(String.format("Importing excluded root '%s' for content root '%s' of module '%s'", path, entry.getUrl(), moduleName));
|
||||
entry.addExcludeFolder(toVfsUrl(path));
|
||||
}
|
||||
|
||||
private static void createTestRootIfAbsent(@NotNull ContentEntry entry, @NotNull String path, @NotNull String moduleName) {
|
||||
SourceFolder[] folders = entry.getSourceFolders();
|
||||
if (folders == null) {
|
||||
LOG.info(String.format("Importing test root '%s' for content root '%s' of module '%s'", path, entry.getUrl(), moduleName));
|
||||
entry.addSourceFolder(toVfsUrl(path), true);
|
||||
return;
|
||||
}
|
||||
for (SourceFolder folder : folders) {
|
||||
if (!folder.isTestSource()) {
|
||||
continue;
|
||||
}
|
||||
VirtualFile file = folder.getFile();
|
||||
if (file == null) {
|
||||
continue;
|
||||
}
|
||||
if (ExternalSystemApiUtil.getLocalFileSystemPath(file).equals(path)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG.info(String.format("Importing test root '%s' for content root '%s' of module '%s'", path, entry.getUrl(), moduleName));
|
||||
entry.addSourceFolder(toVfsUrl(path), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeData(@NotNull Collection<DataNode<ContentRootData>> toRemove, @NotNull Project project, boolean synchronous) {
|
||||
if (toRemove.isEmpty()) {
|
||||
|
||||
+1
-2
@@ -138,7 +138,6 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
|
||||
}
|
||||
|
||||
for (DataNode<LibraryDependencyData> dependencyNode : nodesToImport) {
|
||||
ProjectStructureHelper helper = ServiceManager.getService(module.getProject(), ProjectStructureHelper.class);
|
||||
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
|
||||
final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
|
||||
try {
|
||||
@@ -149,7 +148,7 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
|
||||
assert false;
|
||||
continue;
|
||||
}
|
||||
LibraryOrderEntry orderEntry = helper.findIdeLibraryDependency(dependencyData.getName(), moduleRootModel);
|
||||
LibraryOrderEntry orderEntry = myProjectStructureHelper.findIdeLibraryDependency(dependencyData.getName(), moduleRootModel);
|
||||
if (orderEntry == null) {
|
||||
// We need to get the most up-to-date Library object due to our project model restrictions.
|
||||
orderEntry = moduleRootModel.addLibraryEntry(library);
|
||||
|
||||
+3
@@ -44,6 +44,9 @@ public class ProjectDataServiceImpl implements ProjectDataService<ProjectData> {
|
||||
|
||||
@Override
|
||||
public void importData(@NotNull Collection<DataNode<ProjectData>> toImport, @NotNull Project project, boolean synchronous) {
|
||||
if (!ExternalSystemApiUtil.isNewProjectConstruction()) {
|
||||
return;
|
||||
}
|
||||
if (toImport.size() != 1) {
|
||||
throw new IllegalArgumentException(String.format("Expected to get a single project but got %d: %s", toImport.size(), toImport));
|
||||
}
|
||||
|
||||
+51
-36
@@ -6,9 +6,9 @@ import com.intellij.openapi.externalSystem.model.DataNode;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.model.project.LibraryData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemResolveProjectTask;
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
|
||||
import com.intellij.openapi.externalSystem.service.settings.AbstractImportFromExternalSystemControl;
|
||||
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
|
||||
@@ -130,7 +130,7 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
|
||||
AbstractExternalSystemSettings settings = mySettingsManager.getSettings(project, myExternalSystemId);
|
||||
final String linkedProjectPath = myControl.getProjectSettings().getExternalProjectPath();
|
||||
assert linkedProjectPath != null;
|
||||
List<ExternalProjectSettings> projects = ContainerUtilRt.newArrayList(settings.getLinkedProjectsSettings());
|
||||
Set<ExternalProjectSettings> projects = ContainerUtilRt.newHashSet(settings.getLinkedProjectsSettings());
|
||||
projects.add(myControl.getProjectSettings());
|
||||
settings.setLinkedProjectsSettings(projects);
|
||||
onProjectInit(project);
|
||||
@@ -142,8 +142,7 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
|
||||
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Collection<DataNode<ModuleData>> modules = ExternalSystemApiUtil.findAll(externalProjectNode, ProjectKeys.MODULE);
|
||||
myProjectDataManager.importData(ProjectKeys.MODULE, modules, project, true);
|
||||
myProjectDataManager.importData(externalProjectNode.getKey(), Collections.singleton(externalProjectNode), project, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -210,23 +209,25 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
|
||||
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Clean existing libraries (if any).
|
||||
LibraryTable projectLibraryTable = ProjectLibraryTable.getInstance(project);
|
||||
if (projectLibraryTable == null) {
|
||||
LOG.warn(
|
||||
"Can't resolve external dependencies of the target gradle project (" + project + "). Reason: project "
|
||||
+ "library table is undefined"
|
||||
);
|
||||
return;
|
||||
}
|
||||
LibraryTable.ModifiableModel model = projectLibraryTable.getModifiableModel();
|
||||
try {
|
||||
for (Library library : model.getLibraries()) {
|
||||
model.removeLibrary(library);
|
||||
if (ExternalSystemApiUtil.isNewProjectConstruction()) {
|
||||
// Clean existing libraries (if any).
|
||||
LibraryTable projectLibraryTable = ProjectLibraryTable.getInstance(project);
|
||||
if (projectLibraryTable == null) {
|
||||
LOG.warn(
|
||||
"Can't resolve external dependencies of the target gradle project (" + project + "). Reason: project "
|
||||
+ "library table is undefined"
|
||||
);
|
||||
return;
|
||||
}
|
||||
LibraryTable.ModifiableModel model = projectLibraryTable.getModifiableModel();
|
||||
try {
|
||||
for (Library library : model.getLibraries()) {
|
||||
model.removeLibrary(library);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
model.commit();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
model.commit();
|
||||
}
|
||||
|
||||
// Register libraries.
|
||||
@@ -258,30 +259,41 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
|
||||
throw new ConfigurationException(ExternalSystemBundle.message("error.project.undefined"));
|
||||
}
|
||||
projectFile = getExternalProjectConfigToUse(projectFile);
|
||||
final Ref<String> errorReason = new Ref<String>();
|
||||
final Ref<String> errorDetails = new Ref<String>();
|
||||
final Ref<ConfigurationException> error = new Ref<ConfigurationException>();
|
||||
ExternalProjectRefreshCallback callback = new ExternalProjectRefreshCallback() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable DataNode<ProjectData> externalProject) {
|
||||
myExternalProjectNode = externalProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
|
||||
if (!StringUtil.isEmpty(errorDetails)) {
|
||||
LOG.warn(errorDetails);
|
||||
}
|
||||
error.set(new ConfigurationException(ExternalSystemBundle.message("error.resolve.with.reason", errorMessage),
|
||||
ExternalSystemBundle.message("error.resolve.generic")));
|
||||
}
|
||||
};
|
||||
try {
|
||||
final Project project = getProject(wizardContext);
|
||||
myExternalProjectNode = ExternalSystemUtil.refreshProject(project, myExternalSystemId, projectFile.getAbsolutePath(), errorReason,
|
||||
errorDetails, false, true);
|
||||
ExternalSystemUtil.refreshProject(
|
||||
project,
|
||||
myExternalSystemId,
|
||||
projectFile.getAbsolutePath(),
|
||||
callback,
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new ConfigurationException(e.getMessage(), ExternalSystemBundle.message("error.cannot.parse.project", externalSystemName));
|
||||
}
|
||||
if (myExternalProjectNode == null) {
|
||||
final String details = errorDetails.get();
|
||||
if (!StringUtil.isEmpty(details)) {
|
||||
LOG.warn(details);
|
||||
ConfigurationException exception = error.get();
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
String errorMessage;
|
||||
String reason = errorReason.get();
|
||||
if (reason == null) {
|
||||
errorMessage = ExternalSystemBundle.message("error.resolve.generic.without.reason", externalSystemName, projectFile.getPath());
|
||||
}
|
||||
else {
|
||||
errorMessage = ExternalSystemBundle.message("error.resolve.with.reason", reason);
|
||||
}
|
||||
throw new ConfigurationException(errorMessage, ExternalSystemBundle.message("error.resolve.generic"));
|
||||
}
|
||||
else {
|
||||
applyProjectSettings(wizardContext);
|
||||
@@ -302,6 +314,9 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
|
||||
* @param context storage for the project/module settings.
|
||||
*/
|
||||
public void applyProjectSettings(@NotNull WizardContext context) {
|
||||
if (!ExternalSystemApiUtil.isNewProjectConstruction()) {
|
||||
return;
|
||||
}
|
||||
if (myExternalProjectNode == null) {
|
||||
assert false;
|
||||
return;
|
||||
|
||||
+71
-91
@@ -21,31 +21,30 @@ import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.externalSystem.ExternalSystemManager;
|
||||
import com.intellij.openapi.externalSystem.model.DataNode;
|
||||
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectEntityData;
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemResolveProjectTask;
|
||||
import com.intellij.openapi.externalSystem.service.project.ModuleAwareContentRoot;
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
|
||||
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
|
||||
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
|
||||
import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsManager;
|
||||
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry;
|
||||
import com.intellij.openapi.roots.ModuleOrderEntry;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -53,6 +52,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
@@ -60,38 +63,9 @@ import java.io.StringWriter;
|
||||
*/
|
||||
public class ExternalSystemUtil {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#" + ExternalSystemUtil.class.getName());
|
||||
|
||||
private ExternalSystemUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to dispatch given entity via the given visitor.
|
||||
*
|
||||
* @param entity intellij project entity candidate to dispatch
|
||||
* @param visitor dispatch callback to use for the given entity
|
||||
*/
|
||||
public static void dispatch(@Nullable Object entity, @NotNull IdeEntityVisitor visitor) {
|
||||
if (entity instanceof Project) {
|
||||
visitor.visit(((Project)entity));
|
||||
}
|
||||
else if (entity instanceof Module) {
|
||||
visitor.visit(((Module)entity));
|
||||
}
|
||||
else if (entity instanceof ModuleAwareContentRoot) {
|
||||
visitor.visit(((ModuleAwareContentRoot)entity));
|
||||
}
|
||||
else if (entity instanceof LibraryOrderEntry) {
|
||||
visitor.visit(((LibraryOrderEntry)entity));
|
||||
}
|
||||
else if (entity instanceof ModuleOrderEntry) {
|
||||
visitor.visit(((ModuleOrderEntry)entity));
|
||||
}
|
||||
else if (entity instanceof Library) {
|
||||
visitor.visit(((Library)entity));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T getToolWindowElement(@NotNull Class<T> clazz,
|
||||
@Nullable DataContext context,
|
||||
@@ -177,43 +151,58 @@ public class ExternalSystemUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void refreshProject(@NotNull Project project, @NotNull ProjectSystemId externalSystemId) {
|
||||
refreshProject(project, externalSystemId, new Ref<String>());
|
||||
}
|
||||
/**
|
||||
* Asks to refresh all external projects of the target external system linked to the given ide project.
|
||||
* <p/>
|
||||
* 'Refresh' here means 'obtain the most up-to-date version and apply it to the ide'.
|
||||
*
|
||||
* @param project target ide project
|
||||
* @param externalSystemId target external system which projects should be refreshed
|
||||
*/
|
||||
public static void refreshProjects(@NotNull final Project project, @NotNull ProjectSystemId externalSystemId) {
|
||||
ExternalSystemManager<?,?,?,?,?> manager = ExternalSystemApiUtil.getManager(externalSystemId);
|
||||
if (manager == null) {
|
||||
return;
|
||||
}
|
||||
AbstractExternalSystemSettings<?, ?> settings = manager.getSettingsProvider().fun(project);
|
||||
Collection<? extends ExternalProjectSettings> projectsSettings = settings.getLinkedProjectsSettings();
|
||||
if (projectsSettings.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
public static void refreshProject(@NotNull Project project,
|
||||
@NotNull ProjectSystemId externalSystemId,
|
||||
@NotNull final Consumer<String> errorCallback)
|
||||
{
|
||||
final Ref<String> errorMessageHolder = new Ref<String>() {
|
||||
final ProjectDataManager projectDataManager = ServiceManager.getService(ProjectDataManager.class);
|
||||
final Set<String> externalModuleNames = ContainerUtilRt.newHashSet();
|
||||
ExternalProjectRefreshCallback callback = new ExternalProjectRefreshCallback() {
|
||||
@Override
|
||||
public void set(@Nullable String value) {
|
||||
if (value != null) {
|
||||
errorCallback.consume(value);
|
||||
public void onSuccess(@Nullable DataNode<ProjectData> externalProject) {
|
||||
if (externalProject == null) {
|
||||
return;
|
||||
}
|
||||
Collection<DataNode<ModuleData>> moduleNodes = ExternalSystemApiUtil.findAll(externalProject, ProjectKeys.MODULE);
|
||||
for (DataNode<ModuleData> node : moduleNodes) {
|
||||
externalModuleNames.add(node.getData().getName());
|
||||
}
|
||||
projectDataManager.importData(externalProject.getKey(), Collections.singleton(externalProject), project, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
|
||||
}
|
||||
};
|
||||
refreshProject(project, externalSystemId, errorMessageHolder);
|
||||
}
|
||||
|
||||
public static void refreshProject(@NotNull Project project,
|
||||
@NotNull ProjectSystemId externalSystemId,
|
||||
@NotNull final Ref<String> errorMessageHolder)
|
||||
{
|
||||
ExternalSystemSettingsManager settingsManager = ServiceManager.getService(ExternalSystemSettingsManager.class);
|
||||
AbstractExternalSystemSettings settings = settingsManager.getSettings(project, externalSystemId);
|
||||
for (Object path : settings.getLinkedProjectsSettings()) {
|
||||
Ref<String> errorDetailsHolder = new Ref<String>() {
|
||||
@Override
|
||||
public void set(@Nullable String error) {
|
||||
if (!StringUtil.isEmpty(error)) {
|
||||
assert error != null;
|
||||
LOG.warn(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
refreshProject(project, externalSystemId, path.toString(), errorMessageHolder, errorDetailsHolder, true, false);
|
||||
for (ExternalProjectSettings setting : projectsSettings) {
|
||||
refreshProject(project, externalSystemId, setting.getExternalProjectPath(), callback, true, false);
|
||||
}
|
||||
PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
|
||||
List<Module> orphanIdeModules = ContainerUtilRt.newArrayList();
|
||||
String externalSystemIdAsString = externalSystemId.toString();
|
||||
for (Module module : platformFacade.getModules(project)) {
|
||||
String s = module.getOptionValue(ExternalSystemConstants.EXTERNAL_SYSTEM_ID_KEY);
|
||||
if (externalSystemIdAsString.equals(s) && !externalModuleNames.contains(module.getName())) {
|
||||
orphanIdeModules.add(module);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO den offer to remove orphan modules here
|
||||
}
|
||||
|
||||
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
|
||||
@@ -231,21 +220,17 @@ public class ExternalSystemUtil {
|
||||
*
|
||||
* @param project target intellij project to use
|
||||
* @param externalProjectPath path of the target gradle project's file
|
||||
* @param errorMessageHolder holder for the error message that describes a problem occurred during the refresh (if any)
|
||||
* @param errorDetailsHolder holder for the error details of the problem occurred during the refresh (if any)
|
||||
* @param callback callback to be notified on refresh result
|
||||
* @param resolveLibraries flag that identifies whether gradle libraries should be resolved during the refresh
|
||||
* @return the most up-to-date gradle project (if any)
|
||||
*/
|
||||
@Nullable
|
||||
public static DataNode<ProjectData> refreshProject(@NotNull final Project project,
|
||||
@NotNull final ProjectSystemId externalSystemId,
|
||||
@NotNull final String externalProjectPath,
|
||||
@NotNull final Ref<String> errorMessageHolder,
|
||||
@NotNull final Ref<String> errorDetailsHolder,
|
||||
final boolean resolveLibraries,
|
||||
final boolean modal)
|
||||
public static void refreshProject(@NotNull final Project project,
|
||||
@NotNull final ProjectSystemId externalSystemId,
|
||||
@NotNull final String externalProjectPath,
|
||||
@NotNull final ExternalProjectRefreshCallback callback,
|
||||
final boolean resolveLibraries,
|
||||
final boolean modal)
|
||||
{
|
||||
final Ref<DataNode<ProjectData>> externalProject = new Ref<DataNode<ProjectData>>();
|
||||
final TaskUnderProgress refreshProjectStructureTask = new TaskUnderProgress() {
|
||||
@SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "IOResourceOpenedButNotSafelyClosed"})
|
||||
@Override
|
||||
@@ -253,22 +238,20 @@ public class ExternalSystemUtil {
|
||||
ExternalSystemResolveProjectTask task
|
||||
= new ExternalSystemResolveProjectTask(externalSystemId, project, externalProjectPath, resolveLibraries);
|
||||
task.execute(indicator);
|
||||
externalProject.set(task.getExternalProject());
|
||||
final Throwable error = task.getError();
|
||||
if (error == null) {
|
||||
DataNode<ProjectData> externalProject = task.getExternalProject();
|
||||
callback.onSuccess(externalProject);
|
||||
return;
|
||||
}
|
||||
final String message = buildErrorMessage(error);
|
||||
String message = buildErrorMessage(error);
|
||||
if (StringUtil.isEmpty(message)) {
|
||||
errorMessageHolder.set(String.format(
|
||||
message = String.format(
|
||||
"Can't resolve %s project at '%s'. Reason: %s",
|
||||
ExternalSystemApiUtil.toReadableName(externalSystemId), externalProjectPath, message
|
||||
));
|
||||
);
|
||||
}
|
||||
else {
|
||||
errorMessageHolder.set(message);
|
||||
}
|
||||
errorDetailsHolder.set(extractDetails(error));
|
||||
callback.onFailure(message, extractDetails(error));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -310,12 +293,9 @@ public class ExternalSystemUtil {
|
||||
}
|
||||
}
|
||||
});
|
||||
return externalProject.get();
|
||||
}
|
||||
|
||||
private interface TaskUnderProgress {
|
||||
void execute(@NotNull ProgressIndicator indicator);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
|
||||
<postStartupActivity implementation="com.intellij.openapi.externalSystem.service.ExternalSystemStartupActivity"/>
|
||||
|
||||
<!--Generic services-->
|
||||
<applicationService serviceImplementation="com.intellij.openapi.externalSystem.service.ExternalSystemFacadeManager"/>
|
||||
<applicationService
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
<projectOpenProcessor implementation="org.jetbrains.plugins.gradle.service.settings.GradleProjectOpenProcessor"/>
|
||||
|
||||
<externalSystemManager implementation="org.jetbrains.plugins.gradle.GradleManager"/>
|
||||
<postStartupActivity implementation="org.jetbrains.plugins.gradle.sync.GradleStartupActivity"/>
|
||||
|
||||
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.service.GradleInstallationManager"/>
|
||||
|
||||
|
||||
+2
-2
@@ -68,7 +68,7 @@ public class GradleRefreshProjectAction extends AbstractGradleLinkedProjectActio
|
||||
// return;
|
||||
//}
|
||||
|
||||
myErrorMessage.set(null);
|
||||
ExternalSystemUtil.refreshProject(project, GradleConstants.SYSTEM_ID, myErrorMessage);
|
||||
//myErrorMessage.set(null);
|
||||
//ExternalSystemUtil.refreshProject(project, GradleConstants.SYSTEM_ID, myErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -46,7 +46,6 @@ import java.util.List;
|
||||
public class GradleProjectImportBuilder extends AbstractExternalProjectImportBuilder<ImportFromGradleControl> {
|
||||
|
||||
public GradleProjectImportBuilder(@NotNull ExternalSystemSettingsManager settingsManager, @NotNull ProjectDataManager dataManager) {
|
||||
// TODO den implement
|
||||
super(settingsManager, dataManager, new ImportFromGradleControl(), GradleConstants.SYSTEM_ID);
|
||||
}
|
||||
|
||||
@@ -72,6 +71,9 @@ public class GradleProjectImportBuilder extends AbstractExternalProjectImportBui
|
||||
|
||||
@Override
|
||||
protected void beforeCommit(@NotNull DataNode<ProjectData> dataNode, @NotNull Project project) {
|
||||
if (!ExternalSystemApiUtil.isNewProjectConstruction()) {
|
||||
return;
|
||||
}
|
||||
DataNode<JavaProjectData> javaProjectNode = ExternalSystemApiUtil.find(dataNode, JavaProjectData.KEY);
|
||||
if (javaProjectNode == null) {
|
||||
return;
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package org.jetbrains.plugins.gradle.sync;
|
||||
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.startup.StartupActivity;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.config.GradlePatcher;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
import org.jetbrains.plugins.gradle.util.GradleUtil;
|
||||
|
||||
/**
|
||||
* Performs gradle-specific actions on IJ project loading.
|
||||
* <p/>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 3/13/12 12:01 PM
|
||||
*/
|
||||
// TODO den generalize and move to 'external-system'
|
||||
public class GradleStartupActivity implements StartupActivity {
|
||||
@SuppressWarnings("UseOfArchaicSystemPropertyAccessors")
|
||||
@Override
|
||||
public void runActivity(@NotNull final Project project) {
|
||||
Runnable task = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO den implement
|
||||
// new GradlePatcher().patch(project);
|
||||
//
|
||||
// if (!Boolean.getBoolean(ExternalSystemConstants.NEWLY_IMPORTED_PROJECT)) {
|
||||
// ExternalSystemUtil.refreshProject(project, GradleConstants.SYSTEM_ID);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
if (project.isInitialized()) {
|
||||
task.run();
|
||||
}
|
||||
else {
|
||||
StartupManager.getInstance(project).registerPostStartupActivity(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user