mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-109437 Cannot set Gradle home in Cardea
1. Provide ability to setup generic external system settings listener for particular external system topic; 2. Refresh linked gradle projects automatically on gradle service directory change;
This commit is contained in:
+20
@@ -43,6 +43,26 @@ public abstract class AbstractExternalSystemSettings<S extends ExternalProjectSe
|
||||
myChangesTopic = topic;
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Every time particular external system setting is changed corresponding message is sent via ide
|
||||
* <a href="http://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+Messaging+infrastructure">messaging sub-system</a>.
|
||||
* The problem is that every external system implementation defines it's own topic/listener pair. Listener interface is derived
|
||||
* from the common {@link ExternalSystemSettingsListener} interface and is specific to external sub-system implementation.
|
||||
* However, it's possible that a client wants to perform particular actions based only on {@link ExternalSystemSettingsListener}
|
||||
* facilities. There is no way for such external system-agnostic client to create external system-specific listener
|
||||
* implementation then.
|
||||
* <p/>
|
||||
* That's why this method allows to wrap given 'generic listener' into external system-specific one.
|
||||
*
|
||||
* @param listener target generic listener to wrap to external system-specific implementation
|
||||
*/
|
||||
public abstract void subscribe(@NotNull ExternalSystemSettingsListener<S> listener);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@NotNull
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.settings;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 6/24/13 6:23 PM
|
||||
*/
|
||||
public class DelegatingExternalSystemSettingsListener<S extends ExternalProjectSettings> implements ExternalSystemSettingsListener<S> {
|
||||
|
||||
@NotNull private final ExternalSystemSettingsListener<S> myDelegate;
|
||||
|
||||
public DelegatingExternalSystemSettingsListener(@NotNull ExternalSystemSettingsListener<S> delegate) {
|
||||
myDelegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProjectsLinked(@NotNull Collection<S> settings) {
|
||||
myDelegate.onProjectsLinked(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProjectsUnlinked(@NotNull Set<String> linkedProjectPaths) {
|
||||
myDelegate.onProjectsUnlinked(linkedProjectPaths);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUseAutoImportChange(boolean currentValue, @NotNull String linkedProjectPath) {
|
||||
myDelegate.onUseAutoImportChange(currentValue, linkedProjectPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBulkChangeStart() {
|
||||
myDelegate.onBulkChangeStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBulkChangeEnd() {
|
||||
myDelegate.onBulkChangeEnd();
|
||||
}
|
||||
}
|
||||
+26
-11
@@ -27,6 +27,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -181,12 +182,21 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
|
||||
}
|
||||
|
||||
public void syncPaths(@NotNull final LibraryData externalLibrary, @NotNull final Library ideLibrary, boolean synchronous) {
|
||||
final Set<String> toRemove = ContainerUtilRt.newHashSet();
|
||||
final Set<String> toAdd = ContainerUtilRt.newHashSet(externalLibrary.getPaths(LibraryPathType.BINARY));
|
||||
for (VirtualFile ideFile : ideLibrary.getFiles(OrderRootType.CLASSES)) {
|
||||
String idePath = ExternalSystemApiUtil.getLocalFileSystemPath(ideFile);
|
||||
if (!toAdd.remove(idePath)) {
|
||||
toRemove.add(idePath);
|
||||
final Map<OrderRootType, Set<String>> toRemove = ContainerUtilRt.newHashMap();
|
||||
final Map<OrderRootType, Set<String>> toAdd = ContainerUtilRt.newHashMap();
|
||||
for (LibraryPathType pathType : LibraryPathType.values()) {
|
||||
OrderRootType ideType = myLibraryPathTypeMapper.map(pathType);
|
||||
HashSet<String> toAddPerType = ContainerUtilRt.newHashSet(externalLibrary.getPaths(pathType));
|
||||
toAdd.put(ideType, toAddPerType);
|
||||
|
||||
HashSet<String> toRemovePerType = ContainerUtilRt.newHashSet();
|
||||
toRemove.put(ideType, toRemovePerType);
|
||||
|
||||
for (VirtualFile ideFile : ideLibrary.getFiles(ideType)) {
|
||||
String idePath = ExternalSystemApiUtil.getLocalFileSystemPath(ideFile);
|
||||
if (!toAddPerType.remove(idePath)) {
|
||||
toRemovePerType.add(ideFile.getUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toRemove.isEmpty() && toAdd.isEmpty()) {
|
||||
@@ -197,12 +207,17 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
|
||||
public void run() {
|
||||
Library.ModifiableModel model = ideLibrary.getModifiableModel();
|
||||
try {
|
||||
for (String path : toRemove) {
|
||||
model.removeRoot(path, OrderRootType.CLASSES);
|
||||
for (Map.Entry<OrderRootType, Set<String>> entry : toRemove.entrySet()) {
|
||||
for (String path : entry.getValue()) {
|
||||
model.removeRoot(path, entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<OrderRootType, Set<String>> entry : toAdd.entrySet()) {
|
||||
Map<OrderRootType, Collection<File>> roots = ContainerUtilRt.newHashMap();
|
||||
roots.put(entry.getKey(), ContainerUtil.map(entry.getValue(), PATH_TO_FILE));
|
||||
registerPaths(roots, model, externalLibrary.getName());
|
||||
}
|
||||
Map<OrderRootType, Collection<File>> roots = ContainerUtilRt.newHashMap();
|
||||
roots.put(OrderRootType.CLASSES, ContainerUtil.map(toAdd, PATH_TO_FILE));
|
||||
registerPaths(roots, model, externalLibrary.getName());
|
||||
}
|
||||
finally {
|
||||
model.commit();
|
||||
|
||||
+2
-1
@@ -26,10 +26,11 @@ import java.util.Set;
|
||||
*/
|
||||
public class ExternalToolWindowManager {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void handle(@NotNull final Project project) {
|
||||
for (final ExternalSystemManager<?, ?, ?, ?, ?> manager : ExternalSystemApiUtil.getAllManagers()) {
|
||||
final AbstractExternalSystemSettings settings = manager.getSettingsProvider().fun(project);
|
||||
project.getMessageBus().connect(project).subscribe(settings.getChangesTopic(), new ExternalSystemSettingsListenerAdapter() {
|
||||
settings.subscribe(new ExternalSystemSettingsListenerAdapter() {
|
||||
@Override
|
||||
public void onProjectsLinked(@NotNull Collection linked) {
|
||||
if (settings.getLinkedProjectsSettings().size() != 1) {
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.intellij.openapi.externalSystem.service.project.autoimport.CachingExt
|
||||
import com.intellij.openapi.externalSystem.service.ui.DefaultExternalSystemUiAware;
|
||||
import com.intellij.openapi.externalSystem.task.ExternalSystemTaskManager;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.module.EmptyModuleType;
|
||||
import com.intellij.openapi.module.JavaModuleType;
|
||||
@@ -50,10 +51,12 @@ import com.intellij.util.Function;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.PathsList;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import icons.GradleIcons;
|
||||
import org.gradle.tooling.ProjectConnection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleJavaHelper;
|
||||
import org.jetbrains.plugins.gradle.remote.impl.GradleTaskManager;
|
||||
import org.jetbrains.plugins.gradle.service.GradleInstallationManager;
|
||||
@@ -279,11 +282,33 @@ implements ExternalSystemConfigurableAware, ExternalSystemUiAware, ExternalSyste
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runActivity(Project project) {
|
||||
public void runActivity(final Project project) {
|
||||
// We want to automatically refresh linked projects on gradle service directory change.
|
||||
MessageBusConnection connection = project.getMessageBus().connect(project);
|
||||
connection.subscribe(GradleSettings.getInstance(project).getChangesTopic(), new GradleSettingsListenerAdapter() {
|
||||
@Override
|
||||
public void onServiceDirectoryPathChange(@Nullable String oldPath, @Nullable String newPath) {
|
||||
ExternalSystemUtil.refreshProjects(project, GradleConstants.SYSTEM_ID, true);
|
||||
}
|
||||
});
|
||||
|
||||
// We used to assume that gradle scripts are always named 'build.gradle' and kept path to that build.gradle file at ide settings.
|
||||
// However, it was found out that that is incorrect assumption (IDEA-109064). Now we keep paths to gradle script's directories
|
||||
// However, it was found out that that is incorrect assumption (IDEA-109064). Now we keep paths to gradle script's directories
|
||||
// instead. However, we don't want to force old users to re-import gradle projects because of that. That's why we check gradle
|
||||
// config and re-point it from build.gradle to the parent dir if necessary.
|
||||
Map<String, String> adjustedPaths = patchLinkedProjects(project);
|
||||
if (adjustedPaths == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GradleLocalSettings localSettings = GradleLocalSettings.getInstance(project);
|
||||
patchRecentTasks(adjustedPaths, localSettings);
|
||||
patchAvailableProjects(adjustedPaths, localSettings);
|
||||
patchAvailableTasks(adjustedPaths, localSettings);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Map<String, String> patchLinkedProjects(@NotNull Project project) {
|
||||
GradleSettings settings = GradleSettings.getInstance(project);
|
||||
Collection<GradleProjectSettings> correctedSettings = ContainerUtilRt.newArrayList();
|
||||
Map<String/* old path */, String/* new path */> adjustedPaths = ContainerUtilRt.newHashMap();
|
||||
@@ -305,35 +330,14 @@ implements ExternalSystemConfigurableAware, ExternalSystemUiAware, ExternalSyste
|
||||
correctedSettings.add(projectSettings);
|
||||
}
|
||||
if (adjustedPaths.isEmpty()) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
settings.setLinkedProjectsSettings(correctedSettings);
|
||||
|
||||
GradleLocalSettings localSettings = GradleLocalSettings.getInstance(project);
|
||||
// Recent tasks.
|
||||
for (ExternalTaskExecutionInfo taskInfo : localSettings.getRecentTasks()) {
|
||||
ExternalSystemTaskExecutionSettings s = taskInfo.getSettings();
|
||||
String newPath = adjustedPaths.get(s.getExternalProjectPath());
|
||||
if (newPath != null) {
|
||||
s.setExternalProjectPath(newPath);
|
||||
}
|
||||
}
|
||||
|
||||
// Available projects.
|
||||
Map<ExternalProjectPojo, Collection<ExternalProjectPojo>> adjustedAvailableProjects = ContainerUtilRt.newHashMap();
|
||||
for (Map.Entry<ExternalProjectPojo, Collection<ExternalProjectPojo>> entry : localSettings.getAvailableProjects().entrySet()) {
|
||||
String newPath = adjustedPaths.get(entry.getKey().getPath());
|
||||
if (newPath == null) {
|
||||
adjustedAvailableProjects.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
else {
|
||||
adjustedAvailableProjects.put(new ExternalProjectPojo(entry.getKey().getName(), newPath), entry.getValue());
|
||||
}
|
||||
}
|
||||
localSettings.setAvailableProjects(adjustedAvailableProjects);
|
||||
|
||||
// Available tasks.
|
||||
settings.setLinkedProjectsSettings(correctedSettings);
|
||||
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());
|
||||
@@ -352,4 +356,28 @@ implements ExternalSystemConfigurableAware, ExternalSystemUiAware, ExternalSyste
|
||||
}
|
||||
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()) {
|
||||
String newPath = adjustedPaths.get(entry.getKey().getPath());
|
||||
if (newPath == null) {
|
||||
adjustedAvailableProjects.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
else {
|
||||
adjustedAvailableProjects.put(new ExternalProjectPojo(entry.getKey().getName(), newPath), entry.getValue());
|
||||
}
|
||||
}
|
||||
localSettings.setAvailableProjects(adjustedAvailableProjects);
|
||||
}
|
||||
|
||||
private static void patchRecentTasks(@NotNull Map<String, String> adjustedPaths, @NotNull GradleLocalSettings localSettings) {
|
||||
for (ExternalTaskExecutionInfo taskInfo : localSettings.getRecentTasks()) {
|
||||
ExternalSystemTaskExecutionSettings s = taskInfo.getSettings();
|
||||
String newPath = adjustedPaths.get(s.getExternalProjectPath());
|
||||
if (newPath != null) {
|
||||
s.setExternalProjectPath(newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 org.jetbrains.plugins.gradle.config;
|
||||
|
||||
import com.intellij.openapi.externalSystem.settings.DelegatingExternalSystemSettingsListener;
|
||||
import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettingsListener;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 6/24/13 6:35 PM
|
||||
*/
|
||||
public class DelegatingGradleSettingsListenerAdapter extends DelegatingExternalSystemSettingsListener<GradleProjectSettings>
|
||||
implements GradleSettingsListener
|
||||
{
|
||||
|
||||
public DelegatingGradleSettingsListenerAdapter(@NotNull ExternalSystemSettingsListener<GradleProjectSettings> delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGradleHomeChange(@Nullable String oldPath, @Nullable String newPath, @NotNull String linkedProjectPath) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreferLocalGradleDistributionToWrapperChange(boolean currentValue, @NotNull String linkedProjectPath) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDirectoryPathChange(@Nullable String oldPath, @Nullable String newPath) {
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,14 @@ package org.jetbrains.plugins.gradle.settings;
|
||||
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
|
||||
import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListener;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.xmlb.annotations.AbstractCollection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.config.DelegatingGradleSettingsListenerAdapter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@@ -53,6 +55,13 @@ public class GradleSettings extends AbstractExternalSystemSettings<GradleProject
|
||||
return ServiceManager.getService(project, GradleSettings.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(@NotNull ExternalSystemSettingsListener<GradleProjectSettings> listener) {
|
||||
getProject().getMessageBus().connect(getProject()).subscribe(GradleSettingsListener.TOPIC,
|
||||
new DelegatingGradleSettingsListenerAdapter(listener));
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -80,10 +89,11 @@ public class GradleSettings extends AbstractExternalSystemSettings<GradleProject
|
||||
return myServiceDirectoryPath;
|
||||
}
|
||||
|
||||
public void setServiceDirectoryPath(@Nullable String path) {
|
||||
if (!Comparing.equal(myServiceDirectoryPath, path)) {
|
||||
final String oldPath = myServiceDirectoryPath;
|
||||
getPublisher().onServiceDirectoryPathChange(oldPath, path);
|
||||
public void setServiceDirectoryPath(@Nullable String newPath) {
|
||||
if (!Comparing.equal(myServiceDirectoryPath, newPath)) {
|
||||
String oldPath = myServiceDirectoryPath;
|
||||
myServiceDirectoryPath = newPath;
|
||||
getPublisher().onServiceDirectoryPathChange(oldPath, newPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user