2 * Copyright 2000-2014 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.plugins.gradle.tooling.builder;
18 import org.gradle.api.Project;
19 import org.gradle.api.Task;
20 import org.gradle.api.artifacts.Configuration;
21 import org.gradle.api.artifacts.ConfigurationContainer;
22 import org.gradle.api.tasks.SourceSet;
23 import org.gradle.api.tasks.SourceSetContainer;
24 import org.gradle.api.tasks.SourceSetOutput;
25 import org.gradle.api.tasks.bundling.Jar;
26 import org.gradle.api.tasks.testing.Test;
27 import org.gradle.plugins.ide.idea.IdeaPlugin;
28 import org.gradle.plugins.ide.idea.model.IdeaModel;
29 import org.gradle.util.GradleVersion;
30 import org.jetbrains.annotations.NotNull;
31 import org.jetbrains.annotations.Nullable;
32 import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
33 import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
34 import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder;
35 import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
36 import org.jetbrains.plugins.gradle.tooling.internal.IdeaCompilerOutputImpl;
37 import org.jetbrains.plugins.gradle.tooling.internal.IdeaContentRootImpl;
38 import org.jetbrains.plugins.gradle.tooling.internal.IdeaSourceDirectoryImpl;
39 import org.jetbrains.plugins.gradle.tooling.internal.ModuleExtendedModelImpl;
42 import java.io.IOException;
46 * @author Vladislav.Soroka
49 public class ModuleExtendedModelBuilderImpl implements ModelBuilderService {
51 private static final String SOURCE_SETS_PROPERTY = "sourceSets";
52 private static final String TEST_SRC_DIRS_PROPERTY = "testSrcDirs";
55 public boolean canBuild(String modelName) {
56 return ModuleExtendedModel.class.getName().equals(modelName);
61 public Object buildAll(String modelName, Project project) {
63 final String moduleName = project.getName();
64 final String moduleGroup = project.getGroup().toString();
65 final String moduleVersion = project.getVersion().toString();
66 final File buildDir = project.getBuildDir();
68 final ModuleExtendedModelImpl moduleVersionModel = new ModuleExtendedModelImpl(moduleName, moduleGroup, moduleVersion, buildDir);
70 final List<File> artifacts = new ArrayList<File>();
71 for (Task task : project.getTasks()) {
72 if (task instanceof Jar) {
74 artifacts.add(jar.getArchivePath());
78 moduleVersionModel.setArtifacts(artifacts);
80 final Set<String> sourceDirectories = new HashSet<String>();
81 final Set<String> testDirectories = new HashSet<String>();
82 final Set<String> resourceDirectories = new HashSet<String>();
83 final Set<String> testResourceDirectories = new HashSet<String>();
85 final List<File> testClassesDirs = new ArrayList<File>();
86 for (Task task : project.getTasks()) {
87 if (task instanceof Test) {
88 Test test = (Test)task;
89 testClassesDirs.add(test.getTestClassesDir());
91 if (test.hasProperty(TEST_SRC_DIRS_PROPERTY)) {
92 Object testSrcDirs = test.property(TEST_SRC_DIRS_PROPERTY);
93 if (testSrcDirs instanceof Iterable) {
94 for (Object dir : Iterable.class.cast(testSrcDirs)) {
95 addFilePath(testDirectories, dir);
102 IdeaCompilerOutputImpl compilerOutput = new IdeaCompilerOutputImpl();
104 if (project.hasProperty(SOURCE_SETS_PROPERTY)) {
105 Object sourceSets = project.property(SOURCE_SETS_PROPERTY);
106 if (sourceSets instanceof SourceSetContainer) {
107 SourceSetContainer sourceSetContainer = (SourceSetContainer)sourceSets;
108 for (SourceSet sourceSet : sourceSetContainer) {
110 SourceSetOutput output = sourceSet.getOutput();
111 if (SourceSet.TEST_SOURCE_SET_NAME.equals(sourceSet.getName())) {
112 compilerOutput.setTestClassesDir(output.getClassesDir());
113 compilerOutput.setTestResourcesDir(output.getResourcesDir());
115 if (SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) {
116 compilerOutput.setMainClassesDir(output.getClassesDir());
117 compilerOutput.setMainResourcesDir(output.getResourcesDir());
120 for (File javaSrcDir : sourceSet.getAllJava().getSrcDirs()) {
121 boolean isTestDir = isTestDir(sourceSet, testClassesDirs);
122 addFilePath(isTestDir ? testDirectories : sourceDirectories, javaSrcDir);
124 for (File resourcesSrcDir : sourceSet.getResources().getSrcDirs()) {
125 boolean isTestDir = isTestDir(sourceSet, testClassesDirs);
126 addFilePath(isTestDir ? testResourceDirectories : resourceDirectories, resourcesSrcDir);
132 File projectDir = project.getProjectDir();
133 IdeaContentRootImpl contentRoot = new IdeaContentRootImpl(projectDir);
135 final Set<String> ideaSourceDirectories = new HashSet<String>();
136 final Set<String> ideaTestDirectories = new HashSet<String>();
137 final Set<String> ideaGeneratedDirectories = new HashSet<String>();
138 final Set<File> excludeDirectories = new HashSet<File>();
140 enrichDataFromIdeaPlugin(project, excludeDirectories, ideaSourceDirectories, ideaTestDirectories, ideaGeneratedDirectories);
142 if (ideaSourceDirectories.isEmpty()) {
143 sourceDirectories.clear();
144 resourceDirectories.clear();
146 if (ideaTestDirectories.isEmpty()) {
147 testDirectories.clear();
148 testResourceDirectories.clear();
151 ideaSourceDirectories.removeAll(resourceDirectories);
152 sourceDirectories.removeAll(ideaTestDirectories);
153 sourceDirectories.addAll(ideaSourceDirectories);
154 ideaTestDirectories.removeAll(testResourceDirectories);
155 testDirectories.addAll(ideaTestDirectories);
157 // ensure disjoint directories with different type
158 resourceDirectories.removeAll(sourceDirectories);
159 testDirectories.removeAll(sourceDirectories);
160 testResourceDirectories.removeAll(testDirectories);
162 for (String javaDir : sourceDirectories) {
163 contentRoot.addSourceDirectory(new IdeaSourceDirectoryImpl(new File(javaDir), ideaGeneratedDirectories.contains(javaDir)));
165 for (String testDir : testDirectories) {
166 contentRoot.addTestDirectory(new IdeaSourceDirectoryImpl(new File(testDir), ideaGeneratedDirectories.contains(testDir)));
168 for (String resourceDir : resourceDirectories) {
169 contentRoot.addResourceDirectory(new IdeaSourceDirectoryImpl(new File(resourceDir)));
171 for (String testResourceDir : testResourceDirectories) {
172 contentRoot.addTestResourceDirectory(new IdeaSourceDirectoryImpl(new File(testResourceDir)));
174 for (File excludeDir : excludeDirectories) {
175 contentRoot.addExcludeDirectory(excludeDir);
178 moduleVersionModel.setContentRoots(Collections.<ExtIdeaContentRoot>singleton(contentRoot));
179 moduleVersionModel.setCompilerOutput(compilerOutput);
181 ConfigurationContainer configurations = project.getConfigurations();
182 SortedMap<String, Configuration> configurationsByName = configurations.getAsMap();
184 Map<String, Set<File>> artifactsByConfiguration = new HashMap<String, Set<File>>();
185 for (Map.Entry<String, Configuration> configurationEntry : configurationsByName.entrySet()) {
186 Set<File> files = configurationEntry.getValue().getAllArtifacts().getFiles().getFiles();
187 artifactsByConfiguration.put(configurationEntry.getKey(), files);
189 moduleVersionModel.setArtifactsByConfiguration(artifactsByConfiguration);
191 return moduleVersionModel;
196 public ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) {
197 return ErrorMessageBuilder.create(
199 ).withDescription("Unable to resolve all content root directories");
202 private static boolean isTestDir(SourceSet sourceSet, List<File> testClassesDirs) {
203 if (SourceSet.TEST_SOURCE_SET_NAME.equals(sourceSet.getName())) return true;
204 if (SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) return false;
206 File sourceSetClassesDir = sourceSet.getOutput().getClassesDir();
207 for (File testClassesDir : testClassesDirs) {
209 if (sourceSetClassesDir.getPath().equals(testClassesDir.getPath())) return true;
211 while ((testClassesDir = testClassesDir.getParentFile()) != null);
217 private static void addFilePath(Set<String> filePathSet, Object file) {
218 if (file instanceof File) {
220 filePathSet.add(((File)file).getCanonicalPath());
222 catch (IOException ignore) {
227 private static void enrichDataFromIdeaPlugin(Project project,
228 Set<File> excludeDirectories,
229 Set<String> javaDirectories,
230 Set<String> testDirectories,
231 Set<String> ideaGeneratedDirectories) {
233 IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
234 if (ideaPlugin == null) return;
236 IdeaModel ideaModel = ideaPlugin.getModel();
237 if (ideaModel == null || ideaModel.getModule() == null) return;
239 for (File excludeDir : ideaModel.getModule().getExcludeDirs()) {
240 excludeDirectories.add(excludeDir);
242 for (File file : ideaModel.getModule().getSourceDirs()) {
243 javaDirectories.add(file.getPath());
245 for (File file : ideaModel.getModule().getTestSourceDirs()) {
246 testDirectories.add(file.getPath());
249 if(GradleVersion.current().compareTo(GradleVersion.version("2.2")) >=0) {
250 for (File file : ideaModel.getModule().getGeneratedSourceDirs()) {
251 ideaGeneratedDirectories.add(file.getPath());