]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-after/core refactoring/org/eclipse/jdt/internal/corext/refactoring/binary/StubCreator.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core refactoring / org / eclipse / jdt / internal / corext / refactoring / binary / StubCreator.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2006, 2012 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 *******************************************************************************/
11package org.eclipse.jdt.internal.corext.refactoring.binary;
12
13import java.util.ArrayList;
14import java.util.List;
15import java.util.Map;
16import java.util.TreeMap;
17
18import org.eclipse.core.runtime.Assert;
19import org.eclipse.core.runtime.IProgressMonitor;
20import org.eclipse.core.runtime.NullProgressMonitor;
21import org.eclipse.core.runtime.SubProgressMonitor;
22
23import org.eclipse.jdt.core.Flags;
24import org.eclipse.jdt.core.IAnnotatable;
25import org.eclipse.jdt.core.IAnnotation;
26import org.eclipse.jdt.core.IField;
27import org.eclipse.jdt.core.IJavaElement;
28import org.eclipse.jdt.core.IMember;
29import org.eclipse.jdt.core.IMemberValuePair;
30import org.eclipse.jdt.core.IMethod;
31import org.eclipse.jdt.core.IType;
32import org.eclipse.jdt.core.ITypeParameter;
33import org.eclipse.jdt.core.JavaModelException;
34import org.eclipse.jdt.core.Signature;
35
36import org.eclipse.jdt.internal.corext.refactoring.Checks;
37import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
38
39public class StubCreator {
40
41 /** The internal string buffer */
42 protected StringBuffer fBuffer;
43
44 /** Should stubs for private member be generated as well? */
45 protected final boolean fStubInvisible;
46
47 public StubCreator(final boolean stubInvisible) {
48 fStubInvisible= stubInvisible;
49 }
50
51 protected void appendEnumConstants(final IType type) throws JavaModelException {
52 final IField[] fields= type.getFields();
53 final List<IField> list= new ArrayList<IField>(fields.length);
54 for (int index= 0; index < fields.length; index++) {
55 final IField field= fields[index];
56 if (Flags.isEnum(field.getFlags()))
57 list.add(field);
58 }
59 for (int index= 0; index < list.size(); index++) {
60 if (index > 0)
61 fBuffer.append(","); //$NON-NLS-1$
62 fBuffer.append(list.get(index).getElementName());
63 }
64 fBuffer.append(";"); //$NON-NLS-1$
65 }
66
67 protected void appendExpression(final String signature) {
68 appendExpression(signature, false);
69 }
70
71 protected void appendExpression(String signature, boolean castNull) {
72 switch (signature.charAt(0)) {
73 case Signature.C_BOOLEAN:
74 fBuffer.append("false"); //$NON-NLS-1$
75 break;
76 case Signature.C_BYTE:
77 case Signature.C_CHAR:
78 case Signature.C_DOUBLE:
79 case Signature.C_FLOAT:
80 case Signature.C_INT:
81 case Signature.C_LONG:
82 case Signature.C_SHORT:
83 fBuffer.append("0"); //$NON-NLS-1$
84 break;
85 default:
86 if (castNull) {
87 fBuffer.append("("); //$NON-NLS-1$
88 fBuffer.append(Signature.toString(signature));
89 fBuffer.append(")"); //$NON-NLS-1$
90 }
91 fBuffer.append("null"); //$NON-NLS-1$
92 break;
93 }
94 }
95
96 protected void appendFieldDeclaration(final IField field) throws JavaModelException {
97 appendFlags(field);
98 fBuffer.append(" "); //$NON-NLS-1$
99 final String signature= field.getTypeSignature();
100 fBuffer.append(Signature.toString(signature));
101 fBuffer.append(" "); //$NON-NLS-1$
102 fBuffer.append(field.getElementName());
103 if (Flags.isFinal(field.getFlags())) {
104 fBuffer.append("="); //$NON-NLS-1$
105 appendExpression(signature);
106 }
107 fBuffer.append(";"); //$NON-NLS-1$
108 }
109
110 protected void appendFlags(final IMember member) throws JavaModelException {
111 if (member instanceof IAnnotatable)
112 for (IAnnotation annotation : ((IAnnotatable) member).getAnnotations()) {
113 appendAnnotation(annotation);
114 }
115
116 int flags= member.getFlags();
117 final int kind= member.getElementType();
118 if (kind == IJavaElement.TYPE) {
119 flags&= ~Flags.AccSuper;
120 final IType type= (IType) member;
121 if (!type.isMember())
122 flags&= ~Flags.AccPrivate;
123 if (Flags.isEnum(flags))
124 flags&= ~Flags.AccAbstract;
125 }
126 if (Flags.isEnum(flags))
127 flags&= ~Flags.AccFinal;
128 if (kind == IJavaElement.METHOD) {
129 flags&= ~Flags.AccVarargs;
130 flags&= ~Flags.AccBridge;
131 }
132 if (flags != 0)
133 fBuffer.append(Flags.toString(flags));
134 }
135
136 private void appendAnnotation(IAnnotation annotation) throws JavaModelException {
137 fBuffer.append('@');
138 fBuffer.append(annotation.getElementName());
139 fBuffer.append('(');
140
141 IMemberValuePair[] memberValuePairs= annotation.getMemberValuePairs();
142 for (IMemberValuePair pair : memberValuePairs) {
143 fBuffer.append(pair.getMemberName());
144 fBuffer.append('=');
145 appendAnnotationValue(pair.getValue(), pair.getValueKind());
146 fBuffer.append(',');
147 }
148 if (memberValuePairs.length > 0)
149 fBuffer.deleteCharAt(fBuffer.length() - 1);
150
151 fBuffer.append(')').append('\n');
152 }
153
154 private void appendAnnotationValue(Object value, int valueKind) throws JavaModelException {
155 if (value instanceof Object[]) {
156 Object[] objects= (Object[]) value;
157 fBuffer.append('{');
158 for (Object object : objects) {
159 appendAnnotationValue(object, valueKind);
160 fBuffer.append(',');
161 }
162 if (objects.length > 0)
163 fBuffer.deleteCharAt(fBuffer.length() - 1);
164 fBuffer.append('}');
165
166 } else {
167 switch (valueKind) {
168 case IMemberValuePair.K_ANNOTATION:
169 appendAnnotation((IAnnotation) value);
170 break;
171 case IMemberValuePair.K_STRING:
172 fBuffer.append('"').append(value).append('"');
173 break;
174
175 default:
176 fBuffer.append(value);
177 break;
178 }
179 }
180 }
181
182 protected void appendMembers(final IType type, final IProgressMonitor monitor) throws JavaModelException {
183 try {
184 monitor.beginTask(RefactoringCoreMessages.StubCreationOperation_creating_type_stubs, 1);
185 final IJavaElement[] children= type.getChildren();
186 for (int index= 0; index < children.length; index++) {
187 final IMember child= (IMember) children[index];
188 final int flags= child.getFlags();
189 final boolean isPrivate= Flags.isPrivate(flags);
190 final boolean isDefault= !Flags.isPublic(flags) && !Flags.isProtected(flags) && !isPrivate;
191 final boolean stub= fStubInvisible || (!isPrivate && !isDefault);
192 if (child instanceof IType) {
193 if (stub)
194 appendTypeDeclaration((IType) child, new SubProgressMonitor(monitor, 1));
195 } else if (child instanceof IField) {
196 if (stub && !Flags.isEnum(flags) && !Flags.isSynthetic(flags))
197 appendFieldDeclaration((IField) child);
198 } else if (child instanceof IMethod) {
199 final IMethod method= (IMethod) child;
200 final String name= method.getElementName();
201 if (method.getDeclaringType().isEnum()) {
202 final int count= method.getNumberOfParameters();
203 if (count == 0 && "values".equals(name)) //$NON-NLS-1$
204 continue;
205 if (count == 1 && "valueOf".equals(name) && "Ljava.lang.String;".equals(method.getParameterTypes()[0])) //$NON-NLS-1$ //$NON-NLS-2$
206 continue;
207 if (method.isConstructor())
208 continue;
209 }
210 boolean skip= !stub || name.equals("<clinit>"); //$NON-NLS-1$
211 if (method.isConstructor())
212 skip= false;
213 skip= skip || Flags.isSynthetic(flags) || Flags.isBridge(flags);
214 if (!skip)
215 appendMethodDeclaration(method);
216 }
217 fBuffer.append("\n"); //$NON-NLS-1$
218 }
219 } finally {
220 monitor.done();
221 }
222 }
223
224 @SuppressWarnings("boxing")
225 protected void appendMethodBody(final IMethod method) throws JavaModelException {
226 if (method.isConstructor()) {
227 final IType declaringType= method.getDeclaringType();
228 String superSignature= declaringType.getSuperclassTypeSignature();
229 if (superSignature != null) {
230 superSignature= Signature.getTypeErasure(superSignature);
231 final IType superclass= declaringType.getJavaProject().findType(Signature.getSignatureQualifier(superSignature), Signature.getSignatureSimpleName(superSignature));
232 if (superclass != null) {
233 final IMethod[] superMethods= superclass.getMethods();
234
235 // collect super constructors by parameter count
236 Map<Integer, List<IMethod>> superConstructorsByParamCount= new TreeMap<Integer, List<IMethod>>();
237 boolean multi= false;
238 IMethod superConstructor= null;
239 for (int i= 0; i < superMethods.length; i++) {
240 IMethod superMethod= superMethods[i];
241 if (superMethod.isConstructor()
242 && !Flags.isPrivate(superMethod.getFlags())
243 && !(Flags.isPackageDefault(superMethod.getFlags()) && !declaringType.getPackageFragment().equals(superclass.getPackageFragment()))
244 ) {
245 int paramCount= superMethod.getNumberOfParameters();
246 if (paramCount == 0) {
247 superConstructor= superMethod;
248 break;
249 }
250 List<IMethod> constructors= superConstructorsByParamCount.get(paramCount);
251 if (constructors == null) {
252 constructors= new ArrayList<IMethod>();
253 superConstructorsByParamCount.put(paramCount, constructors);
254 }
255 constructors.add(superMethod);
256 }
257 }
258 if (superConstructor == null && superConstructorsByParamCount.size() > 0) {
259 // look for constructors without exceptions and without parameters
260 done: for (List<IMethod> constructors : superConstructorsByParamCount.values()) {
261 for (IMethod constructor : constructors) {
262 if (constructor.getExceptionTypes().length == 0) {
263 superConstructor= constructor;
264 multi= constructors.size() != 1;
265 if (multi)
266 break;
267 else
268 break done;
269 }
270 if (superConstructor == null) {
271 superConstructor= constructor;
272 multi= constructors.size() != 1;
273 }
274 }
275 }
276 if (superConstructor == null) {
277 // give up, get first
278 superConstructor= superConstructorsByParamCount.values().iterator().next().get(0);
279 multi= true;
280 }
281 }
282 if (superConstructor != null) {
283 final String[] superParameters= superConstructor.getParameterTypes();
284 final int paramLength= superParameters.length;
285 fBuffer.append("super("); //$NON-NLS-1$
286 if (paramLength != 0) {
287 for (int index= 0; index < paramLength; index++) {
288 if (index > 0)
289 fBuffer.append(","); //$NON-NLS-1$
290 appendExpression(superParameters[index], multi);
291 }
292 }
293 fBuffer.append(");"); //$NON-NLS-1$
294 }
295 }
296 }
297 } else {
298 String returnType= method.getReturnType();
299 if (!Signature.SIG_VOID.equals(returnType)) {
300 fBuffer.append("return "); //$NON-NLS-1$
301 appendExpression(returnType);
302 fBuffer.append(";"); //$NON-NLS-1$
303 }
304 }
305 }
306
307 protected void appendMethodDeclaration(final IMethod method) throws JavaModelException {
308 appendFlags(method);
309 fBuffer.append(" "); //$NON-NLS-1$
310 final ITypeParameter[] parameters= method.getTypeParameters();
311 if (parameters.length > 0) {
312 appendTypeParameters(parameters);
313 fBuffer.append(" "); //$NON-NLS-1$
314 }
315 final String returnType= method.getReturnType();
316 if (!method.isConstructor()) {
317 fBuffer.append(Signature.toString(returnType));
318 fBuffer.append(" "); //$NON-NLS-1$
319 }
320 fBuffer.append(method.getElementName());
321 fBuffer.append("("); //$NON-NLS-1$
322 final String[] parameterTypes= method.getParameterTypes();
323 final int flags= method.getFlags();
324 final boolean varargs= Flags.isVarargs(flags);
325 final int parameterLength= parameterTypes.length;
326 for (int index= 0; index < parameterLength; index++) {
327 if (index > 0)
328 fBuffer.append(","); //$NON-NLS-1$
329 fBuffer.append(Signature.toString(parameterTypes[index]));
330 if (varargs && index == parameterLength - 1) {
331 final int length= fBuffer.length();
332 if (length >= 2 && fBuffer.indexOf("[]", length - 2) >= 0) //$NON-NLS-1$
333 fBuffer.setLength(length - 2);
334 fBuffer.append("..."); //$NON-NLS-1$
335 }
336 fBuffer.append(" "); //$NON-NLS-1$
337 appendMethodParameterName(method, index);
338 }
339 fBuffer.append(")"); //$NON-NLS-1$
340 final String[] exceptionTypes= method.getExceptionTypes();
341 final int exceptionLength= exceptionTypes.length;
342 if (exceptionLength > 0)
343 fBuffer.append(" throws "); //$NON-NLS-1$
344 for (int index= 0; index < exceptionLength; index++) {
345 if (index > 0)
346 fBuffer.append(","); //$NON-NLS-1$
347 fBuffer.append(Signature.toString(exceptionTypes[index]));
348 }
349 if (Flags.isAbstract(flags) || Flags.isNative(flags))
350 fBuffer.append(";"); //$NON-NLS-1$
351 else {
352 fBuffer.append("{\n"); //$NON-NLS-1$
353 appendMethodBody(method);
354 fBuffer.append("}"); //$NON-NLS-1$
355 }
356 }
357
358 /**
359 * Appends a parameter name
360 *
361 * @param method the method
362 * @param index the index of the parameter
363 */
364 protected void appendMethodParameterName(IMethod method, int index) {
365 fBuffer.append("a"); //$NON-NLS-1$
366 fBuffer.append(index);
367 }
368
369 protected void appendSuperInterfaceTypes(final IType type) throws JavaModelException {
370 final String[] signatures= type.getSuperInterfaceTypeSignatures();
371 if (signatures.length > 0) {
372 if (type.isInterface())
373 fBuffer.append(" extends "); //$NON-NLS-1$
374 else
375 fBuffer.append(" implements "); //$NON-NLS-1$
376 }
377 for (int index= 0; index < signatures.length; index++) {
378 if (index > 0)
379 fBuffer.append(","); //$NON-NLS-1$
380 fBuffer.append(Signature.toString(signatures[index]));
381 }
382 }
383
384 protected void appendTopLevelType(final IType type, IProgressMonitor subProgressMonitor) throws JavaModelException {
385 String packageName= type.getPackageFragment().getElementName();
386 if (packageName.length() > 0) {
387 fBuffer.append("package "); //$NON-NLS-1$
388 fBuffer.append(packageName);
389 fBuffer.append(";\n"); //$NON-NLS-1$
390 }
391 appendTypeDeclaration(type, subProgressMonitor);
392 }
393
394 protected void appendTypeDeclaration(final IType type, final IProgressMonitor monitor) throws JavaModelException {
395 try {
396 monitor.beginTask(RefactoringCoreMessages.StubCreationOperation_creating_type_stubs, 1);
397 if (type.isAnnotation()) {
398 appendFlags(type);
399 fBuffer.append(" @interface "); //$NON-NLS-1$
400 fBuffer.append(type.getElementName());
401 fBuffer.append("{\n"); //$NON-NLS-1$
402 appendMembers(type, new SubProgressMonitor(monitor, 1));
403 fBuffer.append("}"); //$NON-NLS-1$
404 } else if (type.isInterface()) {
405 appendFlags(type);
406 fBuffer.append(" interface "); //$NON-NLS-1$
407 fBuffer.append(type.getElementName());
408 appendTypeParameters(type.getTypeParameters());
409 appendSuperInterfaceTypes(type);
410 fBuffer.append("{\n"); //$NON-NLS-1$
411 appendMembers(type, new SubProgressMonitor(monitor, 1));
412 fBuffer.append("}"); //$NON-NLS-1$
413 } else if (type.isClass()) {
414 appendFlags(type);
415 fBuffer.append(" class "); //$NON-NLS-1$
416 fBuffer.append(type.getElementName());
417 appendTypeParameters(type.getTypeParameters());
418 final String signature= type.getSuperclassTypeSignature();
419 if (signature != null) {
420 fBuffer.append(" extends "); //$NON-NLS-1$
421 fBuffer.append(Signature.toString(signature));
422 }
423 appendSuperInterfaceTypes(type);
424 fBuffer.append("{\n"); //$NON-NLS-1$
425 appendMembers(type, new SubProgressMonitor(monitor, 1));
426 fBuffer.append("}"); //$NON-NLS-1$
427 } else if (type.isEnum()) {
428 appendFlags(type);
429 fBuffer.append(" enum "); //$NON-NLS-1$
430 fBuffer.append(type.getElementName());
431 appendSuperInterfaceTypes(type);
432 fBuffer.append("{\n"); //$NON-NLS-1$
433 appendEnumConstants(type);
434 appendMembers(type, new SubProgressMonitor(monitor, 1));
435 fBuffer.append("}"); //$NON-NLS-1$
436 }
437 } finally {
438 monitor.done();
439 }
440 }
441
442 protected void appendTypeParameters(final ITypeParameter[] parameters) throws JavaModelException {
443 final int length= parameters.length;
444 if (length > 0)
445 fBuffer.append("<"); //$NON-NLS-1$
446 for (int index= 0; index < length; index++) {
447 if (index > 0)
448 fBuffer.append(","); //$NON-NLS-1$
449 final ITypeParameter parameter= parameters[index];
450 fBuffer.append(parameter.getElementName());
451 final String[] bounds= parameter.getBounds();
452 final int size= bounds.length;
453 if (size > 0)
454 fBuffer.append(" extends "); //$NON-NLS-1$
455 for (int offset= 0; offset < size; offset++) {
456 if (offset > 0)
457 fBuffer.append(" & "); //$NON-NLS-1$
458 fBuffer.append(bounds[offset]);
459 }
460 }
461 if (length > 0)
462 fBuffer.append(">"); //$NON-NLS-1$
463 }
464
465 /**
466 * Creates and returns a stub for the given top-level type.
467 *
468 * @param topLevelType the top-level type
469 * @param monitor the progress monitor, can be <code>null</code>
470 * @return the source stub
471 * @throws JavaModelException if this element does not exist or if an exception occurs while
472 * accessing its corresponding resource
473 */
474 public String createStub(IType topLevelType, IProgressMonitor monitor) throws JavaModelException {
475 Assert.isTrue(Checks.isTopLevel(topLevelType));
476 if (monitor == null)
477 monitor= new NullProgressMonitor();
478
479 fBuffer= new StringBuffer(2046);
480 appendTopLevelType(topLevelType, monitor);
481 String result= fBuffer.toString();
482 fBuffer= null;
483 return result;
484 }
485
486}