IDEA-189333 Gradle: buildscript classpath resolve doesn't work for included build project dependency

This commit is contained in:
Vladislav.Soroka
2018-04-17 18:12:31 +03:00
parent 4941670b1a
commit 12ed7b2fc2
6 changed files with 124 additions and 36 deletions
@@ -117,31 +117,45 @@ public class GradleFindUsagesTest extends GradleImportingTestCase {
createProjectSubFile("buildSrc/src/main/groovy/org/buildsrc/BuildSrcClass.groovy", "package org.buildsrc;\n" +
"public class BuildSrcClass {}");
createProjectSubFile("build.gradle", "def foo = new org.buildsrc.BuildSrcClass()");
createProjectSubFile("app/build.gradle", "def foo1 = new org.buildsrc.BuildSrcClass()");
createProjectSubFile("build.gradle", "buildscript {\n" +
" dependencies {\n" +
" classpath 'my.included:gradle-plugin:0'\n" +
" }\n" +
"}\n" +
"def foo1 = new org.buildsrc.BuildSrcClass()\n" +
"def foo2 = new org.included.IncludedBuildClass()");
createProjectSubFile("app/build.gradle", "def foo1 = new org.buildsrc.BuildSrcClass()\n" +
"def foo2 = new org.included.IncludedBuildClass()");
// included build
createProjectSubFile("gradle-plugin/settings.gradle", "");
createProjectSubFile("gradle-plugin/build.gradle", "def foo = new org.buildsrc.IncludedBuildSrcClass()");
createProjectSubFile("gradle-plugin/build.gradle", "group 'my.included'\n" +
"apply plugin: 'java'\n" +
"def foo = new org.included.buildsrc.IncludedBuildSrcClass()");
createProjectSubFile("gradle-plugin/buildSrc/src/main/groovy/org/included/buildsrc/IncludedBuildSrcClass.groovy",
"package org.buildsrc;\n" +
"package org.included.buildsrc;\n" +
"public class IncludedBuildSrcClass {}");
createProjectSubFile("gradle-plugin/src/main/java/org/included/IncludedBuildClass.java",
"package org.included;\n" +
"public class IncludedBuildClass {}");
importProject();
assertModules("multiproject", "app",
"multiproject_buildSrc", "multiproject_buildSrc_main", "multiproject_buildSrc_test",
"gradle-plugin",
"gradle-plugin_buildSrc", "gradle-plugin_buildSrc_main", "gradle-plugin_buildSrc_test");
"gradle-plugin", "gradle-plugin_test", "gradle-plugin_main",
"my.included_buildSrc", "my.included_buildSrc_main", "my.included_buildSrc_test");
assertUsages("org.buildsrc.BuildSrcClass", 2);
assertUsages("org.buildsrc.IncludedBuildSrcClass", 1);
assertUsages("org.included.buildsrc.IncludedBuildSrcClass", 1);
assertUsages("org.included.IncludedBuildClass", 2);
importProjectUsingSingeModulePerGradleProject();
assertModules("multiproject", "app",
"multiproject_buildSrc",
"gradle-plugin",
"gradle-plugin_buildSrc");
assertUsages(pair("org.buildsrc.BuildSrcClass", 2), pair("org.buildsrc.IncludedBuildSrcClass", 1));
"my.included_buildSrc");
assertUsages(pair("org.buildsrc.BuildSrcClass", 2), pair("org.included.buildsrc.IncludedBuildSrcClass", 1));
assertUsages("org.included.IncludedBuildClass", 2);
// check for qualified module names
getCurrentExternalProjectSettings().setUseQualifiedModuleNames(true);
@@ -149,37 +163,38 @@ public class GradleFindUsagesTest extends GradleImportingTestCase {
importProject();
assertModules("multiproject", "multiproject.app",
"multiproject.buildSrc", "multiproject.buildSrc.main", "multiproject.buildSrc.test",
"gradle-plugin",
"gradle-plugin.buildSrc", "gradle-plugin.buildSrc.main", "gradle-plugin.buildSrc.test");
assertUsages(pair("org.buildsrc.BuildSrcClass", 2), pair("org.buildsrc.IncludedBuildSrcClass", 1));
"my.included.gradle-plugin", "my.included.gradle-plugin.test", "my.included.gradle-plugin.main",
"my.included.buildSrc", "my.included.buildSrc.main", "my.included.buildSrc.test");
assertUsages(pair("org.buildsrc.BuildSrcClass", 2), pair("org.included.buildsrc.IncludedBuildSrcClass", 1));
assertUsages("org.included.IncludedBuildClass", 2);
importProjectUsingSingeModulePerGradleProject();
assertModules("multiproject", "multiproject.app",
"multiproject.buildSrc",
"gradle-plugin",
"gradle-plugin.buildSrc");
assertUsages(pair("org.buildsrc.BuildSrcClass", 2), pair("org.buildsrc.IncludedBuildSrcClass", 1));
"my.included.gradle-plugin",
"my.included.buildSrc");
assertUsages(pair("org.buildsrc.BuildSrcClass", 2), pair("org.included.buildsrc.IncludedBuildSrcClass", 1));
assertUsages("org.included.IncludedBuildClass", 2);
}
private void assertUsages(String fqn, GlobalSearchScope scope, int count) {
edt(() -> {
PsiClass[] psiClasses = JavaPsiFacade.getInstance(myProject).findClasses(fqn, scope);
assertEquals(1, psiClasses.length);
assertUsagesCount(count, psiClasses[0]);
});
private void assertUsages(String fqn, GlobalSearchScope scope, int count) throws Exception {
final PsiClass[][] psiClasses = new PsiClass[1][1];
edt(() -> psiClasses[0] = JavaPsiFacade.getInstance(myProject).findClasses(fqn, scope));
assertEquals(1, psiClasses[0].length);
assertUsagesCount(count, psiClasses[0][0]);
}
private void assertUsages(String fqn, int count) {
private void assertUsages(String fqn, int count) throws Exception {
assertUsages(fqn, GlobalSearchScope.projectScope(myProject), count);
}
private void assertUsages(Trinity<String, GlobalSearchScope, Integer>... classUsageCount) {
private void assertUsages(Trinity<String, GlobalSearchScope, Integer>... classUsageCount) throws Exception {
for (Trinity<String, GlobalSearchScope, Integer> trinity : classUsageCount) {
assertUsages(trinity.first, trinity.second, trinity.third);
}
}
private void assertUsages(Pair<String, Integer>... classUsageCount) {
private void assertUsages(Pair<String, Integer>... classUsageCount) throws Exception {
for (Pair<String, Integer> pair : classUsageCount) {
assertUsages(Trinity.create(pair.first, GlobalSearchScope.projectScope(myProject), pair.second));
}
@@ -29,4 +29,6 @@ public interface ExternalProjectDependency extends ExternalDependency {
String getConfigurationName();
Collection<File> getProjectDependencyArtifacts();
Collection<File> getProjectDependencyArtifactsSources();
}
@@ -33,6 +33,7 @@ public class DefaultExternalProjectDependency extends AbstractExternalDependency
private String myProjectPath;
private String myConfigurationName = Dependency.DEFAULT_CONFIGURATION;
private Collection<File> myProjectDependencyArtifacts;
private Collection<File> myProjectDependencyArtifactsSources;
public DefaultExternalProjectDependency() {
}
@@ -78,6 +79,15 @@ public class DefaultExternalProjectDependency extends AbstractExternalDependency
myProjectDependencyArtifacts = projectArtifacts;
}
@Override
public Collection<File> getProjectDependencyArtifactsSources() {
return myProjectDependencyArtifactsSources;
}
public void setProjectDependencyArtifactsSources(Collection<File> projectArtifactsSources) {
myProjectDependencyArtifactsSources = projectArtifactsSources;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -89,7 +89,17 @@ public class ModelBuildScriptClasspathBuilderImpl implements ModelBuilderService
new DependencyResolverImpl(project, false, downloadJavadoc, downloadSources, mySourceSetFinder).resolveDependencies(classpathConfiguration);
for (ExternalDependency dependency : new DependencyTraverser(dependencies)) {
if (dependency instanceof ExternalLibraryDependency) {
if (dependency instanceof ExternalProjectDependency) {
ExternalProjectDependency projectDependency = (ExternalProjectDependency)dependency;
Collection<File> projectDependencyArtifacts = projectDependency.getProjectDependencyArtifacts();
Collection<File> projectDependencyArtifactsSources = projectDependency.getProjectDependencyArtifactsSources();
buildScriptClasspath.add(new ClasspathEntryModelImpl(
pathSet(projectDependencyArtifacts),
pathSet(projectDependencyArtifactsSources),
new HashSet<String>()
));
}
else if (dependency instanceof ExternalLibraryDependency) {
final ExternalLibraryDependency libraryDep = (ExternalLibraryDependency)dependency;
buildScriptClasspath.add(new ClasspathEntryModelImpl(
pathSet(libraryDep.getFile()),
@@ -97,7 +107,7 @@ public class ModelBuildScriptClasspathBuilderImpl implements ModelBuilderService
pathSet(libraryDep.getJavadoc())
));
}
if (dependency instanceof ExternalMultiLibraryDependency) {
else if (dependency instanceof ExternalMultiLibraryDependency) {
ExternalMultiLibraryDependency multiLibraryDependency = (ExternalMultiLibraryDependency)dependency;
buildScriptClasspath.add(new ClasspathEntryModelImpl(
pathSet(multiLibraryDependency.getFiles()),
@@ -105,8 +115,7 @@ public class ModelBuildScriptClasspathBuilderImpl implements ModelBuilderService
pathSet(multiLibraryDependency.getJavadoc())
));
}
if (dependency instanceof FileCollectionDependency) {
else if (dependency instanceof FileCollectionDependency) {
FileCollectionDependency fileCollectionDependency = (FileCollectionDependency)dependency;
buildScriptClasspath.add(new ClasspathEntryModelImpl(
pathSet(fileCollectionDependency.getFiles()),
@@ -904,7 +904,9 @@ public class DependencyResolverImpl implements DependencyResolver {
projectDependency.setScope(scope);
projectDependency.setProjectPath(project.getPath());
projectDependency.setConfigurationName(targetConfiguration.getName());
projectDependency.setProjectDependencyArtifacts(targetConfiguration.getAllArtifacts().getFiles().getFiles());
Set<File> artifacts = targetConfiguration.getAllArtifacts().getFiles().getFiles();
projectDependency.setProjectDependencyArtifacts(artifacts);
setProjectDependencyArtifactsSources(projectDependency, artifacts, mySourceSetFinder);
result.add(projectDependency);
} else if (it != null) {
@@ -1034,7 +1036,9 @@ public class DependencyResolverImpl implements DependencyResolver {
dependency.setSelectionReason(selectionReason);
dependency.setProjectPath(((ProjectComponentSelector)componentSelector).getProjectPath());
dependency.setConfigurationName(it.getName());
dependency.setProjectDependencyArtifacts(it.getAllArtifacts().getFiles().getFiles());
Set<File> artifacts = it.getAllArtifacts().getFiles().getFiles();
dependency.setProjectDependencyArtifacts(artifacts);
setProjectDependencyArtifactsSources(dependency, artifacts, mySourceSetFinder);
resolvedDepsFiles.addAll(dependency.getProjectDependencyArtifacts());
@@ -1060,7 +1064,9 @@ public class DependencyResolverImpl implements DependencyResolver {
dependency.setSelectionReason(selectionReason);
dependency.setProjectPath(((ProjectComponentSelector)componentSelector).getProjectPath());
dependency.setConfigurationName(it.getName());
dependency.setProjectDependencyArtifacts(it.getAllArtifacts().getFiles().getFiles());
Set<File> artifactsFiles = it.getAllArtifacts().getFiles().getFiles();
dependency.setProjectDependencyArtifacts(artifactsFiles);
setProjectDependencyArtifactsSources(dependency, artifactsFiles, mySourceSetFinder);
resolvedDepsFiles.addAll(dependency.getProjectDependencyArtifacts());
@@ -1164,9 +1170,9 @@ public class DependencyResolverImpl implements DependencyResolver {
files.add(resolvedArtifact.getFile());
}
dDep.setProjectDependencyArtifacts(files);
setProjectDependencyArtifactsSources(dDep, files, mySourceSetFinder);
resolvedDepsFiles.addAll(dDep.getProjectDependencyArtifacts());
}
else {
dependency = new DefaultExternalLibraryDependency();
DefaultExternalLibraryDependency dDep = (DefaultExternalLibraryDependency)dependency;
@@ -1228,6 +1234,19 @@ public class DependencyResolverImpl implements DependencyResolver {
}
}
private static void setProjectDependencyArtifactsSources(DefaultExternalProjectDependency projectDependency,
Collection<File> artifactFiles,
SourceSetCachedFinder sourceSetFinder) {
List<File> artifactSources = new ArrayList<File>();
for (File artifactFile : artifactFiles) {
SourceSet sourceSet = sourceSetFinder.findByArtifact(artifactFile.getPath());
if (sourceSet != null) {
artifactSources.addAll(sourceSet.getAllJava().getSrcDirs());
}
}
projectDependency.setProjectDependencyArtifactsSources(artifactSources);
}
@Nullable
private static ResolvedArtifactResult findMatchingArtifact(ResolvedArtifact artifact,
ComponentArtifactsResult componentArtifacts,
@@ -17,10 +17,13 @@ package org.jetbrains.plugins.gradle.tooling.util
import groovy.transform.CompileStatic
import org.gradle.api.Project
import org.gradle.api.initialization.IncludedBuild
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.composite.internal.IncludedBuildInternal
import org.gradle.util.GradleVersion
import org.jetbrains.annotations.NotNull
/**
@@ -29,14 +32,31 @@ import org.jetbrains.annotations.NotNull
*/
@CompileStatic
class SourceSetCachedFinder {
private final Map<String, SourceSet> myArtifactsMap = new HashMap<String, SourceSet>()
private final Map<String, SourceSet> myArtifactsMap
@SuppressWarnings("GrUnresolvedAccess")
SourceSetCachedFinder(@NotNull Project project) {
def rootProject = project.rootProject
for (Project p : rootProject.subprojects) {
def extraProperties = rootProject.extensions.extraProperties
def key = "$SourceSetCachedFinder.name${System.identityHashCode(SourceSetCachedFinder.class)}"
if (extraProperties.has(key)) {
def cached = extraProperties.get(key)
if (cached instanceof SourceSetCachedFinder) {
myArtifactsMap = (cached as SourceSetCachedFinder).myArtifactsMap
return
}
}
def artifactsMap = new HashMap<String, SourceSet>()
def projects = new ArrayList<Project>(rootProject.allprojects)
def isCompositeBuildsSupported = GradleVersion.current() >= GradleVersion.version("3.1")
if (isCompositeBuildsSupported) {
projects = exposeIncludedBuilds(project, projects)
}
for (Project p : projects) {
SourceSetContainer sourceSetContainer = getSourceSetContainer(p)
if(sourceSetContainer == null || sourceSetContainer.isEmpty()) continue
if (sourceSetContainer == null || sourceSetContainer.isEmpty()) continue
for (SourceSet sourceSet : sourceSetContainer) {
def task = p.tasks.findByName(sourceSet.getJarTaskName())
@@ -44,11 +64,24 @@ class SourceSetCachedFinder {
AbstractArchiveTask jarTask = (AbstractArchiveTask)task
def archivePath = jarTask?.getArchivePath()
if (archivePath) {
myArtifactsMap[archivePath.path] = sourceSet
artifactsMap[archivePath.path] = sourceSet
}
}
}
}
myArtifactsMap = Collections.unmodifiableMap(artifactsMap)
extraProperties.set(key, this)
}
private static List<Project> exposeIncludedBuilds(Project project, List<Project> projects) {
for (IncludedBuild includedBuild : project.gradle.includedBuilds) {
if (includedBuild instanceof IncludedBuildInternal) {
def build = includedBuild as IncludedBuildInternal
projects += build.configuredBuild.rootProject.allprojects
}
}
return projects
}
SourceSet findByArtifact(String artifactPath) {