diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ModuleData.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ModuleData.java
index c2c06d218043..bd9ad5180310 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ModuleData.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ModuleData.java
@@ -209,6 +209,7 @@ public class ModuleData extends AbstractNamedData implements Named, ExternalConf
ModuleData that = (ModuleData)o;
+ if (!myId.equals(that.myId)) return false;
if (myGroup != null ? !myGroup.equals(that.myGroup) : that.myGroup != null) return false;
if (!myModuleTypeId.equals(that.myModuleTypeId)) return false;
if (myVersion != null ? !myVersion.equals(that.myVersion) : that.myVersion != null) return false;
@@ -220,6 +221,7 @@ public class ModuleData extends AbstractNamedData implements Named, ExternalConf
@Override
public int hashCode() {
int result = super.hashCode();
+ result = 31 * result + myId.hashCode();
result = 31 * result + myModuleTypeId.hashCode();
result = 31 * result + (myGroup != null ? myGroup.hashCode() : 0);
result = 31 * result + (myVersion != null ? myVersion.hashCode() : 0);
@@ -229,9 +231,6 @@ public class ModuleData extends AbstractNamedData implements Named, ExternalConf
@Override
public String toString() {
- return String.format("module '%s:%s:%s'",
- myGroup == null ? "" : myGroup,
- getExternalName(),
- myVersion == null ? "" : myVersion);
+ return getId();
}
}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/IdeModelsProviderImpl.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/IdeModelsProviderImpl.java
index 56aa9449c796..61b206ad9d51 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/IdeModelsProviderImpl.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/IdeModelsProviderImpl.java
@@ -24,20 +24,20 @@ import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
-import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Function;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.File;
import java.util.List;
import java.util.Set;
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.*;
+import static com.intellij.openapi.util.io.FileUtil.pathsEqual;
/**
* @author Vladislav.Soroka
@@ -75,19 +75,39 @@ public class IdeModelsProviderImpl implements IdeModelsProvider {
@Nullable
@Override
public Module findIdeModule(@NotNull ModuleData module) {
- final Module ideModule = findIdeModule(module.getInternalName());
- return isExternalSystemAwareModule(module.getOwner(), ideModule) ? ideModule : null;
+ for (String candidate : suggestModuleNameCandidates(module)) {
+ Module ideModule = findIdeModule(candidate);
+ if (ideModule != null && isApplicableIdeModule(module, ideModule)) {
+ return ideModule;
+ }
+ }
+ return null;
+ }
+
+ protected String[] suggestModuleNameCandidates(@NotNull ModuleData module) {
+ String prefix = module.getGroup();
+ File modulePath = new File(module.getLinkedExternalProjectPath());
+ if(modulePath.isFile()) {
+ modulePath = modulePath.getParentFile();
+ }
+ if (modulePath.getParentFile() != null) {
+ prefix = modulePath.getParentFile().getName();
+ }
+ return new String[]{
+ module.getInternalName(),
+ prefix + '-' + module.getInternalName(),
+ prefix + '-' + module.getInternalName() + "~1"};
+ }
+
+ private static boolean isApplicableIdeModule(@NotNull ModuleData moduleData, @NotNull Module ideModule) {
+ return isExternalSystemAwareModule(moduleData.getOwner(), ideModule) &&
+ pathsEqual(getExternalProjectPath(ideModule), moduleData.getLinkedExternalProjectPath());
}
@Nullable
@Override
public Module findIdeModule(@NotNull String ideModuleName) {
- for (Module module : getModules()) {
- if (ideModuleName.equals(module.getName())) {
- return module;
- }
- }
- return null;
+ return ModuleManager.getInstance(myProject).findModuleByName(ideModuleName);
}
@Nullable
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/IdeModifiableModelsProvider.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/IdeModifiableModelsProvider.java
index a72dc7cc601c..218e2490c6c6 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/IdeModifiableModelsProvider.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/IdeModifiableModelsProvider.java
@@ -17,6 +17,7 @@ package com.intellij.openapi.externalSystem.service.project;
import com.intellij.facet.ModifiableFacetModel;
import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModifiableRootModel;
@@ -35,6 +36,9 @@ public interface IdeModifiableModelsProvider extends IdeModelsProvider {
@NotNull
Module newModule(@NotNull @NonNls String filePath, final String moduleTypeId);
+ @NotNull
+ Module newModule(@NotNull ModuleData moduleData);
+
@NotNull
ModifiableModuleModel getModifiableModuleModel();
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/AbstractIdeModifiableModelsProvider.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/AbstractIdeModifiableModelsProvider.java
index 45b171e20b67..6a98ae509460 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/AbstractIdeModifiableModelsProvider.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/AbstractIdeModifiableModelsProvider.java
@@ -19,9 +19,11 @@ import com.intellij.facet.Facet;
import com.intellij.facet.FacetModel;
import com.intellij.facet.FacetTypeId;
import com.intellij.facet.ModifiableFacetModel;
+import com.intellij.ide.highlighter.ModuleFileType;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.project.LibraryData;
+import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleWithNameAlreadyExists;
@@ -56,6 +58,7 @@ import java.io.File;
import java.util.*;
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.isRelated;
+import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.toCanonicalPath;
public abstract class AbstractIdeModifiableModelsProvider extends IdeModelsProviderImpl implements IdeModifiableModelsProvider {
private static final Logger LOG = Logger.getInstance(AbstractIdeModifiableModelsProvider.class);
@@ -131,6 +134,21 @@ public abstract class AbstractIdeModifiableModelsProvider extends IdeModelsProvi
return module;
}
+ @NotNull
+ @Override
+ public Module newModule(@NotNull ModuleData moduleData) {
+ String filePath = moduleData.getModuleFilePath();
+ String moduleTypeId = moduleData.getModuleTypeId();
+ for (String candidate : suggestModuleNameCandidates(moduleData)) {
+ Module module = findIdeModule(candidate);
+ if (module == null) {
+ filePath = toCanonicalPath(moduleData.getModuleFileDirectoryPath() + "/" + candidate + ModuleFileType.DOT_DEFAULT_EXTENSION);
+ break;
+ }
+ }
+ return newModule(filePath, moduleTypeId);
+ }
+
@Nullable
@Override
public Module findIdeModule(@NotNull String ideModuleName) {
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractDependencyDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractDependencyDataService.java
index 379057d379c3..97d869729a77 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractDependencyDataService.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractDependencyDataService.java
@@ -95,7 +95,17 @@ public abstract class AbstractDependencyDataService byModuleName = MultiMap.create();
for (DataNode node : toImport) {
final AbstractDependencyData data = node.getData();
- byModuleName.putValue(data.getOwnerModule().getInternalName(), getInternalName(data));
+ Module ownerModule = modelsProvider.findIdeModule(data.getOwnerModule());
+ assert ownerModule != null;
+ String depName;
+ if(data instanceof ModuleDependencyData) {
+ Module targetModule = modelsProvider.findIdeModule(((ModuleDependencyData)data).getTarget());
+ assert targetModule != null;
+ depName = targetModule.getName();
+ } else {
+ depName = getInternalName(data);
+ }
+ byModuleName.putValue(ownerModule.getName(), depName);
}
final ModifiableModuleModel modifiableModuleModel = modelsProvider.getModifiableModuleModel();
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java
index 07ed220fef5d..cefac479cc51 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java
@@ -33,14 +33,12 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleWithNameAlreadyExists;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.ui.CheckBoxList;
@@ -48,7 +46,6 @@ import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
-import com.intellij.util.Function;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
@@ -57,7 +54,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
-import java.io.File;
import java.util.*;
import java.util.List;
@@ -116,7 +112,7 @@ public abstract class AbstractModuleDataService extends Ab
@NotNull Project project) {
for (final DataNode module : toCreate) {
ModuleData data = module.getData();
- final Module created = modelsProvider.newModule(data.getModuleFilePath(), data.getModuleTypeId());
+ final Module created = modelsProvider.newModule(data);
module.putUserData(MODULE_KEY, created);
Set orphanFiles = project.getUserData(ORPHAN_MODULE_FILES);
if (orphanFiles != null) {
@@ -154,23 +150,12 @@ public abstract class AbstractModuleDataService extends Ab
Collection> result = ContainerUtilRt.newArrayList();
for (DataNode node : modules) {
ModuleData moduleData = node.getData();
- Module module = modelsProvider.findIdeModule(moduleData.getInternalName());
+ Module module = modelsProvider.findIdeModule(moduleData);
if (module == null) {
result.add(node);
}
else {
- if (!FileUtil.pathsEqual(ExternalSystemApiUtil.getExternalProjectPath(module), moduleData.getLinkedExternalProjectPath())) {
- modelsProvider.getModifiableModuleModel().disposeModule(module);
- result.add(node);
- Set orphanFiles = project.getUserData(ORPHAN_MODULE_FILES);
- if (orphanFiles == null) {
- project.putUserData(ORPHAN_MODULE_FILES, orphanFiles = ContainerUtil.newHashSet());
- }
- orphanFiles.add(module.getModuleFilePath());
- }
- else {
- node.putUserData(MODULE_KEY, module);
- }
+ node.putUserData(MODULE_KEY, module);
}
}
return result;
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDependencyDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDependencyDataService.java
index 2752d312331a..31e4b100e3c1 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDependencyDataService.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDependencyDataService.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.Key;
import com.intellij.openapi.externalSystem.model.ProjectKeys;
+import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData;
import com.intellij.openapi.externalSystem.model.project.OrderAware;
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider;
@@ -97,8 +98,8 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService
ideDependencyModule == null
- ? modifiableRootModel.addInvalidModuleEntry(moduleName)
+ ? modifiableRootModel.addInvalidModuleEntry(moduleData.getInternalName())
: modifiableRootModel.addModuleOrderEntry(ideDependencyModule));
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildParticipant.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildParticipant.java
index e2228afcb465..cb3e00db3f64 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildParticipant.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildParticipant.java
@@ -31,9 +31,19 @@ import java.util.Set;
*/
@Tag("build")
public class BuildParticipant implements Serializable {
+ private String myRootProjectName;
private String myRootPath;
@NotNull private Set myProjects = new HashSet<>();
+ @Attribute("name")
+ public String getRootProjectName() {
+ return myRootProjectName;
+ }
+
+ public void setRootProjectName(String rootProjectName) {
+ myRootProjectName = rootProjectName;
+ }
+
@Attribute("path")
public String getRootPath() {
return myRootPath;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
index 9755dbea54e7..480b4b1a8e85 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
@@ -68,7 +68,7 @@ import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData;
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData;
import org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataService;
import org.jetbrains.plugins.gradle.service.project.data.GradleExtensionsDataService;
-import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
+import org.jetbrains.plugins.gradle.settings.GradleExecutionWorkspace;
import org.jetbrains.plugins.gradle.tooling.builder.ModelBuildScriptClasspathBuilderImpl;
import org.jetbrains.plugins.gradle.tooling.internal.init.Init;
import org.jetbrains.plugins.gradle.util.GradleBundle;
@@ -187,7 +187,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
mainModuleData.setIdeModuleGroup(isRootModule ? null : moduleGroup);
for (ExternalSourceSet sourceSet : externalProject.getSourceSets().values()) {
- final String moduleId = getModuleId(externalProject, sourceSet);
+ final String moduleId = getModuleId(resolverCtx, gradleModule, sourceSet);
final String moduleExternalName = gradleModule.getName() + ":" + sourceSet.getName();
final String moduleInternalName = getInternalModuleName(gradleModule, sourceSet.getName());
@@ -301,7 +301,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
@NotNull DataNode ideModule) {
ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class);
if (externalProject != null) {
- processSourceSets(externalProject, ideModule, new SourceSetsProcessor() {
+ processSourceSets(resolverCtx, gradleModule, externalProject, ideModule, new SourceSetsProcessor() {
@Override
public void process(@NotNull DataNode extends ModuleData> dataNode, @NotNull ExternalSourceSet sourceSet) {
for (Map.Entry directorySetEntry : sourceSet.getSources().entrySet()) {
@@ -350,7 +350,9 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
}
}
- private static void processSourceSets(@NotNull ExternalProject externalProject,
+ private static void processSourceSets(@NotNull ProjectResolverContext resolverCtx,
+ @NotNull IdeaModule gradleModule,
+ @NotNull ExternalProject externalProject,
@NotNull DataNode ideModule,
@NotNull SourceSetsProcessor processor) {
Map> sourceSetsMap = ContainerUtil.newHashMap();
@@ -361,7 +363,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
for (ExternalSourceSet sourceSet : externalProject.getSourceSets().values()) {
if (sourceSet == null || sourceSet.getSources().isEmpty()) continue;
- final String moduleId = getModuleId(externalProject, sourceSet);
+ final String moduleId = getModuleId(resolverCtx, gradleModule, sourceSet);
final DataNode extends ModuleData> moduleDataNode = sourceSetsMap.isEmpty() ? ideModule : sourceSetsMap.get(moduleId);
if (moduleDataNode == null) continue;
@@ -380,7 +382,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
final Map> moduleOutputsMap = projectDataNode.getUserData(MODULES_OUTPUTS);
assert moduleOutputsMap != null;
- processSourceSets(externalProject, ideModule, new SourceSetsProcessor() {
+ processSourceSets(resolverCtx, gradleModule, externalProject, ideModule, new SourceSetsProcessor() {
@Override
public void process(@NotNull DataNode extends ModuleData> dataNode, @NotNull ExternalSourceSet sourceSet) {
for (Map.Entry directorySetEntry : sourceSet.getSources().entrySet()) {
@@ -470,7 +472,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
if (resolverCtx.isResolveModulePerSourceSet()) {
assert sourceSetMap != null;
- processSourceSets(externalProject, ideModule, new SourceSetsProcessor() {
+ processSourceSets(resolverCtx, gradleModule, externalProject, ideModule, new SourceSetsProcessor() {
@Override
public void process(@NotNull DataNode extends ModuleData> dataNode, @NotNull ExternalSourceSet sourceSet) {
buildDependencies(resolverCtx, sourceSetMap, artifactsMap, dataNode, sourceSet.getDependencies(), ideProject);
@@ -493,7 +495,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
DependencyScope scope = parseScope(dependency.getScope());
if (dependency instanceof IdeaModuleDependency) {
- ModuleDependencyData d = buildDependency(resolverCtx.getSettings(), ideModule, (IdeaModuleDependency)dependency, ideProject);
+ ModuleDependencyData d = buildDependency(resolverCtx, ideModule, (IdeaModuleDependency)dependency, ideProject);
d.setExported(dependency.getExported());
if (scope != null) {
d.setScope(scope);
@@ -826,23 +828,30 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
}
@NotNull
- private static ModuleDependencyData buildDependency(@Nullable GradleExecutionSettings executionSettings,
+ private static ModuleDependencyData buildDependency(@NotNull ProjectResolverContext resolverContext,
@NotNull DataNode ownerModule,
@NotNull IdeaModuleDependency dependency,
@NotNull DataNode ideProject)
throws IllegalStateException {
IdeaModule module = dependency.getDependencyModule();
if (module == null) {
- if (executionSettings != null) {
+ if (resolverContext.getSettings() != null) {
String moduleName = dependency.getTargetModuleName();
- ModuleData moduleData = executionSettings.getExecutionWorkspace().findModuleDataByName(moduleName);
+ GradleExecutionWorkspace executionWorkspace = resolverContext.getSettings().getExecutionWorkspace();
+ ModuleData moduleData = executionWorkspace.findModuleDataByName(moduleName);
if (moduleData != null) {
return new ModuleDependencyData(ownerModule.getData(), moduleData);
}
- else if (StringUtil.isNotEmpty(moduleName)) {
- return new ModuleDependencyData(
- ownerModule.getData(), new ModuleData("", GradleConstants.SYSTEM_ID, StdModuleTypes.JAVA.getId(), moduleName, "", ""));
+ else {
+ for (IdeaProject project : resolverContext.getModels().getIncludedBuilds()) {
+ moduleData = executionWorkspace.findModuleDataByName(project.getName() + ':' + moduleName);
+ if (moduleData != null) {
+ return new ModuleDependencyData(ownerModule.getData(), moduleData);
+ }
+ }
}
+ return new ModuleDependencyData(
+ ownerModule.getData(), new ModuleData("", GradleConstants.SYSTEM_ID, StdModuleTypes.JAVA.getId(), moduleName, "", ""));
}
throw new IllegalStateException(
String.format("Can't parse gradle module dependency '%s'. Reason: referenced module is null", dependency)
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DefaultProjectResolverContext.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DefaultProjectResolverContext.java
index 1b99465d3327..35c293d59edb 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DefaultProjectResolverContext.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DefaultProjectResolverContext.java
@@ -141,13 +141,13 @@ public class DefaultProjectResolverContext extends UserDataHolderBase implements
@Nullable
@Override
public T getExtraProject(Class modelClazz) {
- return myModels.getExtraProject(null, modelClazz);
+ return myModels.getExtraProject((IdeaModule)null, modelClazz);
}
@Nullable
@Override
public T getExtraProject(@Nullable IdeaModule module, Class modelClazz) {
- return myModels.getExtraProject(module, modelClazz);
+ return myModels.getExtraProject(module != null ? module.getGradleProject() : null, modelClazz);
}
@NotNull
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
index df308930c2d5..78daf36171c5 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
@@ -38,6 +38,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
+import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.MultiMap;
@@ -288,8 +289,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver gradleModulesWithIncludedBuilds = exposeCompositeBuild(allModels, projectDataNode, gradleModules);
-
+ Collection includedModules = exposeCompositeBuild(allModels, projectDataNode);
final Map, IdeaModule>> moduleMap = ContainerUtilRt.newHashMap();
final Map, ExternalSourceSet>> sourceSetsMap = ContainerUtil.newHashMap();
projectDataNode.putUserData(RESOLVED_SOURCE_SETS, sourceSetsMap);
@@ -322,7 +321,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver moduleDataNode = projectResolverChain.createModule(gradleModule, projectDataNode);
- String mainModuleId = getModuleId(gradleModule);
+ String mainModuleId = getModuleId(resolverCtx, gradleModule);
+
+ if (moduleMap.containsKey(mainModuleId)) {
+ // we should ensure deduplicated module names in the scope of single import
+ throw new IllegalStateException("Duplicate modules names detected: " + gradleModule);
+ }
moduleMap.put(mainModuleId, Pair.create(moduleDataNode, gradleModule));
}
@@ -415,18 +419,21 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver exposeCompositeBuild(ProjectImportAction.AllModels allModels,
- DataNode projectDataNode,
- DomainObjectSet extends IdeaModule> gradleModules) {
- List gradleModulesWithIncludedBuilds = ContainerUtil.newArrayList(gradleModules.getAll());
+ private static Collection exposeCompositeBuild(ProjectImportAction.AllModels allModels,
+ DataNode projectDataNode) {
+ CompositeBuildData compositeBuildData = null;
+ List gradleIncludedModules = new SmartList<>();
List includedBuilds = allModels.getIncludedBuilds();
if (!includedBuilds.isEmpty()) {
ProjectData projectData = projectDataNode.getData();
- CompositeBuildData compositeBuildData = new CompositeBuildData(projectData.getLinkedExternalProjectPath());
+ compositeBuildData = new CompositeBuildData(projectData.getLinkedExternalProjectPath());
for (IdeaProject project : includedBuilds) {
if (!project.getModules().isEmpty()) {
+ String rootProjectName = project.getName();
BuildParticipant buildParticipant = new BuildParticipant();
- gradleModulesWithIncludedBuilds.addAll(project.getModules());
+ for (IdeaModule ideaModule : project.getModules()) {
+ gradleIncludedModules.add(ideaModule);
+ }
GradleProject gradleProject = project.getModules().getAt(0).getGradleProject();
String projectPath = null;
do {
@@ -439,6 +446,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver projectDataNode,
@@ -626,33 +634,53 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver extractExternalProjectModels(ProjectImportAction.AllModels models, boolean isPreview) {
- final Class extends ExternalProject> modelClazz = isPreview ? ExternalProjectPreview.class : ExternalProject.class;
- final ExternalProject externalRootProject = models.getExtraProject(null, modelClazz);
- if (externalRootProject == null) return Collections.emptyMap();
+ private static void extractExternalProjectModels(@NotNull ProjectImportAction.AllModels models,
+ @NotNull ProjectResolverContext resolverCtx) {
+ resolverCtx.setModels(models);
+ final Class extends ExternalProject> modelClazz = resolverCtx.isPreviewMode() ? ExternalProjectPreview.class : ExternalProject.class;
+ final ExternalProject externalRootProject = models.getExtraProject((IdeaModule)null, modelClazz);
+ if (externalRootProject == null) return;
final DefaultExternalProject wrappedExternalRootProject = new DefaultExternalProject(externalRootProject);
models.addExtraProject(wrappedExternalRootProject, ExternalProject.class);
- final Map externalProjectsMap = createExternalProjectsMap(wrappedExternalRootProject);
+ final Map externalProjectsMap = createExternalProjectsMap(null, wrappedExternalRootProject);
DomainObjectSet extends IdeaModule> gradleModules = models.getIdeaProject().getModules();
if (gradleModules != null && !gradleModules.isEmpty()) {
- List 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));
+ for (IdeaModule ideaModule : gradleModules) {
+ final ExternalProject externalProject = externalProjectsMap.get(getModuleId(resolverCtx, ideaModule));
if (externalProject != null) {
- models.addExtraProject(externalProject, ExternalProject.class, ideaModule);
+ models.addExtraProject(externalProject, ExternalProject.class, ideaModule.getGradleProject());
}
}
}
+ for (IdeaProject project : models.getIncludedBuilds()) {
+ DomainObjectSet extends IdeaModule> ideaModules = project.getModules();
+ if (ideaModules.isEmpty()) continue;
- return externalProjectsMap;
+ GradleProject gradleProject = ideaModules.getAt(0).getGradleProject();
+ while (gradleProject.getParent() != null) {
+ gradleProject = gradleProject.getParent();
+ }
+ final ExternalProject externalIncludedRootProject = models.getExtraProject(gradleProject, modelClazz);
+ if (externalIncludedRootProject == null) continue;
+ final DefaultExternalProject wrappedExternalIncludedRootProject = new DefaultExternalProject(externalIncludedRootProject);
+ wrappedExternalRootProject.getChildProjects().put(wrappedExternalIncludedRootProject.getName(), wrappedExternalIncludedRootProject);
+ models.addExtraProject(wrappedExternalIncludedRootProject, ExternalProject.class);
+ String compositePrefix = project.getName();
+ final Map externalIncludedProjectsMap =
+ createExternalProjectsMap(compositePrefix, wrappedExternalIncludedRootProject);
+ for (IdeaModule ideaModule : ideaModules) {
+ final ExternalProject externalProject = externalIncludedProjectsMap.get(getModuleId(resolverCtx, ideaModule));
+ if (externalProject != null) {
+ models.addExtraProject(externalProject, ExternalProject.class, ideaModule.getGradleProject());
+ }
+ }
+ }
}
- private static Map createExternalProjectsMap(@Nullable final ExternalProject rootExternalProject) {
+ private static Map createExternalProjectsMap(@Nullable String compositePrefix,
+ @Nullable final ExternalProject rootExternalProject) {
final Map externalProjectMap = ContainerUtilRt.newHashMap();
if (rootExternalProject == null) return externalProjectMap;
@@ -666,6 +694,9 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver compositeParticipants = new HashSet<>();
- for (Pair pair : pairs) {
- compositeParticipants.add(pair.second.toString());
- }
- if (compositeParticipants.isEmpty()) {
+ Pair[] compositeParticipants = myTree.getCheckedNodes(Pair.class, null);
+ if (compositeParticipants.length == 0) {
myCompositeRootSettings.setCompositeBuild(null);
}
else {
GradleProjectSettings.CompositeBuild compositeBuild = new GradleProjectSettings.CompositeBuild();
compositeBuild.setCompositeDefinitionSource(CompositeDefinitionSource.IDE);
- for (String participant : compositeParticipants) {
+ for (Pair participant : compositeParticipants) {
BuildParticipant buildParticipant = new BuildParticipant();
- buildParticipant.setRootPath(participant);
+ buildParticipant.setRootProjectName(participant.first.toString());
+ buildParticipant.setRootPath(participant.second.toString());
compositeBuild.getCompositeParticipants().add(buildParticipant);
}
myCompositeRootSettings.setCompositeBuild(compositeBuild);
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleCompositeImportingTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleCompositeImportingTest.java
index b8bf57004772..4d05583e1037 100644
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleCompositeImportingTest.java
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleCompositeImportingTest.java
@@ -15,6 +15,10 @@
*/
package org.jetbrains.plugins.gradle.importing;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider;
+import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl;
+import com.intellij.openapi.module.StdModuleTypes;
import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions;
import org.junit.Test;
@@ -80,4 +84,91 @@ public class GradleCompositeImportingTest extends GradleImportingTestCase {
assertModuleModuleDepScope("my-app_main", "string-utils_main", COMPILE);
assertModuleLibDepScope("my-app_main", "Gradle: org.apache.commons:commons-lang3:3.4", COMPILE);
}
+
+ @Test
+ @TargetVersions("3.3+")
+ public void testCompositeBuildWithProjectNameDuplicates() throws Exception {
+ IdeModifiableModelsProvider modelsProvider = new IdeModifiableModelsProviderImpl(myProject);
+ modelsProvider.newModule(getProjectPath() + "/api.iml", StdModuleTypes.JAVA.getId());
+ modelsProvider.newModule(getProjectPath() + "/my-app-api.iml", StdModuleTypes.JAVA.getId());
+ modelsProvider.newModule(getProjectPath() + "/my-app-api_main.iml", StdModuleTypes.JAVA.getId());
+ edt(() -> ApplicationManager.getApplication().runWriteAction(modelsProvider::commit));
+
+ createSettingsFile("rootProject.name='adhoc'\n" +
+ "\n" +
+ "includeBuild '../my-app'\n" +
+ "includeBuild '../my-utils'");
+
+ createProjectSubFile("../my-app/settings.gradle", "rootProject.name = 'my-app'\n" +
+ "include 'api'\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" +
+ "project(':api') {\n" +
+ " apply plugin: 'java'\n" +
+ " dependencies {\n" +
+ " compile 'commons-lang:commons-lang:2.6'\n" +
+ " }\n" +
+ "}\n");
+
+ createProjectSubFile("../my-utils/settings.gradle",
+ "rootProject.name = 'my-utils'\n" +
+ "include 'number-utils', 'string-utils', 'api'");
+ 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" +
+ "}\n" +
+ "project(':api') {\n" +
+ " dependencies {\n" +
+ " compile 'junit:junit:4.11'\n" +
+ " }\n" +
+ "}");
+
+ importProject();
+
+ assertModules("adhoc", "api", "api_main", "api_test",
+ "my-app", "my-app_main", "my-app_test",
+ "my-app-api", "my-app-api~1", "my-app-api_main",
+ "my-utils",
+ "string-utils", "string-utils_main", "string-utils_test",
+ "number-utils", "number-utils_main", "number-utils_test",
+ "my-utils-api", "my-utils-api_main", "my-utils-api_test");
+
+ String[] emptyModules =
+ new String[]{"api", "adhoc", "my-app", "my-app-api", "my-app-api_main", "my-app-api~1", "my-utils", "my-utils-api", "string-utils",
+ "number-utils"};
+ for (String rootModule : emptyModules) {
+ 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);
+
+ // my-app api project
+ assertModuleModuleDeps("api_main");
+ assertModuleLibDeps("api_main", "Gradle: commons-lang:commons-lang:2.6");
+ assertModuleLibDepScope("api_main", "Gradle: commons-lang:commons-lang:2.6", COMPILE);
+
+ assertModuleModuleDeps("my-utils-api_main");
+ //assertModuleLibDeps("my-utils-api_main", "Gradle: junit:junit:4.11");
+ assertModuleLibDepScope("my-utils-api_main", "Gradle: junit:junit:4.11", COMPILE);
+ //assertModuleLibDepScope("my-utils-api_main", "Gradle: org.hamcrest:hamcrest-core:1.3", COMPILE);
+ }
}
diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExternalProject.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExternalProject.java
index e8a3c449e953..40c22a1be611 100644
--- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExternalProject.java
+++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExternalProject.java
@@ -34,6 +34,9 @@ public interface ExternalProject extends Model, Serializable {
@NotNull
String getExternalSystemId();
+ @NotNull
+ String getId();
+
@NotNull
String getName();
diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
index afe2827ca764..b06bbcc7a3ed 100644
--- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
+++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
@@ -20,12 +20,12 @@ import org.gradle.tooling.BuildAction;
import org.gradle.tooling.BuildController;
import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter;
import org.gradle.tooling.internal.adapter.TargetTypeProvider;
+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;
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;
@@ -122,7 +122,7 @@ public class ProjectImportAction implements BuildAction {
+ public static class AllModels extends ModelsHolder {
private List includedBuilds = new ArrayList();
private boolean isGradleProjectDirSupported;
@@ -167,13 +167,27 @@ public class ProjectImportAction implements BuildAction T getExtraProject(@Nullable IdeaModule model, Class modelClazz) {
+ return super.getExtraProject(model != null ? model.getGradleProject() : null, modelClazz);
+ }
+
+ public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz, @Nullable IdeaModule subPropject) {
+ super.addExtraProject(project, modelClazz, subPropject != null ? subPropject.getGradleProject() : null);
+ }
+
+ @NotNull
+ protected String extractMapKey(Class modelClazz, @Nullable IdeaModule module) {
+ return extractMapKey(modelClazz, module);
+ }
+
@NotNull
@Override
- protected String extractMapKey(Class modelClazz, @Nullable IdeaModule module) {
- if (module != null) {
+ protected String extractMapKey(Class modelClazz, @Nullable GradleProject gradleProject) {
+ if (gradleProject != null) {
String id = isGradleProjectDirSupported ?
- module.getGradleProject().getProjectDirectory().getPath() :
- module.getGradleProject().getPath();
+ gradleProject.getProjectDirectory().getPath() :
+ gradleProject.getPath();
return modelClazz.getName() + '@' + id;
}
else {
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultExternalProject.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultExternalProject.java
index fd26ee43342e..7e59e7c5db58 100644
--- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultExternalProject.java
+++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultExternalProject.java
@@ -29,6 +29,8 @@ public class DefaultExternalProject implements ExternalProject, ExternalProjectP
private static final long serialVersionUID = 1L;
+ @NotNull
+ private String myId;
@NotNull
private String myName;
@NotNull
@@ -74,6 +76,7 @@ public class DefaultExternalProject implements ExternalProject, ExternalProjectP
public DefaultExternalProject(@NotNull ExternalProject externalProject) {
this();
+ myId = externalProject.getId();
myName = externalProject.getName();
myQName = externalProject.getQName();
myVersion = externalProject.getVersion();
@@ -109,6 +112,16 @@ public class DefaultExternalProject implements ExternalProject, ExternalProjectP
return myExternalSystemId;
}
+ @NotNull
+ @Override
+ public String getId() {
+ return myId;
+ }
+
+ public void setId(@NotNull String id) {
+ myId = id;
+ }
+
public void setExternalSystemId(@NotNull String externalSystemId) {
myExternalSystemId = externalSystemId;
}
@@ -271,6 +284,6 @@ public class DefaultExternalProject implements ExternalProject, ExternalProjectP
@Override
public String toString() {
- return "project '" + myQName + "'";
+ return "project '" + myId + "'";
}
}
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy
index 7510e7c4c7fe..c5fc91b32206 100644
--- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy
+++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy
@@ -82,7 +82,15 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
DefaultExternalProject defaultExternalProject = new DefaultExternalProject()
defaultExternalProject.externalSystemId = "GRADLE"
defaultExternalProject.name = project.name
- defaultExternalProject.QName = ":" == project.path ? project.name : project.path
+ def qName = ":" == project.path ? project.name : project.path
+ defaultExternalProject.QName = qName
+ final IdeaPlugin ideaPlugin = project.getPlugins().findPlugin(IdeaPlugin.class)
+ def ideaPluginModule = ideaPlugin?.model?.module
+ def parentBuildRootProject = project.gradle.parent?.rootProject
+ def compositePrefix = parentBuildRootProject && !project.rootProject.is(parentBuildRootProject) && ":" != project.path ?
+ (ideaPlugin?.model?.project?.name ?: project.rootProject.name) : "";
+ def ideaModuleName = ideaPluginModule?.name ?: project.name
+ defaultExternalProject.id = compositePrefix + (":" == project.path ? ideaModuleName : qName)
defaultExternalProject.version = wrap(project.version)
defaultExternalProject.description = project.description
defaultExternalProject.buildDir = project.buildDir