gradle: module/project wizard fixes

related issues:
IDEA-119806 Gradle tool window doesn't appear until project is reopened;
IDEA-134144 Newly created Gradle module doesn't show in Gradle tasks panel;
IDEA-138454 Intellij 14.1 cannot Import correctly Module with Gradle;
This commit is contained in:
Vladislav.Soroka
2015-04-23 14:46:23 +03:00
parent 7564fd472f
commit ddee073492
47 changed files with 2435 additions and 1116 deletions
@@ -0,0 +1,28 @@
/*
* Copyright 2000-2015 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.model.project;
/**
* @author Vladislav.Soroka
* @since 4/14/2015
*/
public interface ProjectCoordinate {
String getGroupId();
String getArtifactId();
String getVersion();
}
@@ -17,6 +17,8 @@ public class ProjectData extends AbstractNamedData implements ExternalConfigPath
@NotNull private final String myLinkedExternalProjectPath;
@NotNull private String myIdeProjectFileDirectoryPath;
private String myGroup;
private String myVersion;
@Deprecated
public ProjectData(@NotNull ProjectSystemId owner,
@@ -87,4 +89,20 @@ public class ProjectData extends AbstractNamedData implements ExternalConfigPath
public String getId() {
return "";
}
public String getGroup() {
return myGroup;
}
public void setGroup(String group) {
myGroup = group;
}
public String getVersion() {
return myVersion;
}
public void setVersion(String version) {
myVersion = version;
}
}
@@ -0,0 +1,106 @@
/*
* Copyright 2000-2015 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.model.project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
public class ProjectId implements Serializable, ProjectCoordinate {
public static final String UNKNOWN_VALUE = "Unknown";
@Nullable private final String myGroupId;
@Nullable private final String myArtifactId;
@Nullable private final String myVersion;
public ProjectId(@Nullable String groupId, @Nullable String artifactId, @Nullable String version) {
myGroupId = groupId;
myArtifactId = artifactId;
myVersion = version;
}
@Nullable
public String getGroupId() {
return myGroupId;
}
@Nullable
public String getArtifactId() {
return myArtifactId;
}
@Nullable
public String getVersion() {
return myVersion;
}
@NotNull
public String getKey() {
StringBuilder builder = new StringBuilder();
append(builder, myGroupId);
append(builder, myArtifactId);
append(builder, myVersion);
return builder.toString();
}
@NotNull
public String getDisplayString() {
return getKey();
}
public static void append(StringBuilder builder, String part) {
if (builder.length() != 0) builder.append(':');
builder.append(part == null ? "<unknown>" : part);
}
@Override
public String toString() {
return getDisplayString();
}
public boolean equals(@Nullable String groupId, @Nullable String artifactId) {
if (myArtifactId != null ? !myArtifactId.equals(artifactId) : artifactId != null) return false;
if (myGroupId != null ? !myGroupId.equals(groupId) : groupId != null) return false;
return true;
}
public boolean equals(@Nullable String groupId, @Nullable String artifactId, @Nullable String version) {
if (!equals(groupId, artifactId)) return false;
if (myVersion != null ? !myVersion.equals(version) : version != null) return false;
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ProjectId other = (ProjectId)o;
return equals(other.getGroupId(), other.myArtifactId, other.myVersion);
}
@Override
public int hashCode() {
int result;
result = (myGroupId != null ? myGroupId.hashCode() : 0);
result = 31 * result + (myArtifactId != null ? myArtifactId.hashCode() : 0);
result = 31 * result + (myVersion != null ? myVersion.hashCode() : 0);
return result;
}
}
@@ -1,11 +1,20 @@
package com.intellij.openapi.externalSystem.service.project;
import com.intellij.openapi.externalSystem.model.project.LibraryData;
import com.intellij.openapi.externalSystem.model.project.LibraryDependencyData;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleOrderEntry;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
@@ -47,4 +56,35 @@ public interface PlatformFacade {
*/
@NotNull
String getLocalFileSystemPath(@NotNull VirtualFile file);
/**
* Creates a module of the specified type at the specified path and adds it to the project
* to which the module manager is related. {@link #commit()} must be called to
* bring the changes in effect.
*
*
* @param project
* @param filePath the path at which the module is created.
* @param moduleTypeId the ID of the module type to create.
* @return the module instance.
*/
Module newModule(Project project, @NotNull @NonNls String filePath, final String moduleTypeId);
ModifiableRootModel getModuleModifiableModel(Module module);
@Nullable
Module findIdeModule(@NotNull ModuleData module, @NotNull Project ideProject);
@Nullable
Module findIdeModule(@NotNull String ideModuleName, @NotNull Project ideProject);
@Nullable
Library findIdeLibrary(@NotNull LibraryData libraryData, @NotNull Project ideProject);
@SuppressWarnings("MethodMayBeStatic")
@Nullable
ModuleOrderEntry findIdeModuleDependency(@NotNull ModuleDependencyData dependency, @NotNull ModifiableRootModel model);
@Nullable
OrderEntry findIdeModuleOrderEntry(LibraryDependencyData data, Project project);
}
@@ -16,7 +16,7 @@
package com.intellij.openapi.externalSystem.action;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.externalSystem.view.ExternalProjectsView;
import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable;
*/
public abstract class ExternalSystemViewGearAction extends ExternalSystemToggleAction {
private ExternalProjectsView myView;
private ExternalProjectsViewImpl myView;
@Override
protected boolean isEnabled(AnActionEvent e) {
@@ -36,28 +36,28 @@ public abstract class ExternalSystemViewGearAction extends ExternalSystemToggleA
@Override
protected boolean doIsSelected(AnActionEvent e) {
final ExternalProjectsView view = getView();
final ExternalProjectsViewImpl view = getView();
return view != null && isSelected(view);
}
@Override
public void setSelected(AnActionEvent e, boolean state) {
final ExternalProjectsView view = getView();
final ExternalProjectsViewImpl view = getView();
if (view != null){
setSelected(view, state);
}
}
protected abstract boolean isSelected(@NotNull ExternalProjectsView view);
protected abstract boolean isSelected(@NotNull ExternalProjectsViewImpl view);
protected abstract void setSelected(@NotNull ExternalProjectsView view, boolean value);
protected abstract void setSelected(@NotNull ExternalProjectsViewImpl view, boolean value);
@Nullable
protected ExternalProjectsView getView() {
protected ExternalProjectsViewImpl getView() {
return myView;
}
public void setView(ExternalProjectsView view) {
public void setView(ExternalProjectsViewImpl view) {
myView = view;
}
}
@@ -1,8 +1,6 @@
package com.intellij.openapi.externalSystem.action;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData;
@@ -10,23 +8,15 @@ import com.intellij.openapi.externalSystem.model.project.ExternalConfigPathAware
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.externalSystem.view.ExternalSystemNode;
import com.intellij.openapi.externalSystem.view.ProjectNode;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
/**
@@ -70,31 +60,7 @@ public class RefreshExternalProjectAction extends ExternalSystemNodeAction<Abstr
// We save all documents because there is a possible case that there is an external system config file changed inside the ide.
FileDocumentManager.getInstance().saveAllDocuments();
final ProjectDataManager projectDataManager = ServiceManager.getService(ProjectDataManager.class);
ExternalSystemUtil.refreshProject(
project, projectSystemId, externalConfigPathAware.getLinkedExternalProjectPath(),
new ExternalProjectRefreshCallback() {
@Override
public void onSuccess(@Nullable final DataNode<ProjectData> externalProject) {
if (externalProject == null) {
return;
}
ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(project) {
@Override
public void execute() {
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
@Override
public void run() {
projectDataManager.importData(externalProject.getKey(), Collections.singleton(externalProject), project, true);
}
});
}
});
}
@Override
public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
}
}, false, ProgressExecutionMode.IN_BACKGROUND_ASYNC);
project, projectSystemId, externalConfigPathAware.getLinkedExternalProjectPath(), false, ProgressExecutionMode.IN_BACKGROUND_ASYNC);
}
}
@@ -16,7 +16,7 @@
package com.intellij.openapi.externalSystem.action.task;
import com.intellij.openapi.externalSystem.action.ExternalSystemViewGearAction;
import com.intellij.openapi.externalSystem.view.ExternalProjectsView;
import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl;
import org.jetbrains.annotations.NotNull;
/**
@@ -25,12 +25,12 @@ import org.jetbrains.annotations.NotNull;
*/
public class GroupTasksAction extends ExternalSystemViewGearAction {
@Override
protected boolean isSelected(@NotNull ExternalProjectsView view) {
protected boolean isSelected(@NotNull ExternalProjectsViewImpl view) {
return view.getGroupTasks();
}
@Override
protected void setSelected(@NotNull ExternalProjectsView view, boolean value) {
protected void setSelected(@NotNull ExternalProjectsViewImpl view, boolean value) {
view.setGroupTasks(value);
}
}
@@ -16,7 +16,7 @@
package com.intellij.openapi.externalSystem.action.task;
import com.intellij.openapi.externalSystem.action.ExternalSystemViewGearAction;
import com.intellij.openapi.externalSystem.view.ExternalProjectsView;
import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl;
import org.jetbrains.annotations.NotNull;
/**
@@ -25,12 +25,12 @@ import org.jetbrains.annotations.NotNull;
*/
public class ShowInheritedTasksAction extends ExternalSystemViewGearAction {
@Override
protected boolean isSelected(@NotNull ExternalProjectsView view) {
protected boolean isSelected(@NotNull ExternalProjectsViewImpl view) {
return view.showInheritedTasks();
}
@Override
protected void setSelected(@NotNull ExternalProjectsView view, boolean value) {
protected void setSelected(@NotNull ExternalProjectsViewImpl view, boolean value) {
view.setShowInheritedTasks(value);
}
}
@@ -17,6 +17,7 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.externalSystem.view.ExternalProjectsView;
import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
@@ -153,7 +154,8 @@ public class ExternalSystemNotificationManager {
NotificationGroup group;
if (notificationData.getBalloonGroup() == null) {
ExternalProjectsView externalProjectsView = ExternalProjectsManager.getInstance(myProject).getExternalProjectsView(externalSystemId);
group = externalProjectsView != null ? externalProjectsView.getNotificationGroup() : null;
group = externalProjectsView instanceof ExternalProjectsViewImpl ?
((ExternalProjectsViewImpl)externalProjectsView).getNotificationGroup() : null;
}
else {
final NotificationGroup registeredGroup = NotificationGroup.findRegisteredGroup(notificationData.getBalloonGroup());
@@ -1,17 +1,21 @@
package com.intellij.openapi.externalSystem.service.project;
import com.intellij.openapi.externalSystem.model.project.*;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
/**
* @author Denis Zhdanov
@@ -42,4 +46,95 @@ public class PlatformFacadeImpl implements PlatformFacade {
public String getLocalFileSystemPath(@NotNull VirtualFile file) {
return ExternalSystemApiUtil.getLocalFileSystemPath(file);
}
@Override
public Module newModule(Project project, @NotNull @NonNls String filePath, String moduleTypeId) {
final ModuleManager moduleManager = ModuleManager.getInstance(project);
return moduleManager.newModule(filePath, moduleTypeId);
}
@Override
public ModifiableRootModel getModuleModifiableModel(Module module) {
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
return moduleRootManager.getModifiableModel();
}
@Nullable
@Override
public Module findIdeModule(@NotNull ModuleData module, @NotNull Project ideProject) {
return findIdeModule(module.getInternalName(), ideProject);
}
@Nullable
@Override
public Module findIdeModule(@NotNull String ideModuleName, @NotNull Project ideProject) {
for (Module module : getModules(ideProject)) {
if (ideModuleName.equals(module.getName())) {
return module;
}
}
return null;
}
@Nullable
@Override
public Library findIdeLibrary(@NotNull final LibraryData libraryData, @NotNull Project ideProject) {
final LibraryTable libraryTable = getProjectLibraryTable(ideProject);
for (Library ideLibrary : libraryTable.getLibraries()) {
if (ExternalSystemApiUtil.isRelated(ideLibrary, libraryData)) return ideLibrary;
}
return null;
}
public boolean isOrphanProjectLibrary(@NotNull final Library library,
@NotNull final Iterable<Module> ideModules) {
RootPolicy<Boolean> visitor = new RootPolicy<Boolean>() {
@Override
public Boolean visitLibraryOrderEntry(LibraryOrderEntry ideDependency, Boolean value) {
return !ideDependency.isModuleLevel() && library == ideDependency.getLibrary();
}
};
for (Module module : ideModules) {
for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
if (entry.accept(visitor, false)) return false;
}
}
return true;
}
@SuppressWarnings("MethodMayBeStatic")
@Nullable
@Override
public ModuleOrderEntry findIdeModuleDependency(@NotNull ModuleDependencyData dependency, @NotNull ModifiableRootModel model) {
for (OrderEntry entry : model.getOrderEntries()) {
if (entry instanceof ModuleOrderEntry) {
ModuleOrderEntry candidate = (ModuleOrderEntry)entry;
if (dependency.getInternalName().equals(candidate.getModuleName()) &&
dependency.getScope().equals(candidate.getScope())) {
return candidate;
}
}
}
return null;
}
@Nullable
@Override
public OrderEntry findIdeModuleOrderEntry(LibraryDependencyData data, Project project) {
Module ownerIdeModule = findIdeModule(data.getOwnerModule(), project);
if (ownerIdeModule == null) return null;
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(ownerIdeModule);
for (OrderEntry entry : moduleRootManager.getOrderEntries()) {
if (entry instanceof LibraryOrderEntry) {
if (((LibraryOrderEntry)entry).isModuleLevel() && data.getLevel() != LibraryLevel.MODULE) continue;
}
if (data.getInternalName().equals(entry.getPresentableName())) {
return entry;
}
}
return null;
}
}
@@ -1,12 +1,13 @@
package com.intellij.openapi.externalSystem.service.project;
import com.intellij.openapi.externalSystem.model.project.*;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.model.project.LibraryData;
import com.intellij.openapi.externalSystem.model.project.LibraryDependencyData;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,26 +27,17 @@ public class ProjectStructureHelper {
@Nullable
public Module findIdeModule(@NotNull ModuleData module, @NotNull Project ideProject) {
return findIdeModule(module.getInternalName(), ideProject);
return myFacade.findIdeModule(module, ideProject);
}
@Nullable
public Module findIdeModule(@NotNull String ideModuleName, @NotNull Project ideProject) {
for (Module module : myFacade.getModules(ideProject)) {
if (ideModuleName.equals(module.getName())) {
return module;
}
}
return null;
return myFacade.findIdeModule(ideModuleName, ideProject);
}
@Nullable
public Library findIdeLibrary(@NotNull final LibraryData libraryData, @NotNull Project ideProject) {
final LibraryTable libraryTable = myFacade.getProjectLibraryTable(ideProject);
for (Library ideLibrary : libraryTable.getLibraries()) {
if (ExternalSystemApiUtil.isRelated(ideLibrary, libraryData)) return ideLibrary;
}
return null;
return myFacade.findIdeLibrary(libraryData, ideProject);
}
public static boolean isOrphanProjectLibrary(@NotNull final Library library,
@@ -67,34 +59,11 @@ public class ProjectStructureHelper {
@SuppressWarnings("MethodMayBeStatic")
@Nullable
public ModuleOrderEntry findIdeModuleDependency(@NotNull ModuleDependencyData dependency, @NotNull ModifiableRootModel model) {
for (OrderEntry entry : model.getOrderEntries()) {
if (entry instanceof ModuleOrderEntry) {
ModuleOrderEntry candidate = (ModuleOrderEntry)entry;
if (dependency.getInternalName().equals(candidate.getModuleName()) &&
dependency.getScope().equals(candidate.getScope())) {
return candidate;
}
}
}
return null;
return myFacade.findIdeModuleDependency(dependency, model);
}
@Nullable
public OrderEntry findIdeModuleOrderEntry(LibraryDependencyData data, Project project) {
Module ownerIdeModule = findIdeModule(data.getOwnerModule(), project);
if (ownerIdeModule == null) return null;
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(ownerIdeModule);
for (OrderEntry entry : moduleRootManager.getOrderEntries()) {
if (entry instanceof LibraryOrderEntry) {
if (((LibraryOrderEntry)entry).isModuleLevel() && data.getLevel() != LibraryLevel.MODULE) continue;
}
if (data.getInternalName().equals(entry.getPresentableName())) {
return entry;
}
}
return null;
return myFacade.findIdeModuleOrderEntry(data, project);
}
}
@@ -15,7 +15,10 @@
*/
package com.intellij.openapi.externalSystem.service.project.manage;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.project.AbstractDependencyData;
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
@@ -36,9 +39,16 @@ import java.util.Map;
*/
@Order(ExternalSystemConstants.BUILTIN_SERVICE_ORDER)
public abstract class AbstractDependencyDataService<E extends AbstractDependencyData<?>, I extends ExportableOrderEntry>
implements ProjectDataService<E, I>
implements ProjectDataServiceEx<E, I>
{
public void importData(@NotNull final Collection<DataNode<E>> toImport,
@NotNull final Project project,
final boolean synchronous) {
final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
importData(toImport, project, platformFacade, synchronous);
}
public void setScope(@NotNull final DependencyScope scope, @NotNull final ExportableOrderEntry dependency, boolean synchronous) {
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(dependency.getOwnerModule()) {
@Override
@@ -69,8 +79,8 @@ public abstract class AbstractDependencyDataService<E extends AbstractDependency
private static void doForDependency(@NotNull ExportableOrderEntry entry, @NotNull Consumer<ExportableOrderEntry> consumer) {
// We need to get an up-to-date modifiable model to work with.
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(entry.getOwnerModule());
final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
final ModifiableRootModel moduleRootModel =
ModifiableModelsProvider.SERVICE.getInstance().getModuleModifiableModel(entry.getOwnerModule());
try {
// The thing is that intellij created order entry objects every time new modifiable model is created,
// that's why we can't use target dependency object as is but need to get a reference to the current
@@ -89,13 +99,22 @@ public abstract class AbstractDependencyDataService<E extends AbstractDependency
@Override
public void removeData(@NotNull Collection<? extends I> toRemove, @NotNull Project project, boolean synchronous) {
final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
removeData(toRemove, project, platformFacade, synchronous);
}
@Override
public void removeData(@NotNull Collection<? extends I> toRemove,
@NotNull Project project,
@NotNull final PlatformFacade platformFacade,
boolean synchronous) {
if (toRemove.isEmpty()) {
return;
}
Map<Module, Collection<ExportableOrderEntry>> byModule = groupByModule(toRemove);
for (Map.Entry<Module, Collection<ExportableOrderEntry>> entry : byModule.entrySet()) {
removeData(entry.getValue(), entry.getKey(), synchronous);
removeData(entry.getValue(), entry.getKey(), platformFacade, synchronous);
}
}
@@ -111,8 +130,11 @@ public abstract class AbstractDependencyDataService<E extends AbstractDependency
}
return result;
}
public void removeData(@NotNull Collection<? extends ExportableOrderEntry> toRemove, @NotNull final Module module, boolean synchronous) {
protected void removeData(@NotNull Collection<? extends ExportableOrderEntry> toRemove,
@NotNull final Module module,
@NotNull final PlatformFacade platformFacade,
boolean synchronous) {
if (toRemove.isEmpty()) {
return;
}
@@ -120,8 +142,7 @@ public abstract class AbstractDependencyDataService<E extends AbstractDependency
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(dependency.getOwnerModule()) {
@Override
public void execute() {
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
final ModifiableRootModel moduleRootModel = platformFacade.getModuleModifiableModel(module);
try {
// The thing is that intellij created order entry objects every time new modifiable model is created,
// that's why we can't use target dependency object as is but need to get a reference to the current
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.externalSystem.service.project.manage;
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.Key;
@@ -24,7 +25,7 @@ import com.intellij.openapi.externalSystem.model.project.ContentRootData;
import com.intellij.openapi.externalSystem.model.project.ContentRootData.SourceRoot;
import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
@@ -64,33 +65,35 @@ import java.util.Map;
* @since 2/7/12 3:20 PM
*/
@Order(ExternalSystemConstants.BUILTIN_SERVICE_ORDER)
public class ContentRootDataService implements ProjectDataService<ContentRootData, ContentEntry> {
public class ContentRootDataService implements ProjectDataServiceEx<ContentRootData, ContentEntry> {
private static final Logger LOG = Logger.getInstance("#" + ContentRootDataService.class.getName());
@NotNull private final ProjectStructureHelper myProjectStructureHelper;
public ContentRootDataService(@NotNull ProjectStructureHelper helper) {
myProjectStructureHelper = helper;
}
@NotNull
@Override
public Key<ContentRootData> getTargetDataKey() {
return ProjectKeys.CONTENT_ROOT;
}
public void importData(@NotNull final Collection<DataNode<ContentRootData>> toImport,
@NotNull final Project project,
final boolean synchronous) {
final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
importData(toImport, project, platformFacade, synchronous);
}
@Override
public void importData(@NotNull final Collection<DataNode<ContentRootData>> toImport,
@NotNull final Project project,
boolean synchronous) {
@NotNull final PlatformFacade platformFacade,
final boolean synchronous) {
if (toImport.isEmpty()) {
return;
}
Map<DataNode<ModuleData>, List<DataNode<ContentRootData>>> byModule = ExternalSystemApiUtil.groupBy(toImport, ProjectKeys.MODULE);
for (Map.Entry<DataNode<ModuleData>, List<DataNode<ContentRootData>>> entry : byModule.entrySet()) {
final Module module = myProjectStructureHelper.findIdeModule(entry.getKey().getData(), project);
final Module module = platformFacade.findIdeModule(entry.getKey().getData(), project);
if (module == null) {
LOG.warn(String.format(
"Can't import content roots. Reason: target module (%s) is not found at the ide. Content roots: %s",
@@ -237,6 +240,13 @@ public class ContentRootDataService implements ProjectDataService<ContentRootDat
public void removeData(@NotNull Collection<? extends ContentEntry> toRemove, @NotNull Project project, boolean synchronous) {
}
@Override
public void removeData(@NotNull Collection<? extends ContentEntry> toRemove,
@NotNull Project project,
@NotNull PlatformFacade platformFacade,
boolean synchronous) {
}
private static String toVfsUrl(@NotNull String path) {
return LocalFileSystem.PROTOCOL_PREFIX + path;
}
@@ -31,6 +31,7 @@ import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.task.TaskData;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings;
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.module.ModuleTypeId;
import com.intellij.openapi.project.Project;
@@ -47,6 +48,7 @@ import java.io.*;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -189,6 +191,22 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent {
changed.set(true);
}
// restore linked project sub-modules
ExternalProjectSettings linkedProjectSettings =
manager.getSettingsProvider().fun(myProject).getLinkedProjectSettings(externalProjectPath);
if (linkedProjectSettings != null && ContainerUtil.isEmpty(linkedProjectSettings.getModules())) {
final Set<String> modulePaths = ContainerUtil.map2Set(
ExternalSystemApiUtil.findAllRecursively(externalProjectInfo.getExternalProjectStructure(), ProjectKeys.MODULE),
new Function<DataNode<ModuleData>, String>() {
@Override
public String fun(DataNode<ModuleData> node) {
return node.getData().getLinkedExternalProjectPath();
}
});
linkedProjectSettings.setModules(modulePaths);
}
}
}
}
@@ -27,6 +27,7 @@ import com.intellij.openapi.externalSystem.model.task.TaskData;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.externalSystem.view.ExternalProjectsView;
import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl;
import com.intellij.openapi.externalSystem.view.ExternalProjectsViewState;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
@@ -90,11 +91,15 @@ public class ExternalProjectsManager implements PersistentStateComponent<Externa
}
public void registerView(@NotNull ExternalProjectsView externalProjectsView) {
assert getExternalProjectsView(externalProjectsView.getSystemId()) == null;
init();
myProjectsViews.add(externalProjectsView);
externalProjectsView.loadState(
myState.getExternalSystemsState().get(externalProjectsView.getSystemId().getId()).getProjectsViewState());
externalProjectsView.init();
if (externalProjectsView instanceof ExternalProjectsViewImpl) {
ExternalProjectsViewImpl view = (ExternalProjectsViewImpl)externalProjectsView;
view.loadState(myState.getExternalSystemsState().get(externalProjectsView.getSystemId().getId()).getProjectsViewState());
view.init();
}
}
@Nullable
@@ -153,6 +158,7 @@ public class ExternalProjectsManager implements PersistentStateComponent<Externa
public void forgetExternalProjectData(@NotNull ProjectSystemId projectSystemId, @NotNull String linkedProjectPath) {
ExternalProjectsDataStorage.getInstance(myProject).remove(projectSystemId, linkedProjectPath);
ExternalSystemUtil.scheduleExternalViewStructureUpdate(myProject, projectSystemId);
}
@NotNull
@@ -160,10 +166,12 @@ public class ExternalProjectsManager implements PersistentStateComponent<Externa
public ExternalProjectsState getState() {
ApplicationManager.getApplication().assertIsDispatchThread();
for (ExternalProjectsView externalProjectsView : myProjectsViews) {
final ExternalProjectsViewState externalProjectsViewState = externalProjectsView.getState();
final ExternalProjectsState.State state = myState.getExternalSystemsState().get(externalProjectsView.getSystemId().getId());
assert state != null;
state.setProjectsViewState(externalProjectsViewState);
if (externalProjectsView instanceof ExternalProjectsViewImpl) {
final ExternalProjectsViewState externalProjectsViewState = ((ExternalProjectsViewImpl)externalProjectsView).getState();
final ExternalProjectsState.State state = myState.getExternalSystemsState().get(externalProjectsView.getSystemId().getId());
assert state != null;
state.setProjectsViewState(externalProjectsViewState);
}
}
return myState;
}
@@ -1,5 +1,6 @@
package com.intellij.openapi.externalSystem.service.project.manage;
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.Key;
@@ -8,7 +9,6 @@ import com.intellij.openapi.externalSystem.model.project.LibraryData;
import com.intellij.openapi.externalSystem.model.project.LibraryPathType;
import com.intellij.openapi.externalSystem.service.project.ExternalLibraryPathTypeMapper;
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
@@ -38,7 +38,7 @@ import java.util.Set;
* @since 2/15/12 11:32 AM
*/
@Order(ExternalSystemConstants.BUILTIN_SERVICE_ORDER)
public class LibraryDataService implements ProjectDataService<LibraryData, Library> {
public class LibraryDataService implements ProjectDataServiceEx<LibraryData, Library> {
private static final Logger LOG = Logger.getInstance("#" + LibraryDataService.class.getName());
@NotNull public static final NotNullFunction<String, File> PATH_TO_FILE = new NotNullFunction<String, File>() {
@@ -49,16 +49,9 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
}
};
@NotNull private final PlatformFacade myPlatformFacade;
@NotNull private final ProjectStructureHelper myProjectStructureHelper;
@NotNull private final ExternalLibraryPathTypeMapper myLibraryPathTypeMapper;
public LibraryDataService(@NotNull PlatformFacade platformFacade,
@NotNull ProjectStructureHelper helper,
@NotNull ExternalLibraryPathTypeMapper mapper)
{
myPlatformFacade = platformFacade;
myProjectStructureHelper = helper;
public LibraryDataService(@NotNull ExternalLibraryPathTypeMapper mapper) {
myLibraryPathTypeMapper = mapper;
}
@@ -68,22 +61,35 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
return ProjectKeys.LIBRARY;
}
public void importData(@NotNull final Collection<DataNode<LibraryData>> toImport,
@NotNull final Project project,
final boolean synchronous) {
final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
importData(toImport, project, platformFacade, synchronous);
}
@Override
public void importData(@NotNull Collection<DataNode<LibraryData>> toImport, @NotNull Project project, boolean synchronous) {
public void importData(@NotNull final Collection<DataNode<LibraryData>> toImport,
@NotNull final Project project,
@NotNull final PlatformFacade platformFacade,
final boolean synchronous) {
for (DataNode<LibraryData> dataNode : toImport) {
importLibrary(dataNode.getData(), project, synchronous);
importLibrary(dataNode.getData(), project, platformFacade, synchronous);
}
}
public void importLibrary(@NotNull final LibraryData toImport, @NotNull final Project project, boolean synchronous) {
private void importLibrary(@NotNull final LibraryData toImport,
@NotNull final Project project,
@NotNull final PlatformFacade platformFacade,
boolean synchronous) {
Map<OrderRootType, Collection<File>> libraryFiles = prepareLibraryFiles(toImport);
Library library = myProjectStructureHelper.findIdeLibrary(toImport, project);
Library library = platformFacade.findIdeLibrary(toImport, project);
if (library != null) {
syncPaths(toImport, library, project, synchronous);
return;
}
importLibrary(toImport.getInternalName(), libraryFiles, project, synchronous);
importLibrary(toImport.getInternalName(), libraryFiles, project, platformFacade, synchronous);
}
@NotNull
@@ -99,16 +105,17 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
return result;
}
public void importLibrary(@NotNull final String libraryName,
@NotNull final Map<OrderRootType, Collection<File>> libraryFiles,
@NotNull final Project project,
boolean synchronous)
private void importLibrary(@NotNull final String libraryName,
@NotNull final Map<OrderRootType, Collection<File>> libraryFiles,
@NotNull final Project project,
@NotNull final PlatformFacade platformFacade,
boolean synchronous)
{
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
@Override
public void execute() {
// Is assumed to be called from the EDT.
final LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(project);
final LibraryTable libraryTable = platformFacade.getProjectLibraryTable(project);
final LibraryTable.ModifiableModel projectLibraryModel = libraryTable.getModifiableModel();
final Library intellijLibrary;
try {
@@ -173,14 +180,24 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
}
}
@Override
public void removeData(@NotNull final Collection<? extends Library> libraries, @NotNull final Project project, boolean synchronous) {
final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
removeData(libraries, project, platformFacade, synchronous);
}
@Override
public void removeData(@NotNull final Collection<? extends Library> libraries,
@NotNull final Project project,
@NotNull final PlatformFacade platformFacade,
boolean synchronous) {
if (libraries.isEmpty()) {
return;
}
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
@Override
public void execute() {
final LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(project);
final LibraryTable libraryTable = platformFacade.getProjectLibraryTable(project);
final LibraryTable.ModifiableModel model = libraryTable.getModifiableModel();
try {
for (Library library : libraries) {
@@ -21,7 +21,6 @@ import com.intellij.openapi.externalSystem.model.Key;
import com.intellij.openapi.externalSystem.model.ProjectKeys;
import com.intellij.openapi.externalSystem.model.project.*;
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
@@ -51,18 +50,12 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
private static final Logger LOG = Logger.getInstance("#" + LibraryDependencyDataService.class.getName());
@NotNull private final PlatformFacade myPlatformFacade;
@NotNull private final ProjectStructureHelper myProjectStructureHelper;
@NotNull private final ModuleDataService myModuleManager;
@NotNull private final LibraryDataService myLibraryManager;
public LibraryDependencyDataService(@NotNull PlatformFacade platformFacade,
@NotNull ProjectStructureHelper helper,
@NotNull ModuleDataService moduleManager,
public LibraryDependencyDataService(@NotNull ModuleDataService moduleManager,
@NotNull LibraryDataService libraryManager)
{
myPlatformFacade = platformFacade;
myProjectStructureHelper = helper;
myModuleManager = moduleManager;
myLibraryManager = libraryManager;
}
@@ -74,17 +67,20 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
}
@Override
public void importData(@NotNull Collection<DataNode<LibraryDependencyData>> toImport, @NotNull Project project, boolean synchronous) {
public void importData(@NotNull Collection<DataNode<LibraryDependencyData>> toImport,
@NotNull Project project,
@NotNull PlatformFacade platformFacade,
boolean synchronous) {
if (toImport.isEmpty()) {
return;
}
Map<DataNode<ModuleData>, List<DataNode<LibraryDependencyData>>> byModule = ExternalSystemApiUtil.groupBy(toImport, MODULE);
for (Map.Entry<DataNode<ModuleData>, List<DataNode<LibraryDependencyData>>> entry : byModule.entrySet()) {
Module module = myProjectStructureHelper.findIdeModule(entry.getKey().getData(), project);
Module module = platformFacade.findIdeModule(entry.getKey().getData(), project);
if (module == null) {
myModuleManager.importData(Collections.singleton(entry.getKey()), project, true);
module = myProjectStructureHelper.findIdeModule(entry.getKey().getData(), project);
module = platformFacade.findIdeModule(entry.getKey().getData(), project);
if (module == null) {
LOG.warn(String.format(
"Can't import library dependencies %s. Reason: target module (%s) is not found at the ide and can't be imported",
@@ -93,18 +89,19 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
continue;
}
}
importData(entry.getValue(), module, synchronous);
importData(entry.getValue(), module, platformFacade, synchronous);
}
}
public void importData(@NotNull final Collection<DataNode<LibraryDependencyData>> nodesToImport,
@NotNull final Module module,
@NotNull final PlatformFacade platformFacade,
final boolean synchronous)
{
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(module) {
@Override
public void execute() {
importMissingProjectLibraries(module, nodesToImport, synchronous);
importMissingProjectLibraries(module, platformFacade, nodesToImport, synchronous);
// The general idea is to import all external project library dependencies and module libraries which don't present at the
// ide side yet and remove all project library dependencies and module libraries which present at the ide but not at
@@ -137,10 +134,11 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
}
}
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
//ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
//final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
final ModifiableRootModel moduleRootModel = ModifiableModelsProvider.SERVICE.getInstance().getModuleModifiableModel(module);
LibraryTable moduleLibraryTable = moduleRootModel.getModuleLibraryTable();
LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(module.getProject());
LibraryTable libraryTable = platformFacade.getProjectLibraryTable(module.getProject());
try {
syncExistingAndRemoveObsolete(moduleLibrariesToImport, projectLibrariesToImport, toImport, moduleRootModel, hasUnresolved);
@@ -258,10 +256,11 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
}
private void importMissingProjectLibraries(@NotNull Module module,
@NotNull PlatformFacade platformFacade,
@NotNull Collection<DataNode<LibraryDependencyData>> nodesToImport,
boolean synchronous)
{
LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(module.getProject());
LibraryTable libraryTable = platformFacade.getProjectLibraryTable(module.getProject());
List<DataNode<LibraryData>> librariesToImport = ContainerUtilRt.newArrayList();
for (DataNode<LibraryDependencyData> dataNode : nodesToImport) {
final LibraryDependencyData dependencyData = dataNode.getData();
@@ -2,6 +2,7 @@ package com.intellij.openapi.externalSystem.service.project.manage;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
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.Key;
@@ -9,7 +10,7 @@ import com.intellij.openapi.externalSystem.model.ProjectKeys;
import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
@@ -38,7 +39,7 @@ import java.util.concurrent.TimeUnit;
* @since 2/7/12 2:49 PM
*/
@Order(ExternalSystemConstants.BUILTIN_SERVICE_ORDER)
public class ModuleDataService implements ProjectDataService<ModuleData, Module> {
public class ModuleDataService implements ProjectDataServiceEx<ModuleData, Module> {
public static final com.intellij.openapi.util.Key<ModuleData> MODULE_DATA_KEY = com.intellij.openapi.util.Key.create("MODULE_DATA_KEY");
@@ -52,12 +53,6 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
@NotNull private final ProjectStructureHelper myProjectStructureHelper;
public ModuleDataService(@NotNull ProjectStructureHelper helper) {
myProjectStructureHelper = helper;
}
@NotNull
@Override
public Key<ModuleData> getTargetDataKey() {
@@ -66,8 +61,16 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
public void importData(@NotNull final Collection<DataNode<ModuleData>> toImport,
@NotNull final Project project,
final boolean synchronous)
{
final boolean synchronous) {
final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
importData(toImport, project, platformFacade, synchronous);
}
@Override
public void importData(@NotNull final Collection<DataNode<ModuleData>> toImport,
@NotNull final Project project,
@NotNull final PlatformFacade platformFacade,
final boolean synchronous) {
if (toImport.isEmpty()) {
return;
}
@@ -78,40 +81,40 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
@Override
public void execute() {
final Collection<DataNode<ModuleData>> toCreate = filterExistingModules(toImport, project);
final Collection<DataNode<ModuleData>> toCreate = filterExistingModules(toImport, project, platformFacade);
if (!toCreate.isEmpty()) {
createModules(toCreate, project);
createModules(toCreate, project, platformFacade);
}
for (DataNode<ModuleData> node : toImport) {
Module module = myProjectStructureHelper.findIdeModule(node.getData(), project);
Module module = platformFacade.findIdeModule(node.getData(), project);
if (module != null) {
syncPaths(module, node.getData());
syncPaths(module, platformFacade, node.getData());
}
}
}
}
});
}
private void createModules(@NotNull final Collection<DataNode<ModuleData>> toCreate, @NotNull final Project project) {
private void createModules(@NotNull final Collection<DataNode<ModuleData>> toCreate,
@NotNull final Project project,
@NotNull final PlatformFacade platformFacade) {
removeExistingModulesConfigs(toCreate, project);
Application application = ApplicationManager.getApplication();
final Map<DataNode<ModuleData>, Module> moduleMappings = ContainerUtilRt.newHashMap();
application.runWriteAction(new Runnable() {
@Override
public void run() {
final ModuleManager moduleManager = ModuleManager.getInstance(project);
for (DataNode<ModuleData> module : toCreate) {
importModule(moduleManager, module);
importModule(module);
}
}
private void importModule(@NotNull ModuleManager moduleManager, @NotNull DataNode<ModuleData> module) {
private void importModule(@NotNull DataNode<ModuleData> module) {
ModuleData data = module.getData();
final Module created = moduleManager.newModule(data.getModuleFilePath(), data.getModuleTypeId());
final Module created = platformFacade.newModule(project, data.getModuleFilePath(), data.getModuleTypeId());
// Ensure that the dependencies are clear (used to be not clear when manually removing the module and importing it via gradle)
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(created);
final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
final ModifiableRootModel moduleRootModel = platformFacade.getModuleModifiableModel(created);
moduleRootModel.inheritSdk();
setModuleOptions(created, module);
@@ -142,13 +145,13 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
}
@NotNull
private Collection<DataNode<ModuleData>> filterExistingModules(@NotNull Collection<DataNode<ModuleData>> modules,
@NotNull Project project)
private static Collection<DataNode<ModuleData>> filterExistingModules(@NotNull Collection<DataNode<ModuleData>> modules,
@NotNull Project project, @NotNull PlatformFacade platformFacade)
{
Collection<DataNode<ModuleData>> result = ContainerUtilRt.newArrayList();
for (DataNode<ModuleData> node : modules) {
ModuleData moduleData = node.getData();
Module module = myProjectStructureHelper.findIdeModule(moduleData, project);
Module module = platformFacade.findIdeModule(moduleData, project);
if (module == null) {
result.add(node);
}
@@ -184,8 +187,8 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
});
}
private static void syncPaths(@NotNull Module module, @NotNull ModuleData data) {
ModifiableRootModel modifiableModel = ModuleRootManager.getInstance(module).getModifiableModel();
private static void syncPaths(@NotNull Module module, @NotNull PlatformFacade platformFacade, @NotNull ModuleData data) {
ModifiableRootModel modifiableModel = platformFacade.getModuleModifiableModel(module);
CompilerModuleExtension extension = modifiableModel.getModuleExtension(CompilerModuleExtension.class);
if (extension == null) {
modifiableModel.dispose();
@@ -209,9 +212,21 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
modifiableModel.commit();
}
}
@Override
public void removeData(@NotNull final Collection<? extends Module> modules, @NotNull Project project, boolean synchronous) {
public void removeData(@NotNull Collection<? extends Module> toRemove,
@NotNull Project project,
boolean synchronous) {
final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
removeData(toRemove, project, platformFacade, synchronous);
}
@Override
public void removeData(@NotNull final Collection<? extends Module> modules,
@NotNull Project project,
@NotNull PlatformFacade platformFacade,
boolean synchronous) {
if (modules.isEmpty()) {
return;
}
@@ -219,7 +234,7 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
@Override
public void execute() {
for (Module module : modules) {
if(module.isDisposed()) continue;
if (module.isDisposed()) continue;
ModuleManager moduleManager = ModuleManager.getInstance(module.getProject());
String path = module.getModuleFilePath();
@@ -241,7 +256,7 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
module.clearOption(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY);
module.clearOption(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
}
private class ImportModulesTask implements Runnable {
private final Project myProject;
@@ -22,7 +22,7 @@ import com.intellij.openapi.externalSystem.model.ProjectKeys;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
@@ -51,11 +51,9 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService<M
private static final Logger LOG = Logger.getInstance("#" + ModuleDependencyDataService.class.getName());
@NotNull private final ProjectStructureHelper myProjectStructureHelper;
@NotNull private final ModuleDataService myModuleDataManager;
public ModuleDependencyDataService(@NotNull ProjectStructureHelper projectStructureHelper, @NotNull ModuleDataService manager) {
myProjectStructureHelper = projectStructureHelper;
public ModuleDependencyDataService(@NotNull ModuleDataService manager) {
myModuleDataManager = manager;
}
@@ -66,13 +64,16 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService<M
}
@Override
public void importData(@NotNull Collection<DataNode<ModuleDependencyData>> toImport, @NotNull Project project, boolean synchronous) {
public void importData(@NotNull Collection<DataNode<ModuleDependencyData>> toImport,
@NotNull Project project,
@NotNull PlatformFacade platformFacade,
boolean synchronous) {
Map<DataNode<ModuleData>, List<DataNode<ModuleDependencyData>>> byModule= ExternalSystemApiUtil.groupBy(toImport, MODULE);
for (Map.Entry<DataNode<ModuleData>, List<DataNode<ModuleDependencyData>>> entry : byModule.entrySet()) {
Module ideModule = myProjectStructureHelper.findIdeModule(entry.getKey().getData(), project);
Module ideModule = platformFacade.findIdeModule(entry.getKey().getData(), project);
if (ideModule == null) {
myModuleDataManager.importData(Collections.singleton(entry.getKey()), project, true);
ideModule = myProjectStructureHelper.findIdeModule(entry.getKey().getData(), project);
ideModule = platformFacade.findIdeModule(entry.getKey().getData(), project);
}
if (ideModule == null) {
LOG.warn(String.format(
@@ -81,13 +82,14 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService<M
));
continue;
}
importData(entry.getValue(), ideModule, synchronous);
importData(entry.getValue(), ideModule, platformFacade, synchronous);
}
}
public void importData(@NotNull final Collection<DataNode<ModuleDependencyData>> toImport,
@NotNull final Module module,
final boolean synchronous)
private void importData(@NotNull final Collection<DataNode<ModuleDependencyData>> toImport,
@NotNull final Module module,
@NotNull final PlatformFacade platformFacade,
final boolean synchronous)
{
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(module) {
@Override
@@ -100,19 +102,18 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService<M
toRemove.put(Pair.create(e.getModuleName(), e.getScope()), e);
}
}
final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
final ModifiableRootModel moduleRootModel = platformFacade.getModuleModifiableModel(module);
try {
for (DataNode<ModuleDependencyData> dependencyNode : toImport) {
final ModuleDependencyData dependencyData = dependencyNode.getData();
toRemove.remove(Pair.create(dependencyData.getInternalName(), dependencyData.getScope()));
final String moduleName = dependencyData.getInternalName();
Module ideDependencyModule = myProjectStructureHelper.findIdeModule(moduleName, module.getProject());
Module ideDependencyModule = platformFacade.findIdeModule(moduleName, module.getProject());
if (ideDependencyModule == null) {
DataNode<ProjectData> projectNode = dependencyNode.getDataNode(ProjectKeys.PROJECT);
if (projectNode != null) {
DataNode<ModuleData> n
= ExternalSystemApiUtil.find(projectNode, MODULE, new BooleanFunction<DataNode<ModuleData>>() {
DataNode<ModuleData> n = ExternalSystemApiUtil.find(projectNode, MODULE, new BooleanFunction<DataNode<ModuleData>>() {
@Override
public boolean fun(DataNode<ModuleData> node) {
return node.getData().equals(dependencyData.getTarget());
@@ -120,7 +121,7 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService<M
});
if (n != null) {
myModuleDataManager.importData(Collections.singleton(n), module.getProject(), true);
ideDependencyModule = myProjectStructureHelper.findIdeModule(moduleName, module.getProject());
ideDependencyModule = platformFacade.findIdeModule(moduleName, module.getProject());
}
}
}
@@ -134,7 +135,7 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService<M
continue;
}
ModuleOrderEntry orderEntry = myProjectStructureHelper.findIdeModuleDependency(dependencyData, moduleRootModel);
ModuleOrderEntry orderEntry = platformFacade.findIdeModuleDependency(dependencyData, moduleRootModel);
if (orderEntry == null) {
orderEntry = moduleRootModel.addModuleOrderEntry(ideDependencyModule);
}
@@ -147,7 +148,7 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService<M
}
if (!toRemove.isEmpty()) {
removeData(toRemove.values(), module, synchronous);
removeData(toRemove.values(), module, platformFacade, synchronous);
}
}
});
@@ -21,6 +21,7 @@ import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalProjectInfo;
import com.intellij.openapi.externalSystem.model.Key;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NotNullLazyValue;
@@ -28,7 +29,6 @@ import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,6 +36,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import static com.intellij.util.containers.ContainerUtil.map2Array;
/**
* Aggregates all {@link ProjectDataService#EP_NAME registered data services} and provides entry points for project data management.
*
@@ -47,12 +49,13 @@ public class ProjectDataManager {
private static final Logger LOG = Logger.getInstance("#" + ProjectDataManager.class.getName());
@NotNull private final NotNullLazyValue<Map<Key<?>, List<ProjectDataService<?, ?>>>> myServices;
private final PlatformFacade myPlatformFacade;
public static ProjectDataManager getInstance() {
return ServiceManager.getService(ProjectDataManager.class);
}
public ProjectDataManager() {
public ProjectDataManager(@NotNull PlatformFacade platformFacade) {
myServices = new NotNullLazyValue<Map<Key<?>, List<ProjectDataService<?, ?>>>>() {
@NotNull
@Override
@@ -72,6 +75,7 @@ public class ProjectDataManager {
return result;
}
};
myPlatformFacade = platformFacade;
}
@Nullable
@@ -82,7 +86,10 @@ public class ProjectDataManager {
}
@SuppressWarnings("unchecked")
public <T> void importData(@NotNull Collection<DataNode<?>> nodes, @NotNull Project project, boolean synchronous) {
public <T> void importData(@NotNull Collection<DataNode<?>> nodes,
@NotNull Project project,
@NotNull PlatformFacade platformFacade,
boolean synchronous) {
if (project.isDisposed()) return;
Map<Key<?>, List<DataNode<?>>> grouped = ExternalSystemApiUtil.group(nodes);
@@ -92,12 +99,20 @@ public class ProjectDataManager {
for (DataNode<?> node : entry.getValue()) {
dummy.add((DataNode<T>)node);
}
importData((Key<T>)entry.getKey(), dummy, project, synchronous);
importData((Key<T>)entry.getKey(), dummy, project, platformFacade, synchronous);
}
}
public <T> void importData(@NotNull Collection<DataNode<?>> nodes, @NotNull Project project, boolean synchronous) {
importData(nodes, project, myPlatformFacade, synchronous);
}
@SuppressWarnings("unchecked")
public <T> void importData(@NotNull Key<T> key, @NotNull Collection<DataNode<T>> nodes, @NotNull Project project, boolean synchronous) {
public <T> void importData(@NotNull Key<T> key,
@NotNull Collection<DataNode<T>> nodes,
@NotNull Project project,
@NotNull PlatformFacade platformFacade,
boolean synchronous) {
if (project.isDisposed()) return;
ensureTheDataIsReadyToUse((Collection)nodes);
@@ -110,7 +125,12 @@ public class ProjectDataManager {
}
else {
for (ProjectDataService<?, ?> service : services) {
((ProjectDataService<T, ?>)service).importData(nodes, project, synchronous);
if (service instanceof ProjectDataServiceEx) {
((ProjectDataServiceEx<T, ?>)service).importData(nodes, project, platformFacade, synchronous);
}
else {
((ProjectDataService<T, ?>)service).importData(nodes, project, synchronous);
}
}
}
@@ -118,7 +138,14 @@ public class ProjectDataManager {
for (DataNode<T> node : nodes) {
children.addAll(node.getChildren());
}
importData(children, project, synchronous);
importData(children, project, platformFacade, synchronous);
}
public <T> void importData(@NotNull Key<T> key,
@NotNull Collection<DataNode<T>> nodes,
@NotNull Project project,
boolean synchronous) {
importData(key, nodes, project, myPlatformFacade, synchronous);
}
public void ensureTheDataIsReadyToUse(DataNode dataNode) {
@@ -129,7 +156,7 @@ public class ProjectDataManager {
List<ProjectDataService<?, ?>> services = servicesByKey.get(dataNode.getKey());
if (services != null) {
try {
dataNode.prepareData(ContainerUtil.map2Array(services, ClassLoader.class, new Function<ProjectDataService<?, ?>, ClassLoader>() {
dataNode.prepareData(map2Array(services, ClassLoader.class, new Function<ProjectDataService<?, ?>, ClassLoader>() {
@Override
public ClassLoader fun(ProjectDataService<?, ?> service) {
return service.getClass().getClassLoader();
@@ -0,0 +1,40 @@
/*
* Copyright 2000-2015 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.manage;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* @author Vladislav.Soroka
* @since 4/13/2015
*/
public interface ProjectDataServiceEx<E, I> extends ProjectDataService<E, I> {
void importData(@NotNull Collection<DataNode<E>> toImport,
@NotNull Project project,
@NotNull PlatformFacade platformFacade,
boolean synchronous);
void removeData(@NotNull Collection<? extends I> toRemove,
@NotNull Project project,
@NotNull PlatformFacade platformFacade,
boolean synchronous);
}
@@ -1,17 +1,20 @@
package com.intellij.openapi.externalSystem.service.project.wizard;
import com.intellij.ide.util.projectWizard.WizardContext;
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;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.service.internal.ExternalSystemResolveProjectTask;
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
import com.intellij.openapi.externalSystem.service.project.PlatformFacadeImpl;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
import com.intellij.openapi.externalSystem.service.settings.AbstractImportFromExternalSystemControl;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
@@ -22,30 +25,28 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.options.ConfigurationException;
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.project.ProjectManager;
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.packaging.artifacts.ModifiableArtifactModel;
import com.intellij.projectImport.ProjectImportBuilder;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* GoF builder for gradle-backed projects.
@@ -77,7 +78,7 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
@Override
public List<DataNode<ProjectData>> getList() {
return Arrays.asList(myExternalProjectNode);
return Collections.singletonList(myExternalProjectNode);
}
@Override
@@ -100,6 +101,7 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
}
public void prepare(@NotNull WizardContext context) {
myControl.setShowProjectFormatPanel(context.isCreatingNewProject());
myControl.reset();
String pathToUse = getFileToImport();
myControl.setLinkedProjectPath(pathToUse);
@@ -110,71 +112,97 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
@Override
public List<Module> commit(final Project project,
ModifiableModuleModel model,
ModulesProvider modulesProvider,
ModifiableArtifactModel artifactModel)
final ModifiableModuleModel model,
final ModulesProvider modulesProvider,
final ModifiableArtifactModel artifactModel)
{
project.putUserData(ExternalSystemDataKeys.NEWLY_IMPORTED_PROJECT, Boolean.TRUE);
final DataNode<ProjectData> externalProjectNode = getExternalProjectNode();
if (externalProjectNode != null) {
beforeCommit(externalProjectNode, project);
}
StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() {
@SuppressWarnings("unchecked")
boolean isFromUI = model != null;
final List<Module> modules = ContainerUtil.newSmartList();
final PlatformFacade platformFacade = isFromUI ? new PlatformFacadeImpl() {
@NotNull
@Override
public void run() {
AbstractExternalSystemSettings systemSettings = ExternalSystemApiUtil.getSettings(project, myExternalSystemId);
final ExternalProjectSettings projectSettings = getCurrentExternalProjectSettings();
Set<ExternalProjectSettings> projects = ContainerUtilRt.newHashSet(systemSettings.getLinkedProjectsSettings());
// add current importing project settings to linked projects settings or replace if similar already exist
projects.remove(projectSettings);
projects.add(projectSettings);
public Collection<Module> getModules(@NotNull Project project) {
return ContainerUtil.list(modulesProvider.getModules());
}
systemSettings.copyFrom(myControl.getSystemSettings());
systemSettings.setLinkedProjectsSettings(projects);
@Override
public Module newModule(Project project, @NotNull @NonNls String filePath, String moduleTypeId) {
final Module module = model.newModule(filePath, moduleTypeId);
modules.add(module);
return module;
}
} : ServiceManager.getService(PlatformFacade.class);
AbstractExternalSystemSettings systemSettings = ExternalSystemApiUtil.getSettings(project, myExternalSystemId);
final ExternalProjectSettings projectSettings = getCurrentExternalProjectSettings();
if (externalProjectNode != null) {
ExternalSystemUtil.ensureToolWindowInitialized(project, myExternalSystemId);
ExternalSystemApiUtil.executeProjectChangeAction(new DisposeAwareProjectChange(project) {
@Override
public void execute() {
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
@Override
public void run() {
myProjectDataManager.importData(externalProjectNode.getKey(), Collections.singleton(externalProjectNode), project, true);
myExternalProjectNode = null;
}
});
}
});
//noinspection unchecked
Set<ExternalProjectSettings> projects = ContainerUtilRt.newHashSet(systemSettings.getLinkedProjectsSettings());
// add current importing project settings to linked projects settings or replace if similar already exist
projects.remove(projectSettings);
projects.add(projectSettings);
final Runnable resolveDependenciesTask = new Runnable() {
//noinspection unchecked
systemSettings.copyFrom(myControl.getSystemSettings());
//noinspection unchecked
systemSettings.setLinkedProjectsSettings(projects);
if (externalProjectNode != null) {
ExternalSystemApiUtil.executeProjectChangeAction(new DisposeAwareProjectChange(project) {
@Override
public void execute() {
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
@Override
public void run() {
String progressText = ExternalSystemBundle.message("progress.resolve.libraries", myExternalSystemId.getReadableName());
ProgressManager.getInstance().run(
new Task.Backgroundable(project, progressText, false) {
@Override
public void run(@NotNull final ProgressIndicator indicator) {
if(project.isDisposed()) return;
ExternalSystemResolveProjectTask task
= new ExternalSystemResolveProjectTask(myExternalSystemId, project, projectSettings.getExternalProjectPath(), false);
task.execute(indicator, ExternalSystemTaskNotificationListener.EP_NAME.getExtensions());
DataNode<ProjectData> projectWithResolvedLibraries = task.getExternalProject();
if (projectWithResolvedLibraries == null) {
return;
}
setupLibraries(projectWithResolvedLibraries, project);
}
});
myProjectDataManager.importData(
externalProjectNode.getKey(), Collections.singleton(externalProjectNode), project, platformFacade, true);
myExternalProjectNode = null;
}
};
UIUtil.invokeLaterIfNeeded(resolveDependenciesTask);
});
}
});
// resolve dependencies
final Runnable resolveDependenciesTask = new Runnable() {
@Override
public void run() {
ExternalSystemUtil.refreshProject(
project, myExternalSystemId, projectSettings.getExternalProjectPath(), false,
ProgressExecutionMode.IN_BACKGROUND_ASYNC);
}
};
if (!isFromUI) {
resolveDependenciesTask.run();
}
});
return Collections.emptyList();
else {
// execute when current dialog is closed
ExternalSystemUtil.invokeLater(project, ModalityState.NON_MODAL, new Runnable() {
@Override
public void run() {
final Module[] committedModules = ModuleManager.getInstance(project).getModules();
if (ContainerUtil.list(committedModules).containsAll(modules)) {
resolveDependenciesTask.run();
}
else {
ExternalSystemApiUtil.getLocalSettings(project, myExternalSystemId).forgetExternalProjects(
Collections.singleton(projectSettings.getExternalProjectPath()));
ExternalSystemApiUtil.getSettings(project, myExternalSystemId).unlinkExternalProject(
projectSettings.getExternalProjectPath());
ExternalProjectsManager.getInstance(project).forgetExternalProjectData(
myExternalSystemId, projectSettings.getExternalProjectPath());
}
}
});
}
}
return modules;
}
@NotNull
@@ -189,62 +217,6 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
protected abstract void beforeCommit(@NotNull DataNode<ProjectData> dataNode, @NotNull Project project);
/**
* The whole import sequence looks like below:
* <p/>
* <pre>
* <ol>
* <li>Get project view from the gradle tooling api without resolving dependencies (downloading libraries);</li>
* <li>Allow to adjust project settings before importing;</li>
* <li>Create IJ project and modules;</li>
* <li>Ask gradle tooling api to resolve library dependencies (download the if necessary);</li>
* <li>Configure libraries used by the gradle project at intellij;</li>
* <li>Configure library dependencies;</li>
* </ol>
* </pre>
* <p/>
*
* @param projectWithResolvedLibraries gradle project with resolved libraries (libraries have already been downloaded and
* are available at file system under gradle service directory)
* @param project current intellij project which should be configured by libraries and module library
* dependencies information available at the given gradle project
*/
private void setupLibraries(@NotNull final DataNode<ProjectData> projectWithResolvedLibraries, final Project project) {
ExternalSystemApiUtil.executeProjectChangeAction(new DisposeAwareProjectChange(project) {
@Override
public void execute() {
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
@Override
public void run() {
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();
}
}
// Register libraries.
myProjectDataManager.importData(Collections.<DataNode<?>>singletonList(projectWithResolvedLibraries), project, false);
}
});
}
});
}
@Nullable
private File getProjectFile() {
String path = myControl.getProjectSettings().getExternalProjectPath();
@@ -323,11 +295,6 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
@SuppressWarnings("unchecked")
private void executeAndRestoreDefaultProjectSettings(@NotNull Project project, @NotNull Runnable task) {
if (!project.isDefault()) {
task.run();
return;
}
AbstractExternalSystemSettings systemSettings = ExternalSystemApiUtil.getSettings(project, myExternalSystemId);
Object systemStateToRestore = null;
if (systemSettings instanceof PersistentStateComponent) {
@@ -16,11 +16,13 @@
package com.intellij.openapi.externalSystem.service.project.wizard;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.externalSystem.service.settings.AbstractExternalProjectSettingsControl;
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil;
import com.intellij.openapi.externalSystem.util.PaintAwarePanel;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.util.Key;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,14 +34,25 @@ import javax.swing.*;
*/
public class ExternalModuleSettingsStep<S extends ExternalProjectSettings> extends ModuleWizardStep {
public static final Key<Boolean> SKIP_STEP_KEY = Key.create("SKIP_STEP_KEY");
@NotNull private final AbstractExternalModuleBuilder<S> myExternalModuleBuilder;
@NotNull private final AbstractExternalProjectSettingsControl<S> myControl;
@Nullable private final WizardContext myContext;
@Nullable private PaintAwarePanel myComponent;
public ExternalModuleSettingsStep(@NotNull AbstractExternalModuleBuilder<S> externalModuleBuilder, @NotNull AbstractExternalProjectSettingsControl<S> control) {
public ExternalModuleSettingsStep(@Nullable WizardContext context,
@NotNull AbstractExternalModuleBuilder<S> externalModuleBuilder,
@NotNull AbstractExternalProjectSettingsControl<S> control) {
myExternalModuleBuilder = externalModuleBuilder;
myControl = control;
myContext = context;
}
public ExternalModuleSettingsStep(@NotNull AbstractExternalModuleBuilder<S> externalModuleBuilder,
@NotNull AbstractExternalProjectSettingsControl<S> control) {
this(null, externalModuleBuilder, control);
}
@Override
@@ -83,4 +96,9 @@ public class ExternalModuleSettingsStep<S extends ExternalProjectSettings> exten
super.disposeUIResources();
myControl.disposeUIResources();
}
@Override
public boolean isStepVisible() {
return myContext == null || !Boolean.TRUE.equals(myContext.getUserData(SKIP_STEP_KEY));
}
}
@@ -54,7 +54,7 @@ public abstract class AbstractImportFromExternalSystemControl<
@NotNull private final PaintAwarePanel myComponent = new PaintAwarePanel(new GridBagLayout());
@NotNull private final TextFieldWithBrowseButton myLinkedProjectPathField = new TextFieldWithBrowseButton();
@Nullable private final HideableTitledPanel hideableSystemSettingsPanel;
@Nullable private final ProjectFormatPanel myProjectFormatPanel;
@NotNull private final ProjectFormatPanel myProjectFormatPanel;
@NotNull private final ExternalSystemSettingsControl<ProjectSettings> myProjectSettingsControl;
@NotNull private final ProjectSystemId myExternalSystemId;
@@ -62,6 +62,9 @@ public abstract class AbstractImportFromExternalSystemControl<
@Nullable Project myCurrentProject;
private boolean myShowProjectFormatPanel;
private final JLabel myProjectFormatLabel;
protected AbstractImportFromExternalSystemControl(@NotNull ProjectSystemId externalSystemId,
@NotNull SystemSettings systemSettings,
@NotNull ProjectSettings projectSettings)
@@ -80,6 +83,7 @@ public abstract class AbstractImportFromExternalSystemControl<
myProjectSettings = projectSettings;
myProjectSettingsControl = createProjectSettingsControl(projectSettings);
mySystemSettingsControl = createSystemSettingsControl(systemSettings);
myShowProjectFormatPanel = showProjectFormatPanel;
JLabel linkedProjectPathLabel =
new JLabel(ExternalSystemBundle.message("settings.label.select.project", externalSystemId.getReadableName()));
@@ -115,14 +119,10 @@ public abstract class AbstractImportFromExternalSystemControl<
myComponent.add(myLinkedProjectPathField, ExternalSystemUiUtil.getFillLineConstraints(0));
myProjectSettingsControl.fillUi(myComponent, 0);
if(showProjectFormatPanel) {
myProjectFormatPanel = new ProjectFormatPanel();
JLabel myProjectFormatLabel = new JLabel(ExternalSystemBundle.message("settings.label.project.format"));
myComponent.add(myProjectFormatLabel, ExternalSystemUiUtil.getLabelConstraints(0));
myComponent.add(myProjectFormatPanel.getStorageFormatComboBox(), ExternalSystemUiUtil.getFillLineConstraints(0));
} else {
myProjectFormatPanel = null;
}
myProjectFormatPanel = new ProjectFormatPanel();
myProjectFormatLabel = new JLabel(ExternalSystemBundle.message("settings.label.project.format"));
myComponent.add(myProjectFormatLabel, ExternalSystemUiUtil.getLabelConstraints(0));
myComponent.add(myProjectFormatPanel.getStorageFormatComboBox(), ExternalSystemUiUtil.getFillLineConstraints(0));
if (mySystemSettingsControl != null) {
final PaintAwarePanel mySystemSettingsControlPanel = new PaintAwarePanel();
@@ -213,6 +213,10 @@ public abstract class AbstractImportFromExternalSystemControl<
return myProjectSettings;
}
public void setShowProjectFormatPanel(boolean showProjectFormatPanel) {
myShowProjectFormatPanel = showProjectFormatPanel;
}
public void reset() {
myLinkedProjectPathField.setText("");
myProjectSettingsControl.reset();
@@ -222,6 +226,10 @@ public abstract class AbstractImportFromExternalSystemControl<
if (hideableSystemSettingsPanel != null) {
hideableSystemSettingsPanel.setOn(false);
}
myProjectFormatLabel.setVisible(myShowProjectFormatPanel);
myProjectFormatPanel.setVisible(myShowProjectFormatPanel);
myProjectFormatPanel.getPanel().setVisible(myShowProjectFormatPanel);
myProjectFormatPanel.getStorageFormatComboBox().setVisible(myShowProjectFormatPanel);
}
public void apply() throws ConfigurationException {
@@ -252,6 +260,6 @@ public abstract class AbstractImportFromExternalSystemControl<
@Nullable
public ProjectFormatPanel getProjectFormatPanel() {
return myProjectFormatPanel;
return myShowProjectFormatPanel ? myProjectFormatPanel : null;
}
}
@@ -18,7 +18,7 @@ package com.intellij.openapi.externalSystem.service.task.ui;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager;
import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
import com.intellij.openapi.externalSystem.view.ExternalProjectsView;
import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
@@ -44,7 +44,7 @@ public abstract class AbstractExternalSystemToolWindowFactory implements ToolWin
public void createToolWindowContent(@NotNull final Project project, @NotNull final ToolWindow toolWindow) {
toolWindow.setTitle(myExternalSystemId.getReadableName());
ContentManager contentManager = toolWindow.getContentManager();
final ExternalProjectsView projectsView = new ExternalProjectsView(project, (ToolWindowEx)toolWindow, myExternalSystemId);
final ExternalProjectsViewImpl projectsView = new ExternalProjectsViewImpl(project, (ToolWindowEx)toolWindow, myExternalSystemId);
ExternalProjectsManager.getInstance(project).registerView(projectsView);
ContentImpl tasksContent = new ContentImpl(projectsView, ExternalSystemBundle.message("tool.window.title.projects"), true);
contentManager.addContent(tasksContent);
@@ -5,7 +5,10 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.impl.ToolWindowImpl;
@@ -41,6 +44,25 @@ public class ExternalToolWindowManager {
if (toolWindow != null) {
toolWindow.setAvailable(true, null);
}
else {
StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() {
@Override
public void run() {
if (project.isDisposed()) return;
ExternalSystemUtil.ensureToolWindowInitialized(project, manager.getSystemId());
ToolWindowManager.getInstance(project).invokeLater(new Runnable() {
public void run() {
if (project.isDisposed()) return;
ToolWindow toolWindow = getToolWindow(project, manager.getSystemId());
if (toolWindow != null) {
toolWindow.setAvailable(true, null);
}
}
});
}
});
}
}
@Override
@@ -53,7 +75,7 @@ public class ExternalToolWindowManager {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
toolWindow.setAvailable(false, null);
toolWindow.setAvailable(false, null);
}
});
}
@@ -26,8 +26,6 @@ import com.intellij.execution.rmi.RemoteUtil;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.ServiceManager;
@@ -62,6 +60,7 @@ import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettin
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
import com.intellij.openapi.externalSystem.task.TaskCallback;
import com.intellij.openapi.externalSystem.view.ExternalProjectsView;
import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -88,9 +87,8 @@ import com.intellij.openapi.wm.impl.ToolWindowImpl;
import com.intellij.ui.CheckBoxList;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentManager;
import com.intellij.util.Consumer;
import com.intellij.util.DisposeAwareRunnable;
import com.intellij.util.Function;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.containers.ContainerUtil;
@@ -126,57 +124,27 @@ public class ExternalSystemUtil {
}
public static void ensureToolWindowInitialized(@NotNull Project project, @NotNull ProjectSystemId externalSystemId) {
ToolWindowManager manager = ToolWindowManager.getInstance(project);
if (!(manager instanceof ToolWindowManagerEx)) {
return;
}
ToolWindowManagerEx managerEx = (ToolWindowManagerEx)manager;
String id = externalSystemId.getReadableName();
ToolWindow window = manager.getToolWindow(id);
if (window != null) {
return;
}
ToolWindowEP[] beans = Extensions.getExtensions(ToolWindowEP.EP_NAME);
for (final ToolWindowEP bean : beans) {
if (id.equals(bean.id)) {
managerEx.initToolWindow(bean);
try {
ToolWindowManager manager = ToolWindowManager.getInstance(project);
if (!(manager instanceof ToolWindowManagerEx)) {
return;
}
}
}
@Nullable
public static <T> T getToolWindowElement(@NotNull Class<T> clazz,
@NotNull Project project,
@NotNull DataKey<T> key,
@NotNull ProjectSystemId externalSystemId) {
if (project.isDisposed() || !project.isOpen()) {
return null;
}
final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
if (toolWindowManager == null) {
return null;
}
final ToolWindow toolWindow = ensureToolWindowContentInitialized(project, externalSystemId);
if (toolWindow == null) {
return null;
}
final ContentManager contentManager = toolWindow.getContentManager();
if (contentManager == null) {
return null;
}
for (Content content : contentManager.getContents()) {
final JComponent component = content.getComponent();
if (component instanceof DataProvider) {
final Object data = ((DataProvider)component).getData(key.getName());
if (data != null && clazz.isInstance(data)) {
//noinspection unchecked
return (T)data;
ToolWindowManagerEx managerEx = (ToolWindowManagerEx)manager;
String id = externalSystemId.getReadableName();
ToolWindow window = manager.getToolWindow(id);
if (window != null) {
return;
}
ToolWindowEP[] beans = Extensions.getExtensions(ToolWindowEP.EP_NAME);
for (final ToolWindowEP bean : beans) {
if (id.equals(bean.id)) {
managerEx.initToolWindow(bean);
}
}
}
return null;
catch (Exception e) {
LOG.error(String.format("Unable to initialize %s tool window", externalSystemId.getReadableName()), e);
}
}
@Nullable
@@ -201,7 +169,7 @@ public class ExternalSystemUtil {
* @param project target ide project
* @param externalSystemId target external system which projects should be refreshed
* @param force flag which defines if external project refresh should be performed if it's config is up-to-date
* @deprecated use {@link ExternalSystemUtil#refreshProjects(com.intellij.openapi.externalSystem.importing.ImportSpecBuilder)}
* @deprecated use {@link ExternalSystemUtil#refreshProjects(ImportSpecBuilder)}
*/
@Deprecated
public static void refreshProjects(@NotNull final Project project, @NotNull final ProjectSystemId externalSystemId, boolean force) {
@@ -217,7 +185,7 @@ public class ExternalSystemUtil {
* @param externalSystemId target external system which projects should be refreshed
* @param force flag which defines if external project refresh should be performed if it's config is up-to-date
*
* @deprecated use {@link ExternalSystemUtil#refreshProjects(com.intellij.openapi.externalSystem.importing.ImportSpecBuilder)}
* @deprecated use {@link ExternalSystemUtil#refreshProjects(ImportSpecBuilder)}
*/
@Deprecated
public static void refreshProjects(@NotNull final Project project, @NotNull final ProjectSystemId externalSystemId, boolean force, @NotNull final ProgressExecutionMode progressExecutionMode) {
@@ -399,8 +367,51 @@ public class ExternalSystemUtil {
return null;
}
public static void refreshProject(@NotNull final Project project,
@NotNull final ProjectSystemId externalSystemId,
@NotNull final String externalProjectPath,
final boolean isPreviewMode,
@NotNull final ProgressExecutionMode progressExecutionMode) {
final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class);
refreshProject(project, platformFacade, externalSystemId, externalProjectPath, isPreviewMode, progressExecutionMode);
}
public static void refreshProject(@NotNull final Project project,
@NotNull final PlatformFacade platformFacade,
@NotNull final ProjectSystemId externalSystemId,
@NotNull final String externalProjectPath,
final boolean isPreviewMode,
@NotNull final ProgressExecutionMode progressExecutionMode) {
refreshProject(project, externalSystemId, externalProjectPath, new ExternalProjectRefreshCallback() {
@Override
public void onSuccess(@Nullable final DataNode<ProjectData> externalProject) {
if (externalProject == null) {
return;
}
final boolean synchronous = progressExecutionMode == ProgressExecutionMode.MODAL_SYNC;
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
@Override
public void execute() {
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
@Override
public void run() {
final ProjectDataManager projectDataManager = ServiceManager.getService(ProjectDataManager.class);
projectDataManager
.importData(externalProject.getKey(), Collections.singleton(externalProject), project, platformFacade, synchronous);
}
});
}
});
}
@Override
public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
}
}, isPreviewMode, progressExecutionMode, true);
}
/**
* TODO[Vlad]: refactor the method to use {@link com.intellij.openapi.externalSystem.importing.ImportSpecBuilder}
* TODO[Vlad]: refactor the method to use {@link ImportSpecBuilder}
*
* Queries slave gradle process to refresh target gradle project.
*
@@ -420,7 +431,7 @@ public class ExternalSystemUtil {
}
/**
* TODO[Vlad]: refactor the method to use {@link com.intellij.openapi.externalSystem.importing.ImportSpecBuilder}
* TODO[Vlad]: refactor the method to use {@link ImportSpecBuilder}
*
* Queries slave gradle process to refresh target gradle project.
*
@@ -916,8 +927,8 @@ public class ExternalSystemUtil {
public static void scheduleExternalViewStructureUpdate(final Project project, final ProjectSystemId systemId) {
ExternalProjectsView externalProjectsView = ExternalProjectsManager.getInstance(project).getExternalProjectsView(systemId);
if (externalProjectsView != null) {
externalProjectsView.scheduleStructureUpdate();
if (externalProjectsView instanceof ExternalProjectsViewImpl) {
((ExternalProjectsViewImpl)externalProjectsView).scheduleStructureUpdate();
}
}
@@ -934,6 +945,24 @@ public class ExternalSystemUtil {
}
public static void invokeLater(Project p, Runnable r) {
invokeLater(p, ModalityState.defaultModalityState(), r);
}
public static void invokeLater(final Project p, final ModalityState state, final Runnable r) {
if (isNoBackgroundMode()) {
r.run();
}
else {
ApplicationManager.getApplication().invokeLater(DisposeAwareRunnable.create(r, p), state);
}
}
public static boolean isNoBackgroundMode() {
return (ApplicationManager.getApplication().isUnitTestMode()
|| ApplicationManager.getApplication().isHeadlessEnvironment());
}
private interface TaskUnderProgress {
void execute(@NotNull ProgressIndicator indicator);
}
@@ -1012,9 +1041,7 @@ public class ExternalSystemUtil {
if (externalSystemIdAsString.equals(s) && !myExternalModulePaths.contains(p)) {
orphanIdeModules.add(module);
if(ExternalSystemDebugEnvironment.DEBUG_ORPHAN_MODULES_PROCESSING) {
LOG.info(String.format(
"External paths doesn't contain IDE module LINKED_PROJECT_PATH_KEY anymore => add to orphan IDE modules."
));
LOG.info("External paths doesn't contain IDE module LINKED_PROJECT_PATH_KEY anymore => add to orphan IDE modules.");
}
}
}
@@ -19,11 +19,9 @@ import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.treeStructure.SimpleNode;
import com.intellij.ui.treeStructure.SimpleTree;
import com.intellij.ui.treeStructure.SimpleTreeBuilder;
import com.intellij.ui.treeStructure.SimpleTreeStructure;
import com.intellij.ui.treeStructure.*;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
@@ -42,21 +40,23 @@ import java.util.Map;
*/
public class ExternalProjectsStructure extends SimpleTreeStructure {
private final Project myProject;
private final ExternalProjectsView myExternalProjectsView;
private ExternalProjectsView myExternalProjectsView;
private final SimpleTreeBuilder myTreeBuilder;
private final RootNode myRoot;
private RootNode myRoot;
private final Map<String, ExternalSystemNode> myNodeMapping = new THashMap<String, ExternalSystemNode>();
public ExternalProjectsStructure(Project project, ExternalProjectsView externalProjectsView, SimpleTree tree) {
public ExternalProjectsStructure(Project project, SimpleTree tree) {
myProject = project;
myExternalProjectsView = externalProjectsView;
configureTree(tree);
myTreeBuilder = new SimpleTreeBuilder(tree, (DefaultTreeModel)tree.getModel(), this, null);
Disposer.register(myProject, myTreeBuilder);
}
public void init(ExternalProjectsView externalProjectsView) {
myExternalProjectsView = externalProjectsView;
myRoot = new RootNode();
myTreeBuilder.initRoot();
myTreeBuilder.expand(myRoot, null);
@@ -66,11 +66,11 @@ public class ExternalProjectsStructure extends SimpleTreeStructure {
return myProject;
}
void updateFrom(SimpleNode node) {
public void updateFrom(SimpleNode node) {
myTreeBuilder.addSubtreeToUpdateByElement(node);
}
void updateUpTo(SimpleNode node) {
public void updateUpTo(SimpleNode node) {
SimpleNode each = node;
while (each != null) {
updateFrom(each);
@@ -88,16 +88,40 @@ public class ExternalProjectsStructure extends SimpleTreeStructure {
tree.setShowsRootHandles(true);
}
public void accept(@NotNull SimpleNodeVisitor visitor) {
if (myTreeBuilder.getTree() instanceof SimpleTree) {
((SimpleTree)myTreeBuilder.getTree()).accept(myTreeBuilder, visitor);
}
}
public void select(SimpleNode node) {
myTreeBuilder.select(node, null);
}
protected Class<? extends ExternalSystemNode>[] getVisibleNodesClasses() {
return null;
}
public void updateProjects(Collection<DataNode<ProjectData>> toImport) {
List<String> orphanProjects = ContainerUtil.mapNotNull(
myNodeMapping.entrySet(), new Function<Map.Entry<String, ExternalSystemNode>, String>() {
@Override
public String fun(Map.Entry<String, ExternalSystemNode> entry) {
return entry.getValue() instanceof ProjectNode ? entry.getKey() : null;
}
});
for (DataNode<ProjectData> each : toImport) {
final ProjectData projectData = each.getData();
ExternalSystemNode projectNode = findNodeFor(projectData.getLinkedExternalProjectPath());
final String projectPath = projectData.getLinkedExternalProjectPath();
orphanProjects.remove(projectPath);
ExternalSystemNode projectNode = findNodeFor(projectPath);
if (projectNode instanceof ProjectNode) {
doMergeChildrenChanges(projectNode, each, new ProjectNode(myExternalProjectsView, each));
}
else {
ExternalSystemNode node = myNodeMapping.remove(projectData.getLinkedExternalProjectPath());
ExternalSystemNode node = myNodeMapping.remove(projectPath);
if (node != null) {
SimpleNode parent = node.getParent();
if (parent instanceof ExternalSystemNode) {
@@ -106,13 +130,25 @@ public class ExternalProjectsStructure extends SimpleTreeStructure {
}
projectNode = new ProjectNode(myExternalProjectsView, each);
myNodeMapping.put(projectData.getLinkedExternalProjectPath(), projectNode);
myNodeMapping.put(projectPath, projectNode);
}
if (toImport.size() == 0) {
myTreeBuilder.expand(projectNode, null);
}
doUpdateProject((ProjectNode)projectNode);
}
//remove orphan projects from view
for (String orphanProjectPath : orphanProjects) {
ExternalSystemNode projectNode = myNodeMapping.remove(orphanProjectPath);
if (projectNode instanceof ProjectNode) {
SimpleNode parent = projectNode.getParent();
if (parent instanceof ExternalSystemNode) {
((ExternalSystemNode)parent).remove(projectNode);
updateUpTo(projectNode);
}
}
}
}
private void doMergeChildrenChanges(ExternalSystemNode currentNode, DataNode<?> newDataNode, ExternalSystemNode newNode) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -15,602 +15,40 @@
*/
package com.intellij.openapi.externalSystem.view;
import com.intellij.execution.*;
import com.intellij.ide.util.treeView.TreeState;
import com.intellij.notification.NotificationGroup;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.ExternalSystemUiAware;
import com.intellij.openapi.externalSystem.action.ExternalSystemViewGearAction;
import com.intellij.openapi.externalSystem.model.*;
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecutionInfo;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.task.TaskData;
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemTaskLocation;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemShortcutsManager;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ex.ToolWindowEx;
import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.openapi.wm.impl.ToolWindowImpl;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.ui.PopupHandler;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.treeStructure.SimpleTree;
import com.intellij.util.Consumer;
import com.intellij.util.DisposeAwareRunnable;
import com.intellij.util.Function;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* @author Vladislav.Soroka
* @since 9/19/2014
* @since 4/15/2015
*/
public class ExternalProjectsView extends SimpleToolWindowPanel implements DataProvider {
public static final Logger LOG = Logger.getInstance(ExternalProjectsView.class);
@NotNull
private final Project myProject;
@NotNull
private final ExternalProjectsManager myProjectsManager;
@NotNull
private final ToolWindowEx myToolWindow;
@NotNull
private final ProjectSystemId myExternalSystemId;
@NotNull
private final ExternalSystemUiAware myUiAware;
public interface ExternalProjectsView {
ExternalSystemUiAware getUiAware();
@Nullable
private ExternalProjectsStructure myStructure;
private SimpleTree myTree;
@NotNull
private final NotificationGroup myNotificationGroup;
ExternalProjectsStructure getStructure();
private ExternalProjectsViewState myState = new ExternalProjectsViewState();
ExternalSystemShortcutsManager getShortcutsManager();
public ExternalProjectsView(@NotNull Project project, @NotNull ToolWindowEx toolWindow, @NotNull ProjectSystemId externalSystemId) {
super(true, true);
myProject = project;
myToolWindow = toolWindow;
myExternalSystemId = externalSystemId;
myUiAware = ExternalSystemUiUtil.getUiAware(externalSystemId);
myProjectsManager = ExternalProjectsManager.getInstance(myProject);
ExternalSystemTaskActivator getTaskActivator();
String toolWindowId =
toolWindow instanceof ToolWindowImpl ? ((ToolWindowImpl)toolWindow).getId() : myExternalSystemId.getReadableName();
void updateUpTo(ExternalSystemNode node);
String notificationId = "notification.group.id." + externalSystemId.getId().toLowerCase(Locale.ENGLISH);
NotificationGroup registeredGroup = NotificationGroup.findRegisteredGroup(notificationId);
myNotificationGroup = registeredGroup != null ? registeredGroup : NotificationGroup.toolWindowGroup(notificationId, toolWindowId);
}
List<ExternalSystemNode<?>> createNodes(@NotNull ExternalProjectsView externalProjectsView, @Nullable ExternalSystemNode<?> parent, @NotNull DataNode<?> dataNode);
@Nullable
@Override
public Object getData(@NonNls String dataId) {
if (ExternalSystemDataKeys.VIEW.is(dataId)) return this;
Project getProject();
if (PlatformDataKeys.HELP_ID.is(dataId)) return "reference.toolwindows.gradle";
if (CommonDataKeys.PROJECT.is(dataId)) return myProject;
if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) return extractVirtualFile();
if (CommonDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) return extractVirtualFiles();
if (Location.DATA_KEY.is(dataId)) {
return extractLocation();
}
if (CommonDataKeys.NAVIGATABLE_ARRAY.is(dataId)) return extractNavigatables();
boolean showInheritedTasks();
if (ExternalSystemDataKeys.EXTERNAL_SYSTEM_ID.is(dataId)) return myExternalSystemId;
if (ExternalSystemDataKeys.UI_AWARE.is(dataId)) return myUiAware;
if (ExternalSystemDataKeys.SELECTED_PROJECT_NODE.is(dataId)) return getSelectedProjectNode();
if (ExternalSystemDataKeys.SELECTED_NODES.is(dataId)) return getSelectedNodes(ExternalSystemNode.class);
if (ExternalSystemDataKeys.PROJECTS_TREE.is(dataId)) return myTree;
if (ExternalSystemDataKeys.NOTIFICATION_GROUP.is(dataId)) return myNotificationGroup;
boolean getGroupTasks();
return super.getData(dataId);
}
@NotNull
public Project getProject() {
return myProject;
}
@NotNull
public ExternalSystemUiAware getUiAware() {
return myUiAware;
}
public ExternalSystemShortcutsManager getShortcutsManager() {
return myProjectsManager.getShortcutsManager();
}
public ExternalSystemTaskActivator getTaskActivator() {
return myProjectsManager.getTaskActivator();
}
@NotNull
public ProjectSystemId getSystemId() {
return myExternalSystemId;
}
@NotNull
public NotificationGroup getNotificationGroup() {
return myNotificationGroup;
}
public void init() {
initTree();
final ToolWindowManagerEx manager = ToolWindowManagerEx.getInstanceEx(myProject);
final ToolWindowManagerAdapter listener = new ToolWindowManagerAdapter() {
boolean wasVisible = false;
@Override
public void stateChanged() {
if (myToolWindow.isDisposed()) return;
boolean visible = myToolWindow.isVisible();
if (!visible || wasVisible) {
wasVisible = visible;
return;
}
scheduleStructureUpdate();
wasVisible = true;
}
};
manager.addToolWindowManagerListener(listener);
Disposer.register(myProject, new Disposable() {
public void dispose() {
manager.removeToolWindowManagerListener(listener);
}
});
getShortcutsManager().addListener(new ExternalSystemShortcutsManager.Listener() {
@Override
public void shortcutsUpdated() {
scheduleTasksUpdate();
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
myStructure.updateNodes(RunConfigurationNode.class);
}
});
}
});
getTaskActivator().addListener(new ExternalSystemTaskActivator.Listener() {
@Override
public void tasksActivationChanged() {
scheduleTasksUpdate();
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
myStructure.updateNodes(RunConfigurationNode.class);
}
});
}
});
((RunManagerEx)RunManager.getInstance(myProject)).addRunManagerListener(new RunManagerAdapter() {
private void changed() {
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
myStructure.visitNodes(ModuleNode.class, new Consumer<ModuleNode>() {
@Override
public void consume(ModuleNode node) {
node.updateRunConfigurations();
}
});
}
});
}
@Override
public void runConfigurationAdded(@NotNull RunnerAndConfigurationSettings settings) {
changed();
}
@Override
public void runConfigurationRemoved(@NotNull RunnerAndConfigurationSettings settings) {
changed();
}
@Override
public void runConfigurationChanged(@NotNull RunnerAndConfigurationSettings settings) {
changed();
}
});
ExternalSystemApiUtil.subscribe(myProject, myExternalSystemId, new ExternalSystemSettingsListenerAdapter(){
@Override
public void onUseAutoImportChange(boolean currentValue, @NotNull final String linkedProjectPath) {
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
final List<ProjectNode> projectNodes = myStructure.getNodes(ProjectNode.class);
for (ProjectNode projectNode : projectNodes) {
final ProjectData projectData = projectNode.getData();
if(projectData != null && projectData.getLinkedExternalProjectPath().equals(linkedProjectPath)) {
projectNode.updateProject();
break;
}
}
}
});
}
});
myToolWindow.setAdditionalGearActions(createAdditionalGearActionsGroup());
scheduleStructureUpdate();
}
private ActionGroup createAdditionalGearActionsGroup() {
ActionManager actionManager = ActionManager.getInstance();
DefaultActionGroup group = new DefaultActionGroup();
String[] ids = new String[]{"ExternalSystem.GroupTasks", "ExternalSystem.ShowInheritedTasks"};
for (String id : ids) {
final AnAction gearAction = actionManager.getAction(id);
if (gearAction instanceof ExternalSystemViewGearAction) {
((ExternalSystemViewGearAction)gearAction).setView(this);
group.add(gearAction);
}
}
return group;
}
private void initStructure() {
myStructure = new ExternalProjectsStructure(myProject, this, myTree);
}
private void initTree() {
myTree = new SimpleTree();
myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
final ActionManager actionManager = ActionManager.getInstance();
ActionToolbar actionToolbar = actionManager.createActionToolbar(myExternalSystemId.getReadableName() + " View Toolbar",
(DefaultActionGroup)actionManager
.getAction("ExternalSystemView.ActionsToolbar"), true);
actionToolbar.setTargetComponent(myTree);
setToolbar(actionToolbar.getComponent());
setContent(ScrollPaneFactory.createScrollPane(myTree));
myTree.addMouseListener(new PopupHandler() {
public void invokePopup(final Component comp, final int x, final int y) {
final String id = getMenuId(getSelectedNodes(ExternalSystemNode.class));
if (id != null) {
final ActionGroup actionGroup = (ActionGroup)actionManager.getAction(id);
if (actionGroup != null) {
actionManager.createActionPopupMenu("", actionGroup).getComponent().show(comp, x, y);
}
}
}
@Nullable
private String getMenuId(Collection<? extends ExternalSystemNode> nodes) {
String id = null;
for (ExternalSystemNode node : nodes) {
String menuId = node.getMenuId();
if (menuId == null) {
return null;
}
if (id == null) {
id = menuId;
}
else if (!id.equals(menuId)) {
return null;
}
}
return id;
}
});
}
public void scheduleStructureUpdate() {
scheduleStructureRequest(new Runnable() {
public void run() {
final Collection<ExternalProjectInfo> projectsData =
ProjectDataManager.getInstance().getExternalProjectsData(myProject, myExternalSystemId);
final List<DataNode<ProjectData>> toImport =
ContainerUtil.mapNotNull(projectsData, new Function<ExternalProjectInfo, DataNode<ProjectData>>() {
@Override
public DataNode<ProjectData> fun(ExternalProjectInfo info) {
return info.getExternalProjectStructure();
}
});
assert myStructure != null;
myStructure.updateProjects(toImport);
}
});
}
protected boolean isUnitTestMode() {
return ApplicationManager.getApplication().isUnitTestMode();
}
public static void invokeLater(Project p, Runnable r) {
invokeLater(p, ModalityState.defaultModalityState(), r);
}
public static void invokeLater(final Project p, final ModalityState state, final Runnable r) {
if (isNoBackgroundMode()) {
r.run();
}
else {
ApplicationManager.getApplication().invokeLater(DisposeAwareRunnable.create(r, p), state);
}
}
public static boolean isNoBackgroundMode() {
return (ApplicationManager.getApplication().isUnitTestMode()
|| ApplicationManager.getApplication().isHeadlessEnvironment());
}
public void updateUpTo(ExternalSystemNode node) {
if (myStructure != null) {
myStructure.updateUpTo(node);
}
}
@Nullable
protected ExternalProjectsStructure getStructure() {
return myStructure;
}
@NotNull
public List<ExternalSystemNode<?>> createNodes(@Nullable ExternalSystemNode<?> parent, @NotNull DataNode<?> dataNode) {
final List<ExternalSystemNode<?>> result = new SmartList<ExternalSystemNode<?>>();
final Map<Key<?>, List<DataNode<?>>> groups = ExternalSystemApiUtil.group(dataNode.getChildren());
for (ExternalSystemViewContributor contributor : ExternalSystemViewContributor.EP_NAME.getExtensions()) {
List<Key<?>> keys = contributor.getKeys();
final MultiMap<Key<?>, DataNode<?>> dataNodes = MultiMap.create();
for (Key<?> key : keys) {
final List<DataNode<?>> values = groups.get(key);
if(key != null && values != null) {
dataNodes.put(key, values);
}
}
if (dataNodes.isEmpty()) continue;
final List<ExternalSystemNode<?>> childNodes = contributor.createNodes(this, dataNodes);
result.addAll(childNodes);
if (parent == null) continue;
for (ExternalSystemNode childNode : childNodes) {
childNode.setParent(parent);
}
}
return result;
}
@Nullable
public ExternalProjectsViewState getState() {
ApplicationManager.getApplication().assertIsDispatchThread();
if (myStructure != null) {
try {
myState.treeState = new Element("root");
TreeState.createOn(myTree).writeExternal(myState.treeState);
}
catch (WriteExternalException e) {
LOG.warn(e);
}
}
return myState;
}
public void loadState(ExternalProjectsViewState state) {
myState = state;
}
public boolean getGroupTasks() {
return myState.groupTasks;
}
public void setGroupTasks(boolean value) {
if (myState.groupTasks != value) {
myState.groupTasks = value;
scheduleTasksRebuild();
}
}
public boolean showInheritedTasks() {
return myState.showInheritedTasks;
}
public void setShowInheritedTasks(boolean value) {
if (myState.showInheritedTasks != value) {
myState.showInheritedTasks = value;
scheduleStructureUpdate();
}
}
private void scheduleTasksRebuild() {
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
final List<TasksNode> tasksNodes = myStructure.getNodes(TasksNode.class);
for (TasksNode tasksNode : tasksNodes) {
tasksNode.cleanUpCache();
updateUpTo(tasksNode);
}
}
});
}
private void scheduleTasksUpdate() {
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
myStructure.updateNodes(TaskNode.class);
}
});
}
private void scheduleStructureRequest(final Runnable r) {
if (isUnitTestMode()) {
r.run();
return;
}
invokeLater(myProject, new Runnable() {
public void run() {
if (!myToolWindow.isVisible()) return;
boolean shouldCreate = myStructure == null;
if (shouldCreate) {
initStructure();
}
myTree.setPaintBusy(true);
try {
r.run();
if (shouldCreate) {
restoreTreeState();
}
}
finally {
myTree.setPaintBusy(false);
}
}
});
}
private void restoreTreeState() {
if (myState.treeState != null) {
TreeState treeState = new TreeState();
try {
treeState.readExternal(myState.treeState);
treeState.applyTo(myTree);
}
catch (InvalidDataException e) {
LOG.info(e);
}
}
}
private <T extends ExternalSystemNode> List<T> getSelectedNodes(Class<T> aClass) {
return myStructure != null ? myStructure.getSelectedNodes(myTree, aClass) : ContainerUtil.<T>emptyList();
}
private List<ProjectNode> getSelectedProjectNodes() {
return getSelectedNodes(ProjectNode.class);
}
@Nullable
private ProjectNode getSelectedProjectNode() {
final List<ProjectNode> projectNodes = getSelectedProjectNodes();
return projectNodes.size() == 1 ? projectNodes.get(0) : null;
}
@Nullable
private Location extractLocation() {
final List<ExternalSystemNode> selectedNodes = getSelectedNodes(ExternalSystemNode.class);
if (selectedNodes.isEmpty()) return null;
List<TaskData> tasks = ContainerUtil.newSmartList();
ExternalTaskExecutionInfo taskExecutionInfo = new ExternalTaskExecutionInfo();
String projectPath = null;
for (ExternalSystemNode node : selectedNodes) {
final Object data = node.getData();
if (data instanceof TaskData) {
final TaskData taskData = (TaskData)data;
if (projectPath == null) {
projectPath = taskData.getLinkedExternalProjectPath();
}
else if (!taskData.getLinkedExternalProjectPath().equals(projectPath)) {
return null;
}
taskExecutionInfo.getSettings().getTaskNames().add(taskData.getName());
taskExecutionInfo.getSettings().getTaskDescriptions().add(taskData.getDescription());
tasks.add(taskData);
}
}
if(tasks.isEmpty()) return null;
taskExecutionInfo.getSettings().setExternalSystemIdString(myExternalSystemId.toString());
taskExecutionInfo.getSettings().setExternalProjectPath(projectPath);
String name = myExternalSystemId.getReadableName() + projectPath + StringUtil.join(taskExecutionInfo.getSettings().getTaskNames(), " ");
// We create a dummy text file instead of re-using external system file in order to avoid clashing with other configuration producers.
// For example gradle files are enhanced groovy scripts but we don't want to run them via regular IJ groovy script runners.
// Gradle tooling api should be used for running gradle tasks instead. IJ execution sub-system operates on Location objects
// which encapsulate PsiElement and groovy runners are automatically applied if that PsiElement IS-A GroovyFile.
PsiFile file = PsiFileFactory.getInstance(myProject).createFileFromText(name, PlainTextFileType.INSTANCE, "");
return new ExternalSystemTaskLocation(myProject, file, taskExecutionInfo);
}
private VirtualFile extractVirtualFile() {
for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) {
VirtualFile file = each.getVirtualFile();
if (file != null && file.isValid()) return file;
}
final ProjectNode projectNode = getSelectedProjectNode();
if (projectNode == null) return null;
VirtualFile file = projectNode.getVirtualFile();
if (file == null || !file.isValid()) return null;
return file;
}
private Object extractVirtualFiles() {
final List<VirtualFile> files = new ArrayList<VirtualFile>();
for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) {
VirtualFile file = each.getVirtualFile();
if (file != null && file.isValid()) files.add(file);
}
return files.isEmpty() ? null : VfsUtilCore.toVirtualFileArray(files);
}
private Object extractNavigatables() {
final List<Navigatable> navigatables = new ArrayList<Navigatable>();
for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) {
Navigatable navigatable = each.getNavigatable();
if (navigatable != null) navigatables.add(navigatable);
}
return navigatables.isEmpty() ? null : navigatables.toArray(new Navigatable[navigatables.size()]);
}
ProjectSystemId getSystemId();
}
@@ -0,0 +1,93 @@
/*
* Copyright 2000-2015 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.view;
import com.intellij.openapi.externalSystem.ExternalSystemUiAware;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemShortcutsManager;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author Vladislav.Soroka
* @since 4/15/2015
*/
public class ExternalProjectsViewAdapter implements ExternalProjectsView {
@NotNull
private final ExternalProjectsView delegate;
public ExternalProjectsViewAdapter(@NotNull ExternalProjectsView delegate) {
this.delegate = delegate;
}
@Override
public ExternalSystemUiAware getUiAware() {
return delegate.getUiAware();
}
@Override
@Nullable
public ExternalProjectsStructure getStructure() {
return delegate.getStructure();
}
@Override
public ExternalSystemShortcutsManager getShortcutsManager() {
return delegate.getShortcutsManager();
}
@Override
public ExternalSystemTaskActivator getTaskActivator() {
return delegate.getTaskActivator();
}
@Override
public void updateUpTo(ExternalSystemNode node) {
delegate.updateUpTo(node);
}
@Override
public List<ExternalSystemNode<?>> createNodes(@NotNull ExternalProjectsView externalProjectsView,
@Nullable ExternalSystemNode<?> parent,
@NotNull DataNode<?> dataNode) {
return delegate.createNodes(externalProjectsView, parent, dataNode);
}
@Override
public Project getProject() {
return delegate.getProject();
}
@Override
public boolean showInheritedTasks() {
return delegate.showInheritedTasks();
}
@Override
public boolean getGroupTasks() {
return delegate.getGroupTasks();
}
@Override
public ProjectSystemId getSystemId() {
return delegate.getSystemId();
}
}
@@ -0,0 +1,620 @@
/*
* Copyright 2000-2015 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.view;
import com.intellij.execution.*;
import com.intellij.ide.util.treeView.TreeState;
import com.intellij.notification.NotificationGroup;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.ExternalSystemUiAware;
import com.intellij.openapi.externalSystem.action.ExternalSystemViewGearAction;
import com.intellij.openapi.externalSystem.model.*;
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecutionInfo;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.task.TaskData;
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemTaskLocation;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemShortcutsManager;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ex.ToolWindowEx;
import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.openapi.wm.impl.ToolWindowImpl;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.ui.PopupHandler;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.treeStructure.SimpleTree;
import com.intellij.util.Consumer;
import com.intellij.util.DisposeAwareRunnable;
import com.intellij.util.Function;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* @author Vladislav.Soroka
* @since 9/19/2014
*/
public class ExternalProjectsViewImpl extends SimpleToolWindowPanel implements DataProvider, ExternalProjectsView {
public static final Logger LOG = Logger.getInstance(ExternalProjectsViewImpl.class);
@NotNull
private final Project myProject;
@NotNull
private final ExternalProjectsManager myProjectsManager;
@NotNull
private final ToolWindowEx myToolWindow;
@NotNull
private final ProjectSystemId myExternalSystemId;
@NotNull
private final ExternalSystemUiAware myUiAware;
@Nullable
private ExternalProjectsStructure myStructure;
private SimpleTree myTree;
@NotNull
private final NotificationGroup myNotificationGroup;
private ExternalProjectsViewState myState = new ExternalProjectsViewState();
public ExternalProjectsViewImpl(@NotNull Project project, @NotNull ToolWindowEx toolWindow, @NotNull ProjectSystemId externalSystemId) {
super(true, true);
myProject = project;
myToolWindow = toolWindow;
myExternalSystemId = externalSystemId;
myUiAware = ExternalSystemUiUtil.getUiAware(externalSystemId);
myProjectsManager = ExternalProjectsManager.getInstance(myProject);
String toolWindowId =
toolWindow instanceof ToolWindowImpl ? ((ToolWindowImpl)toolWindow).getId() : myExternalSystemId.getReadableName();
String notificationId = "notification.group.id." + externalSystemId.getId().toLowerCase(Locale.ENGLISH);
NotificationGroup registeredGroup = NotificationGroup.findRegisteredGroup(notificationId);
myNotificationGroup = registeredGroup != null ? registeredGroup : NotificationGroup.toolWindowGroup(notificationId, toolWindowId);
}
@Nullable
@Override
public Object getData(@NonNls String dataId) {
if (ExternalSystemDataKeys.VIEW.is(dataId)) return this;
if (PlatformDataKeys.HELP_ID.is(dataId)) return "reference.toolwindows.gradle";
if (CommonDataKeys.PROJECT.is(dataId)) return myProject;
if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) return extractVirtualFile();
if (CommonDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) return extractVirtualFiles();
if (Location.DATA_KEY.is(dataId)) {
return extractLocation();
}
if (CommonDataKeys.NAVIGATABLE_ARRAY.is(dataId)) return extractNavigatables();
if (ExternalSystemDataKeys.EXTERNAL_SYSTEM_ID.is(dataId)) return myExternalSystemId;
if (ExternalSystemDataKeys.UI_AWARE.is(dataId)) return myUiAware;
if (ExternalSystemDataKeys.SELECTED_PROJECT_NODE.is(dataId)) return getSelectedProjectNode();
if (ExternalSystemDataKeys.SELECTED_NODES.is(dataId)) return getSelectedNodes(ExternalSystemNode.class);
if (ExternalSystemDataKeys.PROJECTS_TREE.is(dataId)) return myTree;
if (ExternalSystemDataKeys.NOTIFICATION_GROUP.is(dataId)) return myNotificationGroup;
return super.getData(dataId);
}
@NotNull
public Project getProject() {
return myProject;
}
@NotNull
public ExternalSystemUiAware getUiAware() {
return myUiAware;
}
public ExternalSystemShortcutsManager getShortcutsManager() {
return myProjectsManager.getShortcutsManager();
}
public ExternalSystemTaskActivator getTaskActivator() {
return myProjectsManager.getTaskActivator();
}
@NotNull
public ProjectSystemId getSystemId() {
return myExternalSystemId;
}
@NotNull
public NotificationGroup getNotificationGroup() {
return myNotificationGroup;
}
public void init() {
initTree();
final ToolWindowManagerEx manager = ToolWindowManagerEx.getInstanceEx(myProject);
final ToolWindowManagerAdapter listener = new ToolWindowManagerAdapter() {
boolean wasVisible = false;
@Override
public void stateChanged() {
if (myToolWindow.isDisposed()) return;
boolean visible = myToolWindow.isVisible();
if (!visible || wasVisible) {
wasVisible = visible;
return;
}
scheduleStructureUpdate();
wasVisible = true;
}
};
manager.addToolWindowManagerListener(listener);
Disposer.register(myProject, new Disposable() {
public void dispose() {
manager.removeToolWindowManagerListener(listener);
}
});
getShortcutsManager().addListener(new ExternalSystemShortcutsManager.Listener() {
@Override
public void shortcutsUpdated() {
scheduleTasksUpdate();
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
myStructure.updateNodes(RunConfigurationNode.class);
}
});
}
});
getTaskActivator().addListener(new ExternalSystemTaskActivator.Listener() {
@Override
public void tasksActivationChanged() {
scheduleTasksUpdate();
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
myStructure.updateNodes(RunConfigurationNode.class);
}
});
}
});
((RunManagerEx)RunManager.getInstance(myProject)).addRunManagerListener(new RunManagerAdapter() {
private void changed() {
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
myStructure.visitNodes(ModuleNode.class, new Consumer<ModuleNode>() {
@Override
public void consume(ModuleNode node) {
node.updateRunConfigurations();
}
});
}
});
}
@Override
public void runConfigurationAdded(@NotNull RunnerAndConfigurationSettings settings) {
changed();
}
@Override
public void runConfigurationRemoved(@NotNull RunnerAndConfigurationSettings settings) {
changed();
}
@Override
public void runConfigurationChanged(@NotNull RunnerAndConfigurationSettings settings) {
changed();
}
});
ExternalSystemApiUtil.subscribe(myProject, myExternalSystemId, new ExternalSystemSettingsListenerAdapter(){
@Override
public void onUseAutoImportChange(boolean currentValue, @NotNull final String linkedProjectPath) {
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
final List<ProjectNode> projectNodes = myStructure.getNodes(ProjectNode.class);
for (ProjectNode projectNode : projectNodes) {
final ProjectData projectData = projectNode.getData();
if(projectData != null && projectData.getLinkedExternalProjectPath().equals(linkedProjectPath)) {
projectNode.updateProject();
break;
}
}
}
});
}
});
myToolWindow.setAdditionalGearActions(createAdditionalGearActionsGroup());
scheduleStructureUpdate();
}
private ActionGroup createAdditionalGearActionsGroup() {
ActionManager actionManager = ActionManager.getInstance();
DefaultActionGroup group = new DefaultActionGroup();
String[] ids = new String[]{"ExternalSystem.GroupTasks", "ExternalSystem.ShowInheritedTasks"};
for (String id : ids) {
final AnAction gearAction = actionManager.getAction(id);
if (gearAction instanceof ExternalSystemViewGearAction) {
((ExternalSystemViewGearAction)gearAction).setView(this);
group.add(gearAction);
}
}
return group;
}
private void initStructure() {
myStructure = new ExternalProjectsStructure(myProject, myTree);
myStructure.init(this);
}
private void initTree() {
myTree = new SimpleTree();
myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
final ActionManager actionManager = ActionManager.getInstance();
ActionToolbar actionToolbar = actionManager.createActionToolbar(myExternalSystemId.getReadableName() + " View Toolbar",
(DefaultActionGroup)actionManager
.getAction("ExternalSystemView.ActionsToolbar"), true);
actionToolbar.setTargetComponent(myTree);
setToolbar(actionToolbar.getComponent());
setContent(ScrollPaneFactory.createScrollPane(myTree));
myTree.addMouseListener(new PopupHandler() {
public void invokePopup(final Component comp, final int x, final int y) {
final String id = getMenuId(getSelectedNodes(ExternalSystemNode.class));
if (id != null) {
final ActionGroup actionGroup = (ActionGroup)actionManager.getAction(id);
if (actionGroup != null) {
actionManager.createActionPopupMenu("", actionGroup).getComponent().show(comp, x, y);
}
}
}
@Nullable
private String getMenuId(Collection<? extends ExternalSystemNode> nodes) {
String id = null;
for (ExternalSystemNode node : nodes) {
String menuId = node.getMenuId();
if (menuId == null) {
return null;
}
if (id == null) {
id = menuId;
}
else if (!id.equals(menuId)) {
return null;
}
}
return id;
}
});
}
public void scheduleStructureUpdate() {
scheduleStructureRequest(new Runnable() {
public void run() {
final Collection<ExternalProjectInfo> projectsData =
ProjectDataManager.getInstance().getExternalProjectsData(myProject, myExternalSystemId);
final List<DataNode<ProjectData>> toImport =
ContainerUtil.mapNotNull(projectsData, new Function<ExternalProjectInfo, DataNode<ProjectData>>() {
@Override
public DataNode<ProjectData> fun(ExternalProjectInfo info) {
return info.getExternalProjectStructure();
}
});
assert myStructure != null;
myStructure.updateProjects(toImport);
}
});
}
protected boolean isUnitTestMode() {
return ApplicationManager.getApplication().isUnitTestMode();
}
public static void invokeLater(Project p, Runnable r) {
invokeLater(p, ModalityState.defaultModalityState(), r);
}
public static void invokeLater(final Project p, final ModalityState state, final Runnable r) {
if (isNoBackgroundMode()) {
r.run();
}
else {
ApplicationManager.getApplication().invokeLater(DisposeAwareRunnable.create(r, p), state);
}
}
public static boolean isNoBackgroundMode() {
return (ApplicationManager.getApplication().isUnitTestMode()
|| ApplicationManager.getApplication().isHeadlessEnvironment());
}
public void updateUpTo(ExternalSystemNode node) {
ExternalProjectsStructure structure = getStructure();
if (structure != null) {
structure.updateUpTo(node);
}
}
@Nullable
public ExternalProjectsStructure getStructure() {
return myStructure;
}
@NotNull
public List<ExternalSystemNode<?>> createNodes(@NotNull ExternalProjectsView externalProjectsView,
@Nullable ExternalSystemNode<?> parent,
@NotNull DataNode<?> dataNode) {
final List<ExternalSystemNode<?>> result = new SmartList<ExternalSystemNode<?>>();
final Map<Key<?>, List<DataNode<?>>> groups = ExternalSystemApiUtil.group(dataNode.getChildren());
for (ExternalSystemViewContributor contributor : ExternalSystemViewContributor.EP_NAME.getExtensions()) {
List<Key<?>> keys = contributor.getKeys();
final MultiMap<Key<?>, DataNode<?>> dataNodes = MultiMap.create();
for (Key<?> key : keys) {
final List<DataNode<?>> values = groups.get(key);
if(key != null && values != null) {
dataNodes.put(key, values);
}
}
if (dataNodes.isEmpty()) continue;
final List<ExternalSystemNode<?>> childNodes = contributor.createNodes(externalProjectsView, dataNodes);
result.addAll(childNodes);
if (parent == null) continue;
for (ExternalSystemNode childNode : childNodes) {
childNode.setParent(parent);
}
}
return result;
}
@Nullable
public ExternalProjectsViewState getState() {
ApplicationManager.getApplication().assertIsDispatchThread();
if (myStructure != null) {
try {
myState.treeState = new Element("root");
TreeState.createOn(myTree).writeExternal(myState.treeState);
}
catch (WriteExternalException e) {
LOG.warn(e);
}
}
return myState;
}
public void loadState(ExternalProjectsViewState state) {
myState = state;
}
public boolean getGroupTasks() {
return myState.groupTasks;
}
public void setGroupTasks(boolean value) {
if (myState.groupTasks != value) {
myState.groupTasks = value;
scheduleTasksRebuild();
}
}
public boolean showInheritedTasks() {
return myState.showInheritedTasks;
}
public void setShowInheritedTasks(boolean value) {
if (myState.showInheritedTasks != value) {
myState.showInheritedTasks = value;
scheduleStructureUpdate();
}
}
private void scheduleTasksRebuild() {
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
final List<TasksNode> tasksNodes = myStructure.getNodes(TasksNode.class);
for (TasksNode tasksNode : tasksNodes) {
tasksNode.cleanUpCache();
updateUpTo(tasksNode);
}
}
});
}
private void scheduleTasksUpdate() {
scheduleStructureRequest(new Runnable() {
public void run() {
assert myStructure != null;
myStructure.updateNodes(TaskNode.class);
}
});
}
private void scheduleStructureRequest(final Runnable r) {
if (isUnitTestMode()) {
r.run();
return;
}
invokeLater(myProject, new Runnable() {
public void run() {
if (!myToolWindow.isVisible()) return;
boolean shouldCreate = myStructure == null;
if (shouldCreate) {
initStructure();
}
myTree.setPaintBusy(true);
try {
r.run();
if (shouldCreate) {
restoreTreeState();
}
}
finally {
myTree.setPaintBusy(false);
}
}
});
}
private void restoreTreeState() {
if (myState.treeState != null) {
TreeState treeState = new TreeState();
try {
treeState.readExternal(myState.treeState);
treeState.applyTo(myTree);
}
catch (InvalidDataException e) {
LOG.info(e);
}
}
}
private <T extends ExternalSystemNode> List<T> getSelectedNodes(Class<T> aClass) {
return myStructure != null ? myStructure.getSelectedNodes(myTree, aClass) : ContainerUtil.<T>emptyList();
}
private List<ProjectNode> getSelectedProjectNodes() {
return getSelectedNodes(ProjectNode.class);
}
@Nullable
private ProjectNode getSelectedProjectNode() {
final List<ProjectNode> projectNodes = getSelectedProjectNodes();
return projectNodes.size() == 1 ? projectNodes.get(0) : null;
}
@Nullable
private Location extractLocation() {
final List<ExternalSystemNode> selectedNodes = getSelectedNodes(ExternalSystemNode.class);
if (selectedNodes.isEmpty()) return null;
List<TaskData> tasks = ContainerUtil.newSmartList();
ExternalTaskExecutionInfo taskExecutionInfo = new ExternalTaskExecutionInfo();
String projectPath = null;
for (ExternalSystemNode node : selectedNodes) {
final Object data = node.getData();
if (data instanceof TaskData) {
final TaskData taskData = (TaskData)data;
if (projectPath == null) {
projectPath = taskData.getLinkedExternalProjectPath();
}
else if (!taskData.getLinkedExternalProjectPath().equals(projectPath)) {
return null;
}
taskExecutionInfo.getSettings().getTaskNames().add(taskData.getName());
taskExecutionInfo.getSettings().getTaskDescriptions().add(taskData.getDescription());
tasks.add(taskData);
}
}
if(tasks.isEmpty()) return null;
taskExecutionInfo.getSettings().setExternalSystemIdString(myExternalSystemId.toString());
taskExecutionInfo.getSettings().setExternalProjectPath(projectPath);
String name = myExternalSystemId.getReadableName() + projectPath + StringUtil.join(taskExecutionInfo.getSettings().getTaskNames(), " ");
// We create a dummy text file instead of re-using external system file in order to avoid clashing with other configuration producers.
// For example gradle files are enhanced groovy scripts but we don't want to run them via regular IJ groovy script runners.
// Gradle tooling api should be used for running gradle tasks instead. IJ execution sub-system operates on Location objects
// which encapsulate PsiElement and groovy runners are automatically applied if that PsiElement IS-A GroovyFile.
PsiFile file = PsiFileFactory.getInstance(myProject).createFileFromText(name, PlainTextFileType.INSTANCE, "");
return new ExternalSystemTaskLocation(myProject, file, taskExecutionInfo);
}
private VirtualFile extractVirtualFile() {
for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) {
VirtualFile file = each.getVirtualFile();
if (file != null && file.isValid()) return file;
}
final ProjectNode projectNode = getSelectedProjectNode();
if (projectNode == null) return null;
VirtualFile file = projectNode.getVirtualFile();
if (file == null || !file.isValid()) return null;
return file;
}
private Object extractVirtualFiles() {
final List<VirtualFile> files = new ArrayList<VirtualFile>();
for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) {
VirtualFile file = each.getVirtualFile();
if (file != null && file.isValid()) files.add(file);
}
return files.isEmpty() ? null : VfsUtilCore.toVirtualFileArray(files);
}
private Object extractNavigatables() {
final List<Navigatable> navigatables = new ArrayList<Navigatable>();
for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) {
Navigatable navigatable = each.getNavigatable();
if (navigatable != null) navigatables.add(navigatable);
}
return navigatables.isEmpty() ? null : navigatables.toArray(new Navigatable[navigatables.size()]);
}
}
@@ -157,7 +157,12 @@ public abstract class ExternalSystemNode<T> extends SimpleNode implements Compar
}
public ExternalProjectsStructure.DisplayKind getDisplayKind() {
return ExternalProjectsStructure.DisplayKind.NORMAL;
Class[] visibles = getStructure().getVisibleNodesClasses();
if (visibles == null) return ExternalProjectsStructure.DisplayKind.NORMAL;
for (Class each : visibles) {
if (each.isInstance(this)) return ExternalProjectsStructure.DisplayKind.ALWAYS;
}
return ExternalProjectsStructure.DisplayKind.NEVER;
}
@NotNull
@@ -270,7 +275,8 @@ public abstract class ExternalSystemNode<T> extends SimpleNode implements Compar
@NotNull
protected List<? extends ExternalSystemNode> doBuildChildren() {
if (myDataNode != null && !myDataNode.getChildren().isEmpty()) {
return getExternalProjectsView().createNodes(this, myDataNode);
final ExternalProjectsView externalProjectsView = getExternalProjectsView();
return externalProjectsView.createNodes(externalProjectsView, this, myDataNode);
}
else {
return myChildrenList;
@@ -81,7 +81,7 @@ public class ModuleNode extends ExternalSystemNode<ModuleData> {
@Override
public boolean isVisible() {
return true;
return super.isVisible();
}
@Override
@@ -60,7 +60,7 @@ public class RunConfigurationsNode extends ExternalSystemNode<Void> {
@Override
public boolean isVisible() {
return hasChildren() && super.isVisible();
return super.isVisible() && hasChildren();
}
@NotNull
@@ -68,7 +68,7 @@ public class TasksNode extends ExternalSystemNode {
@Override
public boolean isVisible() {
return hasChildren() && super.isVisible();
return super.isVisible() && hasChildren();
}
@SuppressWarnings("unchecked")
@@ -95,7 +95,7 @@ public class TasksNode extends ExternalSystemNode {
@Override
public boolean isVisible() {
return hasChildren() && super.isVisible();
return super.isVisible() && hasChildren();
}
@Override
@@ -1,7 +1,13 @@
apply plugin: 'java'
sourceCompatibility = 1.5
version = '1.0'
#if (${MODULE_GROUP} && ${MODULE_GROUP} != "")
group '${MODULE_GROUP}'
#end
#if (${MODULE_VERSION} && ${MODULE_VERSION} != "")
version '${MODULE_VERSION}'
#end
task wrapper(type: Wrapper) {
gradleVersion = '1.9'
@@ -1,7 +1,13 @@
apply plugin: 'java'
sourceCompatibility = 1.5
version = '1.0'
#if (${MODULE_GROUP} && ${MODULE_GROUP} != "")
group '${MODULE_GROUP}'
#end
#if (${MODULE_VERSION} && ${MODULE_VERSION} != "")
version '${MODULE_VERSION}'
#end
repositories {
mavenCentral()
@@ -1,6 +1,12 @@
#if (${CONTENT} && ${CONTENT} != "")${CONTENT}#end
#if (${MODULE_DIR_NAME} && ${MODULE_DIR_NAME} != "")include '${MODULE_DIR_NAME}'
#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_DIR_NAME} != ${MODULE_NAME})rootProject.children.find { it.name == '${MODULE_DIR_NAME}' }.name = '${MODULE_NAME}'
#if (${CONTENT} && ${CONTENT} != "")${CONTENT}
#end
#if (${MODULE_PATH} && ${MODULE_PATH} != "")
#if (${MODULE_FLAT_DIR} == "true")includeFlat '${MODULE_PATH}'
#else
include '${MODULE_PATH}'
#end
#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_PATH} != ${MODULE_NAME})
findProject(':${MODULE_PATH}')?.name = '${MODULE_NAME}'
#end
#end
@@ -1,11 +1,17 @@
#if (${PROJECT_NAME} && ${PROJECT_NAME} != "")
#if (((!${MODULE_DIR_NAME} || ${MODULE_DIR_NAME} == "")) && (${MODULE_NAME} && ${MODULE_NAME} != ""))rootProject.name = '${MODULE_NAME}'
#elseif(true)rootProject.name = '${PROJECT_NAME}'
#if (((!${MODULE_PATH} || ${MODULE_PATH} == "")) && (${MODULE_NAME} && ${MODULE_NAME} != ""))
rootProject.name = '${MODULE_NAME}'
#else
rootProject.name = '${PROJECT_NAME}'
#end
#end
#if (${MODULE_DIR_NAME} && ${MODULE_DIR_NAME} != "")
include '${MODULE_DIR_NAME}'
#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_DIR_NAME} != ${MODULE_NAME})rootProject.children.find { it.name == '${MODULE_DIR_NAME}' }.name = '${MODULE_NAME}'
#if (${MODULE_PATH} && ${MODULE_PATH} != "")
#if (${MODULE_FLAT_DIR} == "true")includeFlat '${MODULE_PATH}'
#else
include '${MODULE_PATH}'
#end
#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_PATH} != ${MODULE_NAME})
findProject(':${MODULE_PATH}')?.name = '${MODULE_NAME}'
#end
#end
@@ -16,17 +16,10 @@
package org.jetbrains.plugins.gradle.codeInsight;
import com.intellij.ProjectTopics;
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.project.ProjectData;
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
@@ -35,7 +28,6 @@ import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootAdapter;
import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -120,32 +112,9 @@ public class UseDistributionWithSourcesNotificationProvider extends EditorNotifi
public void run() {
updateDefaultWrapperConfiguration(rootProjectPath);
EditorNotifications.getInstance(module.getProject()).updateAllNotifications();
final ProjectDataManager projectDataManager = ServiceManager.getService(ProjectDataManager.class);
ExternalSystemUtil.refreshProject(
module.getProject(), GradleConstants.SYSTEM_ID, settings.getExternalProjectPath(),
new ExternalProjectRefreshCallback() {
@Override
public void onSuccess(@Nullable final DataNode<ProjectData> externalProject) {
if (externalProject == null) {
return;
}
ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(module.getProject()) {
@Override
public void execute() {
ProjectRootManagerEx.getInstanceEx(module.getProject()).mergeRootsChangesDuring(new Runnable() {
@Override
public void run() {
projectDataManager.importData(externalProject.getKey(), Collections.singleton(externalProject), module.getProject(), true);
}
});
}
});
}
@Override
public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
}
}, true, ProgressExecutionMode.START_IN_FOREGROUND_ASYNC);
module.getProject(), GradleConstants.SYSTEM_ID, settings.getExternalProjectPath(), true,
ProgressExecutionMode.START_IN_FOREGROUND_ASYNC);
}
});
return panel;
@@ -32,6 +32,8 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemDebugEnvironment;
import com.intellij.openapi.util.KeyValue;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.BooleanFunction;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
@@ -255,6 +257,10 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
}
DataNode<ModuleData> moduleDataNode = projectDataNode.createChild(ProjectKeys.MODULE, moduleData);
moduleMap.put(moduleName, Pair.create(moduleDataNode, gradleModule));
if(StringUtil.equals(moduleData.getLinkedExternalProjectPath(), projectData.getLinkedExternalProjectPath())) {
projectData.setGroup(moduleData.getGroup());
projectData.setVersion(moduleData.getVersion());
}
}
// populate modules nodes
@@ -17,25 +17,34 @@ package org.jetbrains.plugins.gradle.service.project.wizard;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.projectWizard.ProjectSettingsStep;
import com.intellij.ide.util.EditorHelper;
import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.SettingsStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.project.ProjectId;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.service.project.wizard.AbstractExternalModuleBuilder;
import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.*;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.SdkTypeId;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.io.FileUtil;
@@ -45,6 +54,9 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -72,10 +84,19 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradlePro
private static final String DEFAULT_TEMPLATE_GRADLE_BUILD = "Gradle Build Script.gradle";
private static final String TEMPLATE_ATTRIBUTE_PROJECT_NAME = "PROJECT_NAME";
private static final String TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME = "MODULE_DIR_NAME";
private static final String TEMPLATE_ATTRIBUTE_MODULE_PATH = "MODULE_PATH";
private static final String TEMPLATE_ATTRIBUTE_MODULE_FLAT_DIR = "MODULE_FLAT_DIR";
private static final String TEMPLATE_ATTRIBUTE_MODULE_NAME = "MODULE_NAME";
private static final String TEMPLATE_ATTRIBUTE_MODULE_GROUP = "MODULE_GROUP";
private static final String TEMPLATE_ATTRIBUTE_MODULE_VERSION = "MODULE_VERSION";
private @NotNull WizardContext myWizardContext;
private WizardContext myWizardContext;
@Nullable
private ProjectData myParentProject;
private boolean myInheritGroupId;
private boolean myInheritVersion;
private ProjectId myProjectId;
public GradleModuleBuilder() {
super(GradleConstants.SYSTEM_ID, new GradleProjectSettings());
@@ -105,12 +126,21 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradlePro
final Project project = modifiableRootModel.getProject();
setupGradleBuildFile(modelContentRootDir);
setupGradleSettingsFile(modelContentRootDir, modifiableRootModel);
final String rootProjectPath;
if (myParentProject != null) {
rootProjectPath = myParentProject.getLinkedExternalProjectPath();
}
else {
rootProjectPath =
FileUtil.toCanonicalPath(myWizardContext.isCreatingNewProject() ? project.getBasePath() : modelContentRootDir.getPath());
}
assert rootProjectPath != null;
final VirtualFile gradleBuildFile = setupGradleBuildFile(modelContentRootDir);
setupGradleSettingsFile(rootProjectPath, modelContentRootDir, modifiableRootModel);
if (myWizardContext.isCreatingNewProject()) {
String externalProjectPath = FileUtil.toCanonicalPath(project.getBasePath());
getExternalProjectSettings().setExternalProjectPath(externalProjectPath);
getExternalProjectSettings().setExternalProjectPath(rootProjectPath);
AbstractExternalSystemSettings settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID);
project.putUserData(ExternalSystemDataKeys.NEWLY_CREATED_PROJECT, Boolean.TRUE);
//noinspection unchecked
@@ -118,20 +148,49 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradlePro
}
else {
FileDocumentManager.getInstance().saveAllDocuments();
ExternalSystemUtil.refreshProjects(project, GradleConstants.SYSTEM_ID, false);
final GradleProjectSettings gradleProjectSettings = getExternalProjectSettings();
Runnable runnable = new Runnable() {
public void run() {
if (myParentProject == null) {
gradleProjectSettings.setExternalProjectPath(rootProjectPath);
AbstractExternalSystemSettings settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID);
//noinspection unchecked
settings.linkProject(gradleProjectSettings);
}
ExternalSystemUtil.refreshProject(
project, GradleConstants.SYSTEM_ID, rootProjectPath, false,
ProgressExecutionMode.IN_BACKGROUND_ASYNC);
final PsiFile psiFile;
if (gradleBuildFile != null) {
psiFile = PsiManager.getInstance(project).findFile(gradleBuildFile);
if (psiFile != null) {
EditorHelper.openInEditor(psiFile);
}
}
}
};
// execute when current dialog is closed
ExternalSystemUtil.invokeLater(project, ModalityState.NON_MODAL, runnable);
}
}
@Override
public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) {
myWizardContext = wizardContext;
return super.createWizardSteps(wizardContext, modulesProvider);
return new ModuleWizardStep[]{
new GradleModuleWizardStep(this, wizardContext),
new ExternalModuleSettingsStep<GradleProjectSettings>(
wizardContext, this, new GradleProjectSettingsControl(getExternalProjectSettings()))
};
}
@Nullable
@Override
public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
if (!myWizardContext.isCreatingNewProject()) return new ModuleWizardStep() {
return new ModuleWizardStep() {
@Override
public JComponent getComponent() {
return new JPanel();
@@ -139,11 +198,8 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradlePro
@Override
public void updateDataModel() {
}
};
final GradleProjectSettingsControl settingsControl = new GradleProjectSettingsControl(getExternalProjectSettings());
return new ExternalModuleSettingsStep<GradleProjectSettings>(this, settingsControl);
}
@Override
@@ -167,69 +223,61 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradlePro
}
@Nullable
private VirtualFile setupGradleBuildFile(@NotNull VirtualFile modelContentRootDir) throws ConfigurationException {
final VirtualFile file = getExternalProjectConfigFile(modelContentRootDir.getPath(), GradleConstants.DEFAULT_SCRIPT_NAME);
final String templateName = getExternalProjectSettings().getDistributionType() == DistributionType.WRAPPED
? TEMPLATE_GRADLE_BUILD_WITH_WRAPPER
: DEFAULT_TEMPLATE_GRADLE_BUILD;
private VirtualFile setupGradleBuildFile(@NotNull VirtualFile modelContentRootDir)
throws ConfigurationException {
final VirtualFile file = getOrCreateExternalProjectConfigFile(modelContentRootDir.getPath(), GradleConstants.DEFAULT_SCRIPT_NAME);
Map attributes = ContainerUtil.newHashMap();
if (file != null) {
final String templateName = getExternalProjectSettings().getDistributionType() == DistributionType.WRAPPED
? TEMPLATE_GRADLE_BUILD_WITH_WRAPPER
: DEFAULT_TEMPLATE_GRADLE_BUILD;
Map<String, String> attributes = ContainerUtil.newHashMap();
if (myProjectId != null) {
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_VERSION, myProjectId.getVersion());
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_GROUP, myProjectId.getGroupId());
}
saveFile(file, templateName, attributes);
}
return file;
}
@Nullable
private VirtualFile setupGradleSettingsFile(@NotNull VirtualFile modelContentRootDir, @NotNull ModifiableRootModel model)
private VirtualFile setupGradleSettingsFile(@NotNull String rootProjectPath,
@NotNull VirtualFile modelContentRootDir,
@NotNull ModifiableRootModel model)
throws ConfigurationException {
VirtualFile file = null;
if (myWizardContext.isCreatingNewProject()) {
final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, model.getProject().getBaseDir(), '/');
file = getExternalProjectConfigFile(model.getProject().getBasePath(), GradleConstants.SETTINGS_FILE_NAME);
if (file == null) return null;
final VirtualFile file = getOrCreateExternalProjectConfigFile(rootProjectPath, GradleConstants.SETTINGS_FILE_NAME);
if (file == null) return null;
final String moduleName = myProjectId == null ? model.getModule().getName() : myProjectId.getArtifactId();
if (myWizardContext.isCreatingNewProject() || myParentProject == null) {
final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, file.getParent(), '/');
Map<String, String> attributes = ContainerUtil.newHashMap();
final String projectName = model.getProject().getName();
attributes.put(TEMPLATE_ATTRIBUTE_PROJECT_NAME, projectName);
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME, moduleDirName);
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, model.getModule().getName());
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_PATH, moduleDirName);
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, moduleName);
saveFile(file, TEMPLATE_GRADLE_SETTINGS, attributes);
}
else {
Map<String, Module> moduleMap = ContainerUtil.newHashMap();
for (Module module : ModuleManager.getInstance(model.getProject()).getModules()) {
for (ContentEntry contentEntry : model.getContentEntries()) {
if (contentEntry.getFile() != null) {
moduleMap.put(contentEntry.getFile().getPath(), module);
}
}
char separatorChar = file.getParent() == null || !VfsUtilCore.isAncestor(file.getParent(), modelContentRootDir, true) ? '/' : ':';
String modulePath = VfsUtil.getPath(file, modelContentRootDir, separatorChar);
Map<String, String> attributes = ContainerUtil.newHashMap();
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, moduleName);
// check for flat structure
final String flatStuctureModulePath =
modulePath != null && StringUtil.startsWith(modulePath, "../") ? StringUtil.trimStart(modulePath, "../") : null;
if (StringUtil.equals(flatStuctureModulePath, modelContentRootDir.getName())) {
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_FLAT_DIR, "true");
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_PATH, flatStuctureModulePath);
}
else {
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_PATH, modulePath);
}
VirtualFile virtualFile = modelContentRootDir;
Module module = null;
while (virtualFile != null && module == null) {
module = moduleMap.get(virtualFile.getPath());
virtualFile = virtualFile.getParent();
}
if (module != null) {
String rootProjectPath = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
if (!StringUtil.isEmpty(rootProjectPath)) {
VirtualFile rootProjectFile = VfsUtil.findFileByIoFile(new File(rootProjectPath), true);
if (rootProjectFile == null) return null;
final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, rootProjectFile, '/');
file = getExternalProjectConfigFile(rootProjectPath, GradleConstants.SETTINGS_FILE_NAME);
if (file == null) return null;
Map<String, String> attributes = ContainerUtil.newHashMap();
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME, moduleDirName);
attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, model.getModule().getName());
appendToFile(file, TEMPLATE_GRADLE_SETTINGS_MERGE, attributes);
}
}
appendToFile(file, TEMPLATE_GRADLE_SETTINGS_MERGE, attributes);
}
return file;
}
@@ -239,7 +287,9 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradlePro
FileTemplateManager manager = FileTemplateManager.getDefaultInstance();
FileTemplate template = manager.getInternalTemplate(templateName);
try {
VfsUtil.saveText(file, templateAttributes != null ? template.getText(templateAttributes) : template.getText());
String lineSeparator = CodeStyleSettingsManager.getSettings(ProjectManagerEx.getInstanceEx().getDefaultProject()).getLineSeparator();
VfsUtil.saveText(file, StringUtil.convertLineSeparators(
templateAttributes != null ? template.getText(templateAttributes) : template.getText(), lineSeparator));
}
catch (IOException e) {
LOG.warn(String.format("Unexpected exception on applying template %s config", GradleConstants.SYSTEM_ID.getReadableName()), e);
@@ -254,8 +304,16 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradlePro
FileTemplateManager manager = FileTemplateManager.getDefaultInstance();
FileTemplate template = manager.getInternalTemplate(templateName);
try {
VfsUtil.saveText(file, VfsUtilCore.loadText(file) +
(templateAttributes != null ? template.getText(templateAttributes) : template.getText()));
String lineSeparator = LoadTextUtil.detectLineSeparator(file, false);
if (lineSeparator == null) {
lineSeparator = CodeStyleSettingsManager.getSettings(ProjectManagerEx.getInstanceEx().getDefaultProject()).getLineSeparator();
}
String content = StringUtil.trimTrailing(VfsUtilCore.loadText(file)) +
lineSeparator +
StringUtil.convertLineSeparators(
(templateAttributes != null ? template.getText(templateAttributes) : template.getText()), lineSeparator);
content = StringUtil.convertLineSeparators(content, lineSeparator);
VfsUtil.saveText(file, content);
}
catch (IOException e) {
LOG.warn(String.format("Unexpected exception on appending template %s config", GradleConstants.SYSTEM_ID.getReadableName()), e);
@@ -267,9 +325,54 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradlePro
@Nullable
private static VirtualFile getExternalProjectConfigFile(@NotNull String parent, @NotNull String fileName) {
private static VirtualFile getOrCreateExternalProjectConfigFile(@NotNull String parent, @NotNull String fileName) {
File file = new File(parent, fileName);
FileUtilRt.createIfNotExists(file);
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
}
public void setParentProject(@Nullable ProjectData parentProject) {
myParentProject = parentProject;
}
public boolean isInheritGroupId() {
return myInheritGroupId;
}
public void setInheritGroupId(boolean inheritGroupId) {
myInheritGroupId = inheritGroupId;
}
public boolean isInheritVersion() {
return myInheritVersion;
}
public void setInheritVersion(boolean inheritVersion) {
myInheritVersion = inheritVersion;
}
public ProjectId getProjectId() {
return myProjectId;
}
public void setProjectId(@NotNull ProjectId projectId) {
myProjectId = projectId;
}
@Nullable
@Override
public ModuleWizardStep modifySettingsStep(@NotNull SettingsStep settingsStep) {
if (settingsStep instanceof ProjectSettingsStep) {
final ProjectSettingsStep projectSettingsStep = (ProjectSettingsStep)settingsStep;
if (myProjectId != null) {
final JTextField moduleNameField = settingsStep.getModuleNameField();
if (moduleNameField != null) {
moduleNameField.setText(myProjectId.getArtifactId());
}
projectSettingsStep.setModuleName(myProjectId.getArtifactId());
}
projectSettingsStep.bindModuleSettings();
}
return super.modifySettingsStep(settingsStep);
}
}
@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.gradle.service.project.wizard.GradleModuleWizardStep">
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="5" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="529" height="386"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="ddae6" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="GroupId"/>
</properties>
</component>
<component id="bbb74" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="ArtifactId"/>
</properties>
</component>
<component id="4eb56" class="javax.swing.JLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Version"/>
</properties>
</component>
<component id="d7d25" class="javax.swing.JTextField" binding="myGroupIdField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="efb5e" class="javax.swing.JTextField" binding="myArtifactIdField">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="b1344" class="javax.swing.JTextField" binding="myVersionField">
<constraints>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="d0095" class="javax.swing.JCheckBox" binding="myInheritGroupIdCheckBox">
<constraints>
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Inherit"/>
</properties>
</component>
<component id="897ff" class="javax.swing.JCheckBox" binding="myInheritVersionCheckBox">
<constraints>
<grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Inherit"/>
</properties>
</component>
<grid id="102d8" binding="myAddToPanel" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="cf9eb" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Add as module to"/>
</properties>
</component>
<component id="376fa" class="javax.swing.JButton" binding="mySelectParent">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<margin top="0" left="0" bottom="0" right="0"/>
<text value=""/>
</properties>
</component>
<component id="651e0" class="javax.swing.JLabel" binding="myParentNameLabel">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Label"/>
</properties>
</component>
</children>
</grid>
<grid id="90185" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="4" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
</children>
</grid>
</form>
@@ -0,0 +1,282 @@
/*
* Copyright 2000-2015 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 org.jetbrains.plugins.gradle.service.project.wizard;
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.externalSystem.model.ExternalProjectInfo;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.project.ProjectId;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* @author Vladislav.Soroka
* @since 4/15/2015
*/
public class GradleModuleWizardStep extends ModuleWizardStep {
private static final Icon WIZARD_ICON = null;
private static final String INHERIT_GROUP_ID_KEY = "GradleModuleWizard.inheritGroupId";
private static final String INHERIT_VERSION_KEY = "GradleModuleWizard.inheritVersion";
@Nullable
private final Project myProjectOrNull;
@NotNull
private final GradleModuleBuilder myBuilder;
@NotNull
private final WizardContext myContext;
@Nullable
private ProjectData myParent;
private String myInheritedGroupId;
private String myInheritedVersion;
private JPanel myMainPanel;
private JLabel myParentNameLabel;
private JButton mySelectParent;
private JTextField myGroupIdField;
private JCheckBox myInheritGroupIdCheckBox;
private JTextField myArtifactIdField;
private JTextField myVersionField;
private JCheckBox myInheritVersionCheckBox;
private JPanel myAddToPanel;
public GradleModuleWizardStep(@NotNull GradleModuleBuilder builder, @NotNull WizardContext context) {
myProjectOrNull = context.getProject();
myBuilder = builder;
myContext = context;
initComponents();
loadSettings();
}
private void initComponents() {
mySelectParent.setIcon(AllIcons.Actions.Module);
mySelectParent.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
myParent = doSelectProject(myParent);
updateComponents();
}
});
ActionListener updatingListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
updateComponents();
}
};
myInheritGroupIdCheckBox.addActionListener(updatingListener);
myInheritVersionCheckBox.addActionListener(updatingListener);
}
@Override
public JComponent getPreferredFocusedComponent() {
return myGroupIdField;
}
private ProjectData doSelectProject(ProjectData current) {
assert myProjectOrNull != null : "must not be called when creating a new project";
SelectExternalProjectDialog d = new SelectExternalProjectDialog(myProjectOrNull, current);
if (!d.showAndGet()) {
return current;
}
return d.getResult();
}
@Override
public void onStepLeaving() {
saveSettings();
}
private void loadSettings() {
myBuilder.setInheritGroupId(getSavedValue(INHERIT_GROUP_ID_KEY, true));
myBuilder.setInheritVersion(getSavedValue(INHERIT_VERSION_KEY, true));
}
private void saveSettings() {
saveValue(INHERIT_GROUP_ID_KEY, myInheritGroupIdCheckBox.isSelected());
saveValue(INHERIT_VERSION_KEY, myInheritVersionCheckBox.isSelected());
}
private static boolean getSavedValue(String key, boolean defaultValue) {
return getSavedValue(key, String.valueOf(defaultValue)).equals(String.valueOf(true));
}
private static String getSavedValue(String key, String defaultValue) {
String value = PropertiesComponent.getInstance().getValue(key);
return value == null ? defaultValue : value;
}
private static void saveValue(String key, boolean value) {
saveValue(key, String.valueOf(value));
}
private static void saveValue(String key, String value) {
PropertiesComponent props = PropertiesComponent.getInstance();
props.setValue(key, value);
}
public JComponent getComponent() {
return myMainPanel;
}
@Override
public boolean validate() throws ConfigurationException {
if (StringUtil.isEmptyOrSpaces(myArtifactIdField.getText())) {
throw new ConfigurationException("Please, specify artifactId");
}
return true;
}
@Nullable
public ProjectData findPotentialParentProject(@Nullable Project project) {
if (project == null) return null;
final ExternalProjectInfo projectInfo =
ProjectDataManager.getInstance().getExternalProjectData(project, GradleConstants.SYSTEM_ID, myContext.getProjectFileDirectory());
return projectInfo != null && projectInfo.getExternalProjectStructure() != null
? projectInfo.getExternalProjectStructure().getData()
: null;
}
private static void setTestIfEmpty(@NotNull JTextField artifactIdField, @Nullable String text) {
if (StringUtil.isEmpty(artifactIdField.getText())) {
artifactIdField.setText(StringUtil.notNullize(text));
}
}
@Override
public void updateStep() {
myParent = findPotentialParentProject(myProjectOrNull);
ProjectId projectId = myBuilder.getProjectId();
if (projectId == null) {
setTestIfEmpty(myArtifactIdField, myBuilder.getName());
setTestIfEmpty(myGroupIdField, myParent == null ? myBuilder.getName() : myParent.getGroup());
setTestIfEmpty(myVersionField, myParent == null ? "1.0-SNAPSHOT" : myParent.getVersion());
}
else {
setTestIfEmpty(myArtifactIdField, projectId.getArtifactId());
setTestIfEmpty(myGroupIdField, projectId.getGroupId());
setTestIfEmpty(myVersionField, projectId.getVersion());
}
myInheritGroupIdCheckBox.setSelected(myBuilder.isInheritGroupId());
myInheritVersionCheckBox.setSelected(myBuilder.isInheritVersion());
updateComponents();
}
private void updateComponents() {
boolean isAddToVisible = !myContext.isCreatingNewProject() && myProjectOrNull != null && isGradleModuleExist();
myAddToPanel.setVisible(isAddToVisible);
myInheritGroupIdCheckBox.setVisible(isAddToVisible);
myInheritVersionCheckBox.setVisible(isAddToVisible);
myParentNameLabel.setText(formatProjectString(myParent));
if (myParent == null) {
myContext.putUserData(ExternalModuleSettingsStep.SKIP_STEP_KEY, Boolean.FALSE);
myGroupIdField.setEnabled(true);
myVersionField.setEnabled(true);
myInheritGroupIdCheckBox.setEnabled(false);
myInheritVersionCheckBox.setEnabled(false);
}
else {
myContext.putUserData(ExternalModuleSettingsStep.SKIP_STEP_KEY, Boolean.TRUE);
myGroupIdField.setEnabled(!myInheritGroupIdCheckBox.isSelected());
myVersionField.setEnabled(!myInheritVersionCheckBox.isSelected());
if (myInheritGroupIdCheckBox.isSelected()
|| myGroupIdField.getText().equals(myInheritedGroupId)) {
myGroupIdField.setText(myParent.getGroup());
}
if (myInheritVersionCheckBox.isSelected()
|| myVersionField.getText().equals(myInheritedVersion)) {
myVersionField.setText(myParent.getVersion());
}
myInheritedGroupId = myGroupIdField.getText();
myInheritedVersion = myVersionField.getText();
myInheritGroupIdCheckBox.setEnabled(true);
myInheritVersionCheckBox.setEnabled(true);
}
}
private boolean isGradleModuleExist() {
for (Module module : myContext.getModulesProvider().getModules()) {
if (ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) return true;
}
return false;
}
private static String formatProjectString(ProjectData moduleData) {
if (moduleData == null) return "<none>";
return moduleData.toString();
}
@Override
public void updateDataModel() {
myContext.setProjectBuilder(myBuilder);
myBuilder.setParentProject(myParent);
myBuilder.setProjectId(new ProjectId(myGroupIdField.getText(),
myArtifactIdField.getText(),
myVersionField.getText()));
myBuilder.setInheritGroupId(myInheritGroupIdCheckBox.isSelected());
myBuilder.setInheritVersion(myInheritVersionCheckBox.isSelected());
if (StringUtil.isNotEmpty(myBuilder.getProjectId().getArtifactId())) {
myContext.setProjectName(myBuilder.getProjectId().getArtifactId());
}
if (myParent != null) {
myContext.setProjectFileDirectory(myParent.getLinkedExternalProjectPath() + '/' + myContext.getProjectName());
}
else {
if (myProjectOrNull != null) {
myContext.setProjectFileDirectory(myProjectOrNull.getBaseDir().getPath() + '/' + myContext.getProjectName());
}
}
}
@Override
public Icon getIcon() {
return WIZARD_ICON;
}
}
@@ -52,7 +52,7 @@ public class GradleProjectOpenProcessor extends ProjectOpenProcessorBase<GradleP
@Nullable
@Override
public String[] getSupportedExtensions() {
return BUILD_FILE_EXTENSIONS;
return new String[] {GradleConstants.DEFAULT_SCRIPT_NAME, GradleConstants.SETTINGS_FILE_NAME};
}
@Override
@@ -0,0 +1,75 @@
/*
* Copyright 2000-2015 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 org.jetbrains.plugins.gradle.service.project.wizard;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.view.ProjectNode;
import com.intellij.openapi.project.Project;
import com.intellij.ui.treeStructure.NullNode;
import com.intellij.ui.treeStructure.SimpleNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
import java.awt.event.ActionEvent;
/**
* @author Vladislav.Soroka
* @since 4/15/2015
*/
public class SelectExternalProjectDialog extends SelectExternalSystemNodeDialog {
private ProjectData myResult;
public SelectExternalProjectDialog(Project project, final ProjectData current) {
super(project, String.format("Select %s Project", GradleConstants.SYSTEM_ID.getReadableName()), ProjectNode.class,
new SelectExternalSystemNodeDialog.NodeSelector() {
public boolean shouldSelect(SimpleNode node) {
if (node instanceof ProjectNode) {
return ((ProjectNode)node).getData() == current;
}
return false;
}
});
init();
}
@NotNull
@Override
protected Action[] createActions() {
Action selectNoneAction = new AbstractAction("&None") {
public void actionPerformed(ActionEvent e) {
doOKAction();
myResult = null;
}
};
return new Action[]{selectNoneAction, getOKAction(), getCancelAction()};
}
@Override
protected void doOKAction() {
SimpleNode node = getSelectedNode();
if (node instanceof NullNode) node = null;
myResult = node instanceof ProjectNode ? ((ProjectNode)node).getData() : null;
super.doOKAction();
}
public ProjectData getResult() {
return myResult;
}
}
@@ -0,0 +1,124 @@
/*
* Copyright 2000-2015 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 org.jetbrains.plugins.gradle.service.project.wizard;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalProjectInfo;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
import com.intellij.openapi.externalSystem.view.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.treeStructure.SimpleNode;
import com.intellij.ui.treeStructure.SimpleNodeVisitor;
import com.intellij.ui.treeStructure.SimpleTree;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
import javax.swing.tree.TreeSelectionModel;
import java.util.Collection;
import java.util.List;
/**
* @author Vladislav.Soroka
* @since 4/15/2015
*/
public class SelectExternalSystemNodeDialog extends DialogWrapper {
private final SimpleTree myTree;
private final NodeSelector mySelector;
public SelectExternalSystemNodeDialog(Project project,
String title,
final Class<? extends ExternalSystemNode> nodeClass,
NodeSelector selector) {
super(project, false);
mySelector = selector;
setTitle(title);
myTree = new SimpleTree();
myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
final ExternalProjectsView projectsView = ExternalProjectsManager.getInstance(project).getExternalProjectsView(GradleConstants.SYSTEM_ID);
if(projectsView != null) {
final ExternalProjectsStructure treeStructure = new ExternalProjectsStructure(project, myTree) {
@Override
protected Class<? extends ExternalSystemNode>[] getVisibleNodesClasses() {
return new Class[]{nodeClass};
}
};
treeStructure.init(new ExternalProjectsViewAdapter(projectsView) {
@Nullable
@Override
public ExternalProjectsStructure getStructure() {
return treeStructure;
}
@Override
public void updateUpTo(ExternalSystemNode node) {
treeStructure.updateUpTo(node);
}
});
final Collection<ExternalProjectInfo> projectsData =
ProjectDataManager.getInstance().getExternalProjectsData(project, GradleConstants.SYSTEM_ID);
final List<DataNode<ProjectData>> dataNodes =
ContainerUtil.mapNotNull(projectsData, new Function<ExternalProjectInfo, DataNode<ProjectData>>() {
@Override
public DataNode<ProjectData> fun(ExternalProjectInfo info) {
return info.getExternalProjectStructure();
}
});
treeStructure.updateProjects(dataNodes);
final SimpleNode[] selection = new SimpleNode[]{null};
treeStructure.accept(new SimpleNodeVisitor() {
public boolean accept(SimpleNode each) {
if (!mySelector.shouldSelect(each)) return false;
selection[0] = each;
return true;
}
});
if (selection[0] != null) {
treeStructure.select(selection[0]);
}
}
init();
}
protected SimpleNode getSelectedNode() {
return myTree.getNodeFor(myTree.getSelectionPath());
}
@Nullable
protected JComponent createCenterPanel() {
final JScrollPane pane = ScrollPaneFactory.createScrollPane(myTree);
pane.setPreferredSize(JBUI.size(320, 400));
return pane;
}
protected interface NodeSelector {
boolean shouldSelect(SimpleNode node);
}
}