mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
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;
|
||||
|
||||
+4
-2
@@ -80,9 +80,11 @@ public class CreateNewLibraryAction extends DumbAwareAction {
|
||||
@NotNull final Project project, @NotNull final LibrariesModifiableModel modifiableModel) {
|
||||
final NewLibraryConfiguration configuration = createNewLibraryConfiguration(type, parentComponent, project);
|
||||
if (configuration == null) return null;
|
||||
final Library library = modifiableModel.createLibrary(LibraryEditingUtil.suggestNewLibraryName(modifiableModel, configuration.getDefaultLibraryName()), configuration.getLibraryType().getKind());
|
||||
final LibraryType<?> libraryType = configuration.getLibraryType();
|
||||
final Library library = modifiableModel.createLibrary(
|
||||
LibraryEditingUtil.suggestNewLibraryName(modifiableModel, configuration.getDefaultLibraryName()), libraryType != null ? libraryType.getKind() : null);
|
||||
|
||||
final NewLibraryEditor editor = new NewLibraryEditor(configuration.getLibraryType(), configuration.getProperties());
|
||||
final NewLibraryEditor editor = new NewLibraryEditor(libraryType, configuration.getProperties());
|
||||
configuration.addRoots(editor);
|
||||
final Library.ModifiableModel model = library.getModifiableModel();
|
||||
editor.applyTo((LibraryEx.ModifiableModelEx)model);
|
||||
|
||||
@@ -540,6 +540,7 @@ public class HighlightUtil {
|
||||
if (errorResult != null && valueType != null) {
|
||||
IntentionAction fix = QUICK_FIX_FACTORY.createMethodReturnFix(method, valueType, true);
|
||||
QuickFixAction.registerQuickFixAction(errorResult, fix);
|
||||
ChangeParameterClassFix.registerQuickFixAction(returnType, valueType, errorResult);
|
||||
if (returnType instanceof PsiArrayType && TypeConversionUtil.isAssignable(((PsiArrayType)returnType).getComponentType(), valueType)) {
|
||||
QuickFixAction.registerQuickFixAction(errorResult, new SurroundWithArrayFix(null) {
|
||||
@Override
|
||||
@@ -2507,7 +2508,7 @@ public class HighlightUtil {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, action);
|
||||
}
|
||||
}
|
||||
ChangeParameterClassFix.registerQuickFixAction(parameter, itemType, highlightInfo);
|
||||
ChangeParameterClassFix.registerQuickFixAction(parameter.getType(), itemType, highlightInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+20
-16
@@ -61,11 +61,11 @@ public class ChangeParameterClassFix extends ExtendsListFix {
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
return
|
||||
super.isAvailable(project, file, startElement, endElement)
|
||||
&& myClassToExtendFrom != null
|
||||
&& myClassToExtendFrom.isValid()
|
||||
&& myClassToExtendFrom.getQualifiedName() != null
|
||||
;
|
||||
super.isAvailable(project, file, startElement, endElement)
|
||||
&& myClassToExtendFrom != null
|
||||
&& myClassToExtendFrom.isValid()
|
||||
&& myClassToExtendFrom.getQualifiedName() != null
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -114,18 +114,21 @@ public class ChangeParameterClassFix extends ExtendsListFix {
|
||||
UndoUtil.markPsiFileForUndo(file);
|
||||
}
|
||||
|
||||
public static void registerQuickFixAction(PsiVariable variable, PsiType returnType, HighlightInfo info) {
|
||||
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(returnType);
|
||||
final PsiType variableType = variable.getType();
|
||||
final PsiClass variableClass = PsiUtil.resolveClassInClassTypeOnly(variableType);
|
||||
if (psiClass != null && variableClass != null && !psiClass.isInheritor(variableClass, true)) {
|
||||
QuickFixAction.registerQuickFixAction(info, new ChangeParameterClassFix(psiClass, (PsiClassType)variableType));
|
||||
}
|
||||
public static void registerQuickFixAction(PsiType lType, PsiType rType, HighlightInfo info) {
|
||||
final PsiClass lClass = PsiUtil.resolveClassInClassTypeOnly(lType);
|
||||
final PsiClass rClass = PsiUtil.resolveClassInClassTypeOnly(rType);
|
||||
|
||||
if (rClass == null || lClass == null) return;
|
||||
if (rClass instanceof PsiAnonymousClass) return;
|
||||
if (rClass.isInheritor(lClass, true)) return;
|
||||
if (lClass.isInheritor(rClass, true)) return;
|
||||
|
||||
QuickFixAction.registerQuickFixAction(info, new ChangeParameterClassFix(rClass, (PsiClassType)lType));
|
||||
}
|
||||
|
||||
|
||||
public static void registerQuickFixActions(PsiCall methodCall, PsiExpressionList list, HighlightInfo highlightInfo) {
|
||||
final JavaResolveResult result = methodCall.resolveMethodGenerics();
|
||||
PsiMethod method = (PsiMethod) result.getElement();
|
||||
PsiMethod method = (PsiMethod)result.getElement();
|
||||
final PsiSubstitutor substitutor = result.getSubstitutor();
|
||||
PsiExpression[] expressions = list.getExpressions();
|
||||
if (method == null || method.getParameterList().getParametersCount() != expressions.length) return;
|
||||
@@ -134,12 +137,13 @@ public class ChangeParameterClassFix extends ExtendsListFix {
|
||||
PsiParameter parameter = method.getParameterList().getParameters()[i];
|
||||
PsiType expressionType = expression.getType();
|
||||
PsiType parameterType = substitutor.substitute(parameter.getType());
|
||||
if (expressionType == null || expressionType instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(expressionType) || expressionType instanceof PsiArrayType ) continue;
|
||||
if (parameterType instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(parameterType) || parameterType instanceof PsiArrayType ) continue;
|
||||
if (expressionType == null || expressionType instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(expressionType) || expressionType instanceof PsiArrayType) continue;
|
||||
if (parameterType instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(parameterType) || parameterType instanceof PsiArrayType) continue;
|
||||
if (parameterType.isAssignableFrom(expressionType)) continue;
|
||||
PsiClass parameterClass = PsiUtil.resolveClassInType(parameterType);
|
||||
PsiClass expressionClass = PsiUtil.resolveClassInType(expressionType);
|
||||
if (parameterClass == null || expressionClass == null) continue;
|
||||
if (expressionClass instanceof PsiAnonymousClass) continue;
|
||||
if (parameterClass.isInheritor(expressionClass, true)) continue;
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new ChangeParameterClassFix(expressionClass, (PsiClassType)parameterType));
|
||||
}
|
||||
|
||||
@@ -412,7 +412,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private void inlineMethodCall(PsiReferenceExpression ref) throws IncorrectOperationException {
|
||||
public void inlineMethodCall(PsiReferenceExpression ref) throws IncorrectOperationException {
|
||||
InlineUtil.TailCallType tailCall = InlineUtil.getTailCallType(ref);
|
||||
ChangeContextUtil.encodeContextInfo(myMethod, false);
|
||||
myMethodCopy = (PsiMethod)myMethod.copy();
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ public class InlineSuperCallUsageInfo extends FixableUsageInfo {
|
||||
assert inliningClass != null;
|
||||
methodCopy = (PsiMethod)inliningClass.add(methodCopy);
|
||||
final InlineMethodProcessor inlineMethodProcessor = new InlineMethodProcessor(getProject(), methodCopy, methodExpression, null, true);
|
||||
inlineMethodProcessor.run();
|
||||
inlineMethodProcessor.inlineMethodCall(methodExpression);
|
||||
methodCopy.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
@@ -356,7 +357,8 @@ public class PushDownProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
else if (member instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)member;
|
||||
final PsiMethod methodBySignature = targetClass.findMethodBySignature(method, false);
|
||||
final PsiMethod methodBySignature =
|
||||
MethodSignatureUtil.findMethodBySuperSignature(targetClass, method.getSignature(substitutor), false);
|
||||
if (methodBySignature == null) {
|
||||
final boolean wasInterface = myClass.isInterface();
|
||||
newMember = (PsiMethod)targetClass.add(method);
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make 'Foo' implement 'Foo.Bar'" "true"
|
||||
public class Foo implements Foo.Bar {
|
||||
|
||||
public Bar getBar() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public interface Bar {}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Make 'null' implement 'Foo.IBar'" "false"
|
||||
|
||||
public abstract class Foo {
|
||||
static Foo anonymous = new Foo() {
|
||||
@Override
|
||||
void fooMethod() {
|
||||
foo2Method(th<caret>is);
|
||||
}
|
||||
};
|
||||
|
||||
protected Foo() {
|
||||
IBar bar = anonymou<caret>s;
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// "Make 'null' implement 'Foo.IBar'" "false"
|
||||
|
||||
public abstract class Foo {
|
||||
public static interface IBar {
|
||||
void barMethod();
|
||||
}
|
||||
|
||||
abstract void fooMethod();
|
||||
|
||||
void foo2Method(IBar b) {
|
||||
}
|
||||
|
||||
static Foo anonymous = new Foo() {
|
||||
@Override
|
||||
void fooMethod() {
|
||||
foo2Method(th<caret>is);
|
||||
}
|
||||
};
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Make 'Foo' implement 'Foo.Bar'" "false"
|
||||
public class Foo {
|
||||
|
||||
public void getBar() {
|
||||
Bar f = new F<caret>oo();
|
||||
}
|
||||
|
||||
public class Bar extends Foo {
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Make 'Foo' implement 'Foo.Bar'" "true"
|
||||
public class Foo {
|
||||
|
||||
public Bar getBar() {
|
||||
return t<caret>his;
|
||||
}
|
||||
|
||||
public interface Bar {}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
abstract class BaseTask<T, S extends BaseTask<T, S>> {
|
||||
public abstract S make<caret>Task(int depth, ParallelStream<T> coll);
|
||||
}
|
||||
|
||||
|
||||
class ForEachTask<T> extends BaseTask<T, ForEachTask<T>> {
|
||||
public ForEachTask<T> makeTask(int depth, ParallelStream<T> coll) {
|
||||
return new ForEachTask<T>();
|
||||
}
|
||||
}
|
||||
|
||||
class ParallelStream<T> {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
abstract class BaseTask<T, S extends BaseTask<T, S>> {
|
||||
}
|
||||
|
||||
|
||||
class ForEachTask<T> extends BaseTask<T, ForEachTask<T>> {
|
||||
public ForEachTask<T> makeTask(int depth, ParallelStream<T> coll) {
|
||||
return new ForEachTask<T>();
|
||||
}
|
||||
}
|
||||
|
||||
class ParallelStream<T> {
|
||||
}
|
||||
@@ -115,6 +115,10 @@ public class PushDownTest extends LightRefactoringTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testOverridingMethodWithSubst() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSameClassInterface() throws Exception {
|
||||
final String filePath = "/refactoring/pushDown/" + getTestName(false) + ".java";
|
||||
configureByFile(filePath);
|
||||
|
||||
@@ -46,6 +46,7 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler
|
||||
private final CanceledStatus myCancelStatus;
|
||||
private float myDone = -1.0f;
|
||||
private EventDispatcher<BuildListener> myListeners = EventDispatcher.create(BuildListener.class);
|
||||
private Map<Module, AnnotationProcessingProfile> myAnnotationProcessingProfileMap;
|
||||
|
||||
public CompileContext(CompileScope scope,
|
||||
ProjectDescriptor pd, boolean isMake,
|
||||
@@ -103,6 +104,32 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler
|
||||
myListeners.removeListener(listener);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public AnnotationProcessingProfile getAnnotationProcessingProfile(Module module) {
|
||||
final CompilerConfiguration compilerConfig = getProject().getCompilerConfiguration();
|
||||
Map<Module, AnnotationProcessingProfile> map = myAnnotationProcessingProfileMap;
|
||||
if (map == null) {
|
||||
map = new HashMap<Module, AnnotationProcessingProfile>();
|
||||
final Map<String, Module> namesMap = new HashMap<String, Module>();
|
||||
for (Module m : getProject().getModules().values()) {
|
||||
namesMap.put(m.getName(), m);
|
||||
}
|
||||
if (!namesMap.isEmpty()) {
|
||||
for (AnnotationProcessingProfile profile : compilerConfig.getModuleAnnotationProcessingProfiles()) {
|
||||
for (String name : profile.getProcessModule()) {
|
||||
final Module mod = namesMap.get(name);
|
||||
if (mod != null) {
|
||||
map.put(mod, profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
myAnnotationProcessingProfileMap = map;
|
||||
}
|
||||
final AnnotationProcessingProfile profile = map.get(module);
|
||||
return profile != null? profile : compilerConfig.getDefaultAnnotationProcessingProfile();
|
||||
}
|
||||
|
||||
public void markDirty(final File file) throws IOException {
|
||||
final RootDescriptor descriptor = getModuleAndRoot(file);
|
||||
if (descriptor != null) {
|
||||
|
||||
@@ -416,6 +416,15 @@ public class IncProjectBuilder {
|
||||
throw new ProjectBuildException(e);
|
||||
}
|
||||
finally {
|
||||
final Collection<RootDescriptor> tempRoots = context.getRootsIndex().clearTempRoots();
|
||||
if (!tempRoots.isEmpty()) {
|
||||
final Set<File> rootFiles = new HashSet<File>();
|
||||
for (RootDescriptor rd : tempRoots) {
|
||||
rootFiles.add(rd.root);
|
||||
context.getProjectDescriptor().fsState.clearRecompile(rd);
|
||||
}
|
||||
FileUtil.asyncDelete(rootFiles);
|
||||
}
|
||||
|
||||
try {
|
||||
// restore deleted paths that were not procesesd by 'integrate'
|
||||
|
||||
@@ -41,13 +41,13 @@ public class ModuleRootsIndex {
|
||||
}
|
||||
for (String r : module.getSourceRoots()) {
|
||||
final File root = new File(FileUtil.toCanonicalPath(r));
|
||||
final RootDescriptor descriptor = new RootDescriptor(moduleName, root, false, generatedRoots.contains(r));
|
||||
final RootDescriptor descriptor = new RootDescriptor(moduleName, root, false, generatedRoots.contains(r), false);
|
||||
myRootToModuleMap.put(root, descriptor);
|
||||
moduleRoots.add(descriptor);
|
||||
}
|
||||
for (String r : module.getTestRoots()) {
|
||||
final File root = new File(FileUtil.toCanonicalPath(r));
|
||||
final RootDescriptor descriptor = new RootDescriptor(moduleName, root, true, generatedRoots.contains(r));
|
||||
final RootDescriptor descriptor = new RootDescriptor(moduleName, root, true, generatedRoots.contains(r), false);
|
||||
myRootToModuleMap.put(root, descriptor);
|
||||
moduleRoots.add(descriptor);
|
||||
}
|
||||
@@ -79,7 +79,7 @@ public class ModuleRootsIndex {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public RootDescriptor associateRoot(File root, Module module, boolean isTestRoot, final boolean isForGeneratedSources) {
|
||||
public RootDescriptor associateRoot(File root, Module module, boolean isTestRoot, final boolean isForGeneratedSources, final boolean isTemp) {
|
||||
final RootDescriptor d = myRootToModuleMap.get(root);
|
||||
if (d != null) {
|
||||
return d;
|
||||
@@ -89,12 +89,29 @@ public class ModuleRootsIndex {
|
||||
moduleRoots = new ArrayList<RootDescriptor>();
|
||||
myModuleToRootsMap.put(module, moduleRoots);
|
||||
}
|
||||
final RootDescriptor descriptor = new RootDescriptor(module.getName(), root, isTestRoot, isForGeneratedSources);
|
||||
final RootDescriptor descriptor = new RootDescriptor(module.getName(), root, isTestRoot, isForGeneratedSources, isTemp);
|
||||
myRootToModuleMap.put(root, descriptor);
|
||||
moduleRoots.add(descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<RootDescriptor> clearTempRoots() {
|
||||
final Set<RootDescriptor> toRemove = new HashSet<RootDescriptor>();
|
||||
for (Iterator<Map.Entry<File, RootDescriptor>> iterator = myRootToModuleMap.entrySet().iterator(); iterator.hasNext(); ) {
|
||||
Map.Entry<File, RootDescriptor> entry = iterator.next();
|
||||
final RootDescriptor rd = entry.getValue();
|
||||
if (rd.isTemp) {
|
||||
toRemove.add(rd);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
for (Map.Entry<Module, List<RootDescriptor>> entry : myModuleToRootsMap.entrySet()) {
|
||||
entry.getValue().removeAll(toRemove);
|
||||
}
|
||||
return toRemove;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RootDescriptor getModuleAndRoot(File file) {
|
||||
File current = file;
|
||||
|
||||
@@ -15,12 +15,14 @@ public final class RootDescriptor {
|
||||
public final File root;
|
||||
public final boolean isTestRoot;
|
||||
public final boolean isGeneratedSources;
|
||||
public final boolean isTemp;
|
||||
|
||||
public RootDescriptor(@NotNull final String moduleName, @NotNull File root, boolean isTestRoot, boolean isGenerated) {
|
||||
public RootDescriptor(@NotNull final String moduleName, @NotNull File root, boolean isTestRoot, boolean isGenerated, boolean isTemp) {
|
||||
this.module = moduleName;
|
||||
this.root = root;
|
||||
this.isTestRoot = isTestRoot;
|
||||
this.isGeneratedSources = isGenerated;
|
||||
this.isTemp = isTemp;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -60,7 +60,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
public static final boolean USE_EMBEDDED_JAVAC = System.getProperty(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null;
|
||||
private static final Key<Integer> JAVA_COMPILER_VERSION_KEY = Key.create("_java_compiler_version_");
|
||||
private static final Set<String> FILTERED_OPTIONS = new HashSet<String>(Arrays.<String>asList(
|
||||
"-target"
|
||||
"-target", "-proc:none", "-proc:only"
|
||||
));
|
||||
private static final Set<String> FILTERED_SINGLE_OPTIONS = new HashSet<String>(Arrays.<String>asList(
|
||||
"-g", "-deprecation", "-nowarn", "-verbose"
|
||||
@@ -89,26 +89,32 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
//add here class processors in the sequence they should be executed
|
||||
myClassProcessors.add(new ClassPostProcessor() {
|
||||
public void process(CompileContext context, OutputFileObject out) {
|
||||
final Callbacks.Backend callback = DELTA_MAPPINGS_CALLBACK_KEY.get(context);
|
||||
if (callback != null) {
|
||||
final OutputFileObject.Content content = out.getContent();
|
||||
final File srcFile = out.getSourceFile();
|
||||
if (srcFile != null && content != null) {
|
||||
final String outputPath = FileUtil.toSystemIndependentName(out.getFile().getPath());
|
||||
final String sourcePath = FileUtil.toSystemIndependentName(srcFile.getPath());
|
||||
final RootDescriptor moduleAndRoot = context.getModuleAndRoot(srcFile);
|
||||
final BuildDataManager dataManager = context.getDataManager();
|
||||
if (moduleAndRoot != null) {
|
||||
final OutputFileObject.Content content = out.getContent();
|
||||
final File srcFile = out.getSourceFile();
|
||||
if (srcFile != null && content != null) {
|
||||
final String outputPath = FileUtil.toSystemIndependentName(out.getFile().getPath());
|
||||
final String sourcePath = FileUtil.toSystemIndependentName(srcFile.getPath());
|
||||
final RootDescriptor moduleAndRoot = context.getModuleAndRoot(srcFile);
|
||||
final BuildDataManager dataManager = context.getDataManager();
|
||||
boolean isTemp = false;
|
||||
if (moduleAndRoot != null) {
|
||||
isTemp = moduleAndRoot.isTemp;
|
||||
if (!isTemp) {
|
||||
try {
|
||||
final String moduleName = moduleAndRoot.module;
|
||||
dataManager.getSourceToOutputMap(moduleName, context.isCompilingTests()).appendData(sourcePath, outputPath);
|
||||
dataManager.getSourceToOutputMap(moduleAndRoot.module, context.isCompilingTests()).appendData(sourcePath, outputPath);
|
||||
}
|
||||
catch (Exception e) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, e));
|
||||
}
|
||||
}
|
||||
final ClassReader reader = new ClassReader(content.getBuffer(), content.getOffset(), content.getLength());
|
||||
callback.associate(outputPath, sourcePath, reader);
|
||||
}
|
||||
out.setTemp(isTemp);
|
||||
if (!isTemp) {
|
||||
final Callbacks.Backend callback = DELTA_MAPPINGS_CALLBACK_KEY.get(context);
|
||||
if (callback != null) {
|
||||
final ClassReader reader = new ClassReader(content.getBuffer(), content.getOffset(), content.getLength());
|
||||
callback.associate(outputPath, sourcePath, reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,17 +130,6 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
return "Java Builder";
|
||||
}
|
||||
|
||||
private static final Key<Set<File>> TEMPORARY_SOURCE_ROOTS_KEY = Key.create("_additional_source_roots_");
|
||||
|
||||
public static void addTempSourcePathRoot(CompileContext context, File root) {
|
||||
Set<File> roots = TEMPORARY_SOURCE_ROOTS_KEY.get(context);
|
||||
if (roots == null) {
|
||||
roots = new HashSet<File>();
|
||||
TEMPORARY_SOURCE_ROOTS_KEY.set(context, roots);
|
||||
}
|
||||
roots.add(root);
|
||||
}
|
||||
|
||||
public ExitCode build(final CompileContext context, final ModuleChunk chunk) throws ProjectBuildException {
|
||||
try {
|
||||
final Set<File> filesToCompile = new HashSet<File>();
|
||||
@@ -282,7 +277,15 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
try {
|
||||
if (hasSourcesToCompile) {
|
||||
exitCode = ExitCode.OK;
|
||||
final Set<File> sourcePath = TEMPORARY_SOURCE_ROOTS_KEY.get(context, Collections.<File>emptySet());
|
||||
final Set<File> tempRootsSourcePath = new HashSet<File>();
|
||||
final ModuleRootsIndex index = context.getRootsIndex();
|
||||
for (Module module : chunk.getModules()) {
|
||||
for (RootDescriptor rd : index.getModuleRoots(module)) {
|
||||
if (rd.isTemp) {
|
||||
tempRootsSourcePath.add(rd.root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final String chunkName = getChunkPresentableName(chunk);
|
||||
context.processMessage(new ProgressMessage("Compiling java [" + chunkName + "]"));
|
||||
@@ -291,7 +294,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
boolean compiledOk = true;
|
||||
if (filesCount > 0) {
|
||||
LOG.info("Compiling " + filesCount + " java files; module: " + chunkName);
|
||||
compiledOk = compileJava(chunk, files, classpath, platformCp, sourcePath, outs, context, diagnosticSink, outputSink);
|
||||
compiledOk = compileJava(chunk, files, classpath, platformCp, tempRootsSourcePath, outs, context, diagnosticSink, outputSink);
|
||||
}
|
||||
|
||||
context.checkCanceled();
|
||||
@@ -362,13 +365,6 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
if (exitCode != ExitCode.ADDITIONAL_PASS_REQUIRED) {
|
||||
final Set<File> tempRoots = TEMPORARY_SOURCE_ROOTS_KEY.get(context);
|
||||
TEMPORARY_SOURCE_ROOTS_KEY.set(context, null);
|
||||
if (tempRoots != null && tempRoots.size() > 0) {
|
||||
FileUtil.asyncDelete(tempRoots);
|
||||
}
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
@@ -399,6 +395,9 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
DiagnosticOutputConsumer diagnosticSink,
|
||||
final OutputFileConsumer outputSink) throws Exception {
|
||||
final List<String> options = getCompilationOptions(context, chunk);
|
||||
if (context.errorsDetected()) {
|
||||
return true;
|
||||
}
|
||||
final ClassProcessingConsumer classesConsumer = new ClassProcessingConsumer(context, outputSink);
|
||||
try {
|
||||
final boolean rc;
|
||||
@@ -670,9 +669,57 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
AnnotationProcessingProfile profile = null;
|
||||
for (Module module : chunk.getModules()) {
|
||||
if (profile == null) {
|
||||
profile = context.getAnnotationProcessingProfile(module);
|
||||
}
|
||||
else {
|
||||
final AnnotationProcessingProfile profile2 = context.getAnnotationProcessingProfile(module);
|
||||
if (profile2 != profile) {
|
||||
String message = "Modules in cycle [" + getChunkPresentableName(chunk) + "] must use the same annotation processing profile";
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (profile != null && profile.isEnabled()) {
|
||||
// configuring annotation processing
|
||||
if (!profile.getObtainProcessorsFromClasspath()) {
|
||||
final String processorsPath = profile.getProcessorsPath();
|
||||
options.add("-processorpath");
|
||||
options.add(processorsPath == null? "" : FileUtil.toSystemDependentName(processorsPath.trim()));
|
||||
}
|
||||
|
||||
for (String procFQName : profile.getProcessors()) {
|
||||
options.add("-processor");
|
||||
options.add(procFQName);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> optionEntry : profile.getProcessorsOptions().entrySet()) {
|
||||
options.add("-A" + optionEntry.getKey() + "=" + optionEntry.getValue());
|
||||
}
|
||||
|
||||
final File srcOutput = getGeneratedSourcesOutputDirectory(context, chunk, profile.getGeneratedSourcesDirName());
|
||||
if (srcOutput != null) {
|
||||
srcOutput.mkdirs();
|
||||
options.add("-s");
|
||||
options.add(srcOutput.getPath());
|
||||
}
|
||||
}
|
||||
else {
|
||||
options.add("-proc:none");
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static File getGeneratedSourcesOutputDirectory(CompileContext context, ModuleChunk chunk, String name) {
|
||||
// todo: support multiple outputs for module chunk
|
||||
return context.getProjectPaths().getAnnotationProcessorGeneratedSourcesOutputDir(chunk.getModules().iterator().next(), context.isCompilingTests(), name);
|
||||
}
|
||||
|
||||
private static boolean isEncodingSet(List<String> options) {
|
||||
for (String option : options) {
|
||||
if ("-encoding".equals(option)) {
|
||||
@@ -718,7 +765,8 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
|
||||
//options.add("-verbose");
|
||||
final Project project = context.getProject();
|
||||
final Map<String, String> javacOpts = project.getCompilerConfiguration().getJavacOptions();
|
||||
final CompilerConfiguration compilerConfig = project.getCompilerConfiguration();
|
||||
final Map<String, String> javacOpts = compilerConfig.getJavacOptions();
|
||||
final boolean debugInfo = !"false".equals(javacOpts.get("DEBUGGING_INFO"));
|
||||
final boolean nowarn = "true".equals(javacOpts.get("GENERATE_NO_WARNINGS"));
|
||||
final boolean deprecation = !"false".equals(javacOpts.get("DEPRECATION"));
|
||||
@@ -778,6 +826,9 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
private static void instrumentNotNull(CompileContext context, OutputFilesSink sink, final InstrumentationClassFinder finder) {
|
||||
for (final OutputFileObject fileObject : sink.getFileObjects()) {
|
||||
final OutputFileObject.Content originalContent = fileObject.getContent();
|
||||
if (originalContent == null || !JavaFileObject.Kind.CLASS.equals(fileObject.getKind())) {
|
||||
continue;
|
||||
}
|
||||
final ClassReader reader = new ClassReader(originalContent.getBuffer(), originalContent.getOffset(), originalContent.getLength());
|
||||
final int version = getClassFileVersion(reader);
|
||||
if (version >= Opcodes.V1_5) {
|
||||
@@ -822,7 +873,9 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
|
||||
final Map<String, OutputFileObject> compiledClassNames = new HashMap<String, OutputFileObject>();
|
||||
for (OutputFileObject fileObject : outputSink.getFileObjects()) {
|
||||
compiledClassNames.put(fileObject.getClassName(), fileObject);
|
||||
if (JavaFileObject.Kind.CLASS.equals(fileObject.getKind())) {
|
||||
compiledClassNames.put(fileObject.getClassName(), fileObject);
|
||||
}
|
||||
}
|
||||
|
||||
final MyNestedFormLoader nestedFormsLoader =
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.util.*;
|
||||
*/
|
||||
class OutputFilesSink implements OutputFileConsumer {
|
||||
private final CompileContext myContext;
|
||||
private final Set<File> mySuccessfullyCompiled = new HashSet<File>();
|
||||
private final Set<File> mySuccessfullyCompiled = new LinkedHashSet<File>();
|
||||
private final Set<File> myProblematic = new HashSet<File>();
|
||||
private final List<OutputFileObject> myFileObjects = new ArrayList<OutputFileObject>();
|
||||
private final Map<String, OutputFileObject> myCompiledClasses = new HashMap<String, OutputFileObject>();
|
||||
@@ -113,7 +113,7 @@ class OutputFilesSink implements OutputFileConsumer {
|
||||
}
|
||||
|
||||
final File source = fileObject.getSourceFile();
|
||||
if (source != null && !myProblematic.contains(source)) {
|
||||
if (!fileObject.isTemp() && source != null && !myProblematic.contains(source)) {
|
||||
mySuccessfullyCompiled.add(source);
|
||||
final String className = fileObject.getClassName();
|
||||
if (className != null) {
|
||||
|
||||
@@ -19,7 +19,7 @@ public class JavacMain {
|
||||
"-d", "-classpath", "-cp", "-bootclasspath"
|
||||
));
|
||||
private static final Set<String> FILTERED_SINGLE_OPTIONS = new HashSet<String>(Arrays.<String>asList(
|
||||
"-verbose", "-proc:none", "-implicit:class", "-implicit:none"
|
||||
"-verbose", "-proc:only", "-implicit:class", "-implicit:none"
|
||||
));
|
||||
|
||||
public static boolean compile(Collection<String> options,
|
||||
@@ -71,12 +71,12 @@ public class JavacMain {
|
||||
out, fileManager, outConsumer, _options, null, fileManager.toJavaFileObjects(sources)
|
||||
);
|
||||
|
||||
if (!IS_VM_6_VERSION) {
|
||||
// Do not add the processor for JDK 1.6 because of the bugs in javac
|
||||
// The processor's presence may lead to NPE and resolve bugs in compiler
|
||||
final JavacASTAnalyser analyzer = new JavacASTAnalyser(outConsumer, shouldSuppressAnnotationProcessing(options));
|
||||
task.setProcessors(Collections.singleton(analyzer));
|
||||
}
|
||||
//if (!IS_VM_6_VERSION) { //todo!
|
||||
// // Do not add the processor for JDK 1.6 because of the bugs in javac
|
||||
// // The processor's presence may lead to NPE and resolve bugs in compiler
|
||||
// final JavacASTAnalyser analyzer = new JavacASTAnalyser(outConsumer, !annotationProcessingEnabled);
|
||||
// task.setProcessors(Collections.singleton(analyzer));
|
||||
//}
|
||||
return task.call();
|
||||
}
|
||||
catch(IllegalArgumentException e) {
|
||||
@@ -88,13 +88,13 @@ public class JavacMain {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean shouldSuppressAnnotationProcessing(final Collection<String> options) {
|
||||
private static boolean isAnnotationProcessingEnabled(final Collection<String> options) {
|
||||
for (String option : options) {
|
||||
if ("-proc:none".equals(option)) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Collection<String> prepareOptions(final Collection<String> options) {
|
||||
|
||||
@@ -25,6 +25,7 @@ public final class OutputFileObject extends SimpleJavaFileObject {
|
||||
@Nullable private final URI mySourceUri;
|
||||
private volatile Content myContent;
|
||||
private final File mySourceFile;
|
||||
public boolean myIsTemp = false;
|
||||
|
||||
public OutputFileObject(@NotNull JavacFileManager.Context context, @Nullable File outputRoot, String relativePath, @NotNull File file, @NotNull Kind kind, @Nullable String className, @Nullable final URI sourceUri) {
|
||||
this(context, outputRoot, relativePath, file, kind, className, sourceUri, null);
|
||||
@@ -42,6 +43,14 @@ public final class OutputFileObject extends SimpleJavaFileObject {
|
||||
mySourceFile = srcUri != null? Utils.convertToFile(srcUri) : null;
|
||||
}
|
||||
|
||||
public boolean isTemp() {
|
||||
return myIsTemp;
|
||||
}
|
||||
|
||||
public void setTemp(boolean isTemp) {
|
||||
myIsTemp = isTemp;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public File getOutputRoot() {
|
||||
return myOutputRoot;
|
||||
|
||||
@@ -846,7 +846,7 @@ public class Mappings {
|
||||
}
|
||||
|
||||
private class Differential {
|
||||
static final int DESPERATE_MASK = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
|
||||
final int DESPERATE_MASK = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
|
||||
|
||||
final Mappings myDelta;
|
||||
final Collection<String> myRemoved;
|
||||
@@ -994,7 +994,7 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
|
||||
private void processAddedMethods (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
private void processAddedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
debug("Processing added methods: ");
|
||||
for (final MethodRepr m : diff.methods().added()) {
|
||||
debug("Method: ", m.name);
|
||||
@@ -1120,7 +1120,7 @@ public class Mappings {
|
||||
debug("End of added methods processing");
|
||||
}
|
||||
|
||||
private void processRemovedMethods (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
private void processRemovedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
debug("Processing removed methods:");
|
||||
for (final MethodRepr m : diff.methods().removed()) {
|
||||
debug("Method ", m.name);
|
||||
@@ -1216,7 +1216,7 @@ public class Mappings {
|
||||
debug("End of removed methods processing");
|
||||
}
|
||||
|
||||
private void processChangedMethods (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
private void processChangedMethods(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
debug("Processing changed methods:");
|
||||
for (final Pair<MethodRepr, Difference> mr : diff.methods().changed()) {
|
||||
final MethodRepr m = mr.first;
|
||||
@@ -1305,7 +1305,7 @@ public class Mappings {
|
||||
debug("End of changed methods processing");
|
||||
}
|
||||
|
||||
private boolean processAddedFields (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
private boolean processAddedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
debug("Processing added fields");
|
||||
|
||||
for (final FieldRepr f : diff.fields().added()) {
|
||||
@@ -1407,7 +1407,7 @@ public class Mappings {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean processRemovedFields (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
private boolean processRemovedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
debug("Processing removed fields:");
|
||||
|
||||
for (final FieldRepr f : diff.fields().removed()) {
|
||||
@@ -1434,7 +1434,7 @@ public class Mappings {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean processChangedFields (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
private boolean processChangedFields(final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
|
||||
debug("Processing changed fields:");
|
||||
|
||||
for (final Pair<FieldRepr, Difference> f : diff.fields().changed()) {
|
||||
@@ -1623,19 +1623,19 @@ public class Mappings {
|
||||
debug("End of annotation-specific analysis");
|
||||
}
|
||||
|
||||
processAddedMethods (state, diff, it);
|
||||
processRemovedMethods (state, diff, it);
|
||||
processChangedMethods (state, diff, it);
|
||||
processAddedMethods(state, diff, it);
|
||||
processRemovedMethods(state, diff, it);
|
||||
processChangedMethods(state, diff, it);
|
||||
|
||||
if (!processAddedFields (state, diff, it)) {
|
||||
if (!processAddedFields(state, diff, it)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!processRemovedFields (state, diff, it)) {
|
||||
if (!processRemovedFields(state, diff, it)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!processChangedFields (state, diff, it)) {
|
||||
if (!processChangedFields(state, diff, it)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1880,6 +1880,16 @@ public class Mappings {
|
||||
}
|
||||
|
||||
if (delta.myIsDifferentiated) {
|
||||
final TIntHashSet compiledClasses = new TIntHashSet();
|
||||
|
||||
delta.myClassToSourceFile.forEachEntry(new TIntIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(final int a, final int b) {
|
||||
compiledClasses.add(a);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
for (ClassRepr repr : delta.getDeletedClasses()) {
|
||||
cleanupRemovedClass(repr, null, subclassesTrashBin, dependenciesTrashBin);
|
||||
}
|
||||
@@ -1895,13 +1905,31 @@ public class Mappings {
|
||||
|
||||
delta.getChangedClasses().forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int className) {
|
||||
final TIntHashSet subClasses = delta.myClassToSubclasses.get(className);
|
||||
if (subClasses != null) {
|
||||
myClassToSubclasses.replace(className, subClasses);
|
||||
public boolean execute(final int className) {
|
||||
TIntHashSet s = delta.myClassToSubclasses.get(className);
|
||||
|
||||
final TIntHashSet newSubClasses = s == null ? new TIntHashSet() : s;
|
||||
final TIntHashSet oldSubClasses = myClassToSubclasses.get(className);
|
||||
|
||||
if (oldSubClasses != null) {
|
||||
oldSubClasses.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(final int value) {
|
||||
if (!compiledClasses.contains(value)) {
|
||||
newSubClasses.add(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (newSubClasses.size() == 0) {
|
||||
myClassToSubclasses.remove(className);
|
||||
}
|
||||
else {
|
||||
myClassToSubclasses.remove(className);
|
||||
myClassToSubclasses.replace(className, newSubClasses);
|
||||
}
|
||||
|
||||
final int sourceFile = delta.myClassToSourceFile.get(className);
|
||||
|
||||
@@ -10,17 +10,21 @@ class CompilerConfiguration {
|
||||
Map<String, String> javacOptions = [:]
|
||||
boolean clearOutputDirectoryOnRebuild = true
|
||||
boolean addNotNullAssertions = true
|
||||
AnnotationProcessingConfiguration annotationProcessing = new AnnotationProcessingConfiguration()
|
||||
AnnotationProcessingProfile defaultAnnotationProcessingProfile = new AnnotationProcessingProfile()
|
||||
Collection<AnnotationProcessingProfile> moduleAnnotationProcessingProfiles = []
|
||||
BytecodeTargetConfiguration bytecodeTarget = new BytecodeTargetConfiguration()
|
||||
CompilerExcludes excludes = new CompilerExcludes()
|
||||
}
|
||||
|
||||
class AnnotationProcessingConfiguration {
|
||||
class AnnotationProcessingProfile {
|
||||
String name = ""
|
||||
boolean enabled = false
|
||||
boolean obtainProcessorsFromClasspath = true
|
||||
String processorsPath
|
||||
List<String> processors = []
|
||||
Map<String, String> processorsOptions = [:]
|
||||
Map<String, String> processModule = [:]
|
||||
String generatedSourcesDirName = ""
|
||||
List<String> processModule = []
|
||||
}
|
||||
|
||||
class BytecodeTargetConfiguration {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jps;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -12,6 +13,7 @@ import java.util.*;
|
||||
* Date: 9/30/11
|
||||
*/
|
||||
public class ProjectPaths {
|
||||
private static final String DEFAULT_GENERATED_DIR_NAME = "generated";
|
||||
@NotNull
|
||||
private final Project myProject;
|
||||
@Nullable
|
||||
@@ -236,6 +238,36 @@ public class ProjectPaths {
|
||||
return path != null ? new File(path) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public File getAnnotationProcessorGeneratedSourcesOutputDir(Module module, final boolean forTests, String sourceDirName) {
|
||||
if (!StringUtil.isEmpty(sourceDirName)) {
|
||||
List<String> roots = module.getContentRoots();
|
||||
if (roots.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (roots.size() > 1) {
|
||||
roots = new ArrayList<String>(roots); // sort roots to get deterministic result
|
||||
Collections.sort(roots, new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
});
|
||||
}
|
||||
return new File(roots.get(0), sourceDirName);
|
||||
}
|
||||
|
||||
final File outputDir = getModuleOutputDir(module, forTests);
|
||||
if (outputDir == null) {
|
||||
return null;
|
||||
}
|
||||
final File parentFile = outputDir.getParentFile();
|
||||
if (parentFile == null) {
|
||||
return null;
|
||||
}
|
||||
return new File(parentFile, outputDir.getName() + "_" + DEFAULT_GENERATED_DIR_NAME);
|
||||
}
|
||||
|
||||
public List<String> getProjectRuntimeClasspath(boolean includeTests) {
|
||||
Set<File> classpath = new LinkedHashSet<File>();
|
||||
final ClasspathKind kind = ClasspathKind.runtime(includeTests);
|
||||
|
||||
@@ -251,18 +251,36 @@ public class IdeaProjectLoader {
|
||||
|
||||
def annotationProcessingTag = componentTag?.annotationProcessing
|
||||
if (annotationProcessingTag != null) {
|
||||
configuration.annotationProcessing.enabled = parseBoolean(annotationProcessingTag."@enabled", false)
|
||||
configuration.annotationProcessing.obtainProcessorsFromClasspath = parseBoolean(annotationProcessingTag."@useClasspath", true)
|
||||
List<String> processorPaths = []
|
||||
annotationProcessingTag.processorPath?.each {
|
||||
processorPaths << projectMacroExpander.expandMacros(it."@value")
|
||||
}
|
||||
configuration.annotationProcessing.processorsPath = processorPaths.join(File.pathSeparator)
|
||||
annotationProcessingTag.processor?.each {
|
||||
configuration.annotationProcessing.processorsOptions[it."@name"] = it."@options" ?: ""
|
||||
}
|
||||
annotationProcessingTag.processModule?.each {
|
||||
configuration.annotationProcessing.processModule[it."@name"] = it."@generatedDirName"
|
||||
configuration.moduleAnnotationProcessingProfiles = []
|
||||
annotationProcessingTag?.profile?.each {profileTag ->
|
||||
AnnotationProcessingProfile profile
|
||||
if (parseBoolean(profileTag."@default", false)) {
|
||||
profile = configuration.defaultAnnotationProcessingProfile
|
||||
}
|
||||
else {
|
||||
profile = new AnnotationProcessingProfile()
|
||||
configuration.moduleAnnotationProcessingProfiles << profile
|
||||
}
|
||||
profile.name = profileTag."@name";
|
||||
profile.enabled = parseBoolean(profileTag."@enabled", false)
|
||||
profile.generatedSourcesDirName = profileTag.sourceOutputDir?.getAt(0)?."@name"
|
||||
profileTag.processor?.each {
|
||||
profile.processors << it."@name"
|
||||
}
|
||||
profileTag.option?.each {
|
||||
profile.processorsOptions[it."@name"] = it."@value" ?: ""
|
||||
}
|
||||
def pathTag = profileTag.processorPath?.getAt(0)
|
||||
profile.obtainProcessorsFromClasspath = parseBoolean(pathTag?."@useClasspath", true)
|
||||
List<String> processorPaths = []
|
||||
pathTag?.each {
|
||||
processorPaths << projectMacroExpander.expandMacros(it."@name")
|
||||
}
|
||||
profile.processorsPath = processorPaths.join(File.pathSeparator)
|
||||
|
||||
profileTag.module?.each {
|
||||
profile.processModule << it."@name"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,16 @@
|
||||
<entry name="?*.tld" />
|
||||
<entry name="?*.ftl" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing enabled="true" useClasspath="false">
|
||||
<processorPath value="$PROJECT_DIR$/src" />
|
||||
<processor name="my.proc" options="a=b c=d" />
|
||||
<processModule name="compilerConfiguration" generatedDirName="gen" />
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="true">
|
||||
<sourceOutputDir name="gen" />
|
||||
<option name="a" value="b" />
|
||||
<option name="c" value="d" />
|
||||
<processor name="my.proc" />
|
||||
<processorPath useClasspath="false">
|
||||
<entry name="$PROJECT_DIR$/src" />
|
||||
</processorPath>
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||
|
||||
+10
-4
@@ -20,10 +20,16 @@
|
||||
<entry name="?*.tld" />
|
||||
<entry name="?*.ftl" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing enabled="true" useClasspath="false">
|
||||
<processorPath value="$PROJECT_DIR$/src" />
|
||||
<processor name="my.proc" options="a=b c=d" />
|
||||
<processModule name="compilerConfiguration" generatedDirName="gen" />
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="true">
|
||||
<sourceOutputDir name="gen" />
|
||||
<option name="a" value="b" />
|
||||
<option name="c" value="d" />
|
||||
<processor name="my.proc" />
|
||||
<processorPath useClasspath="false">
|
||||
<entry name="$PROJECT_DIR$/src" />
|
||||
</processorPath>
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
@@ -33,11 +33,12 @@ class CompilerConfigurationTest extends JpsBuildTestCase {
|
||||
String basePath = project.modules["compilerConfiguration"].basePath
|
||||
assertFalse(configuration.clearOutputDirectoryOnRebuild)
|
||||
assertFalse(configuration.addNotNullAssertions)
|
||||
assertTrue(configuration.annotationProcessing.enabled)
|
||||
assertFalse(configuration.annotationProcessing.obtainProcessorsFromClasspath)
|
||||
assertEquals("$basePath/src", configuration.annotationProcessing.processorsPath)
|
||||
assertEquals("a=b c=d", configuration.annotationProcessing.processorsOptions["my.proc"])
|
||||
assertEquals("gen", configuration.annotationProcessing.processModule["compilerConfiguration"])
|
||||
assertTrue(configuration.defaultAnnotationProcessingProfile.enabled)
|
||||
assertFalse(configuration.defaultAnnotationProcessingProfile.obtainProcessorsFromClasspath)
|
||||
assertEquals("$basePath/src", configuration.defaultAnnotationProcessingProfile.processorsPath)
|
||||
assertEquals("b", configuration.defaultAnnotationProcessingProfile.processorsOptions["a"])
|
||||
assertEquals("d", configuration.defaultAnnotationProcessingProfile.processorsOptions["c"])
|
||||
assertEquals("gen", configuration.defaultAnnotationProcessingProfile.generatedSourcesDirName)
|
||||
assertFalse(configuration.excludes.isExcluded(new File("$basePath/src/nonrec/x/Y.java")))
|
||||
assertTrue(configuration.excludes.isExcluded(new File("$basePath/src/nonrec/Y.java")))
|
||||
assertTrue(configuration.excludes.isExcluded(new File("$basePath/src/rec/x/Y.java")))
|
||||
|
||||
@@ -204,6 +204,17 @@ public class VfsUtilCore {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String loadText(@NotNull VirtualFile file, int length) throws IOException{
|
||||
InputStreamReader reader = new InputStreamReader(file.getInputStream(), file.getCharset());
|
||||
try {
|
||||
return new String(FileUtil.loadText(reader, length));
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static VirtualFile[] toVirtualFileArray(@NotNull Collection<? extends VirtualFile> files) {
|
||||
int size = files.size();
|
||||
|
||||
+21
-2
@@ -23,6 +23,8 @@ import com.intellij.openapi.command.undo.DocumentReferenceManager;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -31,7 +33,7 @@ import java.io.OutputStream;
|
||||
* @author traff
|
||||
*/
|
||||
public class ConsoleExecuteActionHandler {
|
||||
private final ProcessHandler myProcessHandler;
|
||||
private ProcessHandler myProcessHandler;
|
||||
private final boolean myPreserveMarkup;
|
||||
private boolean myAddCurrentToHistory = true;
|
||||
private ConsoleHistoryModel myConsoleHistoryModel;
|
||||
@@ -42,6 +44,15 @@ public class ConsoleExecuteActionHandler {
|
||||
myPreserveMarkup = preserveMarkup;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private synchronized ProcessHandler getProcessHandler() {
|
||||
return myProcessHandler;
|
||||
}
|
||||
|
||||
public synchronized void setProcessHandler(@NotNull final ProcessHandler processHandler) {
|
||||
myProcessHandler = processHandler;
|
||||
}
|
||||
|
||||
public void setConsoleHistoryModel(ConsoleHistoryModel consoleHistoryModel) {
|
||||
myConsoleHistoryModel = consoleHistoryModel;
|
||||
}
|
||||
@@ -81,7 +92,10 @@ public class ConsoleExecuteActionHandler {
|
||||
|
||||
public void sendText(String line) {
|
||||
//final Charset charset = myProcessHandler.getCharset();
|
||||
final OutputStream outputStream = myProcessHandler.getProcessInput();
|
||||
final ProcessHandler handler = getProcessHandler();
|
||||
assert handler != null : "process handler is null";
|
||||
final OutputStream outputStream = handler.getProcessInput();
|
||||
assert outputStream != null : "output stream is null";
|
||||
try {
|
||||
//byte[] bytes = (line + "\n").getBytes(charset.name());
|
||||
byte[] bytes = line.getBytes();
|
||||
@@ -100,6 +114,11 @@ public class ConsoleExecuteActionHandler {
|
||||
public void finishExecution() {
|
||||
}
|
||||
|
||||
public final boolean isProcessTerminated() {
|
||||
final ProcessHandler handler = getProcessHandler();
|
||||
return handler == null || handler.isProcessTerminated();
|
||||
}
|
||||
|
||||
public String getEmptyExecuteAction() {
|
||||
return "Console.Execute";
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class ContextHelpAction extends AnAction implements DumbAware {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public ContextHelpAction(@NonNls String helpID) {
|
||||
public ContextHelpAction(@NonNls @Nullable String helpID) {
|
||||
myHelpID = helpID;
|
||||
}
|
||||
|
||||
|
||||
+12
-2
@@ -63,8 +63,18 @@ public class MultiLevelDiffTool implements DiffTool, DiscloseMultiRequest {
|
||||
Disposer.dispose(builder);
|
||||
return;
|
||||
}
|
||||
// todo ?
|
||||
builder.removeAllActions();
|
||||
final Runnable onOkRunnable = request.getOnOkRunnable();
|
||||
if (onOkRunnable != null){
|
||||
builder.setOkOperation(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
builder.getDialogWrapper().close(0);
|
||||
onOkRunnable.run();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
builder.removeAllActions();
|
||||
}
|
||||
builder.setCenterPanel(diffPanel.getComponent());
|
||||
builder.setPreferedFocusComponent(diffPanel.getPreferredFocusedComponent());
|
||||
builder.setTitle(request.getWindowTitle());
|
||||
|
||||
@@ -8,7 +8,7 @@ java.terms.parameter=parameter
|
||||
java.terms.variable=variable
|
||||
java.terms.interface=interface
|
||||
java.terms.exception=exception
|
||||
java.terms.static.initializer=static intializer
|
||||
java.terms.static.initializer=static initializer
|
||||
java.terms.instance.initializer=instance initializer
|
||||
java.terms.enum=enum
|
||||
java.terms.annotation.interface=@interface
|
||||
|
||||
+1
-1
@@ -238,7 +238,7 @@ public class ChangesFragmentedDiffPanel implements Disposable {
|
||||
final DialogWrapper wrapper = ((DialogWrapperDialog)window).getDialogWrapper();
|
||||
if (wrapper != null) {
|
||||
Disposer.dispose(wrapper.getDisposable());
|
||||
wrapper.close(0);
|
||||
wrapper.close(DialogWrapper.CANCEL_EXIT_CODE);
|
||||
ApplicationManager.getApplication().invokeLater(runnable, ModalityState.NON_MODAL, myProject.getDisposed());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ public class ApplyPatchAction extends DumbAwareAction {
|
||||
simpleRequest.setContents(new SimpleContent(texts.getLocal().toString(), file.getFileType()),
|
||||
mergedDocument);
|
||||
simpleRequest.setContentTitles(VcsBundle.message("diff.title.local"), "Patched (with problems)");
|
||||
simpleRequest.addHint(DiffTool.HINT_SHOW_NOT_MODAL_DIALOG);
|
||||
simpleRequest.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG);
|
||||
simpleRequest.addHint(DiffTool.HINT_DIFF_IS_APPROXIMATE);
|
||||
|
||||
if (! readonly) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<compiler implementation="org.jetbrains.android.compiler.AndroidExternalApklibExtractingCompiler" order="first"/>
|
||||
<compiler implementation="org.jetbrains.android.compiler.AndroidMavenResourcesCompiler"/>
|
||||
<compiler implementation="org.jetbrains.android.compiler.AndroidMavenResourcesCompiler" order="first"/>
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="org.jetbrains">
|
||||
<android.mavenProvider implementation="org.jetbrains.android.maven.AndroidMavenProviderImpl"/>
|
||||
|
||||
+36
-8
@@ -7,13 +7,13 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.android.dom.manifest.Manifest;
|
||||
import com.intellij.util.xml.NanoXmlUtil;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.facet.AndroidRootUtil;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -55,13 +55,16 @@ public class AndroidBuildConfigGeneratingCompiler implements SourceGeneratingCom
|
||||
continue;
|
||||
}
|
||||
|
||||
final Manifest manifest = AndroidUtils.loadDomElement(module, manifestFile, Manifest.class);
|
||||
if (manifest == null) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, "Cannot parse file", manifestFile.getUrl(), -1, -1);
|
||||
String packageName;
|
||||
try {
|
||||
// we cannot use DOM here because custom manifest file can be excluded (ex. it can be located in /target/ folder)
|
||||
packageName = parsePackageName(manifestFile);
|
||||
}
|
||||
catch (IOException e) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, "I/O error: " + e.getMessage(), null, -1, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
String packageName = manifest.getPackage().getValue();
|
||||
if (packageName != null) {
|
||||
packageName = packageName.trim();
|
||||
}
|
||||
@@ -113,6 +116,31 @@ public class AndroidBuildConfigGeneratingCompiler implements SourceGeneratingCom
|
||||
return result.toArray(new GenerationItem[result.size()]);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String parsePackageName(@NotNull VirtualFile manifestFile) throws IOException {
|
||||
final Ref<String> packageNameRef = Ref.create(null);
|
||||
|
||||
NanoXmlUtil.parse(manifestFile.getInputStream(), new NanoXmlUtil.BaseXmlBuilder() {
|
||||
@Override
|
||||
public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type)
|
||||
throws Exception {
|
||||
super.addAttribute(key, nsPrefix, nsURI, value, type);
|
||||
|
||||
if ("package".equals(key) && NanoXmlUtil.createLocation("manifest").equals(getLocation())) {
|
||||
packageNameRef.set(value);
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void elementAttributesProcessed(String name, String nsPrefix, String nsURI) throws Exception {
|
||||
super.elementAttributesProcessed(name, nsPrefix, nsURI);
|
||||
stop();
|
||||
}
|
||||
});
|
||||
return packageNameRef.get();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
@@ -129,7 +157,7 @@ public class AndroidBuildConfigGeneratingCompiler implements SourceGeneratingCom
|
||||
return new MyValidityState(in);
|
||||
}
|
||||
|
||||
private static class MyGenerationItem implements GenerationItem{
|
||||
private static class MyGenerationItem implements GenerationItem {
|
||||
final Module myModule;
|
||||
final String myPackage;
|
||||
final boolean myDebug;
|
||||
@@ -190,4 +218,4 @@ public class AndroidBuildConfigGeneratingCompiler implements SourceGeneratingCom
|
||||
out.writeBoolean(myDebug);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@ public class AndroidRootUtil {
|
||||
return getFileByRelativeModulePath(facet.getModule(), facet.getConfiguration().CUSTOM_COMPILER_MANIFEST, false);
|
||||
}
|
||||
|
||||
// DO NOT get PSI or DOM from this file, because it may be excluded (f.ex. it can be in /target/ directory)
|
||||
@Nullable
|
||||
public static VirtualFile getManifestFileForCompiler(@NotNull AndroidFacet facet) {
|
||||
return facet.getConfiguration().USE_CUSTOM_COMPILER_MANIFEST
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.jetbrains.idea.devkit.dom.impl;
|
||||
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.util.xml.DomFileDescription;
|
||||
import org.jetbrains.idea.devkit.dom.IdeaPlugin;
|
||||
|
||||
@@ -33,7 +34,7 @@ public class PluginXmlDomFileDescription extends DomFileDescription<IdeaPlugin>
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getFileIcon(int flags) {
|
||||
public Icon getFileIcon(@Iconable.IconFlags int flags) {
|
||||
return ICON;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.jetbrains.groovy.compiler.rt.GroovyCompilerWrapper;
|
||||
import org.jetbrains.jps.*;
|
||||
import org.jetbrains.jps.incremental.*;
|
||||
import org.jetbrains.jps.incremental.fs.RootDescriptor;
|
||||
import org.jetbrains.jps.incremental.java.JavaBuilder;
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||
import org.jetbrains.jps.incremental.messages.FileGeneratedEvent;
|
||||
import org.jetbrains.jps.incremental.messages.ProgressMessage;
|
||||
@@ -100,8 +99,7 @@ public class GroovyBuilder extends ModuleLevelBuilder {
|
||||
if (myForStubs) {
|
||||
for (Module module : generationOutputs.keySet()) {
|
||||
File root = new File(generationOutputs.get(module));
|
||||
context.getRootsIndex().associateRoot(root, module, context.isCompilingTests(), true);
|
||||
JavaBuilder.addTempSourcePathRoot(context, root);
|
||||
context.getRootsIndex().associateRoot(root, module, context.isCompilingTests(), true, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +60,10 @@ import org.jetbrains.plugins.groovy.GroovyBundle;
|
||||
import org.jetbrains.plugins.groovy.annotator.intentions.*;
|
||||
import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicMethodFix;
|
||||
import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicPropertyFix;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection;
|
||||
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
|
||||
import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment;
|
||||
import org.jetbrains.plugins.groovy.dsl.toplevel.AnnotatedContextFilter;
|
||||
import org.jetbrains.plugins.groovy.extensions.GroovyUnresolvedHighlightFilter;
|
||||
import org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter;
|
||||
import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil;
|
||||
@@ -101,12 +103,14 @@ import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatem
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
@@ -128,6 +132,9 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
|
||||
if (element instanceof GroovyPsiElement) {
|
||||
myHolder = holder;
|
||||
((GroovyPsiElement)element).accept(this);
|
||||
if (isCompileStatic(element)) {
|
||||
GroovyAssignabilityCheckInspection.checkElement((GroovyPsiElement)element, holder);
|
||||
}
|
||||
myHolder = null;
|
||||
}
|
||||
else {
|
||||
@@ -324,6 +331,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
|
||||
|
||||
PsiElement resolved = resolveResult.getElement();
|
||||
final PsiElement parent = referenceExpression.getParent();
|
||||
|
||||
if (resolved != null) {
|
||||
if (resolved instanceof PsiMember) {
|
||||
highlightMemberResolved(myHolder, referenceExpression, ((PsiMember)resolved));
|
||||
@@ -337,7 +345,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
|
||||
Annotation annotation = myHolder.createInfoAnnotation(referenceExpression,
|
||||
GroovyBundle.message("cannot.reference.nonstatic",
|
||||
referenceExpression.getReferenceName()));
|
||||
annotation.setTextAttributes(DefaultHighlighter.UNRESOLVED_ACCESS);
|
||||
annotation.setTextAttributes(isStaticallyCompiled(referenceExpression)?DefaultHighlighter.BAD_CHARACTER:DefaultHighlighter.UNRESOLVED_ACCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -377,8 +385,22 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
|
||||
PsiElement refNameElement = referenceExpression.getReferenceNameElement();
|
||||
PsiElement elt = refNameElement == null ? referenceExpression : refNameElement;
|
||||
|
||||
Annotation annotation = myHolder.createInfoAnnotation(elt, null);
|
||||
final GrExpression qualifier = referenceExpression.getQualifierExpression();
|
||||
|
||||
Annotation annotation;
|
||||
|
||||
boolean compileStatic = isCompileStatic(referenceExpression);
|
||||
if (compileStatic) {
|
||||
annotation = myHolder.createInfoAnnotation(elt, GroovyBundle.message("cannot.resolve", referenceExpression.getReferenceName()));
|
||||
annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
|
||||
}
|
||||
else {
|
||||
if (qualifier != null && qualifier.getType() == null) return;
|
||||
|
||||
annotation = myHolder.createInfoAnnotation(elt, null);
|
||||
annotation.setTextAttributes(DefaultHighlighter.UNRESOLVED_ACCESS);
|
||||
}
|
||||
|
||||
if (qualifier == null) {
|
||||
if (parent instanceof GrMethodCall) {
|
||||
registerStaticImportFix(referenceExpression, annotation);
|
||||
@@ -388,20 +410,22 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
|
||||
registerAddImportFixes(referenceExpression, annotation);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (qualifier.getType() == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
registerReferenceFixes(referenceExpression, annotation);
|
||||
registerReferenceFixes(referenceExpression, annotation, compileStatic);
|
||||
UnresolvedReferenceQuickFixProvider.registerReferenceFixes(referenceExpression, new QuickFixActionRegistrarAdapter(annotation));
|
||||
OrderEntryFix.registerFixes(new QuickFixActionRegistrarAdapter(annotation), referenceExpression);
|
||||
|
||||
annotation.setTextAttributes(DefaultHighlighter.UNRESOLVED_ACCESS);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isCompileStatic(PsiElement e) {
|
||||
PsiMember containingMember = PsiTreeUtil.getParentOfType(e, PsiMember.class);
|
||||
return containingMember != null && GroovyPsiManager.getInstance(containingMember.getProject()).isCompileStatic(containingMember);
|
||||
}
|
||||
|
||||
private static boolean isStaticallyCompiled(GrReferenceExpression referenceExpression) {
|
||||
return AnnotatedContextFilter.findContextAnnotation(referenceExpression, GroovyCommonClassNames.GROOVY_TRANSFORM_COMPILE_STATIC)!=null;
|
||||
}
|
||||
|
||||
private void highlightVariable(GrVariable variable, PsiElement toHighlight) {
|
||||
Annotation annotation = myHolder.createInfoAnnotation(toHighlight, null);
|
||||
boolean reassigned = isReassigned(variable);
|
||||
@@ -1772,11 +1796,13 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
|
||||
}
|
||||
|
||||
|
||||
private static void registerReferenceFixes(GrReferenceExpression refExpr, Annotation annotation) {
|
||||
PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr);
|
||||
private static void registerReferenceFixes(GrReferenceExpression refExpr, Annotation annotation, boolean compileStatic) {
|
||||
PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr, compileStatic);
|
||||
if (targetClass == null) return;
|
||||
|
||||
addDynamicAnnotation(annotation, refExpr);
|
||||
if (!compileStatic) {
|
||||
addDynamicAnnotation(annotation, refExpr);
|
||||
}
|
||||
if (targetClass.isWritable()) {
|
||||
if (!(targetClass instanceof GroovyScriptClass)) {
|
||||
if (targetClass instanceof GrMemberOwner) {
|
||||
|
||||
+9
-19
@@ -26,7 +26,6 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import gnu.trove.THashSet;
|
||||
@@ -34,13 +33,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ParamInfo;
|
||||
import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ui.DynamicElementSettings;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceResolveUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
@@ -53,22 +52,13 @@ import java.util.*;
|
||||
*/
|
||||
public class QuickfixUtil {
|
||||
@Nullable
|
||||
public static PsiClass findTargetClass(GrReferenceExpression refExpr) {
|
||||
final PsiClass psiClass;
|
||||
if (refExpr.isQualified()) {
|
||||
GrExpression qualifier = refExpr.getQualifierExpression();
|
||||
PsiType type = qualifier.getType();
|
||||
if (!(type instanceof PsiClassType)) return null;
|
||||
|
||||
psiClass = ((PsiClassType)type).resolve();
|
||||
} else {
|
||||
GroovyPsiElement context = PsiTreeUtil.getParentOfType(refExpr, GrTypeDefinition.class, GroovyFileBase.class);
|
||||
if (context instanceof GrTypeDefinition) {
|
||||
return (PsiClass)context;
|
||||
} else if (context instanceof GroovyFileBase) return ((GroovyFileBase)context).getScriptClass();
|
||||
return null;
|
||||
public static PsiClass findTargetClass(GrReferenceExpression refExpr, boolean compileStatic) {
|
||||
PsiType type = GrReferenceResolveUtil.getQualifierType(refExpr);
|
||||
if (type == null && compileStatic) {
|
||||
return GroovyPsiManager.getInstance(refExpr.getProject()).findClassWithCache(CommonClassNames.JAVA_LANG_OBJECT, refExpr.getResolveScope());
|
||||
}
|
||||
return psiClass;
|
||||
if (!(type instanceof PsiClassType)) return null;
|
||||
return ((PsiClassType)type).resolve();
|
||||
}
|
||||
|
||||
public static boolean isStaticCall(GrReferenceExpression refExpr) {
|
||||
@@ -184,7 +174,7 @@ public class QuickfixUtil {
|
||||
|
||||
public static DynamicElementSettings createSettings(GrReferenceExpression referenceExpression) {
|
||||
DynamicElementSettings settings = new DynamicElementSettings();
|
||||
final PsiClass containingClass = findTargetClass(referenceExpression);
|
||||
final PsiClass containingClass = findTargetClass(referenceExpression, false);
|
||||
|
||||
assert containingClass != null;
|
||||
String className = containingClass.getQualifiedName();
|
||||
|
||||
+96
-6
@@ -16,14 +16,22 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.codeInspection.assignment;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.lang.annotation.Annotation;
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -31,7 +39,6 @@ import org.jetbrains.plugins.groovy.GroovyBundle;
|
||||
import org.jetbrains.plugins.groovy.annotator.GroovyAnnotator;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovyFix;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
|
||||
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
|
||||
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
|
||||
@@ -45,6 +52,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
|
||||
@@ -56,10 +64,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceResolveUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
@@ -80,11 +90,6 @@ import java.util.Map;
|
||||
public class GroovyAssignabilityCheckInspection extends BaseInspection {
|
||||
private static final Logger LOG = Logger.getInstance(GroovyAssignabilityCheckInspection.class);
|
||||
|
||||
@Override
|
||||
protected GroovyFix buildFix(PsiElement location) {
|
||||
return super.buildFix(location); //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -159,6 +164,8 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
|
||||
|
||||
@Override
|
||||
public void visitMethod(GrMethod method) {
|
||||
if (GroovyPsiManager.getInstance(method.getProject()).isCompileStatic(method)) return;
|
||||
|
||||
super.visitMethod(method);
|
||||
final GrOpenBlock block = method.getBlock();
|
||||
if (block == null) return;
|
||||
@@ -178,6 +185,18 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitField(GrField field) {
|
||||
if (GroovyPsiManager.getInstance(field.getProject()).isCompileStatic(field)) return;
|
||||
super.visitField(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeDefinition(GrTypeDefinition typeDefinition) {
|
||||
if (GroovyPsiManager.getInstance(typeDefinition.getProject()).isCompileStatic(typeDefinition)) return;
|
||||
super.visitTypeDefinition(typeDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReturnStatement(GrReturnStatement returnStatement) {
|
||||
super.visitReturnStatement(returnStatement);
|
||||
@@ -761,4 +780,75 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
|
||||
}
|
||||
return GrReferenceResolveUtil.getQualifierType(place);
|
||||
}
|
||||
|
||||
|
||||
private static class AnnotatingVisitor extends MyVisitor {
|
||||
private AnnotationHolder myHolder;
|
||||
|
||||
|
||||
@Override
|
||||
protected void registerError(@NotNull final PsiElement location,
|
||||
final String description,
|
||||
final LocalQuickFix[] fixes,
|
||||
final ProblemHighlightType highlightType) {
|
||||
Annotation annotation = myHolder.createErrorAnnotation(location, description);
|
||||
for (final LocalQuickFix fix : fixes) {
|
||||
annotation.registerFix(new IntentionAction() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return fix.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return fix.getFamilyName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
InspectionManager manager = InspectionManager.getInstance(project);
|
||||
ProblemDescriptor descriptor = manager.createProblemDescriptor(location, description, fixes, highlightType, fixes.length == 1, false);
|
||||
fix.applyFix(project, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitElement(GroovyPsiElement element) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
|
||||
private static final ThreadLocal<AnnotatingVisitor> visitor = new ThreadLocal<AnnotatingVisitor>() {
|
||||
@Override
|
||||
protected AnnotatingVisitor initialValue() {
|
||||
return new AnnotatingVisitor();
|
||||
}
|
||||
};
|
||||
|
||||
public static void checkElement(GroovyPsiElement e, AnnotationHolder holder) {
|
||||
AnnotatingVisitor annotatingVisitor = visitor.get();
|
||||
|
||||
AnnotationHolder oldHolder = annotatingVisitor.myHolder;
|
||||
try {
|
||||
annotatingVisitor.myHolder = holder;
|
||||
e.accept(annotatingVisitor);
|
||||
}
|
||||
finally {
|
||||
annotatingVisitor.myHolder = oldHolder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,15 +77,9 @@ public class GroovyBraceEnforcer extends GroovyRecursiveElementVisitor {
|
||||
// if (true) i = 1; // Cool assignment
|
||||
// We can't just surround target block of code with curly braces because the closing one will be treated as comment as well.
|
||||
// Hence, we perform a check if we have such situation at the moment and insert new line before the closing brace.
|
||||
int lastLineFeedIndex = oldText.lastIndexOf("\n");
|
||||
lastLineFeedIndex = Math.max(0, lastLineFeedIndex);
|
||||
int lastLineCommentIndex = oldText.indexOf("//", lastLineFeedIndex);
|
||||
StringBuilder buf = new StringBuilder(oldText.length() + 5);
|
||||
buf.append("{ ").append(oldText);
|
||||
if (lastLineCommentIndex >= 0) {
|
||||
buf.append("\n");
|
||||
}
|
||||
buf.append(" }");
|
||||
buf.append("{\n").append(oldText);
|
||||
buf.append("\n}");
|
||||
final int oldTextLength = statement.getTextLength();
|
||||
try {
|
||||
CodeEditUtil.replaceChild(SourceTreeToPsiMap.psiElementToTree(statement),
|
||||
|
||||
@@ -65,6 +65,7 @@ public class GroovyPsiManager {
|
||||
|
||||
private final ConcurrentMap<GroovyPsiElement, PsiType> myCalculatedTypes = new ConcurrentWeakHashMap<GroovyPsiElement, PsiType>();
|
||||
private final ConcurrentMap<String, SoftReference<Map<GlobalSearchScope, PsiClass>>> myClassCache = new ConcurrentHashMap<String, SoftReference<Map<GlobalSearchScope, PsiClass>>>();
|
||||
private final ConcurrentMap<PsiMember, Boolean> myCompileStatic = new ConcurrentHashMap<PsiMember, Boolean>();
|
||||
|
||||
private static final RecursionGuard ourGuard = RecursionManager.createGuard("groovyPsiManager");
|
||||
|
||||
@@ -92,6 +93,7 @@ public class GroovyPsiManager {
|
||||
|
||||
public void dropTypesCache() {
|
||||
myCalculatedTypes.clear();
|
||||
myCompileStatic.clear();
|
||||
}
|
||||
|
||||
public static boolean isInheritorCached(@Nullable PsiClass aClass, @NotNull String baseClassName) {
|
||||
@@ -122,6 +124,25 @@ public class GroovyPsiManager {
|
||||
return JavaPsiFacade.getElementFactory(myProject).createTypeByFQClassName(fqName, resolveScope);
|
||||
}
|
||||
|
||||
public boolean isCompileStatic(PsiMember member) {
|
||||
Boolean aBoolean = myCompileStatic.get(member);
|
||||
if (aBoolean == null) {
|
||||
aBoolean = ConcurrencyUtil.cacheOrGet(myCompileStatic, member, isCompileStaticInner(member));
|
||||
}
|
||||
return aBoolean;
|
||||
}
|
||||
|
||||
private boolean isCompileStaticInner(PsiMember member) {
|
||||
PsiModifierList list = member.getModifierList();
|
||||
if (list != null) {
|
||||
PsiAnnotation annotation = list.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_COMPILE_STATIC);
|
||||
if (annotation != null) return true;
|
||||
}
|
||||
PsiClass aClass = member.getContainingClass();
|
||||
if (aClass != null) return isCompileStatic(aClass);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiClass findClassWithCache(String fqName, GlobalSearchScope resolveScope) {
|
||||
SoftReference<Map<GlobalSearchScope, PsiClass>> reference = myClassCache.get(fqName);
|
||||
|
||||
+2
-1
@@ -50,7 +50,8 @@ public final class GroovyCommonClassNames {
|
||||
@NonNls public static final String GROOVY_LANG_USE = "groovy.lang.Use";
|
||||
@NonNls public static final String GROOVY_LANG_MIXIN = "groovy.lang.Mixin";
|
||||
@NonNls public static final String GROOVY_UTIL_TEST_CASE = "groovy.util.GroovyTestCase";
|
||||
public static final String GROOVY_LANG_SINGLETON = "groovy.lang.Singleton";
|
||||
@NonNls public static final String GROOVY_LANG_SINGLETON = "groovy.lang.Singleton";
|
||||
@NonNls public static final String GROOVY_TRANSFORM_COMPILE_STATIC = "groovy.transform.CompileStatic";
|
||||
|
||||
|
||||
private GroovyCommonClassNames() {
|
||||
|
||||
@@ -640,7 +640,7 @@ public class Main {
|
||||
CompileServerManager.instance.shutdownServer()
|
||||
}
|
||||
|
||||
public void "_test make stub-level error and correct it"() {
|
||||
public void "test make stub-level error and correct it"() {
|
||||
def foo = myFixture.addFileToProject('Foo.groovy', 'class Foo { }')
|
||||
myFixture.addFileToProject('Bar.java', 'class Bar extends Foo {}')
|
||||
|
||||
|
||||
@@ -1009,4 +1009,53 @@ use(Ca) {
|
||||
''', GroovyAssignabilityCheckInspection)
|
||||
}
|
||||
|
||||
void testCompileStatic() {
|
||||
myFixture.addClass('''\
|
||||
package groovy.transform;
|
||||
public @interface CompileStatic {
|
||||
}''')
|
||||
|
||||
myFixture.configureByText('_.groovy', '''\
|
||||
<info descr="null">import</info> <info descr="null">groovy.transform.CompileStatic</info>
|
||||
|
||||
<info descr="null">class</info> <info descr="null">A</info> {
|
||||
|
||||
<info descr="null">def</info> <info descr="null">foo</info>() {
|
||||
<info descr="null">print</info> <info descr="null">abc</info>
|
||||
}
|
||||
|
||||
<info descr="null">@CompileStatic</info>
|
||||
<info descr="null">def</info> <info descr="null">bar</info>() {
|
||||
<info descr="null">print</info> <info descr="Cannot resolve symbol 'abc'">abc</info>
|
||||
}
|
||||
}
|
||||
''')
|
||||
myFixture.testHighlighting(true, true, true)
|
||||
}
|
||||
|
||||
|
||||
void testCompileStaticWithAssignabilityCheck() {
|
||||
myFixture.addClass('''\
|
||||
package groovy.transform;
|
||||
public @interface CompileStatic {
|
||||
}''')
|
||||
|
||||
myFixture.configureByText('_.groovy', '''\
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
class A {
|
||||
|
||||
def foo(String s) {
|
||||
int x = <warning descr="Cannot assign 'Date' to 'int'">new Date()</warning>
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
def bar() {
|
||||
int x = <error descr="Cannot assign 'Date' to 'int'">new Date()</error>
|
||||
}
|
||||
}
|
||||
''')
|
||||
myFixture.enableInspections(GroovyAssignabilityCheckInspection)
|
||||
myFixture.checkHighlighting(true, false, true)
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.jetbrains.idea.svn;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -50,7 +51,7 @@ public class SvnRecursiveStatusWalker {
|
||||
}
|
||||
|
||||
public void go(final FilePath rootPath, final SVNDepth depth) throws SVNException {
|
||||
final MyItem root = new MyItem(myProject, rootPath, depth, myPartner.createStatusClient(), true);
|
||||
final MyItem root = new MyItem(myProject, rootPath, depth, myPartner.createStatusClient(), false);
|
||||
myQueue.add(root);
|
||||
|
||||
while (! myQueue.isEmpty()) {
|
||||
@@ -177,7 +178,7 @@ public class SvnRecursiveStatusWalker {
|
||||
}
|
||||
|
||||
public void checkIfCopyRootWasReported() {
|
||||
if (! myMetCurrentItem && myCurrentItem.isIsInnerCopyRoot()) {
|
||||
if (! myMetCurrentItem) {
|
||||
myMetCurrentItem = true;
|
||||
final SVNStatus statusInner = SvnUtil.getStatus(SvnVcs.getInstance(myProject), myCurrentItem.getPath().getIOFile());
|
||||
if (statusInner == null) return;
|
||||
@@ -200,7 +201,7 @@ public class SvnRecursiveStatusWalker {
|
||||
if (SVNStatusType.OBSTRUCTED.equals(status) || SVNStatusType.STATUS_NONE.equals(status)) {
|
||||
return;
|
||||
}
|
||||
if (vf != null) {
|
||||
if (vf != null && myCurrentItem.isIsInnerCopyRoot()) {
|
||||
myReceiver.processCopyRoot(vf, statusInner.getURL(),
|
||||
WorkingCopyFormat.getInstance(statusInner.getWorkingCopyFormat()));
|
||||
}
|
||||
@@ -217,7 +218,7 @@ public class SvnRecursiveStatusWalker {
|
||||
|
||||
if ((vFile != null) && (SvnVcs.svnStatusIsUnversioned(status))) {
|
||||
if (vFile.isDirectory()) {
|
||||
if (myCurrentItem.getPath().getIOFile().equals(ioFile)) {
|
||||
if (FileUtil.filesEqual(myCurrentItem.getPath().getIOFile(), ioFile)) {
|
||||
myReceiver.processUnversioned(vFile);
|
||||
processRecursively(vFile, myCurrentItem.getDepth());
|
||||
} else {
|
||||
|
||||
+3
-2
@@ -18,6 +18,7 @@ package org.jetbrains.idea.svn.commandLine;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.portable.SvnExceptionWrapper;
|
||||
@@ -32,6 +33,7 @@ import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringBufferInputStream;
|
||||
@@ -106,9 +108,8 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient {
|
||||
|
||||
try {
|
||||
final String result = command.run();
|
||||
// todo not synchronized wrapper stream!
|
||||
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||
parser.parse(new StringBufferInputStream(result), infoHandler[0]);
|
||||
parser.parse(new ByteArrayInputStream(result.getBytes(CharsetToolkit.UTF8_CHARSET)), infoHandler[0]);
|
||||
|
||||
}
|
||||
catch (SvnExceptionWrapper e) {
|
||||
|
||||
+2
-2
@@ -18,6 +18,7 @@ package org.jetbrains.idea.svn.commandLine;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import org.jetbrains.idea.svn.SvnUtil;
|
||||
import org.jetbrains.idea.svn.portable.PortableStatus;
|
||||
@@ -156,9 +157,8 @@ public class SvnCommandLineStatusClient implements SvnStatusClientI {
|
||||
|
||||
try {
|
||||
final String result = command.run();
|
||||
// todo not synchronized wrapper stream!
|
||||
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||
parser.parse(new StringBufferInputStream(result), svnHandl[0]);
|
||||
parser.parse(new ByteArrayInputStream(result.getBytes(CharsetToolkit.UTF8_CHARSET)), svnHandl[0]);
|
||||
if (! svnHandl[0].isAnythingReported()) {
|
||||
if (! SvnUtil.isSvnVersioned(myProject, path)) {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY));
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.util.xml;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.psi.xml.XmlDocument;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
@@ -151,7 +152,7 @@ public class DomFileDescription<T> {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Icon getFileIcon(int flags) {
|
||||
public Icon getFileIcon(@Iconable.IconFlags int flags) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user