Make: heuristics for processing removed constant fields added. If precise analysis...
[fedora-idea.git] / java / compiler / impl / src / com / intellij / compiler / CompilerManagerImpl.java
blob1f5fbdf98164ca6b42041f6e85f54ecb2ffe632c
1 /*
2 * Copyright 2000-2009 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 com.intellij.compiler;
18 import com.intellij.compiler.impl.*;
19 import com.intellij.compiler.impl.javaCompiler.AnnotationProcessingCompiler;
20 import com.intellij.compiler.impl.javaCompiler.JavaCompiler;
21 import com.intellij.compiler.impl.resourceCompiler.ResourceCompiler;
22 import com.intellij.compiler.impl.rmiCompiler.RmicCompiler;
23 import com.intellij.openapi.compiler.*;
24 import com.intellij.openapi.compiler.Compiler;
25 import com.intellij.openapi.extensions.Extensions;
26 import com.intellij.openapi.fileTypes.FileType;
27 import com.intellij.openapi.fileTypes.StdFileTypes;
28 import com.intellij.openapi.module.Module;
29 import com.intellij.openapi.project.Project;
30 import com.intellij.openapi.vfs.LocalFileSystem;
31 import com.intellij.openapi.vfs.VirtualFile;
32 import com.intellij.packaging.impl.compiler.IncrementalArtifactsCompiler;
33 import com.intellij.util.ArrayUtil;
34 import com.intellij.util.Chunk;
35 import com.intellij.util.containers.ContainerUtil;
36 import com.intellij.util.graph.CachingSemiGraph;
37 import com.intellij.util.graph.Graph;
38 import com.intellij.util.graph.GraphGenerator;
39 import com.intellij.util.messages.MessageBus;
40 import com.intellij.util.messages.MessageBusConnection;
41 import org.jetbrains.annotations.NotNull;
42 import org.jetbrains.annotations.Nullable;
44 import java.lang.reflect.Array;
45 import java.util.*;
46 import java.util.concurrent.Semaphore;
48 public class CompilerManagerImpl extends CompilerManager {
49 private final Project myProject;
51 private final List<Compiler> myCompilers = new ArrayList<Compiler>();
52 private final List<TranslatingCompiler> myTranslators = new ArrayList<TranslatingCompiler>();
54 private final List<CompileTask> myBeforeTasks = new ArrayList<CompileTask>();
55 private final List<CompileTask> myAfterTasks = new ArrayList<CompileTask>();
56 private final Set<FileType> myCompilableTypes = new HashSet<FileType>();
57 private final CompilationStatusListener myEventPublisher;
58 private final Semaphore myCompilationSemaphore = new Semaphore(1, true);
59 private final Map<Compiler, Set<FileType>> myCompilerToInputTypes = new HashMap<Compiler, Set<FileType>>();
60 private final Map<Compiler, Set<FileType>> myCompilerToOutputTypes = new HashMap<Compiler, Set<FileType>>();
62 public CompilerManagerImpl(final Project project, CompilerConfigurationImpl compilerConfiguration, MessageBus messageBus) {
63 myProject = project;
64 myEventPublisher = messageBus.syncPublisher(CompilerTopics.COMPILATION_STATUS);
66 // predefined compilers
67 addTranslatingCompiler(new AnnotationProcessingCompiler(project), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA)), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA, StdFileTypes.CLASS)));
68 addTranslatingCompiler(new JavaCompiler(project), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA)), new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
69 addCompiler(new ResourceCompiler(project, compilerConfiguration));
70 addCompiler(new RmicCompiler());
71 addCompiler(new IncrementalArtifactsCompiler());
73 for(Compiler compiler: Extensions.getExtensions(Compiler.EP_NAME, myProject)) {
74 addCompiler(compiler);
76 for(CompilerFactory factory: Extensions.getExtensions(CompilerFactory.EP_NAME, myProject)) {
77 Compiler[] compilers = factory.createCompilers(this);
78 for (Compiler compiler : compilers) {
79 addCompiler(compiler);
83 addCompilableFileType(StdFileTypes.JAVA);
85 //addCompiler(new DummyTransformingCompiler()); // this one is for testing purposes only
86 //addCompiler(new DummySourceGeneratingCompiler(myProject)); // this one is for testing purposes only
88 // for testing only
89 ApplicationManager.getApplication().invokeLater(new Runnable() {
90 public void run() {
91 ApplicationManager.getApplication().runWriteAction(new Runnable() {
92 public void run() {
93 FileTypeManager.getInstance().registerFileType(DummyTranslatingCompiler.INPUT_FILE_TYPE, DummyTranslatingCompiler.FILETYPE_EXTENSION);
94 addTranslatingCompiler(
95 new DummyTranslatingCompiler(),
96 new HashSet<FileType>(Arrays.asList(DummyTranslatingCompiler.INPUT_FILE_TYPE)),
97 new HashSet<FileType>(Arrays.asList( StdFileTypes.JAVA))
107 public Semaphore getCompilationSemaphore() {
108 return myCompilationSemaphore;
111 public boolean isCompilationActive() {
112 return myCompilationSemaphore.availablePermits() == 0;
115 public void addTranslatingCompiler(@NotNull final TranslatingCompiler compiler, final Set<FileType> inputTypes, final Set<FileType> outputTypes) {
116 myTranslators.add(compiler);
117 myCompilerToInputTypes.put(compiler, inputTypes);
118 myCompilerToOutputTypes.put(compiler, outputTypes);
120 final List<Chunk<Compiler>> chunks = ModuleCompilerUtil.getSortedChunks(createCompilerGraph((List<Compiler>)(List)myTranslators));
122 myTranslators.clear();
123 for (Chunk<Compiler> chunk : chunks) {
124 for (Compiler chunkCompiler : chunk.getNodes()) {
125 myTranslators.add((TranslatingCompiler)chunkCompiler);
130 @NotNull
131 public Set<FileType> getRegisteredInputTypes(@NotNull final TranslatingCompiler compiler) {
132 final Set<FileType> inputs = myCompilerToInputTypes.get(compiler);
133 return inputs != null? Collections.unmodifiableSet(inputs) : Collections.<FileType>emptySet();
136 @NotNull
137 public Set<FileType> getRegisteredOutputTypes(@NotNull final TranslatingCompiler compiler) {
138 final Set<FileType> outs = myCompilerToOutputTypes.get(compiler);
139 return outs != null? Collections.unmodifiableSet(outs) : Collections.<FileType>emptySet();
142 public final void addCompiler(@NotNull Compiler compiler) {
143 if (compiler instanceof TranslatingCompiler) {
144 myTranslators.add((TranslatingCompiler)compiler);
147 else {
148 myCompilers.add(compiler);
152 public final void removeCompiler(@NotNull Compiler compiler) {
153 if (compiler instanceof TranslatingCompiler) {
154 myTranslators.remove(compiler);
156 else {
157 myCompilers.remove(compiler);
159 myCompilerToInputTypes.remove(compiler);
160 myCompilerToOutputTypes.remove(compiler);
163 @NotNull
164 public <T extends Compiler> T[] getCompilers(@NotNull Class<T> compilerClass) {
165 return getCompilers(compilerClass, CompilerFilter.ALL);
168 @NotNull
169 public <T extends Compiler> T[] getCompilers(@NotNull Class<T> compilerClass, CompilerFilter filter) {
170 final List<T> compilers = new ArrayList<T>(myCompilers.size());
171 for (final Compiler item : myCompilers) {
172 if (compilerClass.isAssignableFrom(item.getClass()) && filter.acceptCompiler(item)) {
173 compilers.add((T)item);
176 for (final Compiler item : myTranslators) {
177 if (compilerClass.isAssignableFrom(item.getClass()) && filter.acceptCompiler(item)) {
178 compilers.add((T)item);
181 final T[] array = (T[])Array.newInstance(compilerClass, compilers.size());
182 return compilers.toArray(array);
185 public void addCompilableFileType(@NotNull FileType type) {
186 myCompilableTypes.add(type);
189 public void removeCompilableFileType(@NotNull FileType type) {
190 myCompilableTypes.remove(type);
193 public boolean isCompilableFileType(@NotNull FileType type) {
194 return myCompilableTypes.contains(type);
197 public final void addBeforeTask(@NotNull CompileTask task) {
198 myBeforeTasks.add(task);
201 public final void addAfterTask(@NotNull CompileTask task) {
202 myAfterTasks.add(task);
205 @NotNull
206 public CompileTask[] getBeforeTasks() {
207 return myBeforeTasks.toArray(new CompileTask[myBeforeTasks.size()]);
210 @NotNull
211 public CompileTask[] getAfterTasks() {
212 return myAfterTasks.toArray(new CompileTask[myAfterTasks.size()]);
215 public void compile(@NotNull VirtualFile[] files, CompileStatusNotification callback, final boolean trackDependencies) {
216 compile(createFilesCompileScope(files), callback, trackDependencies);
219 public void compile(@NotNull Module module, CompileStatusNotification callback, final boolean trackDependencies) {
220 new CompileDriver(myProject).compile(createModuleCompileScope(module, false), new ListenerNotificator(callback), trackDependencies, true);
223 public void compile(@NotNull CompileScope scope, CompileStatusNotification callback, final boolean trackDependencies) {
224 new CompileDriver(myProject).compile(scope, new ListenerNotificator(callback), trackDependencies, false);
227 public void make(CompileStatusNotification callback) {
228 new CompileDriver(myProject).make(createProjectCompileScope(myProject), new ListenerNotificator(callback));
231 public void make(@NotNull Module module, CompileStatusNotification callback) {
232 new CompileDriver(myProject).make(createModuleCompileScope(module, true), new ListenerNotificator(callback));
235 public void make(@NotNull Project project, @NotNull Module[] modules, CompileStatusNotification callback) {
236 new CompileDriver(myProject).make(createModuleGroupCompileScope(project, modules, true), new ListenerNotificator(callback));
239 public void make(@NotNull CompileScope scope, CompileStatusNotification callback) {
240 new CompileDriver(myProject).make(scope, new ListenerNotificator(callback));
243 public void make(@NotNull CompileScope scope, CompilerFilter filter, @Nullable CompileStatusNotification callback) {
244 final CompileDriver compileDriver = new CompileDriver(myProject);
245 compileDriver.setCompilerFilter(filter);
246 compileDriver.make(scope, new ListenerNotificator(callback));
249 public boolean isUpToDate(@NotNull final CompileScope scope) {
250 return new CompileDriver(myProject).isUpToDate(scope);
253 public void rebuild(CompileStatusNotification callback) {
254 new CompileDriver(myProject).rebuild(new ListenerNotificator(callback));
257 public void executeTask(@NotNull CompileTask task, @NotNull CompileScope scope, String contentName, Runnable onTaskFinished) {
258 final CompileDriver compileDriver = new CompileDriver(myProject);
259 compileDriver.executeCompileTask(task, scope, contentName, onTaskFinished);
262 private final Map<CompilationStatusListener, MessageBusConnection> myListenerAdapters = new HashMap<CompilationStatusListener, MessageBusConnection>();
264 public void addCompilationStatusListener(@NotNull final CompilationStatusListener listener) {
265 final MessageBusConnection connection = myProject.getMessageBus().connect();
266 myListenerAdapters.put(listener, connection);
267 connection.subscribe(CompilerTopics.COMPILATION_STATUS, listener);
270 public void removeCompilationStatusListener(@NotNull final CompilationStatusListener listener) {
271 final MessageBusConnection connection = myListenerAdapters.remove(listener);
272 if (connection != null) {
273 connection.disconnect();
277 // Compiler tests support
279 private static List<String> ourDeletedPaths;
280 private static List<String> ourRecompiledPaths;
281 private static List<String> ourCompiledPaths;
283 public static void testSetup() {
284 ourDeletedPaths = new ArrayList<String>();
285 ourRecompiledPaths = new ArrayList<String>();
286 ourCompiledPaths = new ArrayList<String>();
289 public static void addDeletedPath(String path) {
290 ourDeletedPaths.add(path);
293 public static void addRecompiledPath(String path) {
294 ourRecompiledPaths.add(path);
297 public static void addCompiledPath(String path) {
298 ourCompiledPaths.add(path);
301 public static String[] getPathsToDelete() {
302 return ArrayUtil.toStringArray(ourDeletedPaths);
305 public static String[] getPathsToRecompile() {
306 return ArrayUtil.toStringArray(ourRecompiledPaths);
309 public static String[] getPathsToCompile() {
310 return ArrayUtil.toStringArray(ourCompiledPaths);
313 public static void clearPathsToCompile() {
314 if (ourCompiledPaths != null) {
315 ourCompiledPaths.clear();
319 public boolean isExcludedFromCompilation(@NotNull VirtualFile file) {
320 return CompilerConfiguration.getInstance(myProject).isExcludedFromCompilation(file);
323 private static final OutputToSourceMapping OUTPUT_TO_SOURCE_MAPPING = new OutputToSourceMapping() {
324 public String getSourcePath(final String outputPath) {
325 final LocalFileSystem lfs = LocalFileSystem.getInstance();
326 final VirtualFile outputFile = lfs.findFileByPath(outputPath);
328 final VirtualFile sourceFile = outputFile != null ? TranslatingCompilerFilesMonitor.getSourceFileByOutput(outputFile) : null;
329 return sourceFile != null? sourceFile.getPath() : null;
332 @NotNull
333 public OutputToSourceMapping getJavaCompilerOutputMapping() {
334 return OUTPUT_TO_SOURCE_MAPPING;
337 @NotNull
338 public CompileScope createFilesCompileScope(@NotNull final VirtualFile[] files) {
339 CompileScope[] scopes = new CompileScope[files.length];
340 for(int i = 0; i < files.length; i++){
341 scopes[i] = new OneProjectItemCompileScope(myProject, files[i]);
343 return new CompositeScope(scopes);
346 @NotNull
347 public CompileScope createModuleCompileScope(@NotNull final Module module, final boolean includeDependentModules) {
348 return new ModuleCompileScope(module, includeDependentModules);
351 @NotNull
352 public CompileScope createModulesCompileScope(@NotNull final Module[] modules, final boolean includeDependentModules) {
353 return new ModuleCompileScope(myProject, modules, includeDependentModules);
356 @NotNull
357 public CompileScope createModuleGroupCompileScope(@NotNull final Project project, @NotNull final Module[] modules, final boolean includeDependentModules) {
358 return new ModuleCompileScope(project, modules, includeDependentModules);
361 @NotNull
362 public CompileScope createProjectCompileScope(@NotNull final Project project) {
363 return new ProjectCompileScope(project);
366 private Graph<Compiler> createCompilerGraph(final List<Compiler> compilers) {
367 return GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<Compiler>() {
368 public Collection<Compiler> getNodes() {
369 return compilers;
372 public Iterator<Compiler> getIn(Compiler compiler) {
373 final Set<FileType> compilerInput = myCompilerToInputTypes.get(compiler);
374 if (compilerInput == null || compilerInput.isEmpty()) {
375 return Collections.<Compiler>emptySet().iterator();
378 final Set<Compiler> inCompilers = new HashSet<Compiler>();
380 for (Map.Entry<Compiler, Set<FileType>> entry : myCompilerToOutputTypes.entrySet()) {
381 final Set<FileType> outputs = entry.getValue();
382 Compiler comp = entry.getKey();
383 if (outputs != null && ContainerUtil.intersects(compilerInput, outputs)) {
384 inCompilers.add(comp);
387 return inCompilers.iterator();
389 }));
392 private class ListenerNotificator implements CompileStatusNotification {
393 private final CompileStatusNotification myDelegate;
395 private ListenerNotificator(CompileStatusNotification delegate) {
396 myDelegate = delegate;
399 public void finished(boolean aborted, int errors, int warnings, final CompileContext compileContext) {
400 myEventPublisher.compilationFinished(aborted, errors, warnings, compileContext);
401 if (myDelegate != null) {
402 myDelegate.finished(aborted, errors, warnings, compileContext);