diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 29a081c309a7..71b39fa46d96 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -852,7 +852,7 @@ binding.setVariable("buildWinLauncher", { String ch, String inputPath, String ou launcherProperties = launcherPropertiesTemp } - ant.java(classname: "com.pme.launcher.LauncherGeneratorMain", fork: "true") { + ant.java(classname: "com.pme.launcher.LauncherGeneratorMain", fork: "true", failonerror: "true") { sysproperty(key: "java.awt.headless", value: "true") arg(value: inputPath) arg(value: appInfo) diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/EqualsHashCodeTemplatesManager.java b/java/java-impl/src/com/intellij/codeInsight/generation/EqualsHashCodeTemplatesManager.java index c852e93a3db5..0f25e54cfa1c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/EqualsHashCodeTemplatesManager.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/EqualsHashCodeTemplatesManager.java @@ -19,12 +19,18 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; +import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.java.generate.exception.TemplateResourceException; import org.jetbrains.java.generate.template.TemplateResource; import org.jetbrains.java.generate.template.TemplatesManager; import java.io.IOException; +import java.util.*; @State( name = "EqualsHashCodeTemplates", @@ -36,6 +42,23 @@ import java.io.IOException; public class EqualsHashCodeTemplatesManager extends TemplatesManager { private static final String DEFAULT_EQUALS = "/com/intellij/codeInsight/generation/defaultEquals.vm"; private static final String DEFAULT_HASH_CODE = "/com/intellij/codeInsight/generation/defaultHashCode.vm"; + private static final String APACHE3_EQUALS = "/com/intellij/codeInsight/generation/apacheEqualsBuilder3.vm"; + private static final String APACHE3_HASH_CODE = "/com/intellij/codeInsight/generation/apacheHashCodeBuilder3.vm"; + private static final String APACHE_EQUALS = "/com/intellij/codeInsight/generation/apacheEqualsBuilder.vm"; + private static final String APACHE_HASH_CODE = "/com/intellij/codeInsight/generation/apacheHashCodeBuilder.vm"; + private static final String GUAVA_EQUALS = "/com/intellij/codeInsight/generation/guavaEquals.vm"; + private static final String GUAVA_HASH_CODE = "/com/intellij/codeInsight/generation/guavaHashCode.vm"; + private static final String OBJECTS_EQUALS = "/com/intellij/codeInsight/generation/objectsEquals.vm"; + private static final String OBJECTS_HASH_CODE = "/com/intellij/codeInsight/generation/objectsHashCode.vm"; + + private static final String EQUALS_SUFFIX = "equals"; + private static final String HASH_CODE_SUFFIX = "hashCode"; + + @NonNls public static final String INTELLI_J_DEFAULT = "IntelliJ Default"; + @NonNls public static final String EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG = "Equals/HashCodeBuilder (Apache commons-lang)"; + @NonNls public static final String EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG_3 = "Equals/HashCodeBuilder (Apache commons-lang 3)"; + @NonNls public static final String OBJECTS_EQUAL_AND_HASH_CODE_GUAVA = "Objects.equal and hashCode (Guava)"; + @NonNls public static final String JAVA_UTIL_OBJECTS_EQUALS_AND_HASH_CODE = "java.util.Objects.equals and hashCode (java 7+)"; public static EqualsHashCodeTemplatesManager getInstance() { @@ -46,8 +69,20 @@ public class EqualsHashCodeTemplatesManager extends TemplatesManager { public TemplateResource[] getDefaultTemplates() { try { return new TemplateResource[] { - new TemplateResource("Default equals", readFile(DEFAULT_EQUALS), true), - new TemplateResource("Default hashCode", readFile(DEFAULT_HASH_CODE), true), + new TemplateResource(toEqualsName(INTELLI_J_DEFAULT), readFile(DEFAULT_EQUALS), true), + new TemplateResource(toHashCodeName(INTELLI_J_DEFAULT), readFile(DEFAULT_HASH_CODE), true), + + new TemplateResource(toEqualsName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG), readFile(APACHE_EQUALS), true), + new TemplateResource(toHashCodeName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG), readFile(APACHE_HASH_CODE), true), + + new TemplateResource(toEqualsName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG_3), readFile(APACHE3_EQUALS), true), + new TemplateResource(toHashCodeName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG_3), readFile(APACHE3_HASH_CODE), true), + + new TemplateResource(toEqualsName(OBJECTS_EQUAL_AND_HASH_CODE_GUAVA), readFile(GUAVA_EQUALS), true), + new TemplateResource(toHashCodeName(OBJECTS_EQUAL_AND_HASH_CODE_GUAVA), readFile(GUAVA_HASH_CODE), true), + + new TemplateResource(toEqualsName(JAVA_UTIL_OBJECTS_EQUALS_AND_HASH_CODE), readFile(OBJECTS_EQUALS), true), + new TemplateResource(toHashCodeName(JAVA_UTIL_OBJECTS_EQUALS_AND_HASH_CODE), readFile(OBJECTS_HASH_CODE), true) }; } catch (IOException e) { @@ -60,15 +95,35 @@ public class EqualsHashCodeTemplatesManager extends TemplatesManager { } public TemplateResource getDefaultEqualsTemplate() { - return getDefaultEqualsTemplate("equals", "hashCode"); + return getEqualsTemplate(getDefaultTemplate()); } public TemplateResource getDefaultHashcodeTemplate() { - return getDefaultEqualsTemplate("hashCode", "equals"); + return getHashcodeTemplate(getDefaultTemplate()); } - private TemplateResource getDefaultEqualsTemplate(String selfSuffix, String oppositeSuffix) { - final TemplateResource defaultTemplate = getDefaultTemplate(); + public TemplateResource getEqualsTemplate(TemplateResource template) { + return getDefaultTemplate(EQUALS_SUFFIX, HASH_CODE_SUFFIX, template); + } + + public TemplateResource getHashcodeTemplate(TemplateResource template) { + return getDefaultTemplate(HASH_CODE_SUFFIX, EQUALS_SUFFIX, template); + } + + public String[] getTemplateNames() { + final Set names = new LinkedHashSet(); + for (TemplateResource resource : getAllTemplates()) { + names.add(getTemplateBaseName(resource)); + } + return ArrayUtil.toStringArray(names); + } + + @NotNull + public static String getTemplateBaseName(TemplateResource resource) { + return StringUtil.trimEnd(StringUtil.trimEnd(resource.getFileName(), EQUALS_SUFFIX), HASH_CODE_SUFFIX).trim(); + } + + private TemplateResource getDefaultTemplate(String selfSuffix, String oppositeSuffix, TemplateResource defaultTemplate) { final String fileName = defaultTemplate.getFileName(); if (fileName.endsWith(selfSuffix)) { return defaultTemplate; @@ -82,4 +137,44 @@ public class EqualsHashCodeTemplatesManager extends TemplatesManager { assert false : selfSuffix + " template for " + fileName + " not found"; return null; } + + public void setDefaultTemplate(String name) { + Set fullNames = ContainerUtil.newHashSet(toEqualsName(name), toHashCodeName(name)); + for (TemplateResource resource : getAllTemplates()) { + if (fullNames.contains(resource.getFileName())) { + setDefaultTemplate(resource); + break; + } + } + } + + public String getDefaultTemplateBaseName() { + return getTemplateBaseName(getDefaultTemplate()); + } + + public static String toEqualsName(String name) { + return name + " " + EQUALS_SUFFIX; + } + + public static String toHashCodeName(String name) { + return name + " " + HASH_CODE_SUFFIX; + } + + public Collection> getTemplateCouples() { + final LinkedHashMap> resources = new LinkedHashMap>(); + for (TemplateResource resource : getAllTemplates()) { + final String baseName = getTemplateBaseName(resource); + TemplateResource eq = toEqualsName(baseName).equals(resource.getFileName()) ? resource : null; + TemplateResource hc = toHashCodeName(baseName).equals(resource.getFileName()) ? resource : null; + final Couple couple = resources.get(baseName); + if (couple != null) { + resources.put(baseName, Couple.of(couple.first != null ? couple.first : eq, + couple.second != null ? couple.second : hc)); + } + else { + resources.put(baseName, Couple.of(eq, hc)); + } + } + return resources.values(); + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java index 42adc40a11dd..106733b899a1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java @@ -159,8 +159,16 @@ public class GenerateEqualsHelper implements Runnable { .velocityGenerateCode(myClass, equalsFields, myNonNullSet, new HashMap(), contextMap, EqualsHashCodeTemplatesManager.getInstance().getDefaultEqualsTemplate().getTemplate(), 0, false); buffer.append(methodText); - PsiMethod result = myFactory.createMethodFromText(buffer.toString(), myClass); - final PsiParameter parameter = result.getParameterList().getParameters()[0]; + PsiMethod result; + try { + result = myFactory.createMethodFromText(buffer.toString(), myClass); + } + catch (IncorrectOperationException e) { + return null; + } + final PsiParameter[] parameters = result.getParameterList().getParameters(); + if (parameters.length != 1) return null; + final PsiParameter parameter = parameters[0]; PsiUtil.setModifierProperty(parameter, PsiModifier.FINAL, styleSettings.GENERATE_FINAL_PARAMETERS); PsiMethod method = (PsiMethod)myCodeStyleManager.reformat(result); @@ -190,7 +198,13 @@ public class GenerateEqualsHelper implements Runnable { .velocityGenerateCode(myClass, Arrays.asList(myHashCodeFields), myNonNullSet, new HashMap(), contextMap, EqualsHashCodeTemplatesManager.getInstance().getDefaultHashcodeTemplate().getTemplate(), 0, false); buffer.append(methodText); - PsiMethod hashCode = myFactory.createMethodFromText(buffer.toString(), null); + PsiMethod hashCode; + try { + hashCode = myFactory.createMethodFromText(buffer.toString(), null); + } + catch (IncorrectOperationException e) { + return null; + } hashCode = (PsiMethod)myJavaCodeStyleManager.shortenClassReferences(hashCode); return (PsiMethod)myCodeStyleManager.reformat(hashCode); } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/VelocityIncludesClassLoader.java b/java/java-impl/src/com/intellij/codeInsight/generation/VelocityIncludesClassLoader.java new file mode 100644 index 000000000000..0266e86d3d36 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/VelocityIncludesClassLoader.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2015 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.codeInsight.generation; + +import org.apache.velocity.exception.ResourceNotFoundException; +import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; + +import java.io.InputStream; + +public class VelocityIncludesClassLoader extends ClasspathResourceLoader { + @Override + public InputStream getResourceStream(String name) throws ResourceNotFoundException { + return super.getResourceStream("com/intellij/codeInsight/generation/" + name); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/apacheEqualsBuilder.vm b/java/java-impl/src/com/intellij/codeInsight/generation/apacheEqualsBuilder.vm new file mode 100644 index 000000000000..690a223c5d00 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/apacheEqualsBuilder.vm @@ -0,0 +1,21 @@ +#parse("equalsHelper.vm") +public boolean equals(## +#if ($settings.generateFinalParameters) + final ## +#end +Object $paramName){ + if(this == $paramName) return true; + + #addInstanceOfToText() + + #addClassInstance() + + return new org.apache.commons.lang.builder.EqualsBuilder() + #if($superHasEquals) + .appendSuper(super.equals($paramName)) + #end + #foreach($field in $members) + .append($field.name, ${classInstanceName}.$field.name) + #end + .isEquals(); +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/apacheEqualsBuilder3.vm b/java/java-impl/src/com/intellij/codeInsight/generation/apacheEqualsBuilder3.vm new file mode 100644 index 000000000000..dd3fecd94f80 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/apacheEqualsBuilder3.vm @@ -0,0 +1,21 @@ +#parse("equalsHelper.vm") +public boolean equals(## +#if ($settings.generateFinalParameters) + final ## +#end +Object $paramName){ + if(this == $paramName) return true; + + #addInstanceOfToText() + + #addClassInstance() + + return new org.apache.commons.lang3.builder.EqualsBuilder() + #if($superHasEquals) + .appendSuper(super.equals($paramName)) + #end + #foreach($field in $members) + .append($field.name, ${classInstanceName}.$field.name) + #end + .isEquals(); +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/apacheHashCodeBuilder.vm b/java/java-impl/src/com/intellij/codeInsight/generation/apacheHashCodeBuilder.vm new file mode 100644 index 000000000000..db93847c6d3b --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/apacheHashCodeBuilder.vm @@ -0,0 +1,10 @@ +public int hashCode() { + return new org.apache.commons.lang.builder.HashCodeBuilder(17, 37) + #if($superHasHashCode) + .appendSuper(super.hashCode()) + #end + #foreach($field in $members) + .append($field.name) + #end + .toHashCode(); +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/apacheHashCodeBuilder3.vm b/java/java-impl/src/com/intellij/codeInsight/generation/apacheHashCodeBuilder3.vm new file mode 100644 index 000000000000..ecb288dc146a --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/apacheHashCodeBuilder3.vm @@ -0,0 +1,10 @@ +public int hashCode() { + return new org.apache.commons.lang3.builder.HashCodeBuilder(17, 37) + #if($superHasHashCode) + .appendSuper(super.hashCode()) + #end + #foreach($field in $members) + .append($field.name) + #end + .toHashCode(); +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/defaultEquals.vm b/java/java-impl/src/com/intellij/codeInsight/generation/defaultEquals.vm index 5c0ba0820672..94c6c93d4065 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/defaultEquals.vm +++ b/java/java-impl/src/com/intellij/codeInsight/generation/defaultEquals.vm @@ -1,5 +1,4 @@ -#set($classInstanceName = $helper.getUniqueLocalVarName($instanceName, $members, $settings)) -#set($paramName = $helper.getUniqueLocalVarName($baseParamName, $members, $settings)) +#parse("equalsHelper.vm") public boolean equals(## #if ($settings.generateFinalParameters) final ## @@ -11,20 +10,18 @@ Object $paramName){ #addClassInstance() #foreach($field in $members) - #if (!$field.static) - #if ($field.array) - #addArrayEquals($field) - #elseif ($field.primitive) - #if ($field.double || $field.float) - #addDoubleFieldComparison($field) - #else - #addPrimitiveFieldComparison($field) - #end - #elseif ($field.enum) + #if ($field.array) + #addArrayEquals($field) + #elseif ($field.primitive) + #if ($field.double || $field.float) + #addDoubleFieldComparison($field) + #else #addPrimitiveFieldComparison($field) - #else - #addFieldComparison($field) #end + #elseif ($field.enum) + #addPrimitiveFieldComparison($field) + #else + #addFieldComparison($field) #end #end #end @@ -32,31 +29,6 @@ Object $paramName){ return true; } ## -#macro(addClassInstance) - #if ($settings.generateFinalLocals) - final ## - #end - $classname $classInstanceName = ($classname)$paramName; -#end -## -#macro(addEqualsPrologue) - if(this == $paramName) return true; - #if (!$superHasEquals) - #addInstanceOfToText() - #else - #addInstanceOfToText() - if(!super.equals($paramName)) return false; - #end -#end -## -#macro(addInstanceOfToText) - #if ($checkParameterWithInstanceof) - if(!($paramName instanceof $classname)) return false; - #else - if($paramName == null || getClass() != ${paramName}.getClass()) return false; - #end -#end -## #macro(addPrimitiveFieldComparison $field) if($field.name != ${classInstanceName}.$field.name) return false; #end diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/equalsHelper.vm b/java/java-impl/src/com/intellij/codeInsight/generation/equalsHelper.vm new file mode 100644 index 000000000000..8b8137f19a4e --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/equalsHelper.vm @@ -0,0 +1,24 @@ +#set($classInstanceName = $helper.getUniqueLocalVarName($instanceName, $members, $settings)) +#set($paramName = $helper.getUniqueLocalVarName($baseParamName, $members, $settings)) +#macro(addClassInstance) + #if ($settings.generateFinalLocals) + final ## + #end + $classname $classInstanceName = ($classname)$paramName; +#end +## +#macro(addEqualsPrologue) +if(this == $paramName) return true; + #addInstanceOfToText() + #if ($superHasEquals) + if(!super.equals($paramName)) return false; + #end +#end +## +#macro(addInstanceOfToText) + #if ($checkParameterWithInstanceof) + if(!($paramName instanceof $classname)) return false; + #else + if($paramName == null || getClass() != ${paramName}.getClass()) return false; + #end +#end diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/guavaEquals.vm b/java/java-impl/src/com/intellij/codeInsight/generation/guavaEquals.vm new file mode 100644 index 000000000000..213cabdd032d --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/guavaEquals.vm @@ -0,0 +1,27 @@ +#parse("equalsHelper.vm") +public boolean equals(## +#if ($settings.generateFinalParameters) + final ## +#end +Object $paramName){ + #addEqualsPrologue() + #addClassInstance() + return ## + #set($i = 0) + #foreach($field in $members) + #if ($i > 0) + && + #end + #set($i = $i + 1) + #if ($field.array) + #if ($field.nestedArray) +java.util.Arrays.deepEquals($field.name, ${classInstanceName}.$field.name)## + #else +java.util.Arrays.equals($field.name, ${classInstanceName}.$field.name)## + #end + #else +com.google.common.base.Objects.equal($field.name, ${classInstanceName}.$field.name)## + #end + #end + ; +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/guavaHashCode.vm b/java/java-impl/src/com/intellij/codeInsight/generation/guavaHashCode.vm new file mode 100644 index 000000000000..ff5bfcec7fb0 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/guavaHashCode.vm @@ -0,0 +1,18 @@ +public int hashCode() { + return com.google.common.base.Objects.hashCode(## + #set($i = 0) + #if($superHasHashCode) + super.hashCode() ## + #set($i = 1) + #end + #foreach($member in $members) + #if (!$member.static) + #if ($i > 0) + , ## + #end + $member.name ## + #set($i = $i + 1) + #end + #end + ); +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/objectsEquals.vm b/java/java-impl/src/com/intellij/codeInsight/generation/objectsEquals.vm new file mode 100644 index 000000000000..878a1f7656bd --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/objectsEquals.vm @@ -0,0 +1,27 @@ +#parse("equalsHelper.vm") +public boolean equals(## +#if ($settings.generateFinalParameters) + final ## +#end +Object $paramName){ + #addEqualsPrologue() + #addClassInstance() + return ## + #set($i = 0) + #foreach($field in $members) + #if ($i > 0) + && + #end + #set($i = $i + 1) + #if ($field.array) + #if ($field.nestedArray) +java.util.Arrays.deepEquals($field.name, ${classInstanceName}.$field.name)## + #else +java.util.Arrays.equals($field.name, ${classInstanceName}.$field.name)## + #end + #else +java.util.Objects.equals($field.name, ${classInstanceName}.$field.name)## + #end + #end + ; +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/objectsHashCode.vm b/java/java-impl/src/com/intellij/codeInsight/generation/objectsHashCode.vm new file mode 100644 index 000000000000..dfe06020b040 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/objectsHashCode.vm @@ -0,0 +1,18 @@ +public int hashCode() { + return java.util.Objects.hash(## + #set($i = 0) + #if($superHasHashCode) + super.hashCode() ## + #set($i = 1) + #end + #foreach($member in $members) + #if (!$member.static) + #if ($i > 0) + , ## + #end + $member.name ## + #set($i = $i + 1) + #end + #end + ); +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/ui/EqualsHashCodeTemplatesPanel.java b/java/java-impl/src/com/intellij/codeInsight/generation/ui/EqualsHashCodeTemplatesPanel.java new file mode 100644 index 000000000000..144c8da3586e --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/ui/EqualsHashCodeTemplatesPanel.java @@ -0,0 +1,204 @@ +/* + * Copyright 2000-2015 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.codeInsight.generation.ui; + +import com.intellij.codeInsight.generation.EqualsHashCodeTemplatesManager; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.UnnamedConfigurable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.NamedItemsListEditor; +import com.intellij.openapi.ui.Namer; +import com.intellij.openapi.ui.Splitter; +import com.intellij.openapi.util.Cloner; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Couple; +import com.intellij.openapi.util.Factory; +import com.intellij.ui.TitledSeparator; +import gnu.trove.Equality; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.java.generate.template.TemplateResource; +import org.jetbrains.java.generate.view.GenerateTemplateConfigurable; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class EqualsHashCodeTemplatesPanel extends NamedItemsListEditor> { + private static final Namer> NAMER = new Namer>() { + + @Override + public String getName(Couple couple) { + return EqualsHashCodeTemplatesManager.getTemplateBaseName(couple.first); + } + + @Override + public boolean canRename(Couple item) { + return !item.first.isDefault(); + } + + @Override + public void setName(Couple couple, String name) { + couple.first.setFileName(EqualsHashCodeTemplatesManager.toEqualsName(name)); + couple.second.setFileName(EqualsHashCodeTemplatesManager.toHashCodeName(name)); + } + }; + + private static final Factory> FACTORY = new Factory>() { + @Override + public Couple create() { + return Couple.of(new TemplateResource(), new TemplateResource()); + } + }; + + private static final Cloner> CLONER = new Cloner>() { + @Override + public Couple cloneOf(Couple couple) { + if (couple.first.isDefault()) return couple; + return copyOf(couple); + } + + @Override + public Couple copyOf(Couple couple) { + return Couple.of(copyOf(couple.first), copyOf(couple.second)); + } + + @NotNull + private TemplateResource copyOf(TemplateResource resource) { + TemplateResource result = new TemplateResource(); + result.setFileName(resource.getFileName()); + result.setTemplate(resource.getTemplate()); + return result; + } + }; + + private static final Equality> COMPARER = new Equality>() { + @Override + public boolean equals(Couple o1, Couple o2) { + return equals(o1.first, o2.first) && equals(o1.second, o2.second); + } + + private boolean equals(TemplateResource r1, TemplateResource r2) { + return Comparing.equal(r1.getTemplate(), r2.getTemplate()) && Comparing.equal(r1.getFileName(), r2.getFileName()); + } + }; + private final Project myProject; + private final EqualsHashCodeTemplatesManager myManager; + + public EqualsHashCodeTemplatesPanel(Project project, EqualsHashCodeTemplatesManager manager) { + super(NAMER, FACTORY, CLONER, COMPARER, new ArrayList>(manager.getTemplateCouples())); + myProject = project; + myManager = manager; + } + + @Nls + public String getDisplayName() { + return "Templates"; + } + + @Override + protected String subjDisplayName() { + return "template"; + } + + @Nullable + @NonNls + public String getHelpTopic() { + return null; + } + + @Override + public boolean isModified() { + return super.isModified() || !Comparing.equal(myManager.getDefaultTemplate(), getSelectedItem().first); + } + + @Override + protected boolean canDelete(Couple item) { + return !item.first.isDefault(); + } + + @Override + protected UnnamedConfigurable createConfigurable(Couple item) { + final GenerateTemplateConfigurable equalsConfigurable = new GenerateTemplateConfigurable(item.first, myProject); + final GenerateTemplateConfigurable hashCodeConfigurable = new GenerateTemplateConfigurable(item.second, myProject); + return new UnnamedConfigurable() { + @Nullable + @Override + public JComponent createComponent() { + final Splitter splitter = new Splitter(true); + + final JPanel eqPanel = new JPanel(new BorderLayout()); + eqPanel.add(new TitledSeparator("Equals Template:"), BorderLayout.NORTH); + final JComponent eqPane = equalsConfigurable.createComponent(); + eqPane.setPreferredSize(new Dimension(300, 200)); + eqPanel.add(eqPane, BorderLayout.CENTER); + splitter.setFirstComponent(eqPanel); + + final JPanel hcPanel = new JPanel(new BorderLayout()); + hcPanel.add(new TitledSeparator("HashCode Template:"), BorderLayout.NORTH); + final JComponent hcPane = hashCodeConfigurable.createComponent(); + hcPane.setPreferredSize(new Dimension(300, 200)); + hcPanel.add(hcPane, BorderLayout.CENTER); + splitter.setSecondComponent(hcPanel); + + return splitter; + } + + @Override + public boolean isModified() { + return equalsConfigurable.isModified() || hashCodeConfigurable.isModified(); + } + + @Override + public void apply() throws ConfigurationException { + equalsConfigurable.apply(); + hashCodeConfigurable.apply(); + } + + @Override + public void reset() { + equalsConfigurable.reset(); + hashCodeConfigurable.reset(); + } + + @Override + public void disposeUIResources() { + equalsConfigurable.disposeUIResources(); + hashCodeConfigurable.disposeUIResources(); + } + }; + } + + @Override + public void apply() throws ConfigurationException { + super.apply(); + List resources = new ArrayList(); + for (Couple resource : getItems()) { + resources.add(resource.first); + resources.add(resource.second); + } + myManager.setTemplates(resources); + + final Couple selection = getSelectedItem(); + if (selection != null) { + myManager.setDefaultTemplate(selection.first); + } + } +} + diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java b/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java index 1a80bc93a0eb..5261839f25ad 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java @@ -18,12 +18,16 @@ package com.intellij.codeInsight.generation.ui; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.NullableNotNullManager; +import com.intellij.codeInsight.generation.EqualsHashCodeTemplatesManager; import com.intellij.codeInsight.generation.GenerateEqualsHelper; import com.intellij.ide.wizard.StepAdapter; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.JavaVersionService; +import com.intellij.openapi.ui.ComboBox; +import com.intellij.openapi.ui.ComponentWithBrowseButton; import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.psi.*; import com.intellij.refactoring.classMembers.AbstractMemberInfoModel; @@ -38,9 +42,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.java.generate.psi.PsiAdapter; import javax.swing.*; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.*; +import java.util.List; /** * @author dsl @@ -247,7 +253,7 @@ public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard comboBoxWithBrowseButton = new ComponentWithBrowseButton(comboBox, + new MyEditTemplatesListener(project, myPanel, comboBox)); + final EqualsHashCodeTemplatesManager manager = EqualsHashCodeTemplatesManager.getInstance(); + comboBox.setModel(new DefaultComboBoxModel(manager.getTemplateNames())); + comboBox.setSelectedItem(manager.getDefaultTemplateBaseName()); + comboBox.addActionListener(new ActionListener() { + public void actionPerformed(@NotNull final ActionEvent M) { + manager.setDefaultTemplate((String)comboBox.getSelectedItem()); + } + }); + + templateChooserPanel.add(comboBoxWithBrowseButton, BorderLayout.CENTER); + myPanel.add(templateChooserPanel); myPanel.add(checkbox); myPanel.add(new JLabel(CodeInsightBundle.message("generate.equals.hashcode.accept.sublcasses.explanation"))); } @@ -353,5 +377,27 @@ public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/generateEquals/beforeDifferentTypesSuperEqualsAndHashCodeGuava.java b/java/java-tests/testData/codeInsight/generateEquals/beforeDifferentTypesSuperEqualsAndHashCodeGuava.java new file mode 100644 index 000000000000..b123e793ba14 --- /dev/null +++ b/java/java-tests/testData/codeInsight/generateEquals/beforeDifferentTypesSuperEqualsAndHashCodeGuava.java @@ -0,0 +1,31 @@ +class B { + @Override + public boolean equals(Object obj) { + return obj != null; + } + + @Override + public int hashCode() { + return super.hashCode(); + } +} +class A extends B { + Object[] a1; + Object[][] a2; + String[] a3; + String[][] a4; + int[] a5; + int[][] a6; + + byte a7; + short a8; + int a9; + long a10; + float a11; + double a12; + + Object a13; + String a14; + + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEquals15Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEquals15Test.java index 992f237c435e..68cd47604a9a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEquals15Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEquals15Test.java @@ -1,5 +1,6 @@ package com.intellij.codeInsight; +import com.intellij.codeInsight.generation.EqualsHashCodeTemplatesManager; import com.intellij.psi.PsiField; import com.intellij.util.Function; @@ -37,4 +38,22 @@ public class GenerateEquals15Test extends GenerateEqualsTestCase { doTest(Function.ID, Function.ID, Function.ID, true); } + public void testDifferentTypesSuperEqualsAndHashCodeApache3() throws Exception { + doTestWithTemplate(EqualsHashCodeTemplatesManager.EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG_3); + } + + public void testDifferentTypesSuperEqualsAndHashCodeGuava() throws Exception { + doTestWithTemplate(EqualsHashCodeTemplatesManager.OBJECTS_EQUAL_AND_HASH_CODE_GUAVA); + } + + private void doTestWithTemplate(String templateName) throws Exception { + try { + EqualsHashCodeTemplatesManager.getInstance().setDefaultTemplate(templateName); + doTest(Function.ID, Function.ID, Function.ID, true); + } + finally { + EqualsHashCodeTemplatesManager.getInstance().setDefaultTemplate(EqualsHashCodeTemplatesManager.INTELLI_J_DEFAULT); + } + } + } \ No newline at end of file diff --git a/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java b/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java index 595585998fde..3be1079fffc3 100644 --- a/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java +++ b/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java @@ -1,5 +1,17 @@ /* - * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved. + * Copyright 2000-2015 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.coverage; @@ -287,7 +299,8 @@ public class SrcFileAnnotator implements Disposable { // let's find old content in local history and build mapping from old lines to new one // local history doesn't index libraries, so let's distinguish libraries content with other one final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); - final VirtualFile file = getVirtualFile(); + final VirtualFile file = psiFile.getVirtualFile(); + LOG.assertTrue(file != null); final long fileTimeStamp = file.getTimeStamp(); final long coverageTimeStamp = suite.getLastCoverageTimeStamp(); diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java index 0e4c06929f68..8e3f7db77a60 100644 --- a/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java @@ -74,17 +74,13 @@ public class EditorSettingsManager extends FileDocumentManagerAdapter { private void applyConfigValueToUserData(VirtualFile file, Key userDataKey, String editorConfigKey, String configValue, Map configMap) { - if (configValue.isEmpty()) { - file.putUserData(userDataKey, null); - } - else { - final T data = configMap.get(configValue); - if (data == null) { - Utils.invalidConfigMessage(myProject, configValue, editorConfigKey, file.getCanonicalPath()); - } - else { - file.putUserData(userDataKey, data); - } + if (configValue.isEmpty()) return; + + final T data = configMap.get(configValue); + if (data == null) { + Utils.invalidConfigMessage(myProject, configValue, editorConfigKey, file.getCanonicalPath()); + } else { + file.putUserData(userDataKey, data); } } } diff --git a/plugins/generate-tostring/src/org/jetbrains/java/generate/velocity/VelocityFactory.java b/plugins/generate-tostring/src/org/jetbrains/java/generate/velocity/VelocityFactory.java index 542e181142ed..faaa80907a8e 100644 --- a/plugins/generate-tostring/src/org/jetbrains/java/generate/velocity/VelocityFactory.java +++ b/plugins/generate-tostring/src/org/jetbrains/java/generate/velocity/VelocityFactory.java @@ -15,10 +15,14 @@ */ package org.jetbrains.java.generate.velocity; +import com.intellij.codeInsight.generation.VelocityIncludesClassLoader; import org.apache.commons.collections.ExtendedProperties; +import org.apache.velocity.app.Velocity; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; import org.apache.velocity.runtime.log.SimpleLog4JLogSystem; +import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; +import org.apache.velocity.runtime.resource.loader.FileResourceLoader; /** * Velocity factory. @@ -47,6 +51,8 @@ public class VelocityFactory { ExtendedProperties prop = new ExtendedProperties(); prop.addProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, SimpleLog4JLogSystem.class.getName()); prop.addProperty("runtime.log.logsystem.log4j.category", "GenerateToString"); + prop.addProperty(RuntimeConstants.RESOURCE_LOADER, "includes"); + prop.addProperty("includes.resource.loader.class", VelocityIncludesClassLoader.class.getName()); VelocityEngine velocity = new VelocityEngine(); velocity.setExtendedProperties(prop); velocity.init();