001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.corext.codemanipulation;
011:
012: import java.util.ArrayList;
013: import java.util.Arrays;
014: import java.util.HashSet;
015: import java.util.Iterator;
016: import java.util.List;
017: import java.util.Map;
018:
019: import org.eclipse.core.runtime.Assert;
020: import org.eclipse.core.runtime.CoreException;
021:
022: import org.eclipse.jdt.core.Flags;
023: import org.eclipse.jdt.core.ICompilationUnit;
024: import org.eclipse.jdt.core.IJavaProject;
025: import org.eclipse.jdt.core.JavaCore;
026: import org.eclipse.jdt.core.NamingConventions;
027: import org.eclipse.jdt.core.dom.AST;
028: import org.eclipse.jdt.core.dom.ASTNode;
029: import org.eclipse.jdt.core.dom.Annotation;
030: import org.eclipse.jdt.core.dom.Assignment;
031: import org.eclipse.jdt.core.dom.Block;
032: import org.eclipse.jdt.core.dom.Expression;
033: import org.eclipse.jdt.core.dom.FieldAccess;
034: import org.eclipse.jdt.core.dom.IMethodBinding;
035: import org.eclipse.jdt.core.dom.IPackageBinding;
036: import org.eclipse.jdt.core.dom.ITypeBinding;
037: import org.eclipse.jdt.core.dom.IVariableBinding;
038: import org.eclipse.jdt.core.dom.Javadoc;
039: import org.eclipse.jdt.core.dom.MethodDeclaration;
040: import org.eclipse.jdt.core.dom.MethodInvocation;
041: import org.eclipse.jdt.core.dom.Modifier;
042: import org.eclipse.jdt.core.dom.PrimitiveType;
043: import org.eclipse.jdt.core.dom.ReturnStatement;
044: import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
045: import org.eclipse.jdt.core.dom.Statement;
046: import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
047: import org.eclipse.jdt.core.dom.SuperMethodInvocation;
048: import org.eclipse.jdt.core.dom.Type;
049: import org.eclipse.jdt.core.dom.TypeParameter;
050: import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
051: import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
052: import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
053:
054: import org.eclipse.jdt.internal.corext.codemanipulation.AddDelegateMethodsOperation.DelegateEntry;
055: import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
056: import org.eclipse.jdt.internal.corext.dom.ASTNodes;
057: import org.eclipse.jdt.internal.corext.dom.Bindings;
058: import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
059:
060: import org.eclipse.jdt.ui.CodeGeneration;
061:
062: /**
063: * Utilities for code generation based on ast rewrite.
064: *
065: * @since 3.1
066: */
067: public final class StubUtility2 {
068:
069: public static void addOverrideAnnotation(ASTRewrite rewrite,
070: MethodDeclaration decl, IMethodBinding binding) {
071: String version = binding.getJavaElement().getJavaProject()
072: .getOption(JavaCore.COMPILER_COMPLIANCE, true);
073: if (!binding.getDeclaringClass().isInterface()
074: || !JavaModelUtil.isVersionLessThan(version,
075: JavaCore.VERSION_1_6)) {
076: final Annotation marker = rewrite.getAST()
077: .newMarkerAnnotation();
078: marker.setTypeName(rewrite.getAST().newSimpleName(
079: "Override")); //$NON-NLS-1$
080: rewrite.getListRewrite(decl,
081: MethodDeclaration.MODIFIERS2_PROPERTY).insertFirst(
082: marker, null);
083: }
084: }
085:
086: public static MethodDeclaration createConstructorStub(
087: ICompilationUnit unit, ASTRewrite rewrite,
088: ImportRewrite imports, IMethodBinding binding, String type,
089: int modifiers, boolean omitSuperForDefConst, boolean todo,
090: CodeGenerationSettings settings) throws CoreException {
091: AST ast = rewrite.getAST();
092: MethodDeclaration decl = ast.newMethodDeclaration();
093: decl.modifiers().addAll(
094: ASTNodeFactory.newModifiers(ast, modifiers
095: & ~Modifier.ABSTRACT & ~Modifier.NATIVE));
096: decl.setName(ast.newSimpleName(type));
097: decl.setConstructor(true);
098:
099: ITypeBinding[] typeParams = binding.getTypeParameters();
100: List typeParameters = decl.typeParameters();
101: for (int i = 0; i < typeParams.length; i++) {
102: ITypeBinding curr = typeParams[i];
103: TypeParameter newTypeParam = ast.newTypeParameter();
104: newTypeParam.setName(ast.newSimpleName(curr.getName()));
105: ITypeBinding[] typeBounds = curr.getTypeBounds();
106: if (typeBounds.length != 1
107: || !"java.lang.Object".equals(typeBounds[0].getQualifiedName())) {//$NON-NLS-1$
108: List newTypeBounds = newTypeParam.typeBounds();
109: for (int k = 0; k < typeBounds.length; k++) {
110: newTypeBounds.add(imports.addImport(typeBounds[k],
111: ast));
112: }
113: }
114: typeParameters.add(newTypeParam);
115: }
116:
117: List parameters = createParameters(unit.getJavaProject(),
118: imports, null, ast, binding, decl);
119:
120: List thrownExceptions = decl.thrownExceptions();
121: ITypeBinding[] excTypes = binding.getExceptionTypes();
122: for (int i = 0; i < excTypes.length; i++) {
123: String excTypeName = imports.addImport(excTypes[i]);
124: thrownExceptions.add(ASTNodeFactory.newName(ast,
125: excTypeName));
126: }
127:
128: Block body = ast.newBlock();
129: decl.setBody(body);
130:
131: String delimiter = StubUtility.getLineDelimiterUsed(unit);
132: String bodyStatement = ""; //$NON-NLS-1$
133: if (!omitSuperForDefConst || !parameters.isEmpty()) {
134: SuperConstructorInvocation invocation = ast
135: .newSuperConstructorInvocation();
136: SingleVariableDeclaration varDecl = null;
137: for (Iterator iterator = parameters.iterator(); iterator
138: .hasNext();) {
139: varDecl = (SingleVariableDeclaration) iterator.next();
140: invocation.arguments().add(
141: ast.newSimpleName(varDecl.getName()
142: .getIdentifier()));
143: }
144: bodyStatement = ASTNodes.asFormattedString(invocation, 0,
145: delimiter, unit.getJavaProject().getOptions(true));
146: }
147:
148: if (todo) {
149: String placeHolder = CodeGeneration.getMethodBodyContent(
150: unit, type, binding.getName(), true, bodyStatement,
151: delimiter);
152: if (placeHolder != null) {
153: ASTNode todoNode = rewrite.createStringPlaceholder(
154: placeHolder, ASTNode.RETURN_STATEMENT);
155: body.statements().add(todoNode);
156: }
157: } else {
158: ASTNode statementNode = rewrite.createStringPlaceholder(
159: bodyStatement, ASTNode.RETURN_STATEMENT);
160: body.statements().add(statementNode);
161: }
162:
163: if (settings != null && settings.createComments) {
164: String string = CodeGeneration.getMethodComment(unit, type,
165: decl, binding, delimiter);
166: if (string != null) {
167: Javadoc javadoc = (Javadoc) rewrite
168: .createStringPlaceholder(string,
169: ASTNode.JAVADOC);
170: decl.setJavadoc(javadoc);
171: }
172: }
173: return decl;
174: }
175:
176: public static MethodDeclaration createConstructorStub(
177: ICompilationUnit unit, ASTRewrite rewrite,
178: ImportRewrite imports, ITypeBinding typeBinding,
179: IMethodBinding super Constructor,
180: IVariableBinding[] variableBindings, int modifiers,
181: CodeGenerationSettings settings) throws CoreException {
182: AST ast = rewrite.getAST();
183:
184: MethodDeclaration decl = ast.newMethodDeclaration();
185: decl.modifiers().addAll(
186: ASTNodeFactory.newModifiers(ast, modifiers
187: & ~Modifier.ABSTRACT & ~Modifier.NATIVE));
188: decl.setName(ast.newSimpleName(typeBinding.getName()));
189: decl.setConstructor(true);
190:
191: List parameters = decl.parameters();
192: if (super Constructor != null) {
193: ITypeBinding[] typeParams = super Constructor
194: .getTypeParameters();
195: List typeParameters = decl.typeParameters();
196: for (int i = 0; i < typeParams.length; i++) {
197: ITypeBinding curr = typeParams[i];
198: TypeParameter newTypeParam = ast.newTypeParameter();
199: newTypeParam.setName(ast.newSimpleName(curr.getName()));
200: ITypeBinding[] typeBounds = curr.getTypeBounds();
201: if (typeBounds.length != 1
202: || !"java.lang.Object".equals(typeBounds[0].getQualifiedName())) {//$NON-NLS-1$
203: List newTypeBounds = newTypeParam.typeBounds();
204: for (int k = 0; k < typeBounds.length; k++) {
205: newTypeBounds.add(imports.addImport(
206: typeBounds[k], ast));
207: }
208: }
209: typeParameters.add(newTypeParam);
210: }
211:
212: createParameters(unit.getJavaProject(), imports, null, ast,
213: super Constructor, decl);
214:
215: List thrownExceptions = decl.thrownExceptions();
216: ITypeBinding[] excTypes = super Constructor
217: .getExceptionTypes();
218: for (int i = 0; i < excTypes.length; i++) {
219: String excTypeName = imports.addImport(excTypes[i]);
220: thrownExceptions.add(ASTNodeFactory.newName(ast,
221: excTypeName));
222: }
223: }
224:
225: Block body = ast.newBlock();
226: decl.setBody(body);
227:
228: String delimiter = StubUtility.getLineDelimiterUsed(unit);
229:
230: if (super Constructor != null) {
231: SuperConstructorInvocation invocation = ast
232: .newSuperConstructorInvocation();
233: SingleVariableDeclaration varDecl = null;
234: for (Iterator iterator = parameters.iterator(); iterator
235: .hasNext();) {
236: varDecl = (SingleVariableDeclaration) iterator.next();
237: invocation.arguments().add(
238: ast.newSimpleName(varDecl.getName()
239: .getIdentifier()));
240: }
241: body.statements().add(invocation);
242: }
243:
244: List prohibited = new ArrayList();
245: for (final Iterator iterator = parameters.iterator(); iterator
246: .hasNext();)
247: prohibited
248: .add(((SingleVariableDeclaration) iterator.next())
249: .getName().getIdentifier());
250: String param = null;
251: List list = new ArrayList(prohibited);
252: String[] excluded = null;
253: for (int i = 0; i < variableBindings.length; i++) {
254: SingleVariableDeclaration var = ast
255: .newSingleVariableDeclaration();
256: var.setType(imports.addImport(
257: variableBindings[i].getType(), ast));
258: excluded = new String[list.size()];
259: list.toArray(excluded);
260: param = getParameterName(unit, variableBindings[i],
261: excluded);
262: list.add(param);
263: var.setName(ast.newSimpleName(param));
264: parameters.add(var);
265: }
266:
267: list = new ArrayList(prohibited);
268: for (int i = 0; i < variableBindings.length; i++) {
269: excluded = new String[list.size()];
270: list.toArray(excluded);
271: final String paramName = getParameterName(unit,
272: variableBindings[i], excluded);
273: list.add(paramName);
274: final String fieldName = variableBindings[i].getName();
275: Expression expression = null;
276: if (paramName.equals(fieldName) || settings.useKeywordThis) {
277: FieldAccess access = ast.newFieldAccess();
278: access.setExpression(ast.newThisExpression());
279: access.setName(ast.newSimpleName(fieldName));
280: expression = access;
281: } else
282: expression = ast.newSimpleName(fieldName);
283: Assignment assignment = ast.newAssignment();
284: assignment.setLeftHandSide(expression);
285: assignment.setRightHandSide(ast.newSimpleName(paramName));
286: assignment.setOperator(Assignment.Operator.ASSIGN);
287: body.statements().add(
288: ast.newExpressionStatement(assignment));
289: }
290:
291: if (settings != null && settings.createComments) {
292: String string = CodeGeneration.getMethodComment(unit,
293: typeBinding.getName(), decl, super Constructor,
294: delimiter);
295: if (string != null) {
296: Javadoc javadoc = (Javadoc) rewrite
297: .createStringPlaceholder(string,
298: ASTNode.JAVADOC);
299: decl.setJavadoc(javadoc);
300: }
301: }
302: return decl;
303: }
304:
305: public static MethodDeclaration createDelegationStub(
306: ICompilationUnit unit, ASTRewrite rewrite,
307: ImportRewrite imports, ImportRewriteContext context,
308: IMethodBinding delegate, IVariableBinding delegatingField,
309: CodeGenerationSettings settings) throws CoreException {
310: Assert.isNotNull(delegate);
311: Assert.isNotNull(delegatingField);
312: Assert.isNotNull(settings);
313:
314: AST ast = rewrite.getAST();
315:
316: MethodDeclaration decl = ast.newMethodDeclaration();
317: decl.modifiers().addAll(
318: ASTNodeFactory.newModifiers(ast, delegate
319: .getModifiers()
320: & ~Modifier.SYNCHRONIZED
321: & ~Modifier.ABSTRACT
322: & ~Modifier.NATIVE));
323:
324: decl.setName(ast.newSimpleName(delegate.getName()));
325: decl.setConstructor(false);
326:
327: ITypeBinding[] typeParams = delegate.getTypeParameters();
328: List typeParameters = decl.typeParameters();
329: for (int i = 0; i < typeParams.length; i++) {
330: ITypeBinding curr = typeParams[i];
331: TypeParameter newTypeParam = ast.newTypeParameter();
332: newTypeParam.setName(ast.newSimpleName(curr.getName()));
333: ITypeBinding[] typeBounds = curr.getTypeBounds();
334: if (typeBounds.length != 1
335: || !"java.lang.Object".equals(typeBounds[0].getQualifiedName())) {//$NON-NLS-1$
336: List newTypeBounds = newTypeParam.typeBounds();
337: for (int k = 0; k < typeBounds.length; k++) {
338: newTypeBounds.add(imports.addImport(typeBounds[k],
339: ast, context));
340: }
341: }
342: typeParameters.add(newTypeParam);
343: }
344:
345: decl.setReturnType2(imports.addImport(delegate.getReturnType(),
346: ast, context));
347:
348: List parameters = decl.parameters();
349: ITypeBinding[] params = delegate.getParameterTypes();
350: String[] paramNames = StubUtility.suggestArgumentNames(unit
351: .getJavaProject(), delegate);
352: for (int i = 0; i < params.length; i++) {
353: SingleVariableDeclaration varDecl = ast
354: .newSingleVariableDeclaration();
355: if (params[i].isWildcardType() && !params[i].isUpperbound())
356: varDecl.setType(imports.addImport(params[i].getBound(),
357: ast, context));
358: else {
359: if (delegate.isVarargs() && params[i].isArray()
360: && i == params.length - 1) {
361: StringBuffer buffer = new StringBuffer(imports
362: .addImport(params[i].getElementType(),
363: context));
364: for (int dim = 1; dim < params[i].getDimensions(); dim++)
365: buffer.append("[]"); //$NON-NLS-1$
366: varDecl.setType(ASTNodeFactory.newType(ast, buffer
367: .toString()));
368: varDecl.setVarargs(true);
369: } else
370: varDecl.setType(imports.addImport(params[i], ast,
371: context));
372: }
373: varDecl.setName(ast.newSimpleName(paramNames[i]));
374: parameters.add(varDecl);
375: }
376:
377: List thrownExceptions = decl.thrownExceptions();
378: ITypeBinding[] excTypes = delegate.getExceptionTypes();
379: for (int i = 0; i < excTypes.length; i++) {
380: String excTypeName = imports
381: .addImport(excTypes[i], context);
382: thrownExceptions.add(ASTNodeFactory.newName(ast,
383: excTypeName));
384: }
385:
386: Block body = ast.newBlock();
387: decl.setBody(body);
388:
389: String delimiter = StubUtility.getLineDelimiterUsed(unit);
390:
391: Statement statement = null;
392: MethodInvocation invocation = ast.newMethodInvocation();
393: invocation.setName(ast.newSimpleName(delegate.getName()));
394: List arguments = invocation.arguments();
395: for (int i = 0; i < params.length; i++)
396: arguments.add(ast.newSimpleName(paramNames[i]));
397: if (settings.useKeywordThis) {
398: FieldAccess access = ast.newFieldAccess();
399: access.setExpression(ast.newThisExpression());
400: access
401: .setName(ast.newSimpleName(delegatingField
402: .getName()));
403: invocation.setExpression(access);
404: } else
405: invocation.setExpression(ast.newSimpleName(delegatingField
406: .getName()));
407: if (delegate.getReturnType().isPrimitive()
408: && delegate.getReturnType().getName().equals("void")) {//$NON-NLS-1$
409: statement = ast.newExpressionStatement(invocation);
410: } else {
411: ReturnStatement returnStatement = ast.newReturnStatement();
412: returnStatement.setExpression(invocation);
413: statement = returnStatement;
414: }
415: body.statements().add(statement);
416:
417: ITypeBinding declaringType = delegatingField
418: .getDeclaringClass();
419: if (declaringType == null) { // can be null for
420: return decl;
421: }
422:
423: String qualifiedName = declaringType.getQualifiedName();
424: IPackageBinding packageBinding = declaringType.getPackage();
425: if (packageBinding != null) {
426: if (packageBinding.getName().length() > 0
427: && qualifiedName.startsWith(packageBinding
428: .getName()))
429: qualifiedName = qualifiedName.substring(packageBinding
430: .getName().length());
431: }
432:
433: if (settings.createComments) {
434: /*
435: * TODO: have API for delegate method comments This is an inlined
436: * version of
437: * {@link CodeGeneration#getMethodComment(ICompilationUnit, String, MethodDeclaration, IMethodBinding, String)}
438: */
439: delegate = delegate.getMethodDeclaration();
440: String declaringClassQualifiedName = delegate
441: .getDeclaringClass().getQualifiedName();
442: String linkToMethodName = delegate.getName();
443: String[] parameterTypesQualifiedNames = StubUtility
444: .getParameterTypeNamesForSeeTag(delegate);
445: String string = StubUtility.getMethodComment(unit,
446: qualifiedName, decl, delegate.isDeprecated(),
447: linkToMethodName, declaringClassQualifiedName,
448: parameterTypesQualifiedNames, true, delimiter);
449: if (string != null) {
450: Javadoc javadoc = (Javadoc) rewrite
451: .createStringPlaceholder(string,
452: ASTNode.JAVADOC);
453: decl.setJavadoc(javadoc);
454: }
455: }
456: return decl;
457: }
458:
459: public static MethodDeclaration createImplementationStub(
460: ICompilationUnit unit, ASTRewrite rewrite,
461: ImportRewrite imports, ImportRewriteContext context,
462: IMethodBinding binding, String type,
463: CodeGenerationSettings settings, boolean deferred)
464: throws CoreException {
465: Assert.isNotNull(imports);
466: Assert.isNotNull(rewrite);
467:
468: AST ast = rewrite.getAST();
469:
470: MethodDeclaration decl = ast.newMethodDeclaration();
471: decl.modifiers().addAll(
472: getImplementationModifiers(ast, binding, deferred));
473:
474: decl.setName(ast.newSimpleName(binding.getName()));
475: decl.setConstructor(false);
476:
477: ITypeBinding[] typeParams = binding.getTypeParameters();
478: List typeParameters = decl.typeParameters();
479: for (int i = 0; i < typeParams.length; i++) {
480: ITypeBinding curr = typeParams[i];
481: TypeParameter newTypeParam = ast.newTypeParameter();
482: newTypeParam.setName(ast.newSimpleName(curr.getName()));
483: ITypeBinding[] typeBounds = curr.getTypeBounds();
484: if (typeBounds.length != 1
485: || !"java.lang.Object".equals(typeBounds[0].getQualifiedName())) {//$NON-NLS-1$
486: List newTypeBounds = newTypeParam.typeBounds();
487: for (int k = 0; k < typeBounds.length; k++) {
488: newTypeBounds.add(imports.addImport(typeBounds[k],
489: ast, context));
490: }
491: }
492: typeParameters.add(newTypeParam);
493: }
494:
495: decl.setReturnType2(imports.addImport(binding.getReturnType(),
496: ast, context));
497:
498: List parameters = createParameters(unit.getJavaProject(),
499: imports, context, ast, binding, decl);
500:
501: List thrownExceptions = decl.thrownExceptions();
502: ITypeBinding[] excTypes = binding.getExceptionTypes();
503: for (int i = 0; i < excTypes.length; i++) {
504: String excTypeName = imports
505: .addImport(excTypes[i], context);
506: thrownExceptions.add(ASTNodeFactory.newName(ast,
507: excTypeName));
508: }
509:
510: String delimiter = unit.findRecommendedLineSeparator();
511: if (!deferred) {
512: Map options = unit.getJavaProject().getOptions(true);
513:
514: Block body = ast.newBlock();
515: decl.setBody(body);
516:
517: String bodyStatement = ""; //$NON-NLS-1$
518: ITypeBinding declaringType = binding.getDeclaringClass();
519: if (Modifier.isAbstract(binding.getModifiers())
520: || declaringType.isAnnotation()
521: || declaringType.isInterface()) {
522: Expression expression = ASTNodeFactory
523: .newDefaultExpression(ast, decl
524: .getReturnType2(), decl
525: .getExtraDimensions());
526: if (expression != null) {
527: ReturnStatement returnStatement = ast
528: .newReturnStatement();
529: returnStatement.setExpression(expression);
530: bodyStatement = ASTNodes.asFormattedString(
531: returnStatement, 0, delimiter, options);
532: }
533: } else {
534: SuperMethodInvocation invocation = ast
535: .newSuperMethodInvocation();
536: invocation
537: .setName(ast.newSimpleName(binding.getName()));
538: SingleVariableDeclaration varDecl = null;
539: for (Iterator iterator = parameters.iterator(); iterator
540: .hasNext();) {
541: varDecl = (SingleVariableDeclaration) iterator
542: .next();
543: invocation.arguments().add(
544: ast.newSimpleName(varDecl.getName()
545: .getIdentifier()));
546: }
547: Expression expression = invocation;
548: Type returnType = decl.getReturnType2();
549: if (returnType instanceof PrimitiveType
550: && ((PrimitiveType) returnType)
551: .getPrimitiveTypeCode().equals(
552: PrimitiveType.VOID)) {
553: bodyStatement = ASTNodes.asFormattedString(ast
554: .newExpressionStatement(expression), 0,
555: delimiter, options);
556: } else {
557: ReturnStatement returnStatement = ast
558: .newReturnStatement();
559: returnStatement.setExpression(expression);
560: bodyStatement = ASTNodes.asFormattedString(
561: returnStatement, 0, delimiter, options);
562: }
563: }
564:
565: String placeHolder = CodeGeneration.getMethodBodyContent(
566: unit, type, binding.getName(), false,
567: bodyStatement, delimiter);
568: if (placeHolder != null) {
569: ASTNode todoNode = rewrite.createStringPlaceholder(
570: placeHolder, ASTNode.RETURN_STATEMENT);
571: body.statements().add(todoNode);
572: }
573: }
574:
575: if (settings != null && settings.createComments) {
576: String string = CodeGeneration.getMethodComment(unit, type,
577: decl, binding, delimiter);
578: if (string != null) {
579: Javadoc javadoc = (Javadoc) rewrite
580: .createStringPlaceholder(string,
581: ASTNode.JAVADOC);
582: decl.setJavadoc(javadoc);
583: }
584: }
585: if (settings != null && settings.overrideAnnotation
586: && JavaModelUtil.is50OrHigher(unit.getJavaProject())) {
587: addOverrideAnnotation(rewrite, decl, binding);
588: }
589:
590: return decl;
591: }
592:
593: private static List createParameters(IJavaProject project,
594: ImportRewrite imports, ImportRewriteContext context,
595: AST ast, IMethodBinding binding, MethodDeclaration decl) {
596: List parameters = decl.parameters();
597: ITypeBinding[] params = binding.getParameterTypes();
598: String[] paramNames = StubUtility.suggestArgumentNames(project,
599: binding);
600: for (int i = 0; i < params.length; i++) {
601: SingleVariableDeclaration var = ast
602: .newSingleVariableDeclaration();
603: if (binding.isVarargs() && params[i].isArray()
604: && i == params.length - 1) {
605: StringBuffer buffer = new StringBuffer(imports
606: .addImport(params[i].getElementType(), context));
607: for (int dim = 1; dim < params[i].getDimensions(); dim++)
608: buffer.append("[]"); //$NON-NLS-1$
609: var.setType(ASTNodeFactory.newType(ast, buffer
610: .toString()));
611: var.setVarargs(true);
612: } else
613: var.setType(imports.addImport(params[i], ast, context));
614: var.setName(ast.newSimpleName(paramNames[i]));
615: parameters.add(var);
616: }
617: return parameters;
618: }
619:
620: private static IMethodBinding findMethodBinding(
621: IMethodBinding method, List allMethods) {
622: for (int i = 0; i < allMethods.size(); i++) {
623: IMethodBinding curr = (IMethodBinding) allMethods.get(i);
624: if (Bindings.isSubsignature(method, curr)) {
625: return curr;
626: }
627: }
628: return null;
629: }
630:
631: private static IMethodBinding findOverridingMethod(
632: IMethodBinding method, List allMethods) {
633: for (int i = 0; i < allMethods.size(); i++) {
634: IMethodBinding curr = (IMethodBinding) allMethods.get(i);
635: if (Bindings.areOverriddenMethods(curr, method)
636: || Bindings.isSubsignature(curr, method))
637: return curr;
638: }
639: return null;
640: }
641:
642: private static void findUnimplementedInterfaceMethods(
643: ITypeBinding typeBinding, HashSet visited,
644: ArrayList allMethods, IPackageBinding currPack,
645: ArrayList toImplement) {
646: if (visited.add(typeBinding)) {
647: IMethodBinding[] typeMethods = typeBinding
648: .getDeclaredMethods();
649: for (int i = 0; i < typeMethods.length; i++) {
650: IMethodBinding curr = typeMethods[i];
651: IMethodBinding impl = findMethodBinding(curr,
652: allMethods);
653: if (impl == null
654: || !Bindings.isVisibleInHierarchy(impl,
655: currPack)) {
656: if (impl != null)
657: allMethods.remove(impl);
658: toImplement.add(curr);
659: allMethods.add(curr);
660: }
661: }
662: ITypeBinding[] super Interfaces = typeBinding
663: .getInterfaces();
664: for (int i = 0; i < super Interfaces.length; i++)
665: findUnimplementedInterfaceMethods(super Interfaces[i],
666: visited, allMethods, currPack, toImplement);
667: }
668: }
669:
670: public static DelegateEntry[] getDelegatableMethods(
671: ITypeBinding binding) {
672: final List tuples = new ArrayList();
673: final List declared = new ArrayList();
674: IMethodBinding[] typeMethods = binding.getDeclaredMethods();
675: for (int index = 0; index < typeMethods.length; index++)
676: declared.add(typeMethods[index]);
677: IVariableBinding[] typeFields = binding.getDeclaredFields();
678: for (int index = 0; index < typeFields.length; index++) {
679: IVariableBinding fieldBinding = typeFields[index];
680: if (fieldBinding.isField()
681: && !fieldBinding.isEnumConstant()
682: && !fieldBinding.isSynthetic())
683: getDelegatableMethods(new ArrayList(declared),
684: fieldBinding, fieldBinding.getType(), binding,
685: tuples);
686: }
687: // list of tuple<IVariableBinding, IMethodBinding>
688: return (DelegateEntry[]) tuples
689: .toArray(new DelegateEntry[tuples.size()]);
690: }
691:
692: private static void getDelegatableMethods(List methods,
693: IVariableBinding fieldBinding, ITypeBinding typeBinding,
694: ITypeBinding binding, List/*DelegateEntry*/result) {
695: boolean match = false;
696: if (typeBinding.isTypeVariable()) {
697: ITypeBinding[] typeBounds = typeBinding.getTypeBounds();
698: if (typeBounds.length > 0) {
699: for (int i = 0; i < typeBounds.length; i++) {
700: getDelegatableMethods(methods, fieldBinding,
701: typeBounds[i], binding, result);
702: }
703: } else {
704: ITypeBinding objectBinding = Bindings
705: .findTypeInHierarchy(binding,
706: "java.lang.Object"); //$NON-NLS-1$
707: if (objectBinding != null) {
708: getDelegatableMethods(methods, fieldBinding,
709: objectBinding, binding, result);
710: }
711: }
712: } else {
713: IMethodBinding[] candidates = getDelegateCandidates(
714: typeBinding, binding);
715: for (int index = 0; index < candidates.length; index++) {
716: match = false;
717: final IMethodBinding methodBinding = candidates[index];
718: for (int offset = 0; offset < methods.size() && !match; offset++) {
719: if (Bindings.areOverriddenMethods(
720: (IMethodBinding) methods.get(offset),
721: methodBinding))
722: match = true;
723: }
724: if (!match) {
725: result.add(new DelegateEntry(methodBinding,
726: fieldBinding));
727: methods.add(methodBinding);
728: }
729: }
730: final ITypeBinding super class = typeBinding.getSuperclass();
731: if (super class != null)
732: getDelegatableMethods(methods, fieldBinding,
733: super class, binding, result);
734: ITypeBinding[] super Interfaces = typeBinding
735: .getInterfaces();
736: for (int offset = 0; offset < super Interfaces.length; offset++)
737: getDelegatableMethods(methods, fieldBinding,
738: super Interfaces[offset], binding, result);
739: }
740: }
741:
742: private static IMethodBinding[] getDelegateCandidates(
743: ITypeBinding binding, ITypeBinding hierarchy) {
744: List allMethods = new ArrayList();
745: boolean isInterface = binding.isInterface();
746: IMethodBinding[] typeMethods = binding.getDeclaredMethods();
747: for (int index = 0; index < typeMethods.length; index++) {
748: final int modifiers = typeMethods[index].getModifiers();
749: if (!typeMethods[index].isConstructor()
750: && !Modifier.isStatic(modifiers)
751: && (isInterface || Modifier.isPublic(modifiers))) {
752: IMethodBinding result = Bindings
753: .findOverriddenMethodInHierarchy(hierarchy,
754: typeMethods[index]);
755: if (result != null
756: && Flags.isFinal(result.getModifiers()))
757: continue;
758: ITypeBinding[] parameterBindings = typeMethods[index]
759: .getParameterTypes();
760: boolean upper = false;
761: for (int offset = 0; offset < parameterBindings.length; offset++) {
762: if (parameterBindings[offset].isWildcardType()
763: && parameterBindings[offset].isUpperbound())
764: upper = true;
765: }
766: if (!upper)
767: allMethods.add(typeMethods[index]);
768: }
769: }
770: return (IMethodBinding[]) allMethods
771: .toArray(new IMethodBinding[allMethods.size()]);
772: }
773:
774: private static List getImplementationModifiers(AST ast,
775: IMethodBinding method, boolean deferred) {
776: int modifiers = method.getModifiers() & ~Modifier.ABSTRACT
777: & ~Modifier.NATIVE & ~Modifier.PRIVATE;
778: if (deferred) {
779: modifiers = modifiers & ~Modifier.PROTECTED;
780: modifiers = modifiers | Modifier.PUBLIC;
781: }
782: return ASTNodeFactory.newModifiers(ast, modifiers);
783: }
784:
785: public static IMethodBinding[] getOverridableMethods(AST ast,
786: ITypeBinding typeBinding, boolean isSubType) {
787: List allMethods = new ArrayList();
788: IMethodBinding[] typeMethods = typeBinding.getDeclaredMethods();
789: for (int index = 0; index < typeMethods.length; index++) {
790: final int modifiers = typeMethods[index].getModifiers();
791: if (!typeMethods[index].isConstructor()
792: && !Modifier.isStatic(modifiers)
793: && !Modifier.isPrivate(modifiers))
794: allMethods.add(typeMethods[index]);
795: }
796: ITypeBinding clazz = typeBinding.getSuperclass();
797: while (clazz != null) {
798: IMethodBinding[] methods = clazz.getDeclaredMethods();
799: for (int offset = 0; offset < methods.length; offset++) {
800: final int modifiers = methods[offset].getModifiers();
801: if (!methods[offset].isConstructor()
802: && !Modifier.isStatic(modifiers)
803: && !Modifier.isPrivate(modifiers)) {
804: if (findOverridingMethod(methods[offset],
805: allMethods) == null)
806: allMethods.add(methods[offset]);
807: }
808: }
809: clazz = clazz.getSuperclass();
810: }
811: clazz = typeBinding;
812: while (clazz != null) {
813: ITypeBinding[] super Interfaces = clazz.getInterfaces();
814: for (int index = 0; index < super Interfaces.length; index++) {
815: getOverridableMethods(ast, super Interfaces[index],
816: allMethods);
817: }
818: clazz = clazz.getSuperclass();
819: }
820: if (typeBinding.isInterface())
821: getOverridableMethods(
822: ast,
823: ast.resolveWellKnownType("java.lang.Object"), allMethods); //$NON-NLS-1$
824: if (!isSubType)
825: allMethods.removeAll(Arrays.asList(typeMethods));
826: int modifiers = 0;
827: if (!typeBinding.isInterface()) {
828: for (int index = allMethods.size() - 1; index >= 0; index--) {
829: IMethodBinding method = (IMethodBinding) allMethods
830: .get(index);
831: modifiers = method.getModifiers();
832: if (Modifier.isFinal(modifiers))
833: allMethods.remove(index);
834: }
835: }
836: return (IMethodBinding[]) allMethods
837: .toArray(new IMethodBinding[allMethods.size()]);
838: }
839:
840: private static void getOverridableMethods(AST ast,
841: ITypeBinding super Binding, List allMethods) {
842: IMethodBinding[] methods = super Binding.getDeclaredMethods();
843: for (int offset = 0; offset < methods.length; offset++) {
844: final int modifiers = methods[offset].getModifiers();
845: if (!methods[offset].isConstructor()
846: && !Modifier.isStatic(modifiers)
847: && !Modifier.isPrivate(modifiers)) {
848: if (findOverridingMethod(methods[offset], allMethods) == null
849: && !Modifier.isStatic(modifiers))
850: allMethods.add(methods[offset]);
851: }
852: }
853: ITypeBinding[] super Interfaces = super Binding.getInterfaces();
854: for (int index = 0; index < super Interfaces.length; index++) {
855: getOverridableMethods(ast, super Interfaces[index],
856: allMethods);
857: }
858: }
859:
860: private static String getParameterName(ICompilationUnit unit,
861: IVariableBinding binding, String[] excluded) {
862: final String name = NamingConventions
863: .removePrefixAndSuffixForFieldName(unit
864: .getJavaProject(), binding.getName(), binding
865: .getModifiers());
866: return StubUtility.suggestArgumentName(unit.getJavaProject(),
867: name, excluded);
868: }
869:
870: public static IMethodBinding[] getUnimplementedMethods(
871: ITypeBinding typeBinding) {
872: ArrayList allMethods = new ArrayList();
873: ArrayList toImplement = new ArrayList();
874:
875: IMethodBinding[] typeMethods = typeBinding.getDeclaredMethods();
876: for (int i = 0; i < typeMethods.length; i++) {
877: IMethodBinding curr = typeMethods[i];
878: int modifiers = curr.getModifiers();
879: if (!curr.isConstructor() && !Modifier.isStatic(modifiers)
880: && !Modifier.isPrivate(modifiers)) {
881: allMethods.add(curr);
882: }
883: }
884:
885: ITypeBinding super Class = typeBinding.getSuperclass();
886: while (super Class != null) {
887: typeMethods = super Class.getDeclaredMethods();
888: for (int i = 0; i < typeMethods.length; i++) {
889: IMethodBinding curr = typeMethods[i];
890: int modifiers = curr.getModifiers();
891: if (!curr.isConstructor()
892: && !Modifier.isStatic(modifiers)
893: && !Modifier.isPrivate(modifiers)) {
894: if (findMethodBinding(curr, allMethods) == null) {
895: allMethods.add(curr);
896: }
897: }
898: }
899: super Class = super Class.getSuperclass();
900: }
901:
902: for (int i = 0; i < allMethods.size(); i++) {
903: IMethodBinding curr = (IMethodBinding) allMethods.get(i);
904: int modifiers = curr.getModifiers();
905: if ((Modifier.isAbstract(modifiers) || curr
906: .getDeclaringClass().isInterface())
907: && (typeBinding != curr.getDeclaringClass())) {
908: // implement all abstract methods
909: toImplement.add(curr);
910: }
911: }
912:
913: HashSet visited = new HashSet();
914: ITypeBinding curr = typeBinding;
915: while (curr != null) {
916: ITypeBinding[] super Interfaces = curr.getInterfaces();
917: for (int i = 0; i < super Interfaces.length; i++) {
918: findUnimplementedInterfaceMethods(super Interfaces[i],
919: visited, allMethods, typeBinding.getPackage(),
920: toImplement);
921: }
922: curr = curr.getSuperclass();
923: }
924:
925: return (IMethodBinding[]) toImplement
926: .toArray(new IMethodBinding[toImplement.size()]);
927: }
928:
929: public static IMethodBinding[] getVisibleConstructors(
930: ITypeBinding binding, boolean accountExisting,
931: boolean proposeDefault) {
932: List constructorMethods = new ArrayList();
933: List existingConstructors = null;
934: ITypeBinding super Type = binding.getSuperclass();
935: if (super Type == null)
936: return new IMethodBinding[0];
937: if (accountExisting) {
938: IMethodBinding[] methods = binding.getDeclaredMethods();
939: existingConstructors = new ArrayList(methods.length);
940: for (int index = 0; index < methods.length; index++) {
941: IMethodBinding method = methods[index];
942: if (method.isConstructor()
943: && !method.isDefaultConstructor())
944: existingConstructors.add(method);
945: }
946: }
947: if (existingConstructors != null)
948: constructorMethods.addAll(existingConstructors);
949: IMethodBinding[] methods = binding.getDeclaredMethods();
950: IMethodBinding[] super Methods = super Type.getDeclaredMethods();
951: for (int index = 0; index < super Methods.length; index++) {
952: IMethodBinding method = super Methods[index];
953: if (method.isConstructor()) {
954: if (Bindings.isVisibleInHierarchy(method, binding
955: .getPackage())
956: && (!accountExisting || !Bindings
957: .containsSignatureEquivalentConstructor(
958: methods, method)))
959: constructorMethods.add(method);
960: }
961: }
962: if (existingConstructors != null)
963: constructorMethods.removeAll(existingConstructors);
964: if (constructorMethods.isEmpty()) {
965: super Type = binding;
966: while (super Type.getSuperclass() != null)
967: super Type = super Type.getSuperclass();
968: IMethodBinding method = Bindings.findMethodInType(
969: super Type, "Object", new ITypeBinding[0]); //$NON-NLS-1$
970: if (method != null) {
971: if ((proposeDefault || (!accountExisting || (existingConstructors == null || existingConstructors
972: .isEmpty())))
973: && (!accountExisting || !Bindings
974: .containsSignatureEquivalentConstructor(
975: methods, method)))
976: constructorMethods.add(method);
977: }
978: }
979: return (IMethodBinding[]) constructorMethods
980: .toArray(new IMethodBinding[constructorMethods.size()]);
981: }
982:
983: /**
984: * Creates a new stub utility.
985: */
986: private StubUtility2() {
987: // Not for instantiation
988: }
989: }
|