annotation processors UI

This commit is contained in:
Eugene Zhuravlev
2009-10-12 13:25:39 +04:00
parent 9b472aa982
commit 2a6366f8f2
8 changed files with 227 additions and 25 deletions
@@ -9,6 +9,7 @@
package com.intellij.compiler;
import com.intellij.CommonBundle;
import com.intellij.ProjectTopics;
import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
import com.intellij.compiler.impl.javaCompiler.api.CompilerAPICompiler;
import com.intellij.compiler.impl.javaCompiler.eclipse.EclipseCompiler;
@@ -22,6 +23,9 @@ import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.ModuleListener;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.InputValidator;
import com.intellij.openapi.ui.Messages;
@@ -63,6 +67,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
private final List<Pair<Pattern, Pattern>> myNegatedCompiledPatterns = new ArrayList<Pair<Pattern, Pattern>>();
private boolean myWildcardPatternsInitialized = false;
private final Project myProject;
private final ModuleManager myModuleManager;
private final ExcludedEntriesConfiguration myExcludedEntriesConfiguration;
public int DEPLOY_AFTER_MAKE = Options.SHOW_DIALOG;
@@ -75,10 +80,37 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
loadDefaultWildcardPatterns();
}
public CompilerConfigurationImpl(Project project) {
private boolean myEnableAnnotationProcessors = false;
private final Map<String, String> myProcessorsMap = new HashMap<String, String>(); // map: AnnotationProcessorName -> options
private boolean myObtainProcessorsFromClasspath = true;
private String myProcessorPath = "";
private final Set<Module> myExcludedModules = new HashSet<Module>();
private final Set<String> myExcludedModuleNames = new HashSet<String>();
public CompilerConfigurationImpl(Project project, ModuleManager moduleManager) {
myProject = project;
myModuleManager = moduleManager;
myExcludedEntriesConfiguration = new ExcludedEntriesConfiguration();
Disposer.register(project, myExcludedEntriesConfiguration);
project.getMessageBus().connect(project).subscribe(ProjectTopics.MODULES, new ModuleListener() {
public void modulesRenamed(Project project, List<Module> modules) {
}
public void moduleRemoved(Project project, Module module) {
}
public void beforeModuleRemoved(Project project, Module module) {
myExcludedModules.remove(module);
myExcludedModuleNames.remove(module.getName());
}
public void moduleAdded(Project project, Module module) {
if (myExcludedModuleNames.remove(module.getName())) {
myExcludedModules.add(module);
}
}
});
}
public Element getState() {
@@ -262,6 +294,49 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
return isResourceFile(virtualFile.getName(), virtualFile.getParent());
}
public boolean isAnnotationProcessorsEnabled() {
return myEnableAnnotationProcessors;
}
public void setAnnotationProcessorsEnabled(boolean enableAnnotationProcessors) {
myEnableAnnotationProcessors = enableAnnotationProcessors;
}
public boolean isObtainProcessorsFromClasspath() {
return myObtainProcessorsFromClasspath;
}
public void setObtainProcessorsFromClasspath(boolean obtainProcessorsFromClasspath) {
myObtainProcessorsFromClasspath = obtainProcessorsFromClasspath;
}
public String getProcessorPath() {
return myProcessorPath;
}
public void setProcessorsPath(String processorsPath) {
myProcessorPath = processorsPath;
}
public Map<String, String> getAnnotationProcessorsMap() {
return Collections.unmodifiableMap(myProcessorsMap);
}
public void setAnnotationProcessorsMap(Map<String, String> map) {
myProcessorsMap.clear();
myProcessorsMap.putAll(map);
}
public Set<Module> getExcludedModules() {
return Collections.unmodifiableSet(myExcludedModules);
}
public void setExcludedModules(Collection<Module> modules) {
myExcludedModules.clear();
myExcludedModuleNames.clear();
myExcludedModules.addAll(modules);
}
private void addWildcardResourcePattern(@NonNls final String wildcardPattern) throws MalformedPatternException {
final Pair<Pattern, Pattern> pattern = convertToRegexp(wildcardPattern);
if (pattern != null) {
@@ -400,6 +475,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
// property names
@NonNls private static final String EXCLUDE_FROM_COMPILE = "excludeFromCompile";
@NonNls private static final String RESOURCE_EXTENSIONS = "resourceExtensions";
@NonNls private static final String ANNOTATION_PROCESSING = "annotationProcessing";
@NonNls private static final String WILDCARD_RESOURCE_PATTERNS = "wildcardResourcePatterns";
@NonNls private static final String ENTRY = "entry";
@NonNls private static final String NAME = "name";
@@ -442,6 +518,52 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
throw new InvalidDataException(e);
}
final Element annotationProcessingSettings = parentNode.getChild(ANNOTATION_PROCESSING);
if (annotationProcessingSettings != null) {
myEnableAnnotationProcessors = Boolean.valueOf(annotationProcessingSettings.getAttributeValue("enabled", "false"));
myObtainProcessorsFromClasspath = Boolean.valueOf(annotationProcessingSettings.getAttributeValue("useClasspath", "true"));
final StringBuilder pathBuilder = new StringBuilder();
for (Element pathElement : ((Collection<Element>)annotationProcessingSettings.getChildren("processorPath"))) {
final String path = pathElement.getAttributeValue("value");
if (path != null) {
if (pathBuilder.length() > 0) {
pathBuilder.append(File.pathSeparator);
}
pathBuilder.append(path);
}
}
myProcessorPath = pathBuilder.toString();
myProcessorPath = annotationProcessingSettings.getAttributeValue("processorPath", "");
myProcessorsMap.clear();
for (Element processorChild : ((Collection<Element>)annotationProcessingSettings.getChildren("processor"))) {
final String name = processorChild.getAttributeValue("name");
final String options = processorChild.getAttributeValue("options", "");
myProcessorsMap.put(name, options);
}
myExcludedModules.clear();
myExcludedModuleNames.clear();
final Collection<Element> excluded = (Collection<Element>)annotationProcessingSettings.getChildren("excludeModule");
if (excluded.size() > 0) {
final Map<String, Module> moduleMap = new com.intellij.util.containers.HashMap<String, Module>();
for (Module module : myModuleManager.getModules()) {
moduleMap.put(module.getName(), module);
}
for (Element moduleElement : excluded) {
final String name = moduleElement.getAttributeValue("name");
if (name != null) {
final Module module = moduleMap.get(name);
if (module != null) {
myExcludedModules.add(module);
}
else {
myExcludedModuleNames.add(name);
}
}
}
}
}
}
public void writeExternal(Element parentNode) throws WriteExternalException {
@@ -453,9 +575,8 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
parentNode.addContent(newChild);
}
String[] patterns = getRegexpPatterns();
final Element newChild = new Element(RESOURCE_EXTENSIONS);
for (final String pattern : patterns) {
for (final String pattern : getRegexpPatterns()) {
final Element entry = new Element(ENTRY);
entry.setAttribute(NAME, pattern);
newChild.addContent(entry);
@@ -471,6 +592,37 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
}
parentNode.addContent(wildcardPatterns);
}
final Element annotationProcessingSettings = new Element(ANNOTATION_PROCESSING);
parentNode.addContent(annotationProcessingSettings);
annotationProcessingSettings.setAttribute("enabled", String.valueOf(myEnableAnnotationProcessors));
annotationProcessingSettings.setAttribute("useClasspath", String.valueOf(myObtainProcessorsFromClasspath));
if (myProcessorPath.length() > 0) {
final StringTokenizer tokenizer = new StringTokenizer(myProcessorPath, File.pathSeparator, false);
while (tokenizer.hasMoreTokens()) {
final String path = tokenizer.nextToken();
final Element pathElement = new Element("processorPath");
annotationProcessingSettings.addContent(pathElement);
pathElement.setAttribute("value", path);
}
}
for (Map.Entry<String, String> entry : myProcessorsMap.entrySet()) {
final Element processor = new Element("processor");
annotationProcessingSettings.addContent(processor);
processor.setAttribute("name", entry.getKey());
processor.setAttribute("options", entry.getValue());
}
final List<Module> modules = new ArrayList<Module>(getExcludedModules());
Collections.sort(modules, new Comparator<Module>() {
public int compare(Module o1, Module o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
});
for (Module module : modules) {
final Element moduleElement = new Element("excludeModule");
annotationProcessingSettings.addContent(moduleElement);
moduleElement.setAttribute("name", module.getName());
}
}
@NotNull @NonNls
@@ -16,6 +16,7 @@
package com.intellij.compiler;
import com.intellij.compiler.impl.*;
import com.intellij.compiler.impl.javaCompiler.AnnotationProcessingCompiler;
import com.intellij.compiler.impl.javaCompiler.JavaCompiler;
import com.intellij.compiler.impl.packagingCompiler.IncrementalPackagingCompiler;
import com.intellij.compiler.impl.resourceCompiler.ResourceCompiler;
@@ -65,8 +66,7 @@ public class CompilerManagerImpl extends CompilerManager {
// predefined compilers
addTranslatingCompiler(new JavaCompiler(myProject), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA)), new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
// todo: enable compiler later
//addCompiler(new AnnotationProcessingCompiler(project));
addCompiler(new AnnotationProcessingCompiler(project));
addCompiler(new ResourceCompiler(project, compilerConfiguration));
addCompiler(new RmicCompiler());
addCompiler(new IncrementalPackagingCompiler());
@@ -38,10 +38,7 @@ import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
public class AnnotationProcessingCompiler implements SourceProcessingCompiler{
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.JavaCompiler");
@@ -58,16 +55,23 @@ public class AnnotationProcessingCompiler implements SourceProcessingCompiler{
@NotNull
public ProcessingItem[] getProcessingItems(CompileContext context) {
final VirtualFile[] files = context.getCompileScope().getFiles(StdFileTypes.JAVA, true);
ProcessingItem[] items = new ProcessingItem[files.length];
for (int idx = 0; idx < files.length; idx++) {
items[idx] = new MyProcessingItem(files[idx]);
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
if (!config.isAnnotationProcessorsEnabled()) {
return ProcessingItem.EMPTY_ARRAY;
}
return items;
final VirtualFile[] files = context.getCompileScope().getFiles(StdFileTypes.JAVA, true);
final List<ProcessingItem> items = new ArrayList<ProcessingItem>(files.length);
final Set<Module> excludedModules = config.getExcludedModules();
for (final VirtualFile file : files) {
if (excludedModules.size() == 0 || !excludedModules.contains(context.getModuleByFile(file))) {
items.add(new MyProcessingItem(file));
}
}
return items.toArray(new ProcessingItem[items.size()]);
}
public ProcessingItem[] process(CompileContext context, ProcessingItem[] items) {
VirtualFile[] files = new VirtualFile[items.length];
final VirtualFile[] files = new VirtualFile[items.length];
for (int idx = 0; idx < items.length; idx++) {
files[idx] = items[idx].getFile();
}
@@ -15,6 +15,7 @@
*/
package com.intellij.compiler.impl.javaCompiler.javac;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.compiler.CompilerIOUtil;
import com.intellij.compiler.OutputParser;
@@ -285,10 +286,29 @@ public class JavacCompiler extends ExternalCompiler {
isAnnotationProcessing = false; // makes no sense for these versions
}
if (isAnnotationProcessing) {
final CompilerConfiguration config = CompilerConfiguration.getInstance(javacSettings.getProject());
additionalOptions.add("-Xprefer:source");
additionalOptions.add("-implicit:none");
additionalOptions.add("-proc:only");
// todo: temporary!
if (!config.isObtainProcessorsFromClasspath()) {
final String processorPath = config.getProcessorPath();
if (processorPath.length() > 0) {
additionalOptions.add("-processorpath");
additionalOptions.add(FileUtil.toSystemDependentName(processorPath));
}
}
for (Map.Entry<String, String> entry : config.getAnnotationProcessorsMap().entrySet()) {
additionalOptions.add("-processor");
additionalOptions.add(entry.getKey());
final String options = entry.getValue();
if (options.length() > 0) {
StringTokenizer optionsTokenizer = new StringTokenizer(options, " ", false);
while (optionsTokenizer.hasMoreTokens()) {
final String token = optionsTokenizer.nextToken();
additionalOptions.add("-A"+token);
}
}
}
//additionalOptions.add("-processor");
//additionalOptions.add("CheckNamesProcessor");
//additionalOptions.add("org.apache.openjpa.persistence.meta.AnnotationProcessor6");
@@ -358,12 +378,15 @@ public class JavacCompiler extends ExternalCompiler {
}
if (isAnnotationProcessingMode) {
// todo: come up with some solution about the path for generated sources
commandLine.add("-s");
commandLine.add(outputPath.replace('/', File.separatorChar));
commandLine.add("-d");
commandLine.add(outputPath.replace('/', File.separatorChar));
}
else {
commandLine.add("-d");
commandLine.add(outputPath.replace('/', File.separatorChar));
}
commandLine.add("-d");
commandLine.add(outputPath.replace('/', File.separatorChar));
}
private static void addClassPathValue(final Sdk jdk, final boolean isVersion1_0, final List<String> commandLine, final String cpString, @NonNls final String tempFileName,
@@ -53,6 +53,10 @@ public class JavacSettings implements PersistentStateComponent<Element> {
myProject = project;
}
public Project getProject() {
return myProject;
}
public Element getState() {
try {
final Element e = new Element("state");
@@ -136,6 +136,7 @@ public class CompilerConfigurable implements SearchableConfigurable.Parent {
}
additional.add(0, new RmicConfigurable(RmicSettings.getInstance(myProject)));
additional.add(0, new AnnotationProcessorsConfigurable(myProject));
additional.add(0, new JavaCompilersTab(myProject, compilerConfiguration.getRegisteredJavaCompilers(), compilerConfiguration.getDefaultCompiler()));
kids.addAll(additional);
@@ -16,9 +16,14 @@
package com.intellij.compiler;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
public abstract class CompilerConfiguration {
// need this flag for profiling purposes. In production code is always set to 'true'
public static final boolean MAKE_ENABLED = true;
@@ -35,4 +40,23 @@ public abstract class CompilerConfiguration {
public abstract void addResourceFilePattern(String namePattern) throws MalformedPatternException;
public abstract boolean isAnnotationProcessorsEnabled();
public abstract void setAnnotationProcessorsEnabled(boolean enableAnnotationProcessors);
public abstract boolean isObtainProcessorsFromClasspath();
public abstract void setObtainProcessorsFromClasspath(boolean obtainProcessorsFromClasspath);
public abstract String getProcessorPath();
public abstract void setProcessorsPath(String processorsPath);
public abstract Map<String, String> getAnnotationProcessorsMap();
public abstract void setAnnotationProcessorsMap(Map<String, String> map);
public abstract Set<Module> getExcludedModules();
public abstract void setExcludedModules(Collection<Module> modules);
}
@@ -15,11 +15,5 @@
*/
package com.intellij.openapi.compiler;
/**
* A tag interface indicating that the compiler will instrument java sources.
* This affects the order of compiler calls:
* The sequence in which compilers are called:
* SourceGeneratingCompiler -> SourceInstrumentingCompiler -> TranslatingCompiler -> ClassInstrumentingCompiler -> ClassPostProcessingCompiler -> Validator
*/
public interface SourceProcessingCompiler extends FileProcessingCompiler, IntermediateOutputCompiler {
}