migrated to artifacts
[fedora-idea.git] / java / compiler / impl / src / com / intellij / compiler / CompilerManagerImpl.java
blob4639eef563b42ca075ca4e57f9afcf236cb45dd0
1 package com.intellij.compiler;
3 import com.intellij.compiler.impl.*;
4 import com.intellij.compiler.impl.javaCompiler.JavaCompiler;
5 import com.intellij.compiler.impl.packagingCompiler.IncrementalPackagingCompiler;
6 import com.intellij.compiler.impl.resourceCompiler.ResourceCompiler;
7 import com.intellij.compiler.impl.rmiCompiler.RmicCompiler;
8 import com.intellij.openapi.compiler.*;
9 import com.intellij.openapi.compiler.Compiler;
10 import com.intellij.openapi.extensions.Extensions;
11 import com.intellij.openapi.fileTypes.FileType;
12 import com.intellij.openapi.fileTypes.StdFileTypes;
13 import com.intellij.openapi.module.Module;
14 import com.intellij.openapi.project.Project;
15 import com.intellij.openapi.vfs.LocalFileSystem;
16 import com.intellij.openapi.vfs.VirtualFile;
17 import com.intellij.packaging.impl.compiler.IncrementalArtifactsCompiler;
18 import com.intellij.util.ArrayUtil;
19 import com.intellij.util.Chunk;
20 import com.intellij.util.containers.ContainerUtil;
21 import com.intellij.util.graph.CachingSemiGraph;
22 import com.intellij.util.graph.Graph;
23 import com.intellij.util.graph.GraphGenerator;
24 import com.intellij.util.messages.MessageBus;
25 import com.intellij.util.messages.MessageBusConnection;
26 import org.jetbrains.annotations.NotNull;
27 import org.jetbrains.annotations.Nullable;
29 import java.lang.reflect.Array;
30 import java.util.*;
31 import java.util.concurrent.Semaphore;
33 public class CompilerManagerImpl extends CompilerManager {
34 private final Project myProject;
36 private final List<Compiler> myCompilers = new ArrayList<Compiler>();
37 private final List<TranslatingCompiler> myTranslators = new ArrayList<TranslatingCompiler>();
39 private final List<CompileTask> myBeforeTasks = new ArrayList<CompileTask>();
40 private final List<CompileTask> myAfterTasks = new ArrayList<CompileTask>();
41 private final Set<FileType> myCompilableTypes = new HashSet<FileType>();
42 private final CompilationStatusListener myEventPublisher;
43 private final Semaphore myCompilationSemaphore = new Semaphore(1, true);
44 private final Map<Compiler, Set<FileType>> myCompilerToInputTypes = new HashMap<Compiler, Set<FileType>>();
45 private final Map<Compiler, Set<FileType>> myCompilerToOutputTypes = new HashMap<Compiler, Set<FileType>>();
47 public CompilerManagerImpl(final Project project, CompilerConfigurationImpl compilerConfiguration, MessageBus messageBus) {
48 myProject = project;
49 myEventPublisher = messageBus.syncPublisher(CompilerTopics.COMPILATION_STATUS);
51 // predefined compilers
52 addTranslatingCompiler(new JavaCompiler(myProject), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA)), new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
53 // todo: enable compiler later
54 //addCompiler(new AnnotationProcessingCompiler(project));
55 addCompiler(new ResourceCompiler(project, compilerConfiguration));
56 addCompiler(new RmicCompiler());
57 addCompiler(new IncrementalPackagingCompiler());
58 addCompiler(new IncrementalArtifactsCompiler());
60 for(Compiler compiler: Extensions.getExtensions(Compiler.EP_NAME, myProject)) {
61 addCompiler(compiler);
63 for(CompilerFactory factory: Extensions.getExtensions(CompilerFactory.EP_NAME, myProject)) {
64 Compiler[] compilers = factory.createCompilers(this);
65 for (Compiler compiler : compilers) {
66 addCompiler(compiler);
70 addCompilableFileType(StdFileTypes.JAVA);
72 //addCompiler(new DummyTransformingCompiler()); // this one is for testing purposes only
73 //addCompiler(new DummySourceGeneratingCompiler(myProject)); // this one is for testing purposes only
75 // for testing only
76 ApplicationManager.getApplication().invokeLater(new Runnable() {
77 public void run() {
78 ApplicationManager.getApplication().runWriteAction(new Runnable() {
79 public void run() {
80 FileTypeManager.getInstance().registerFileType(DummyTranslatingCompiler.INPUT_FILE_TYPE, DummyTranslatingCompiler.FILETYPE_EXTENSION);
81 addTranslatingCompiler(
82 new DummyTranslatingCompiler(),
83 new HashSet<FileType>(Arrays.asList(DummyTranslatingCompiler.INPUT_FILE_TYPE)),
84 new HashSet<FileType>(Arrays.asList( StdFileTypes.JAVA))
87 });
90 });
94 public Semaphore getCompilationSemaphore() {
95 return myCompilationSemaphore;
98 public boolean isCompilationActive() {
99 return myCompilationSemaphore.availablePermits() == 0;
102 public void addTranslatingCompiler(@NotNull final TranslatingCompiler compiler, final Set<FileType> inputTypes, final Set<FileType> outputTypes) {
103 myTranslators.add(compiler);
104 myCompilerToInputTypes.put(compiler, inputTypes);
105 myCompilerToOutputTypes.put(compiler, outputTypes);
107 final List<Chunk<Compiler>> chunks = ModuleCompilerUtil.getSortedChunks(createCompilerGraph((List<Compiler>)(List)myTranslators));
109 myTranslators.clear();
110 for (Chunk<Compiler> chunk : chunks) {
111 for (Compiler chunkCompiler : chunk.getNodes()) {
112 myTranslators.add((TranslatingCompiler)chunkCompiler);
117 @NotNull
118 public Set<FileType> getRegisteredInputTypes(@NotNull final TranslatingCompiler compiler) {
119 final Set<FileType> inputs = myCompilerToInputTypes.get(compiler);
120 return inputs != null? Collections.unmodifiableSet(inputs) : Collections.<FileType>emptySet();
123 @NotNull
124 public Set<FileType> getRegisteredOutputTypes(@NotNull final TranslatingCompiler compiler) {
125 final Set<FileType> outs = myCompilerToOutputTypes.get(compiler);
126 return outs != null? Collections.unmodifiableSet(outs) : Collections.<FileType>emptySet();
129 public final void addCompiler(@NotNull Compiler compiler) {
130 if (compiler instanceof TranslatingCompiler) {
131 myTranslators.add((TranslatingCompiler)compiler);
134 else {
135 myCompilers.add(compiler);
139 public final void removeCompiler(@NotNull Compiler compiler) {
140 if (compiler instanceof TranslatingCompiler) {
141 myTranslators.remove(compiler);
143 else {
144 myCompilers.remove(compiler);
146 myCompilerToInputTypes.remove(compiler);
147 myCompilerToOutputTypes.remove(compiler);
150 @NotNull
151 public <T extends Compiler> T[] getCompilers(@NotNull Class<T> compilerClass) {
152 return getCompilers(compilerClass, CompilerFilter.ALL);
155 @NotNull
156 public <T extends Compiler> T[] getCompilers(@NotNull Class<T> compilerClass, CompilerFilter filter) {
157 final List<T> compilers = new ArrayList<T>(myCompilers.size());
158 for (final Compiler item : myCompilers) {
159 if (compilerClass.isAssignableFrom(item.getClass()) && filter.acceptCompiler(item)) {
160 compilers.add((T)item);
163 for (final Compiler item : myTranslators) {
164 if (compilerClass.isAssignableFrom(item.getClass()) && filter.acceptCompiler(item)) {
165 compilers.add((T)item);
168 final T[] array = (T[])Array.newInstance(compilerClass, compilers.size());
169 return compilers.toArray(array);
172 public void addCompilableFileType(@NotNull FileType type) {
173 myCompilableTypes.add(type);
176 public void removeCompilableFileType(@NotNull FileType type) {
177 myCompilableTypes.remove(type);
180 public boolean isCompilableFileType(@NotNull FileType type) {
181 return myCompilableTypes.contains(type);
184 public final void addBeforeTask(@NotNull CompileTask task) {
185 myBeforeTasks.add(task);
188 public final void addAfterTask(@NotNull CompileTask task) {
189 myAfterTasks.add(task);
192 @NotNull
193 public CompileTask[] getBeforeTasks() {
194 return myBeforeTasks.toArray(new CompileTask[myBeforeTasks.size()]);
197 @NotNull
198 public CompileTask[] getAfterTasks() {
199 return myAfterTasks.toArray(new CompileTask[myAfterTasks.size()]);
202 public void compile(@NotNull VirtualFile[] files, CompileStatusNotification callback, final boolean trackDependencies) {
203 compile(createFilesCompileScope(files), callback, trackDependencies);
206 public void compile(@NotNull Module module, CompileStatusNotification callback, final boolean trackDependencies) {
207 compile(createModuleCompileScope(module, false), callback, trackDependencies);
210 public void compile(@NotNull CompileScope scope, CompileStatusNotification callback, final boolean trackDependencies) {
211 new CompileDriver(myProject).compile(scope, new ListenerNotificator(callback), trackDependencies);
214 public void make(CompileStatusNotification callback) {
215 new CompileDriver(myProject).make(createProjectCompileScope(myProject), new ListenerNotificator(callback));
218 public void make(@NotNull Module module, CompileStatusNotification callback) {
219 new CompileDriver(myProject).make(createModuleCompileScope(module, true), new ListenerNotificator(callback));
222 public void make(@NotNull Project project, @NotNull Module[] modules, CompileStatusNotification callback) {
223 new CompileDriver(myProject).make(createModuleGroupCompileScope(project, modules, true), new ListenerNotificator(callback));
226 public void make(@NotNull CompileScope scope, CompileStatusNotification callback) {
227 new CompileDriver(myProject).make(scope, new ListenerNotificator(callback));
230 public void make(@NotNull CompileScope scope, CompilerFilter filter, @Nullable CompileStatusNotification callback) {
231 final CompileDriver compileDriver = new CompileDriver(myProject);
232 compileDriver.setCompilerFilter(filter);
233 compileDriver.make(scope, new ListenerNotificator(callback));
236 public boolean isUpToDate(@NotNull final CompileScope scope) {
237 return new CompileDriver(myProject).isUpToDate(scope);
240 public void rebuild(CompileStatusNotification callback) {
241 new CompileDriver(myProject).rebuild(new ListenerNotificator(callback));
244 public void executeTask(@NotNull CompileTask task, @NotNull CompileScope scope, String contentName, Runnable onTaskFinished) {
245 final CompileDriver compileDriver = new CompileDriver(myProject);
246 compileDriver.executeCompileTask(task, scope, contentName, onTaskFinished);
249 private final Map<CompilationStatusListener, MessageBusConnection> myListenerAdapters = new HashMap<CompilationStatusListener, MessageBusConnection>();
251 public void addCompilationStatusListener(@NotNull final CompilationStatusListener listener) {
252 final MessageBusConnection connection = myProject.getMessageBus().connect();
253 myListenerAdapters.put(listener, connection);
254 connection.subscribe(CompilerTopics.COMPILATION_STATUS, listener);
257 public void removeCompilationStatusListener(@NotNull final CompilationStatusListener listener) {
258 final MessageBusConnection connection = myListenerAdapters.remove(listener);
259 if (connection != null) {
260 connection.disconnect();
264 // Compiler tests support
266 private static List<String> ourDeletedPaths;
267 private static List<String> ourRecompiledPaths;
268 private static List<String> ourCompiledPaths;
270 public static void testSetup() {
271 ourDeletedPaths = new ArrayList<String>();
272 ourRecompiledPaths = new ArrayList<String>();
273 ourCompiledPaths = new ArrayList<String>();
277 * @param path a relative to output directory path
279 public static void addDeletedPath(String path) {
280 ourDeletedPaths.add(path);
283 public static void addRecompiledPath(String path) {
284 ourRecompiledPaths.add(path);
287 public static void addCompiledPath(String path) {
288 ourCompiledPaths.add(path);
291 public static String[] getPathsToDelete() {
292 return ArrayUtil.toStringArray(ourDeletedPaths);
295 public static String[] getPathsToRecompile() {
296 return ArrayUtil.toStringArray(ourRecompiledPaths);
299 public static String[] getPathsToCompile() {
300 return ArrayUtil.toStringArray(ourCompiledPaths);
303 public static void clearPathsToCompile() {
304 if (ourCompiledPaths != null) {
305 ourCompiledPaths.clear();
309 public boolean isExcludedFromCompilation(@NotNull VirtualFile file) {
310 return CompilerConfiguration.getInstance(myProject).isExcludedFromCompilation(file);
313 private static final OutputToSourceMapping OUTPUT_TO_SOURCE_MAPPING = new OutputToSourceMapping() {
314 public String getSourcePath(final String outputPath) {
315 final LocalFileSystem lfs = LocalFileSystem.getInstance();
316 final VirtualFile outputFile = lfs.findFileByPath(outputPath);
318 final VirtualFile sourceFile = outputFile != null ? TranslatingCompilerFilesMonitor.getSourceFileByOutput(outputFile) : null;
319 return sourceFile != null? sourceFile.getPath() : null;
322 @NotNull
323 public OutputToSourceMapping getJavaCompilerOutputMapping() {
324 return OUTPUT_TO_SOURCE_MAPPING;
327 @NotNull
328 public CompileScope createFilesCompileScope(@NotNull final VirtualFile[] files) {
329 CompileScope[] scopes = new CompileScope[files.length];
330 for(int i = 0; i < files.length; i++){
331 scopes[i] = new OneProjectItemCompileScope(myProject, files[i]);
333 return new CompositeScope(scopes);
336 @NotNull
337 public CompileScope createModuleCompileScope(@NotNull final Module module, final boolean includeDependentModules) {
338 return new ModuleCompileScope(module, includeDependentModules);
341 @NotNull
342 public CompileScope createModulesCompileScope(@NotNull final Module[] modules, final boolean includeDependentModules) {
343 return new ModuleCompileScope(myProject, modules, includeDependentModules);
346 @NotNull
347 public CompileScope createModuleGroupCompileScope(@NotNull final Project project, @NotNull final Module[] modules, final boolean includeDependentModules) {
348 return new ModuleCompileScope(project, modules, includeDependentModules);
351 @NotNull
352 public CompileScope createProjectCompileScope(@NotNull final Project project) {
353 return new ProjectCompileScope(project);
356 private Graph<Compiler> createCompilerGraph(final List<Compiler> compilers) {
357 return GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<Compiler>() {
358 public Collection<Compiler> getNodes() {
359 return compilers;
362 public Iterator<Compiler> getIn(Compiler compiler) {
363 final Set<FileType> compilerInput = myCompilerToInputTypes.get(compiler);
364 if (compilerInput == null || compilerInput.isEmpty()) {
365 return Collections.<Compiler>emptySet().iterator();
368 final Set<Compiler> inCompilers = new HashSet<Compiler>();
370 for (Map.Entry<Compiler, Set<FileType>> entry : myCompilerToOutputTypes.entrySet()) {
371 final Set<FileType> outputs = entry.getValue();
372 Compiler comp = entry.getKey();
373 if (outputs != null && ContainerUtil.intersects(compilerInput, outputs)) {
374 inCompilers.add(comp);
377 return inCompilers.iterator();
379 }));
382 private class ListenerNotificator implements CompileStatusNotification {
383 private final CompileStatusNotification myDelegate;
385 private ListenerNotificator(CompileStatusNotification delegate) {
386 myDelegate = delegate;
389 public void finished(boolean aborted, int errors, int warnings, final CompileContext compileContext) {
390 myEventPublisher.compilationFinished(aborted, errors, warnings, compileContext);
391 if (myDelegate != null) {
392 myDelegate.finished(aborted, errors, warnings, compileContext);