Reduce obsolete external system local settings data (IDEA-195275)

This commit is contained in:
Vladislav.Soroka
2018-07-20 13:56:41 +03:00
parent fa3b7eda04
commit bbefbce9b4
9 changed files with 104 additions and 393 deletions
@@ -9,7 +9,6 @@ import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecution
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo;
import com.intellij.openapi.externalSystem.model.project.ExternalProjectBuildClasspathPojo;
import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo;
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;
@@ -17,11 +16,14 @@ import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import gnu.trove.THashMap;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.*;
/**
* Holds local project-level external system-related settings (should be kept at the '*.iws' or 'workspace.xml').
* <p/>
@@ -30,7 +32,7 @@ import java.util.*;
* <p/>
* <b>Note:</b> non-abstract sub-classes of this class are expected to be marked by {@link State} annotation configured
* to be stored under a distinct name at a workspace file.
*
*
* @author Denis Zhdanov
*/
public abstract class AbstractExternalSystemLocalSettings<S extends AbstractExternalSystemLocalSettings.State> {
@@ -64,20 +66,12 @@ public abstract class AbstractExternalSystemLocalSettings<S extends AbstractExte
}
}
for (Iterator<Map.Entry<String, Collection<ExternalTaskPojo>>> it = state.availableTasks.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, Collection<ExternalTaskPojo>> entry = it.next();
if (linkedProjectPathsToForget.contains(entry.getKey())
|| linkedProjectPathsToForget.contains(ExternalSystemApiUtil.getRootProjectPath(entry.getKey(), myExternalSystemId, myProject))) {
it.remove();
}
}
if (!ContainerUtil.isEmpty(state.recentTasks)) {
for (Iterator<ExternalTaskExecutionInfo> it = state.recentTasks.iterator(); it.hasNext(); ) {
ExternalTaskExecutionInfo taskInfo = it.next();
String path = taskInfo.getSettings().getExternalProjectPath();
if (linkedProjectPathsToForget.contains(path) ||
linkedProjectPathsToForget.contains(ExternalSystemApiUtil.getRootProjectPath(path, myExternalSystemId, myProject))) {
linkedProjectPathsToForget.contains(getRootProjectPath(path, myExternalSystemId, myProject))) {
it.remove();
}
}
@@ -87,7 +81,7 @@ public abstract class AbstractExternalSystemLocalSettings<S extends AbstractExte
it.hasNext(); ) {
Map.Entry<String, ExternalProjectBuildClasspathPojo> entry = it.next();
if (linkedProjectPathsToForget.contains(entry.getKey())
|| linkedProjectPathsToForget.contains(ExternalSystemApiUtil.getRootProjectPath(entry.getKey(), myExternalSystemId, myProject))) {
|| linkedProjectPathsToForget.contains(getRootProjectPath(entry.getKey(), myExternalSystemId, myProject))) {
it.remove();
}
}
@@ -95,7 +89,7 @@ public abstract class AbstractExternalSystemLocalSettings<S extends AbstractExte
for (Iterator<Map.Entry<String, SyncType>> it = state.projectSyncType.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, SyncType> entry = it.next();
if (linkedProjectPathsToForget.contains(entry.getKey())
|| linkedProjectPathsToForget.contains(ExternalSystemApiUtil.getRootProjectPath(entry.getKey(), myExternalSystemId, myProject))) {
|| linkedProjectPathsToForget.contains(getRootProjectPath(entry.getKey(), myExternalSystemId, myProject))) {
it.remove();
}
}
@@ -115,13 +109,14 @@ public abstract class AbstractExternalSystemLocalSettings<S extends AbstractExte
state.availableProjects = projects;
}
/**
* @deprecated use com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil#findProjectTasks
*/
@ApiStatus.ScheduledForRemoval(inVersion = "2019")
@Deprecated
@NotNull
public Map<String, Collection<ExternalTaskPojo>> getAvailableTasks() {
return state.availableTasks;
}
public void setAvailableTasks(@NotNull Map<String, Collection<ExternalTaskPojo>> tasks) {
state.availableTasks = tasks;
return Collections.emptyMap();
}
@NotNull
@@ -156,13 +151,12 @@ public abstract class AbstractExternalSystemLocalSettings<S extends AbstractExte
}
private void pruneOutdatedEntries() {
ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(myExternalSystemId);
ExternalSystemManager<?, ?, ?, ?, ?> manager = getManager(myExternalSystemId);
assert manager != null;
Set<String> pathsToForget = ContainerUtilRt.newHashSet();
for (ExternalProjectPojo pojo : state.availableProjects.keySet()) {
pathsToForget.add(pojo.getPath());
}
pathsToForget.addAll(state.availableTasks.keySet());
for (ExternalTaskExecutionInfo taskInfo : ContainerUtil.notNullize(state.recentTasks)) {
pathsToForget.add(taskInfo.getSettings().getExternalProjectPath());
}
@@ -172,8 +166,8 @@ public abstract class AbstractExternalSystemLocalSettings<S extends AbstractExte
pathsToForget.remove(projectSettings.getExternalProjectPath());
}
for (Module module : ModuleManager.getInstance(myProject).getModules()) {
if (!ExternalSystemApiUtil.isExternalSystemAwareModule(myExternalSystemId, module)) continue;
pathsToForget.remove(ExternalSystemApiUtil.getExternalProjectPath(module));
if (!isExternalSystemAwareModule(myExternalSystemId, module)) continue;
pathsToForget.remove(getExternalProjectPath(module));
}
if (!pathsToForget.isEmpty()) {
@@ -189,7 +183,6 @@ public abstract class AbstractExternalSystemLocalSettings<S extends AbstractExte
public void fillState(@NotNull State otherState) {
otherState.recentTasks.clear();
otherState.availableProjects = state.availableProjects;
otherState.availableTasks = state.availableTasks;
otherState.modificationStamps = state.modificationStamps;
otherState.projectBuildClasspath = state.projectBuildClasspath;
otherState.projectSyncType = state.projectSyncType;
@@ -198,8 +191,6 @@ public abstract class AbstractExternalSystemLocalSettings<S extends AbstractExte
public static class State {
public final List<ExternalTaskExecutionInfo> recentTasks = new SmartList<>();
public Map<ExternalProjectPojo, Collection<ExternalProjectPojo>> availableProjects = new THashMap<>();
public Map<String/* project name */, Collection<ExternalTaskPojo>> availableTasks = new THashMap<>();
public Map<String/* linked project path */, Long/* last config modification stamp */> modificationStamps = new THashMap<>();
public Map<String/* linked project path */, ExternalProjectBuildClasspathPojo> projectBuildClasspath = new THashMap<>();
public Map<String/* linked project path */, SyncType> projectSyncType = new THashMap<>();
@@ -20,13 +20,13 @@ import com.intellij.openapi.application.*;
import com.intellij.openapi.externalSystem.ExternalSystemAutoImportAware;
import com.intellij.openapi.externalSystem.ExternalSystemManager;
import com.intellij.openapi.externalSystem.ExternalSystemModulePropertyManager;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
import com.intellij.openapi.externalSystem.model.Key;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.*;
import com.intellij.openapi.externalSystem.model.project.LibraryData;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.settings.ExternalSystemExecutionSettings;
import com.intellij.openapi.externalSystem.model.task.TaskData;
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
@@ -170,7 +170,7 @@ public class ExternalSystemApiUtil {
}
/**
* @param path target path
* @param path target path
* @return absolute path that points to the same location as the given one and that uses only slashes
*/
@NotNull
@@ -303,7 +303,7 @@ public class ExternalSystemApiUtil {
}
public static void visit(@Nullable DataNode node, @NotNull Consumer<DataNode<?>> consumer) {
if(node == null) return;
if (node == null) return;
Stack<DataNode> toProcess = ContainerUtil.newStack(node);
while (!toProcess.isEmpty()) {
@@ -395,7 +395,7 @@ public class ExternalSystemApiUtil {
task.run();
return;
}
if (synchronous) {
app.invokeAndWait(task);
}
@@ -420,11 +420,11 @@ public class ExternalSystemApiUtil {
}
/**
* Adds runnable to Event Dispatch Queue
* if we aren't in UnitTest of Headless environment mode
*
* @param runnable Runnable
*/
* Adds runnable to Event Dispatch Queue
* if we aren't in UnitTest of Headless environment mode
*
* @param runnable Runnable
*/
public static void addToInvokeLater(final Runnable runnable) {
final Application application = ApplicationManager.getApplication();
final boolean unitTestMode = application.isUnitTestMode();
@@ -442,9 +442,9 @@ public class ExternalSystemApiUtil {
/**
* Configures given classpath to reference target i18n bundle file(s).
*
* @param classPath process classpath
* @param bundlePath path to the target bundle file
* @param contextClass class from the same content root as the target bundle file
* @param classPath process classpath
* @param bundlePath path to the target bundle file
* @param contextClass class from the same content root as the target bundle file
*/
public static void addBundle(@NotNull PathsList classPath, @NotNull String bundlePath, @NotNull Class<?> contextClass) {
String pathToUse = bundlePath.replace('.', '/');
@@ -473,10 +473,10 @@ public class ExternalSystemApiUtil {
* This might be necessary in a situation when project-level setting is changed (e.g. project name). We don't want to rename
* ide project if it doesn't completely corresponds to the given ide project then.
*
* @param ideProject target ide project
* @param projectData target external project
* @return {@code true} if given ide project has 1-1 mapping to the given external project;
* {@code false} otherwise
* @param ideProject target ide project
* @param projectData target external project
* @return {@code true} if given ide project has 1-1 mapping to the given external project;
* {@code false} otherwise
*/
public static boolean isOneToOneMapping(@NotNull Project ideProject, @NotNull ProjectData projectData) {
String linkedExternalProjectPath = null;
@@ -544,18 +544,17 @@ public class ExternalSystemApiUtil {
* <p/>
* This method tries to find root project's config path assuming that given path points to a sub-project's config path.
*
* @param externalProjectPath external sub-project's config path
* @param externalSystemId target external system
* @param project target ide project
* @return root external project's path if given path is considered to point to a known sub-project's config;
* {@code null} if it's not possible to find a root project's config path on the basis of the
* given path
* @param externalProjectPath external sub-project's config path
* @param externalSystemId target external system
* @param project target ide project
* @return root external project's path if given path is considered to point to a known sub-project's config;
* {@code null} if it's not possible to find a root project's config path on the basis of the
* given path
*/
@Nullable
public static String getRootProjectPath(@NotNull String externalProjectPath,
@NotNull ProjectSystemId externalSystemId,
@NotNull Project project)
{
@NotNull Project project) {
ExternalSystemManager<?, ?, ?, ?, ?> manager = getManager(externalSystemId);
if (manager == null) {
return null;
@@ -569,7 +568,7 @@ public class ExternalSystemApiUtil {
/**
* {@link RemoteUtil#unwrap(Throwable) unwraps} given exception if possible and builds error message for it.
*
* @param e exception to process
* @param e exception to process
* @return error message for the given exception
*/
@SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "IOResourceOpenedButNotSafelyClosed"})
@@ -600,8 +599,7 @@ public class ExternalSystemApiUtil {
@SuppressWarnings("unchecked")
@NotNull
public static AbstractExternalSystemSettings getSettings(@NotNull Project project, @NotNull ProjectSystemId externalSystemId)
throws IllegalArgumentException
{
throws IllegalArgumentException {
ExternalSystemManager<?, ?, ?, ?, ?> manager = getManager(externalSystemId);
if (manager == null) {
throw new IllegalArgumentException(String.format(
@@ -615,8 +613,7 @@ public class ExternalSystemApiUtil {
@SuppressWarnings("unchecked")
public static <S extends AbstractExternalSystemLocalSettings> S getLocalSettings(@NotNull Project project,
@NotNull ProjectSystemId externalSystemId)
throws IllegalArgumentException
{
throws IllegalArgumentException {
ExternalSystemManager<?, ?, ?, ?, ?> manager = getManager(externalSystemId);
if (manager == null) {
throw new IllegalArgumentException(String.format(
@@ -629,10 +626,9 @@ public class ExternalSystemApiUtil {
@SuppressWarnings("unchecked")
public static <S extends ExternalSystemExecutionSettings> S getExecutionSettings(@NotNull Project project,
@NotNull String linkedProjectPath,
@NotNull ProjectSystemId externalSystemId)
throws IllegalArgumentException
{
@NotNull String linkedProjectPath,
@NotNull ProjectSystemId externalSystemId)
throws IllegalArgumentException {
ExternalSystemManager<?, ?, ?, ?, ?> manager = getManager(externalSystemId);
if (manager == null) {
throw new IllegalArgumentException(String.format(
@@ -652,10 +648,9 @@ public class ExternalSystemApiUtil {
* <p/>
* This method allows to check whether the ide is configured to use 'out of process' or 'in process' mode for the system.
*
* @param externalSystemId target external system
*
* @return {@code true} if the ide is configured to work with external system api from the ide process;
* {@code false} otherwise
* @param externalSystemId target external system
* @return {@code true} if the ide is configured to work with external system api from the ide process;
* {@code false} otherwise
*/
public static boolean isInProcessMode(ProjectSystemId externalSystemId) {
return Registry.is(externalSystemId.getId() + ExternalSystemConstants.USE_IN_PROCESS_COMMUNICATION_REGISTRY_KEY_SUFFIX, false);
@@ -665,48 +660,54 @@ public class ExternalSystemApiUtil {
return ExternalProjectSystemRegistry.getInstance().getSourceById(systemId.getId());
}
@Contract(value = "_, null -> false", pure=true)
@Contract(value = "_, null -> false", pure = true)
public static boolean isExternalSystemAwareModule(@NotNull ProjectSystemId systemId, @Nullable Module module) {
return module != null && !module.isDisposed() && systemId.getId().equals(ExternalSystemModulePropertyManager.getInstance(module).getExternalSystemId());
return module != null &&
!module.isDisposed() &&
systemId.getId().equals(ExternalSystemModulePropertyManager.getInstance(module).getExternalSystemId());
}
@Contract(value = "_, null -> false", pure=true)
@Contract(value = "_, null -> false", pure = true)
public static boolean isExternalSystemAwareModule(@NotNull String systemId, @Nullable Module module) {
return module != null && !module.isDisposed() && systemId.equals(ExternalSystemModulePropertyManager.getInstance(module).getExternalSystemId());
return module != null &&
!module.isDisposed() &&
systemId.equals(ExternalSystemModulePropertyManager.getInstance(module).getExternalSystemId());
}
@Nullable
@Contract(pure=true)
@Contract(pure = true)
public static String getExternalProjectPath(@Nullable Module module) {
return module != null && !module.isDisposed() ? ExternalSystemModulePropertyManager.getInstance(module).getLinkedProjectPath() : null;
}
@Nullable
@Contract(pure=true)
@Contract(pure = true)
public static String getExternalRootProjectPath(@Nullable Module module) {
return module != null && !module.isDisposed() ? ExternalSystemModulePropertyManager.getInstance(module).getRootProjectPath() : null;
}
@Nullable
@Contract(pure=true)
@Contract(pure = true)
public static String getExternalProjectId(@Nullable Module module) {
return module != null && !module.isDisposed() ? ExternalSystemModulePropertyManager.getInstance(module).getLinkedProjectId() : null;
}
@Nullable
@Contract(pure=true)
@Contract(pure = true)
public static String getExternalProjectGroup(@Nullable Module module) {
return module != null && !module.isDisposed() ? ExternalSystemModulePropertyManager.getInstance(module).getExternalModuleGroup() : null;
}
@Nullable
@Contract(pure=true)
@Contract(pure = true)
public static String getExternalProjectVersion(@Nullable Module module) {
return module != null && !module.isDisposed() ? ExternalSystemModulePropertyManager.getInstance(module).getExternalModuleVersion() : null;
return module != null && !module.isDisposed()
? ExternalSystemModulePropertyManager.getInstance(module).getExternalModuleVersion()
: null;
}
@Nullable
@Contract(pure=true)
@Contract(pure = true)
public static String getExternalModuleType(@Nullable Module module) {
return module != null && !module.isDisposed() ? ExternalSystemModulePropertyManager.getInstance(module).getExternalModuleType() : null;
}
@@ -718,6 +719,33 @@ public class ExternalSystemApiUtil {
getSettings(project, systemId).subscribe(listener);
}
@NotNull
public Collection<TaskData> findProjectTasks(@NotNull Project project,
@NotNull ProjectSystemId systemId,
@NotNull String projectPath) {
AbstractExternalSystemSettings settings = getSettings(project, systemId);
ExternalProjectSettings linkedProjectSettings = settings.getLinkedProjectSettings(projectPath);
if (linkedProjectSettings == null) return Collections.emptyList();
ExternalProjectInfo projectInfo = ProjectDataManager.getInstance().getExternalProjectsData(project, systemId).stream()
.filter(info -> FileUtil.pathsEqual(linkedProjectSettings.getExternalProjectPath(), info.getExternalProjectPath()))
.findFirst().orElse(null);
if (projectInfo == null) return Collections.emptyList();
DataNode<ProjectData> projectStructure = projectInfo.getExternalProjectStructure();
if (projectStructure == null) return Collections.emptyList();
List<TaskData> tasks = ContainerUtil.newSmartList();
DataNode<ModuleData> moduleDataNode = findAll(projectStructure, ProjectKeys.MODULE).stream()
.filter(moduleNode -> FileUtil.pathsEqual(projectPath, moduleNode.getData().getLinkedExternalProjectPath()))
.findFirst().orElse(null);
if (moduleDataNode == null) return Collections.emptyList();
findAll(moduleDataNode, ProjectKeys.TASK).stream().map(DataNode::getData).forEach(tasks::add);
return tasks;
}
/**
* DO NOT USE THIS METHOD.
* The method should be removed when the 'java' subsystem features will be extracted from External System API [IDEA-187832]
@@ -7,13 +7,11 @@ import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.ExternalSystemManager;
import com.intellij.openapi.externalSystem.model.*;
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo;
import com.intellij.openapi.externalSystem.model.internal.InternalExternalProjectInfo;
import com.intellij.openapi.externalSystem.model.project.ExternalConfigPathAware;
import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo;
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;
@@ -45,7 +43,8 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.intellij.openapi.externalSystem.model.ProjectKeys.*;
import static com.intellij.openapi.externalSystem.model.ProjectKeys.MODULE;
import static com.intellij.openapi.externalSystem.model.ProjectKeys.PROJECT;
/**
* @author Vladislav.Soroka
@@ -273,7 +272,6 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per
AbstractExternalSystemLocalSettings settings = manager.getLocalSettingsProvider().fun(myProject);
final Map<ExternalProjectPojo, Collection<ExternalProjectPojo>> availableProjects = settings.getAvailableProjects();
final Map<String, Collection<ExternalTaskPojo>> availableTasks = settings.getAvailableTasks();
for (Map.Entry<ExternalProjectPojo, Collection<ExternalProjectPojo>> entry : availableProjects.entrySet()) {
final ExternalProjectPojo projectPojo = entry.getKey();
@@ -281,7 +279,7 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per
final Pair<ProjectSystemId, File> key = Pair.create(systemId, new File(externalProjectPath));
InternalExternalProjectInfo externalProjectInfo = myExternalRootProjects.get(key);
if (externalProjectInfo == null) {
final DataNode<ProjectData> dataNode = convert(systemId, projectPojo, entry.getValue(), availableTasks);
final DataNode<ProjectData> dataNode = convert(systemId, projectPojo, entry.getValue());
externalProjectInfo = new InternalExternalProjectInfo(systemId, externalProjectPath, dataNode);
myExternalRootProjects.put(key, externalProjectInfo);
ExternalProjectsManager.getInstance(myProject).getExternalProjectsWatcher().markDirty(externalProjectPath);
@@ -305,8 +303,7 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per
private static DataNode<ProjectData> convert(@NotNull ProjectSystemId systemId,
@NotNull ExternalProjectPojo rootProject,
@NotNull Collection<ExternalProjectPojo> childProjects,
@NotNull Map<String, Collection<ExternalTaskPojo>> availableTasks) {
@NotNull Collection<ExternalProjectPojo> childProjects) {
ProjectData projectData = new ProjectData(systemId, rootProject.getName(), rootProject.getPath(), rootProject.getPath());
DataNode<ProjectData> projectDataNode = new DataNode<>(PROJECT, projectData, null);
@@ -315,17 +312,8 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per
ModuleData moduleData = new ModuleData(childProject.getName(), systemId,
ModuleTypeId.JAVA_MODULE, childProject.getName(),
moduleConfigPath, moduleConfigPath);
final DataNode<ModuleData> moduleDataNode = projectDataNode.createChild(MODULE, moduleData);
final Collection<ExternalTaskPojo> moduleTasks = availableTasks.get(moduleConfigPath);
if (moduleTasks != null) {
for (ExternalTaskPojo moduleTask : moduleTasks) {
TaskData taskData = new TaskData(systemId, moduleTask.getName(), moduleConfigPath, moduleTask.getDescription());
moduleDataNode.createChild(TASK, taskData);
}
}
projectDataNode.createChild(MODULE, moduleData);
}
return projectDataNode;
}
@@ -1,47 +0,0 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.externalSystem.service.task;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.project.ExternalEntityData;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider;
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* @author Denis Zhdanov
* @since 5/15/13 1:32 PM
*/
public abstract class AbstractToolWindowService<T extends ExternalEntityData> extends AbstractProjectDataService<T, Void> {
@Override
public void importData(@NotNull final Collection<DataNode<T>> toImport,
@Nullable ProjectData projectData,
@NotNull final Project project,
@NotNull IdeModifiableModelsProvider modelsProvider) {
if (toImport.isEmpty()) {
return;
}
processData(toImport, project);
}
protected abstract void processData(@NotNull Collection<DataNode<T>> nodes, @NotNull Project project);
}
@@ -1,111 +0,0 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.externalSystem.service.task;
import com.intellij.openapi.externalSystem.ExternalSystemManager;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.Key;
import com.intellij.openapi.externalSystem.model.ProjectKeys;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.Order;
import com.intellij.openapi.project.Project;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* Ensures that all external system sub-projects are correctly represented at the external system tool window.
*
* @author Denis Zhdanov
* @since 5/15/13 1:02 PM
*/
@Order(ExternalSystemConstants.BUILTIN_TOOL_WINDOW_SERVICE_ORDER)
public class ToolWindowModuleService extends AbstractToolWindowService<ModuleData> {
@NotNull
public static final Function<DataNode<ModuleData>, ExternalProjectPojo> MAPPER
= node -> ExternalProjectPojo.from(node.getData());
@NotNull
@Override
public Key<ModuleData> getTargetDataKey() {
return ProjectKeys.MODULE;
}
@Override
protected void processData(@NotNull final Collection<DataNode<ModuleData>> nodes,
@NotNull Project project)
{
if (nodes.isEmpty()) {
return;
}
ProjectSystemId externalSystemId = nodes.iterator().next().getData().getOwner();
ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(externalSystemId);
assert manager != null;
final MultiMap<DataNode<ProjectData>, DataNode<ModuleData>> grouped = ExternalSystemApiUtil.groupBy(nodes, ProjectKeys.PROJECT);
Map<ExternalProjectPojo, Collection<ExternalProjectPojo>> data = ContainerUtilRt.newHashMap();
for (Map.Entry<DataNode<ProjectData>, Collection<DataNode<ModuleData>>> entry : grouped.entrySet()) {
data.put(ExternalProjectPojo.from(entry.getKey().getData()), ContainerUtilRt.map2List(entry.getValue(), MAPPER));
}
AbstractExternalSystemLocalSettings settings = manager.getLocalSettingsProvider().fun(project);
Set<String> pathsToForget = detectRenamedProjects(data, settings.getAvailableProjects());
if (!pathsToForget.isEmpty()) {
settings.forgetExternalProjects(pathsToForget);
}
Map<ExternalProjectPojo,Collection<ExternalProjectPojo>> projects = ContainerUtilRt.newHashMap(settings.getAvailableProjects());
projects.putAll(data);
settings.setAvailableProjects(projects);
}
@NotNull
private static Set<String> detectRenamedProjects(@NotNull Map<ExternalProjectPojo, Collection<ExternalProjectPojo>> currentInfo,
@NotNull Map<ExternalProjectPojo, Collection<ExternalProjectPojo>> oldInfo)
{
Map<String/* external config path */, String/* project name */> map = ContainerUtilRt.newHashMap();
for (Map.Entry<ExternalProjectPojo, Collection<ExternalProjectPojo>> entry : currentInfo.entrySet()) {
map.put(entry.getKey().getPath(), entry.getKey().getName());
for (ExternalProjectPojo pojo : entry.getValue()) {
map.put(pojo.getPath(), pojo.getName());
}
}
Set<String> result = ContainerUtilRt.newHashSet();
for (Map.Entry<ExternalProjectPojo, Collection<ExternalProjectPojo>> entry : oldInfo.entrySet()) {
String newName = map.get(entry.getKey().getPath());
if (newName != null && !newName.equals(entry.getKey().getName())) {
result.add(entry.getKey().getPath());
}
for (ExternalProjectPojo pojo : entry.getValue()) {
newName = map.get(pojo.getPath());
if (newName != null && !newName.equals(pojo.getName())) {
result.add(pojo.getPath());
}
}
}
return result;
}
}
@@ -1,91 +0,0 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.externalSystem.service.task;
import com.intellij.openapi.externalSystem.ExternalSystemManager;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.Key;
import com.intellij.openapi.externalSystem.model.ProjectKeys;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo;
import com.intellij.openapi.externalSystem.model.project.ExternalConfigPathAware;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.task.TaskData;
import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemKeymapExtension;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.Order;
import com.intellij.openapi.project.Project;
import com.intellij.util.Function;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Map;
/**
* @author Denis Zhdanov
* @since 5/15/13 7:21 PM
*/
@Order(ExternalSystemConstants.BUILTIN_TOOL_WINDOW_SERVICE_ORDER)
public class ToolWindowTaskService extends AbstractToolWindowService<TaskData> {
@NotNull
public static final Function<DataNode<TaskData>, ExternalTaskPojo> MAPPER = node -> ExternalTaskPojo.from(node.getData());
public static final NullableFunction<DataNode<TaskData>, ExternalConfigPathAware> TASK_HOLDER_RETRIEVAL_STRATEGY =
node -> {
ModuleData moduleData = node.getData(ProjectKeys.MODULE);
return moduleData == null ? node.getData(ProjectKeys.PROJECT) : moduleData;
};
@NotNull
@Override
public Key<TaskData> getTargetDataKey() {
return ProjectKeys.TASK;
}
@Override
protected void processData(@NotNull Collection<DataNode<TaskData>> nodes,
@NotNull Project project)
{
if (nodes.isEmpty()) {
return;
}
ProjectSystemId externalSystemId = nodes.iterator().next().getData().getOwner();
ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(externalSystemId);
assert manager != null;
ExternalSystemKeymapExtension.updateActions(project, nodes);
MultiMap<ExternalConfigPathAware, DataNode<TaskData>> grouped = ContainerUtil.groupBy(nodes, TASK_HOLDER_RETRIEVAL_STRATEGY);
Map<String, Collection<ExternalTaskPojo>> data = ContainerUtilRt.newHashMap();
for (Map.Entry<ExternalConfigPathAware, Collection<DataNode<TaskData>>> entry : grouped.entrySet()) {
data.put(entry.getKey().getLinkedExternalProjectPath(), ContainerUtilRt.map2List(entry.getValue(), MAPPER));
}
AbstractExternalSystemLocalSettings settings = manager.getLocalSettingsProvider().fun(project);
Map<String, Collection<ExternalTaskPojo>> availableTasks = ContainerUtilRt.newHashMap(settings.getAvailableTasks());
availableTasks.putAll(data);
settings.setAvailableTasks(availableTasks);
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package com.intellij.openapi.externalSystem.service.project
import com.intellij.openapi.externalSystem.test.AbstractExternalSystemTest
class ExternalSystemSettingsTest extends AbstractExternalSystemTest {
void 'test available tasks are not skipped for multi-module external project'() {
setupExternalProject {
project {
module('module1', externalConfigPath: 'root/module1') {
task('module1-task') }
module('module2', externalConfigPath: 'root/module2') {
task('module2-task') } } }
def settings = externalSystemManager.localSettings
assertEquals(2, settings.availableTasks.size())
settings.loadState(settings.getState())
// There was a problem that all sub-projects (module-level) tasks were removed on project open.
assertEquals(2, settings.availableTasks.size())
}
}
@@ -58,8 +58,6 @@
implementation="com.intellij.openapi.externalSystem.service.project.manage.ExternalModuleStructureExtension"/>
<!--Tool window services-->
<externalProjectDataService implementation="com.intellij.openapi.externalSystem.service.task.ToolWindowModuleService"/>
<externalProjectDataService implementation="com.intellij.openapi.externalSystem.service.task.ToolWindowTaskService"/>
<externalSystemViewContributor id="default" order="last"
implementation="com.intellij.openapi.externalSystem.view.ExternalSystemViewDefaultContributor"/>
@@ -123,10 +123,10 @@ public class GradleManager
// The workaround extensionsFilter should be removed when the IntelliJ java subsystem will become a regular plugin
// or those plugins will be fixed using the optional plugin dependency on 'org.jetbrains.plugins.gradle.java'
boolean isJavaIde = ExternalSystemApiUtil.isJavaCompatibleIde();
if(!isJavaIde) {
if (!isJavaIde) {
ExtensionPoint<GradleProjectResolverExtension> point =
Extensions.getRootArea().getExtensionPoint(GradleProjectResolverExtension.EP_NAME);
if(point instanceof ExtensionPointImpl) {
if (point instanceof ExtensionPointImpl) {
((ExtensionPointImpl<GradleProjectResolverExtension>)point).removeUnloadableExtensions();
}
}
@@ -141,8 +141,8 @@ public class GradleManager
isJavaIde || !javaIdeDependentExtensions.contains(ext.getClass().getName());
Arrays.stream(GradleProjectResolverExtension.EP_NAME.getExtensions())
.filter(extensionsFilter)
.forEach(result::add);
.filter(extensionsFilter)
.forEach(result::add);
ExternalSystemApiUtil.orderAwareSort(result);
return result;
@@ -451,7 +451,6 @@ public class GradleManager
GradleLocalSettings localSettings = GradleLocalSettings.getInstance(project);
patchRecentTasks(adjustedPaths, localSettings);
patchAvailableProjects(adjustedPaths, localSettings);
patchAvailableTasks(adjustedPaths, localSettings);
}
@Nullable
@@ -484,26 +483,6 @@ public class GradleManager
return adjustedPaths;
}
private static void patchAvailableTasks(@NotNull Map<String, String> adjustedPaths, @NotNull GradleLocalSettings localSettings) {
Map<String, Collection<ExternalTaskPojo>> adjustedAvailableTasks = ContainerUtilRt.newHashMap();
for (Map.Entry<String, Collection<ExternalTaskPojo>> entry : localSettings.getAvailableTasks().entrySet()) {
String newPath = adjustedPaths.get(entry.getKey());
if (newPath == null) {
adjustedAvailableTasks.put(entry.getKey(), entry.getValue());
}
else {
for (ExternalTaskPojo task : entry.getValue()) {
String newTaskPath = adjustedPaths.get(task.getLinkedExternalProjectPath());
if (newTaskPath != null) {
task.setLinkedExternalProjectPath(newTaskPath);
}
}
adjustedAvailableTasks.put(newPath, entry.getValue());
}
}
localSettings.setAvailableTasks(adjustedAvailableTasks);
}
private static void patchAvailableProjects(@NotNull Map<String, String> adjustedPaths, @NotNull GradleLocalSettings localSettings) {
Map<ExternalProjectPojo, Collection<ExternalProjectPojo>> adjustedAvailableProjects = ContainerUtilRt.newHashMap();
for (Map.Entry<ExternalProjectPojo, Collection<ExternalProjectPojo>> entry : localSettings.getAvailableProjects().entrySet()) {