gradle: composite builds defined in gradle scripts support (IDEA-162664)

This commit is contained in:
Vladislav.Soroka
2017-02-20 06:26:11 +03:00
parent 6282f11a80
commit c8b6209acf
23 changed files with 699 additions and 76 deletions
@@ -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();
@@ -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;
}
@@ -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);
@@ -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;
}
}
+1
View File
@@ -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) {
@@ -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;
}
}
@@ -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()) {
@@ -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);
@@ -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);
}
}
}
@@ -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)) {
@@ -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
}
@@ -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;
}
}
@@ -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;
}
}
}
@@ -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());
@@ -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);
}
}
@@ -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());
}
}
}
}
@@ -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)
}
@@ -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) {
}
}
}
}
@@ -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)
}
}
@@ -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());