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.
18 * @author: Eugene Zhuravlev
22 package com
.intellij
.compiler
.impl
.javaCompiler
;
24 import com
.intellij
.compiler
.CompilerConfiguration
;
25 import com
.intellij
.compiler
.CompilerConfigurationImpl
;
26 import com
.intellij
.compiler
.CompilerException
;
27 import com
.intellij
.compiler
.impl
.javaCompiler
.javac
.JavacCompiler
;
28 import com
.intellij
.compiler
.make
.CacheCorruptedException
;
29 import com
.intellij
.openapi
.application
.ApplicationManager
;
30 import com
.intellij
.openapi
.compiler
.*;
31 import com
.intellij
.openapi
.compiler
.ex
.CompileContextEx
;
32 import com
.intellij
.openapi
.diagnostic
.Logger
;
33 import com
.intellij
.openapi
.fileTypes
.StdFileTypes
;
34 import com
.intellij
.openapi
.module
.Module
;
35 import com
.intellij
.openapi
.project
.Project
;
36 import com
.intellij
.openapi
.vfs
.VirtualFile
;
37 import com
.intellij
.util
.Chunk
;
38 import org
.jetbrains
.annotations
.NotNull
;
40 import java
.io
.DataInput
;
41 import java
.io
.IOException
;
44 public class AnnotationProcessingCompiler
implements SourceProcessingCompiler
{
45 private static final Logger LOG
= Logger
.getInstance("#com.intellij.compiler.impl.javaCompiler.JavaCompiler");
46 private final Project myProject
;
48 public AnnotationProcessingCompiler(Project project
) {
53 public String
getDescription() {
54 return CompilerBundle
.message("annotation.processing.compiler.description");
58 public ProcessingItem
[] getProcessingItems(CompileContext context
) {
59 final CompilerConfiguration config
= CompilerConfiguration
.getInstance(myProject
);
60 if (!config
.isAnnotationProcessorsEnabled()) {
61 return ProcessingItem
.EMPTY_ARRAY
;
63 final VirtualFile
[] files
= context
.getCompileScope().getFiles(StdFileTypes
.JAVA
, true);
64 final List
<ProcessingItem
> items
= new ArrayList
<ProcessingItem
>(files
.length
);
65 final Set
<Module
> excludedModules
= config
.getExcludedModules();
66 for (final VirtualFile file
: files
) {
67 if (excludedModules
.size() != 0 && excludedModules
.contains(context
.getModuleByFile(file
))) {
70 if (config
.isExcludedFromCompilation(file
)) {
73 items
.add(new MyProcessingItem(file
));
75 return items
.toArray(new ProcessingItem
[items
.size()]);
78 public ProcessingItem
[] process(CompileContext context
, ProcessingItem
[] items
) {
79 final VirtualFile
[] files
= new VirtualFile
[items
.length
];
80 for (int idx
= 0; idx
< items
.length
; idx
++) {
81 files
[idx
] = items
[idx
].getFile();
83 compile(context
, files
);
84 return context
.getMessageCount(CompilerMessageCategory
.ERROR
) == 0? items
: ProcessingItem
.EMPTY_ARRAY
;
87 public ValidityState
createValidityState(DataInput in
) throws IOException
{
91 private void compile(final CompileContext context
, final VirtualFile
[] files
) {
92 final JavacCompiler javacCompiler
= getBackEndCompiler();
93 final boolean processorMode
= javacCompiler
.setAnnotationProcessorMode(true);
94 final Chunk
<Module
> dummyChunk
= new Chunk
<Module
>(Collections
.<Module
>emptySet()); // TODO!
95 final BackendCompilerWrapper wrapper
= new BackendCompilerWrapper(dummyChunk
, myProject
, Arrays
.asList(files
), (CompileContextEx
)context
, javacCompiler
, DummySink
.INSTANCE
);
99 catch (CompilerException e
) {
100 context
.addMessage(CompilerMessageCategory
.ERROR
, e
.getMessage(), null, -1, -1);
102 catch (CacheCorruptedException e
) {
104 context
.requestRebuildNextTime(e
.getMessage());
107 javacCompiler
.setAnnotationProcessorMode(processorMode
);
108 final Set
<VirtualFile
> dirsToRefresh
= new HashSet
<VirtualFile
>();
109 ApplicationManager
.getApplication().runReadAction(new Runnable() {
111 final Set
<Module
> modules
= new HashSet
<Module
>();
112 for (VirtualFile file
: files
) {
113 final Module module
= context
.getModuleByFile(file
);
114 if (module
!= null) {
118 for (Module module
: modules
) {
119 dirsToRefresh
.add(context
.getModuleOutputDirectory(module
));
120 dirsToRefresh
.add(context
.getModuleOutputDirectoryForTests(module
));
121 // todo: Some annotation processors put files into the source code. So need to refresh module source roots.
122 // It is an open question whether we shall support such processors
123 //dirsToRefresh.addAll(Arrays.asList(ModuleRootManager.getInstance(module).getSourceRoots()));
127 for (VirtualFile root
: dirsToRefresh
) {
128 root
.refresh(false, true);
133 public boolean validateConfiguration(CompileScope scope
) {
134 final JavacCompiler compiler
= getBackEndCompiler();
135 final boolean previousValue
= compiler
.setAnnotationProcessorMode(true);
137 return compiler
.checkCompiler(scope
);
140 compiler
.setAnnotationProcessorMode(previousValue
);
144 private JavacCompiler
getBackEndCompiler() {
145 CompilerConfigurationImpl configuration
= (CompilerConfigurationImpl
)CompilerConfiguration
.getInstance(myProject
);
146 return configuration
.getJavacCompiler();
149 private static class MyProcessingItem
implements ProcessingItem
{
150 private final VirtualFile myFile
;
152 public MyProcessingItem(VirtualFile file
) {
157 public VirtualFile
getFile() {
161 public ValidityState
getValidityState() {
166 private static class DummySink
implements TranslatingCompiler
.OutputSink
{
167 public static final DummySink INSTANCE
= new DummySink();
168 public void add(String outputRoot
, Collection
<TranslatingCompiler
.OutputItem
> items
, VirtualFile
[] filesToRecompile
) {