]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2011 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; | |
14 | import java.util.Iterator; | |
15 | import java.util.List; | |
16 | ||
17 | import org.eclipse.core.runtime.Assert; | |
18 | import org.eclipse.core.runtime.CoreException; | |
19 | import org.eclipse.core.runtime.IProgressMonitor; | |
20 | import org.eclipse.core.runtime.NullProgressMonitor; | |
21 | import org.eclipse.core.runtime.jobs.ISchedulingRule; | |
22 | ||
23 | import org.eclipse.core.resources.IWorkspaceRunnable; | |
24 | import org.eclipse.core.resources.ResourcesPlugin; | |
25 | ||
26 | import org.eclipse.text.edits.TextEdit; | |
27 | ||
28 | import org.eclipse.jdt.core.ICompilationUnit; | |
29 | import org.eclipse.jdt.core.IJavaElement; | |
30 | import org.eclipse.jdt.core.IJavaProject; | |
31 | import org.eclipse.jdt.core.dom.AST; | |
32 | import org.eclipse.jdt.core.dom.ASTNode; | |
33 | import org.eclipse.jdt.core.dom.ArrayAccess; | |
34 | import org.eclipse.jdt.core.dom.Assignment; | |
35 | import org.eclipse.jdt.core.dom.Block; | |
36 | import org.eclipse.jdt.core.dom.BodyDeclaration; | |
37 | import org.eclipse.jdt.core.dom.CastExpression; | |
38 | import org.eclipse.jdt.core.dom.CompilationUnit; | |
39 | import org.eclipse.jdt.core.dom.ConditionalExpression; | |
40 | import org.eclipse.jdt.core.dom.Expression; | |
41 | import org.eclipse.jdt.core.dom.FieldAccess; | |
42 | import org.eclipse.jdt.core.dom.ForStatement; | |
43 | import org.eclipse.jdt.core.dom.IMethodBinding; | |
44 | import org.eclipse.jdt.core.dom.ITypeBinding; | |
45 | import org.eclipse.jdt.core.dom.IVariableBinding; | |
46 | import org.eclipse.jdt.core.dom.IfStatement; | |
47 | import org.eclipse.jdt.core.dom.InfixExpression; | |
48 | import org.eclipse.jdt.core.dom.InfixExpression.Operator; | |
49 | import org.eclipse.jdt.core.dom.Javadoc; | |
50 | import org.eclipse.jdt.core.dom.MethodDeclaration; | |
51 | import org.eclipse.jdt.core.dom.MethodInvocation; | |
52 | import org.eclipse.jdt.core.dom.Modifier; | |
53 | import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; | |
54 | import org.eclipse.jdt.core.dom.Name; | |
55 | import org.eclipse.jdt.core.dom.ParenthesizedExpression; | |
56 | import org.eclipse.jdt.core.dom.PostfixExpression; | |
57 | import org.eclipse.jdt.core.dom.PrefixExpression; | |
58 | import org.eclipse.jdt.core.dom.PrimitiveType; | |
59 | import org.eclipse.jdt.core.dom.ReturnStatement; | |
60 | import org.eclipse.jdt.core.dom.SingleVariableDeclaration; | |
61 | import org.eclipse.jdt.core.dom.Statement; | |
62 | import org.eclipse.jdt.core.dom.SuperMethodInvocation; | |
63 | import org.eclipse.jdt.core.dom.TagElement; | |
64 | import org.eclipse.jdt.core.dom.TextElement; | |
65 | import org.eclipse.jdt.core.dom.ThisExpression; | |
66 | import org.eclipse.jdt.core.dom.VariableDeclarationExpression; | |
67 | import org.eclipse.jdt.core.dom.VariableDeclarationFragment; | |
68 | import org.eclipse.jdt.core.dom.VariableDeclarationStatement; | |
69 | import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; | |
70 | import org.eclipse.jdt.core.dom.rewrite.ListRewrite; | |
71 | ||
72 | import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; | |
73 | import org.eclipse.jdt.internal.corext.dom.Bindings; | |
74 | import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; | |
75 | import org.eclipse.jdt.internal.corext.util.JavaModelUtil; | |
76 | ||
77 | /** | |
78 | * <p> | |
79 | * Workspace runnable to add implementations for | |
80 | * <code>{@link java.lang.Object#equals(java.lang.Object)}</code> and | |
81 | * <code>{@link java.lang.Object#hashCode()}</code>. | |
82 | * </p> | |
83 | * | |
84 | * <p> | |
85 | * This implementation creates a hashCode() and an equals() method intended to | |
86 | * be used in value types: The implementation assumes that two objects are equal | |
87 | * (and provide the same hashCode) if all values of all fields are equal. | |
88 | * </p> | |
89 | * | |
90 | * <p> | |
91 | * About the implementation: | |
92 | * <ul> | |
93 | * <li>To deal with reference types of fields and with supertypes, the | |
94 | * implementation calls hashCode() and equals() on reference types of fields and | |
95 | * on the superclass (except if the superclass is Object). It is an error if | |
96 | * these types do not provide an equals() and hashCode() implementation and the | |
97 | * comparison or hash code creation <strong>will fail</strong> if these methods | |
98 | * are not correctly implemented.</li> | |
99 | * <li>The implementation for primitive typed fields is the same as in the JDK | |
100 | * implementations in the wrapper types (and the java.util.Arrays class).</li> | |
101 | * <li>The equals() implementation uses equality of the declaring class instead | |
102 | * of an instanceof check.</li> | |
103 | * <li>A test for null in equals() is only implemented in direct subclasses of | |
104 | * Object. This is only sufficient if every subimplementation calls | |
105 | * super.equals() before any argument checks.</li> | |
106 | * <li>Both equals() and hashCode() use methods from java.util.Arrays to test | |
107 | * for equality and to generate a hash code for arrays. Note that this has an | |
108 | * implication for Double and Float values (consider values -0.0 and 0.0 as well | |
109 | * as border values like NaN and their equality in bit patterns) - however, the | |
110 | * implementation is consistent with the wrapper types java.lang.Float and | |
111 | * java.lang.Double.</li> | |
112 | * </ul> | |
113 | * </p> | |
114 | * | |
115 | * @since 3.2 | |
116 | */ | |
117 | public final class GenerateHashCodeEqualsOperation implements IWorkspaceRunnable { | |
118 | ||
119 | private interface IHashCodeAccessProvider { | |
120 | ||
121 | public Expression getThisAccess(String name); | |
122 | } | |
123 | ||
124 | private static final String JAVA_UTIL_ARRAYS= "java.util.Arrays"; //$NON-NLS-1$ | |
125 | ||
126 | private static final String BOOLEAN_TRUE_CONSTANT= "1231"; //$NON-NLS-1$ | |
127 | ||
128 | private static final String BOOLEAN_FALSE_CONSTANT= "1237"; //$NON-NLS-1$ | |
129 | ||
130 | public static final String JAVA_LANG_OBJECT= "java.lang.Object"; //$NON-NLS-1$ | |
131 | ||
132 | public static final String METHODNAME_GETCLASS= "getClass"; //$NON-NLS-1$ | |
133 | ||
134 | public static final String METHODNAME_EQUALS= "equals"; //$NON-NLS-1$ | |
135 | ||
136 | private static final String METHODNAME_DEEP_EQUALS= "deepEquals"; //$NON-NLS-1$ | |
137 | ||
138 | public static final String METHODNAME_HASH_CODE= "hashCode"; //$NON-NLS-1$ | |
139 | ||
140 | public static final String METHODNAME_OUTER_TYPE= "getOuterType"; //$NON-NLS-1$ | |
141 | ||
142 | private static final String PRIME_NUMBER= "31"; //$NON-NLS-1$ | |
143 | ||
144 | private static final String INITIAL_HASHCODE_VALUE= "1"; //$NON-NLS-1$ | |
145 | ||
146 | private static final String VARIABLE_NAME_DOUBLE_TEMPORARY= "temp"; //$NON-NLS-1$ | |
147 | ||
148 | private static final String VARIABLE_NAME_PRIME= "prime"; //$NON-NLS-1$ | |
149 | ||
150 | private static final String VARIABLE_NAME_RESULT= "result"; //$NON-NLS-1$ | |
151 | ||
152 | public static final String VARIABLE_NAME_EQUALS_PARAM= "obj"; //$NON-NLS-1$ | |
153 | ||
154 | private static final String VARIABLE_NAME_HASHCODE_PARAM= "array"; //$NON-NLS-1$ | |
155 | ||
156 | public static final String VARIABLE_NAME_EQUALS_CASTED= "other"; //$NON-NLS-1$ | |
157 | ||
158 | private static final String VARIABLE_NAME_INDEX= "index"; //$NON-NLS-1$ | |
159 | ||
160 | /** Should the resulting edit be applied? */ | |
161 | public final boolean fApply; | |
162 | ||
163 | /** The resulting text edit */ | |
164 | public TextEdit fEdit= null; | |
165 | ||
166 | /** The insertion point, or <code>null</code> */ | |
167 | public final IJavaElement fInsert; | |
168 | ||
169 | /** The variable binding keys to implement */ | |
170 | public final IVariableBinding[] fFields; | |
171 | ||
172 | /** Should the regeneration of the methods be enforced? */ | |
173 | public final boolean fForce; | |
174 | ||
175 | /** Should the compilation unit content be saved? */ | |
176 | public final boolean fSave; | |
177 | ||
178 | /** The code generation settings to use */ | |
179 | public final CodeGenerationSettings fSettings; | |
180 | ||
181 | /** The type declaration to add the methods to */ | |
182 | public final ITypeBinding fType; | |
183 | ||
184 | /** The compilation unit ast node */ | |
185 | public final CompilationUnit fUnit; | |
186 | ||
187 | /** The CURewrite to be used */ | |
188 | public final CompilationUnitRewrite fRewrite; | |
189 | ||
190 | /** The ast to be used. Convenience accessor field */ | |
191 | public final AST fAst; | |
192 | ||
193 | /** The number of double-typed fields handled so far */ | |
194 | private int fDoubleCount; | |
195 | ||
196 | /** The primitive types to generate custom hashCode() methods for */ | |
197 | public List<ITypeBinding> fCustomHashCodeTypes= new ArrayList<ITypeBinding>(); | |
198 | ||
199 | /** <code>true</code> to use 'instanceof' to compare types, <code>false</code> otherwise */ | |
200 | public final boolean fUseInstanceOf; | |
201 | ||
202 | /** <code>true</code> to use blocks for then */ | |
203 | private boolean fUseBlocksForThen; | |
204 | ||
205 | /** The import rewrite context, only initialized in {@link #run(IProgressMonitor)}. */ | |
206 | public ImportRewriteContext fImportRewriteContext; | |
207 | ||
208 | /** | |
209 | * Creates a new add hash code equals operation. | |
210 | * | |
211 | * @param type the type to add the methods to | |
212 | * @param fields the method binding keys to implement | |
213 | * @param unit the compilation unit ast node | |
214 | * @param insert the insertion point, or <code>null</code> | |
215 | * @param settings the code generation settings to use | |
216 | * @param useInstanceof <code>true</code> to use 'instanceof' to compare types, <code>false</code> otherwise | |
217 | * @param force <code>true</code> to force the regeneration of existing methods, | |
218 | * <code>false</code> otherwise | |
219 | * @param apply <code>true</code> if the resulting edit should be applied, | |
220 | * <code>false</code> otherwise | |
221 | * @param save <code>true</code> if the changed compilation unit should be | |
222 | * saved, <code>false</code> otherwise | |
223 | */ | |
224 | public GenerateHashCodeEqualsOperation(final ITypeBinding type, final IVariableBinding[] fields, final CompilationUnit unit, | |
225 | final IJavaElement insert, final CodeGenerationSettings settings, final boolean useInstanceof, final boolean force, final boolean apply, final boolean save) { | |
226 | Assert.isNotNull(type); | |
227 | Assert.isNotNull(fields); | |
228 | Assert.isNotNull(unit); | |
229 | Assert.isNotNull(settings); | |
230 | Assert.isTrue(unit.getTypeRoot() instanceof ICompilationUnit); | |
231 | ||
232 | fType= type; | |
233 | fInsert= insert; | |
234 | fUnit= unit; | |
235 | fFields= fields; | |
236 | fSettings= settings; | |
237 | fUseInstanceOf= useInstanceof; | |
238 | fSave= save; | |
239 | fApply= apply; | |
240 | fDoubleCount= 0; | |
241 | fRewrite= new CompilationUnitRewrite((ICompilationUnit) fUnit.getTypeRoot(), fUnit); | |
242 | fForce= force; | |
243 | fAst= fRewrite.getAST(); | |
244 | fUseBlocksForThen= false; | |
245 | } | |
246 | ||
247 | /** | |
248 | * Defines if then statements should use blocks or not. | |
249 | * | |
250 | * @param useBlocksForThen if set, blocks are forced in if-then statements | |
251 | */ | |
252 | public void setUseBlocksForThen(boolean useBlocksForThen) { | |
253 | fUseBlocksForThen= useBlocksForThen; | |
254 | } | |
255 | ||
256 | /** | |
257 | * Returns the resulting text edit. | |
258 | * | |
259 | * @return the resulting edit | |
260 | */ | |
261 | public final TextEdit getResultingEdit() { | |
262 | return fEdit; | |
263 | } | |
264 | ||
265 | /** | |
266 | * Returns the scheduling rule for this operation. | |
267 | * | |
268 | * @return the scheduling rule | |
269 | */ | |
270 | public final ISchedulingRule getSchedulingRule() { | |
271 | return ResourcesPlugin.getWorkspace().getRoot(); | |
272 | } | |
273 | ||
274 | /* | |
275 | * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor) | |
276 | */ | |
277 | public final void run(IProgressMonitor monitor) throws CoreException { | |
278 | if (monitor == null) | |
279 | monitor= new NullProgressMonitor(); | |
280 | try { | |
281 | fRewrite.generated_1836712646092749790(this, monitor); | |
282 | } finally { | |
283 | monitor.done(); | |
284 | } | |
285 | } | |
286 | ||
287 | public boolean isMemberType() { | |
288 | return fType.isMember() && !Modifier.isStatic(fType.getModifiers()); | |
289 | } | |
290 | ||
291 | public BodyDeclaration findMethodToReplace(final List<BodyDeclaration> list, String name, ITypeBinding[] paramTypes) { | |
292 | for (final Iterator<BodyDeclaration> iterator= list.iterator(); iterator.hasNext();) { | |
293 | final BodyDeclaration bodyDecl= iterator.next(); | |
294 | if (bodyDecl instanceof MethodDeclaration) { | |
295 | final MethodDeclaration method= (MethodDeclaration) bodyDecl; | |
296 | final IMethodBinding binding= method.resolveBinding(); | |
297 | if (binding != null && binding.getName().equals(name)) { | |
298 | if (Bindings.equals(binding.getParameterTypes(), paramTypes)) { | |
299 | return method; | |
300 | } | |
301 | } | |
302 | } | |
303 | } | |
304 | return null; | |
305 | } | |
306 | ||
307 | public void addHelper(ListRewrite rewriter, ASTNode insertion, MethodDeclaration stub) { | |
308 | if (insertion != null) | |
309 | rewriter.insertBefore(stub, insertion, null); | |
310 | else | |
311 | rewriter.insertFirst(stub, null); | |
312 | } | |
313 | ||
314 | public void addMethod(ListRewrite rewriter, ASTNode insertion, MethodDeclaration stub, BodyDeclaration replace) { | |
315 | if (replace != null) { | |
316 | rewriter.replace(replace, stub, null); | |
317 | } else { | |
318 | if (insertion != null) | |
319 | rewriter.insertBefore(stub, insertion, null); | |
320 | else | |
321 | rewriter.insertLast(stub, null); | |
322 | } | |
323 | } | |
324 | ||
325 | // ******************* HASHCODE ******************* | |
326 | ||
327 | public MethodDeclaration createHashCodeMethod() throws CoreException { | |
328 | ||
329 | MethodDeclaration hashCodeMethod= fAst.newMethodDeclaration(); | |
330 | hashCodeMethod.modifiers().addAll(ASTNodeFactory.newModifiers(fAst, Modifier.PUBLIC)); | |
331 | hashCodeMethod.setName(fAst.newSimpleName(METHODNAME_HASH_CODE)); | |
332 | hashCodeMethod.setConstructor(false); | |
333 | hashCodeMethod.setReturnType2(fAst.newPrimitiveType(PrimitiveType.INT)); | |
334 | ||
335 | Block body= fAst.newBlock(); | |
336 | hashCodeMethod.setBody(body); | |
337 | ||
338 | // PRIME NUMBER | |
339 | VariableDeclarationFragment frag= fAst.newVariableDeclarationFragment(); | |
340 | frag.setName(fAst.newSimpleName(VARIABLE_NAME_PRIME)); | |
341 | frag.setInitializer(fAst.newNumberLiteral(PRIME_NUMBER)); | |
342 | ||
343 | VariableDeclarationStatement primeNumberDeclaration= fAst.newVariableDeclarationStatement(frag); | |
344 | primeNumberDeclaration.modifiers().add(fAst.newModifier(ModifierKeyword.FINAL_KEYWORD)); | |
345 | primeNumberDeclaration.setType(fAst.newPrimitiveType(PrimitiveType.INT)); | |
346 | body.statements().add(primeNumberDeclaration); | |
347 | ||
348 | // RESULT | |
349 | VariableDeclarationFragment fragment= fAst.newVariableDeclarationFragment(); | |
350 | fragment.setName(fAst.newSimpleName(VARIABLE_NAME_RESULT)); | |
351 | ||
352 | VariableDeclarationStatement resultDeclaration= fAst.newVariableDeclarationStatement(fragment); | |
353 | resultDeclaration.setType(fAst.newPrimitiveType(PrimitiveType.INT)); | |
354 | body.statements().add(resultDeclaration); | |
355 | ||
356 | if (needsNoSuperCall(fType, METHODNAME_HASH_CODE, new ITypeBinding[0])) { | |
357 | fragment.setInitializer(fAst.newNumberLiteral(INITIAL_HASHCODE_VALUE)); | |
358 | } else { | |
359 | SuperMethodInvocation invoc= fAst.newSuperMethodInvocation(); | |
360 | invoc.setName(fAst.newSimpleName(METHODNAME_HASH_CODE)); | |
361 | fragment.setInitializer(invoc); | |
362 | } | |
363 | ||
364 | if (isMemberType()) { | |
365 | body.statements().add(createAddOuterHashCode()); | |
366 | } | |
367 | ||
368 | for (int i= 0; i < fFields.length; i++) { | |
369 | if (fFields[i].getType().isPrimitive()) { | |
370 | Statement[] sts= createAddSimpleHashCode(fFields[i].getType(), new IHashCodeAccessProvider() { | |
371 | ||
372 | public Expression getThisAccess(String name) { | |
373 | return getThisAccessForHashCode(name); | |
374 | } | |
375 | ||
376 | }, fFields[i].getName(), false); | |
377 | for (int j= 0; j < sts.length; j++) { | |
378 | body.statements().add(sts[j]); | |
379 | } | |
380 | } else if (fFields[i].getType().isArray()) | |
381 | body.statements().add(createAddArrayHashCode(fFields[i])); | |
382 | else | |
383 | body.statements().add(createAddQualifiedHashCode(fFields[i])); | |
384 | } | |
385 | ||
386 | // the last return: | |
387 | ReturnStatement endReturn= fAst.newReturnStatement(); | |
388 | endReturn.setExpression(fAst.newSimpleName(VARIABLE_NAME_RESULT)); | |
389 | body.statements().add(endReturn); | |
390 | ||
391 | // method comment | |
392 | if (fSettings != null) { | |
393 | ITypeBinding object= fAst.resolveWellKnownType(JAVA_LANG_OBJECT); | |
394 | IMethodBinding[] objms= object.getDeclaredMethods(); | |
395 | IMethodBinding objectMethod= null; | |
396 | for (int i= 0; i < objms.length; i++) { | |
397 | if (objms[i].getName().equals(METHODNAME_HASH_CODE) && objms[i].getParameterTypes().length == 0) | |
398 | objectMethod= objms[i]; | |
399 | } | |
400 | createMethodComment(hashCodeMethod, objectMethod); | |
401 | } | |
402 | ||
403 | return hashCodeMethod; | |
404 | } | |
405 | ||
406 | private Statement createAddOuterHashCode() { | |
407 | MethodInvocation outer= fAst.newMethodInvocation(); | |
408 | outer.setName(fAst.newSimpleName(METHODNAME_OUTER_TYPE)); | |
409 | MethodInvocation hashAccess= fAst.newMethodInvocation(); | |
410 | hashAccess.setName(fAst.newSimpleName(METHODNAME_HASH_CODE)); | |
411 | hashAccess.setExpression(outer); | |
412 | return prepareAssignment(hashAccess); | |
413 | } | |
414 | ||
415 | private Statement[] createAddSimpleHashCode(ITypeBinding type, IHashCodeAccessProvider provider, String name, boolean singleTemp) { | |
416 | ||
417 | List<Statement> statements= new ArrayList<Statement>(); | |
418 | ||
419 | if (!type.isPrimitive()) { | |
420 | // (element == null ? 0 : element.hashCode()) | |
421 | ConditionalExpression ce= fAst.newConditionalExpression(); | |
422 | InfixExpression exp= fAst.newInfixExpression(); | |
423 | ArrayAccess access= fAst.newArrayAccess(); | |
424 | access.setArray(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM)); | |
425 | access.setIndex(fAst.newSimpleName(VARIABLE_NAME_INDEX)); | |
426 | exp.setLeftOperand(access); | |
427 | exp.setOperator(Operator.EQUALS); | |
428 | exp.setRightOperand(fAst.newNullLiteral()); | |
429 | ce.setExpression(exp); | |
430 | ce.setThenExpression(fAst.newNumberLiteral("0")); //$NON-NLS-1$ | |
431 | MethodInvocation invoc= fAst.newMethodInvocation(); | |
432 | access= fAst.newArrayAccess(); | |
433 | access.setArray(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM)); | |
434 | access.setIndex(fAst.newSimpleName(VARIABLE_NAME_INDEX)); | |
435 | invoc.setExpression(access); | |
436 | invoc.setName(fAst.newSimpleName(METHODNAME_HASH_CODE)); | |
437 | ce.setElseExpression(invoc); | |
438 | statements.add(prepareAssignment(parenthesize(ce))); | |
439 | } else if (isPrimitiveType(type, PrimitiveType.BOOLEAN)) { | |
440 | ConditionalExpression ce= fAst.newConditionalExpression(); | |
441 | ce.setExpression(provider.getThisAccess(name)); | |
442 | // see Boolean.hashCode(boolean) | |
443 | ce.setThenExpression(fAst.newNumberLiteral(BOOLEAN_TRUE_CONSTANT)); | |
444 | ce.setElseExpression(fAst.newNumberLiteral(BOOLEAN_FALSE_CONSTANT)); | |
445 | statements.add(prepareAssignment(parenthesize(ce))); | |
446 | } else if (isPrimitiveType(type, new PrimitiveType.Code[] { PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.SHORT, PrimitiveType.BYTE })) { | |
447 | statements.add(prepareAssignment(provider.getThisAccess(name))); | |
448 | } else if (isPrimitiveType(type, PrimitiveType.FLOAT)) { | |
449 | // Float.floatToIntBits(aFloat) | |
450 | statements.add(prepareAssignment(createFloatInvocation(provider.getThisAccess(name)))); | |
451 | } else if (isPrimitiveType(type, PrimitiveType.LONG)) { | |
452 | statements.add(prepareAssignment(createShiftAssignment(provider.getThisAccess(name), provider.getThisAccess(name)))); | |
453 | } else if (isPrimitiveType(type, PrimitiveType.DOUBLE)) { | |
454 | ||
455 | VariableDeclarationFragment fragment= null; | |
456 | if (singleTemp || fDoubleCount == 0) { | |
457 | fragment= fAst.newVariableDeclarationFragment(); | |
458 | fragment.setName(fAst.newSimpleName(VARIABLE_NAME_DOUBLE_TEMPORARY)); | |
459 | ||
460 | VariableDeclarationStatement st2= fAst.newVariableDeclarationStatement(fragment); | |
461 | st2.setType(fAst.newPrimitiveType(PrimitiveType.LONG)); | |
462 | statements.add(st2); | |
463 | } | |
464 | fDoubleCount++; | |
465 | ||
466 | // Double.doubleToIntBits(aDouble) | |
467 | Expression comparison= createDoubleInvocation(provider.getThisAccess(name)); | |
468 | ||
469 | if (singleTemp) | |
470 | fragment.setInitializer(comparison); | |
471 | else { | |
472 | Assignment ass= fAst.newAssignment(); | |
473 | ass.setLeftHandSide(fAst.newSimpleName(VARIABLE_NAME_DOUBLE_TEMPORARY)); | |
474 | ass.setRightHandSide(comparison); | |
475 | statements.add(fAst.newExpressionStatement(ass)); | |
476 | } | |
477 | statements.add(prepareAssignment(createShiftAssignment(fAst.newSimpleName(VARIABLE_NAME_DOUBLE_TEMPORARY), fAst.newSimpleName(VARIABLE_NAME_DOUBLE_TEMPORARY)))); | |
478 | } | |
479 | ||
480 | return statements.toArray(new Statement[statements.size()]); | |
481 | } | |
482 | ||
483 | private Statement createAddArrayHashCode(IVariableBinding binding) { | |
484 | MethodInvocation invoc= fAst.newMethodInvocation(); | |
485 | if (JavaModelUtil.is50OrHigher(fRewrite.getCu().getJavaProject())) { | |
486 | invoc.setName(fAst.newSimpleName(METHODNAME_HASH_CODE)); | |
487 | invoc.setExpression(getQualifiedName(JAVA_UTIL_ARRAYS)); | |
488 | invoc.arguments().add(getThisAccessForHashCode(binding.getName())); | |
489 | } else { | |
490 | invoc.setName(fAst.newSimpleName(METHODNAME_HASH_CODE)); | |
491 | final IJavaElement element= fType.getJavaElement(); | |
492 | if (element != null && !"".equals(element.getElementName())) //$NON-NLS-1$ | |
493 | invoc.setExpression(fAst.newSimpleName(element.getElementName())); | |
494 | invoc.arguments().add(getThisAccessForHashCode(binding.getName())); | |
495 | ITypeBinding type= binding.getType().getElementType(); | |
496 | if (!Bindings.isVoidType(type)) { | |
497 | if (!type.isPrimitive() || binding.getType().getDimensions() >= 2) | |
498 | type= fAst.resolveWellKnownType(JAVA_LANG_OBJECT); | |
499 | if (!fCustomHashCodeTypes.contains(type)) | |
500 | fCustomHashCodeTypes.add(type); | |
501 | } | |
502 | } | |
503 | return prepareAssignment(invoc); | |
504 | } | |
505 | ||
506 | public MethodDeclaration createGetOuterHelper() { | |
507 | String outerTypeName= fType.getDeclaringClass().getTypeDeclaration().getName(); | |
508 | ||
509 | MethodDeclaration helperMethod= fAst.newMethodDeclaration(); | |
510 | helperMethod.modifiers().addAll(ASTNodeFactory.newModifiers(fAst, Modifier.PRIVATE)); | |
511 | helperMethod.setName(fAst.newSimpleName(METHODNAME_OUTER_TYPE)); | |
512 | helperMethod.setConstructor(false); | |
513 | helperMethod.setReturnType2(fAst.newSimpleType(fAst.newSimpleName(outerTypeName))); | |
514 | ||
515 | Block body= fAst.newBlock(); | |
516 | helperMethod.setBody(body); | |
517 | ||
518 | ThisExpression thisExpression= fAst.newThisExpression(); | |
519 | thisExpression.setQualifier(fAst.newSimpleName(outerTypeName)); | |
520 | ||
521 | ReturnStatement endReturn= fAst.newReturnStatement(); | |
522 | endReturn.setExpression(thisExpression); | |
523 | body.statements().add(endReturn); | |
524 | ||
525 | return helperMethod; | |
526 | } | |
527 | ||
528 | ||
529 | public MethodDeclaration createHashCodeHelper(ITypeBinding binding) { | |
530 | Assert.isTrue(!binding.isArray()); | |
531 | ||
532 | MethodDeclaration hashCodeMethod= fAst.newMethodDeclaration(); | |
533 | hashCodeMethod.modifiers().addAll(ASTNodeFactory.newModifiers(fAst, Modifier.PRIVATE | Modifier.STATIC)); | |
534 | hashCodeMethod.setName(fAst.newSimpleName(METHODNAME_HASH_CODE)); | |
535 | hashCodeMethod.setConstructor(false); | |
536 | hashCodeMethod.setReturnType2(fAst.newPrimitiveType(PrimitiveType.INT)); | |
537 | ||
538 | // ARGUMENTS | |
539 | List<SingleVariableDeclaration> parameters= hashCodeMethod.parameters(); | |
540 | SingleVariableDeclaration hashCodeParam= fAst.newSingleVariableDeclaration(); | |
541 | if (!binding.isPrimitive()) | |
542 | hashCodeParam.setType(fAst.newArrayType(fAst.newSimpleType(getQualifiedName(JAVA_LANG_OBJECT)), 1)); | |
543 | else | |
544 | hashCodeParam.setType(fAst.newArrayType(fAst.newPrimitiveType(PrimitiveType.toCode(binding.getName())), 1)); | |
545 | hashCodeParam.setName(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM)); | |
546 | parameters.add(hashCodeParam); | |
547 | ||
548 | Block body= fAst.newBlock(); | |
549 | hashCodeMethod.setBody(body); | |
550 | ||
551 | // PRIME NUMBER | |
552 | VariableDeclarationFragment frag= fAst.newVariableDeclarationFragment(); | |
553 | frag.setName(fAst.newSimpleName(VARIABLE_NAME_PRIME)); | |
554 | frag.setInitializer(fAst.newNumberLiteral(PRIME_NUMBER)); | |
555 | ||
556 | VariableDeclarationStatement primeNumberDeclaration= fAst.newVariableDeclarationStatement(frag); | |
557 | primeNumberDeclaration.setType(fAst.newPrimitiveType(PrimitiveType.INT)); | |
558 | body.statements().add(primeNumberDeclaration); | |
559 | ||
560 | // IF STATEMENT | |
561 | IfStatement ifStatement= fAst.newIfStatement(); | |
562 | final InfixExpression newInfixExpression= fAst.newInfixExpression(); | |
563 | newInfixExpression.setLeftOperand(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM)); | |
564 | newInfixExpression.setRightOperand(fAst.newNullLiteral()); | |
565 | newInfixExpression.setOperator(Operator.EQUALS); | |
566 | ifStatement.setExpression(newInfixExpression); | |
567 | final ReturnStatement returnStatement= fAst.newReturnStatement(); | |
568 | returnStatement.setExpression(fAst.newNumberLiteral("0")); //$NON-NLS-1$ | |
569 | ifStatement.setThenStatement(getThenStatement(returnStatement)); | |
570 | body.statements().add(ifStatement); | |
571 | ||
572 | // RESULT | |
573 | VariableDeclarationFragment resultFragment= fAst.newVariableDeclarationFragment(); | |
574 | resultFragment.setName(fAst.newSimpleName(VARIABLE_NAME_RESULT)); | |
575 | resultFragment.setInitializer(fAst.newNumberLiteral(INITIAL_HASHCODE_VALUE)); | |
576 | VariableDeclarationStatement resultDeclaration= fAst.newVariableDeclarationStatement(resultFragment); | |
577 | resultDeclaration.setType(fAst.newPrimitiveType(PrimitiveType.INT)); | |
578 | body.statements().add(resultDeclaration); | |
579 | ||
580 | // FOR LOOP | |
581 | ForStatement forStatement= fAst.newForStatement(); | |
582 | ||
583 | VariableDeclarationFragment indexDeclaration= fAst.newVariableDeclarationFragment(); | |
584 | indexDeclaration.setName(fAst.newSimpleName(VARIABLE_NAME_INDEX)); | |
585 | indexDeclaration.setInitializer(fAst.newNumberLiteral("0")); //$NON-NLS-1$ | |
586 | final VariableDeclarationExpression declExpression= fAst.newVariableDeclarationExpression(indexDeclaration); | |
587 | declExpression.setType(fAst.newPrimitiveType(PrimitiveType.INT)); | |
588 | forStatement.initializers().add(declExpression); | |
589 | InfixExpression infixExpr= fAst.newInfixExpression(); | |
590 | infixExpr.setLeftOperand(fAst.newSimpleName(VARIABLE_NAME_INDEX)); | |
591 | FieldAccess access= fAst.newFieldAccess(); | |
592 | access.setExpression(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM)); | |
593 | access.setName(fAst.newSimpleName("length")); //$NON-NLS-1$ | |
594 | infixExpr.setRightOperand(access); | |
595 | infixExpr.setOperator(Operator.LESS); | |
596 | forStatement.setExpression(infixExpr); | |
597 | PostfixExpression postfixExpr= fAst.newPostfixExpression(); | |
598 | postfixExpr.setOperand(fAst.newSimpleName(VARIABLE_NAME_INDEX)); | |
599 | postfixExpr.setOperator(org.eclipse.jdt.core.dom.PostfixExpression.Operator.INCREMENT); | |
600 | forStatement.updaters().add(postfixExpr); | |
601 | body.statements().add(forStatement); | |
602 | ||
603 | Block forBody= fAst.newBlock(); | |
604 | Statement[] statements= createAddSimpleHashCode(binding, new IHashCodeAccessProvider() { | |
605 | ||
606 | public Expression getThisAccess(String name) { | |
607 | ArrayAccess a= fAst.newArrayAccess(); | |
608 | a.setArray(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM)); | |
609 | a.setIndex(fAst.newSimpleName(name)); | |
610 | return a; | |
611 | } | |
612 | }, VARIABLE_NAME_INDEX, true); | |
613 | for (int index= 0; index < statements.length; index++) { | |
614 | forBody.statements().add(statements[index]); | |
615 | } | |
616 | forStatement.setBody(forBody); | |
617 | ||
618 | // END RETURN | |
619 | ReturnStatement endReturn= fAst.newReturnStatement(); | |
620 | endReturn.setExpression(fAst.newSimpleName(VARIABLE_NAME_RESULT)); | |
621 | body.statements().add(endReturn); | |
622 | ||
623 | // COMMENT | |
624 | if (fSettings != null && fSettings.createComments) { | |
625 | Javadoc javadoc= fAst.newJavadoc(); | |
626 | final TagElement tagComment= fAst.newTagElement(); | |
627 | TextElement text= fAst.newTextElement(); | |
628 | text.setText(CodeGenerationMessages.GenerateHashCodeEqualsOperation_hash_code_comment); | |
629 | tagComment.fragments().add(text); | |
630 | javadoc.tags().add(tagComment); | |
631 | final TagElement tagParam= fAst.newTagElement(); | |
632 | tagParam.setTagName(CodeGenerationMessages.GenerateHashCodeEqualsOperation_tag_param); | |
633 | tagParam.fragments().add(fAst.newSimpleName(VARIABLE_NAME_HASHCODE_PARAM)); | |
634 | text= fAst.newTextElement(); | |
635 | text.setText(CodeGenerationMessages.GenerateHashCodeEqualsOperation_hash_code_argument); | |
636 | tagParam.fragments().add(text); | |
637 | javadoc.tags().add(tagParam); | |
638 | final TagElement tagReturn= fAst.newTagElement(); | |
639 | tagReturn.setTagName(CodeGenerationMessages.GenerateHashCodeEqualsOperation_tag_return); | |
640 | text= fAst.newTextElement(); | |
641 | text.setText(CodeGenerationMessages.GenerateHashCodeEqualsOperation_return_comment); | |
642 | tagReturn.fragments().add(text); | |
643 | javadoc.tags().add(tagReturn); | |
644 | hashCodeMethod.setJavadoc(javadoc); | |
645 | } | |
646 | return hashCodeMethod; | |
647 | } | |
648 | ||
649 | private Statement createAddQualifiedHashCode(IVariableBinding binding) { | |
650 | ||
651 | MethodInvocation invoc= fAst.newMethodInvocation(); | |
652 | invoc.setExpression(getThisAccessForHashCode(binding.getName())); | |
653 | invoc.setName(fAst.newSimpleName(METHODNAME_HASH_CODE)); | |
654 | ||
655 | InfixExpression expr= fAst.newInfixExpression(); | |
656 | expr.setOperator(Operator.EQUALS); | |
657 | expr.setLeftOperand(getThisAccessForHashCode(binding.getName())); | |
658 | expr.setRightOperand(fAst.newNullLiteral()); | |
659 | ||
660 | ConditionalExpression cexpr= fAst.newConditionalExpression(); | |
661 | cexpr.setThenExpression(fAst.newNumberLiteral("0")); //$NON-NLS-1$ | |
662 | cexpr.setElseExpression(invoc); | |
663 | cexpr.setExpression(parenthesize(expr)); | |
664 | ||
665 | return prepareAssignment(parenthesize(cexpr)); | |
666 | } | |
667 | ||
668 | private Expression createShiftAssignment(Expression shift1, Expression shift2) { | |
669 | // (int)(element ^ (element >>> 32)); | |
670 | // see implementation in Arrays.hashCode(), Double.hashCode() and | |
671 | // Long.hashCode() | |
672 | CastExpression ce= fAst.newCastExpression(); | |
673 | ce.setType(fAst.newPrimitiveType(PrimitiveType.INT)); | |
674 | ||
675 | InfixExpression unsignedShiftRight= fAst.newInfixExpression(); | |
676 | unsignedShiftRight.setLeftOperand(shift1); | |
677 | unsignedShiftRight.setRightOperand(fAst.newNumberLiteral("32")); //$NON-NLS-1$ | |
678 | unsignedShiftRight.setOperator(Operator.RIGHT_SHIFT_UNSIGNED); | |
679 | ||
680 | InfixExpression xor= fAst.newInfixExpression(); | |
681 | xor.setLeftOperand(shift2); | |
682 | xor.setRightOperand(parenthesize(unsignedShiftRight)); | |
683 | xor.setOperator(InfixExpression.Operator.XOR); | |
684 | ||
685 | ce.setExpression(parenthesize(xor)); | |
686 | return ce; | |
687 | } | |
688 | ||
689 | private Statement prepareAssignment(Expression rightHand) { | |
690 | // result = PRIME*result + (...) | |
691 | InfixExpression mul= fAst.newInfixExpression(); | |
692 | mul.setLeftOperand(fAst.newSimpleName(VARIABLE_NAME_PRIME)); | |
693 | mul.setRightOperand(fAst.newSimpleName(VARIABLE_NAME_RESULT)); | |
694 | mul.setOperator(Operator.TIMES); | |
695 | ||
696 | Assignment ass= fAst.newAssignment(); | |
697 | ass.setLeftHandSide(fAst.newSimpleName(VARIABLE_NAME_RESULT)); | |
698 | ||
699 | InfixExpression plus= fAst.newInfixExpression(); | |
700 | plus.setLeftOperand(mul); | |
701 | plus.setOperator(Operator.PLUS); | |
702 | plus.setRightOperand(rightHand); | |
703 | ||
704 | ass.setRightHandSide(plus); | |
705 | ||
706 | return fAst.newExpressionStatement(ass); | |
707 | } | |
708 | ||
709 | // *************** EQUALS *************** | |
710 | ||
711 | public MethodDeclaration createEqualsMethod() throws CoreException { | |
712 | ||
713 | MethodDeclaration equalsMethodDeclaration= fAst.newMethodDeclaration(); | |
714 | equalsMethodDeclaration.modifiers().addAll(ASTNodeFactory.newModifiers(fAst, Modifier.PUBLIC)); | |
715 | equalsMethodDeclaration.setName(fAst.newSimpleName(METHODNAME_EQUALS)); | |
716 | equalsMethodDeclaration.setConstructor(false); | |
717 | equalsMethodDeclaration.setReturnType2(fAst.newPrimitiveType(PrimitiveType.BOOLEAN)); | |
718 | ||
719 | List<SingleVariableDeclaration> parameters= equalsMethodDeclaration.parameters(); | |
720 | return fRewrite.generated_1018980582736112681(this, equalsMethodDeclaration, parameters); | |
721 | } | |
722 | ||
723 | public Statement createOuterComparison() { | |
724 | MethodInvocation outer1= fAst.newMethodInvocation(); | |
725 | outer1.setName(fAst.newSimpleName(METHODNAME_OUTER_TYPE)); | |
726 | ||
727 | MethodInvocation outer2= fAst.newMethodInvocation(); | |
728 | outer2.setName(fAst.newSimpleName(METHODNAME_OUTER_TYPE)); | |
729 | outer2.setExpression(fAst.newSimpleName(VARIABLE_NAME_EQUALS_CASTED)); | |
730 | ||
731 | MethodInvocation outerEql= fAst.newMethodInvocation(); | |
732 | outerEql.setName(fAst.newSimpleName(METHODNAME_EQUALS)); | |
733 | outerEql.setExpression(outer1); | |
734 | outerEql.arguments().add(outer2); | |
735 | ||
736 | PrefixExpression not= fAst.newPrefixExpression(); | |
737 | not.setOperand(outerEql); | |
738 | not.setOperator(PrefixExpression.Operator.NOT); | |
739 | ||
740 | IfStatement notEqNull= fAst.newIfStatement(); | |
741 | notEqNull.setExpression(not); | |
742 | notEqNull.setThenStatement(getThenStatement(getReturnFalse())); | |
743 | return notEqNull; | |
744 | } | |
745 | ||
746 | public Statement createSimpleComparison(IVariableBinding binding) { | |
747 | if (isPrimitiveType(binding.getType(), PrimitiveType.FLOAT)) { | |
748 | return createReturningIfStatement(createFloatInvocation(getThisAccessForEquals(binding.getName())), createFloatInvocation(getOtherAccess(binding | |
749 | .getName())), Operator.NOT_EQUALS, false); | |
750 | } else if (isPrimitiveType(binding.getType(), PrimitiveType.DOUBLE)) { | |
751 | return createReturningIfStatement(createDoubleInvocation(getThisAccessForEquals(binding.getName())), createDoubleInvocation(getOtherAccess(binding | |
752 | .getName())), Operator.NOT_EQUALS, false); | |
753 | } else | |
754 | return createReturningIfStatement(getThisAccessForEquals(binding.getName()), getOtherAccess(binding.getName()), Operator.NOT_EQUALS, false); | |
755 | } | |
756 | ||
757 | public Statement createArrayComparison(String name) { | |
758 | MethodInvocation invoc= fAst.newMethodInvocation(); | |
759 | invoc.setName(fAst.newSimpleName(METHODNAME_EQUALS)); | |
760 | invoc.setExpression(getQualifiedName(JAVA_UTIL_ARRAYS)); | |
761 | invoc.arguments().add(getThisAccessForEquals(name)); | |
762 | invoc.arguments().add(getOtherAccess(name)); | |
763 | ||
764 | PrefixExpression pe= fAst.newPrefixExpression(); | |
765 | pe.setOperator(PrefixExpression.Operator.NOT); | |
766 | pe.setOperand(invoc); | |
767 | ||
768 | IfStatement ifSt= fAst.newIfStatement(); | |
769 | ifSt.setExpression(pe); | |
770 | ifSt.setThenStatement(getThenStatement(getReturnFalse())); | |
771 | ||
772 | return ifSt; | |
773 | } | |
774 | ||
775 | public Statement createMultiArrayComparison(String name) { | |
776 | MethodInvocation invoc= fAst.newMethodInvocation(); | |
777 | invoc.setName(fAst.newSimpleName(METHODNAME_DEEP_EQUALS)); | |
778 | invoc.setExpression(getQualifiedName(JAVA_UTIL_ARRAYS)); | |
779 | invoc.arguments().add(getThisAccessForEquals(name)); | |
780 | invoc.arguments().add(getOtherAccess(name)); | |
781 | ||
782 | PrefixExpression pe= fAst.newPrefixExpression(); | |
783 | pe.setOperator(PrefixExpression.Operator.NOT); | |
784 | pe.setOperand(invoc); | |
785 | ||
786 | IfStatement ifSt= fAst.newIfStatement(); | |
787 | ifSt.setExpression(pe); | |
788 | ifSt.setThenStatement(getThenStatement(getReturnFalse())); | |
789 | ||
790 | return ifSt; | |
791 | } | |
792 | ||
793 | /** | |
794 | * Creates a comparison of reference types. | |
795 | * | |
796 | * <pre> | |
797 | * if (this.a == null) { | |
798 | * if (other.a != null) | |
799 | * return false; | |
800 | * } else { | |
801 | * if (!this.a.equals(other.a)) | |
802 | * return false; | |
803 | * } | |
804 | * </pre> | |
805 | * @param name the field name | |
806 | * @return the comparison statement | |
807 | */ | |
808 | public Statement createQualifiedComparison(String name) { | |
809 | InfixExpression newCondition= fAst.newInfixExpression(); | |
810 | newCondition.setOperator(Operator.EQUALS); | |
811 | newCondition.setLeftOperand(getThisAccessForEquals(name)); | |
812 | newCondition.setRightOperand(fAst.newNullLiteral()); | |
813 | ||
814 | // THEN | |
815 | InfixExpression notEqNull= fAst.newInfixExpression(); | |
816 | notEqNull.setOperator(Operator.NOT_EQUALS); | |
817 | notEqNull.setLeftOperand(getOtherAccess(name)); | |
818 | notEqNull.setRightOperand(fAst.newNullLiteral()); | |
819 | ||
820 | IfStatement thenPart= fAst.newIfStatement(); | |
821 | thenPart.setExpression(notEqNull); | |
822 | thenPart.setThenStatement(getThenStatement(getReturnFalse())); | |
823 | ||
824 | Block thenPart2= fAst.newBlock(); | |
825 | thenPart2.statements().add(thenPart); | |
826 | ||
827 | // ELSE | |
828 | MethodInvocation invoc= fAst.newMethodInvocation(); | |
829 | invoc.setName(fAst.newSimpleName(METHODNAME_EQUALS)); | |
830 | invoc.setExpression(getThisAccessForEquals(name)); | |
831 | invoc.arguments().add(getOtherAccess(name)); | |
832 | ||
833 | PrefixExpression pe= fAst.newPrefixExpression(); | |
834 | pe.setOperator(PrefixExpression.Operator.NOT); | |
835 | pe.setOperand(invoc); | |
836 | ||
837 | IfStatement elsePart= fAst.newIfStatement(); | |
838 | elsePart.setExpression(pe); | |
839 | elsePart.setThenStatement(getThenStatement(getReturnFalse())); | |
840 | ||
841 | // ALL | |
842 | IfStatement isNull= fAst.newIfStatement(); | |
843 | isNull.setExpression(newCondition); | |
844 | isNull.setThenStatement(thenPart2); | |
845 | isNull.setElseStatement(elsePart); | |
846 | ||
847 | return isNull; | |
848 | } | |
849 | ||
850 | // ************************ HELPERS ************************** | |
851 | ||
852 | public Statement createReturningIfStatement(Expression left, Expression right, Operator operator, boolean whatToReturn) { | |
853 | InfixExpression newCondition= fAst.newInfixExpression(); | |
854 | newCondition.setOperator(operator); | |
855 | newCondition.setLeftOperand(left); | |
856 | newCondition.setRightOperand(right); | |
857 | return createReturningIfStatement(whatToReturn, newCondition); | |
858 | } | |
859 | ||
860 | public Statement createReturningIfStatement(boolean result, Expression condition) { | |
861 | IfStatement firstIf= fAst.newIfStatement(); | |
862 | firstIf.setExpression(condition); | |
863 | ||
864 | ReturnStatement returner= fAst.newReturnStatement(); | |
865 | returner.setExpression(fAst.newBooleanLiteral(result)); | |
866 | firstIf.setThenStatement(getThenStatement(returner)); | |
867 | return firstIf; | |
868 | } | |
869 | ||
870 | public void createMethodComment(MethodDeclaration newDeclaration, IMethodBinding copyFrom) throws CoreException { | |
871 | if (fSettings.createComments) { | |
872 | fRewrite.generated_31859225078671094(this, newDeclaration, copyFrom); | |
873 | } | |
874 | IJavaProject project= fUnit.getJavaElement().getJavaProject(); | |
875 | if (fSettings.overrideAnnotation && JavaModelUtil.is50OrHigher(project)) | |
876 | StubUtility2.addOverrideAnnotation(project, fRewrite.getASTRewrite(), newDeclaration, copyFrom); | |
877 | } | |
878 | ||
879 | public boolean needsNoSuperCall(ITypeBinding typeBinding, String name, ITypeBinding[] parameters) { | |
880 | Assert.isNotNull(typeBinding); | |
881 | IMethodBinding binding= Bindings.findMethodInHierarchy(typeBinding.getSuperclass(), name, parameters); | |
882 | if (binding != null && !Modifier.isAbstract(binding.getModifiers())) { | |
883 | ITypeBinding declaring= binding.getDeclaringClass(); | |
884 | return declaring.getQualifiedName().equals(JAVA_LANG_OBJECT); | |
885 | } | |
886 | return true; | |
887 | } | |
888 | ||
889 | ||
890 | private Expression getThisAccessForEquals(String name) { | |
891 | return getThisAccess(name, false); | |
892 | } | |
893 | ||
894 | private Expression getThisAccessForHashCode(String name) { | |
895 | return getThisAccess(name, true); | |
896 | } | |
897 | ||
898 | private Expression getThisAccess(String name, boolean forHashCode) { | |
899 | return fSettings.generated_4209894319447273040(this, name, forHashCode); | |
900 | } | |
901 | ||
902 | private Expression getOtherAccess(String name) { | |
903 | return fAst.newQualifiedName(fAst.newSimpleName(VARIABLE_NAME_EQUALS_CASTED), fAst.newSimpleName(name)); | |
904 | } | |
905 | ||
906 | private boolean isPrimitiveType(ITypeBinding binding, PrimitiveType.Code code) { | |
907 | return (binding.getName().equals(code.toString())); | |
908 | } | |
909 | ||
910 | private boolean isPrimitiveType(ITypeBinding type, PrimitiveType.Code[] codes) { | |
911 | for (int i= 0; i < codes.length; i++) { | |
912 | PrimitiveType.Code code= codes[i]; | |
913 | if (isPrimitiveType(type, code)) | |
914 | return true; | |
915 | } | |
916 | return false; | |
917 | } | |
918 | ||
919 | private Name getQualifiedName(String name) { | |
920 | String importedType= fRewrite.getImportRewrite().addImport(name, fImportRewriteContext); | |
921 | return ASTNodeFactory.newName(fAst, importedType); | |
922 | } | |
923 | ||
924 | public ReturnStatement getReturnFalse() { | |
925 | ReturnStatement falseReturn= fAst.newReturnStatement(); | |
926 | falseReturn.setExpression(fAst.newBooleanLiteral(false)); | |
927 | return falseReturn; | |
928 | } | |
929 | ||
930 | public Statement getThenStatement(Statement statement) { | |
931 | if (fUseBlocksForThen && !(statement instanceof Block)) { | |
932 | Block block= fAst.newBlock(); | |
933 | block.statements().add(statement); | |
934 | return block; | |
935 | } | |
936 | return statement; | |
937 | } | |
938 | ||
939 | ||
940 | private Expression parenthesize(Expression expression) { | |
941 | ParenthesizedExpression pe= fAst.newParenthesizedExpression(); | |
942 | pe.setExpression(expression); | |
943 | return pe; | |
944 | } | |
945 | ||
946 | private Expression createFloatInvocation(Expression access) { | |
947 | return createMethodInvocation(access, "java.lang.Float", "floatToIntBits"); //$NON-NLS-1$ //$NON-NLS-2$ | |
948 | } | |
949 | ||
950 | private Expression createDoubleInvocation(Expression access) { | |
951 | return createMethodInvocation(access, "java.lang.Double", "doubleToLongBits"); //$NON-NLS-1$ //$NON-NLS-2$ | |
952 | } | |
953 | ||
954 | private Expression createMethodInvocation(Expression access, String qualifiedClassName, String methodName) { | |
955 | MethodInvocation invoc= fAst.newMethodInvocation(); | |
956 | invoc.setExpression(getQualifiedName(qualifiedClassName)); | |
957 | invoc.setName(fAst.newSimpleName(methodName)); | |
958 | invoc.arguments().add(access); | |
959 | return invoc; | |
960 | } | |
961 | ||
962 | boolean needsThisQualification(String name, boolean isHashCode) { | |
963 | if (isHashCode) | |
964 | return ( (fDoubleCount > 0 && name.equals(VARIABLE_NAME_DOUBLE_TEMPORARY)) || (name.equals(VARIABLE_NAME_PRIME)) || (name | |
965 | .equals(VARIABLE_NAME_RESULT))); | |
966 | return ( (name.equals(VARIABLE_NAME_EQUALS_CASTED)) || (name.equals(VARIABLE_NAME_EQUALS_PARAM))); | |
967 | } | |
968 | ||
969 | } |