mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
gradle: composite builds defined in gradle scripts support (IDEA-162664)
This commit is contained in:
+6
@@ -16,6 +16,7 @@
|
||||
package com.intellij.openapi.externalSystem;
|
||||
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -30,6 +31,11 @@ public interface ExternalSystemUiAware {
|
||||
@NotNull
|
||||
String getProjectRepresentationName(@NotNull String targetProjectPath, @Nullable String rootProjectPath);
|
||||
|
||||
@NotNull
|
||||
default String getProjectRepresentationName(@NotNull Project project, @NotNull String targetProjectPath, @Nullable String rootProjectPath){
|
||||
return getProjectRepresentationName(targetProjectPath, rootProjectPath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
FileChooserDescriptor getExternalProjectConfigDescriptor();
|
||||
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ public abstract class ExternalProjectSettings implements Comparable<ExternalProj
|
||||
|
||||
protected void copyTo(@NotNull ExternalProjectSettings receiver) {
|
||||
receiver.myExternalProjectPath = myExternalProjectPath;
|
||||
receiver.myModules = new HashSet<>(myModules);
|
||||
receiver.myModules = myModules != null ? new HashSet<>(myModules) : new HashSet<>();
|
||||
receiver.myUseAutoImport = myUseAutoImport;
|
||||
receiver.myCreateEmptyContentRootDirectories = myCreateEmptyContentRootDirectories;
|
||||
}
|
||||
|
||||
+3
-1
@@ -12,6 +12,7 @@ import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo;
|
||||
import com.intellij.openapi.externalSystem.service.ui.DefaultExternalSystemUiAware;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
@@ -145,7 +146,8 @@ public abstract class AbstractExternalSystemTaskConfigurationType implements Con
|
||||
projectName = null;
|
||||
}
|
||||
else {
|
||||
projectName = ExternalSystemApiUtil.getProjectRepresentationName(externalProjectPath, rootProjectPath);
|
||||
final ExternalSystemUiAware uiAware = ExternalSystemUiUtil.getUiAware(externalSystemId);
|
||||
projectName = uiAware.getProjectRepresentationName(project, externalProjectPath, rootProjectPath);
|
||||
}
|
||||
if (!StringUtil.isEmptyOrSpaces(projectName)) {
|
||||
buffer.append(projectName);
|
||||
|
||||
+2
-2
@@ -219,12 +219,12 @@ public class ExternalProjectPathField extends ComponentWithBrowseButton<External
|
||||
String rawText = editor.getDocument().getText();
|
||||
for (Map.Entry<ExternalProjectPojo, Collection<ExternalProjectPojo>> entry : settings.getAvailableProjects().entrySet()) {
|
||||
if (entry.getKey().getPath().equals(rawText)) {
|
||||
collapse(editor, uiAware.getProjectRepresentationName(entry.getKey().getPath(), null));
|
||||
collapse(editor, uiAware.getProjectRepresentationName(project, entry.getKey().getPath(), null));
|
||||
return;
|
||||
}
|
||||
for (ExternalProjectPojo pojo : entry.getValue()) {
|
||||
if (pojo.getPath().equals(rawText)) {
|
||||
collapse(editor, uiAware.getProjectRepresentationName(pojo.getPath(), entry.getKey().getPath()));
|
||||
collapse(editor, uiAware.getProjectRepresentationName(project, pojo.getPath(), entry.getKey().getPath()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
<externalSystemConfigLocator implementation="org.jetbrains.plugins.gradle.service.settings.GradleConfigLocator"/>
|
||||
<externalSystemManager implementation="org.jetbrains.plugins.gradle.GradleManager"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.GradleSourceSetDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.CompositeBuildDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.BuildClasspathModuleGradleDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.GradleExtensionsDataService"/>
|
||||
<externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataService"/>
|
||||
|
||||
@@ -58,6 +58,7 @@ import icons.GradleIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter;
|
||||
import org.jetbrains.plugins.gradle.model.data.BuildParticipant;
|
||||
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData;
|
||||
import org.jetbrains.plugins.gradle.service.GradleInstallationManager;
|
||||
import org.jetbrains.plugins.gradle.service.project.GradleAutoImportAware;
|
||||
@@ -75,6 +76,8 @@ import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.openapi.util.io.FileUtil.pathsEqual;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 4/10/13 1:19 PM
|
||||
@@ -180,7 +183,7 @@ public class GradleManager
|
||||
result.setResolveModulePerSourceSet(projectLevelSettings.isResolveModulePerSourceSet());
|
||||
}
|
||||
|
||||
configureExecutionWorkspace(projectLevelSettings, settings, result, project);
|
||||
configureExecutionWorkspace(projectLevelSettings, settings, result, project, pair.second);
|
||||
return result;
|
||||
};
|
||||
}
|
||||
@@ -191,12 +194,31 @@ public class GradleManager
|
||||
private static void configureExecutionWorkspace(@Nullable GradleProjectSettings compositeRootSettings,
|
||||
GradleSettings settings,
|
||||
GradleExecutionSettings result,
|
||||
Project project) {
|
||||
if(compositeRootSettings == null) return;
|
||||
Project project,
|
||||
String projectPath) {
|
||||
if (compositeRootSettings == null || compositeRootSettings.getCompositeBuild() == null) return;
|
||||
|
||||
GradleProjectSettings.CompositeBuild compositeBuild = compositeRootSettings.getCompositeBuild();
|
||||
if (compositeBuild.getCompositeDefinitionSource() == CompositeDefinitionSource.SCRIPT) {
|
||||
if (pathsEqual(compositeRootSettings.getExternalProjectPath(), projectPath)) return;
|
||||
|
||||
for (BuildParticipant buildParticipant : compositeBuild.getCompositeParticipants()) {
|
||||
if (pathsEqual(buildParticipant.getRootPath(), projectPath)) continue;
|
||||
if (buildParticipant.getProjects().stream().anyMatch(path -> pathsEqual(path, projectPath))) {
|
||||
continue;
|
||||
}
|
||||
result.getExecutionWorkspace().addBuildParticipant(new GradleBuildParticipant(buildParticipant.getRootPath()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (GradleProjectSettings projectSettings : settings.getLinkedProjectsSettings()) {
|
||||
if (projectSettings == compositeRootSettings) continue;
|
||||
if (!compositeRootSettings.getCompositeParticipants().contains(projectSettings.getExternalProjectPath())) continue;
|
||||
if (compositeBuild.getCompositeParticipants()
|
||||
.stream()
|
||||
.noneMatch(participant -> pathsEqual(participant.getRootPath(), projectSettings.getExternalProjectPath()))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GradleBuildParticipant buildParticipant = new GradleBuildParticipant(projectSettings.getExternalProjectPath());
|
||||
ExternalProjectInfo projectData = ProjectDataManager.getInstance()
|
||||
@@ -287,6 +309,22 @@ public class GradleManager
|
||||
return ExternalSystemApiUtil.getProjectRepresentationName(targetProjectPath, rootProjectPath);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getProjectRepresentationName(@NotNull Project project,
|
||||
@NotNull String targetProjectPath,
|
||||
@Nullable String rootProjectPath) {
|
||||
GradleProjectSettings projectSettings = GradleSettings.getInstance(project).getLinkedProjectSettings(targetProjectPath);
|
||||
if (projectSettings != null && projectSettings.getCompositeBuild() != null) {
|
||||
for (BuildParticipant buildParticipant : projectSettings.getCompositeBuild().getCompositeParticipants()) {
|
||||
if (buildParticipant.getProjects().contains(targetProjectPath)) {
|
||||
return ExternalSystemApiUtil.getProjectRepresentationName(targetProjectPath, buildParticipant.getRootPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ExternalSystemApiUtil.getProjectRepresentationName(targetProjectPath, rootProjectPath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getAffectedExternalProjectPath(@NotNull String changedFileOrDirPath, @NotNull Project project) {
|
||||
|
||||
+15
-1
@@ -20,6 +20,8 @@ import com.intellij.openapi.externalSystem.action.ExternalSystemAction;
|
||||
import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
|
||||
import com.intellij.openapi.externalSystem.view.ProjectNode;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.plugins.gradle.settings.CompositeDefinitionSource;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings;
|
||||
import org.jetbrains.plugins.gradle.ui.GradleProjectCompositeSelectorDialog;
|
||||
|
||||
@@ -41,7 +43,19 @@ public class GradleOpenProjectCompositeConfigurationAction extends ExternalSyste
|
||||
protected boolean isVisible(AnActionEvent e) {
|
||||
final Project project = getProject(e);
|
||||
if (project == null) return false;
|
||||
return GradleSettings.getInstance(project).getLinkedProjectsSettings().size() > 1;
|
||||
if (GradleSettings.getInstance(project).getLinkedProjectsSettings().size() > 1) {
|
||||
final ProjectNode projectNode = ExternalSystemDataKeys.SELECTED_PROJECT_NODE.getData(e.getDataContext());
|
||||
if (projectNode == null || projectNode.getData() == null) return false;
|
||||
|
||||
GradleProjectSettings projectSettings =
|
||||
GradleSettings.getInstance(project).getLinkedProjectSettings(projectNode.getData().getLinkedExternalProjectPath());
|
||||
GradleProjectSettings.CompositeBuild compositeBuild = null;
|
||||
if (projectSettings != null) {
|
||||
compositeBuild = projectSettings.getCompositeBuild();
|
||||
}
|
||||
if (compositeBuild == null || compositeBuild.getCompositeDefinitionSource() == CompositeDefinitionSource.IDE) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.model.data;
|
||||
|
||||
import com.intellij.util.xmlb.annotations.AbstractCollection;
|
||||
import com.intellij.util.xmlb.annotations.Attribute;
|
||||
import com.intellij.util.xmlb.annotations.OptionTag;
|
||||
import com.intellij.util.xmlb.annotations.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
* @since 2/18/2017
|
||||
*/
|
||||
@Tag("build")
|
||||
public class BuildParticipant implements Serializable {
|
||||
private String myRootPath;
|
||||
@NotNull private Set<String> myProjects = new HashSet<>();
|
||||
|
||||
@Attribute("path")
|
||||
public String getRootPath() {
|
||||
return myRootPath;
|
||||
}
|
||||
|
||||
public void setRootPath(String rootPath) {
|
||||
myRootPath = rootPath;
|
||||
}
|
||||
|
||||
@AbstractCollection(surroundWithTag = false, elementTag = "project", elementValueAttribute = "path")
|
||||
@OptionTag(tag = "projects", nameAttribute = "")
|
||||
@NotNull
|
||||
public Set<String> getProjects() {
|
||||
return myProjects;
|
||||
}
|
||||
|
||||
public void setProjects(@NotNull Set<String> projects) {
|
||||
myProjects = projects;
|
||||
}
|
||||
|
||||
public BuildParticipant copy() {
|
||||
BuildParticipant result = new BuildParticipant();
|
||||
result.myRootPath = myRootPath;
|
||||
result.myProjects = new HashSet<>(myProjects);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.model.data;
|
||||
|
||||
import com.intellij.openapi.externalSystem.model.Key;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
* @since 2/17/2017
|
||||
*/
|
||||
public class CompositeBuildData {
|
||||
|
||||
@NotNull
|
||||
public static final Key<CompositeBuildData> KEY = Key.create(CompositeBuildData.class, ProjectKeys.PROJECT.getProcessingWeight() + 1);
|
||||
|
||||
private final String myRootProjectPath;
|
||||
@NotNull private List<BuildParticipant> myCompositeParticipants = ContainerUtil.newArrayList();
|
||||
|
||||
public CompositeBuildData(String rootProjectPath) {
|
||||
myRootProjectPath = rootProjectPath;
|
||||
}
|
||||
|
||||
public String getRootProjectPath() {
|
||||
return myRootProjectPath;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<BuildParticipant> getCompositeParticipants() {
|
||||
return myCompositeParticipants;
|
||||
}
|
||||
}
|
||||
+12
-1
@@ -76,6 +76,7 @@ import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
import org.slf4j.impl.Log4jLoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
@@ -539,7 +540,17 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
|
||||
final String moduleConfigPath = ideModule.getData().getLinkedExternalProjectPath();
|
||||
|
||||
ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class);
|
||||
final String rootProjectPath = ideProject.getData().getLinkedExternalProjectPath();
|
||||
String rootProjectPath = ideProject.getData().getLinkedExternalProjectPath();
|
||||
try {
|
||||
GradleBuild build = resolverCtx.getExtraProject(gradleModule, GradleBuild.class);
|
||||
if (build != null) {
|
||||
rootProjectPath = ExternalSystemApiUtil.toCanonicalPath(build.getRootProject().getProjectDirectory().getCanonicalPath());
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn("construction of the canonical path for the module fails", e);
|
||||
}
|
||||
|
||||
final boolean isFlatProject = !FileUtil.isAncestor(rootProjectPath, moduleConfigPath, false);
|
||||
if (externalProject != null) {
|
||||
for (ExternalTask task : externalProject.getTasks().values()) {
|
||||
|
||||
+81
-13
@@ -43,6 +43,7 @@ import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.gradle.tooling.*;
|
||||
import org.gradle.tooling.model.DomainObjectSet;
|
||||
import org.gradle.tooling.model.GradleProject;
|
||||
import org.gradle.tooling.model.build.BuildEnvironment;
|
||||
import org.gradle.tooling.model.gradle.GradleBuild;
|
||||
import org.gradle.tooling.model.idea.BasicIdeaProject;
|
||||
@@ -52,6 +53,8 @@ import org.gradle.util.GradleVersion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.model.*;
|
||||
import org.jetbrains.plugins.gradle.model.data.BuildParticipant;
|
||||
import org.jetbrains.plugins.gradle.model.data.CompositeBuildData;
|
||||
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData;
|
||||
import org.jetbrains.plugins.gradle.remote.impl.GradleLibraryNamesMixer;
|
||||
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper;
|
||||
@@ -62,6 +65,7 @@ import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil.attachGradleSdkSources;
|
||||
@@ -160,7 +164,18 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
boolean isBuildSrcProject)
|
||||
throws IllegalArgumentException, IllegalStateException {
|
||||
|
||||
final ProjectImportAction projectImportAction = new ProjectImportAction(resolverCtx.isPreviewMode());
|
||||
final BuildEnvironment buildEnvironment = GradleExecutionHelper.getBuildEnvironment(resolverCtx.getConnection());
|
||||
GradleVersion gradleVersion = null;
|
||||
|
||||
boolean isGradleProjectDirSupported = false;
|
||||
boolean isCompositeBuildsSupported = false;
|
||||
if (buildEnvironment != null) {
|
||||
gradleVersion = GradleVersion.version(buildEnvironment.getGradle().getGradleVersion());
|
||||
isGradleProjectDirSupported = gradleVersion.compareTo(GradleVersion.version("2.4")) >= 0;
|
||||
isCompositeBuildsSupported = isGradleProjectDirSupported && gradleVersion.compareTo(GradleVersion.version("3.1")) >= 0;
|
||||
}
|
||||
final ProjectImportAction projectImportAction =
|
||||
new ProjectImportAction(resolverCtx.isPreviewMode(), isGradleProjectDirSupported, isCompositeBuildsSupported);
|
||||
|
||||
final List<Pair<String, String>> extraJvmArgs = new ArrayList<>();
|
||||
final List<String> commandLineArgs = ContainerUtil.newArrayList();
|
||||
@@ -212,12 +227,6 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
parametersList.addProperty(jvmArg.first, jvmArg.second);
|
||||
}
|
||||
|
||||
final BuildEnvironment buildEnvironment = GradleExecutionHelper.getBuildEnvironment(resolverCtx.getConnection());
|
||||
GradleVersion gradleVersion = null;
|
||||
if (buildEnvironment != null) {
|
||||
gradleVersion = GradleVersion.version(buildEnvironment.getGradle().getGradleVersion());
|
||||
}
|
||||
|
||||
BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = resolverCtx.getConnection().action(projectImportAction);
|
||||
|
||||
File initScript = GradleExecutionHelper.generateInitScript(isBuildSrcProject, toolingExtensionClasses);
|
||||
@@ -299,6 +308,8 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
throw new IllegalStateException("No modules found for the target project: " + ideaProject);
|
||||
}
|
||||
|
||||
List<IdeaModule> gradleModulesWithIncludedBuilds = exposeCompositeBuild(allModels, projectDataNode, gradleModules);
|
||||
|
||||
final Map<String /* module id */, Pair<DataNode<ModuleData>, IdeaModule>> moduleMap = ContainerUtilRt.newHashMap();
|
||||
final Map<String /* module id */, Pair<DataNode<GradleSourceSetData>, ExternalSourceSet>> sourceSetsMap = ContainerUtil.newHashMap();
|
||||
projectDataNode.putUserData(RESOLVED_SOURCE_SETS, sourceSetsMap);
|
||||
@@ -311,7 +322,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
projectDataNode.putUserData(CONFIGURATION_ARTIFACTS, artifactsMap);
|
||||
|
||||
// import modules data
|
||||
for (IdeaModule gradleModule : gradleModules) {
|
||||
for (IdeaModule gradleModule : gradleModulesWithIncludedBuilds) {
|
||||
if (gradleModule == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -331,6 +342,8 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
moduleMap.put(mainModuleId, Pair.create(moduleDataNode, gradleModule));
|
||||
}
|
||||
|
||||
executionSettings.getExecutionWorkspace().addModuleMap(moduleMap);
|
||||
|
||||
File gradleHomeDir = null;
|
||||
// populate modules nodes
|
||||
for (final Pair<DataNode<ModuleData>, IdeaModule> pair : moduleMap.values()) {
|
||||
@@ -401,6 +414,52 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
return projectDataNode;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<IdeaModule> exposeCompositeBuild(ProjectImportAction.AllModels allModels,
|
||||
DataNode<ProjectData> projectDataNode,
|
||||
DomainObjectSet<? extends IdeaModule> gradleModules) {
|
||||
List<IdeaModule> gradleModulesWithIncludedBuilds = ContainerUtil.newArrayList(gradleModules.getAll());
|
||||
List<IdeaProject> includedBuilds = allModels.getIncludedBuilds();
|
||||
if (!includedBuilds.isEmpty()) {
|
||||
ProjectData projectData = projectDataNode.getData();
|
||||
CompositeBuildData compositeBuildData = new CompositeBuildData(projectData.getLinkedExternalProjectPath());
|
||||
for (IdeaProject project : includedBuilds) {
|
||||
if (!project.getModules().isEmpty()) {
|
||||
BuildParticipant buildParticipant = new BuildParticipant();
|
||||
gradleModulesWithIncludedBuilds.addAll(project.getModules());
|
||||
GradleProject gradleProject = project.getModules().getAt(0).getGradleProject();
|
||||
String projectPath = null;
|
||||
do {
|
||||
try {
|
||||
projectPath = ExternalSystemApiUtil.toCanonicalPath(gradleProject.getProjectDirectory().getCanonicalPath());
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn("construction of the canonical path for the module fails", e);
|
||||
}
|
||||
}
|
||||
while ((gradleProject = gradleProject.getParent()) != null);
|
||||
if (projectPath != null) {
|
||||
buildParticipant.setRootPath(projectPath);
|
||||
for (IdeaModule module : project.getModules()) {
|
||||
try {
|
||||
String modulePath =
|
||||
ExternalSystemApiUtil.toCanonicalPath(module.getGradleProject().getProjectDirectory().getCanonicalPath());
|
||||
buildParticipant.getProjects().add(modulePath);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn("construction of the canonical path for the module fails", e);
|
||||
}
|
||||
}
|
||||
|
||||
compositeBuildData.getCompositeParticipants().add(buildParticipant);
|
||||
}
|
||||
}
|
||||
}
|
||||
projectDataNode.createChild(CompositeBuildData.KEY, compositeBuildData);
|
||||
}
|
||||
return gradleModulesWithIncludedBuilds;
|
||||
}
|
||||
|
||||
private static void mergeLibraryAndModuleDependencyData(DataNode<ProjectData> projectDataNode,
|
||||
@Nullable File gradleHomeDir,
|
||||
@Nullable GradleVersion gradleVersion) {
|
||||
@@ -419,8 +478,6 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
ExternalSystemApiUtil.findAllRecursively(projectDataNode, ProjectKeys.LIBRARY_DEPENDENCY);
|
||||
|
||||
for (DataNode<LibraryDependencyData> libraryDependencyDataNode : libraryDependencies) {
|
||||
if (!libraryDependencyDataNode.getChildren().isEmpty()) continue;
|
||||
|
||||
final DataNode<?> libraryNodeParent = libraryDependencyDataNode.getParent();
|
||||
if (libraryNodeParent == null) continue;
|
||||
|
||||
@@ -430,6 +487,8 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
if (libraryPaths.isEmpty()) continue;
|
||||
if(StringUtil.isNotEmpty(libraryData.getExternalName())) continue;
|
||||
|
||||
boolean projectDependencyCandidate = libraryPaths.size() == 1 && !libraryDependencyDataNode.getChildren().isEmpty();
|
||||
|
||||
final LinkedList<String> unprocessedPaths = ContainerUtil.newLinkedList(libraryPaths);
|
||||
while (!unprocessedPaths.isEmpty()) {
|
||||
final String path = unprocessedPaths.remove();
|
||||
@@ -505,7 +564,12 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
|
||||
if (targetModuleOutputPaths != null) {
|
||||
if (found == null) {
|
||||
libraryNodeParent.createChild(ProjectKeys.MODULE_DEPENDENCY, moduleDependencyData);
|
||||
DataNode<ModuleDependencyData> moduleDependencyNode = libraryNodeParent.createChild(ProjectKeys.MODULE_DEPENDENCY, moduleDependencyData);
|
||||
if(projectDependencyCandidate) {
|
||||
for (DataNode<?> node : libraryDependencyDataNode.getChildren()) {
|
||||
moduleDependencyNode.addChild(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
libraryPaths.removeAll(targetModuleOutputPaths);
|
||||
unprocessedPaths.removeAll(targetModuleOutputPaths);
|
||||
@@ -564,7 +628,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
|
||||
private static Map<String, ExternalProject> extractExternalProjectModels(ProjectImportAction.AllModels models, boolean isPreview) {
|
||||
final Class<? extends ExternalProject> modelClazz = isPreview ? ExternalProjectPreview.class : ExternalProject.class;
|
||||
final ExternalProject externalRootProject = models.getExtraProject(null, modelClazz);
|
||||
final ExternalProject externalRootProject = models.getExtraProject(null, modelClazz);
|
||||
if (externalRootProject == null) return Collections.emptyMap();
|
||||
|
||||
final DefaultExternalProject wrappedExternalRootProject = new DefaultExternalProject(externalRootProject);
|
||||
@@ -573,7 +637,11 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
|
||||
DomainObjectSet<? extends IdeaModule> gradleModules = models.getIdeaProject().getModules();
|
||||
if (gradleModules != null && !gradleModules.isEmpty()) {
|
||||
for (IdeaModule ideaModule : gradleModules) {
|
||||
List<IdeaModule> gradleModulesWithIncludedBuilds = ContainerUtil.newArrayList(gradleModules.getAll());
|
||||
for (IdeaProject project : models.getIncludedBuilds()) {
|
||||
gradleModulesWithIncludedBuilds.addAll(project.getModules());
|
||||
}
|
||||
for (IdeaModule ideaModule : gradleModulesWithIncludedBuilds) {
|
||||
final ExternalProject externalProject = externalProjectsMap.get(getModuleId(ideaModule));
|
||||
if (externalProject != null) {
|
||||
models.addExtraProject(externalProject, ExternalProject.class, ideaModule);
|
||||
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.data;
|
||||
|
||||
import com.intellij.openapi.externalSystem.model.DataNode;
|
||||
import com.intellij.openapi.externalSystem.model.Key;
|
||||
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.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.Order;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.model.data.BuildParticipant;
|
||||
import org.jetbrains.plugins.gradle.model.data.CompositeBuildData;
|
||||
import org.jetbrains.plugins.gradle.settings.CompositeDefinitionSource;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
* @since 2/17/2017
|
||||
*/
|
||||
@Order(ExternalSystemConstants.BUILTIN_SERVICE_ORDER)
|
||||
public class CompositeBuildDataService extends AbstractProjectDataService<CompositeBuildData, Project> {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Key<CompositeBuildData> getTargetDataKey() {
|
||||
return CompositeBuildData.KEY;
|
||||
}
|
||||
|
||||
public void importData(@NotNull final Collection<DataNode<CompositeBuildData>> toImport,
|
||||
@Nullable ProjectData projectData,
|
||||
@NotNull final Project project,
|
||||
@NotNull IdeModifiableModelsProvider modelsProvider) {
|
||||
if (toImport.isEmpty()) {
|
||||
if (projectData != null) {
|
||||
GradleProjectSettings projectSettings =
|
||||
GradleSettings.getInstance(project).getLinkedProjectSettings(projectData.getLinkedExternalProjectPath());
|
||||
if (projectSettings != null) {
|
||||
projectSettings.setCompositeBuild(null);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (toImport.size() != 1) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Expected to get a single composite data node but got %d: %s", toImport.size(), toImport));
|
||||
}
|
||||
CompositeBuildData compositeBuildData = toImport.iterator().next().getData();
|
||||
GradleProjectSettings projectSettings =
|
||||
GradleSettings.getInstance(project).getLinkedProjectSettings(compositeBuildData.getRootProjectPath());
|
||||
if (projectSettings != null) {
|
||||
GradleProjectSettings.CompositeBuild compositeBuild = new GradleProjectSettings.CompositeBuild();
|
||||
compositeBuild.setCompositeDefinitionSource(CompositeDefinitionSource.SCRIPT);
|
||||
for (BuildParticipant buildParticipant : compositeBuildData.getCompositeParticipants()) {
|
||||
compositeBuild.getCompositeParticipants().add(buildParticipant.copy());
|
||||
}
|
||||
projectSettings.setCompositeBuild(compositeBuild);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -334,7 +334,7 @@ public class IdeaGradleProjectSettingsControlBuilder implements GradleProjectSet
|
||||
|
||||
@Override
|
||||
public void apply(GradleProjectSettings settings) {
|
||||
settings.setCompositeParticipants(myInitialSettings.getCompositeParticipants());
|
||||
settings.setCompositeBuild(myInitialSettings.getCompositeBuild());
|
||||
if (myGradleHomePathField != null) {
|
||||
String gradleHomePath = FileUtil.toCanonicalPath(myGradleHomePathField.getText());
|
||||
if (StringUtil.isEmpty(gradleHomePath)) {
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.settings;
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
* @since 2/17/2017
|
||||
*/
|
||||
public enum CompositeDefinitionSource {
|
||||
IDE, SCRIPT
|
||||
}
|
||||
+18
@@ -15,8 +15,11 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.gradle.settings;
|
||||
|
||||
import com.intellij.openapi.externalSystem.model.DataNode;
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.gradle.tooling.model.idea.IdeaModule;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -25,6 +28,7 @@ import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
@@ -35,6 +39,7 @@ public class GradleExecutionWorkspace implements Serializable {
|
||||
|
||||
@NotNull
|
||||
private final List<GradleBuildParticipant> myBuildParticipants = ContainerUtil.newArrayList();
|
||||
private Map<String, Pair<DataNode<ModuleData>, IdeaModule>> myModuleMap;
|
||||
|
||||
public void addBuildParticipant(GradleBuildParticipant participant) {
|
||||
myBuildParticipants.add(participant);
|
||||
@@ -57,10 +62,23 @@ public class GradleExecutionWorkspace implements Serializable {
|
||||
|
||||
public ModuleData findModuleDataByName(String moduleName) {
|
||||
ModuleData result = null;
|
||||
|
||||
Pair<DataNode<ModuleData>, IdeaModule> modulePair = myModuleMap.get(moduleName);
|
||||
if(modulePair == null) {
|
||||
modulePair = myModuleMap.get(":" + moduleName);
|
||||
}
|
||||
if (modulePair != null) {
|
||||
return modulePair.first.getData();
|
||||
}
|
||||
|
||||
for (GradleBuildParticipant buildParticipant : myBuildParticipants) {
|
||||
result = buildParticipant.findModuleDataByName(moduleName);
|
||||
if (result != null) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void addModuleMap(Map<String, Pair<DataNode<ModuleData>, IdeaModule>> moduleMap) {
|
||||
myModuleMap = moduleMap;
|
||||
}
|
||||
}
|
||||
|
||||
+85
-9
@@ -17,12 +17,17 @@ package org.jetbrains.plugins.gradle.settings;
|
||||
|
||||
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil;
|
||||
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xmlb.annotations.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.model.data.BuildParticipant;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
@@ -31,11 +36,43 @@ import java.util.Set;
|
||||
public class GradleProjectSettings extends ExternalProjectSettings {
|
||||
|
||||
@Nullable private String myGradleHome;
|
||||
@Nullable private String myGradleJvm = ExternalSystemJdkUtil.USE_PROJECT_JDK;;
|
||||
@Nullable private String myGradleJvm = ExternalSystemJdkUtil.USE_PROJECT_JDK;
|
||||
@Nullable private DistributionType distributionType;
|
||||
private boolean disableWrapperSourceDistributionNotification;
|
||||
private boolean resolveModulePerSourceSet = true;
|
||||
@Nullable private Set<String> myCompositeParticipants = new HashSet<>();
|
||||
@Nullable private CompositeBuild myCompositeBuild;
|
||||
@Nullable private Set<String> myNonCompositeModules = new HashSet<>();
|
||||
|
||||
@OptionTag("modules")
|
||||
@Nullable
|
||||
public Set<String> getNonCompositeModules() {
|
||||
Set<String> modules = getModules();
|
||||
if (myCompositeBuild != null && !modules.isEmpty()) {
|
||||
Set<String> compositePaths = myCompositeBuild.getCompositeParticipants().stream()
|
||||
.flatMap(participant -> participant.getProjects().stream()).collect(Collectors.toSet());
|
||||
return modules.stream().filter(m -> !compositePaths.contains(m)).collect(Collectors.toSet());
|
||||
}
|
||||
else {
|
||||
return myNonCompositeModules;
|
||||
}
|
||||
}
|
||||
|
||||
public void setNonCompositeModules(@Nullable Set<String> modules) {
|
||||
myNonCompositeModules = modules;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<String> getModules() {
|
||||
return super.getModules();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModules(@Nullable Set<String> modules) {
|
||||
super.setModules(modules);
|
||||
setNonCompositeModules(modules);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getGradleHome() {
|
||||
@@ -80,13 +117,14 @@ public class GradleProjectSettings extends ExternalProjectSettings {
|
||||
this.resolveModulePerSourceSet = useIdeModulePerSourceSet;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<String> getCompositeParticipants() {
|
||||
return myCompositeParticipants == null ? Collections.emptySet() : myCompositeParticipants;
|
||||
@OptionTag(tag = "compositeConfiguration", nameAttribute = "")
|
||||
@Nullable
|
||||
public CompositeBuild getCompositeBuild() {
|
||||
return myCompositeBuild;
|
||||
}
|
||||
|
||||
public void setCompositeParticipants(@Nullable Set<String> compositeParticipants) {
|
||||
myCompositeParticipants = compositeParticipants;
|
||||
public void setCompositeBuild(@Nullable CompositeBuild compositeBuild) {
|
||||
myCompositeBuild = compositeBuild;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -99,7 +137,45 @@ public class GradleProjectSettings extends ExternalProjectSettings {
|
||||
result.distributionType = distributionType;
|
||||
result.disableWrapperSourceDistributionNotification = disableWrapperSourceDistributionNotification;
|
||||
result.resolveModulePerSourceSet = resolveModulePerSourceSet;
|
||||
result.myCompositeParticipants = myCompositeParticipants != null ? new HashSet<>(myCompositeParticipants) : null;
|
||||
result.myCompositeBuild = myCompositeBuild != null ? myCompositeBuild.copy() : null;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Tag("compositeBuild")
|
||||
public static class CompositeBuild {
|
||||
@Nullable private CompositeDefinitionSource myCompositeDefinitionSource;
|
||||
private List<BuildParticipant> myCompositeParticipants = new SmartList<>();
|
||||
|
||||
@Attribute
|
||||
@Nullable
|
||||
public CompositeDefinitionSource getCompositeDefinitionSource() {
|
||||
return myCompositeDefinitionSource;
|
||||
}
|
||||
|
||||
public void setCompositeDefinitionSource(@Nullable CompositeDefinitionSource compositeDefinitionSource) {
|
||||
myCompositeDefinitionSource = compositeDefinitionSource;
|
||||
}
|
||||
|
||||
@AbstractCollection(surroundWithTag = false, elementTag = "build")
|
||||
@OptionTag(tag = "builds", nameAttribute = "")
|
||||
@NotNull
|
||||
public List<BuildParticipant> getCompositeParticipants() {
|
||||
return myCompositeParticipants;
|
||||
}
|
||||
|
||||
public void setCompositeParticipants(List<BuildParticipant> compositeParticipants) {
|
||||
myCompositeParticipants = compositeParticipants == null ? new SmartList<>() : ContainerUtil.newArrayList(compositeParticipants);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CompositeBuild copy() {
|
||||
CompositeBuild result = new CompositeBuild();
|
||||
result.myCompositeParticipants = ContainerUtil.newArrayList();
|
||||
for (BuildParticipant participant : myCompositeParticipants) {
|
||||
result.myCompositeParticipants.add(participant.copy());
|
||||
}
|
||||
result.myCompositeDefinitionSource = myCompositeDefinitionSource;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+25
-2
@@ -32,6 +32,8 @@ import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.model.data.BuildParticipant;
|
||||
import org.jetbrains.plugins.gradle.settings.CompositeDefinitionSource;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
@@ -43,6 +45,8 @@ import javax.swing.tree.TreeNode;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.openapi.util.io.FileUtil.pathsEqual;
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
* @since 10/6/2016
|
||||
@@ -92,7 +96,19 @@ public class GradleProjectCompositeSelectorDialog extends DialogWrapper {
|
||||
for (Pair pair : pairs) {
|
||||
compositeParticipants.add(pair.second.toString());
|
||||
}
|
||||
myCompositeRootSettings.setCompositeParticipants(compositeParticipants.isEmpty() ? null : compositeParticipants);
|
||||
if (compositeParticipants.isEmpty()) {
|
||||
myCompositeRootSettings.setCompositeBuild(null);
|
||||
}
|
||||
else {
|
||||
GradleProjectSettings.CompositeBuild compositeBuild = new GradleProjectSettings.CompositeBuild();
|
||||
compositeBuild.setCompositeDefinitionSource(CompositeDefinitionSource.IDE);
|
||||
for (String participant : compositeParticipants) {
|
||||
BuildParticipant buildParticipant = new BuildParticipant();
|
||||
buildParticipant.setRootPath(participant);
|
||||
compositeBuild.getCompositeParticipants().add(buildParticipant);
|
||||
}
|
||||
myCompositeRootSettings.setCompositeBuild(compositeBuild);
|
||||
}
|
||||
}
|
||||
super.doOKAction();
|
||||
}
|
||||
@@ -113,7 +129,14 @@ public class GradleProjectCompositeSelectorDialog extends DialogWrapper {
|
||||
List<TreeNode> nodes = ContainerUtil.newArrayList();
|
||||
for (GradleProjectSettings projectSettings : GradleSettings.getInstance(myProject).getLinkedProjectsSettings()) {
|
||||
if (projectSettings == myCompositeRootSettings) continue;
|
||||
boolean added = myCompositeRootSettings.getCompositeParticipants().contains(projectSettings.getExternalProjectPath());
|
||||
if (projectSettings.getCompositeBuild() != null &&
|
||||
projectSettings.getCompositeBuild().getCompositeDefinitionSource() == CompositeDefinitionSource.SCRIPT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GradleProjectSettings.CompositeBuild compositeBuild = myCompositeRootSettings.getCompositeBuild();
|
||||
boolean added = compositeBuild != null && compositeBuild.getCompositeParticipants().stream()
|
||||
.anyMatch(participant -> pathsEqual(participant.getRootPath(), projectSettings.getExternalProjectPath()));
|
||||
|
||||
String representationName = myExternalSystemUiAware.getProjectRepresentationName(
|
||||
projectSettings.getExternalProjectPath(), projectSettings.getExternalProjectPath());
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.importing;
|
||||
|
||||
import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions;
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.intellij.openapi.roots.DependencyScope.COMPILE;
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
* @since 2/20/2017
|
||||
*/
|
||||
@SuppressWarnings("JUnit4AnnotatedMethodInJUnit3TestCase")
|
||||
public class GradleCompositeImportingTest extends GradleImportingTestCase {
|
||||
@Test
|
||||
@TargetVersions("3.3+")
|
||||
public void testBasicCompositeBuild() throws Exception {
|
||||
createSettingsFile("rootProject.name='adhoc'\n" +
|
||||
"\n" +
|
||||
"includeBuild '../my-app'\n" +
|
||||
"includeBuild '../my-utils'");
|
||||
|
||||
createProjectSubFile("../my-app/settings.gradle", "rootProject.name = 'my-app'\n");
|
||||
createProjectSubFile("../my-app/build.gradle",
|
||||
"apply plugin: 'java'\n" +
|
||||
"group 'org.sample'\n" +
|
||||
"version '1.0'\n" +
|
||||
"\n" +
|
||||
"dependencies {\n" +
|
||||
" compile 'org.sample:number-utils:1.0'\n" +
|
||||
" compile 'org.sample:string-utils:1.0'\n" +
|
||||
"}\n");
|
||||
|
||||
createProjectSubFile("../my-utils/settings.gradle",
|
||||
"rootProject.name = 'my-utils'\n" +
|
||||
"include 'number-utils', 'string-utils' ");
|
||||
createProjectSubFile("../my-utils/build.gradle",
|
||||
"subprojects {\n" +
|
||||
" apply plugin: 'java'\n" +
|
||||
"\n" +
|
||||
" group 'org.sample'\n" +
|
||||
" version '1.0'\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"project(':string-utils') {\n" +
|
||||
" dependencies {\n" +
|
||||
" compile 'org.apache.commons:commons-lang3:3.4'\n" +
|
||||
" }\n" +
|
||||
"} ");
|
||||
|
||||
importProject();
|
||||
|
||||
assertModules("adhoc",
|
||||
"my-app", "my-app_main", "my-app_test",
|
||||
"my-utils",
|
||||
"string-utils", "string-utils_test", "string-utils_main",
|
||||
"number-utils", "number-utils_main", "number-utils_test");
|
||||
|
||||
String[] rootModules = new String[]{"adhoc", "my-app", "my-utils", "string-utils", "number-utils"};
|
||||
for (String rootModule : rootModules) {
|
||||
assertModuleLibDeps(rootModule);
|
||||
assertModuleModuleDeps(rootModule);
|
||||
}
|
||||
assertModuleModuleDeps("my-app_main", "number-utils_main", "string-utils_main");
|
||||
assertModuleModuleDepScope("my-app_main", "number-utils_main", COMPILE);
|
||||
assertModuleModuleDepScope("my-app_main", "string-utils_main", COMPILE);
|
||||
assertModuleLibDepScope("my-app_main", "Gradle: org.apache.commons:commons-lang3:3.4", COMPILE);
|
||||
}
|
||||
}
|
||||
+45
-2
@@ -21,9 +21,11 @@ import org.gradle.tooling.BuildController;
|
||||
import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
|
||||
import org.gradle.tooling.internal.adapter.TargetTypeProvider;
|
||||
import org.gradle.tooling.model.build.BuildEnvironment;
|
||||
import org.gradle.tooling.model.gradle.GradleBuild;
|
||||
import org.gradle.tooling.model.idea.BasicIdeaProject;
|
||||
import org.gradle.tooling.model.idea.IdeaModule;
|
||||
import org.gradle.tooling.model.idea.IdeaProject;
|
||||
import org.gradle.util.GradleVersion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -39,9 +41,17 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
|
||||
|
||||
private final Set<Class> myExtraProjectModelClasses = new HashSet<Class>();
|
||||
private final boolean myIsPreviewMode;
|
||||
private final boolean myIsGradleProjectDirSupported;
|
||||
private final boolean myIsCompositeBuildsSupported;
|
||||
|
||||
public ProjectImportAction(boolean isPreviewMode) {
|
||||
this(isPreviewMode, false, false);
|
||||
}
|
||||
|
||||
public ProjectImportAction(boolean isPreviewMode, boolean isGradleProjectDirSupported, boolean isCompositeBuildsSupported) {
|
||||
myIsPreviewMode = isPreviewMode;
|
||||
myIsGradleProjectDirSupported= isGradleProjectDirSupported;
|
||||
myIsCompositeBuildsSupported = isCompositeBuildsSupported;
|
||||
}
|
||||
|
||||
public void addExtraProjectModelClasses(@NotNull Set<Class> projectModelClasses) {
|
||||
@@ -60,11 +70,25 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
|
||||
}
|
||||
|
||||
AllModels allModels = new AllModels(ideaProject);
|
||||
allModels.setGradleProjectDirSupported(myIsGradleProjectDirSupported);
|
||||
BuildEnvironment buildEnvironment = controller.findModel(BuildEnvironment.class);
|
||||
allModels.setBuildEnvironment(buildEnvironment);
|
||||
addExtraProject(controller, allModels, null);
|
||||
for (IdeaModule module : ideaProject.getModules()) {
|
||||
addExtraProject(controller, allModels, module);
|
||||
}
|
||||
|
||||
if (myIsCompositeBuildsSupported) {
|
||||
GradleBuild gradleBuild = controller.getModel(GradleBuild.class);
|
||||
for (GradleBuild build : gradleBuild.getIncludedBuilds()) {
|
||||
IdeaProject ideaIncludedProject = controller.findModel(build, IdeaProject.class);
|
||||
allModels.getIncludedBuilds().add(ideaIncludedProject);
|
||||
for (IdeaModule module : ideaIncludedProject.getModules()) {
|
||||
addExtraProject(controller, allModels, module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allModels;
|
||||
}
|
||||
|
||||
@@ -111,6 +135,9 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
|
||||
|
||||
public static class AllModels extends ModelsHolder<IdeaProject, IdeaModule> {
|
||||
|
||||
private List<IdeaProject> includedBuilds = new ArrayList<IdeaProject>();
|
||||
private boolean isGradleProjectDirSupported;
|
||||
|
||||
public AllModels(@NotNull IdeaProject ideaProject) {
|
||||
super(ideaProject);
|
||||
}
|
||||
@@ -120,6 +147,11 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
|
||||
return getRootModel();
|
||||
}
|
||||
|
||||
|
||||
public List<IdeaProject> getIncludedBuilds() {
|
||||
return includedBuilds;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BuildEnvironment getBuildEnvironment() {
|
||||
return getExtraProject(BuildEnvironment.class);
|
||||
@@ -131,11 +163,22 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
|
||||
}
|
||||
}
|
||||
|
||||
public void setGradleProjectDirSupported(boolean gradleProjectDirSupported) {
|
||||
isGradleProjectDirSupported = gradleProjectDirSupported;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String extractMapKey(Class modelClazz, @Nullable IdeaModule module) {
|
||||
return modelClazz.getName() + '@' +
|
||||
(module != null ? module.getGradleProject().getPath() : "root" + getRootModel().getName().hashCode());
|
||||
if (module != null) {
|
||||
String id = isGradleProjectDirSupported ?
|
||||
module.getGradleProject().getProjectDirectory().getPath() :
|
||||
module.getGradleProject().getPath();
|
||||
return modelClazz.getName() + '@' + id;
|
||||
}
|
||||
else {
|
||||
return modelClazz.getName() + '@' + ("root" + getRootModel().getName().hashCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+30
-17
@@ -39,18 +39,12 @@ import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
|
||||
import org.jetbrains.plugins.gradle.tooling.util.DependencyResolverImpl
|
||||
import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
* @since 12/20/13
|
||||
*/
|
||||
class ExternalProjectBuilderImpl implements ModelBuilderService {
|
||||
|
||||
private final cache = new ConcurrentHashMap<String, ExternalProject>()
|
||||
private final myTasksFactory = new TasksFactory()
|
||||
private SourceSetCachedFinder mySourceSetFinder
|
||||
|
||||
@Override
|
||||
boolean canBuild(String modelName) {
|
||||
return ExternalProject.name == modelName || ExternalProjectPreview.name == modelName
|
||||
@@ -59,10 +53,29 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
|
||||
@Nullable
|
||||
@Override
|
||||
Object buildAll(final String modelName, final Project project) {
|
||||
ExternalProject externalProject = cache[project.path]
|
||||
if (externalProject != null) return externalProject
|
||||
def cache = getOrSetExt(project, 'projects cache: ' + ExternalProject.name, { new HashMap<Project, ExternalProject>()}) as Map<Project, ExternalProject>
|
||||
def tasksFactory = getOrSetExt(project , 'tasks cache: ' + ExternalProject.name, { new TasksFactory()}) as TasksFactory
|
||||
def sourceSetFinder = getOrSetExt(project , 'sourceSets finder: ' + ExternalProject.name, { new SourceSetCachedFinder(project)}) as SourceSetCachedFinder
|
||||
return doBuild(modelName, project, cache, tasksFactory, sourceSetFinder)
|
||||
}
|
||||
|
||||
if(!mySourceSetFinder) mySourceSetFinder = new SourceSetCachedFinder(project)
|
||||
private static getOrSetExt(final Project project, String name, Closure<Object> valueProvider) {
|
||||
def rootProject = project.getRootProject()
|
||||
def extraProperties = rootProject.extensions.extraProperties
|
||||
if(!extraProperties.has(name)) {
|
||||
extraProperties.set(name, valueProvider())
|
||||
}
|
||||
return extraProperties.get(name)
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object doBuild(final String modelName,
|
||||
final Project project,
|
||||
Map<Project, ExternalProject> cache,
|
||||
TasksFactory tasksFactory,
|
||||
SourceSetCachedFinder sourceSetFinder) {
|
||||
ExternalProject externalProject = cache[project]
|
||||
if (externalProject != null) return externalProject
|
||||
|
||||
def resolveSourceSetDependencies = System.properties.'idea.resolveSourceSetDependencies' as boolean
|
||||
def isPreview = ExternalProjectPreview.name == modelName
|
||||
@@ -76,8 +89,8 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
|
||||
defaultExternalProject.buildFile = project.buildFile
|
||||
defaultExternalProject.group = wrap(project.group)
|
||||
defaultExternalProject.projectDir = project.projectDir
|
||||
defaultExternalProject.sourceSets = getSourceSets(project, isPreview, resolveSourceSetDependencies)
|
||||
defaultExternalProject.tasks = getTasks(project)
|
||||
defaultExternalProject.sourceSets = getSourceSets(project, isPreview, resolveSourceSetDependencies, sourceSetFinder)
|
||||
defaultExternalProject.tasks = getTasks(project, tasksFactory)
|
||||
|
||||
defaultExternalProject.plugins = getPlugins(project)
|
||||
//defaultExternalProject.setProperties(project.getProperties())
|
||||
@@ -86,13 +99,13 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
|
||||
|
||||
final Map<String, ExternalProject> childProjects = new HashMap<String, ExternalProject>(project.getChildProjects().size())
|
||||
for (Map.Entry<String, Project> projectEntry : project.getChildProjects().entrySet()) {
|
||||
final Object externalProjectChild = buildAll(modelName, projectEntry.getValue())
|
||||
final Object externalProjectChild = doBuild(modelName, projectEntry.getValue(), cache, tasksFactory, sourceSetFinder)
|
||||
if (externalProjectChild instanceof ExternalProject) {
|
||||
childProjects.put(projectEntry.getKey(), (ExternalProject)externalProjectChild)
|
||||
}
|
||||
}
|
||||
defaultExternalProject.setChildProjects(childProjects)
|
||||
cache.put(project.getPath(), defaultExternalProject)
|
||||
cache.put(project, defaultExternalProject)
|
||||
|
||||
defaultExternalProject
|
||||
}
|
||||
@@ -127,10 +140,10 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
|
||||
result
|
||||
}
|
||||
|
||||
Map<String, ExternalTask> getTasks(Project project) {
|
||||
static Map<String, ExternalTask> getTasks(Project project, TasksFactory tasksFactory) {
|
||||
def result = [:] as Map<String, DefaultExternalTask>
|
||||
|
||||
myTasksFactory.getTasks(project).each { Task task ->
|
||||
tasksFactory.getTasks(project).each { Task task ->
|
||||
DefaultExternalTask externalTask = result.get(task.name)
|
||||
if (externalTask == null) {
|
||||
externalTask = new DefaultExternalTask()
|
||||
@@ -150,7 +163,7 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
|
||||
result
|
||||
}
|
||||
|
||||
private Map<String, ExternalSourceSet> getSourceSets(Project project, boolean isPreview, boolean resolveSourceSetDependencies) {
|
||||
private static Map<String, ExternalSourceSet> getSourceSets(Project project, boolean isPreview, boolean resolveSourceSetDependencies, SourceSetCachedFinder sourceSetFinder) {
|
||||
final IdeaPlugin ideaPlugin = project.getPlugins().findPlugin(IdeaPlugin.class)
|
||||
def ideaPluginModule = ideaPlugin?.model?.module
|
||||
boolean inheritOutputDirs = ideaPluginModule?.inheritOutputDirs ?: false
|
||||
@@ -341,7 +354,7 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
|
||||
}
|
||||
|
||||
if(resolveSourceSetDependencies) {
|
||||
def dependencies = new DependencyResolverImpl(project, isPreview, downloadJavadoc, downloadSources, mySourceSetFinder).resolveDependencies(sourceSet)
|
||||
def dependencies = new DependencyResolverImpl(project, isPreview, downloadJavadoc, downloadSources, sourceSetFinder).resolveDependencies(sourceSet)
|
||||
externalSourceSet.dependencies.addAll(dependencies)
|
||||
}
|
||||
|
||||
|
||||
+25
-20
@@ -13,33 +13,38 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.gradle.api.internal.project.ProjectInternal
|
||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||
import org.jetbrains.plugins.gradle.tooling.internal.ExtraModelBuilder
|
||||
|
||||
@SuppressWarnings("GrPackage")
|
||||
class JetGradlePlugin implements Plugin<Project> {
|
||||
private final ToolingModelBuilderRegistry registry
|
||||
|
||||
@javax.inject.Inject
|
||||
public JetGradlePlugin(ToolingModelBuilderRegistry registry) {
|
||||
this.registry = registry
|
||||
}
|
||||
|
||||
public void apply(Project project) {
|
||||
registry.register(project.extraModelBuilder)
|
||||
}
|
||||
}
|
||||
|
||||
System.setProperty("idea.active", "true")
|
||||
|
||||
initscript {
|
||||
dependencies {
|
||||
classpath files(${EXTENSIONS_JARS_PATH})
|
||||
}
|
||||
}
|
||||
|
||||
def extraModelBuilderInstance = new ExtraModelBuilder()
|
||||
allprojects {
|
||||
ext.extraModelBuilder = extraModelBuilderInstance
|
||||
apply plugin: JetGradlePlugin
|
||||
}
|
||||
apply plugin: JetGradlePlugin
|
||||
|
||||
@SuppressWarnings("GrPackage")
|
||||
class JetGradlePlugin implements Plugin<Gradle> {
|
||||
void apply(Gradle gradle) {
|
||||
def extraModelBuilderInstance = new ExtraModelBuilder()
|
||||
def isCompositeBuildsSupported = GradleVersion.current() >= GradleVersion.version("3.1")
|
||||
gradle.allprojects { project ->
|
||||
((ProjectInternal)project).services.getAll(ToolingModelBuilderRegistry.class).each { it.register(extraModelBuilderInstance) }
|
||||
try {
|
||||
if (isCompositeBuildsSupported) {
|
||||
project.gradle.includedBuilds.each {
|
||||
it.configuredBuild.services.getAll(ToolingModelBuilderRegistry.class).each {
|
||||
it.register(extraModelBuilderInstance)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -242,6 +242,9 @@ class DependencyResolverImpl implements DependencyResolver {
|
||||
dependencies.each {((AbstractExternalDependency)it).scope = compileScope}
|
||||
}
|
||||
else {
|
||||
if(dependencies) {
|
||||
((AbstractExternalDependency)it).scope = compileScope
|
||||
}
|
||||
resolvedRuntimeMap.put(resolve(it), it)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -136,7 +136,8 @@ public abstract class AbstractModelBuilderTest {
|
||||
|
||||
GradleConnector connector = GradleConnector.newConnector();
|
||||
|
||||
final URI distributionUri = new DistributionLocator().getDistributionFor(GradleVersion.version(gradleVersion));
|
||||
GradleVersion _gradleVersion = GradleVersion.version(gradleVersion);
|
||||
final URI distributionUri = new DistributionLocator().getDistributionFor(_gradleVersion);
|
||||
connector.useDistribution(distributionUri);
|
||||
connector.forProjectDirectory(testDir);
|
||||
int daemonMaxIdleTime = 10;
|
||||
@@ -149,7 +150,10 @@ public abstract class AbstractModelBuilderTest {
|
||||
ProjectConnection connection = connector.connect();
|
||||
|
||||
try {
|
||||
final ProjectImportAction projectImportAction = new ProjectImportAction(false);
|
||||
boolean isGradleProjectDirSupported = _gradleVersion.compareTo(GradleVersion.version("2.4")) >= 0;
|
||||
boolean isCompositeBuildsSupported = isGradleProjectDirSupported && _gradleVersion.compareTo(GradleVersion.version("3.1")) >= 0;
|
||||
final ProjectImportAction projectImportAction = new ProjectImportAction(false, isGradleProjectDirSupported,
|
||||
isCompositeBuildsSupported);
|
||||
projectImportAction.addExtraProjectModelClasses(getModels());
|
||||
BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = connection.action(projectImportAction);
|
||||
File initScript = GradleExecutionHelper.generateInitScript(false, getToolingExtensionClasses());
|
||||
|
||||
Reference in New Issue
Block a user