Cleanup: NotNull/Nullable
[idea/community.git] / java / compiler / openapi / src / com / intellij / openapi / compiler / CompilerPaths.java
1 /*
2  * Copyright 2000-2017 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.openapi.compiler;
17
18 import com.intellij.compiler.CompilerConfiguration;
19 import com.intellij.openapi.application.Application;
20 import com.intellij.openapi.application.ApplicationManager;
21 import com.intellij.openapi.application.ReadAction;
22 import com.intellij.openapi.diagnostic.Logger;
23 import com.intellij.openapi.module.Module;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.project.ProjectUtil;
26 import com.intellij.openapi.roots.CompilerModuleExtension;
27 import com.intellij.openapi.roots.ModuleRootManager;
28 import com.intellij.openapi.util.text.StringUtil;
29 import com.intellij.openapi.vfs.VirtualFile;
30 import com.intellij.openapi.vfs.VirtualFileManager;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33 import org.jetbrains.jps.model.java.compiler.AnnotationProcessingConfiguration;
34
35 import java.io.File;
36 import java.util.Arrays;
37
38 /**
39  * A set of utility methods for working with paths
40  */
41 public class CompilerPaths {
42   private static final Logger LOG = Logger.getInstance(CompilerPaths.class);
43
44   /**
45    * @return a root directory where generated files for various compilers are stored
46    */
47   public static File getGeneratedDataDirectory(Project project) {
48     return new File(getCompilerSystemDirectory(project), ".generated");
49   }
50
51   /**
52    * @return a root directory where compiler caches for the given project are stored
53    */
54   public static File getCacheStoreDirectory(final Project project) {
55     return new File(getCompilerSystemDirectory(project), ".caches");
56   }
57
58   /**
59    * @return a directory under IDEA "system" directory where all files related to compiler subsystem are stored (such as compiler caches or generated files)
60    */
61   @NotNull
62   public static File getCompilerSystemDirectory(@NotNull Project project) {
63     return ProjectUtil.getProjectCachePath(project, "compiler").toFile();
64   }
65
66   /**
67    * @param forTestClasses true if directory for test sources, false - for sources.
68    * @return a directory to which the sources (or test sources depending on the second parameter) should be compiled.
69    * Null is returned if output directory is not specified or is not valid
70    */
71   @Nullable
72   public static VirtualFile getModuleOutputDirectory(@NotNull Module module, boolean forTestClasses) {
73     final CompilerModuleExtension compilerModuleExtension = CompilerModuleExtension.getInstance(module);
74     if (compilerModuleExtension == null) {
75       return null;
76     }
77     VirtualFile outPath;
78     if (forTestClasses) {
79       final VirtualFile path = compilerModuleExtension.getCompilerOutputPathForTests();
80       if (path != null) {
81         outPath = path;
82       }
83       else {
84         outPath = compilerModuleExtension.getCompilerOutputPath();
85       }
86     }
87     else {
88       outPath = compilerModuleExtension.getCompilerOutputPath();
89     }
90     if (outPath == null) {
91       return null;
92     }
93     if (!outPath.isValid()) {
94       LOG.info("Requested output path for module " + module.getName() + " is not valid");
95       return null;
96     }
97     return outPath;
98   }
99
100   /**
101    * The same as {@link #getModuleOutputDirectory} but returns String.
102    * The method still returns a non-null value if the output path is specified in Settings but does not exist on disk.
103    */
104   @Nullable
105   public static String getModuleOutputPath(final Module module, boolean forTestClasses) {
106     final CompilerModuleExtension extension = CompilerModuleExtension.getInstance(module);
107     if (extension == null) {
108       return null;
109     }
110     final String outPathUrl;
111     final Application application = ApplicationManager.getApplication();
112     if (forTestClasses) {
113       if (application.isDispatchThread()) {
114         final String url = extension.getCompilerOutputUrlForTests();
115         outPathUrl = url != null ? url : extension.getCompilerOutputUrl();
116       }
117       else {
118         outPathUrl = ReadAction.compute(() -> {
119           final String url = extension.getCompilerOutputUrlForTests();
120           return url != null ? url : extension.getCompilerOutputUrl();
121         });
122       }
123     }
124     else { // for ordinary classes
125       if (application.isDispatchThread()) {
126         outPathUrl = extension.getCompilerOutputUrl();
127       }
128       else {
129         outPathUrl = ReadAction.compute(() -> extension.getCompilerOutputUrl());
130       }
131     }
132     return outPathUrl != null? VirtualFileManager.extractPath(outPathUrl) : null;
133   }
134
135   @Nullable
136   public static String getAnnotationProcessorsGenerationPath(Module module, boolean forTests) {
137     final AnnotationProcessingConfiguration config = CompilerConfiguration.getInstance(module.getProject()).getAnnotationProcessingConfiguration(module);
138     final String sourceDirName = config.getGeneratedSourcesDirectoryName(forTests);
139     if (config.isOutputRelativeToContentRoot()) {
140       final String[] roots = ModuleRootManager.getInstance(module).getContentRootUrls();
141       if (roots.length == 0) {
142         return null;
143       }
144       if (roots.length > 1) {
145         Arrays.sort(roots);
146       }
147       return StringUtil.isEmpty(sourceDirName)? VirtualFileManager.extractPath(roots[0]): VirtualFileManager.extractPath(roots[0]) + "/" + sourceDirName;
148     }
149
150
151     final String path = getModuleOutputPath(module, forTests);
152     if (path == null) {
153       return null;
154     }
155     return StringUtil.isEmpty(sourceDirName)? path : path + "/" + sourceDirName;
156   }
157
158 }