IDEA-352674 [Gradle|Sync] fix: added external module options configuration for module entities

GitOrigin-RevId: 5ab8a0240bf87991a9ff18e7b3b64450001a6342
This commit is contained in:
Sergei Vorobyov
2024-06-23 12:59:45 +02:00
committed by intellij-monorepo-bot
parent a395865398
commit d7410a737d
3 changed files with 176 additions and 31 deletions

View File

@@ -28,9 +28,11 @@ import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_SOURCE_ROOT_E
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_TEST_RESOURCE_ROOT_ENTITY_TYPE_ID
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_TEST_ROOT_ENTITY_TYPE_ID
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.plugins.gradle.model.ExternalProject
import org.jetbrains.plugins.gradle.model.ExternalSourceSet
import org.jetbrains.plugins.gradle.model.GradleLightProject
import org.jetbrains.plugins.gradle.model.GradleSourceSetModel
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil.getModuleId
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
import org.jetbrains.plugins.gradle.service.syncAction.GradleSyncContributor
import org.jetbrains.plugins.gradle.service.syncAction.GradleSyncProjectConfigurator.project
@@ -38,6 +40,7 @@ import org.jetbrains.plugins.gradle.service.syncContributor.entitites.GradleBuil
import org.jetbrains.plugins.gradle.service.syncContributor.entitites.GradleLinkedProjectEntitySource
import org.jetbrains.plugins.gradle.service.syncContributor.entitites.GradleProjectEntitySource
import org.jetbrains.plugins.gradle.service.syncContributor.entitites.GradleSourceSetEntitySource
import org.jetbrains.plugins.gradle.util.GradleConstants
import java.nio.file.Path
import kotlin.io.path.exists
@@ -85,6 +88,7 @@ class GradleSourceRootSyncContributor : GradleSyncContributor {
val projectRootUrl = projectRootPath.toVirtualFileUrl(virtualFileUrlManager)
val projectEntitySource = GradleProjectEntitySource(buildEntitySource, projectRootUrl)
val externalProject = context.getProjectModel(projectModel, ExternalProject::class.java) ?: continue
val sourceSetModel = context.getProjectModel(projectModel, GradleSourceSetModel::class.java) ?: continue
val projectModuleEntity = moduleEntities.singleOrNull { isProjectModuleEntity(it, projectEntitySource) } ?: continue
@@ -93,7 +97,7 @@ class GradleSourceRootSyncContributor : GradleSyncContributor {
val sourceSetEntitySource = GradleSourceSetEntitySource(projectEntitySource, sourceSet.name)
val contentRoots = resolveContentRoots(virtualFileUrlManager, projectModel, sourceSet, contentRootWeightMap)
val sourceRootData = GradleSourceRootData(sourceSet, projectModuleEntity, sourceSetEntitySource, contentRoots)
val sourceRootData = GradleSourceRootData(externalProject, sourceSet, projectModuleEntity, sourceSetEntitySource, contentRoots)
if (moduleEntities.any { isConflictedModuleEntity(it, sourceRootData) }) {
continue
@@ -111,7 +115,7 @@ class GradleSourceRootSyncContributor : GradleSyncContributor {
checkCanceled()
configureSourceRoot(storage, virtualFileUrlManager, sourceRootData)
configureSourceRoot(context, storage, virtualFileUrlManager, sourceRootData)
}
}
@@ -146,11 +150,13 @@ class GradleSourceRootSyncContributor : GradleSyncContributor {
}
private fun configureSourceRoot(
context: ProjectResolverContext,
storage: MutableEntityStorage,
virtualFileUrlManager: VirtualFileUrlManager,
sourceRootData: GradleSourceRootData,
) {
val moduleEntity = addModuleEntity(storage, sourceRootData)
addExModuleOptionsEntity(context, storage, moduleEntity, sourceRootData)
val contentRootEntities = addContentRootEntities(storage, sourceRootData, moduleEntity)
addSourceRootEntities(storage, virtualFileUrlManager, sourceRootData, contentRootEntities)
}
@@ -175,6 +181,32 @@ class GradleSourceRootSyncContributor : GradleSyncContributor {
return moduleEntity
}
private fun addExModuleOptionsEntity(
context: ProjectResolverContext,
storage: MutableEntityStorage,
moduleEntity: ModuleEntity.Builder,
sourceRootData: GradleSourceRootData,
) {
val externalProject = sourceRootData.externalProject
val sourceSet = sourceRootData.sourceSet
val entitySource = sourceRootData.entitySource
storage addEntity ExternalSystemModuleOptionsEntity(
entitySource = entitySource
) {
module = moduleEntity
externalSystem = GradleConstants.SYSTEM_ID.id
linkedProjectId = getModuleId(context, externalProject, sourceSet)
linkedProjectPath = externalProject.projectDir.path
rootProjectPath = context.projectPath
externalSystemModuleGroup = externalProject.group
externalSystemModuleVersion = externalProject.version
externalSystemModuleType = GradleConstants.GRADLE_SOURCE_SET_MODULE_TYPE_KEY
}
}
private fun addContentRootEntities(
storage: MutableEntityStorage,
sourceRootData: GradleSourceRootData,
@@ -393,6 +425,7 @@ class GradleSourceRootSyncContributor : GradleSyncContributor {
}
private class GradleSourceRootData(
val externalProject: ExternalProject,
val sourceSet: ExternalSourceSet,
val projectModuleEntity: ModuleEntity,
val entitySource: GradleSourceSetEntitySource,

View File

@@ -29,10 +29,7 @@ import org.gradle.api.artifacts.Dependency;
import org.gradle.tooling.model.BuildIdentifier;
import org.gradle.tooling.model.GradleProject;
import org.gradle.tooling.model.idea.IdeaModule;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.*;
import org.jetbrains.plugins.gradle.DefaultExternalDependencyId;
import org.jetbrains.plugins.gradle.ExternalDependencyId;
import org.jetbrains.plugins.gradle.issue.UnresolvedDependencySyncIssue;
@@ -255,45 +252,78 @@ public final class GradleProjectResolverUtil {
return GradleUtil.getConfigPath(gradleModule.getGradleProject(), rootProjectPath);
}
@NotNull
public static String getModuleId(@NotNull ProjectResolverContext resolverCtx, @NotNull IdeaModule gradleModule) {
ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class);
public static @NotNull String getModuleId(
@NotNull ProjectResolverContext context,
@NotNull IdeaModule gradleModule
) {
ExternalProject externalProject = getExternalProject(context, gradleModule);
return getModuleId(context, externalProject);
}
public static @NotNull String getModuleId(
@NotNull ProjectResolverContext context,
@NotNull IdeaModule gradleModule,
@NotNull ExternalSourceSet sourceSet
) {
ExternalProject externalProject = getExternalProject(context, gradleModule);
return getModuleId(context, externalProject, sourceSet);
}
private static @NotNull ExternalProject getExternalProject(
@NotNull ProjectResolverContext context,
@NotNull IdeaModule gradleModule
) {
ExternalProject externalProject = context.getProjectModel(gradleModule, ExternalProject.class);
if (externalProject == null) {
throw new IllegalStateException(
"Missing " + ExternalProject.class.getSimpleName() + " for " + gradleModule.getGradleProject().getPath()
"Missing " + ExternalProject.class.getSimpleName() + " for " + gradleModule.getProjectIdentifier().getProjectPath()
);
}
if (!StringUtil.isEmpty(resolverCtx.getBuildSrcGroup())) {
return resolverCtx.getBuildSrcGroup() + ":" + getModuleId(externalProject);
return externalProject;
}
public static @NotNull String getModuleId(
@NotNull ProjectResolverContext context,
@NotNull ExternalProject externalProject,
@NotNull ExternalSourceSet sourceSet
) {
String mainModuleId = getModuleId(context, externalProject);
return mainModuleId + ":" + sourceSet.getName();
}
public static @NotNull String getModuleId(
@NotNull ProjectResolverContext context,
@NotNull ExternalProject externalProject
) {
if (!StringUtil.isEmpty(context.getBuildSrcGroup())) {
return context.getBuildSrcGroup() + ":" + getModuleId(externalProject);
}
return getModuleId(externalProject);
}
@NotNull
public static String getModuleId(String gradlePath, String moduleName) {
return StringUtil.isEmpty(gradlePath) || ":".equals(gradlePath) ? moduleName : gradlePath;
private static @NotNull String getModuleId(
@NotNull ExternalProject externalProject
) {
String moduleName = externalProject.getName();
String gradlePath = externalProject.getIdentityPath();
if (StringUtil.isEmpty(gradlePath)) {
return moduleName;
}
if (":".equals(gradlePath)) {
return moduleName;
}
return gradlePath;
}
@NotNull
public static String getModuleId(@NotNull ExternalProject externalProject) {
return getModuleId(externalProject.getIdentityPath(), externalProject.getName());
}
@NotNull
public static String getModuleId(@NotNull ExternalProject externalProject, @NotNull ExternalSourceSet sourceSet) {
@TestOnly
public static @NotNull String getModuleId(
@NotNull ExternalProject externalProject,
@NotNull ExternalSourceSet sourceSet
) {
String mainModuleId = getModuleId(externalProject);
return mainModuleId + ":" + sourceSet.getName();
}
@NotNull
public static String getModuleId(@NotNull ProjectResolverContext resolverCtx,
@NotNull IdeaModule gradleModule,
@NotNull ExternalSourceSet sourceSet) {
String mainModuleId = getModuleId(resolverCtx, gradleModule);
return mainModuleId + ":" + sourceSet.getName();
}
@NotNull
public static String getModuleId(@NotNull ExternalProjectDependency projectDependency) {
DependencyScope dependencyScope = getDependencyScope(projectDependency.getScope());

View File

@@ -14,14 +14,17 @@ import com.intellij.platform.workspace.storage.MutableEntityStorage
import com.intellij.platform.workspace.storage.entities
import com.intellij.platform.workspace.storage.impl.url.toVirtualFileUrl
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.plugins.gradle.model.ExternalProject
import org.jetbrains.plugins.gradle.model.GradleLightBuild
import org.jetbrains.plugins.gradle.model.GradleLightProject
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil.getModuleId
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
import org.jetbrains.plugins.gradle.service.syncAction.GradleSyncContributor
import org.jetbrains.plugins.gradle.service.syncAction.GradleSyncProjectConfigurator.project
import org.jetbrains.plugins.gradle.service.syncContributor.entitites.GradleBuildEntitySource
import org.jetbrains.plugins.gradle.service.syncContributor.entitites.GradleLinkedProjectEntitySource
import org.jetbrains.plugins.gradle.service.syncContributor.entitites.GradleProjectEntitySource
import org.jetbrains.plugins.gradle.util.GradleConstants
import java.nio.file.Path
@ApiStatus.Internal
@@ -39,6 +42,9 @@ class GradleContentRootSyncContributor : GradleSyncContributor {
if (phase == GradleModelFetchPhase.PROJECT_LOADED_PHASE) {
configureProjectContentRoots(context, storage)
}
if (phase == GradleModelFetchPhase.PROJECT_MODEL_PHASE) {
configureExModuleOptions(context, storage)
}
}
}
@@ -215,4 +221,80 @@ class GradleContentRootSyncContributor : GradleSyncContributor {
val projectModel: GradleLightProject,
val entitySource: GradleProjectEntitySource,
)
private suspend fun configureExModuleOptions(
context: ProjectResolverContext,
storage: MutableEntityStorage,
) {
val project = context.project()
val virtualFileUrlManager = project.workspaceModel.getVirtualFileUrlManager()
val exModuleOptionsToAdd = LinkedHashMap<GradleProjectEntitySource, GradleExModuleOptionsData>()
val moduleEntities = storage.entities<ModuleEntity>()
val linkedProjectRootPath = Path.of(context.projectPath)
val linkedProjectRootUrl = linkedProjectRootPath.toVirtualFileUrl(virtualFileUrlManager)
val linkedProjectEntitySource = GradleLinkedProjectEntitySource(linkedProjectRootUrl)
for (buildModel in context.allBuilds) {
val buildRootPath = buildModel.buildIdentifier.rootDir.toPath()
val buildRootUrl = buildRootPath.toVirtualFileUrl(virtualFileUrlManager)
val buildEntitySource = GradleBuildEntitySource(linkedProjectEntitySource, buildRootUrl)
for (projectModel in buildModel.projects) {
checkCanceled()
val projectRootPath = projectModel.projectDirectory.toPath()
val projectRootUrl = projectRootPath.toVirtualFileUrl(virtualFileUrlManager)
val projectEntitySource = GradleProjectEntitySource(buildEntitySource, projectRootUrl)
val moduleEntity = moduleEntities.find { it.entitySource == projectEntitySource } ?: continue
val externalProject = context.getProjectModel(projectModel, ExternalProject::class.java) ?: continue
val exModuleOptionsData = GradleExModuleOptionsData(externalProject, projectEntitySource, moduleEntity)
exModuleOptionsToAdd[projectEntitySource] = exModuleOptionsData
}
}
for (exModuleOptionsData in exModuleOptionsToAdd.values) {
checkCanceled()
configureExModuleOptionsEntity(context, storage, exModuleOptionsData)
}
}
private fun configureExModuleOptionsEntity(
context: ProjectResolverContext,
storage: MutableEntityStorage,
exModuleOptionsData: GradleExModuleOptionsData,
) {
val externalProject = exModuleOptionsData.externalProject
val entitySource = exModuleOptionsData.entitySource
val moduleEntity = exModuleOptionsData.moduleEntity
storage.modifyModuleEntity(moduleEntity) {
exModuleOptions = ExternalSystemModuleOptionsEntity(
entitySource = entitySource
) {
externalSystem = GradleConstants.SYSTEM_ID.id
linkedProjectId = getModuleId(context, externalProject)
linkedProjectPath = externalProject.projectDir.path
rootProjectPath = context.projectPath
externalSystemModuleGroup = externalProject.group
externalSystemModuleVersion = externalProject.version
externalSystemModuleType = GradleConstants.GRADLE_SOURCE_SET_MODULE_TYPE_KEY
}
}
}
private class GradleExModuleOptionsData(
val externalProject: ExternalProject,
val entitySource: GradleProjectEntitySource,
val moduleEntity: ModuleEntity,
)
}