IDEA-195798 Gradle: support resources and test resources of the 'idea' plugin

This commit is contained in:
Vladislav.Soroka
2018-07-19 17:25:26 +03:00
parent 40d4a9ec22
commit 65cd80e684
3 changed files with 143 additions and 46 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.plugins.gradle.service.project;
import com.google.gson.GsonBuilder;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.SimpleJavaParameters;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -73,6 +72,7 @@ import java.lang.reflect.Proxy;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.intellij.openapi.util.Pair.pair;
import static org.jetbrains.plugins.gradle.service.project.GradleProjectResolver.CONFIGURATION_ARTIFACTS;
@@ -153,7 +153,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
mainModuleData.setIdeModuleGroup(isRootModule ? null : moduleGroup);
}
for (ExternalSourceSet sourceSet: externalProject.getSourceSets().values()) {
for (ExternalSourceSet sourceSet : externalProject.getSourceSets().values()) {
final String moduleId = getModuleId(resolverCtx, gradleModule, sourceSet);
final String moduleExternalName = gradleModule.getName() + ":" + sourceSet.getName();
final String moduleInternalName = getInternalModuleName(gradleModule, externalProject, sourceSet.getName(), resolverCtx);
@@ -268,49 +268,59 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
public void populateModuleContentRoots(@NotNull IdeaModule gradleModule,
@NotNull DataNode<ModuleData> ideModule) {
ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class);
if (externalProject != null) {
processSourceSets(resolverCtx, gradleModule, externalProject, ideModule, new SourceSetsProcessor() {
@Override
public void process(@NotNull DataNode<? extends ModuleData> dataNode, @NotNull ExternalSourceSet sourceSet) {
for (Map.Entry<IExternalSystemSourceType, ExternalSourceDirectorySet> directorySetEntry: sourceSet.getSources().entrySet()) {
ExternalSystemSourceType sourceType = ExternalSystemSourceType.from(directorySetEntry.getKey());
ExternalSourceDirectorySet sourceDirectorySet = directorySetEntry.getValue();
for (File file: sourceDirectorySet.getSrcDirs()) {
ContentRootData ideContentRoot = new ContentRootData(GradleConstants.SYSTEM_ID, file.getAbsolutePath());
ideContentRoot.storePath(sourceType, file.getAbsolutePath());
dataNode.createChild(ProjectKeys.CONTENT_ROOT, ideContentRoot);
}
}
}
});
if (resolverCtx.isResolveModulePerSourceSet()) {
assert externalProject != null;
addExternalProjectContentRoots(gradleModule, ideModule, externalProject);
}
DomainObjectSet<? extends IdeaContentRoot> contentRoots = gradleModule.getContentRoots();
if (contentRoots == null) {
return;
}
for (IdeaContentRoot gradleContentRoot: contentRoots) {
for (IdeaContentRoot gradleContentRoot : contentRoots) {
if (gradleContentRoot == null) continue;
File rootDirectory = gradleContentRoot.getRootDirectory();
if (rootDirectory == null) continue;
boolean oldGradle = false;
ContentRootData ideContentRoot = new ContentRootData(GradleConstants.SYSTEM_ID, rootDirectory.getAbsolutePath());
if (externalProject == null) {
populateContentRoot(ideContentRoot, ExternalSystemSourceType.SOURCE, gradleContentRoot.getSourceDirectories());
populateContentRoot(ideContentRoot, ExternalSystemSourceType.TEST, gradleContentRoot.getTestDirectories());
if (!resolverCtx.isResolveModulePerSourceSet()) {
List<? extends IdeaSourceDirectory> sourceDirectories = gradleContentRoot.getSourceDirectories().getAll();
List<? extends IdeaSourceDirectory> testDirectories = gradleContentRoot.getTestDirectories().getAll();
List<? extends IdeaSourceDirectory> resourceDirectories = Collections.emptyList();
List<? extends IdeaSourceDirectory> testResourceDirectories = Collections.emptyList();
try {
resourceDirectories = gradleContentRoot.getResourceDirectories().getAll();
removeAll(sourceDirectories, resourceDirectories);
testResourceDirectories = gradleContentRoot.getTestResourceDirectories().getAll();
removeAll(testDirectories, testResourceDirectories);
}
catch (UnsupportedMethodException e) {
oldGradle = true;
// org.gradle.tooling.model.idea.IdeaContentRoot.getResourceDirectories/getTestResourceDirectories methods supported since Gradle 4.7
LOG.debug(e.getMessage());
if (gradleContentRoot instanceof ExtIdeaContentRoot) {
ExtIdeaContentRoot extIdeaContentRoot = (ExtIdeaContentRoot)gradleContentRoot;
populateContentRoot(ideContentRoot, ExternalSystemSourceType.RESOURCE, extIdeaContentRoot.getResourceDirectories());
populateContentRoot(ideContentRoot, ExternalSystemSourceType.TEST_RESOURCE, extIdeaContentRoot.getTestResourceDirectories());
if (externalProject == null) {
populateContentRoot(ideContentRoot, ExternalSystemSourceType.SOURCE, gradleContentRoot.getSourceDirectories());
populateContentRoot(ideContentRoot, ExternalSystemSourceType.TEST, gradleContentRoot.getTestDirectories());
}
else {
addExternalProjectContentRoots(gradleModule, ideModule, externalProject);
}
}
if (!oldGradle) {
populateContentRoot(ideContentRoot, ExternalSystemSourceType.SOURCE, sourceDirectories);
populateContentRoot(ideContentRoot, ExternalSystemSourceType.TEST, testDirectories);
populateContentRoot(ideContentRoot, ExternalSystemSourceType.RESOURCE, resourceDirectories);
populateContentRoot(ideContentRoot, ExternalSystemSourceType.TEST_RESOURCE, testResourceDirectories);
}
}
Set<File> excluded = gradleContentRoot.getExcludeDirectories();
if (excluded != null) {
for (File file: excluded) {
for (File file : excluded) {
ideContentRoot.storePath(ExternalSystemSourceType.EXCLUDED, file.getAbsolutePath());
}
}
@@ -318,17 +328,42 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
}
}
private void addExternalProjectContentRoots(@NotNull IdeaModule gradleModule,
@NotNull DataNode<ModuleData> ideModule,
@NotNull ExternalProject externalProject) {
processSourceSets(resolverCtx, gradleModule, externalProject, ideModule, new SourceSetsProcessor() {
@Override
public void process(@NotNull DataNode<? extends ModuleData> dataNode, @NotNull ExternalSourceSet sourceSet) {
for (Map.Entry<IExternalSystemSourceType, ExternalSourceDirectorySet> directorySetEntry : sourceSet.getSources().entrySet()) {
ExternalSystemSourceType sourceType = ExternalSystemSourceType.from(directorySetEntry.getKey());
ExternalSourceDirectorySet sourceDirectorySet = directorySetEntry.getValue();
for (File file : sourceDirectorySet.getSrcDirs()) {
ContentRootData ideContentRoot = new ContentRootData(GradleConstants.SYSTEM_ID, file.getAbsolutePath());
ideContentRoot.storePath(sourceType, file.getAbsolutePath());
dataNode.createChild(ProjectKeys.CONTENT_ROOT, ideContentRoot);
}
}
}
});
}
private static void removeAll(List<? extends IdeaSourceDirectory> list, List<? extends IdeaSourceDirectory> toRemove) {
Set<File> files = toRemove.stream().map(o -> o.getDirectory()).collect(Collectors.toSet());
list.removeIf(o -> files.contains(o.getDirectory()));
}
private static void processSourceSets(@NotNull ProjectResolverContext resolverCtx,
@NotNull IdeaModule gradleModule,
@NotNull ExternalProject externalProject,
@NotNull DataNode<ModuleData> ideModule,
@NotNull SourceSetsProcessor processor) {
Map<String, DataNode<GradleSourceSetData>> sourceSetsMap = ContainerUtil.newHashMap();
for (DataNode<GradleSourceSetData> dataNode: ExternalSystemApiUtil.findAll(ideModule, GradleSourceSetData.KEY)) {
for (DataNode<GradleSourceSetData> dataNode : ExternalSystemApiUtil.findAll(ideModule, GradleSourceSetData.KEY)) {
sourceSetsMap.put(dataNode.getData().getId(), dataNode);
}
for (ExternalSourceSet sourceSet: externalProject.getSourceSets().values()) {
for (ExternalSourceSet sourceSet : externalProject.getSourceSets().values()) {
if (sourceSet == null || sourceSet.getSources().isEmpty()) continue;
final String moduleId = getModuleId(resolverCtx, gradleModule, sourceSet);
@@ -362,7 +397,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
gradleOutputMap = MultiMap.create();
dataNode.putUserData(GradleProjectResolver.GRADLE_OUTPUTS, gradleOutputMap);
}
for (Map.Entry<IExternalSystemSourceType, ExternalSourceDirectorySet> directorySetEntry: sourceSet.getSources().entrySet()) {
for (Map.Entry<IExternalSystemSourceType, ExternalSourceDirectorySet> directorySetEntry : sourceSet.getSources().entrySet()) {
ExternalSystemSourceType sourceType = ExternalSystemSourceType.from(directorySetEntry.getKey());
ExternalSourceDirectorySet sourceDirectorySet = directorySetEntry.getValue();
final ModuleData moduleData = dataNode.getData();
@@ -371,7 +406,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
moduleData.setCompileOutputPath(sourceType, outputDir.getAbsolutePath());
moduleData.setInheritProjectCompileOutputPath(sourceDirectorySet.isCompilerOutputPathInherited());
for (File gradleOutputDir: sourceDirectorySet.getGradleOutputDirs()) {
for (File gradleOutputDir : sourceDirectorySet.getGradleOutputDirs()) {
String gradleOutputPath = ExternalSystemApiUtil.toCanonicalPath(gradleOutputDir.getAbsolutePath());
gradleOutputMap.putValue(sourceType, gradleOutputPath);
if (!gradleOutputDir.getPath().equals(outputDir.getPath())) {
@@ -409,7 +444,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
}
}
for (Map.Entry<ExternalSystemSourceType, File> sourceTypeFileEntry: compileOutputPaths.entrySet()) {
for (Map.Entry<ExternalSystemSourceType, File> sourceTypeFileEntry : compileOutputPaths.entrySet()) {
final File outputPath = sourceTypeFileEntry.getValue();
if (outputPath != null) {
moduleData.setCompileOutputPath(sourceTypeFileEntry.getKey(), outputPath.getAbsolutePath());
@@ -472,7 +507,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
List<String> orphanModules = ContainerUtil.newArrayList();
Map<String, ModuleData> modulesIndex = ContainerUtil.newHashMap();
for (DataNode<ModuleData> dataNode: ExternalSystemApiUtil.getChildren(ideProject, ProjectKeys.MODULE)) {
for (DataNode<ModuleData> dataNode : ExternalSystemApiUtil.getChildren(ideProject, ProjectKeys.MODULE)) {
modulesIndex.put(dataNode.getData().getExternalName(), dataNode.getData());
}
@@ -546,7 +581,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
final boolean isFlatProject = !FileUtil.isAncestor(rootProjectPath, moduleConfigPath, false);
if (externalProject != null) {
for (ExternalTask task: externalProject.getTasks().values()) {
for (ExternalTask task : externalProject.getTasks().values()) {
String taskName = isFlatProject ? task.getQName() : task.getName();
String taskGroup = task.getGroup();
if (taskName.trim().isEmpty() || isIdeaTask(taskName, taskGroup)) {
@@ -564,7 +599,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
return tasks;
}
for (GradleTask task: gradleModule.getGradleProject().getTasks()) {
for (GradleTask task : gradleModule.getGradleProject().getTasks()) {
String taskName = task.getName();
String taskGroup = getTaskGroup(task);
if (taskName == null || taskName.trim().isEmpty() || isIdeaTask(taskName, taskGroup)) {
@@ -725,7 +760,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
}
@Override
public void enhanceRemoteProcessing(@NotNull SimpleJavaParameters parameters) throws ExecutionException {
public void enhanceRemoteProcessing(@NotNull SimpleJavaParameters parameters) {
// IntelliJ Gradle integration uses in-process calls for gradle tooling api
}
@@ -744,7 +779,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
if (dirs == null) {
return;
}
for (IdeaSourceDirectory dir: dirs) {
for (IdeaSourceDirectory dir : dirs) {
ExternalSystemSourceType dirSourceType = type;
try {
if (dir.isGenerated() && !dirSourceType.isGenerated()) {
@@ -774,7 +809,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
final Class<?> aClass = obj.getClass();
LOG.debug(String.format("obj class: %s", aClass));
LOG.debug(String.format("classloader: %s", aClass.getClassLoader()));
for (Method m: aClass.getDeclaredMethods()) {
for (Method m : aClass.getDeclaredMethods()) {
LOG.debug(String.format("obj m: %s", m));
}
@@ -789,7 +824,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
LOG.debug(String.format("delegate: %s", delegate));
LOG.debug(String.format("delegate class: %s", delegate.getClass()));
LOG.debug(String.format("delegate classloader: %s", delegate.getClass().getClassLoader()));
for (Method m: delegate.getClass().getDeclaredMethods()) {
for (Method m : delegate.getClass().getDeclaredMethods()) {
LOG.debug(String.format("delegate m: %s", m));
}
}
@@ -808,7 +843,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
if (scopeAsString == null) {
return null;
}
for (DependencyScope dependencyScope: DependencyScope.values()) {
for (DependencyScope dependencyScope : DependencyScope.values()) {
if (scopeAsString.equalsIgnoreCase(dependencyScope.toString())) {
return dependencyScope;
}
@@ -143,6 +143,52 @@ public class GradleFoldersImportingTest extends GradleImportingTestCase {
assertGeneratedTestSources("project", "src/test/java");
}
@Test
@TargetVersions("4.7+")
public void testResourceFoldersWithIdeaPlugin() throws Exception {
createProjectSubDirs("src/main/java",
"src/main/src2",
"src/main/resources",
"src/main/resources2",
"src/test/java",
"src/test/src2",
"src/test/resources",
"src/test/resources2");
importProject(
"apply plugin: 'java'\n" +
"apply plugin: 'idea'\n" +
"idea {\n" +
" module {\n" +
" sourceDirs += file('src/main/src2')\n" +
" resourceDirs += file('src/main/resources2')\n" +
" testSourceDirs += file('src/test/src2')\n" +
" testResourceDirs += file('src/test/resources2')\n" +
" }\n" +
"}"
);
assertModules("project", "project_main", "project_test");
assertContentRoots("project", getProjectPath());
assertExcludes("project", ".gradle", "build", "out");
assertContentRoots("project_main", getProjectPath() + "/src/main");
assertSources("project_main", "java", "src2");
assertResources("project_main", "resources", "resources2");
assertContentRoots("project_test", getProjectPath() + "/src/test");
assertTestSources("project_test", "java", "src2");
assertTestResources("project_test", "resources", "resources2");
importProjectUsingSingeModulePerGradleProject();
assertModules("project");
assertContentRoots("project", getProjectPath());
assertExcludes("project", ".gradle", "build", "out");
assertSources("project", "src/main/java", "src/main/src2");
assertResources("project", "src/main/resources", "src/main/resources2");
assertTestSources("project", "src/test/java", "src/test/src2");
assertTestResources("project", "src/test/resources", "src/test/resources2");
}
@Test
public void testProjectWithInheritedOutputDirs() throws Exception {
@@ -226,7 +272,7 @@ public class GradleFoldersImportingTest extends GradleImportingTestCase {
createProjectSubFile("src/main/java/A.java");
createProjectSubFile("src/test/resources/res.properties");
importProjectUsingSingeModulePerGradleProject(
"apply plugin: 'java'"
"apply plugin: 'java'"
);
assertModules("project");
@@ -298,9 +344,10 @@ public class GradleFoldersImportingTest extends GradleImportingTestCase {
edt(() -> UIUtil.dispatchAllInvocationEvents());
assertTestSources(projectRef.get(), "project", "src/test/java");
} finally {
}
finally {
if (!projectRef.isNull()) {
edt(() ->{
edt(() -> {
projectManager.closeTestProject(projectRef.get());
WriteAction.run(() -> Disposer.dispose(projectRef.get()));
});
@@ -343,5 +390,4 @@ public class GradleFoldersImportingTest extends GradleImportingTestCase {
String rootUrl = contentRoots.length > 1 ? ExternalSystemApiUtil.getExternalProjectPath(fooModule) : null;
doAssertContentFolders(rootUrl, contentRoots, JavaSourceRootType.TEST_SOURCE, expected);
}
}
@@ -183,19 +183,25 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
def ideaPluginTestOutDir = ideaPluginModule?.testOutputDir
def generatedSourceDirs
def ideaSourceDirs
def ideaResourceDirs
def ideaTestSourceDirs
def ideaTestResourceDirs
def downloadJavadoc = false
def downloadSources = true
if(ideaPluginModule) {
generatedSourceDirs = ideaPluginModule.hasProperty("generatedSourceDirs") ? new LinkedHashSet<>(ideaPluginModule.generatedSourceDirs): null
if (ideaPluginModule) {
generatedSourceDirs = ideaPluginModule.hasProperty("generatedSourceDirs") ? new LinkedHashSet<>(ideaPluginModule.generatedSourceDirs) : null
ideaSourceDirs = new LinkedHashSet<>(ideaPluginModule.sourceDirs)
ideaResourceDirs = ideaPluginModule.hasProperty("resourceDirs") ? new LinkedHashSet<>(ideaPluginModule.resourceDirs) : []
ideaTestSourceDirs = new LinkedHashSet<>(ideaPluginModule.testSourceDirs)
ideaTestResourceDirs = ideaPluginModule.hasProperty("testResourceDirs") ? new LinkedHashSet<>(ideaPluginModule.testResourceDirs) : []
downloadJavadoc = ideaPluginModule.downloadJavadoc
downloadSources = ideaPluginModule.downloadSources
} else {
generatedSourceDirs = null
ideaSourceDirs = null
ideaResourceDirs = null
ideaTestSourceDirs = null
ideaTestResourceDirs = null
}
def projectSourceCompatibility
@@ -410,7 +416,9 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
if (ideaPluginModule && SourceSet.MAIN_SOURCE_SET_NAME != sourceSet.name && SourceSet.TEST_SOURCE_SET_NAME != sourceSet.name) {
sources.values().each {
ideaSourceDirs.removeAll(it.srcDirs)
ideaResourceDirs.removeAll(it.srcDirs)
ideaTestSourceDirs.removeAll(it.srcDirs)
ideaTestResourceDirs.removeAll(it.srcDirs)
}
}
}
@@ -432,6 +440,10 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
if(mainSourceDirectorySet) {
mainSourceDirectorySet.srcDirs.addAll(ideaSourceDirs - (mainGradleSourceSet.resources.srcDirs + generatedSourceDirs))
}
def mainResourceDirectorySet = mainSourceSet.sources[ExternalSystemSourceType.RESOURCE]
if(mainResourceDirectorySet) {
mainResourceDirectorySet.srcDirs.addAll(ideaResourceDirs)
}
if (!additionalIdeaGenDirs.isEmpty()) {
def mainAdditionalGenDirs = additionalIdeaGenDirs.intersect(ideaSourceDirs)
@@ -460,6 +472,10 @@ class ExternalProjectBuilderImpl implements ModelBuilderService {
if(testSourceDirectorySet) {
testSourceDirectorySet.srcDirs.addAll(ideaTestSourceDirs - (testGradleSourceSet.resources.srcDirs + generatedSourceDirs))
}
def testResourceDirectorySet = testSourceSet.sources[ExternalSystemSourceType.TEST_RESOURCE]
if(testResourceDirectorySet) {
testResourceDirectorySet.srcDirs.addAll(ideaTestResourceDirs)
}
if (!additionalIdeaGenDirs.isEmpty()) {
def testAdditionalGenDirs = additionalIdeaGenDirs.intersect(ideaTestSourceDirs)