KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > codemanipulation > GenerateHashCodeEqualsOperation


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.codemanipulation;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import org.eclipse.text.edits.TextEdit;
20
21 import org.eclipse.core.runtime.Assert;
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.core.runtime.NullProgressMonitor;
26 import org.eclipse.core.runtime.OperationCanceledException;
27 import org.eclipse.core.runtime.Status;
28 import org.eclipse.core.runtime.SubProgressMonitor;
29 import org.eclipse.core.runtime.jobs.ISchedulingRule;
30
31 import org.eclipse.core.filebuffers.ITextFileBuffer;
32
33 import org.eclipse.core.resources.IWorkspaceRunnable;
34 import org.eclipse.core.resources.ResourcesPlugin;
35
36 import org.eclipse.jface.text.Document;
37 import org.eclipse.jface.text.IDocument;
38
39 import org.eclipse.ltk.core.refactoring.Change;
40
41 import org.eclipse.jdt.core.ICompilationUnit;
42 import org.eclipse.jdt.core.IJavaElement;
43 import org.eclipse.jdt.core.IMethod;
44 import org.eclipse.jdt.core.dom.AST;
45 import org.eclipse.jdt.core.dom.ASTNode;
46 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
47 import org.eclipse.jdt.core.dom.ArrayAccess;
48 import org.eclipse.jdt.core.dom.Assignment;
49 import org.eclipse.jdt.core.dom.Block;
50 import org.eclipse.jdt.core.dom.BodyDeclaration;
51 import org.eclipse.jdt.core.dom.CastExpression;
52 import org.eclipse.jdt.core.dom.CompilationUnit;
53 import org.eclipse.jdt.core.dom.ConditionalExpression;
54 import org.eclipse.jdt.core.dom.Expression;
55 import org.eclipse.jdt.core.dom.FieldAccess;
56 import org.eclipse.jdt.core.dom.ForStatement;
57 import org.eclipse.jdt.core.dom.IMethodBinding;
58 import org.eclipse.jdt.core.dom.ITypeBinding;
59 import org.eclipse.jdt.core.dom.IVariableBinding;
60 import org.eclipse.jdt.core.dom.IfStatement;
61 import org.eclipse.jdt.core.dom.InfixExpression;
62 import org.eclipse.jdt.core.dom.InstanceofExpression;
63 import org.eclipse.jdt.core.dom.Javadoc;
64 import org.eclipse.jdt.core.dom.MethodDeclaration;
65 import org.eclipse.jdt.core.dom.MethodInvocation;
66 import org.eclipse.jdt.core.dom.Modifier;
67 import org.eclipse.jdt.core.dom.Name;
68 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
69 import org.eclipse.jdt.core.dom.PostfixExpression;
70 import org.eclipse.jdt.core.dom.PrefixExpression;
71 import org.eclipse.jdt.core.dom.PrimitiveType;
72 import org.eclipse.jdt.core.dom.ReturnStatement;
73 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
74 import org.eclipse.jdt.core.dom.Statement;
75 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
76 import org.eclipse.jdt.core.dom.TagElement;
77 import org.eclipse.jdt.core.dom.TextElement;
78 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
79 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
80 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
81 import org.eclipse.jdt.core.dom.InfixExpression.Operator;
82 import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
83 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
84
85 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
86 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
87 import org.eclipse.jdt.internal.corext.dom.Bindings;
88 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
89 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
90 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
91 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringFileBuffers;
92 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
93
94 import org.eclipse.jdt.ui.CodeGeneration;
95
96 import org.eclipse.jdt.internal.ui.JavaPlugin;
97
98 /**
99  * <p>
100  * Workspace runnable to add implementations for
101  * <code>{@link java.lang.Object#equals(java.lang.Object)}</code> and
102  * <code>{@link java.lang.Object#hashCode()}</code>.
103  * </p>
104  *
105  * <p>
106  * This implementation creates a hashCode() and an equals() method intended to
107  * be used in value types: The implementation assumes that two objects are equal
108  * (and provide the same hashCode) if all values of all fields are equal.
109  * </p>
110  *
111  * <p>
112  * About the implementation:
113  * <ul>
114  * <li>To deal with reference types of fields and with supertypes, the
115  * implementation calls hashCode() and equals() on reference types of fields and
116  * on the superclass (except if the superclass is Object). It is an error if
117  * these types do not provide an equals() and hashCode() implementation and the
118  * comparison or hash code creation <strong>will fail</strong> if these methods
119  * are not correctly implemented.</li>
120  * <li>The implementation for primitive typed fields is the same as in the JDK
121  * implementations in the wrapper types (and the java.util.Arrays class).</li>
122  * <li>The equals() implementation uses equality of the declaring class instead
123  * of an instanceof check.</li>
124  * <li>A test for null in equals() is only implemented in direct subclasses of
125  * Object. This is only sufficient if every subimplementation calls
126  * super.equals() before any argument checks.</li>
127  * <li>Both equals() and hashCode() use methods from java.util.Arrays to test
128  * for equality and to generate a hash code for arrays. Note that this has an
129  * implication for Double and Float values (consider values -0.0 and 0.0 as well
130  * as border values like NaN and their equality in bit patterns) - however, the
131  * implementation is consistent with the wrapper types java.lang.Float and
132  * java.lang.Double.</li>
133  * </ul>
134  * </p>
135  *
136  * @since 3.2
137  */

138 public final class GenerateHashCodeEqualsOperation implements IWorkspaceRunnable {
139
140     private interface IHashCodeAccessProvider {
141
142         public Expression getThisAccess(String JavaDoc name);
143     }
144
145     private static final String JavaDoc JAVA_UTIL_ARRAYS= "java.util.Arrays"; //$NON-NLS-1$
146

147     private static final String JavaDoc BOOLEAN_TRUE_CONSTANT= "1231"; //$NON-NLS-1$
148

149     private static final String JavaDoc BOOLEAN_FALSE_CONSTANT= "1237"; //$NON-NLS-1$
150

151     private static final String JavaDoc JAVA_LANG_OBJECT= "java.lang.Object"; //$NON-NLS-1$
152

153     private static final String JavaDoc METHODNAME_GETCLASS= "getClass"; //$NON-NLS-1$
154

155     private static final String JavaDoc METHODNAME_EQUALS= "equals"; //$NON-NLS-1$
156

157     private static final String JavaDoc METHODNAME_HASH_CODE= "hashCode"; //$NON-NLS-1$
158

159     private static final String JavaDoc PRIME_NUMBER= "31"; //$NON-NLS-1$
160

161     private static final String JavaDoc INITIAL_HASHCODE_VALUE= "1"; //$NON-NLS-1$
162

163     private static final String JavaDoc VARIABLE_NAME_DOUBLE_TEMPORARY= "temp"; //$NON-NLS-1$
164

165     private static final String JavaDoc VARIABLE_NAME_PRIME= "prime"; //$NON-NLS-1$
166

167     private static final String JavaDoc VARIABLE_NAME_RESULT= "result"; //$NON-NLS-1$
168

169     private static final String JavaDoc VARIABLE_NAME_EQUALS_PARAM= "obj"; //$NON-NLS-1$
170

171     private static final String JavaDoc VARIABLE_NAME_HASHCODE_PARAM= "array"; //$NON-NLS-1$
172

173     private static final String JavaDoc VARIABLE_NAME_EQUALS_CASTED= "other"; //$NON-NLS-1$
174

175     private static final String JavaDoc VARIABLE_NAME_INDEX= "index"; //$NON-NLS-1$
176

177     /** Should the resulting edit be applied? */
178     private final boolean fApply;
179
180     /** The resulting text edit */
181     private TextEdit fEdit= null;
182
183     /** The insertion point, or <code>null</code> */
184     private final IJavaElement fInsert;
185
186     /** The variable binding keys to implement */
187     private final IVariableBinding[] fFields;
188
189     /** Should the regeneration of the methods be enforced? */
190     private final boolean fForce;
191
192     /** Should the compilation unit content be saved? */
193     private final boolean fSave;
194
195     /** The code generation settings to use */
196     private final CodeGenerationSettings fSettings;
197
198     /** The type declaration to add the methods to */
199     private final ITypeBinding fType;
200
201     /** The compilation unit ast node */
202     private final CompilationUnit fUnit;
203
204     /** The CURewrite to be used */
205     private final CompilationUnitRewrite fRewrite;
206
207     /** The ast to be used. Convenience accessor field */
208     private final AST fAst;
209
210     /** The number of double-typed fields handled so far */
211     private int fDoubleCount;
212
213     /** The primitive types to generate custom hashCode() methods for */
214     private Set JavaDoc fCustomHashCodeTypes= new HashSet JavaDoc();
215
216     /** <code>true</code> to use 'instanceof' to compare types, <code>false</code> otherwise */
217     private final boolean fUseInstanceOf;
218
219     /**
220      * Creates a new add hash code equals operation.
221      *
222      * @param type the type to add the methods to
223      * @param fields the method binding keys to implement
224      * @param unit the compilation unit ast node
225      * @param insert the insertion point, or <code>null</code>
226      * @param settings the code generation settings to use
227      * @param useInstanceof <code>true</code> to use 'instanceof' to compare types, <code>false</code> otherwise
228      * @param force <code>true</code> to force the regeneration of existing methods,
229      * <code>false</code> otherwise
230      * @param apply <code>true</code> if the resulting edit should be applied,
231      * <code>false</code> otherwise
232      * @param save <code>true</code> if the changed compilation unit should be
233      * saved, <code>false</code> otherwise
234      */

235     public GenerateHashCodeEqualsOperation(final ITypeBinding type, final IVariableBinding[] fields, final CompilationUnit unit,
236             final IJavaElement insert, final CodeGenerationSettings settings, final boolean useInstanceof, final boolean force, final boolean apply, final boolean save) {
237         Assert.isNotNull(type);
238         Assert.isNotNull(fields);
239         Assert.isNotNull(unit);
240         Assert.isNotNull(settings);
241         fType= type;
242         fInsert= insert;
243         fUnit= unit;
244         fFields= fields;
245         fSettings= settings;
246         fUseInstanceOf= useInstanceof;
247         fSave= save;
248         fApply= apply;
249         fDoubleCount= 0;
250         fRewrite= new CompilationUnitRewrite((ICompilationUnit) fUnit.getJavaElement(), fUnit);
251         fForce= force;
252         fAst= fRewrite.getAST();
253     }
254
255     /**
256      * Returns the resulting text edit.
257      *
258      * @return the resulting edit
259      */

260     public final TextEdit getResultingEdit() {
261         return fEdit;
262     }
263
264     /**
265      * Returns the scheduling rule for this operation.
266      *
267      * @return the scheduling rule
268      */

269     public final ISchedulingRule getSchedulingRule() {
270         return ResourcesPlugin.getWorkspace().getRoot();
271     }
272
273     /*
274      * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
275      */

276     public final void run(IProgressMonitor monitor) throws CoreException {
277         if (monitor == null)
278             monitor= new NullProgressMonitor();
279         try {
280             monitor.beginTask("", 1); //$NON-NLS-1$
281
monitor.setTaskName(CodeGenerationMessages.GenerateHashCodeEqualsOperation_description);
282
283             fCustomHashCodeTypes.clear();
284
285             // get the declaration and the rewrite
286
AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.findDeclaration(fType, fRewrite.getRoot());
287             ListRewrite rewriter= fRewrite.getASTRewrite().getListRewrite(declaration, declaration.getBodyDeclarationsProperty());
288
289             if (fType != null && rewriter != null) {
290
291                 ICompilationUnit cu= (ICompilationUnit) fUnit.getJavaElement();
292
293                 ITextFileBuffer buffer= null;
294                 IDocument document= null;
295                 try {
296                     if (!JavaModelUtil.isPrimary(cu))
297                         document= new Document(cu.getBuffer().getContents());
298                     else {
299                         buffer= RefactoringFileBuffers.acquire(cu);
300                         document= buffer.getDocument();
301                     }
302                     ASTNode insertion= null;
303                     if (fInsert instanceof IMethod)
304                         insertion= ASTNodes.getParent(NodeFinder.perform(fRewrite.getRoot(), ((IMethod) fInsert).getNameRange()),
305                                 MethodDeclaration.class);
306
307                     BodyDeclaration toReplace= null;
308                     if (fForce) {
309                         final List JavaDoc list= (List JavaDoc) declaration.getStructuralProperty(declaration.getBodyDeclarationsProperty());
310                         for (final Iterator JavaDoc iterator= list.iterator(); iterator.hasNext();) {
311                             final BodyDeclaration bodyDecl= (BodyDeclaration) iterator.next();
312                             if (bodyDecl instanceof MethodDeclaration) {
313                                 final MethodDeclaration method= (MethodDeclaration) bodyDecl;
314                                 final IMethodBinding binding= method.resolveBinding();
315                                 if (binding != null && binding.getName().equals(METHODNAME_EQUALS)) {
316                                     final ITypeBinding[] bindings= binding.getParameterTypes();
317                                     if (bindings.length == 1 && bindings[0].getQualifiedName().equals(JAVA_LANG_OBJECT)) {
318                                         toReplace= bodyDecl;
319                                         break;
320                                     }
321                                 }
322                             }
323                         }
324                     }
325                     // equals(..)
326
MethodDeclaration equalsMethod= createEqualsMethod();
327                     addMethod(rewriter, insertion, equalsMethod, toReplace);
328
329                     if (monitor.isCanceled())
330                         throw new OperationCanceledException();
331
332                     toReplace= null;
333                     if (fForce) {
334                         final List JavaDoc list= (List JavaDoc) declaration.getStructuralProperty(declaration.getBodyDeclarationsProperty());
335                         for (final Iterator JavaDoc iterator= list.iterator(); iterator.hasNext();) {
336                             final BodyDeclaration bodyDecl= (BodyDeclaration) iterator.next();
337                             if (bodyDecl instanceof MethodDeclaration) {
338                                 final MethodDeclaration method= (MethodDeclaration) bodyDecl;
339                                 final IMethodBinding binding= method.resolveBinding();
340                                 if (binding != null && binding.getName().equals(METHODNAME_HASH_CODE)) {
341                                     final ITypeBinding[] bindings= binding.getParameterTypes();
342                                     if (bindings.length == 0) {
343                                         toReplace= bodyDecl;
344                                         break;
345                                     }
346                                 }
347                             }
348                         }
349                     }
350                     // hashCode()
351
MethodDeclaration hashCodeMethod= createHashCodeMethod();
352                     addMethod(rewriter, equalsMethod, hashCodeMethod, toReplace);
353
354                     // helpers
355
MethodDeclaration previous= null;
356                     for (final Iterator JavaDoc iterator= fCustomHashCodeTypes.iterator(); iterator.hasNext();) {
357                         boolean found= false;
358                         final ITypeBinding binding= (ITypeBinding) iterator.next();
359                         final ITypeBinding typeBinding= declaration.resolveBinding();
360                         if (typeBinding != null) {
361                             final IMethodBinding[] bindings= typeBinding.getDeclaredMethods();
362                             for (int index= 0; index < bindings.length; index++) {
363                                 final IMethodBinding method= bindings[index];
364                                 final ITypeBinding[] parameters= method.getParameterTypes();
365                                 if (method.getName().equals(METHODNAME_HASH_CODE) && parameters.length == 1) {
366                                     final ITypeBinding parameter= parameters[0];
367                                     if (!parameter.isPrimitive()) {
368                                         found= parameter.getQualifiedName().equals(JAVA_LANG_OBJECT);
369                                     } else
370                                         found= parameter.isEqualTo(binding);
371                                     if (found)
372                                         break;
373                                 }
374                             }
375                         }
376                         if (!found) {
377                             final MethodDeclaration helperDecl= createHashCodeHelper(binding);
378                             addHelper(rewriter, previous, helperDecl);
379                         }
380                     }
381
382                     // add 'em
383
final Change result= fRewrite.createChange();
384                     if (result instanceof CompilationUnitChange) {
385                         final CompilationUnitChange change= (CompilationUnitChange) result;
386                         final TextEdit edit= change.getEdit();
387                         if (edit != null) {
388                             try {
389                                 fEdit= edit;
390                                 if (fApply)
391                                     edit.apply(document, TextEdit.UPDATE_REGIONS);
392                                 if (fSave) {
393                                     if (buffer != null)
394                                         buffer.commit(new SubProgressMonitor(monitor, 1), true);
395                                     else
396                                         cu.getBuffer().setContents(document.get());
397                                 }
398                             } catch (Exception JavaDoc exception) {
399                                 throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), 0, exception.getLocalizedMessage(),
400                                         exception));
401                             }
402                         }
403                     }
404                 } finally {
405                     if (buffer != null)
406                         RefactoringFileBuffers.release(cu);
407                 }
408             }
409         } finally {
410             monitor.done();
411         }
412     }
413
414     private void addHelper(ListRewrite rewriter, ASTNode insertion, MethodDeclaration stub) {
415         if (insertion != null)
416             rewriter.insertBefore(stub, insertion, null);
417         else
418             rewriter.insertFirst(stub, null);
419     }
420
421     private void addMethod(ListRewrite rewriter, ASTNode insertion, MethodDeclaration stub, BodyDeclaration replace) {
422         if (replace != null) {
423             rewriter.replace(replace, stub, null);
424         } else {
425         if (insertion != null)
426             rewriter.insertBefore(stub, insertion, null);
427         else
428             rewriter.insertLast(stub, null);
429         }
430     }
431
432     // ******************* HASHCODE *******************
433

434     private MethodDeclaration createHashCodeMethod() throws CoreException {
435
436         MethodDeclaration hashCodeMethod= fAst.newMethodDeclaration();
437         hashCodeMethod.modifiers().addAll(ASTNodeFactory.newModifiers(fAst, Modifier.PUBLIC));
438         hashCodeMethod.setName(fAst.newSimpleName(METHODNAME_HASH_CODE));
439         hashCodeMethod.setConstructor(false);
440         hashCodeMethod.setReturnType2(fAst.newPrimitiveType(PrimitiveType.INT));
441
442         Block body= fAst.newBlock();
443         hashCodeMethod.setBody(body);
444
445         // PRIME NUMBER
446
VariableDeclarationFragment frag= fAst.newVariableDeclarationFragment();
447         frag.setName(fAst.newSimpleName(VARIABLE_NAME_PRIME));
448         frag.setInitializer(fAst.newNumberLiteral(PRIME_NUMBER));
449
450         VariableDeclarationStatement primeNumberDeclaration= fAst.newVariableDeclarationStatement(frag);
451         primeNumberDeclaration.modifiers().add(fAst.newModifier(ModifierKeyword.FINAL_KEYWORD));
452         primeNumberDeclaration.setType(fAst.newPrimitiveType(PrimitiveType.INT));
453         body.statements().add(primeNumberDeclaration);
454
455         // RESULT
456
VariableDeclarationFragment fragment= fAst.newVariableDeclarationFragment();
457         fragment.setName(fAst.newSimpleName(VARIABLE_NAME_RESULT));
458
459         VariableDeclarationStatement resultDeclaration= fAst.newVariableDeclarationStatement(fragment);
460         resultDeclaration.setType(fAst.newPrimitiveType(PrimitiveType.INT));
461         body.statements().add(resultDeclaration);
462
463         if (needsNoSuperCall(fType, METHODNAME_HASH_CODE, new ITypeBinding[0])) {
464             fragment.setInitializer(fAst.newNumberLiteral(INITIAL_HASHCODE_VALUE));
465         } else {
466             SuperMethodInvocation invoc= fAst.newSuperMethodInvocation();
467             invoc.setName(fAst.newSimpleName(METHODNAME_HASH_CODE));
468             fragment.setInitializer(invoc);
469         }
470
471         for (int i= 0; i < fFields.length; i++) {
472             if (fFields[i].getType().isPrimitive()) {
473                 Statement[] sts= createAddSimpleHashCode(fFields[i].getType(), new IHashCodeAccessProvider() {
474                 
475                     public Expression getThisAccess(String JavaDoc name) {
476                         return getThisAccessForHashCode(name);
477                     }
478                 
479                 }, fFields[i].getName(), false);
480                 for (int j= 0; j < sts.length; j++) {
481                     body.statements().add(sts[j]);
482                 }
483             } else if (fFields[i].getType().isArray())
484                 body.statements().add(createAddArrayHashCode(fFields[i]));
485             else
486                 body.statements().add(createAddQualifiedHashCode(fFields[i]));
487         }
488
489         // the last return:
490
ReturnStatement endReturn= fAst.newReturnStatement();
491         endReturn.setExpression(fAst.newSimpleName(VARIABLE_NAME_RESULT));
492         body.statements().add(endReturn);
493
494         // method comment
495
if (fSettings != null) {
496             ITypeBinding object= fAst.resolveWellKnownType(JAVA_LANG_OBJECT);
497             IMethodBinding[] objms= object.getDeclaredMethods();
498             IMethodBinding objectMethod= null;
499             for (int i= 0; i < objms.length; i++) {
500                 if (objms[i].getName().equals(METHODNAME_HASH_CODE) && objms[i].getParameterTypes().length == 0)
501                     objectMethod= objms[i];
502             }
503             createMethodComment(hashCodeMethod, objectMethod);
504         }
505
506         return hashCodeMethod;
507     }
508
509
510     private Statement[] createAddSimpleHashCode(ITypeBinding type, IHashCodeAccessProvider provider, String JavaDoc name, boolean singleTemp) {
511
512         List JavaDoc statements= new ArrayList JavaDoc();
513
514         if (!type.isPrimitive()) {
515             // (element == null ? 0 : element.hashCode())
516
ConditionalExpression ce= fAst.newConditionalExpression();
517             InfixExpression exp= fAst.newInfixExpression();
518             ArrayAccess access= fAst.newArrayAccess();
519             access.setArray(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM));
520             access.setIndex(fAst.newSimpleName(VARIABLE_NAME_INDEX));
521             exp.setLeftOperand(access);
522             exp.setOperator(Operator.EQUALS);
523             exp.setRightOperand(fAst.newNullLiteral());
524             ce.setExpression(exp);
525             ce.setThenExpression(fAst.newNumberLiteral("0")); //$NON-NLS-1$
526
MethodInvocation invoc= fAst.newMethodInvocation();
527             access= fAst.newArrayAccess();
528             access.setArray(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM));
529             access.setIndex(fAst.newSimpleName(VARIABLE_NAME_INDEX));
530             invoc.setExpression(access);
531             invoc.setName(fAst.newSimpleName(METHODNAME_HASH_CODE));
532             ce.setElseExpression(invoc);
533             statements.add(prepareAssignment(parenthesize(ce)));
534         } else if (isPrimitiveType(type, PrimitiveType.BOOLEAN)) {
535             ConditionalExpression ce= fAst.newConditionalExpression();
536             ce.setExpression(provider.getThisAccess(name));
537             // see Boolean.hashCode(boolean)
538
ce.setThenExpression(fAst.newNumberLiteral(BOOLEAN_TRUE_CONSTANT));
539             ce.setElseExpression(fAst.newNumberLiteral(BOOLEAN_FALSE_CONSTANT));
540             statements.add(prepareAssignment(parenthesize(ce)));
541         } else if (isPrimitiveType(type, new PrimitiveType.Code[] { PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.SHORT })) {
542             statements.add(prepareAssignment(provider.getThisAccess(name)));
543         } else if (isPrimitiveType(type, PrimitiveType.FLOAT)) {
544             // Float.floatToIntBits(aFloat)
545
statements.add(prepareAssignment(createFloatInvocation(provider.getThisAccess(name))));
546         } else if (isPrimitiveType(type, PrimitiveType.LONG)) {
547             statements.add(prepareAssignment(createShiftAssignment(provider.getThisAccess(name), provider.getThisAccess(name))));
548         } else if (isPrimitiveType(type, PrimitiveType.DOUBLE)) {
549
550             VariableDeclarationFragment fragment= null;
551             if (singleTemp || fDoubleCount == 0) {
552                 fragment= fAst.newVariableDeclarationFragment();
553                 fragment.setName(fAst.newSimpleName(VARIABLE_NAME_DOUBLE_TEMPORARY));
554
555                 VariableDeclarationStatement st2= fAst.newVariableDeclarationStatement(fragment);
556                 st2.setType(fAst.newPrimitiveType(PrimitiveType.LONG));
557                 statements.add(st2);
558             }
559             fDoubleCount++;
560
561             // Double.doubleToIntBits(aDouble)
562
Expression comparison= createDoubleInvocation(provider.getThisAccess(name));
563
564             if (singleTemp)
565                 fragment.setInitializer(comparison);
566             else {
567                 Assignment ass= fAst.newAssignment();
568                 ass.setLeftHandSide(fAst.newSimpleName(VARIABLE_NAME_DOUBLE_TEMPORARY));
569                 ass.setRightHandSide(comparison);
570                 statements.add(fAst.newExpressionStatement(ass));
571             }
572             statements.add(prepareAssignment(createShiftAssignment(fAst.newSimpleName(VARIABLE_NAME_DOUBLE_TEMPORARY), fAst.newSimpleName(VARIABLE_NAME_DOUBLE_TEMPORARY))));
573         }
574
575         return (Statement[]) statements.toArray(new Statement[statements.size()]);
576     }
577
578     private Statement createAddArrayHashCode(IVariableBinding binding) {
579         MethodInvocation invoc= fAst.newMethodInvocation();
580         if (JavaModelUtil.is50OrHigher(fRewrite.getCu().getJavaProject())) {
581             invoc.setName(fAst.newSimpleName(METHODNAME_HASH_CODE));
582             invoc.setExpression(getQualifiedName(JAVA_UTIL_ARRAYS));
583             invoc.arguments().add(getThisAccessForHashCode(binding.getName()));
584         } else {
585             invoc.setName(fAst.newSimpleName(METHODNAME_HASH_CODE));
586             final IJavaElement element= fType.getJavaElement();
587             if (element != null && !"".equals(element.getElementName())) //$NON-NLS-1$
588
invoc.setExpression(fAst.newSimpleName(element.getElementName()));
589             invoc.arguments().add(getThisAccessForHashCode(binding.getName()));
590             final ITypeBinding type= binding.getType().getElementType();
591             if (!Bindings.isVoidType(type)) {
592                 if (type.isPrimitive() && binding.getType().getDimensions() < 2)
593                     fCustomHashCodeTypes.add(type);
594                 else
595                     fCustomHashCodeTypes.add(fAst.resolveWellKnownType(JAVA_LANG_OBJECT));
596             }
597         }
598         return prepareAssignment(invoc);
599     }
600
601     private MethodDeclaration createHashCodeHelper(ITypeBinding binding) {
602         Assert.isTrue(!binding.isArray());
603
604         MethodDeclaration hashCodeMethod= fAst.newMethodDeclaration();
605         hashCodeMethod.modifiers().addAll(ASTNodeFactory.newModifiers(fAst, Modifier.PRIVATE | Modifier.STATIC));
606         hashCodeMethod.setName(fAst.newSimpleName(METHODNAME_HASH_CODE));
607         hashCodeMethod.setConstructor(false);
608         hashCodeMethod.setReturnType2(fAst.newPrimitiveType(PrimitiveType.INT));
609
610         // ARGUMENTS
611
List JavaDoc parameters= hashCodeMethod.parameters();
612         SingleVariableDeclaration hashCodeParam= fAst.newSingleVariableDeclaration();
613         if (!binding.isPrimitive())
614             hashCodeParam.setType(fAst.newArrayType(fAst.newSimpleType(getQualifiedName(JAVA_LANG_OBJECT)), 1));
615         else
616             hashCodeParam.setType(fAst.newArrayType(fAst.newPrimitiveType(PrimitiveType.toCode(binding.getName())), 1));
617         hashCodeParam.setName(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM));
618         parameters.add(hashCodeParam);
619
620         Block body= fAst.newBlock();
621         hashCodeMethod.setBody(body);
622
623         // PRIME NUMBER
624
VariableDeclarationFragment frag= fAst.newVariableDeclarationFragment();
625         frag.setName(fAst.newSimpleName(VARIABLE_NAME_PRIME));
626         frag.setInitializer(fAst.newNumberLiteral(PRIME_NUMBER));
627
628         VariableDeclarationStatement primeNumberDeclaration= fAst.newVariableDeclarationStatement(frag);
629         primeNumberDeclaration.modifiers().add(fAst.newModifier(ModifierKeyword.FINAL_KEYWORD));
630         primeNumberDeclaration.setType(fAst.newPrimitiveType(PrimitiveType.INT));
631         body.statements().add(primeNumberDeclaration);
632
633         // IF STATEMENT
634
IfStatement ifStatement= fAst.newIfStatement();
635         final InfixExpression newInfixExpression= fAst.newInfixExpression();
636         newInfixExpression.setLeftOperand(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM));
637         newInfixExpression.setRightOperand(fAst.newNullLiteral());
638         newInfixExpression.setOperator(Operator.EQUALS);
639         ifStatement.setExpression(newInfixExpression);
640         final ReturnStatement returnStatement= fAst.newReturnStatement();
641         returnStatement.setExpression(fAst.newNumberLiteral("0")); //$NON-NLS-1$
642
ifStatement.setThenStatement(returnStatement);
643         body.statements().add(ifStatement);
644
645         // RESULT
646
VariableDeclarationFragment resultFragment= fAst.newVariableDeclarationFragment();
647         resultFragment.setName(fAst.newSimpleName(VARIABLE_NAME_RESULT));
648         resultFragment.setInitializer(fAst.newNumberLiteral(INITIAL_HASHCODE_VALUE));
649         VariableDeclarationStatement resultDeclaration= fAst.newVariableDeclarationStatement(resultFragment);
650         resultDeclaration.setType(fAst.newPrimitiveType(PrimitiveType.INT));
651         body.statements().add(resultDeclaration);
652
653         // FOR LOOP
654
ForStatement forStatement= fAst.newForStatement();
655         
656         VariableDeclarationFragment indexDeclaration= fAst.newVariableDeclarationFragment();
657         indexDeclaration.setName(fAst.newSimpleName(VARIABLE_NAME_INDEX));
658         indexDeclaration.setInitializer(fAst.newNumberLiteral("0")); //$NON-NLS-1$
659
final VariableDeclarationExpression declExpression= fAst.newVariableDeclarationExpression(indexDeclaration);
660         declExpression.setType(fAst.newPrimitiveType(PrimitiveType.INT));
661         forStatement.initializers().add(declExpression);
662         InfixExpression infixExpr= fAst.newInfixExpression();
663         infixExpr.setLeftOperand(fAst.newSimpleName(VARIABLE_NAME_INDEX));
664         FieldAccess access= fAst.newFieldAccess();
665         access.setExpression(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM));
666         access.setName(fAst.newSimpleName("length")); //$NON-NLS-1$
667
infixExpr.setRightOperand(access);
668         infixExpr.setOperator(Operator.LESS);
669         forStatement.setExpression(infixExpr);
670         PostfixExpression postfixExpr= fAst.newPostfixExpression();
671         postfixExpr.setOperand(fAst.newSimpleName(VARIABLE_NAME_INDEX));
672         postfixExpr.setOperator(org.eclipse.jdt.core.dom.PostfixExpression.Operator.INCREMENT);
673         forStatement.updaters().add(postfixExpr);
674         body.statements().add(forStatement);
675         
676         Block forBody= fAst.newBlock();
677         Statement[] statements= createAddSimpleHashCode(binding, new IHashCodeAccessProvider() {
678         
679             public Expression getThisAccess(String JavaDoc name) {
680                 ArrayAccess a= fAst.newArrayAccess();
681                 a.setArray(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM));
682                 a.setIndex(fAst.newSimpleName(name));
683                 return a;
684             }
685         }, VARIABLE_NAME_INDEX, true);
686         for (int index= 0; index < statements.length; index++) {
687             forBody.statements().add(statements[index]);
688         }
689         forStatement.setBody(forBody);
690         
691         // END RETURN
692
ReturnStatement endReturn= fAst.newReturnStatement();
693         endReturn.setExpression(fAst.newSimpleName(VARIABLE_NAME_RESULT));
694         body.statements().add(endReturn);
695
696         // COMMENT
697
if (fSettings != null && fSettings.createComments) {
698             Javadoc javadoc= fAst.newJavadoc();
699             final TagElement tagComment= fAst.newTagElement();
700             TextElement text= fAst.newTextElement();
701             text.setText(CodeGenerationMessages.GenerateHashCodeEqualsOperation_hash_code_comment);
702             tagComment.fragments().add(text);
703             javadoc.tags().add(tagComment);
704             final TagElement tagParam= fAst.newTagElement();
705             tagParam.setTagName(CodeGenerationMessages.GenerateHashCodeEqualsOperation_tag_param);
706             tagParam.fragments().add(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM));
707             text= fAst.newTextElement();
708             text.setText(CodeGenerationMessages.GenerateHashCodeEqualsOperation_hash_code_argument);
709             tagParam.fragments().add(text);
710             javadoc.tags().add(tagParam);
711             final TagElement tagReturn= fAst.newTagElement();
712             tagReturn.setTagName(CodeGenerationMessages.GenerateHashCodeEqualsOperation_tag_return);
713             text= fAst.newTextElement();
714             text.setText(CodeGenerationMessages.GenerateHashCodeEqualsOperation_return_comment);
715             tagReturn.fragments().add(text);
716             javadoc.tags().add(tagReturn);
717             hashCodeMethod.setJavadoc(javadoc);
718         }
719         return hashCodeMethod;
720     }
721
722     private Statement createAddQualifiedHashCode(IVariableBinding binding) {
723
724         MethodInvocation invoc= fAst.newMethodInvocation();
725         invoc.setExpression(getThisAccessForHashCode(binding.getName()));
726         invoc.setName(fAst.newSimpleName(METHODNAME_HASH_CODE));
727
728         InfixExpression expr= fAst.newInfixExpression();
729         expr.setOperator(Operator.EQUALS);
730         expr.setLeftOperand(getThisAccessForHashCode(binding.getName()));
731         expr.setRightOperand(fAst.newNullLiteral());
732
733         ConditionalExpression cexpr= fAst.newConditionalExpression();
734         cexpr.setThenExpression(fAst.newNumberLiteral("0")); //$NON-NLS-1$
735
cexpr.setElseExpression(invoc);
736         cexpr.setExpression(parenthesize(expr));
737
738         return prepareAssignment(parenthesize(cexpr));
739     }
740
741     private Expression createShiftAssignment(Expression shift1, Expression shift2) {
742         // (int)(element ^ (element >>> 32));
743
// see implementation in Arrays.hashCode(), Double.hashCode() and
744
// Long.hashCode()
745
CastExpression ce= fAst.newCastExpression();
746         ce.setType(fAst.newPrimitiveType(PrimitiveType.INT));
747
748         InfixExpression unsignedShiftRight= fAst.newInfixExpression();
749         unsignedShiftRight.setLeftOperand(shift1);
750         unsignedShiftRight.setRightOperand(fAst.newNumberLiteral("32")); //$NON-NLS-1$
751
unsignedShiftRight.setOperator(Operator.RIGHT_SHIFT_UNSIGNED);
752
753         InfixExpression xor= fAst.newInfixExpression();
754         xor.setLeftOperand(shift2);
755         xor.setRightOperand(parenthesize(unsignedShiftRight));
756         xor.setOperator(InfixExpression.Operator.XOR);
757
758         ce.setExpression(parenthesize(xor));
759         return ce;
760     }
761
762     private Statement prepareAssignment(Expression rightHand) {
763         // result = PRIME*result + (...)
764
InfixExpression mul= fAst.newInfixExpression();
765         mul.setLeftOperand(fAst.newSimpleName(VARIABLE_NAME_PRIME));
766         mul.setRightOperand(fAst.newSimpleName(VARIABLE_NAME_RESULT));
767         mul.setOperator(Operator.TIMES);
768
769         Assignment ass= fAst.newAssignment();
770         ass.setLeftHandSide(fAst.newSimpleName(VARIABLE_NAME_RESULT));
771
772         InfixExpression plus= fAst.newInfixExpression();
773         plus.setLeftOperand(mul);
774         plus.setOperator(Operator.PLUS);
775         plus.setRightOperand(rightHand);
776
777         ass.setRightHandSide(plus);
778
779         return fAst.newExpressionStatement(ass);
780     }
781
782     // *************** EQUALS ***************
783

784     private MethodDeclaration createEqualsMethod() throws CoreException {
785
786         MethodDeclaration equalsMethodDeclaration= fAst.newMethodDeclaration();
787         equalsMethodDeclaration.modifiers().addAll(ASTNodeFactory.newModifiers(fAst, Modifier.PUBLIC));
788         equalsMethodDeclaration.setName(fAst.newSimpleName(METHODNAME_EQUALS));
789         equalsMethodDeclaration.setConstructor(false);
790         equalsMethodDeclaration.setReturnType2(fAst.newPrimitiveType(PrimitiveType.BOOLEAN));
791
792         List JavaDoc parameters= equalsMethodDeclaration.parameters();
793         SingleVariableDeclaration equalsParam= fAst.newSingleVariableDeclaration();
794         equalsParam.setType(fAst.newSimpleType(fAst.newSimpleName("Object"))); //$NON-NLS-1$
795
equalsParam.setName(fAst.newSimpleName(VARIABLE_NAME_EQUALS_PARAM));
796         parameters.add(equalsParam);
797
798         Block body= fAst.newBlock();
799         equalsMethodDeclaration.setBody(body);
800
801         // if (this == obj) return true;
802
body.statements().add(
803                 createReturningIfStatement(fAst.newThisExpression(), fAst.newSimpleName(VARIABLE_NAME_EQUALS_PARAM), Operator.EQUALS, true));
804
805         if (needsNoSuperCall(fType, METHODNAME_EQUALS, new ITypeBinding[] {fAst.resolveWellKnownType(JAVA_LANG_OBJECT)})) {
806             // if (obj == null) return false;
807
body.statements().add(
808                     createReturningIfStatement(fAst.newSimpleName(VARIABLE_NAME_EQUALS_PARAM), fAst.newNullLiteral(), Operator.EQUALS, false));
809
810         } else {
811             // if (!super.equals(obj)) return false;
812
SuperMethodInvocation superEqualsCall= fAst.newSuperMethodInvocation();
813             superEqualsCall.setName(fAst.newSimpleName(METHODNAME_EQUALS));
814             superEqualsCall.arguments().add(fAst.newSimpleName(VARIABLE_NAME_EQUALS_PARAM));
815
816             PrefixExpression pe= fAst.newPrefixExpression();
817             pe.setOperator(PrefixExpression.Operator.NOT);
818             pe.setOperand(superEqualsCall);
819
820             IfStatement superEqualsIf= fAst.newIfStatement();
821             superEqualsIf.setExpression(pe);
822             superEqualsIf.setThenStatement(getReturnFalse());
823
824             body.statements().add(superEqualsIf);
825         }
826
827         if (fUseInstanceOf) {
828             // if (!(obj instanceof Type)) return false;
829
InstanceofExpression expression= fAst.newInstanceofExpression();
830             expression.setLeftOperand(fAst.newSimpleName(VARIABLE_NAME_EQUALS_PARAM));
831             expression.setRightOperand(fRewrite.getImportRewrite().addImport(fType, fAst));
832
833             PrefixExpression notExpression= fAst.newPrefixExpression();
834             notExpression.setOperator(org.eclipse.jdt.core.dom.PrefixExpression.Operator.NOT);
835             
836             ParenthesizedExpression parenthesizedExpression= fAst.newParenthesizedExpression();
837             parenthesizedExpression.setExpression(expression);
838             
839             notExpression.setOperand(parenthesizedExpression);
840
841             body.statements().add(createReturningIfStatement(false, notExpression));
842         } else {
843             // if (getClass() != obj.getClass()) return false;
844
MethodInvocation thisClass= fAst.newMethodInvocation();
845             thisClass.setName(fAst.newSimpleName(METHODNAME_GETCLASS));
846
847             MethodInvocation objGetClass= fAst.newMethodInvocation();
848             objGetClass.setExpression(fAst.newSimpleName(VARIABLE_NAME_EQUALS_PARAM));
849             objGetClass.setName(fAst.newSimpleName(METHODNAME_GETCLASS));
850
851             body.statements().add(createReturningIfStatement(thisClass, objGetClass, Operator.NOT_EQUALS, false));
852         }
853         
854         // Type other= (Type) obj;
855
VariableDeclarationFragment sd= fAst.newVariableDeclarationFragment();
856         sd.setName(fAst.newSimpleName(VARIABLE_NAME_EQUALS_CASTED));
857
858         CastExpression cast= fAst.newCastExpression();
859         cast.setType(fAst.newSimpleType(fAst.newSimpleName(fType.getName())));
860         cast.setExpression(fAst.newSimpleName(VARIABLE_NAME_EQUALS_PARAM));
861         sd.setInitializer(cast);
862
863         VariableDeclarationStatement otherDeclaration= fAst.newVariableDeclarationStatement(sd);
864         otherDeclaration.setType(fAst.newSimpleType(fAst.newSimpleName(fType.getName())));
865         otherDeclaration.modifiers().add(fAst.newModifier(ModifierKeyword.FINAL_KEYWORD));
866
867         body.statements().add(otherDeclaration);
868
869         for (int i= 0; i < fFields.length; i++) {
870             if (fFields[i].getType().isPrimitive())
871                 body.statements().add(createSimpleComparison(fFields[i]));
872             else if (fFields[i].getType().isArray())
873                 body.statements().add(createArrayComparison(fFields[i].getName()));
874             else
875                 body.statements().add(createQualifiedComparison(fFields[i].getName()));
876         }
877
878         // the last return true:
879
ReturnStatement endReturn= fAst.newReturnStatement();
880         endReturn.setExpression(fAst.newBooleanLiteral(true));
881
882         body.statements().add(endReturn);
883
884         // method comment
885
if (fSettings != null) {
886             ITypeBinding object= fAst.resolveWellKnownType(JAVA_LANG_OBJECT);
887             IMethodBinding[] objms= object.getDeclaredMethods();
888             IMethodBinding objectMethod= null;
889             for (int i= 0; i < objms.length; i++) {
890                 if (objms[i].getName().equals(METHODNAME_EQUALS) && objms[i].getParameterTypes().length == 1
891                         && objms[i].getParameterTypes()[0].getQualifiedName().equals(JAVA_LANG_OBJECT))
892                     objectMethod= objms[i];
893             }
894             createMethodComment(equalsMethodDeclaration, objectMethod);
895         }
896
897         return equalsMethodDeclaration;
898     }
899
900     private Statement createSimpleComparison(IVariableBinding binding) {
901         if (isPrimitiveType(binding.getType(), PrimitiveType.FLOAT)) {
902             return createReturningIfStatement(createFloatInvocation(getThisAccessForEquals(binding.getName())), createFloatInvocation(getOtherAccess(binding
903                     .getName())), Operator.NOT_EQUALS, false);
904         } else if (isPrimitiveType(binding.getType(), PrimitiveType.DOUBLE)) {
905             return createReturningIfStatement(createDoubleInvocation(getThisAccessForEquals(binding.getName())), createDoubleInvocation(getOtherAccess(binding
906                     .getName())), Operator.NOT_EQUALS, false);
907         } else
908             return createReturningIfStatement(getThisAccessForEquals(binding.getName()), getOtherAccess(binding.getName()), Operator.NOT_EQUALS, false);
909     }
910
911     private Statement createArrayComparison(String JavaDoc name) {
912         MethodInvocation invoc= fAst.newMethodInvocation();
913         invoc.setName(fAst.newSimpleName(METHODNAME_EQUALS));
914         invoc.setExpression(getQualifiedName(JAVA_UTIL_ARRAYS));
915         invoc.arguments().add(getThisAccessForEquals(name));
916         invoc.arguments().add(getOtherAccess(name));
917
918         PrefixExpression pe= fAst.newPrefixExpression();
919         pe.setOperator(PrefixExpression.Operator.NOT);
920         pe.setOperand(invoc);
921
922         IfStatement ifSt= fAst.newIfStatement();
923         ifSt.setExpression(pe);
924         ifSt.setThenStatement(getReturnFalse());
925
926         return ifSt;
927     }
928
929     /**
930      * Creates a comparison of reference types.
931      *
932      * <pre>
933      * if (this.a == null) {
934      * if (other.a != null)
935      * return false;
936      * } else {
937      * if (!this.a.equals(other.a))
938      * return false;
939      * }
940      * </pre>
941      * @param name the field name
942      * @return the comparison statement
943      */

944     private Statement createQualifiedComparison(String JavaDoc name) {
945         InfixExpression newCondition= fAst.newInfixExpression();
946         newCondition.setOperator(Operator.EQUALS);
947         newCondition.setLeftOperand(getThisAccessForEquals(name));
948         newCondition.setRightOperand(fAst.newNullLiteral());
949
950         // THEN
951
InfixExpression notEqNull= fAst.newInfixExpression();
952         notEqNull.setOperator(Operator.NOT_EQUALS);
953         notEqNull.setLeftOperand(getOtherAccess(name));
954         notEqNull.setRightOperand(fAst.newNullLiteral());
955
956         IfStatement thenPart= fAst.newIfStatement();
957         thenPart.setExpression(notEqNull);
958         thenPart.setThenStatement(getReturnFalse());
959
960         Block thenPart2= fAst.newBlock();
961         thenPart2.statements().add(thenPart);
962
963         // ELSE
964
MethodInvocation invoc= fAst.newMethodInvocation();
965         invoc.setName(fAst.newSimpleName(METHODNAME_EQUALS));
966         invoc.setExpression(getThisAccessForEquals(name));
967         invoc.arguments().add(getOtherAccess(name));
968
969         PrefixExpression pe= fAst.newPrefixExpression();
970         pe.setOperator(PrefixExpression.Operator.NOT);
971         pe.setOperand(invoc);
972
973         IfStatement elsePart= fAst.newIfStatement();
974         elsePart.setExpression(pe);
975         elsePart.setThenStatement(getReturnFalse());
976
977         // ALL
978
IfStatement isNull= fAst.newIfStatement();
979         isNull.setExpression(newCondition);
980         isNull.setThenStatement(thenPart2);
981         isNull.setElseStatement(elsePart);
982
983         return isNull;
984     }
985
986     // ************************ HELPERS **************************
987

988     private Statement createReturningIfStatement(Expression left, Expression right, Operator operator, boolean whatToReturn) {
989         InfixExpression newCondition= fAst.newInfixExpression();
990         newCondition.setOperator(operator);
991         newCondition.setLeftOperand(left);
992         newCondition.setRightOperand(right);
993         return createReturningIfStatement(whatToReturn, newCondition);
994     }
995
996     private Statement createReturningIfStatement(boolean result, Expression condition) {
997         IfStatement firstIf= fAst.newIfStatement();
998         firstIf.setExpression(condition);
999
1000        ReturnStatement returner= fAst.newReturnStatement();
1001        returner.setExpression(fAst.newBooleanLiteral(result));
1002        firstIf.setThenStatement(returner);
1003        return firstIf;
1004    }
1005
1006    private void createMethodComment(MethodDeclaration newDeclaration, IMethodBinding copyFrom) throws CoreException {
1007        if (fSettings.createComments) {
1008            String JavaDoc string= CodeGeneration.getMethodComment(fRewrite.getCu(), fType.getQualifiedName(), newDeclaration, copyFrom, StubUtility.getLineDelimiterUsed(fRewrite.getCu()));
1009            if (string != null) {
1010                Javadoc javadoc= (Javadoc) fRewrite.getASTRewrite().createStringPlaceholder(string, ASTNode.JAVADOC);
1011                newDeclaration.setJavadoc(javadoc);
1012            }
1013        }
1014        if (fSettings.overrideAnnotation && JavaModelUtil.is50OrHigher(fUnit.getJavaElement().getJavaProject()))
1015            StubUtility2.addOverrideAnnotation(fRewrite.getASTRewrite(), newDeclaration, copyFrom);
1016    }
1017
1018    private boolean needsNoSuperCall(ITypeBinding typeBinding, String JavaDoc name, ITypeBinding[] parameters) {
1019        Assert.isNotNull(typeBinding);
1020        IMethodBinding binding= Bindings.findMethodInHierarchy(typeBinding.getSuperclass(), name, parameters);
1021        if (binding != null) {
1022            ITypeBinding declaring= binding.getDeclaringClass();
1023            return declaring.getQualifiedName().equals(JAVA_LANG_OBJECT);
1024        }
1025        return true;
1026    }
1027
1028
1029    private Expression getThisAccessForEquals(String JavaDoc name) {
1030        return getThisAccess(name, false);
1031    }
1032
1033    private Expression getThisAccessForHashCode(String JavaDoc name) {
1034        return getThisAccess(name, true);
1035    }
1036
1037    private Expression getThisAccess(String JavaDoc name, boolean forHashCode) {
1038        if (fSettings.useKeywordThis || needsThisQualification(name, forHashCode)) {
1039            FieldAccess fa= fAst.newFieldAccess();
1040            fa.setExpression(fAst.newThisExpression());
1041            fa.setName(fAst.newSimpleName(name));
1042            return fa;
1043        }
1044        return fAst.newSimpleName(name);
1045    }
1046
1047    private Expression getOtherAccess(String JavaDoc name) {
1048        return fAst.newQualifiedName(fAst.newSimpleName(VARIABLE_NAME_EQUALS_CASTED), fAst.newSimpleName(name));
1049    }
1050
1051    private boolean isPrimitiveType(ITypeBinding binding, PrimitiveType.Code code) {
1052        return (binding.getName().equals(code.toString()));
1053    }
1054
1055    private boolean isPrimitiveType(ITypeBinding type, PrimitiveType.Code[] codes) {
1056        for (int i= 0; i < codes.length; i++) {
1057            PrimitiveType.Code code= codes[i];
1058            if (isPrimitiveType(type, code))
1059                return true;
1060        }
1061        return false;
1062    }
1063
1064    private Name getQualifiedName(String JavaDoc name) {
1065        String JavaDoc importedType= fRewrite.getImportRewrite().addImport(name);
1066        return ASTNodeFactory.newName(fAst, importedType);
1067    }
1068
1069    private ReturnStatement getReturnFalse() {
1070        ReturnStatement falseReturn= fAst.newReturnStatement();
1071        falseReturn.setExpression(fAst.newBooleanLiteral(false));
1072        return falseReturn;
1073    }
1074
1075    private Expression parenthesize(Expression expression) {
1076        ParenthesizedExpression pe= fAst.newParenthesizedExpression();
1077        pe.setExpression(expression);
1078        return pe;
1079    }
1080
1081    private Expression createFloatInvocation(Expression access) {
1082        return createMethodInvocation(access, "java.lang.Float", "floatToIntBits"); //$NON-NLS-1$ //$NON-NLS-2$
1083
}
1084
1085    private Expression createDoubleInvocation(Expression access) {
1086        return createMethodInvocation(access, "java.lang.Double", "doubleToLongBits"); //$NON-NLS-1$ //$NON-NLS-2$
1087
}
1088
1089    private Expression createMethodInvocation(Expression access, String JavaDoc qualifiedClassName, String JavaDoc methodName) {
1090        MethodInvocation invoc= fAst.newMethodInvocation();
1091        invoc.setExpression(getQualifiedName(qualifiedClassName));
1092        invoc.setName(fAst.newSimpleName(methodName));
1093        invoc.arguments().add(access);
1094        return invoc;
1095    }
1096
1097    private boolean needsThisQualification(String JavaDoc name, boolean isHashCode) {
1098        if (isHashCode)
1099            return ( (fDoubleCount > 0 && name.equals(VARIABLE_NAME_DOUBLE_TEMPORARY)) || (name.equals(VARIABLE_NAME_PRIME)) || (name
1100                    .equals(VARIABLE_NAME_RESULT)));
1101        return ( (name.equals(VARIABLE_NAME_EQUALS_CASTED)) || (name.equals(VARIABLE_NAME_EQUALS_PARAM)));
1102    }
1103
1104}
1105
Popular Tags