generate equals/hashCode: allow getters (IDEA-73860)

This commit is contained in:
Anna Kozlova
2015-01-13 12:48:00 +01:00
parent 2b03432618
commit 04b8cf4aa5
25 changed files with 337 additions and 79 deletions
@@ -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
@@ -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).
@@ -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);
@@ -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;
}
}