diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java index ef3bf971394f..04a9dd1abac9 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java @@ -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 ideModule) { ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class); - if (externalProject != null) { - processSourceSets(resolverCtx, gradleModule, externalProject, ideModule, new SourceSetsProcessor() { - @Override - public void process(@NotNull DataNode dataNode, @NotNull ExternalSourceSet sourceSet) { - for (Map.Entry 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 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 sourceDirectories = gradleContentRoot.getSourceDirectories().getAll(); + List testDirectories = gradleContentRoot.getTestDirectories().getAll(); + List resourceDirectories = Collections.emptyList(); + List 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 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 ideModule, + @NotNull ExternalProject externalProject) { + processSourceSets(resolverCtx, gradleModule, externalProject, ideModule, new SourceSetsProcessor() { + @Override + public void process(@NotNull DataNode dataNode, @NotNull ExternalSourceSet sourceSet) { + for (Map.Entry 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 list, List toRemove) { + Set 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 ideModule, @NotNull SourceSetsProcessor processor) { Map> sourceSetsMap = ContainerUtil.newHashMap(); - for (DataNode dataNode: ExternalSystemApiUtil.findAll(ideModule, GradleSourceSetData.KEY)) { + for (DataNode 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 directorySetEntry: sourceSet.getSources().entrySet()) { + for (Map.Entry 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 sourceTypeFileEntry: compileOutputPaths.entrySet()) { + for (Map.Entry 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 orphanModules = ContainerUtil.newArrayList(); Map modulesIndex = ContainerUtil.newHashMap(); - for (DataNode dataNode: ExternalSystemApiUtil.getChildren(ideProject, ProjectKeys.MODULE)) { + for (DataNode 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; } diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleFoldersImportingTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleFoldersImportingTest.java index cbe400eebcef..6b2775303c08 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleFoldersImportingTest.java +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/GradleFoldersImportingTest.java @@ -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); } - } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy index a501415bdf48..2f1b444b08fa 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy @@ -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)