mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
generate equals/hashCode: allow getters (IDEA-73860)
This commit is contained in:
@@ -118,9 +118,10 @@ public class GenerateEqualsHandler extends GenerateMembersHandlerBase {
|
||||
protected List<? extends GenerationInfo> generateMemberPrototypes(PsiClass aClass, ClassMember[] originalMembers) throws IncorrectOperationException {
|
||||
Project project = aClass.getProject();
|
||||
final boolean useInstanceofToCheckParameterType = CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER;
|
||||
final boolean useAccessors = CodeInsightSettings.getInstance().USE_ACCESSORS_IN_EQUALS_HASHCODE;
|
||||
|
||||
GenerateEqualsHelper helper = new GenerateEqualsHelper(project, aClass, myEqualsFields, myHashCodeFields, myNonNullFields,
|
||||
useInstanceofToCheckParameterType);
|
||||
useInstanceofToCheckParameterType, useAccessors);
|
||||
return OverrideImplementUtil.convert2GenerationInfos(helper.generateMembers());
|
||||
}
|
||||
|
||||
|
||||
@@ -47,18 +47,30 @@ public class GenerateEqualsHelper implements Runnable {
|
||||
private final JavaCodeStyleManager myJavaCodeStyleManager;
|
||||
private final Project myProject;
|
||||
private final boolean myCheckParameterWithInstanceof;
|
||||
private final boolean myUseAccessors;
|
||||
|
||||
public GenerateEqualsHelper(Project project,
|
||||
PsiClass aClass,
|
||||
PsiField[] equalsFields,
|
||||
PsiField[] hashCodeFields,
|
||||
PsiField[] nonNullFields,
|
||||
boolean useInstanceofToCheckParameterType) {
|
||||
this(project, aClass, equalsFields, hashCodeFields, nonNullFields, useInstanceofToCheckParameterType, false);
|
||||
}
|
||||
|
||||
public GenerateEqualsHelper(Project project,
|
||||
PsiClass aClass,
|
||||
PsiField[] equalsFields,
|
||||
PsiField[] hashCodeFields,
|
||||
PsiField[] nonNullFields,
|
||||
boolean useInstanceofToCheckParameterType) {
|
||||
boolean useInstanceofToCheckParameterType,
|
||||
boolean useAccessors) {
|
||||
myClass = aClass;
|
||||
myEqualsFields = equalsFields;
|
||||
myHashCodeFields = hashCodeFields;
|
||||
myProject = project;
|
||||
myCheckParameterWithInstanceof = useInstanceofToCheckParameterType;
|
||||
myUseAccessors = useAccessors;
|
||||
|
||||
myNonNullSet = new HashSet<PsiField>();
|
||||
ContainerUtil.addAll(myNonNullSet, nonNullFields);
|
||||
@@ -157,7 +169,7 @@ public class GenerateEqualsHelper implements Runnable {
|
||||
|
||||
final String methodText = GenerationUtil
|
||||
.velocityGenerateCode(myClass, equalsFields, myNonNullSet, new HashMap<String, String>(), contextMap,
|
||||
EqualsHashCodeTemplatesManager.getInstance().getDefaultEqualsTemplate().getTemplate(), 0, false);
|
||||
EqualsHashCodeTemplatesManager.getInstance().getDefaultEqualsTemplate().getTemplate(), 0, false, myUseAccessors);
|
||||
buffer.append(methodText);
|
||||
PsiMethod result;
|
||||
try {
|
||||
@@ -196,7 +208,7 @@ public class GenerateEqualsHelper implements Runnable {
|
||||
|
||||
final String methodText = GenerationUtil
|
||||
.velocityGenerateCode(myClass, Arrays.asList(myHashCodeFields), myNonNullSet, new HashMap<String, String>(), contextMap,
|
||||
EqualsHashCodeTemplatesManager.getInstance().getDefaultHashcodeTemplate().getTemplate(), 0, false);
|
||||
EqualsHashCodeTemplatesManager.getInstance().getDefaultHashcodeTemplate().getTemplate(), 0, false, myUseAccessors);
|
||||
buffer.append(methodText);
|
||||
PsiMethod hashCode;
|
||||
try {
|
||||
|
||||
@@ -14,8 +14,8 @@ Object $paramName){
|
||||
#if($superHasEquals)
|
||||
.appendSuper(super.equals($paramName))
|
||||
#end
|
||||
#foreach($field in $members)
|
||||
.append($field.name, ${classInstanceName}.$field.name)
|
||||
#foreach($field in $fields)
|
||||
.append($field.accessor, ${classInstanceName}.$field.accessor)
|
||||
#end
|
||||
.isEquals();
|
||||
}
|
||||
@@ -14,8 +14,8 @@ Object $paramName){
|
||||
#if($superHasEquals)
|
||||
.appendSuper(super.equals($paramName))
|
||||
#end
|
||||
#foreach($field in $members)
|
||||
.append($field.name, ${classInstanceName}.$field.name)
|
||||
#foreach($field in $fields)
|
||||
.append($field.accessor, ${classInstanceName}.$field.accessor)
|
||||
#end
|
||||
.isEquals();
|
||||
}
|
||||
@@ -3,8 +3,8 @@ public int hashCode() {
|
||||
#if($superHasHashCode)
|
||||
.appendSuper(super.hashCode())
|
||||
#end
|
||||
#foreach($field in $members)
|
||||
.append($field.name)
|
||||
#foreach($field in $fields)
|
||||
.append($field.accessor)
|
||||
#end
|
||||
.toHashCode();
|
||||
}
|
||||
@@ -3,8 +3,8 @@ public int hashCode() {
|
||||
#if($superHasHashCode)
|
||||
.appendSuper(super.hashCode())
|
||||
#end
|
||||
#foreach($field in $members)
|
||||
.append($field.name)
|
||||
#foreach($field in $fields)
|
||||
.append($field.accessor)
|
||||
#end
|
||||
.toHashCode();
|
||||
}
|
||||
@@ -5,11 +5,11 @@ public boolean equals(##
|
||||
#end
|
||||
Object $paramName){
|
||||
#addEqualsPrologue()
|
||||
#if ($members.size() > 0)
|
||||
#if ($fields.size() > 0)
|
||||
|
||||
#addClassInstance()
|
||||
|
||||
#foreach($field in $members)
|
||||
#foreach($field in $fields)
|
||||
#if ($field.array)
|
||||
#addArrayEquals($field)
|
||||
#elseif ($field.primitive)
|
||||
@@ -30,29 +30,29 @@ Object $paramName){
|
||||
}
|
||||
##
|
||||
#macro(addPrimitiveFieldComparison $field)
|
||||
if($field.name != ${classInstanceName}.$field.name) return false;
|
||||
if($field.accessor != ${classInstanceName}.$field.accessor) return false;
|
||||
#end
|
||||
##
|
||||
#macro(addDoubleFieldComparison $field)
|
||||
#if ($field.double)
|
||||
if(Double.compare(${classInstanceName}.$field.name, $field.name) != 0)return false;
|
||||
if(Double.compare(${classInstanceName}.$field.accessor, $field.accessor) != 0)return false;
|
||||
#else
|
||||
if(Float.compare(${classInstanceName}.$field.name, $field.name) != 0)return false;
|
||||
if(Float.compare(${classInstanceName}.$field.accessor, $field.accessor) != 0)return false;
|
||||
#end
|
||||
#end
|
||||
##
|
||||
#macro(addFieldComparison $field)
|
||||
#if ($field.notNull)
|
||||
if(!${field.name}.equals(${classInstanceName}.$field.name))return false;
|
||||
if(!${field.accessor}.equals(${classInstanceName}.$field.accessor))return false;
|
||||
#else
|
||||
if($field.name != null ? !${field.name}.equals(${classInstanceName}.$field.name) : ${classInstanceName}.$field.name != null)return false;
|
||||
if($field.accessor != null ? !${field.accessor}.equals(${classInstanceName}.$field.accessor) : ${classInstanceName}.$field.accessor != null)return false;
|
||||
#end
|
||||
#end
|
||||
##
|
||||
#macro(addArrayEquals $field)
|
||||
#if ($field.nestedArray)
|
||||
#if ($java_version > 4)
|
||||
if(!java.util.Arrays.deepEquals($field.name, ${classInstanceName}.$field.name)) return false;
|
||||
if(!java.util.Arrays.deepEquals($field.accessor, ${classInstanceName}.$field.accessor)) return false;
|
||||
#else
|
||||
// Compare nested arrays - values of $field.name here
|
||||
#end
|
||||
@@ -61,5 +61,5 @@ Object $paramName){
|
||||
#if ($field.objectArray)
|
||||
// Probably incorrect - comparing Object[] arrays with Arrays.equals
|
||||
#end
|
||||
if(!java.util.Arrays.equals($field.name, ${classInstanceName}.$field.name)) return false;
|
||||
if(!java.util.Arrays.equals($field.accessor, ${classInstanceName}.$field.accessor)) return false;
|
||||
#end
|
||||
@@ -1,14 +1,14 @@
|
||||
public int hashCode() {
|
||||
#if (!$superHasHashCode && $members.size() == 1)
|
||||
#set($field = $members.get(0))
|
||||
#if (!$superHasHashCode && $fields.size() == 1)
|
||||
#set($field = $fields.get(0))
|
||||
#if ($field.primitive)
|
||||
#addTempForOneField($field)
|
||||
return #addPrimitiveFieldHashCode($field);
|
||||
#else
|
||||
return #addFieldHashCode($field, false);
|
||||
#end
|
||||
#elseif ($members.size() > 0)
|
||||
#set($resultName = $helper.getUniqueLocalVarName("result", $members, $settings))
|
||||
#elseif ($fields.size() > 0)
|
||||
#set($resultName = $helper.getUniqueLocalVarName("result", $fields, $settings))
|
||||
int $resultName ##
|
||||
#set($resultAssigned = false)
|
||||
#set($resultDeclarationCompleted = false)
|
||||
@@ -19,7 +19,7 @@ public int hashCode() {
|
||||
#end
|
||||
#addTempDeclaration($resultDeclarationCompleted)
|
||||
#set($tempName = "#addTempDeclaration($resultDeclarationCompleted)")
|
||||
#foreach($field in $members)
|
||||
#foreach($field in $fields)
|
||||
#addTempAssignment($field)
|
||||
#if ($resultDeclarationCompleted)
|
||||
$resultName ##
|
||||
@@ -44,7 +44,7 @@ public int hashCode() {
|
||||
}
|
||||
##
|
||||
#macro (addPrimitiveFieldHashCode $field)
|
||||
#set ($fName = $field.name)
|
||||
#set ($fName = $field.accessor)
|
||||
#if ($field.byte || $field.short || $field.char)
|
||||
(int) $fName##
|
||||
#elseif ($field.long)
|
||||
@@ -64,7 +64,7 @@ public int hashCode() {
|
||||
#end
|
||||
##
|
||||
#macro(getTempVarName)
|
||||
$helper.getUniqueLocalVarName("temp", $members, $settings)##
|
||||
$helper.getUniqueLocalVarName("temp", $fields, $settings)##
|
||||
#end
|
||||
##
|
||||
#macro(addTempForOneField $field)
|
||||
@@ -73,7 +73,7 @@ public int hashCode() {
|
||||
final ##
|
||||
#end
|
||||
#set($tempName = "#getTempVarName()")
|
||||
long $tempName = Double.doubleToLongBits($field.name);
|
||||
long $tempName = Double.doubleToLongBits($field.accessor);
|
||||
#end
|
||||
#end
|
||||
##
|
||||
@@ -82,9 +82,9 @@ public int hashCode() {
|
||||
#if ($field.nestedArray)
|
||||
// Probably incorrect - hashCode for high dimension arrays with Arrays.hashCode
|
||||
#end
|
||||
java.util.Arrays.hashCode($field.name)##
|
||||
java.util.Arrays.hashCode($field.accessor)##
|
||||
#else
|
||||
${field.name}.hashCode()##
|
||||
${field.accessor}.hashCode()##
|
||||
#end
|
||||
#end
|
||||
##
|
||||
@@ -97,8 +97,8 @@ public int hashCode() {
|
||||
#end
|
||||
##
|
||||
#macro(addTempDeclaration $resultDeclarationCompleted)
|
||||
#foreach($member in $members)
|
||||
#if ($member.double)
|
||||
#foreach($field in $fields)
|
||||
#if ($field.double)
|
||||
#if (!$resultDeclarationCompleted)
|
||||
;
|
||||
#end
|
||||
@@ -113,12 +113,12 @@ public int hashCode() {
|
||||
#macro(addTempAssignment $field)
|
||||
#if ($field.double)
|
||||
#set($tempName = "#getTempVarName()")
|
||||
$tempName = Double.doubleToLongBits($field.name);
|
||||
$tempName = Double.doubleToLongBits($field.accessor);
|
||||
#end
|
||||
#end
|
||||
##
|
||||
#macro(addFieldHashCode $field $brace)
|
||||
#set($name = $field.name)
|
||||
#set($name = $field.accessor)
|
||||
#if ($field.notNull)#adjustHashCodeToArrays($field)
|
||||
#else
|
||||
#if ($brace)(##
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#set($classInstanceName = $helper.getUniqueLocalVarName($instanceName, $members, $settings))
|
||||
#set($paramName = $helper.getUniqueLocalVarName($baseParamName, $members, $settings))
|
||||
#set($classInstanceName = $helper.getUniqueLocalVarName($instanceName, $fields, $settings))
|
||||
#set($paramName = $helper.getUniqueLocalVarName($baseParamName, $fields, $settings))
|
||||
#macro(addClassInstance)
|
||||
#if ($settings.generateFinalLocals)
|
||||
final ##
|
||||
|
||||
@@ -8,19 +8,19 @@ Object $paramName){
|
||||
#addClassInstance()
|
||||
return ##
|
||||
#set($i = 0)
|
||||
#foreach($field in $members)
|
||||
#foreach($field in $fields)
|
||||
#if ($i > 0)
|
||||
&&
|
||||
#end
|
||||
#set($i = $i + 1)
|
||||
#if ($field.array)
|
||||
#if ($field.nestedArray)
|
||||
java.util.Arrays.deepEquals($field.name, ${classInstanceName}.$field.name)##
|
||||
java.util.Arrays.deepEquals($field.accessor, ${classInstanceName}.$field.accessor)##
|
||||
#else
|
||||
java.util.Arrays.equals($field.name, ${classInstanceName}.$field.name)##
|
||||
java.util.Arrays.equals($field.accessor, ${classInstanceName}.$field.accessor)##
|
||||
#end
|
||||
#else
|
||||
com.google.common.base.Objects.equal($field.name, ${classInstanceName}.$field.name)##
|
||||
com.google.common.base.Objects.equal($field.accessor, ${classInstanceName}.$field.accessor)##
|
||||
#end
|
||||
#end
|
||||
;
|
||||
|
||||
@@ -5,12 +5,12 @@ public int hashCode() {
|
||||
super.hashCode() ##
|
||||
#set($i = 1)
|
||||
#end
|
||||
#foreach($member in $members)
|
||||
#if (!$member.static)
|
||||
#foreach($field in $fields)
|
||||
#if (!$field.static)
|
||||
#if ($i > 0)
|
||||
, ##
|
||||
#end
|
||||
$member.name ##
|
||||
$field.accessor ##
|
||||
#set($i = $i + 1)
|
||||
#end
|
||||
#end
|
||||
|
||||
@@ -8,19 +8,19 @@ Object $paramName){
|
||||
#addClassInstance()
|
||||
return ##
|
||||
#set($i = 0)
|
||||
#foreach($field in $members)
|
||||
#foreach($field in $fields)
|
||||
#if ($i > 0)
|
||||
&&
|
||||
#end
|
||||
#set($i = $i + 1)
|
||||
#if ($field.array)
|
||||
#if ($field.nestedArray)
|
||||
java.util.Arrays.deepEquals($field.name, ${classInstanceName}.$field.name)##
|
||||
java.util.Arrays.deepEquals($field.accessor, ${classInstanceName}.$field.accessor)##
|
||||
#else
|
||||
java.util.Arrays.equals($field.name, ${classInstanceName}.$field.name)##
|
||||
java.util.Arrays.equals($field.accessor, ${classInstanceName}.$field.accessor)##
|
||||
#end
|
||||
#else
|
||||
java.util.Objects.equals($field.name, ${classInstanceName}.$field.name)##
|
||||
java.util.Objects.equals($field.accessor, ${classInstanceName}.$field.accessor)##
|
||||
#end
|
||||
#end
|
||||
;
|
||||
|
||||
@@ -5,12 +5,12 @@ public int hashCode() {
|
||||
super.hashCode() ##
|
||||
#set($i = 1)
|
||||
#end
|
||||
#foreach($member in $members)
|
||||
#if (!$member.static)
|
||||
#foreach($field in $fields)
|
||||
#if (!$field.static)
|
||||
#if ($i > 0)
|
||||
, ##
|
||||
#end
|
||||
$member.name ##
|
||||
$field.accessor ##
|
||||
#set($i = $i + 1)
|
||||
#end
|
||||
#end
|
||||
|
||||
+22
-12
@@ -341,23 +341,15 @@ public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard<PsiClass,
|
||||
private final JComponent myPanel;
|
||||
|
||||
private TemplateChooserStep(boolean isFinal, Project project) {
|
||||
final JCheckBox checkbox = new NonFocusableCheckBox(CodeInsightBundle.message("generate.equals.hashcode.accept.sublcasses"));
|
||||
checkbox.setSelected(!isFinal && CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER);
|
||||
checkbox.setEnabled(!isFinal);
|
||||
checkbox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(@NotNull final ActionEvent M) {
|
||||
CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER = checkbox.isSelected();
|
||||
}
|
||||
});
|
||||
|
||||
myPanel = new JPanel(new VerticalFlowLayout());
|
||||
final JPanel templateChooserPanel = new JPanel(new BorderLayout());
|
||||
final JLabel templateChooserLabel = new JLabel("Template:");
|
||||
final JLabel templateChooserLabel = new JLabel(CodeInsightBundle.message("generate.equals.hashcode.template"));
|
||||
templateChooserPanel.add(templateChooserLabel, BorderLayout.WEST);
|
||||
|
||||
final ComboBox comboBox = new ComboBox();
|
||||
final ComponentWithBrowseButton<ComboBox> comboBoxWithBrowseButton = new ComponentWithBrowseButton<ComboBox>(comboBox,
|
||||
new MyEditTemplatesListener(project, myPanel, comboBox));
|
||||
final ComponentWithBrowseButton<ComboBox> comboBoxWithBrowseButton =
|
||||
new ComponentWithBrowseButton<ComboBox>(comboBox, new MyEditTemplatesListener(project, myPanel, comboBox));
|
||||
templateChooserLabel.setLabelFor(comboBox);
|
||||
final EqualsHashCodeTemplatesManager manager = EqualsHashCodeTemplatesManager.getInstance();
|
||||
comboBox.setModel(new DefaultComboBoxModel(manager.getTemplateNames()));
|
||||
comboBox.setSelectedItem(manager.getDefaultTemplateBaseName());
|
||||
@@ -369,8 +361,26 @@ public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard<PsiClass,
|
||||
|
||||
templateChooserPanel.add(comboBoxWithBrowseButton, BorderLayout.CENTER);
|
||||
myPanel.add(templateChooserPanel);
|
||||
|
||||
final JCheckBox checkbox = new NonFocusableCheckBox(CodeInsightBundle.message("generate.equals.hashcode.accept.sublcasses"));
|
||||
checkbox.setSelected(!isFinal && CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER);
|
||||
checkbox.setEnabled(!isFinal);
|
||||
checkbox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(@NotNull final ActionEvent M) {
|
||||
CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER = checkbox.isSelected();
|
||||
}
|
||||
});
|
||||
myPanel.add(checkbox);
|
||||
myPanel.add(new JLabel(CodeInsightBundle.message("generate.equals.hashcode.accept.sublcasses.explanation")));
|
||||
|
||||
final JCheckBox gettersCheckbox = new NonFocusableCheckBox(CodeInsightBundle.message("generate.equals.hashcode.use.getters"));
|
||||
gettersCheckbox.setSelected(CodeInsightSettings.getInstance().USE_ACCESSORS_IN_EQUALS_HASHCODE);
|
||||
gettersCheckbox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(@NotNull final ActionEvent M) {
|
||||
CodeInsightSettings.getInstance().USE_ACCESSORS_IN_EQUALS_HASHCODE = gettersCheckbox.isSelected();
|
||||
}
|
||||
});
|
||||
myPanel.add(gettersCheckbox);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import java.util.Arrays;
|
||||
|
||||
class A {
|
||||
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;
|
||||
|
||||
public Object[] getA1() {
|
||||
return a1;
|
||||
}
|
||||
|
||||
public Object[][] getA2() {
|
||||
return a2;
|
||||
}
|
||||
|
||||
public String[] getA3() {
|
||||
return a3;
|
||||
}
|
||||
|
||||
public String[][] getA4() {
|
||||
return a4;
|
||||
}
|
||||
|
||||
public int[] getA5() {
|
||||
return a5;
|
||||
}
|
||||
|
||||
public int[][] getA6() {
|
||||
return a6;
|
||||
}
|
||||
|
||||
public byte getA7() {
|
||||
return a7;
|
||||
}
|
||||
|
||||
public short getA8() {
|
||||
return a8;
|
||||
}
|
||||
|
||||
public int getA9() {
|
||||
return a9;
|
||||
}
|
||||
|
||||
public long getA10() {
|
||||
return a10;
|
||||
}
|
||||
|
||||
public float getA11() {
|
||||
return a11;
|
||||
}
|
||||
|
||||
public double getA12() {
|
||||
return a12;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final A a = (A) o;
|
||||
|
||||
if (getA10() != a.getA10()) return false;
|
||||
if (Float.compare(a.getA11(), getA11()) != 0) return false;
|
||||
if (Double.compare(a.getA12(), getA12()) != 0) return false;
|
||||
if (getA7() != a.getA7()) return false;
|
||||
if (getA8() != a.getA8()) return false;
|
||||
if (getA9() != a.getA9()) return false;
|
||||
// Probably incorrect - comparing Object[] arrays with Arrays.equals
|
||||
if (!Arrays.equals(getA1(), a.getA1())) return false;
|
||||
if (a13 != null ? !a13.equals(a.a13) : a.a13 != null) return false;
|
||||
if (a14 != null ? !a14.equals(a.a14) : a.a14 != null) return false;
|
||||
if (!Arrays.deepEquals(getA2(), a.getA2())) return false;
|
||||
// Probably incorrect - comparing Object[] arrays with Arrays.equals
|
||||
if (!Arrays.equals(getA3(), a.getA3())) return false;
|
||||
if (!Arrays.deepEquals(getA4(), a.getA4())) return false;
|
||||
if (!Arrays.equals(getA5(), a.getA5())) return false;
|
||||
if (!Arrays.deepEquals(getA6(), a.getA6())) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
result = getA1() != null ? Arrays.hashCode(getA1()) : 0;
|
||||
result = 31 * result + (getA2() != null ? // Probably incorrect - hashCode for high dimension arrays with Arrays.hashCode
|
||||
Arrays.hashCode(getA2()) : 0);
|
||||
result = 31 * result + (getA3() != null ? Arrays.hashCode(getA3()) : 0);
|
||||
result = 31 * result + (getA4() != null ? // Probably incorrect - hashCode for high dimension arrays with Arrays.hashCode
|
||||
Arrays.hashCode(getA4()) : 0);
|
||||
result = 31 * result + (getA5() != null ? Arrays.hashCode(getA5()) : 0);
|
||||
result = 31 * result + (getA6() != null ? // Probably incorrect - hashCode for high dimension arrays with Arrays.hashCode
|
||||
Arrays.hashCode(getA6()) : 0);
|
||||
result = 31 * result + (int) getA7();
|
||||
result = 31 * result + (int) getA8();
|
||||
result = 31 * result + getA9();
|
||||
result = 31 * result + (int) (getA10() ^ (getA10() >>> 32));
|
||||
result = 31 * result + (getA11() != +0.0f ? Float.floatToIntBits(getA11()) : 0);
|
||||
temp = Double.doubleToLongBits(getA12());
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
result = 31 * result + (a13 != null ? a13.hashCode() : 0);
|
||||
result = 31 * result + (a14 != null ? a14.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
class A {
|
||||
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;
|
||||
|
||||
public Object[] getA1() {
|
||||
return a1;
|
||||
}
|
||||
|
||||
public Object[][] getA2() {
|
||||
return a2;
|
||||
}
|
||||
|
||||
public String[] getA3() {
|
||||
return a3;
|
||||
}
|
||||
|
||||
public String[][] getA4() {
|
||||
return a4;
|
||||
}
|
||||
|
||||
public int[] getA5() {
|
||||
return a5;
|
||||
}
|
||||
|
||||
public int[][] getA6() {
|
||||
return a6;
|
||||
}
|
||||
|
||||
public byte getA7() {
|
||||
return a7;
|
||||
}
|
||||
|
||||
public short getA8() {
|
||||
return a8;
|
||||
}
|
||||
|
||||
public int getA9() {
|
||||
return a9;
|
||||
}
|
||||
|
||||
public long getA10() {
|
||||
return a10;
|
||||
}
|
||||
|
||||
public float getA11() {
|
||||
return a11;
|
||||
}
|
||||
|
||||
public double getA12() {
|
||||
return a12;
|
||||
}
|
||||
|
||||
<caret>
|
||||
}
|
||||
@@ -22,6 +22,15 @@ public class GenerateEquals15Test extends GenerateEqualsTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
public void testDifferentTypesGetters() throws Exception {
|
||||
doTest(Function.ID, Function.ID, new Function<PsiField[], PsiField[]>() {
|
||||
@Override
|
||||
public PsiField[] fun(PsiField[] fields) {
|
||||
return new PsiField[0];
|
||||
}
|
||||
}, true, true);
|
||||
}
|
||||
|
||||
public void testDifferentTypesAllNotNull() throws Exception {
|
||||
doTest(Function.ID, Function.ID, Function.ID, true);
|
||||
}
|
||||
|
||||
@@ -43,12 +43,23 @@ public abstract class GenerateEqualsTestCase extends LightCodeInsightTestCase {
|
||||
Function<PsiField[], PsiField[]> hFunction,
|
||||
Function<PsiField[], PsiField[]> nnFunction,
|
||||
boolean insertOverride) throws Exception {
|
||||
doTest(eqFunction, hFunction, nnFunction, insertOverride, false);
|
||||
}
|
||||
|
||||
protected void doTest(Function<PsiField[], PsiField[]> eqFunction,
|
||||
Function<PsiField[], PsiField[]> hFunction,
|
||||
Function<PsiField[], PsiField[]> nnFunction,
|
||||
boolean insertOverride, boolean useAccessors) throws Exception {
|
||||
configureByFile("/codeInsight/generateEquals/before" + getTestName(false) + ".java");
|
||||
performTest(eqFunction, hFunction, nnFunction, insertOverride);
|
||||
performTest(eqFunction, hFunction, nnFunction, insertOverride, useAccessors);
|
||||
checkResultByFile("/codeInsight/generateEquals/after" + getTestName(false) + ".java");
|
||||
}
|
||||
|
||||
private static void performTest(Function<PsiField[], PsiField[]> equals, Function<PsiField[], PsiField[]> hashCode, Function<PsiField[], PsiField[]> nonNull, boolean insertOverride) {
|
||||
private static void performTest(Function<PsiField[], PsiField[]> equals,
|
||||
Function<PsiField[], PsiField[]> hashCode,
|
||||
Function<PsiField[], PsiField[]> nonNull,
|
||||
boolean insertOverride,
|
||||
boolean useAccessors) {
|
||||
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()).clone();
|
||||
settings.GENERATE_FINAL_LOCALS = true;
|
||||
settings.INSERT_OVERRIDE_ANNOTATION = insertOverride;
|
||||
@@ -59,7 +70,7 @@ public abstract class GenerateEqualsTestCase extends LightCodeInsightTestCase {
|
||||
PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
|
||||
if (aClass == null) return;
|
||||
PsiField[] fields = aClass.getFields();
|
||||
new GenerateEqualsHelper(getProject(), aClass, equals.fun(fields), hashCode.fun(fields), nonNull.fun(fields), false).invoke();
|
||||
new GenerateEqualsHelper(getProject(), aClass, equals.fun(fields), hashCode.fun(fields), nonNull.fun(fields), false, useAccessors).invoke();
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -127,6 +127,7 @@ public class CodeInsightSettings implements PersistentStateComponent<Element>, C
|
||||
public boolean HIGHLIGHT_SCOPE = false;
|
||||
|
||||
public boolean USE_INSTANCEOF_ON_EQUALS_PARAMETER = false;
|
||||
public boolean USE_ACCESSORS_IN_EQUALS_HASHCODE = false;
|
||||
|
||||
public boolean HIGHLIGHT_IDENTIFIER_UNDER_CARET = true;
|
||||
|
||||
|
||||
@@ -97,6 +97,8 @@ generate.equals.hashcode.wizard.title=Generate equals() and hashCode()
|
||||
generate.equals.hashcode.equals.fields.chooser.title=Choose &fields to be included in equals()
|
||||
generate.equals.hashcode.hashcode.fields.chooser.title=Choose &fields to be included in hashCode()
|
||||
generate.equals.hashcode.non.null.fields.chooser.title=Select all non-null &fields
|
||||
generate.equals.hashcode.use.getters=Use &getters during code generation
|
||||
generate.equals.hashcode.template=&Template:
|
||||
generate.equals.hashcode.accept.sublcasses=Accept &subclasses as parameter to equals() method
|
||||
generate.equals.hashcode.accept.sublcasses.explanation=<html><body>While generally incompliant to Object.equals() specification accepting<br>subclasses might be necessary for generated \
|
||||
method to work correctly<br>with frameworks, which generate Proxy subclasses like Hibernate.</body></html>
|
||||
|
||||
@@ -138,7 +138,7 @@ public class GenerationUtil {
|
||||
int sortElements,
|
||||
boolean useFullyQualifiedName)
|
||||
throws GenerateCodeException {
|
||||
return velocityGenerateCode(clazz, selectedMembers, Collections.<PsiMember>emptyList(), params, Collections.<String, Object>emptyMap(), templateMacro, sortElements, useFullyQualifiedName);
|
||||
return velocityGenerateCode(clazz, selectedMembers, Collections.<PsiMember>emptyList(), params, Collections.<String, Object>emptyMap(), templateMacro, sortElements, useFullyQualifiedName, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,6 +149,7 @@ public class GenerationUtil {
|
||||
* @param selectedMembers the selected members as both {@link PsiField} and {@link PsiMethod}.
|
||||
* @param params additional parameters stored with key/value in the map.
|
||||
* @param templateMacro the velocity macro template
|
||||
* @param useAccessors if true, accessor property for FieldElement bean would be assigned to field getter name append with ()
|
||||
* @return code (usually javacode). Returns null if templateMacro is null.
|
||||
* @throws GenerateCodeException is thrown when there is an error generating the javacode.
|
||||
*/
|
||||
@@ -159,7 +160,8 @@ public class GenerationUtil {
|
||||
Map<String, Object> contextMap,
|
||||
String templateMacro,
|
||||
int sortElements,
|
||||
boolean useFullyQualifiedName)
|
||||
boolean useFullyQualifiedName,
|
||||
boolean useAccessors)
|
||||
throws GenerateCodeException {
|
||||
if (templateMacro == null) {
|
||||
return null;
|
||||
@@ -173,7 +175,7 @@ public class GenerationUtil {
|
||||
|
||||
// field information
|
||||
logger.debug("Velocity Context - adding fields");
|
||||
vc.put("fields", ElementUtils.getOnlyAsFieldElements(selectedMembers));
|
||||
vc.put("fields", ElementUtils.getOnlyAsFieldElements(selectedMembers, selectedNotNullMembers, useAccessors));
|
||||
|
||||
// method information
|
||||
logger.debug("Velocity Context - adding methods");
|
||||
@@ -181,7 +183,7 @@ public class GenerationUtil {
|
||||
|
||||
// element information (both fields and methods)
|
||||
logger.debug("Velocity Context - adding members (fields and methods)");
|
||||
List<Element> elements = ElementUtils.getOnlyAsFieldAndMethodElements(selectedMembers, selectedNotNullMembers);
|
||||
List<Element> elements = ElementUtils.getOnlyAsFieldAndMethodElements(selectedMembers, selectedNotNullMembers, useAccessors);
|
||||
// sort elements if enabled and not using chooser dialog
|
||||
if (sortElements != 0) {
|
||||
Collections.sort(elements, new ElementComparator(sortElements));
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.jetbrains.java.generate.element;
|
||||
|
||||
import com.intellij.psi.PsiField;
|
||||
|
||||
/**
|
||||
* This is an Element.
|
||||
* <p/>
|
||||
@@ -27,7 +29,8 @@ public interface Element {
|
||||
/**
|
||||
* Get's the elements accessor.
|
||||
* <p/>
|
||||
* <br/>If the element is a field the accessor is just the name of the field - example: <code>myField</code>
|
||||
* <br/>If the element is a field the accessor is just the of the field or name of it's accessor with () when useAccessor property is on
|
||||
* {@link ElementFactory#newFieldElement(PsiField, boolean)} - example: <code>myField</code> or <code>getMyField()</code>
|
||||
* <br/>If the element is a method the accessor is the methodname with () - example: <code>getMyField()</code>
|
||||
*
|
||||
* @return the accessor, null if none exists (only for a method with parameters).
|
||||
|
||||
+4
-1
@@ -17,6 +17,7 @@ package org.jetbrains.java.generate.element;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import org.jetbrains.java.generate.psi.PsiAdapter;
|
||||
|
||||
/**
|
||||
@@ -66,9 +67,11 @@ public class ElementFactory {
|
||||
* @param field the {@link com.intellij.psi.PsiField} to get the information from.
|
||||
* @return a new {@link FieldElement} object.
|
||||
*/
|
||||
public static FieldElement newFieldElement(PsiField field) {
|
||||
public static FieldElement newFieldElement(PsiField field, boolean useAccessor) {
|
||||
FieldElement fe = new FieldElement();
|
||||
fe.setName(field.getName());
|
||||
final PsiMethod getterForField = useAccessor ? PropertyUtil.findGetterForField(field) : null;
|
||||
fe.setAccessor(getterForField != null ? getterForField.getName() + "()" : field.getName());
|
||||
|
||||
if (PsiAdapter.isConstantField(field)) fe.setConstant(true);
|
||||
if (PsiAdapter.isEnumField(field)) fe.setEnum(true);
|
||||
|
||||
+14
-5
@@ -33,16 +33,23 @@ public class ElementUtils {
|
||||
/**
|
||||
* Gets the list of members to be put in the VelocityContext.
|
||||
*
|
||||
* @param members a list of {@link com.intellij.psi.PsiMember} objects.
|
||||
* @param members a list of {@link PsiMember} objects.
|
||||
* @param selectedNotNullMembers
|
||||
* @param useAccessors
|
||||
* @return a filtered list of only the fields as {@link FieldElement} objects.
|
||||
*/
|
||||
public static List<FieldElement> getOnlyAsFieldElements(Collection<? extends PsiMember> members) {
|
||||
public static List<FieldElement> getOnlyAsFieldElements(Collection<? extends PsiMember> members,
|
||||
Collection<? extends PsiMember> selectedNotNullMembers,
|
||||
boolean useAccessors) {
|
||||
List<FieldElement> fieldElementList = new ArrayList<FieldElement>();
|
||||
|
||||
for (PsiMember member : members) {
|
||||
if (member instanceof PsiField) {
|
||||
PsiField field = (PsiField) member;
|
||||
FieldElement fe = ElementFactory.newFieldElement(field);
|
||||
FieldElement fe = ElementFactory.newFieldElement(field, useAccessors);
|
||||
if (selectedNotNullMembers.contains(member)) {
|
||||
fe.setNotNull(true);
|
||||
}
|
||||
fieldElementList.add(fe);
|
||||
}
|
||||
}
|
||||
@@ -75,16 +82,18 @@ public class ElementUtils {
|
||||
*
|
||||
* @param members a list of {@link PsiMember} objects.
|
||||
* @param selectedNotNullMembers a list of @NotNull objects
|
||||
* @param useAccessors
|
||||
* @return a filtered list of only the methods as a {@link FieldElement} or {@link MethodElement} objects.
|
||||
*/
|
||||
public static List<Element> getOnlyAsFieldAndMethodElements(Collection<? extends PsiMember> members,
|
||||
Collection<? extends PsiMember> selectedNotNullMembers) {
|
||||
Collection<? extends PsiMember> selectedNotNullMembers,
|
||||
boolean useAccessors) {
|
||||
List<Element> elementList = new ArrayList<Element>();
|
||||
|
||||
for (PsiMember member : members) {
|
||||
AbstractElement element = null;
|
||||
if (member instanceof PsiField) {
|
||||
element = ElementFactory.newFieldElement((PsiField) member);
|
||||
element = ElementFactory.newFieldElement((PsiField) member, useAccessors);
|
||||
} else if (member instanceof PsiMethod) {
|
||||
element = ElementFactory.newMethodElement((PsiMethod) member);
|
||||
}
|
||||
|
||||
@@ -30,9 +30,10 @@ public class FieldElement extends AbstractElement implements Element {
|
||||
|
||||
private boolean isModifierTransient;
|
||||
private boolean isModifierVolatile;
|
||||
private String accessor;
|
||||
|
||||
public String getAccessor() {
|
||||
return name;
|
||||
public String getAccessor() {
|
||||
return accessor;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,4 +104,8 @@ public class FieldElement extends AbstractElement implements Element {
|
||||
", isModifierVolatile=" + isModifierVolatile +
|
||||
"}";
|
||||
}
|
||||
|
||||
public void setAccessor(String accessor) {
|
||||
this.accessor = accessor;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user