Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.intellij.openapi.util.text.Strings;
import com.intellij.platform.workspace.jps.entities.ModuleId;
import com.intellij.platform.workspace.storage.EntityStorage;
import com.intellij.platform.workspace.storage.ImmutableEntityStorage;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.PathUtilRt;
import com.intellij.util.SmartList;
Expand Down Expand Up @@ -199,6 +200,27 @@ public static String getDefaultModuleTypeId() {
@NotNull ExternalProject externalProject,
@Nullable String sourceSetName,
@NotNull ProjectResolverContext resolverCtx) {
if (resolverCtx.isPhasedSyncEnabled()) {
if (sourceSetName == null) {
return getHolderModuleName(
resolverCtx,
gradleModule.getGradleProject().getProjectIdentifier().getBuildIdentifier().getRootDir().toPath(),
// Build name is derived from the root project's name
getRootProject(gradleModule.getGradleProject()).getName(),
externalProject
);
} else {
return resolveSourceSetModuleName(
resolverCtx,
gradleModule.getGradleProject().getProjectIdentifier().getBuildIdentifier().getRootDir().toPath(),
// Build name is derived from the root project's name
getRootProject(gradleModule.getGradleProject()).getName(),
externalProject,
sourceSetName
);
}
}

String delimiter;
StringBuilder moduleName = new StringBuilder();
String rootName = gradleModule.getProject().getName();
Expand Down Expand Up @@ -240,11 +262,25 @@ public static String getDefaultModuleTypeId() {
@NotNull GradleLightProject projectModel,
// TODO: replace with GradleLightProject#identityPath
@NotNull ExternalProject externalProject
) {
return getHolderModuleName(
context,
projectModel.getBuild().getBuildIdentifier().getRootDir().toPath(),
projectModel.getBuild().getName(),
externalProject
);
}

private static @NotNull String getHolderModuleName(
@NotNull ProjectResolverContext context,
@NotNull Path buildPath,
@NotNull String buildName,
// TODO: replace with GradleLightProject#identityPath
@NotNull ExternalProject externalProject
) {
var rootBuildPath = context.getRootBuild().getBuildIdentifier().getRootDir().toPath();
var rootBuildName = context.getRootBuild().getName();
var buildPath = projectModel.getBuild().getBuildIdentifier().getRootDir().toPath();
var buildName = projectModel.getBuild().getName();

var identityPath = externalProject.getIdentityPath();

var moduleName = Strings.trimStart(identityPath, ":");
Expand Down Expand Up @@ -285,16 +321,32 @@ public static String getDefaultModuleTypeId() {
@NotNull ExternalProject externalProject,
@NotNull String sourceSetName
) {
var holderModuleName = getHolderModuleName(context, projectModel, externalProject);
var sourceSetModuleName = holderModuleName + "." + escapeModuleNameElement(sourceSetName);

var sourceSetModuleName = resolveSourceSetModuleName(
context,
projectModel.getBuild().getBuildIdentifier().getRootDir().toPath(),
projectModel.getBuild().getName(),
externalProject,
sourceSetName
);
if (storage.contains(new ModuleId(sourceSetModuleName))) {
// Related issue: IDEA-169388
// The user can create the 'test' holder module that conflicts with the `test` source set module.
return sourceSetModuleName + "~1";
} else {
return sourceSetModuleName;
}
}

return sourceSetModuleName;
private static @NotNull String resolveSourceSetModuleName(
@NotNull ProjectResolverContext context,
@NotNull Path buildPath,
@NotNull String buildName,
// TODO: replace with GradleLightProject#identityPath
@NotNull ExternalProject externalProject,
@NotNull String sourceSetName
) {
var holderModuleName = getHolderModuleName(context, buildPath, buildName, externalProject);
return holderModuleName + "." + escapeModuleNameElement(sourceSetName);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ package org.jetbrains.plugins.gradle.importing.syncAction
import com.intellij.gradle.toolingExtension.modelAction.GradleModelFetchPhase
import com.intellij.openapi.observable.operation.OperationExecutionStatus
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.modules
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.use
import com.intellij.platform.testFramework.assertion.WorkspaceAssertions
import com.intellij.platform.testFramework.assertion.collectionAssertion.CollectionAssertions
import com.intellij.platform.testFramework.assertion.listenerAssertion.ListenerAssertion
import com.intellij.platform.workspace.storage.toBuilder
import kotlinx.coroutines.delay
Expand All @@ -22,6 +24,7 @@ import org.jetbrains.plugins.gradle.util.entity.GradleTestEntityId
import org.jetbrains.plugins.gradle.util.entity.GradleTestEntitySource
import org.jetbrains.plugins.gradle.util.whenExternalSystemTaskFinished
import org.jetbrains.plugins.gradle.util.whenExternalSystemTaskStarted
import org.junit.Assume
import org.junit.Test
import org.junit.jupiter.api.Assertions
import java.util.concurrent.CopyOnWriteArrayList
Expand All @@ -30,6 +33,40 @@ import kotlin.time.Duration.Companion.seconds

class GradlePhasedSyncTest : GradlePhasedSyncTestCase() {

@Test
fun `test module naming`() {
var moduleNamesAtTheEndOfSyncContributors: Set<String>? = null
whenModelFetchCompleted(testRootDisposable) {
moduleNamesAtTheEndOfSyncContributors = myProject.modules.map { it.name }.toSet()
}

initMultiModuleProject()
importProject()
assertMultiModuleProjectStructure()

assertNotNull("Module names at the end of sync contributors not initialized!", moduleNamesAtTheEndOfSyncContributors)

CollectionAssertions.assertEqualsUnordered(moduleNamesAtTheEndOfSyncContributors, myProject.modules.map { it.name }.toSet())
}


@Test
fun `test module naming consistency with duplicated included project names`() {
Assume.assumeTrue(isGradleAtLeast("6.1")) // Gradle < 6.0 fails in such a case
var moduleNamesAtTheEndOfSyncContributors: Set<String>? = null
whenModelFetchCompleted(testRootDisposable) {
moduleNamesAtTheEndOfSyncContributors = myProject.modules.map { it.name }.toSet()
}

initMultiModuleProject(includeProjectsWithDuplicatedNames = true)
importProject()
assertMultiModuleProjectStructure(includeProjectsWithDuplicatedNames = true)

assertNotNull("Module names at the end of sync contributors not initialized!", moduleNamesAtTheEndOfSyncContributors)

CollectionAssertions.assertEqualsUnordered(moduleNamesAtTheEndOfSyncContributors, myProject.modules.map { it.name }.toSet())
}

@Test
fun `test Gradle model fetch phase completion`() {
Disposer.newDisposable().use { disposable ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ abstract class GradleProjectResolverTestCase : GradleImportingTestCase() {
*
* @see assertMultiModuleProjectStructure
*/
fun initMultiModuleProject(useBuildSrc: Boolean = isGradleAtLeast("8.0")) {
fun initMultiModuleProject(useBuildSrc: Boolean = isGradleAtLeast("8.0"), includeProjectsWithDuplicatedNames: Boolean = false) {
if (useBuildSrc) {
createBuildFile("buildSrc") {
withPlugin("groovy")
Expand All @@ -124,25 +124,50 @@ abstract class GradleProjectResolverTestCase : GradleImportingTestCase() {
}
}
createSettingsFile {
setProjectName("project")
setProjectName("rootProjectName")
include("module")
includeBuild("../includedProject")
if (includeProjectsWithDuplicatedNames) {
includeBuild("../includedProject2")
}
}
createBuildFile {
withJavaPlugin()
}
createBuildFile("module") {
withJavaPlugin()
addGroup("moduleGroup")
addVersion("1.0")
}
createSettingsFile("../includedProject") {
setProjectName("includedProject")
setProjectName("includedProjectName")
include("module")
}
createBuildFile("../includedProject") {
withJavaPlugin()
addGroup("includedProjectGroup")
addVersion("1.0")
}
createBuildFile("../includedProject/module") {
withJavaPlugin()
addGroup("includedProjectModuleGroup")
addVersion("1.0")
}
if (includeProjectsWithDuplicatedNames) {
createSettingsFile("../includedProject2") {
setProjectName("includedProjectName")
include("module2")
}
createBuildFile("../includedProject2") {
withJavaPlugin()
addGroup("includedProject2Group")
addVersion("1.0")
}
createBuildFile("../includedProject2/module2") {
withJavaPlugin()
addGroup("includedProject2ModuleGroup")
addVersion("1.0")
}
}
}

Expand All @@ -153,26 +178,41 @@ abstract class GradleProjectResolverTestCase : GradleImportingTestCase() {
* The IDEA syncs a project with build src in two sequent Gradle calls.
* Therefore, by default, we don't use buildSrc for the model project.
*
* @param includeProjectsWithDuplicatedNames whether to add any projects with duplicated names.
* This is used to test naming of the modules in those cases.
*
* @see initMultiModuleProject
*/
fun assertMultiModuleProjectStructure(useBuildSrc: Boolean = isGradleAtLeast("8.0")) {
fun assertMultiModuleProjectStructure(
useBuildSrc: Boolean = isGradleAtLeast("8.0"),
includeProjectsWithDuplicatedNames: Boolean = false
) {
val buildSrcModules = listOf(
"project.buildSrc", "project.buildSrc.main", "project.buildSrc.test"
"rootProjectName.buildSrc", "rootProjectName.buildSrc.main", "rootProjectName.buildSrc.test"
)
val projectModules = listOf(
"project", "project.main", "project.test",
"project.module", "project.module.main", "project.module.test"
"rootProjectName", "rootProjectName.main", "rootProjectName.test",
"rootProjectName.module", "rootProjectName.module.main", "rootProjectName.module.test"
)
// Naming semantics change after Gradle 6.0, so need to account for it
val includedProjectName = if(isGradleAtLeast("6.0")) "includedProject" else "includedProjectName"
val includesProjectModules = listOf(
"includedProject", "includedProject.main", "includedProject.test",
"includedProject.module", "includedProject.module.main", "includedProject.module.test"
includedProjectName, "$includedProjectName.main", "$includedProjectName.test",
"$includedProjectName.module", "$includedProjectName.module.main", "$includedProjectName.module.test"
)
val includesProject2Modules = listOf(
"includedProject2", "includedProject2.main", "includedProject2.test",
"includedProject2.module2", "includedProject2.module2.main", "includedProject2.module2.test"
)
assertModules(buildList {
if (useBuildSrc) {
addAll(buildSrcModules)
}
addAll(projectModules)
addAll(includesProjectModules)
if (includeProjectsWithDuplicatedNames) {
addAll(includesProject2Modules)
}
})
}

Expand Down