mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
- annotation processors profiles
- out-of-process build: supported annotation processing configurable via profiles
This commit is contained in:
@@ -52,7 +52,6 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.apache.oro.text.regex.*;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -74,6 +73,12 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.CompilerConfiguration");
|
||||
@NonNls public static final String TESTS_EXTERNAL_COMPILER_HOME_PROPERTY_NAME = "tests.external.compiler.home";
|
||||
public static final int DEPENDENCY_FORMAT_VERSION = 55;
|
||||
private static final Comparator<String> ALPHA_COMPARATOR = new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
return o1.compareToIgnoreCase(o2);
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings({"WeakerAccess"}) public String DEFAULT_COMPILER;
|
||||
@NotNull private BackendCompiler myDefaultJavaCompiler;
|
||||
@@ -96,15 +101,14 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
{
|
||||
loadDefaultWildcardPatterns();
|
||||
}
|
||||
|
||||
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 Map<Module, String> myProcessedModules = new HashMap<Module, String>();
|
||||
private final Map<String, String> myModuleNames = new HashMap<String, String>();
|
||||
private boolean myAddNotNullAssertions = true;
|
||||
|
||||
private final ProcessorConfigProfile myDefaultProcessorsProfile = new ProcessorConfigProfile("Default");
|
||||
private final List<ProcessorConfigProfile> myModuleProcessorProfiles = new ArrayList<ProcessorConfigProfile>();
|
||||
|
||||
// the map is calculated by module processor profiles list for faster access to module settings
|
||||
private Map<Module, ProcessorConfigProfile> myProcessorsProfilesMap = null;
|
||||
|
||||
@Nullable
|
||||
private String myBytecodeTargetLevel = null; // null means compiler default
|
||||
private final Map<String, String> myModuleBytecodeTarget = new java.util.HashMap<String, String>();
|
||||
@@ -116,16 +120,11 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
Disposer.register(project, myExcludedEntriesConfiguration);
|
||||
project.getMessageBus().connect(project).subscribe(ProjectTopics.MODULES, new ModuleAdapter() {
|
||||
public void beforeModuleRemoved(Project project, Module module) {
|
||||
myProcessedModules.remove(module);
|
||||
myModuleNames.remove(module.getName());
|
||||
getAnnotationProcessingConfiguration(module).removeModuleName(module.getName());
|
||||
}
|
||||
|
||||
public void moduleAdded(Project project, Module module) {
|
||||
final String moduleName = module.getName();
|
||||
if (myModuleNames.containsKey(moduleName)) {
|
||||
final String dirName = myModuleNames.remove(moduleName);
|
||||
myProcessedModules.put(module, dirName);
|
||||
}
|
||||
myProcessorsProfilesMap = null; // clear cache
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -376,55 +375,62 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
myAddNotNullAssertions = enabled;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ProcessorConfigProfile getDefaultProcessorProfile() {
|
||||
return myDefaultProcessorsProfile;
|
||||
}
|
||||
|
||||
public void setDefaultProcessorProfile(ProcessorConfigProfile profile) {
|
||||
myDefaultProcessorsProfile.initFrom(profile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<ProcessorConfigProfile> getModuleProcessorProfiles() {
|
||||
return myModuleProcessorProfiles;
|
||||
}
|
||||
|
||||
public void setModuleProcessorProfiles(Collection<ProcessorConfigProfile> moduleProfiles) {
|
||||
myModuleProcessorProfiles.clear();
|
||||
myModuleProcessorProfiles.addAll(moduleProfiles);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ProcessorConfigProfile getAnnotationProcessingConfiguration(Module module) {
|
||||
Map<Module, ProcessorConfigProfile> map = myProcessorsProfilesMap;
|
||||
if (map == null) {
|
||||
map = new HashMap<Module, ProcessorConfigProfile>();
|
||||
final Map<String, Module> namesMap = new HashMap<String, Module>();
|
||||
for (Module m : ModuleManager.getInstance(module.getProject()).getModules()) {
|
||||
namesMap.put(m.getName(), m);
|
||||
}
|
||||
if (!namesMap.isEmpty()) {
|
||||
for (ProcessorConfigProfile profile : myModuleProcessorProfiles) {
|
||||
for (String name : profile.getModuleNames()) {
|
||||
final Module mod = namesMap.get(name);
|
||||
if (mod != null) {
|
||||
map.put(mod, profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
myProcessorsProfilesMap = map;
|
||||
}
|
||||
final ProcessorConfigProfile profile = map.get(module);
|
||||
return profile != null? profile : myDefaultProcessorsProfile;
|
||||
}
|
||||
|
||||
@Override
|
||||
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 void setAnotationProcessedModules(Map<Module, String> modules) {
|
||||
myProcessedModules.clear();
|
||||
myModuleNames.clear();
|
||||
myProcessedModules.putAll(modules);
|
||||
}
|
||||
|
||||
public Map<Module, String> getAnotationProcessedModules() {
|
||||
return Collections.unmodifiableMap(myProcessedModules);
|
||||
}
|
||||
|
||||
public boolean isAnnotationProcessingEnabled(Module module) {
|
||||
return myProcessedModules.containsKey(module);
|
||||
}
|
||||
|
||||
public String getGeneratedSourceDirName(Module module) {
|
||||
return myProcessedModules.get(module);
|
||||
if (myDefaultProcessorsProfile.isEnabled()) {
|
||||
return true;
|
||||
}
|
||||
for (ProcessorConfigProfile profile : myModuleProcessorProfiles) {
|
||||
if (profile.isEnabled()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addWildcardResourcePattern(@NonNls final String wildcardPattern) throws MalformedPatternException {
|
||||
@@ -579,21 +585,26 @@ 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 BYTECODE_TARGET_LEVEL = "bytecodeTargetLevel";
|
||||
@NonNls private static final String WILDCARD_RESOURCE_PATTERNS = "wildcardResourcePatterns";
|
||||
@NonNls private static final String ENTRY = "entry";
|
||||
@NonNls private static final String NAME = "name";
|
||||
@NonNls private static final String ADD_NOTNULL_ASSERTIONS = "addNotNullAssertions";
|
||||
private static final String EXCLUDE_FROM_COMPILE = "excludeFromCompile";
|
||||
private static final String RESOURCE_EXTENSIONS = "resourceExtensions";
|
||||
private static final String ANNOTATION_PROCESSING = "annotationProcessing";
|
||||
private static final String BYTECODE_TARGET_LEVEL = "bytecodeTargetLevel";
|
||||
private static final String WILDCARD_RESOURCE_PATTERNS = "wildcardResourcePatterns";
|
||||
private static final String ADD_NOTNULL_ASSERTIONS = "addNotNullAssertions";
|
||||
private static final String ENTRY = "entry";
|
||||
private static final String NAME = "name";
|
||||
private static final String VALUE = "value";
|
||||
private static final String ENABLED = "enabled";
|
||||
private static final String OPTION = "option";
|
||||
private static final String MODULE = "module";
|
||||
|
||||
|
||||
public void readExternal(Element parentNode) throws InvalidDataException {
|
||||
DefaultJDOMExternalizer.readExternal(this, parentNode);
|
||||
|
||||
final Element notNullAssertions = parentNode.getChild(ADD_NOTNULL_ASSERTIONS);
|
||||
if (notNullAssertions != null) {
|
||||
myAddNotNullAssertions = Boolean.valueOf(notNullAssertions.getAttributeValue("enabled", "true"));
|
||||
myAddNotNullAssertions = Boolean.valueOf(notNullAssertions.getAttributeValue(ENABLED, "true"));
|
||||
}
|
||||
|
||||
Element node = parentNode.getChild(EXCLUDE_FROM_COMPILE);
|
||||
@@ -608,7 +619,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
for (final Object o : node.getChildren(ENTRY)) {
|
||||
Element element = (Element)o;
|
||||
String pattern = element.getAttributeValue(NAME);
|
||||
if (pattern != null && !"".equals(pattern)) {
|
||||
if (!StringUtil.isEmpty(pattern)) {
|
||||
addRegexpPattern(pattern);
|
||||
}
|
||||
}
|
||||
@@ -621,7 +632,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
for (final Object o : node.getChildren(ENTRY)) {
|
||||
final Element element = (Element)o;
|
||||
String pattern = element.getAttributeValue(NAME);
|
||||
if (pattern != null && !"".equals(pattern)) {
|
||||
if (!StringUtil.isEmpty(pattern)) {
|
||||
addWildcardResourcePattern(pattern);
|
||||
}
|
||||
}
|
||||
@@ -631,69 +642,41 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
throw new InvalidDataException(e);
|
||||
}
|
||||
|
||||
|
||||
myModuleProcessorProfiles.clear();
|
||||
myProcessorsProfilesMap = null;
|
||||
|
||||
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);
|
||||
for (Object elem : annotationProcessingSettings.getChildren("profile")) {
|
||||
final Element profileElement = (Element)elem;
|
||||
final boolean isDefault = "true".equals(profileElement.getAttributeValue("default"));
|
||||
if (isDefault) {
|
||||
readProfile(profileElement, myDefaultProcessorsProfile);
|
||||
}
|
||||
else {
|
||||
final ProcessorConfigProfile profile = new ProcessorConfigProfile("");
|
||||
readProfile(profileElement, profile);
|
||||
myModuleProcessorProfiles.add(profile);
|
||||
}
|
||||
}
|
||||
myProcessorPath = pathBuilder.toString();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
myProcessedModules.clear();
|
||||
myModuleNames.clear();
|
||||
|
||||
final Collection<Element> processed = (Collection<Element>)annotationProcessingSettings.getChildren("processModule");
|
||||
if (!processed.isEmpty()) {
|
||||
final Map<String, Module> moduleMap = new HashMap<String, Module>();
|
||||
for (Module module : myModuleManager.getModules()) {
|
||||
moduleMap.put(module.getName(), module);
|
||||
myBytecodeTargetLevel = null;
|
||||
myModuleBytecodeTarget.clear();
|
||||
final Element bytecodeTargetElement = parentNode.getChild(BYTECODE_TARGET_LEVEL);
|
||||
if (bytecodeTargetElement != null) {
|
||||
myBytecodeTargetLevel = bytecodeTargetElement.getAttributeValue("target");
|
||||
for (Element elem : (Collection<Element>)bytecodeTargetElement.getChildren(MODULE)) {
|
||||
final String name = elem.getAttributeValue(NAME);
|
||||
if (name == null) {
|
||||
continue;
|
||||
}
|
||||
for (Element moduleElement : processed) {
|
||||
final String name = moduleElement.getAttributeValue("name");
|
||||
final String dirname = moduleElement.getAttributeValue("generatedDirName");
|
||||
if (name != null) {
|
||||
final Module module = moduleMap.get(name);
|
||||
if (module != null) {
|
||||
myProcessedModules.put(module, dirname);
|
||||
}
|
||||
else {
|
||||
myModuleNames.put(name, dirname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myBytecodeTargetLevel = null;
|
||||
myModuleBytecodeTarget.clear();
|
||||
final Element bytecodeTargetElement = parentNode.getChild(BYTECODE_TARGET_LEVEL);
|
||||
if (bytecodeTargetElement != null) {
|
||||
myBytecodeTargetLevel = bytecodeTargetElement.getAttributeValue("target");
|
||||
for (Element elem : (Collection<Element>)bytecodeTargetElement.getChildren("module")) {
|
||||
final String name = elem.getAttributeValue("name");
|
||||
if (name == null) {
|
||||
continue;
|
||||
}
|
||||
final String target = elem.getAttributeValue("target");
|
||||
if (target == null) {
|
||||
continue;
|
||||
}
|
||||
myModuleBytecodeTarget.put(name, target);
|
||||
final String target = elem.getAttributeValue("target");
|
||||
if (target == null) {
|
||||
continue;
|
||||
}
|
||||
myModuleBytecodeTarget.put(name, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -702,88 +685,42 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
DefaultJDOMExternalizer.writeExternal(this, parentNode);
|
||||
|
||||
if (myAddNotNullAssertions != true) {
|
||||
final Element notNullAssertions = new Element(ADD_NOTNULL_ASSERTIONS);
|
||||
notNullAssertions.setAttribute("enabled", String.valueOf(myAddNotNullAssertions));
|
||||
parentNode.addContent(notNullAssertions);
|
||||
addChild(parentNode, ADD_NOTNULL_ASSERTIONS).setAttribute(ENABLED, String.valueOf(myAddNotNullAssertions));
|
||||
}
|
||||
|
||||
if(myExcludedEntriesConfiguration.getExcludeEntryDescriptions().length > 0) {
|
||||
Element newChild = new Element(EXCLUDE_FROM_COMPILE);
|
||||
myExcludedEntriesConfiguration.writeExternal(newChild);
|
||||
parentNode.addContent(newChild);
|
||||
myExcludedEntriesConfiguration.writeExternal(addChild(parentNode, EXCLUDE_FROM_COMPILE));
|
||||
}
|
||||
|
||||
final Element newChild = new Element(RESOURCE_EXTENSIONS);
|
||||
final Element newChild = addChild(parentNode, RESOURCE_EXTENSIONS);
|
||||
for (final String pattern : getRegexpPatterns()) {
|
||||
final Element entry = new Element(ENTRY);
|
||||
entry.setAttribute(NAME, pattern);
|
||||
newChild.addContent(entry);
|
||||
addChild(newChild, ENTRY).setAttribute(NAME, pattern);
|
||||
}
|
||||
parentNode.addContent(newChild);
|
||||
|
||||
if (myWildcardPatternsInitialized || !myWildcardPatterns.isEmpty()) {
|
||||
final Element wildcardPatterns = new Element(WILDCARD_RESOURCE_PATTERNS);
|
||||
final Element wildcardPatterns = addChild(parentNode, WILDCARD_RESOURCE_PATTERNS);
|
||||
for (final String wildcardPattern : myWildcardPatterns) {
|
||||
final Element entry = new Element(ENTRY);
|
||||
entry.setAttribute(NAME, wildcardPattern);
|
||||
wildcardPatterns.addContent(entry);
|
||||
addChild(wildcardPatterns, ENTRY).setAttribute(NAME, wildcardPattern);
|
||||
}
|
||||
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>(myProcessedModules.keySet());
|
||||
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("processModule");
|
||||
annotationProcessingSettings.addContent(moduleElement);
|
||||
moduleElement.setAttribute("name", module.getName());
|
||||
final String dirName = myProcessedModules.get(module);
|
||||
if (dirName != null && dirName.length() > 0) {
|
||||
moduleElement.setAttribute("generatedDirName", dirName);
|
||||
}
|
||||
final Element annotationProcessingSettings = addChild(parentNode, ANNOTATION_PROCESSING);
|
||||
writeProfile(addChild(annotationProcessingSettings, "profile").setAttribute("default", "true"), myDefaultProcessorsProfile);
|
||||
for (ProcessorConfigProfile profile : myModuleProcessorProfiles) {
|
||||
writeProfile(addChild(annotationProcessingSettings, "profile").setAttribute("default", "false"), profile);
|
||||
}
|
||||
|
||||
if (!StringUtil.isEmpty(myBytecodeTargetLevel) || !myModuleBytecodeTarget.isEmpty()) {
|
||||
final Element bytecodeTarget = new Element(BYTECODE_TARGET_LEVEL);
|
||||
parentNode.addContent(bytecodeTarget);
|
||||
final Element bytecodeTarget = addChild(parentNode, BYTECODE_TARGET_LEVEL);
|
||||
if (!StringUtil.isEmpty(myBytecodeTargetLevel)) {
|
||||
bytecodeTarget.setAttribute("target", myBytecodeTargetLevel);
|
||||
}
|
||||
if (!myModuleBytecodeTarget.isEmpty()) {
|
||||
final List<String> moduleNames = new ArrayList<String>(myModuleBytecodeTarget.keySet());
|
||||
Collections.sort(moduleNames, new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
});
|
||||
Collections.sort(moduleNames, ALPHA_COMPARATOR);
|
||||
for (String name : moduleNames) {
|
||||
final Element moduleElement = new Element("module");
|
||||
bytecodeTarget.addContent(moduleElement);
|
||||
moduleElement.setAttribute("name", name);
|
||||
final Element moduleElement = addChild(bytecodeTarget, MODULE);
|
||||
moduleElement.setAttribute(NAME, name);
|
||||
final String value = myModuleBytecodeTarget.get(name);
|
||||
moduleElement.setAttribute("target", value != null? value : "");
|
||||
}
|
||||
@@ -791,6 +728,109 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
}
|
||||
}
|
||||
|
||||
private static void readProfile(Element element, ProcessorConfigProfile profile) {
|
||||
profile.setName(element.getAttributeValue(NAME, ""));
|
||||
profile.setEnabled(Boolean.valueOf(element.getAttributeValue(ENABLED, "false")));
|
||||
|
||||
final Element srcOutput = element.getChild("sourceOutputDir");
|
||||
profile.setGeneratedSourcesDirectoryName(srcOutput != null? srcOutput.getAttributeValue(NAME) : null);
|
||||
|
||||
profile.clearProcessorOptions();
|
||||
for (Object optionElement : element.getChildren(OPTION)) {
|
||||
final Element elem = (Element)optionElement;
|
||||
final String key = elem.getAttributeValue(NAME);
|
||||
final String value = elem.getAttributeValue(VALUE);
|
||||
if (!StringUtil.isEmptyOrSpaces(key) && value != null) {
|
||||
profile.setOption(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
profile.clearProcessors();
|
||||
for (Object procElement : element.getChildren("processor")) {
|
||||
final String name = ((Element)procElement).getAttributeValue(NAME);
|
||||
if (StringUtil.isEmptyOrSpaces(name)) {
|
||||
profile.addProcessor(name);
|
||||
}
|
||||
}
|
||||
|
||||
final Element pathElement = element.getChild("processorPath");
|
||||
if (pathElement != null) {
|
||||
profile.setObtainProcessorsFromClasspath(Boolean.parseBoolean(pathElement.getAttributeValue("useClasspath", "true")));
|
||||
final StringBuilder pathBuilder = new StringBuilder();
|
||||
for (Object entry : pathElement.getChildren(ENTRY)) {
|
||||
final String path = ((Element)entry).getAttributeValue(NAME);
|
||||
if (!StringUtil.isEmptyOrSpaces(path)) {
|
||||
if (pathBuilder.length() > 0) {
|
||||
pathBuilder.append(File.pathSeparator);
|
||||
}
|
||||
pathBuilder.append(FileUtil.toSystemDependentName(path));
|
||||
}
|
||||
}
|
||||
profile.setProcessorPath(pathBuilder.toString());
|
||||
}
|
||||
|
||||
profile.clearModuleNames();
|
||||
for (Object moduleElement : element.getChildren(MODULE)) {
|
||||
final String name = ((Element)moduleElement).getAttributeValue(NAME);
|
||||
if (!StringUtil.isEmptyOrSpaces(name)) {
|
||||
profile.addModuleName(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeProfile(final Element element, ProcessorConfigProfile profile) {
|
||||
element.setAttribute(NAME, profile.getName());
|
||||
element.setAttribute(ENABLED, Boolean.toString(profile.isEnabled()));
|
||||
|
||||
final String srcDirName = profile.getGeneratedSourcesDirectoryName();
|
||||
if (srcDirName != null) {
|
||||
addChild(element, "sourceOutputDir").setAttribute(NAME, srcDirName);
|
||||
}
|
||||
|
||||
final Map<String, String> options = profile.getProcessorOptions();
|
||||
if (!options.isEmpty()) {
|
||||
final List<String> keys = new ArrayList<String>(options.keySet());
|
||||
Collections.sort(keys, ALPHA_COMPARATOR);
|
||||
for (String key : keys) {
|
||||
addChild(element, OPTION).setAttribute(NAME, key).setAttribute(VALUE, options.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
final Set<String> processors = profile.getProcessors();
|
||||
if (!processors.isEmpty()) {
|
||||
final List<String> processorList = new ArrayList<String>(processors);
|
||||
Collections.sort(processorList, ALPHA_COMPARATOR);
|
||||
for (String proc : processorList) {
|
||||
addChild(element, "processor").setAttribute(NAME, proc);
|
||||
}
|
||||
}
|
||||
|
||||
final Element pathElement = addChild(element, "processorPath").setAttribute("useClasspath", Boolean.toString(profile.isObtainProcessorsFromClasspath()));
|
||||
final String path = profile.getProcessorPath();
|
||||
if (!StringUtil.isEmpty(path)) {
|
||||
final StringTokenizer tokenizer = new StringTokenizer(path, File.pathSeparator, false);
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
final String token = tokenizer.nextToken();
|
||||
addChild(pathElement, ENTRY).setAttribute(NAME, FileUtil.toSystemIndependentName(token));
|
||||
}
|
||||
}
|
||||
|
||||
final Set<String> moduleNames = profile.getModuleNames();
|
||||
if (!moduleNames.isEmpty()) {
|
||||
final List<String> names = new ArrayList<String>(moduleNames);
|
||||
Collections.sort(names, ALPHA_COMPARATOR);
|
||||
for (String name : names) {
|
||||
addChild(element, MODULE).setAttribute(NAME, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Element addChild(Element parent, final String childName) {
|
||||
final Element child = new Element(childName);
|
||||
parent.addContent(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
@NotNull @NonNls
|
||||
public String getComponentName() {
|
||||
return "CompilerConfiguration";
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.compiler;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 5/25/12
|
||||
*/
|
||||
public class ProcessorConfigProfile implements AnnotationProcessingConfiguration {
|
||||
private String myName = "";
|
||||
|
||||
private boolean myEnabled = false;
|
||||
private boolean myObtainProcessorsFromClasspath = true;
|
||||
private String myProcessorPath = "";
|
||||
private final Set<String> myProcessors = new HashSet<String>(); // empty list means all discovered
|
||||
private final Map<String, String> myProcessorOptions = new HashMap<String, String>(); // key=value map of options
|
||||
@Nullable
|
||||
private String myGeneratedSourcesDirectoryName = null; // null means 'auto'
|
||||
private final Set<String> myModuleNames = new HashSet<String>();
|
||||
|
||||
public ProcessorConfigProfile(String name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
public ProcessorConfigProfile(ProcessorConfigProfile profile) {
|
||||
initFrom(profile);
|
||||
}
|
||||
|
||||
public final void initFrom(ProcessorConfigProfile other) {
|
||||
myName = other.myName;
|
||||
myEnabled = other.myEnabled;
|
||||
myObtainProcessorsFromClasspath = other.myObtainProcessorsFromClasspath;
|
||||
myProcessorPath = other.myProcessorPath;
|
||||
myProcessors.clear();
|
||||
myProcessors.addAll(other.myProcessors);
|
||||
myProcessorOptions.clear();
|
||||
myProcessorOptions.putAll(other.myProcessorOptions);
|
||||
myGeneratedSourcesDirectoryName = other.myGeneratedSourcesDirectoryName;
|
||||
myModuleNames.clear();
|
||||
myModuleNames.addAll(other.myModuleNames);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return myEnabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
myEnabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getProcessorPath() {
|
||||
return myProcessorPath;
|
||||
}
|
||||
|
||||
public void setProcessorPath(@Nullable String processorPath) {
|
||||
myProcessorPath = processorPath != null? processorPath : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObtainProcessorsFromClasspath() {
|
||||
return myObtainProcessorsFromClasspath;
|
||||
}
|
||||
|
||||
public void setObtainProcessorsFromClasspath(boolean value) {
|
||||
myObtainProcessorsFromClasspath = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getGeneratedSourcesDirectoryName() {
|
||||
return myGeneratedSourcesDirectoryName;
|
||||
}
|
||||
|
||||
public void setGeneratedSourcesDirectoryName(@Nullable String generatedSourcesDirectoryName) {
|
||||
myGeneratedSourcesDirectoryName = generatedSourcesDirectoryName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<String> getModuleNames() {
|
||||
return myModuleNames;
|
||||
}
|
||||
|
||||
public boolean addModuleName(String name) {
|
||||
return myModuleNames.add(name);
|
||||
}
|
||||
|
||||
public boolean addModuleNames(Collection<String> names) {
|
||||
return myModuleNames.addAll(names);
|
||||
}
|
||||
|
||||
public boolean removeModuleName(String name) {
|
||||
return myModuleNames.remove(name);
|
||||
}
|
||||
|
||||
public boolean removeModuleNames(Collection<String> names) {
|
||||
return myModuleNames.removeAll(names);
|
||||
}
|
||||
|
||||
public void clearModuleNames() {
|
||||
myModuleNames.clear();
|
||||
}
|
||||
|
||||
public void clearProcessors() {
|
||||
myProcessors.clear();
|
||||
}
|
||||
|
||||
public boolean addProcessor(String processor) {
|
||||
return myProcessors.add(processor);
|
||||
}
|
||||
|
||||
public boolean removeProcessor(String processor) {
|
||||
return myProcessors.remove(processor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Set<String> getProcessors() {
|
||||
return Collections.unmodifiableSet(myProcessors);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Map<String, String> getProcessorOptions() {
|
||||
return Collections.unmodifiableMap(myProcessorOptions);
|
||||
}
|
||||
|
||||
public String setOption(String key, String value) {
|
||||
return myProcessorOptions.put(key, value);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getOption(String key) {
|
||||
return myProcessorOptions.get(key);
|
||||
}
|
||||
|
||||
public void clearProcessorOptions() {
|
||||
myProcessorOptions.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ProcessorConfigProfile profile = (ProcessorConfigProfile)o;
|
||||
|
||||
if (myEnabled != profile.myEnabled) return false;
|
||||
if (myObtainProcessorsFromClasspath != profile.myObtainProcessorsFromClasspath) return false;
|
||||
if (myGeneratedSourcesDirectoryName != null
|
||||
? !myGeneratedSourcesDirectoryName.equals(profile.myGeneratedSourcesDirectoryName)
|
||||
: profile.myGeneratedSourcesDirectoryName != null) {
|
||||
return false;
|
||||
}
|
||||
if (!myModuleNames.equals(profile.myModuleNames)) return false;
|
||||
if (!myProcessorOptions.equals(profile.myProcessorOptions)) return false;
|
||||
if (myProcessorPath != null ? !myProcessorPath.equals(profile.myProcessorPath) : profile.myProcessorPath != null) return false;
|
||||
if (!myProcessors.equals(profile.myProcessors)) return false;
|
||||
if (!myName.equals(profile.myName)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myName.hashCode();
|
||||
result = 31 * result + (myEnabled ? 1 : 0);
|
||||
result = 31 * result + (myObtainProcessorsFromClasspath ? 1 : 0);
|
||||
result = 31 * result + (myProcessorPath != null ? myProcessorPath.hashCode() : 0);
|
||||
result = 31 * result + myProcessors.hashCode();
|
||||
result = 31 * result + myProcessorOptions.hashCode();
|
||||
result = 31 * result + (myGeneratedSourcesDirectoryName != null ? myGeneratedSourcesDirectoryName.hashCode() : 0);
|
||||
result = 31 * result + myModuleNames.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.compiler.actions;
|
||||
|
||||
import com.intellij.compiler.AnnotationProcessingConfiguration;
|
||||
import com.intellij.compiler.CompilerConfiguration;
|
||||
import com.intellij.compiler.impl.FileSetCompileScope;
|
||||
import com.intellij.compiler.impl.ModuleCompileScope;
|
||||
@@ -82,9 +83,12 @@ public class ProcessAnnotationsAction extends CompileActionBase {
|
||||
final Module module = LangDataKeys.MODULE.getData(dataContext);
|
||||
final Module moduleContext = LangDataKeys.MODULE_CONTEXT.getData(dataContext);
|
||||
|
||||
if (!compilerConfiguration.isAnnotationProcessorsEnabled() ||
|
||||
(!compilerConfiguration.isObtainProcessorsFromClasspath() && compilerConfiguration.getAnnotationProcessorsMap().isEmpty()) ||
|
||||
module != null && StringUtil.isEmpty(compilerConfiguration.getAnotationProcessedModules().get(module))) {
|
||||
if (module == null) {
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
final AnnotationProcessingConfiguration profile = compilerConfiguration.getAnnotationProcessingConfiguration(module);
|
||||
if (!profile.isEnabled() || (!profile.isObtainProcessorsFromClasspath() && profile.getProcessors().isEmpty())) {
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -169,12 +169,10 @@ public class CompileDriver {
|
||||
final Pair<VirtualFile, VirtualFile> outputs = new Pair<VirtualFile, VirtualFile>(productionOutput, testOutput);
|
||||
myGenerationCompilerModuleToOutputDirMap.put(pair, outputs);
|
||||
}
|
||||
if (config.isAnnotationProcessorsEnabled()) {
|
||||
if (config.isAnnotationProcessingEnabled(module)) {
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
if (path != null) {
|
||||
lookupVFile(lfs, path); // ensure the file is created and added to VFS
|
||||
}
|
||||
if (config.getAnnotationProcessingConfiguration(module).isEnabled()) {
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
if (path != null) {
|
||||
lookupVFile(lfs, path); // ensure the file is created and added to VFS
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -395,7 +393,7 @@ public class CompileDriver {
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
final Set<Module> affected = new HashSet<Module>(Arrays.asList(context.getCompileScope().getAffectedModules()));
|
||||
for (Module module : affected) {
|
||||
if (!config.isAnnotationProcessingEnabled(module)) {
|
||||
if (!config.getAnnotationProcessingConfiguration(module).isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
@@ -1725,7 +1723,7 @@ public class CompileDriver {
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
if (context.isAnnotationProcessorsEnabled()) {
|
||||
for (Module module : modules) {
|
||||
if (config.isAnnotationProcessingEnabled(module)) {
|
||||
if (config.getAnnotationProcessingConfiguration(module).isEnabled()) {
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
if (path != null) {
|
||||
outputDirs.add(new File(path));
|
||||
@@ -2366,7 +2364,7 @@ public class CompileDriver {
|
||||
modulesWithoutOutputPathSpecified.add(module.getName());
|
||||
}
|
||||
}
|
||||
if (config.isAnnotationProcessorsEnabled() && config.isAnnotationProcessingEnabled(module)) {
|
||||
if (config.getAnnotationProcessingConfiguration(module).isEnabled()) {
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
if (path == null) {
|
||||
final CompilerProjectExtension extension = CompilerProjectExtension.getInstance(module.getProject());
|
||||
@@ -2458,9 +2456,9 @@ public class CompileDriver {
|
||||
if (chunkModules.size() <= 1) {
|
||||
continue; // no need to check one-module chunks
|
||||
}
|
||||
if (config.isAnnotationProcessorsEnabled()) {
|
||||
if (!useOutOfProcessBuild()) {
|
||||
for (Module chunkModule : chunkModules) {
|
||||
if (config.isAnnotationProcessingEnabled(chunkModule)) {
|
||||
if (config.getAnnotationProcessingConfiguration(chunkModule).isEnabled()) {
|
||||
showCyclesNotSupportedForAnnotationProcessors(chunkModules.toArray(new Module[chunkModules.size()]));
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ public class AnnotationProcessingCompiler implements TranslatingCompiler{
|
||||
}
|
||||
final Module module = context.getModuleByFile(file);
|
||||
if (module != null) {
|
||||
if (!myConfig.isAnnotationProcessingEnabled(module)) {
|
||||
if (!myConfig.getAnnotationProcessingConfiguration(module).isEnabled()) {
|
||||
return true;
|
||||
}
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
|
||||
+9
-24
@@ -15,10 +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;
|
||||
import com.intellij.compiler.*;
|
||||
import com.intellij.compiler.impl.CompilerUtil;
|
||||
import com.intellij.compiler.impl.javaCompiler.ExternalCompiler;
|
||||
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
|
||||
@@ -283,33 +280,21 @@ public class JavacCompiler extends ExternalCompiler {
|
||||
annotationProcessorsEnabled = false;
|
||||
}
|
||||
if (isAnnotationProcessing) {
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(chunk.getProject());
|
||||
final AnnotationProcessingConfiguration config = CompilerConfiguration.getInstance(chunk.getProject()).getAnnotationProcessingConfiguration(chunk.getModules()[0]);
|
||||
additionalOptions.add("-Xprefer:source");
|
||||
additionalOptions.add("-implicit:none");
|
||||
additionalOptions.add("-proc:only");
|
||||
if (!config.isObtainProcessorsFromClasspath()) {
|
||||
final String processorPath = config.getProcessorPath();
|
||||
if (processorPath.length() > 0) {
|
||||
additionalOptions.add("-processorpath");
|
||||
additionalOptions.add(FileUtil.toSystemDependentName(processorPath));
|
||||
}
|
||||
additionalOptions.add("-processorpath");
|
||||
additionalOptions.add(FileUtil.toSystemDependentName(processorPath));
|
||||
}
|
||||
for (Map.Entry<String, String> entry : config.getAnnotationProcessorsMap().entrySet()) {
|
||||
for (String processorName : config.getProcessors()) {
|
||||
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();
|
||||
if (token.startsWith("-A")) {
|
||||
additionalOptions.add(token.substring("-A".length()));
|
||||
}
|
||||
else {
|
||||
additionalOptions.add("-A" + token);
|
||||
}
|
||||
}
|
||||
}
|
||||
additionalOptions.add(processorName);
|
||||
}
|
||||
for (Map.Entry<String, String> entry : config.getProcessorOptions().entrySet()) {
|
||||
additionalOptions.add("-A" + entry.getKey() + "=" +entry.getValue());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
+26
-329
@@ -17,41 +17,17 @@ package com.intellij.compiler.options;
|
||||
|
||||
import com.intellij.compiler.CompileServerManager;
|
||||
import com.intellij.compiler.CompilerConfiguration;
|
||||
import com.intellij.compiler.CompilerConfigurationImpl;
|
||||
import com.intellij.compiler.ProcessorConfigProfile;
|
||||
import com.intellij.compiler.server.BuildManager;
|
||||
import com.intellij.openapi.fileChooser.FileChooser;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.ui.EditableModel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.JTableHeader;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -59,15 +35,9 @@ import java.util.Map;
|
||||
* Date: Oct 5, 2009
|
||||
*/
|
||||
public class AnnotationProcessorsConfigurable implements SearchableConfigurable, Configurable.NoScroll {
|
||||
private ProcessedModulesTable myModulesTable;
|
||||
|
||||
private final Project myProject;
|
||||
private JRadioButton myRbClasspath;
|
||||
private JRadioButton myRbProcessorsPath;
|
||||
private TextFieldWithBrowseButton myProcessorPathField;
|
||||
private ProcessorTableModel myProcessorsModel;
|
||||
private JCheckBox myCbEnableProcessing;
|
||||
private JBTable myProcessorTable;
|
||||
private JPanel myProcessorPanel;
|
||||
private AnnotationProcessorsPanel myMainPanel;
|
||||
|
||||
public AnnotationProcessorsConfigurable(final Project project) {
|
||||
myProject = project;
|
||||
@@ -95,163 +65,39 @@ public class AnnotationProcessorsConfigurable implements SearchableConfigurable,
|
||||
}
|
||||
|
||||
public JComponent createComponent() {
|
||||
final JPanel mainPanel = new JPanel(new GridBagLayout());
|
||||
|
||||
myCbEnableProcessing = new JCheckBox("Enable annotation processing");
|
||||
|
||||
myRbClasspath = new JRadioButton("Obtain processors from project classpath");
|
||||
myRbProcessorsPath = new JRadioButton("Processor path:");
|
||||
ButtonGroup group = new ButtonGroup();
|
||||
group.add(myRbClasspath);
|
||||
group.add(myRbProcessorsPath);
|
||||
|
||||
myProcessorPathField = new TextFieldWithBrowseButton(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createAllButJarContentsDescriptor();
|
||||
final VirtualFile[] files = FileChooser.chooseFiles(descriptor, myProcessorPathField, myProject, null);
|
||||
if (files.length > 0) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (VirtualFile file : files) {
|
||||
if (builder.length() > 0) {
|
||||
builder.append(File.pathSeparator);
|
||||
}
|
||||
builder.append(FileUtil.toSystemDependentName(file.getPath()));
|
||||
}
|
||||
myProcessorPathField.setText(builder.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final JPanel processorTablePanel = new JPanel(new BorderLayout());
|
||||
myProcessorsModel = new ProcessorTableModel();
|
||||
processorTablePanel.setBorder(IdeBorderFactory.createTitledBorder("Annotation Processors", false));
|
||||
myProcessorTable = new JBTable(myProcessorsModel);
|
||||
myProcessorTable.getEmptyText().setText("No processors configured");
|
||||
myProcessorPanel = ToolbarDecorator.createDecorator(myProcessorTable)
|
||||
.disableUpAction()
|
||||
.disableDownAction()
|
||||
.setAddAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton anActionButton) {
|
||||
final TableCellEditor cellEditor = myProcessorTable.getCellEditor();
|
||||
if (cellEditor != null) {
|
||||
cellEditor.stopCellEditing();
|
||||
}
|
||||
final ProcessorTableModel model = (ProcessorTableModel)myProcessorTable.getModel();
|
||||
model.addRow();
|
||||
TableUtil.editCellAt(myProcessorTable, model.getRowCount() - 1, ProcessorTableRow.NAME_COLUMN);
|
||||
}
|
||||
})
|
||||
.createPanel();
|
||||
|
||||
|
||||
|
||||
processorTablePanel.add(myProcessorPanel, BorderLayout.CENTER);
|
||||
|
||||
myModulesTable = new ProcessedModulesTable(myProject);
|
||||
myModulesTable.setBorder(IdeBorderFactory.createTitledBorder("Processed Modules", false));
|
||||
final JLabel noteMessage = new JLabel("<html>Source files generated by annotation processors will be stored under the project output directory. " +
|
||||
"To override this behaviour for certain modules you may specify the directory name in the table below. " +
|
||||
"If specified, the directory will be created under corresponding module's content root.</html>");
|
||||
|
||||
final JLabel warning = new JLabel("<html>WARNING!<br>" +
|
||||
"All source files located in the generated sources output directory WILL BE EXCLUDED from annotation processing. " +
|
||||
"If option 'Clear output directory on rebuild' is enabled, " +
|
||||
"the entire contents of directories specified in the table below WILL BE CLEARED on rebuild.</html>");
|
||||
warning.setFont(warning.getFont().deriveFont(Font.BOLD));
|
||||
|
||||
mainPanel.add(myCbEnableProcessing, new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
|
||||
mainPanel.add(myRbClasspath, new GridBagConstraints(0, 1, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 0, 0, 0), 0, 0));
|
||||
mainPanel.add(myRbProcessorsPath, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 0, 0, 0), 0, 0));
|
||||
mainPanel.add(myProcessorPathField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0));
|
||||
mainPanel.add(processorTablePanel, new GridBagConstraints(0, 3, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10, 0, 0, 0), 0, 0));
|
||||
mainPanel.add(noteMessage, new GridBagConstraints(0, 4, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 0, 0), 0, 0));
|
||||
mainPanel.add(warning, new GridBagConstraints(0, 5, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 0, 0), 0, 0));
|
||||
mainPanel.add(myModulesTable, new GridBagConstraints(0, 6, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10, 0, 0, 0), 0, 0));
|
||||
//mainPanel.add(new AnnotationProcessorsPanel(myProject), new GridBagConstraints(0, 7, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10, 0, 0, 0), 0, 0));
|
||||
|
||||
|
||||
myRbClasspath.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
updateEnabledState();
|
||||
}
|
||||
});
|
||||
|
||||
myProcessorTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (!e.getValueIsAdjusting()) {
|
||||
updateEnabledState();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myCbEnableProcessing.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
updateEnabledState();
|
||||
}
|
||||
});
|
||||
|
||||
updateEnabledState();
|
||||
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
private void updateEnabledState() {
|
||||
final boolean enabled = myCbEnableProcessing.isSelected();
|
||||
final boolean useProcessorpath = !myRbClasspath.isSelected();
|
||||
myRbClasspath.setEnabled(enabled);
|
||||
myRbProcessorsPath.setEnabled(enabled);
|
||||
myProcessorPathField.setEnabled(enabled && useProcessorpath);
|
||||
final AnActionButton addButton = ToolbarDecorator.findAddButton(myProcessorPanel);
|
||||
if (addButton != null) {
|
||||
addButton.setEnabled(enabled);
|
||||
}
|
||||
final AnActionButton removeButton = ToolbarDecorator.findRemoveButton(myProcessorPanel);
|
||||
if (removeButton != null) {
|
||||
removeButton.setEnabled(enabled && myProcessorTable.getSelectedRow() >= 0);
|
||||
}
|
||||
myProcessorTable.setEnabled(enabled);
|
||||
final JTableHeader header = myProcessorTable.getTableHeader();
|
||||
if (header != null) {
|
||||
header.repaint();
|
||||
}
|
||||
myModulesTable.getComponent().setEnabled(enabled);
|
||||
myMainPanel = new AnnotationProcessorsPanel(myProject);
|
||||
return myMainPanel;
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
if (config.isAnnotationProcessorsEnabled() != myCbEnableProcessing.isSelected()) {
|
||||
return true;
|
||||
}
|
||||
if (config.isObtainProcessorsFromClasspath() != myRbClasspath.isSelected()) {
|
||||
return true;
|
||||
}
|
||||
if (!FileUtil.pathsEqual(config.getProcessorPath(), FileUtil.toSystemIndependentName(myProcessorPathField.getText().trim()))) {
|
||||
final CompilerConfigurationImpl config = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject);
|
||||
|
||||
if (!config.getDefaultProcessorProfile().equals(myMainPanel.getDefaultProfile())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Map<String, String> map = myProcessorsModel.exportToMap();
|
||||
if (!map.equals(config.getAnnotationProcessorsMap())) {
|
||||
final Map<String, ProcessorConfigProfile> configProfiles = new java.util.HashMap<String, ProcessorConfigProfile>();
|
||||
for (ProcessorConfigProfile profile : config.getModuleProcessorProfiles()) {
|
||||
configProfiles.put(profile.getName(), profile);
|
||||
}
|
||||
final List<ProcessorConfigProfile> panelProfiles = myMainPanel.getModuleProfiles();
|
||||
if (configProfiles.size() != panelProfiles.size()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!getMarkedModules().equals(config.getAnotationProcessedModules())) {
|
||||
return true;
|
||||
for (ProcessorConfigProfile panelProfile : panelProfiles) {
|
||||
final ProcessorConfigProfile configProfile = configProfiles.get(panelProfile.getName());
|
||||
if (configProfile == null || !configProfile.equals(panelProfile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void apply() throws ConfigurationException {
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
config.setAnnotationProcessorsEnabled(myCbEnableProcessing.isSelected());
|
||||
|
||||
config.setObtainProcessorsFromClasspath(myRbClasspath.isSelected());
|
||||
config.setProcessorsPath(FileUtil.toSystemIndependentName(myProcessorPathField.getText().trim()));
|
||||
|
||||
config.setAnnotationProcessorsMap(myProcessorsModel.exportToMap());
|
||||
|
||||
config.setAnotationProcessedModules(getMarkedModules());
|
||||
final CompilerConfigurationImpl config = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject);
|
||||
config.setDefaultProcessorProfile(myMainPanel.getDefaultProfile());
|
||||
config.setModuleProcessorProfiles(myMainPanel.getModuleProfiles());
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
CompileServerManager.getInstance().sendReloadRequest(myProject);
|
||||
@@ -260,161 +106,12 @@ public class AnnotationProcessorsConfigurable implements SearchableConfigurable,
|
||||
});
|
||||
}
|
||||
|
||||
private Map<Module, String> getMarkedModules() {
|
||||
final Map<Module, String> result = new HashMap<Module, String>();
|
||||
for (Pair<Module, String> pair : myModulesTable.getAllModules()) {
|
||||
result.put(pair.getFirst(), pair.getSecond());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
myCbEnableProcessing.setSelected(config.isAnnotationProcessorsEnabled());
|
||||
|
||||
final boolean obtainFromClasspath = config.isObtainProcessorsFromClasspath();
|
||||
if (obtainFromClasspath) {
|
||||
myRbClasspath.setSelected(true);
|
||||
}
|
||||
else {
|
||||
myRbProcessorsPath.setSelected(true);
|
||||
}
|
||||
|
||||
myProcessorPathField.setText(FileUtil.toSystemDependentName(config.getProcessorPath()));
|
||||
|
||||
myProcessorsModel.setProcessorMap(config.getAnnotationProcessorsMap());
|
||||
|
||||
myModulesTable.removeAllElements();
|
||||
for (final Module module : ModuleManager.getInstance(myProject).getModules()) {
|
||||
if (config.isAnnotationProcessingEnabled(module)) {
|
||||
myModulesTable.addModule(module, config.getGeneratedSourceDirName(module));
|
||||
}
|
||||
}
|
||||
myModulesTable.sort(new Comparator<Module>() {
|
||||
public int compare(Module o1, Module o2) {
|
||||
return o1.getName().compareToIgnoreCase(o2.getName());
|
||||
}
|
||||
});
|
||||
final CompilerConfigurationImpl config = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject);
|
||||
myMainPanel.initProfiles(config.getDefaultProcessorProfile(), config.getModuleProcessorProfiles());
|
||||
}
|
||||
|
||||
public void disposeUIResources() {
|
||||
}
|
||||
|
||||
private static class ProcessorTableModel extends AbstractTableModel implements EditableModel {
|
||||
private final java.util.List<ProcessorTableRow> myRows = new ArrayList<ProcessorTableRow>();
|
||||
|
||||
public String getColumnName(int column) {
|
||||
switch (column) {
|
||||
case ProcessorTableRow.NAME_COLUMN: return "Processor FQ Name";
|
||||
case ProcessorTableRow.OPTIONS_COLUMN : return "Processor Run Options (space-separated \"key=value\" pairs)";
|
||||
}
|
||||
return super.getColumnName(column);
|
||||
}
|
||||
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public int getRowCount() {
|
||||
return myRows.size();
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return columnIndex == ProcessorTableRow.NAME_COLUMN || columnIndex == ProcessorTableRow.OPTIONS_COLUMN;
|
||||
}
|
||||
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
final ProcessorTableRow row = myRows.get(rowIndex);
|
||||
switch (columnIndex) {
|
||||
case ProcessorTableRow.NAME_COLUMN: return row.name;
|
||||
case ProcessorTableRow.OPTIONS_COLUMN : return row.options;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
if (aValue != null) {
|
||||
final ProcessorTableRow row = myRows.get(rowIndex);
|
||||
switch (columnIndex) {
|
||||
case ProcessorTableRow.NAME_COLUMN:
|
||||
row.name = (String)aValue;
|
||||
break;
|
||||
case ProcessorTableRow.OPTIONS_COLUMN:
|
||||
row.options = (String)aValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeRow(int idx) {
|
||||
myRows.remove(idx);
|
||||
fireTableRowsDeleted(idx, idx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exchangeRows(int oldIndex, int newIndex) {
|
||||
}
|
||||
|
||||
public void addRow() {
|
||||
myRows.add(new ProcessorTableRow());
|
||||
final int index = myRows.size() - 1;
|
||||
fireTableRowsInserted(index, index);
|
||||
}
|
||||
|
||||
public void setProcessorMap(Map<String, String> processorMap) {
|
||||
clear();
|
||||
if (processorMap.size() > 0) {
|
||||
for (Map.Entry<String, String> entry : processorMap.entrySet()) {
|
||||
myRows.add(new ProcessorTableRow(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
Collections.sort(myRows, new Comparator<ProcessorTableRow>() {
|
||||
public int compare(ProcessorTableRow o1, ProcessorTableRow o2) {
|
||||
return o1.name.compareToIgnoreCase(o2.name);
|
||||
}
|
||||
});
|
||||
fireTableRowsInserted(0, processorMap.size()-1);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final int count = myRows.size();
|
||||
if (count > 0) {
|
||||
myRows.clear();
|
||||
fireTableRowsDeleted(0, count-1);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> exportToMap() {
|
||||
final Map<String, String> map = new HashMap<String, String>();
|
||||
for (ProcessorTableRow row : myRows) {
|
||||
if (row.name != null) {
|
||||
final String name = row.name.trim();
|
||||
if (name.length() > 0 && !map.containsKey(name)) {
|
||||
map.put(name, row.options);
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ProcessorTableRow {
|
||||
public static final int NAME_COLUMN = 0;
|
||||
public static final int OPTIONS_COLUMN = 1;
|
||||
|
||||
public String name = "";
|
||||
public String options = "";
|
||||
|
||||
public ProcessorTableRow() {
|
||||
}
|
||||
|
||||
public ProcessorTableRow(String name, String options) {
|
||||
this.name = name != null? name : "";
|
||||
this.options = options != null? options : "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+181
-99
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.compiler.options;
|
||||
|
||||
import com.intellij.compiler.ProcessorConfigProfile;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.ShortcutSet;
|
||||
@@ -25,10 +26,12 @@ import com.intellij.openapi.ui.InputValidatorEx;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.AnActionButton;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.ToolbarDecorator;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.components.JBList;
|
||||
@@ -52,16 +55,20 @@ import java.util.List;
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "UseOfObsoleteCollectionType"})
|
||||
public class AnnotationProcessorsPanel extends JPanel {
|
||||
private final Map<String, List<Module>> profiles = new HashMap<String, List<Module>>();
|
||||
private static final String DEFAULT_PROFILE = "Default";
|
||||
private final ProcessorConfigProfile myDefaultProfile = new ProcessorConfigProfile("");
|
||||
private final List<ProcessorConfigProfile> myModuleProfiles = new ArrayList<ProcessorConfigProfile>();
|
||||
private final Map<String, Module> myAllModulesMap = new HashMap<String, Module>();
|
||||
private final Project myProject;
|
||||
private final Tree myTree;
|
||||
private JPanel myContentPanel;
|
||||
private final ProcessorProfilePanel myProfilePanel;
|
||||
private ProcessorConfigProfile mySelectedProfile = null;
|
||||
|
||||
public AnnotationProcessorsPanel(Project project) {
|
||||
super(new BorderLayout());
|
||||
myProject = project;
|
||||
loadProfiles();
|
||||
for (Module module : ModuleManager.getInstance(project).getModules()) {
|
||||
myAllModulesMap.put(module.getName(), module);
|
||||
}
|
||||
myTree = new Tree(new MyTreeModel());
|
||||
myTree.setRootVisible(false);
|
||||
final JPanel treePanel =
|
||||
@@ -70,37 +77,39 @@ public class AnnotationProcessorsPanel extends JPanel {
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final MyModuleNode node = (MyModuleNode)myTree.getSelectionPath().getLastPathComponent();
|
||||
final TreePath[] selectedNodes = myTree.getSelectionPaths();
|
||||
final String key = ((MyProfileNode)node.getParent()).myKey;
|
||||
final List<String> profileNames = new ArrayList<String>();
|
||||
profileNames.add(DEFAULT_PROFILE);
|
||||
profileNames.addAll(profiles.keySet());
|
||||
profileNames.remove(key);
|
||||
final JBList list = new JBList(profileNames);
|
||||
final ProcessorConfigProfile nodeProfile = ((ProfileNode)node.getParent()).myProfile;
|
||||
final List<ProcessorConfigProfile> profiles = new ArrayList<ProcessorConfigProfile>();
|
||||
profiles.add(myDefaultProfile);
|
||||
for (ProcessorConfigProfile profile : myModuleProfiles) {
|
||||
profiles.add(profile);
|
||||
}
|
||||
profiles.remove(nodeProfile);
|
||||
final JBList list = new JBList(profiles);
|
||||
final JBPopup popup = JBPopupFactory.getInstance().createListPopupBuilder(list)
|
||||
.setTitle("Move to")
|
||||
.setItemChoosenCallback(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Object value = list.getSelectedValue();
|
||||
if (value instanceof String) {
|
||||
if (value instanceof ProcessorConfigProfile) {
|
||||
final ProcessorConfigProfile chosenProfile = (ProcessorConfigProfile)value;
|
||||
final Module toSelect = (Module)node.getUserObject();
|
||||
if (selectedNodes != null) {
|
||||
for (TreePath selectedNode : selectedNodes) {
|
||||
final Object n = selectedNode.getLastPathComponent();
|
||||
|
||||
if (n instanceof MyModuleNode) {
|
||||
Module module = (Module)((MyModuleNode)n).getUserObject();
|
||||
if (!DEFAULT_PROFILE.equals(key)) {
|
||||
profiles.get(key).remove(module);
|
||||
final Object node = selectedNode.getLastPathComponent();
|
||||
if (node instanceof MyModuleNode) {
|
||||
final Module module = (Module)((MyModuleNode)node).getUserObject();
|
||||
if (nodeProfile != myDefaultProfile) {
|
||||
nodeProfile.removeModuleName(module.getName());
|
||||
}
|
||||
if (!DEFAULT_PROFILE.equals(value)) {
|
||||
profiles.get(value).add(module);
|
||||
if (chosenProfile != myDefaultProfile) {
|
||||
chosenProfile.addModuleName(module.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final MyRootNode root = (MyRootNode)myTree.getModel().getRoot();
|
||||
final RootNode root = (RootNode)myTree.getModel().getRoot();
|
||||
root.sync();
|
||||
final DefaultMutableTreeNode node = TreeUtil.findNodeWithObject(root, toSelect);
|
||||
if (node != null) {
|
||||
@@ -123,15 +132,13 @@ public class AnnotationProcessorsPanel extends JPanel {
|
||||
public boolean isEnabled() {
|
||||
return myTree.getSelectionPath() != null
|
||||
&& myTree.getSelectionPath().getLastPathComponent() instanceof MyModuleNode
|
||||
&& !profiles.isEmpty();
|
||||
&& !myModuleProfiles.isEmpty();
|
||||
}
|
||||
}).createPanel();
|
||||
add(treePanel, BorderLayout.WEST);
|
||||
myTree.setCellRenderer(new MyCellRenderer());
|
||||
((MyRootNode)myTree.getModel().getRoot()).sync();
|
||||
myContentPanel = new JPanel(new BorderLayout());
|
||||
|
||||
myTree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
String currentProfile = null;
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
final TreePath path = myTree.getSelectionPath();
|
||||
@@ -140,25 +147,56 @@ public class AnnotationProcessorsPanel extends JPanel {
|
||||
if (node instanceof MyModuleNode) {
|
||||
node = ((MyModuleNode)node).getParent();
|
||||
}
|
||||
if (node instanceof MyProfileNode) {
|
||||
if (!StringUtil.equals(currentProfile, ((MyProfileNode)node).myKey)) {
|
||||
currentProfile = ((MyProfileNode)node).myKey;
|
||||
myContentPanel.removeAll();
|
||||
myContentPanel.add(getComponentForProfile(currentProfile), BorderLayout.CENTER);
|
||||
revalidate();
|
||||
repaint();
|
||||
if (node instanceof ProfileNode) {
|
||||
final ProcessorConfigProfile nodeProfile = ((ProfileNode)node).myProfile;
|
||||
final ProcessorConfigProfile selectedProfile = mySelectedProfile;
|
||||
if (nodeProfile != selectedProfile) {
|
||||
if (selectedProfile != null) {
|
||||
myProfilePanel.saveTo(selectedProfile);
|
||||
}
|
||||
mySelectedProfile = nodeProfile;
|
||||
myProfilePanel.setProfile(nodeProfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
add(myContentPanel, BorderLayout.CENTER);
|
||||
myProfilePanel = new ProcessorProfilePanel(project);
|
||||
myProfilePanel.setBorder(IdeBorderFactory.createEmptyBorder(0, 6, 0, 0));
|
||||
add(myProfilePanel, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public void initProfiles(ProcessorConfigProfile defaultProfile, Collection<ProcessorConfigProfile> moduleProfiles) {
|
||||
myDefaultProfile.initFrom(defaultProfile);
|
||||
myModuleProfiles.clear();
|
||||
for (ProcessorConfigProfile profile : moduleProfiles) {
|
||||
ProcessorConfigProfile copy = new ProcessorConfigProfile("");
|
||||
copy.initFrom(profile);
|
||||
myModuleProfiles.add(copy);
|
||||
}
|
||||
final RootNode root = (RootNode)myTree.getModel().getRoot();
|
||||
root.sync();
|
||||
final DefaultMutableTreeNode node = TreeUtil.findNodeWithObject(root, myDefaultProfile);
|
||||
if (node != null) {
|
||||
TreeUtil.selectNode(myTree, node);
|
||||
}
|
||||
|
||||
private JComponent getComponentForProfile(String profile) {
|
||||
//TODO[jeka] correct panel
|
||||
return new JLabel(profile, SwingConstants.CENTER);
|
||||
}
|
||||
|
||||
public ProcessorConfigProfile getDefaultProfile() {
|
||||
final ProcessorConfigProfile selectedProfile = mySelectedProfile;
|
||||
if (myDefaultProfile == selectedProfile) {
|
||||
myProfilePanel.saveTo(selectedProfile);
|
||||
}
|
||||
return myDefaultProfile;
|
||||
}
|
||||
|
||||
public List<ProcessorConfigProfile> getModuleProfiles() {
|
||||
final ProcessorConfigProfile selectedProfile = mySelectedProfile;
|
||||
if (myDefaultProfile != selectedProfile) {
|
||||
myProfilePanel.saveTo(selectedProfile);
|
||||
}
|
||||
return myModuleProfiles;
|
||||
}
|
||||
|
||||
private static void expand(JTree tree) {
|
||||
@@ -174,48 +212,74 @@ public class AnnotationProcessorsPanel extends JPanel {
|
||||
while (true);
|
||||
}
|
||||
|
||||
private void loadProfiles() {
|
||||
//TODO[jeka] init profiles map
|
||||
}
|
||||
|
||||
private class MyTreeModel extends DefaultTreeModel implements EditableTreeModel{
|
||||
public MyTreeModel() {
|
||||
super(new MyRootNode());
|
||||
super(new RootNode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreePath addNode(TreePath parentOrNeighbour) {
|
||||
final String profile = Messages.showInputDialog(myProject, "Profile name", "Create new profile", null, "", new InputValidatorEx() {
|
||||
@Override
|
||||
public boolean checkInput(String inputString) {
|
||||
return !DEFAULT_PROFILE.equals(inputString) && !profiles.containsKey(inputString) && !StringUtil.isEmpty(inputString);
|
||||
}
|
||||
final String newProfileName = Messages.showInputDialog(
|
||||
myProject, "Profile name", "Create new profile", null, "",
|
||||
new InputValidatorEx() {
|
||||
@Override
|
||||
public boolean checkInput(String inputString) {
|
||||
if (StringUtil.isEmpty(inputString) ||
|
||||
Comparing.equal(inputString, myDefaultProfile.getName())) {
|
||||
return false;
|
||||
}
|
||||
for (ProcessorConfigProfile profile : myModuleProfiles) {
|
||||
if (Comparing.equal(inputString, profile.getName())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canClose(String inputString) {
|
||||
return checkInput(inputString);
|
||||
}
|
||||
@Override
|
||||
public boolean canClose(String inputString) {
|
||||
return checkInput(inputString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorText(String inputString) {
|
||||
if (checkInput(inputString)) return null;
|
||||
return StringUtil.isEmpty(inputString) ? "Profile name shouldn't be empty"
|
||||
: "Profile " + inputString + " already exists";
|
||||
@Override
|
||||
public String getErrorText(String inputString) {
|
||||
if (checkInput(inputString)) {
|
||||
return null;
|
||||
}
|
||||
return StringUtil.isEmpty(inputString)
|
||||
? "Profile name shouldn't be empty"
|
||||
: "Profile " + inputString + " already exists";
|
||||
}
|
||||
});
|
||||
if (newProfileName != null) {
|
||||
final ProcessorConfigProfile profile = new ProcessorConfigProfile(newProfileName);
|
||||
myModuleProfiles.add(profile);
|
||||
((DataSynchronizable)getRoot()).sync();
|
||||
final DefaultMutableTreeNode object = TreeUtil.findNodeWithObject((DefaultMutableTreeNode)getRoot(), profile);
|
||||
if (object != null) {
|
||||
TreeUtil.selectNode(myTree, object);
|
||||
}
|
||||
});
|
||||
if (profile != null) {
|
||||
profiles.put(profile, new ArrayList<Module>());
|
||||
}
|
||||
((SyncWithMap)getRoot()).sync();
|
||||
final DefaultMutableTreeNode object = TreeUtil.findNodeWithObject((DefaultMutableTreeNode)getRoot(), profile);
|
||||
if (object != null) {
|
||||
TreeUtil.selectNode(myTree, object);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNode(TreePath parent) {
|
||||
public void removeNode(TreePath nodePath) {
|
||||
Object node = nodePath.getLastPathComponent();
|
||||
if (node instanceof ProfileNode) {
|
||||
final ProcessorConfigProfile nodeProfile = ((ProfileNode)node).myProfile;
|
||||
if (nodeProfile != myDefaultProfile) {
|
||||
if (mySelectedProfile == nodeProfile) {
|
||||
mySelectedProfile = null;
|
||||
}
|
||||
myModuleProfiles.remove(nodeProfile);
|
||||
((DataSynchronizable)getRoot()).sync();
|
||||
final DefaultMutableTreeNode object = TreeUtil.findNodeWithObject((DefaultMutableTreeNode)getRoot(), myDefaultProfile);
|
||||
if (object != null) {
|
||||
TreeUtil.selectNode(myTree, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -225,14 +289,14 @@ public class AnnotationProcessorsPanel extends JPanel {
|
||||
}
|
||||
|
||||
|
||||
private class MyRootNode extends DefaultMutableTreeNode implements SyncWithMap {
|
||||
private class RootNode extends DefaultMutableTreeNode implements DataSynchronizable {
|
||||
@Override
|
||||
public SyncWithMap sync() {
|
||||
public DataSynchronizable sync() {
|
||||
final Vector newKids = new Vector();
|
||||
for (String key : profiles.keySet()) {
|
||||
newKids.add(new MyProfileNode(key, this).sync());
|
||||
newKids.add(new ProfileNode(myDefaultProfile, this, true).sync());
|
||||
for (ProcessorConfigProfile profile : myModuleProfiles) {
|
||||
newKids.add(new ProfileNode(profile, this, false).sync());
|
||||
}
|
||||
newKids.add(new MyProfileNode(DEFAULT_PROFILE, this).sync());
|
||||
children = newKids;
|
||||
((DefaultTreeModel)myTree.getModel()).reload();
|
||||
expand(myTree);
|
||||
@@ -240,33 +304,44 @@ public class AnnotationProcessorsPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private interface SyncWithMap {
|
||||
SyncWithMap sync();
|
||||
private interface DataSynchronizable {
|
||||
DataSynchronizable sync();
|
||||
}
|
||||
|
||||
private class MyProfileNode extends DefaultMutableTreeNode implements SyncWithMap {
|
||||
private final String myKey;
|
||||
private class ProfileNode extends DefaultMutableTreeNode implements DataSynchronizable {
|
||||
private final ProcessorConfigProfile myProfile;
|
||||
private final boolean myIsDefault;
|
||||
|
||||
public MyProfileNode(String key, MyRootNode parent) {
|
||||
super(key);
|
||||
public ProfileNode(ProcessorConfigProfile profile, RootNode parent, boolean isDefault) {
|
||||
super(profile);
|
||||
setParent(parent);
|
||||
myKey = key;
|
||||
myIsDefault = isDefault;
|
||||
myProfile = profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SyncWithMap sync() {
|
||||
final List<Module> nodeModules;
|
||||
if (DEFAULT_PROFILE.equals(myKey)) {
|
||||
final Module[] allModules = ModuleManager.getInstance(myProject).getSortedModules();
|
||||
nodeModules = new ArrayList<Module>(Arrays.asList(allModules));
|
||||
for (List<Module> modules : profiles.values()) {
|
||||
for (Module module : modules) {
|
||||
nodeModules.remove(module);
|
||||
public DataSynchronizable sync() {
|
||||
final List<Module> nodeModules = new ArrayList<Module>();
|
||||
if (myIsDefault) {
|
||||
final Set<String> nonDefaultProfileModules = new HashSet<String>();
|
||||
for (ProcessorConfigProfile profile : myModuleProfiles) {
|
||||
nonDefaultProfileModules.addAll(profile.getModuleNames());
|
||||
}
|
||||
for (Map.Entry<String, Module> entry : myAllModulesMap.entrySet()) {
|
||||
if (!nonDefaultProfileModules.contains(entry.getKey())) {
|
||||
nodeModules.add(entry.getValue());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nodeModules = profiles.get(myKey);
|
||||
}
|
||||
else {
|
||||
for (String moduleName : myProfile.getModuleNames()) {
|
||||
final Module module = myAllModulesMap.get(moduleName);
|
||||
if (module != null) {
|
||||
nodeModules.add(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(nodeModules, ModuleComparator.INSTANCE);
|
||||
final Vector vector = new Vector();
|
||||
for (Module module : nodeModules) {
|
||||
vector.add(new MyModuleNode(module, this));
|
||||
@@ -274,32 +349,39 @@ public class AnnotationProcessorsPanel extends JPanel {
|
||||
children = vector;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class MyModuleNode extends DefaultMutableTreeNode {
|
||||
public MyModuleNode(Module module, MyProfileNode parent) {
|
||||
private static class MyModuleNode extends DefaultMutableTreeNode {
|
||||
public MyModuleNode(Module module, ProfileNode parent) {
|
||||
super(module);
|
||||
setParent(parent);
|
||||
setAllowsChildren(false);
|
||||
}
|
||||
}
|
||||
|
||||
private class MyCellRenderer extends ColoredTreeCellRenderer {
|
||||
private static class MyCellRenderer extends ColoredTreeCellRenderer {
|
||||
private static final Icon MODULE_ICON = IconLoader.getIcon("/nodes/ModuleClosed.png");
|
||||
|
||||
@Override
|
||||
public void customizeCellRenderer(JTree tree,
|
||||
Object value,
|
||||
boolean selected,
|
||||
boolean expanded,
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus) {
|
||||
if (value instanceof MyProfileNode) {
|
||||
append(((MyProfileNode)value).myKey);
|
||||
} else if (value instanceof MyModuleNode) {
|
||||
public void customizeCellRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
if (value instanceof ProfileNode) {
|
||||
append(((ProfileNode)value).myProfile.getName());
|
||||
}
|
||||
else if (value instanceof MyModuleNode) {
|
||||
final Module module = (Module)((MyModuleNode)value).getUserObject();
|
||||
setIcon(IconLoader.getIcon("/nodes/ModuleClosed.png"));
|
||||
setIcon(MODULE_ICON);
|
||||
append(module.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ModuleComparator implements Comparator<Module> {
|
||||
static final ModuleComparator INSTANCE = new ModuleComparator();
|
||||
@Override
|
||||
public int compare(Module o1, Module o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.compiler.options;
|
||||
|
||||
import com.intellij.compiler.ProcessorConfigProfile;
|
||||
import com.intellij.openapi.fileChooser.FileChooser;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.ui.EditableModel;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.JTableHeader;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
import javax.swing.table.TableModel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 5/28/12
|
||||
*/
|
||||
public class ProcessorProfilePanel extends JPanel {
|
||||
private final Project myProject;
|
||||
|
||||
private JRadioButton myRbClasspath;
|
||||
private JRadioButton myRbProcessorsPath;
|
||||
private TextFieldWithBrowseButton myProcessorPathField;
|
||||
private JTextField myGeneratedSourcesDirNameField;
|
||||
private ProcessorTableModel myProcessorsModel;
|
||||
private JCheckBox myCbEnableProcessing;
|
||||
private JBTable myProcessorTable;
|
||||
private JBTable myOptionsTable;
|
||||
private JPanel myProcessorPanel;
|
||||
private JPanel myOptionsPanel;
|
||||
private OptionsTableModel myOptionsModel;
|
||||
|
||||
|
||||
public ProcessorProfilePanel(Project project) {
|
||||
super(new GridBagLayout());
|
||||
myProject = project;
|
||||
|
||||
myCbEnableProcessing = new JCheckBox("Enable annotation processing");
|
||||
|
||||
myRbClasspath = new JRadioButton("Obtain processors from project classpath");
|
||||
myRbProcessorsPath = new JRadioButton("Processor path:");
|
||||
ButtonGroup group = new ButtonGroup();
|
||||
group.add(myRbClasspath);
|
||||
group.add(myRbProcessorsPath);
|
||||
|
||||
myProcessorPathField = new TextFieldWithBrowseButton(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createAllButJarContentsDescriptor();
|
||||
final VirtualFile[] files = FileChooser.chooseFiles(descriptor, myProcessorPathField, myProject, null);
|
||||
if (files.length > 0) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (VirtualFile file : files) {
|
||||
if (builder.length() > 0) {
|
||||
builder.append(File.pathSeparator);
|
||||
}
|
||||
builder.append(FileUtil.toSystemDependentName(file.getPath()));
|
||||
}
|
||||
myProcessorPathField.setText(builder.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final JPanel processorTablePanel = new JPanel(new BorderLayout());
|
||||
myProcessorsModel = new ProcessorTableModel();
|
||||
processorTablePanel.setBorder(IdeBorderFactory.createTitledBorder("Annotation Processors", false));
|
||||
myProcessorTable = new JBTable(myProcessorsModel);
|
||||
myProcessorTable.getEmptyText().setText("Compiler will run all automatically discovered processors");
|
||||
myProcessorPanel = createTablePanel(myProcessorTable);
|
||||
processorTablePanel.add(myProcessorPanel, BorderLayout.CENTER);
|
||||
|
||||
final JPanel optionsTablePanel = new JPanel(new BorderLayout());
|
||||
myOptionsModel = new OptionsTableModel();
|
||||
optionsTablePanel.setBorder(IdeBorderFactory.createTitledBorder("Annotation Processor options", false));
|
||||
myOptionsTable = new JBTable(myOptionsModel);
|
||||
myOptionsTable.getEmptyText().setText("No processor-specific options configured");
|
||||
myOptionsPanel = createTablePanel(myOptionsTable);
|
||||
optionsTablePanel.add(myOptionsPanel, BorderLayout.CENTER);
|
||||
|
||||
myGeneratedSourcesDirNameField = new JTextField();
|
||||
|
||||
|
||||
final JLabel warning = new JLabel("<html>WARNING!<br>" +
|
||||
/*"All source files located in the generated sources output directory WILL BE EXCLUDED from annotation processing. " +*/
|
||||
"If option 'Clear output directory on rebuild' is enabled, " +
|
||||
"the entire contents of directories specified in the table below WILL BE CLEARED on rebuild.</html>");
|
||||
warning.setFont(warning.getFont().deriveFont(Font.BOLD));
|
||||
|
||||
add(myCbEnableProcessing,
|
||||
new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
|
||||
add(myRbClasspath,
|
||||
new GridBagConstraints(0, 1, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 0, 0, 0), 0, 0));
|
||||
add(myRbProcessorsPath,
|
||||
new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 0, 0, 0), 0, 0));
|
||||
add(myProcessorPathField,
|
||||
new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0));
|
||||
|
||||
final JLabel noteMessage = new JLabel("<html>Source files generated by annotation processors will be stored under the project output directory. " +
|
||||
"To override this behaviour for this profile you may specify the directory name in the field below. " +
|
||||
"If specified, the directory will be created under corresponding module's content root.</html>");
|
||||
add(noteMessage,
|
||||
new GridBagConstraints(0, 3, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 0, 0), 0, 0));
|
||||
|
||||
add(new JLabel("Directory name:"),
|
||||
new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 0, 0), 0, 0));
|
||||
add(myGeneratedSourcesDirNameField,
|
||||
new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 0, 0), 0, 0));
|
||||
|
||||
add(processorTablePanel,
|
||||
new GridBagConstraints(0, 5, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10, 0, 0, 0), 0, 0));
|
||||
add(optionsTablePanel,
|
||||
new GridBagConstraints(0, 6, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10, 0, 0, 0), 0, 0));
|
||||
add(warning,
|
||||
new GridBagConstraints(0, 7, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 5, 0, 0), 0, 0));
|
||||
|
||||
myRbClasspath.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
updateEnabledState();
|
||||
}
|
||||
});
|
||||
|
||||
myProcessorTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (!e.getValueIsAdjusting()) {
|
||||
updateEnabledState();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myCbEnableProcessing.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
updateEnabledState();
|
||||
}
|
||||
});
|
||||
|
||||
updateEnabledState();
|
||||
|
||||
}
|
||||
|
||||
public void setProfile(ProcessorConfigProfile config) {
|
||||
myCbEnableProcessing.setSelected(config.isEnabled());
|
||||
|
||||
(config.isObtainProcessorsFromClasspath()? myRbClasspath : myRbProcessorsPath).setSelected(true);
|
||||
myProcessorPathField.setText(FileUtil.toSystemDependentName(config.getProcessorPath()));
|
||||
|
||||
final String srcDirName = config.getGeneratedSourcesDirectoryName();
|
||||
myGeneratedSourcesDirNameField.setText(srcDirName != null? srcDirName.trim() : "");
|
||||
myProcessorsModel.setProcessors(config.getProcessors());
|
||||
myOptionsModel.setOptions(config.getProcessorOptions());
|
||||
|
||||
updateEnabledState();
|
||||
}
|
||||
|
||||
public void saveTo(ProcessorConfigProfile profile) {
|
||||
profile.setEnabled(myCbEnableProcessing.isSelected());
|
||||
profile.setObtainProcessorsFromClasspath(myRbClasspath.isSelected());
|
||||
profile.setProcessorPath(myProcessorPathField.getText().trim());
|
||||
final String dirName = myGeneratedSourcesDirNameField.getText().trim();
|
||||
|
||||
profile.setGeneratedSourcesDirectoryName(StringUtil.isEmpty(dirName)? null : dirName);
|
||||
|
||||
profile.clearProcessors();
|
||||
for (String processor : myProcessorsModel.getProcessors()) {
|
||||
profile.addProcessor(processor);
|
||||
}
|
||||
profile.clearProcessorOptions();
|
||||
for (Map.Entry<String, String> entry : myOptionsModel.getOptions().entrySet()) {
|
||||
profile.setOption(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private static JPanel createTablePanel(final JBTable table) {
|
||||
return ToolbarDecorator.createDecorator(table)
|
||||
.disableUpAction()
|
||||
.disableDownAction()
|
||||
.setAddAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton anActionButton) {
|
||||
final TableCellEditor cellEditor = table.getCellEditor();
|
||||
if (cellEditor != null) {
|
||||
cellEditor.stopCellEditing();
|
||||
}
|
||||
final TableModel model = table.getModel();
|
||||
((EditableModel)model).addRow();
|
||||
TableUtil.editCellAt(table, model.getRowCount() - 1, 0);
|
||||
}
|
||||
})
|
||||
.createPanel();
|
||||
}
|
||||
|
||||
private void updateEnabledState() {
|
||||
final boolean enabled = myCbEnableProcessing.isSelected();
|
||||
final boolean useProcessorpath = !myRbClasspath.isSelected();
|
||||
myRbClasspath.setEnabled(enabled);
|
||||
myRbProcessorsPath.setEnabled(enabled);
|
||||
myProcessorPathField.setEnabled(enabled && useProcessorpath);
|
||||
updateTable(myProcessorPanel, myProcessorTable, enabled);
|
||||
updateTable(myOptionsPanel, myOptionsTable, enabled);
|
||||
myGeneratedSourcesDirNameField.setEnabled(enabled);
|
||||
}
|
||||
|
||||
private static void updateTable(final JPanel tablePanel, final JBTable table, boolean enabled) {
|
||||
final AnActionButton addButton = ToolbarDecorator.findAddButton(tablePanel);
|
||||
if (addButton != null) {
|
||||
addButton.setEnabled(enabled);
|
||||
}
|
||||
final AnActionButton removeButton = ToolbarDecorator.findRemoveButton(tablePanel);
|
||||
if (removeButton != null) {
|
||||
removeButton.setEnabled(enabled && table.getSelectedRow() >= 0);
|
||||
}
|
||||
table.setEnabled(enabled);
|
||||
final JTableHeader header = table.getTableHeader();
|
||||
if (header != null) {
|
||||
header.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private static class OptionsTableModel extends AbstractTableModel implements EditableModel {
|
||||
private final java.util.List<KeyValuePair> myRows = new ArrayList<KeyValuePair>();
|
||||
|
||||
public String getColumnName(int column) {
|
||||
switch (column) {
|
||||
case 0: return "Option Name";
|
||||
case 1: return "Value";
|
||||
}
|
||||
return super.getColumnName(column);
|
||||
}
|
||||
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public int getRowCount() {
|
||||
return myRows.size();
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return columnIndex == 0 || columnIndex == 1;
|
||||
}
|
||||
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case 0: return myRows.get(rowIndex).key;
|
||||
case 1: return myRows.get(rowIndex).value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
if (aValue != null) {
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
myRows.get(rowIndex).key = (String)aValue;
|
||||
break;
|
||||
case 1:
|
||||
myRows.get(rowIndex).value = (String)aValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeRow(int idx) {
|
||||
myRows.remove(idx);
|
||||
fireTableRowsDeleted(idx, idx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exchangeRows(int oldIndex, int newIndex) {
|
||||
}
|
||||
|
||||
public void addRow() {
|
||||
myRows.add(new KeyValuePair());
|
||||
final int index = myRows.size() - 1;
|
||||
fireTableRowsInserted(index, index);
|
||||
}
|
||||
|
||||
public void setOptions(Map<String, String> options) {
|
||||
clear();
|
||||
if (!options.isEmpty()) {
|
||||
for (Map.Entry<String, String> entry : options.entrySet()) {
|
||||
myRows.add(new KeyValuePair(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
Collections.sort(myRows, new Comparator<KeyValuePair>() {
|
||||
@Override
|
||||
public int compare(KeyValuePair o1, KeyValuePair o2) {
|
||||
return o1.key.compareToIgnoreCase(o2.key);
|
||||
}
|
||||
});
|
||||
fireTableRowsInserted(0, options.size()-1);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final int count = myRows.size();
|
||||
if (count > 0) {
|
||||
myRows.clear();
|
||||
fireTableRowsDeleted(0, count-1);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> getOptions() {
|
||||
final Map<String, String> map = new java.util.HashMap<String, String>();
|
||||
for (KeyValuePair pair : myRows) {
|
||||
map.put(pair.key.trim(), pair.value.trim());
|
||||
}
|
||||
map.remove("");
|
||||
return map;
|
||||
}
|
||||
|
||||
private static final class KeyValuePair {
|
||||
String key;
|
||||
String value;
|
||||
|
||||
KeyValuePair() {
|
||||
this("", "");
|
||||
}
|
||||
|
||||
KeyValuePair(String key, String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProcessorTableModel extends AbstractTableModel implements EditableModel {
|
||||
private final List<String> myRows = new ArrayList<String>();
|
||||
|
||||
public String getColumnName(int column) {
|
||||
switch (column) {
|
||||
case 0: return "Processor FQ Name";
|
||||
}
|
||||
return super.getColumnName(column);
|
||||
}
|
||||
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public int getRowCount() {
|
||||
return myRows.size();
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return columnIndex == 0;
|
||||
}
|
||||
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case 0: return myRows.get(rowIndex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
if (aValue != null) {
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
myRows.set(rowIndex, (String)aValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeRow(int idx) {
|
||||
myRows.remove(idx);
|
||||
fireTableRowsDeleted(idx, idx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exchangeRows(int oldIndex, int newIndex) {
|
||||
}
|
||||
|
||||
public void addRow() {
|
||||
myRows.add("");
|
||||
final int index = myRows.size() - 1;
|
||||
fireTableRowsInserted(index, index);
|
||||
}
|
||||
|
||||
public void setProcessors(Collection<String> processors) {
|
||||
clear();
|
||||
if (!processors.isEmpty()) {
|
||||
for (String processor : processors) {
|
||||
myRows.add(processor);
|
||||
}
|
||||
Collections.sort(myRows, new Comparator<String>() {
|
||||
public int compare(String o1, String o2) {
|
||||
return o1.compareToIgnoreCase(o2);
|
||||
}
|
||||
});
|
||||
fireTableRowsInserted(0, processors.size()-1);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final int count = myRows.size();
|
||||
if (count > 0) {
|
||||
myRows.clear();
|
||||
fireTableRowsDeleted(0, count-1);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<String> getProcessors() {
|
||||
final Set<String> set = new HashSet<String>();
|
||||
for (String row : myRows) {
|
||||
if (row != null) {
|
||||
set.add(row.trim());
|
||||
}
|
||||
}
|
||||
set.remove("");
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.compiler;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 5/27/12
|
||||
*/
|
||||
public interface AnnotationProcessingConfiguration {
|
||||
boolean isEnabled();
|
||||
|
||||
@NotNull
|
||||
String getProcessorPath();
|
||||
|
||||
@Nullable
|
||||
String getGeneratedSourcesDirectoryName();
|
||||
|
||||
@NotNull
|
||||
Set<String> getProcessors();
|
||||
|
||||
@NotNull
|
||||
Map<String, String> getProcessorOptions();
|
||||
|
||||
boolean isObtainProcessorsFromClasspath();
|
||||
}
|
||||
@@ -19,10 +19,9 @@ package com.intellij.compiler;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
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,6 +34,14 @@ public abstract class CompilerConfiguration {
|
||||
|
||||
public abstract void setBytecodeTargetLevel(Module module, String level);
|
||||
|
||||
@NotNull
|
||||
public abstract AnnotationProcessingConfiguration getAnnotationProcessingConfiguration(Module module);
|
||||
|
||||
/**
|
||||
* @return true if exists at least one enabled annotation processing profile
|
||||
*/
|
||||
public abstract boolean isAnnotationProcessorsEnabled();
|
||||
|
||||
public static CompilerConfiguration getInstance(Project project) {
|
||||
return project.getComponent(CompilerConfiguration.class);
|
||||
}
|
||||
@@ -50,28 +57,4 @@ public abstract class CompilerConfiguration {
|
||||
public abstract boolean isAddNotNullAssertions();
|
||||
|
||||
public abstract void setAddNotNullAssertions(boolean enabled);
|
||||
|
||||
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 void setAnotationProcessedModules(Map<Module, String> modules);
|
||||
|
||||
public abstract Map<Module, String> getAnotationProcessedModules();
|
||||
|
||||
public abstract boolean isAnnotationProcessingEnabled(Module module);
|
||||
|
||||
public abstract String getGeneratedSourceDirName(Module module);
|
||||
}
|
||||
@@ -216,8 +216,8 @@ public class CompilerPaths {
|
||||
public static String getAnnotationProcessorsGenerationPath(Module module) {
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(module.getProject());
|
||||
|
||||
final String sourceDirName = config.getGeneratedSourceDirName(module);
|
||||
if (sourceDirName != null && sourceDirName.length() > 0) {
|
||||
final String sourceDirName = config.getAnnotationProcessingConfiguration(module).getGeneratedSourcesDirectoryName();
|
||||
if (!StringUtil.isEmpty(sourceDirName)) {
|
||||
final String[] roots = ModuleRootManager.getInstance(module).getContentRootUrls();
|
||||
if (roots.length == 0) {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user