mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[gradle] for Gradle 8.0, process buildSrc builds in main resolver call IDEA-313748
GitOrigin-RevId: 5a4e66b803ac5d95e3a75af72c10ef36299e4ce1
This commit is contained in:
committed by
intellij-monorepo-bot
parent
bc682fe448
commit
1fa206f78c
@@ -261,6 +261,54 @@ class GradleBuildSrcImportingTest : GradleImportingTestCase() {
|
||||
"build2.buildSrc", "build2.buildSrc.main", "build2.buildSrc.test")
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Builds inclusion and buildSrc presence graph
|
||||
|
||||
A--> B--> D--> buildSrc
|
||||
| └--> buildSrc
|
||||
|
|
||||
└--> C--> D--> buildSrc
|
||||
└--> buildSrc
|
||||
*/
|
||||
@Test
|
||||
@TargetVersions("8.0+")
|
||||
fun `test buildSrc in a composite with build names duplication`() {
|
||||
createSettingsFile("""
|
||||
rootProject.name = "A"
|
||||
includeBuild("B")
|
||||
includeBuild("C")
|
||||
""".trimIndent())
|
||||
|
||||
createProjectSubFile("B/settings.gradle", """
|
||||
rootProject.name = "B"
|
||||
includeBuild("D")
|
||||
""".trimIndent())
|
||||
|
||||
createProjectSubFile("B/buildSrc/settings.gradle", "")
|
||||
|
||||
createProjectSubFile("B/D/settings.gradle", "rootProject.name = 'D'")
|
||||
createProjectSubFile("B/D/buildSrc/settings.gradle", "")
|
||||
|
||||
|
||||
createProjectSubFile("C/settings.gradle", """
|
||||
rootProject.name = "C"
|
||||
includeBuild("D")
|
||||
""".trimIndent())
|
||||
|
||||
createProjectSubFile("C/buildSrc/settings.gradle", "")
|
||||
|
||||
createProjectSubFile("C/D/settings.gradle", "rootProject.name = 'D'")
|
||||
createProjectSubFile("C/D/buildSrc/settings.gradle", "")
|
||||
|
||||
importProject("")
|
||||
assertModules("A", "B", "C", "D", "C.D",
|
||||
"B.buildSrc", "B.buildSrc.main", "B.buildSrc.test",
|
||||
"C.buildSrc", "C.buildSrc.main", "C.buildSrc.test",
|
||||
"D.buildSrc", "D.buildSrc.main", "D.buildSrc.test",
|
||||
"C.D.buildSrc", "C.D.buildSrc.main", "C.D.buildSrc.test")
|
||||
}
|
||||
|
||||
private fun assertBuildScriptClassPathContains(moduleName: String, expectedEntries: Collection<VirtualFile>) {
|
||||
val module = ModuleManager.getInstance(myProject).findModuleByName(moduleName)
|
||||
val modulePath = ExternalSystemApiUtil.getExternalProjectPath(module)
|
||||
|
||||
+15
@@ -18,6 +18,7 @@ import org.gradle.tooling.model.idea.IdeaModule;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.model.Build;
|
||||
import org.jetbrains.plugins.gradle.model.ProjectImportAction;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
|
||||
|
||||
@@ -201,6 +202,20 @@ public class DefaultProjectResolverContext extends UserDataHolderBase implements
|
||||
return myBuildSrcGroup;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getBuildSrcGroup(@NotNull IdeaModule module) {
|
||||
if (!"buildSrc".equals(module.getProject().getName())) {
|
||||
return myBuildSrcGroup;
|
||||
}
|
||||
String parentRootDir = module.getGradleProject().getProjectIdentifier().getBuildIdentifier().getRootDir().getParent();
|
||||
return getModels().getAllBuilds().stream()
|
||||
.filter(b -> b.getBuildIdentifier().getRootDir().toString().equals(parentRootDir))
|
||||
.findFirst()
|
||||
.map(Build::getName)
|
||||
.orElse(myBuildSrcGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report(@NotNull MessageEvent.Kind kind, @NotNull BuildIssue buildIssue) {
|
||||
BuildIssueEventImpl buildIssueEvent = new BuildIssueEventImpl(myExternalSystemTaskId, buildIssue, kind);
|
||||
|
||||
+54
-3
@@ -47,6 +47,7 @@ import org.jetbrains.plugins.gradle.execution.target.TargetBuildLauncher;
|
||||
import org.jetbrains.plugins.gradle.issue.DeprecatedGradleVersionIssue;
|
||||
import org.jetbrains.plugins.gradle.model.*;
|
||||
import org.jetbrains.plugins.gradle.model.data.BuildParticipant;
|
||||
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData;
|
||||
import org.jetbrains.plugins.gradle.model.data.CompositeBuildData;
|
||||
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData;
|
||||
import org.jetbrains.plugins.gradle.remote.impl.GradleLibraryNamesMixer;
|
||||
@@ -57,8 +58,10 @@ import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -156,9 +159,12 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
getProjectDataFunction(resolverContext, projectResolverChain, false));
|
||||
|
||||
// auto-discover buildSrc projects of the main and included builds
|
||||
File gradleUserHome = resolverContext.getUserData(GRADLE_HOME_DIR);
|
||||
new GradleBuildSrcProjectsResolver(this, resolverContext, gradleUserHome, settings, listener, syncTaskId, projectResolverChain)
|
||||
.discoverAndAppendTo(projectDataNode);
|
||||
if (GradleVersion.version(resolverContext.getProjectGradleVersion()).compareTo(GradleVersion.version("8.0")) < 0) {
|
||||
File gradleUserHome = resolverContext.getUserData(GRADLE_HOME_DIR);
|
||||
new GradleBuildSrcProjectsResolver(this, resolverContext, gradleUserHome, settings, listener, syncTaskId, projectResolverChain)
|
||||
.discoverAndAppendTo(projectDataNode);
|
||||
}
|
||||
|
||||
return projectDataNode;
|
||||
}
|
||||
finally {
|
||||
@@ -488,6 +494,8 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
mergeLibraryAndModuleDependencyData(resolverCtx, projectDataNode, resolverCtx.getGradleUserHome(), gradleHomeDir, gradleVersion);
|
||||
}
|
||||
|
||||
processBuildSrcModules(resolverCtx, projectDataNode);
|
||||
|
||||
for (GradleProjectResolverExtension resolver = tracedResolverChain; resolver != null; resolver = resolver.getNext()) {
|
||||
resolver.resolveFinished(projectDataNode);
|
||||
}
|
||||
@@ -503,6 +511,49 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
|
||||
return projectDataNode;
|
||||
}
|
||||
|
||||
private static void processBuildSrcModules(DefaultProjectResolverContext ctx, DataNode<ProjectData> projectDataNode) {
|
||||
// since Gradle 8.0 buildSrc are available as composite build members
|
||||
DataNode<CompositeBuildData> compositeNode = find(projectDataNode, CompositeBuildData.KEY);
|
||||
if (compositeNode == null) return;
|
||||
|
||||
GradleBuildSrcProjectsResolver.Index index = GradleBuildSrcProjectsResolver.prepareIndexes(projectDataNode);
|
||||
|
||||
CompositeBuildData compositeBuildData = compositeNode.getData();
|
||||
for (BuildParticipant participant : compositeBuildData.getCompositeParticipants()) {
|
||||
if (participant.getRootProjectName().endsWith("buildSrc")) {
|
||||
Set<String> buildSrcProjectPaths = participant.getProjects();
|
||||
|
||||
@NotNull Collection<DataNode<BuildScriptClasspathData>> buildClasspathNodes =
|
||||
index.buildClasspathNodesMap().get(Path.of(participant.getRootPath()).getParent());
|
||||
|
||||
@NotNull Map<String, DataNode<? extends ModuleData>> buildSrcModules = new HashMap<>();
|
||||
@Nullable AtomicReference<DataNode<? extends ModuleData>> buildSrcModuleNode = new AtomicReference<>();
|
||||
|
||||
findAll(projectDataNode, ProjectKeys.MODULE).stream()
|
||||
.filter(node -> buildSrcProjectPaths.contains(node.getData().getLinkedExternalProjectPath()))
|
||||
.forEach(node -> {
|
||||
buildSrcModules.put(node.getData().getId(), node);
|
||||
findAll(node, GradleSourceSetData.KEY).forEach(
|
||||
sourceSetNode -> buildSrcModules.put(sourceSetNode.getData().getId(), sourceSetNode));
|
||||
|
||||
if (participant.getRootPath().equals(node.getData().getLinkedExternalProjectPath())) {
|
||||
if (ctx.isResolveModulePerSourceSet()) {
|
||||
buildSrcModuleNode.set(findChild(node, GradleSourceSetData.KEY,
|
||||
sourceSetNode -> sourceSetNode.getData().getExternalName().endsWith(":main")));
|
||||
}
|
||||
else {
|
||||
buildSrcModuleNode.set(node);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
GradleBuildSrcProjectsResolver.addBuildSrcToBuildScriptClasspathData(buildClasspathNodes,
|
||||
buildSrcModules,
|
||||
buildSrcModuleNode.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isCustomSerializationSupported(@NotNull DefaultProjectResolverContext resolverCtx,
|
||||
GradleVersion gradleVersion,
|
||||
boolean isCompositeBuildsSupported) {
|
||||
|
||||
+68
-16
@@ -177,7 +177,7 @@ public final class GradleProjectResolverUtil {
|
||||
@NotNull ProjectResolverContext resolverCtx) {
|
||||
String delimiter;
|
||||
StringBuilder moduleName = new StringBuilder();
|
||||
String buildSrcGroup = resolverCtx.getBuildSrcGroup();
|
||||
String buildSrcGroup = resolverCtx.getBuildSrcGroup(gradleModule);
|
||||
if (resolverCtx.isUseQualifiedModuleNames()) {
|
||||
delimiter = ".";
|
||||
if (StringUtil.isNotEmpty(buildSrcGroup)) {
|
||||
@@ -228,8 +228,16 @@ public final class GradleProjectResolverUtil {
|
||||
String gradlePath = projectIdentifier.getProjectPath();
|
||||
String compositePrefix = "";
|
||||
boolean isRootPath = StringUtil.isEmpty(gradlePath) || ":".equals(gradlePath);
|
||||
|
||||
if (GradleVersion.version(resolverCtx.getProjectGradleVersion()).compareTo(GradleVersion.version("8.0")) >= 0) {
|
||||
if (build != resolverCtx.getModels().getMainBuild() || isRootPath) {
|
||||
compositePrefix = buildCompositePrefixFromBuildNames(resolverCtx, build.getBuildIdentifier());
|
||||
}
|
||||
return compositePrefix + (StringUtil.isEmpty(gradlePath) || ":".equals(gradlePath) ? "" : gradlePath);
|
||||
}
|
||||
|
||||
if (!isRootPath && build != resolverCtx.getModels().getMainBuild()) {
|
||||
compositePrefix = buildCompositePrefixFromBuildNames(resolverCtx, build.getBuildIdentifier());
|
||||
compositePrefix = build.getName();
|
||||
} else if (!StringUtil.isEmpty(resolverCtx.getBuildSrcGroup())) {
|
||||
compositePrefix = resolverCtx.getBuildSrcGroup() + (isRootPath ? ":" : ":buildSrc");
|
||||
}
|
||||
@@ -244,9 +252,15 @@ public final class GradleProjectResolverUtil {
|
||||
IdeaProject ideaProject = gradleModule.getProject();
|
||||
boolean isRootPath = StringUtil.isEmpty(gradlePath) || ":".equals(gradlePath);
|
||||
|
||||
if (GradleVersion.version(resolverCtx.getProjectGradleVersion()).compareTo(GradleVersion.version("8.0")) >= 0) {
|
||||
if (ideaProject != resolverCtx.getModels().getModel(IdeaProject.class) || isRootPath) {
|
||||
compositePrefix = buildCompositePrefixFromBuildNames(resolverCtx, gradleProject.getProjectIdentifier().getBuildIdentifier());
|
||||
}
|
||||
return compositePrefix + (StringUtil.isEmpty(gradlePath) || ":".equals(gradlePath) ? "" : gradlePath);
|
||||
}
|
||||
|
||||
if (!isRootPath && ideaProject != resolverCtx.getModels().getModel(IdeaProject.class)) {
|
||||
BuildIdentifier buildId = gradleModule.getGradleProject().getProjectIdentifier().getBuildIdentifier();
|
||||
compositePrefix = buildCompositePrefixFromBuildNames(resolverCtx, buildId);
|
||||
compositePrefix = ideaProject.getName();
|
||||
} else if (!StringUtil.isEmpty(resolverCtx.getBuildSrcGroup())) {
|
||||
compositePrefix = resolverCtx.getBuildSrcGroup() + (isRootPath ? ":" : ":buildSrc");
|
||||
}
|
||||
@@ -255,18 +269,48 @@ public final class GradleProjectResolverUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String buildCompositePrefixFromBuildNames(@NotNull ProjectResolverContext resolverCtx, BuildIdentifier buildId) {
|
||||
String compositePrefix;
|
||||
List<String> list = Stream.iterate(
|
||||
findIncludedBuild(resolverCtx, buildId),
|
||||
Objects::nonNull,
|
||||
b -> findIncludedBuild(resolverCtx, b.getParentBuildIdentifier())
|
||||
)
|
||||
.map(Build::getName)
|
||||
.collect(Collectors.toList());
|
||||
Collections.reverse(list);
|
||||
compositePrefix = StringUtil.join(list, ".");
|
||||
return compositePrefix;
|
||||
private static String buildCompositePrefixFromBuildNames(@NotNull ProjectResolverContext resolverCtx, @NotNull BuildIdentifier buildId) {
|
||||
String result = "";
|
||||
Build build = findBuild(resolverCtx, buildId);
|
||||
// if this build can not be found, return empty prefix
|
||||
if (build == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean isBuildSrc = build.getBuildIdentifier().getRootDir().getName().equals("buildSrc");
|
||||
|
||||
if (isBuildSrc) {
|
||||
build = findBuild(resolverCtx, new BuildIdentifier() {
|
||||
@Override
|
||||
public File getRootDir() {
|
||||
return buildId.getRootDir().getParentFile();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
List<String> includedParentsList = Stream.iterate(
|
||||
build,
|
||||
Objects::nonNull,
|
||||
b -> findIncludedBuild(resolverCtx, b.getParentBuildIdentifier())
|
||||
).map(b -> {
|
||||
var ideaProject = resolverCtx.getModels().getModel(b, IdeaProject.class);
|
||||
if (ideaProject != null) {
|
||||
return ideaProject.getName();
|
||||
}
|
||||
else {
|
||||
return b.getName();
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
Collections.reverse(includedParentsList);
|
||||
|
||||
result = StringUtil.join(includedParentsList, ".");
|
||||
|
||||
if (isBuildSrc) {
|
||||
result += ":buildSrc";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -277,6 +321,14 @@ public final class GradleProjectResolverUtil {
|
||||
return ContainerUtil.find(resolverCtx.getModels().getIncludedBuilds(), b -> FileUtil.filesEqual(b.getBuildIdentifier().getRootDir(), buildId.getRootDir()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Build findBuild(@NotNull ProjectResolverContext resolverCtx, @Nullable BuildIdentifier buildId) {
|
||||
if (buildId == null) {
|
||||
return null;
|
||||
}
|
||||
return ContainerUtil.find(resolverCtx.getModels().getAllBuilds(), b -> FileUtil.filesEqual(b.getBuildIdentifier().getRootDir(), buildId.getRootDir()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getModuleId(String gradlePath, String moduleName) {
|
||||
return StringUtil.isEmpty(gradlePath) || ":".equals(gradlePath) ? moduleName : gradlePath;
|
||||
|
||||
+3
@@ -69,6 +69,9 @@ public interface ProjectResolverContext extends UserDataHolderEx {
|
||||
@Nullable
|
||||
String getBuildSrcGroup();
|
||||
|
||||
@Nullable
|
||||
String getBuildSrcGroup(IdeaModule module);
|
||||
|
||||
@ApiStatus.Experimental
|
||||
void report(@NotNull MessageEvent.Kind kind, @NotNull BuildIssue buildIssue);
|
||||
}
|
||||
|
||||
+32
-4
@@ -19,6 +19,7 @@ import org.gradle.tooling.model.build.JavaEnvironment;
|
||||
import org.gradle.tooling.model.gradle.BasicGradleProject;
|
||||
import org.gradle.tooling.model.gradle.GradleBuild;
|
||||
import org.gradle.tooling.model.idea.IdeaProject;
|
||||
import org.gradle.util.GradleVersion;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -132,7 +133,7 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
|
||||
assert myGradleBuild != null;
|
||||
assert myModelConverter != null;
|
||||
//We only need these later, but need to fetch them before fetching other models because of https://github.com/gradle/gradle/issues/20008
|
||||
final Set<GradleBuild> nestedBuilds = getNestedBuilds(myGradleBuild);
|
||||
final Set<GradleBuild> nestedBuilds = getNestedBuilds(myGradleBuild, controller);
|
||||
final MyBuildController wrappedController = new MyBuildController(controller, myGradleBuild);
|
||||
fetchProjectBuildModels(wrappedController, isProjectsLoadedAction, myGradleBuild);
|
||||
addBuildModels(wrappedController, myAllModels, myGradleBuild, isProjectsLoadedAction);
|
||||
@@ -218,7 +219,13 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
|
||||
void accept(@NotNull GradleBuild build);
|
||||
}
|
||||
|
||||
private Set<GradleBuild> getNestedBuilds(@NotNull GradleBuild rootBuild) {
|
||||
private Set<GradleBuild> getNestedBuilds(@NotNull GradleBuild rootBuild, BuildController controller) {
|
||||
BuildEnvironment environment = controller.getModel(BuildEnvironment.class);
|
||||
GradleVersion envGradleVersion = null;
|
||||
if (environment != null) {
|
||||
// call to GradleVersion.current() will load version class from client classloader and return TAPI version number
|
||||
envGradleVersion = GradleVersion.version(environment.getGradle().getGradleVersion());
|
||||
}
|
||||
if (!myIsCompositeBuildsSupported) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
@@ -226,18 +233,32 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
|
||||
Set<GradleBuild> nestedBuilds = new LinkedHashSet<>();
|
||||
String rootBuildPath = rootBuild.getBuildIdentifier().getRootDir().getPath();
|
||||
processedBuildsPaths.add(rootBuildPath);
|
||||
Queue<GradleBuild> queue = new ArrayDeque<>(rootBuild.getIncludedBuilds());
|
||||
Queue<GradleBuild> queue = new ArrayDeque<>(getEditableBuilds(rootBuild, envGradleVersion));
|
||||
while (!queue.isEmpty()) {
|
||||
GradleBuild includedBuild = queue.remove();
|
||||
String includedBuildPath = includedBuild.getBuildIdentifier().getRootDir().getPath();
|
||||
if (processedBuildsPaths.add(includedBuildPath)) {
|
||||
nestedBuilds.add(includedBuild);
|
||||
queue.addAll(includedBuild.getIncludedBuilds());
|
||||
queue.addAll(getEditableBuilds(includedBuild, envGradleVersion));
|
||||
}
|
||||
}
|
||||
return nestedBuilds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nested builds to be imported by IDEA
|
||||
* @param build parent build
|
||||
* @return builds to be imported by IDEA. Before Gradle 8.0 - included builds, 8.0 and later - included and buildSrc builds
|
||||
*/
|
||||
private static DomainObjectSet<? extends GradleBuild> getEditableBuilds(@NotNull GradleBuild rootBuild,
|
||||
@Nullable GradleVersion version) {
|
||||
if (version != null && version.compareTo(GradleVersion.version("8.0")) >= 0) {
|
||||
return rootBuild.getEditableBuilds();
|
||||
} else {
|
||||
return rootBuild.getIncludedBuilds();
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchProjectBuildModels(BuildController controller, final boolean isProjectsLoadedAction, GradleBuild build) {
|
||||
// Prepare nested build actions.
|
||||
List<BuildAction<List<Runnable>>> buildActions = new ArrayList<>();
|
||||
@@ -482,6 +503,13 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
|
||||
return includedBuilds;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Build> getAllBuilds() {
|
||||
List<Build> result = new ArrayList<>(includedBuilds);
|
||||
result.add(0, getMainBuild());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BuildEnvironment getBuildEnvironment() {
|
||||
return getModel(BuildEnvironment.class);
|
||||
|
||||
Reference in New Issue
Block a user