/*******************************************************************************
* Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.ext.java.jdt.internal.corext.codemanipulation;
import org.eclipse.che.ide.ext.java.jdt.core.Flags;
import org.eclipse.che.ide.ext.java.jdt.core.JavaCore;
import org.eclipse.che.ide.ext.java.jdt.core.dom.AST;
import org.eclipse.che.ide.ext.java.jdt.core.dom.ASTNode;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Annotation;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Assignment;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Block;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Expression;
import org.eclipse.che.ide.ext.java.jdt.core.dom.FieldAccess;
import org.eclipse.che.ide.ext.java.jdt.core.dom.IMethodBinding;
import org.eclipse.che.ide.ext.java.jdt.core.dom.IPackageBinding;
import org.eclipse.che.ide.ext.java.jdt.core.dom.ITypeBinding;
import org.eclipse.che.ide.ext.java.jdt.core.dom.IVariableBinding;
import org.eclipse.che.ide.ext.java.jdt.core.dom.MethodDeclaration;
import org.eclipse.che.ide.ext.java.jdt.core.dom.MethodInvocation;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Modifier;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Name;
import org.eclipse.che.ide.ext.java.jdt.core.dom.PrimitiveType;
import org.eclipse.che.ide.ext.java.jdt.core.dom.ReturnStatement;
import org.eclipse.che.ide.ext.java.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Statement;
import org.eclipse.che.ide.ext.java.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.che.ide.ext.java.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.che.ide.ext.java.jdt.core.dom.Type;
import org.eclipse.che.ide.ext.java.jdt.core.dom.TypeParameter;
import org.eclipse.che.ide.ext.java.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.che.ide.ext.java.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.che.ide.ext.java.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.che.ide.ext.java.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.dom.ASTNodeFactory;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.che.ide.ext.java.jdt.internal.corext.dom.Bindings;
import org.eclipse.che.ide.runtime.Assert;
import org.eclipse.che.ide.runtime.CoreException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
//import org.eclipse.jdt.ui.CodeGeneration;
/**
* Utilities for code generation based on AST rewrite.
*
* @since 3.1
*/
public final class StubUtility2 {
public static void addOverrideAnnotation(ASTRewrite rewrite, MethodDeclaration decl, IMethodBinding binding) {
// String version = JavaCore.getOption(JavaCore.COMPILER_COMPLIANCE);
// if (!binding.getDeclaringClass().isInterface())
// {
final Annotation marker = rewrite.getAST().newMarkerAnnotation();
marker.setTypeName(rewrite.getAST().newSimpleName("Override")); //$NON-NLS-1$
rewrite.getListRewrite(decl, MethodDeclaration.MODIFIERS2_PROPERTY).insertFirst(marker, null);
// }
}
public static MethodDeclaration createConstructorStub(ASTRewrite rewrite, ImportRewrite imports,
ImportRewriteContext context, IMethodBinding binding, String type, int modifiers,
boolean omitSuperForDefConst,
boolean todo, CodeGenerationSettings settings) throws CoreException {
AST ast = rewrite.getAST();
MethodDeclaration decl = ast.newMethodDeclaration();
decl.modifiers().addAll(ASTNodeFactory.newModifiers(ast, modifiers & ~Modifier.ABSTRACT & ~Modifier.NATIVE));
decl.setName(ast.newSimpleName(type));
decl.setConstructor(true);
ITypeBinding[] typeParams = binding.getTypeParameters();
List<TypeParameter> typeParameters = decl.typeParameters();
for (int i = 0; i < typeParams.length; i++) {
ITypeBinding curr = typeParams[i];
TypeParameter newTypeParam = ast.newTypeParameter();
newTypeParam.setName(ast.newSimpleName(curr.getName()));
ITypeBinding[] typeBounds = curr.getTypeBounds();
if (typeBounds.length != 1 || !"java.lang.Object".equals(typeBounds[0].getQualifiedName())) {//$NON-NLS-1$
List<Type> newTypeBounds = newTypeParam.typeBounds();
for (int k = 0; k < typeBounds.length; k++) {
newTypeBounds.add(imports.addImport(typeBounds[k], ast, context));
}
}
typeParameters.add(newTypeParam);
}
List<SingleVariableDeclaration> parameters = createParameters(imports, context, ast, binding, decl);
List<Name> thrownExceptions = decl.thrownExceptions();
ITypeBinding[] excTypes = binding.getExceptionTypes();
for (int i = 0; i < excTypes.length; i++) {
String excTypeName = imports.addImport(excTypes[i], context);
thrownExceptions.add(ASTNodeFactory.newName(ast, excTypeName));
}
Block body = ast.newBlock();
decl.setBody(body);
String delimiter = "\n";//StubUtility.getLineDelimiterUsed(unit);
String bodyStatement = ""; //$NON-NLS-1$
if (!omitSuperForDefConst || !parameters.isEmpty()) {
SuperConstructorInvocation invocation = ast.newSuperConstructorInvocation();
SingleVariableDeclaration varDecl = null;
for (Iterator<SingleVariableDeclaration> iterator = parameters.iterator(); iterator.hasNext(); ) {
varDecl = iterator.next();
invocation.arguments().add(ast.newSimpleName(varDecl.getName().getIdentifier()));
}
bodyStatement = ASTNodes.asFormattedString(invocation, 0, delimiter, JavaCore.getOptions());
}
if (todo) {
//TDO
// String placeHolder =
// CodeGeneration.getMethodBodyContent(unit, type, binding.getName(), true, bodyStatement, delimiter);
// if (placeHolder != null)
// {
// ReturnStatement todoNode =
// (ReturnStatement)rewrite.createStringPlaceholder(placeHolder, ASTNode.RETURN_STATEMENT);
// body.statements().add(todoNode);
// }
} else {
ReturnStatement statementNode =
(ReturnStatement)rewrite.createStringPlaceholder(bodyStatement, ASTNode.RETURN_STATEMENT);
body.statements().add(statementNode);
}
if (settings != null && settings.createComments) {
//TODO
// String string = CodeGeneration.getMethodComment(unit, type, decl, binding, delimiter);
// if (string != null)
// {
// Javadoc javadoc = (Javadoc)rewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
// decl.setJavadoc(javadoc);
// }
}
return decl;
}
public static MethodDeclaration createConstructorStub(ASTRewrite rewrite, ImportRewrite imports,
ImportRewriteContext context, ITypeBinding typeBinding,
IMethodBinding superConstructor,
IVariableBinding[] variableBindings, int modifiers,
CodeGenerationSettings settings) {
AST ast = rewrite.getAST();
MethodDeclaration decl = ast.newMethodDeclaration();
decl.modifiers().addAll(ASTNodeFactory.newModifiers(ast, modifiers & ~Modifier.ABSTRACT & ~Modifier.NATIVE));
decl.setName(ast.newSimpleName(typeBinding.getName()));
decl.setConstructor(true);
List<SingleVariableDeclaration> parameters = decl.parameters();
if (superConstructor != null) {
ITypeBinding[] typeParams = superConstructor.getTypeParameters();
List<TypeParameter> typeParameters = decl.typeParameters();
for (int i = 0; i < typeParams.length; i++) {
ITypeBinding curr = typeParams[i];
TypeParameter newTypeParam = ast.newTypeParameter();
newTypeParam.setName(ast.newSimpleName(curr.getName()));
ITypeBinding[] typeBounds = curr.getTypeBounds();
if (typeBounds.length != 1 || !"java.lang.Object".equals(typeBounds[0].getQualifiedName())) {//$NON-NLS-1$
List<Type> newTypeBounds = newTypeParam.typeBounds();
for (int k = 0; k < typeBounds.length; k++) {
newTypeBounds.add(imports.addImport(typeBounds[k], ast, context));
}
}
typeParameters.add(newTypeParam);
}
createParameters(imports, context, ast, superConstructor, decl);
List<Name> thrownExceptions = decl.thrownExceptions();
ITypeBinding[] excTypes = superConstructor.getExceptionTypes();
for (int i = 0; i < excTypes.length; i++) {
String excTypeName = imports.addImport(excTypes[i], context);
thrownExceptions.add(ASTNodeFactory.newName(ast, excTypeName));
}
}
Block body = ast.newBlock();
decl.setBody(body);
String delimiter = "\n";
if (superConstructor != null) {
SuperConstructorInvocation invocation = ast.newSuperConstructorInvocation();
SingleVariableDeclaration varDecl = null;
for (Iterator<SingleVariableDeclaration> iterator = parameters.iterator(); iterator.hasNext(); ) {
varDecl = iterator.next();
invocation.arguments().add(ast.newSimpleName(varDecl.getName().getIdentifier()));
}
body.statements().add(invocation);
}
List<String> prohibited = new ArrayList<String>();
for (final Iterator<SingleVariableDeclaration> iterator = parameters.iterator(); iterator.hasNext(); )
prohibited.add(iterator.next().getName().getIdentifier());
String param = null;
List<String> list = new ArrayList<String>(prohibited);
String[] excluded = null;
for (int i = 0; i < variableBindings.length; i++) {
SingleVariableDeclaration var = ast.newSingleVariableDeclaration();
var.setType(imports.addImport(variableBindings[i].getType(), ast, context));
excluded = new String[list.size()];
list.toArray(excluded);
param = suggestParameterName(variableBindings[i], excluded);
list.add(param);
var.setName(ast.newSimpleName(param));
parameters.add(var);
}
list = new ArrayList<String>(prohibited);
for (int i = 0; i < variableBindings.length; i++) {
excluded = new String[list.size()];
list.toArray(excluded);
final String paramName = suggestParameterName(variableBindings[i], excluded);
list.add(paramName);
final String fieldName = variableBindings[i].getName();
Expression expression = null;
if (paramName.equals(fieldName) || settings.useKeywordThis) {
FieldAccess access = ast.newFieldAccess();
access.setExpression(ast.newThisExpression());
access.setName(ast.newSimpleName(fieldName));
expression = access;
} else
expression = ast.newSimpleName(fieldName);
Assignment assignment = ast.newAssignment();
assignment.setLeftHandSide(expression);
assignment.setRightHandSide(ast.newSimpleName(paramName));
assignment.setOperator(Assignment.Operator.ASSIGN);
body.statements().add(ast.newExpressionStatement(assignment));
}
if (settings != null && settings.createComments) {
//TODO
// String string =
// CodeGeneration.getMethodComment(unit, typeBinding.getName(), decl, superConstructor, delimiter);
// if (string != null)
// {
// Javadoc javadoc = (Javadoc)rewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
// decl.setJavadoc(javadoc);
// }
}
return decl;
}
public static MethodDeclaration createDelegationStub(ASTRewrite rewrite, ImportRewrite imports,
ImportRewriteContext context, IMethodBinding delegate,
IVariableBinding delegatingField,
CodeGenerationSettings settings) throws CoreException {
Assert.isNotNull(delegate);
Assert.isNotNull(delegatingField);
Assert.isNotNull(settings);
AST ast = rewrite.getAST();
MethodDeclaration decl = ast.newMethodDeclaration();
decl.modifiers().addAll(
ASTNodeFactory.newModifiers(ast, delegate.getModifiers() & ~Modifier.SYNCHRONIZED & ~Modifier.ABSTRACT
& ~Modifier.NATIVE));
decl.setName(ast.newSimpleName(delegate.getName()));
decl.setConstructor(false);
ITypeBinding[] typeParams = delegate.getTypeParameters();
List<TypeParameter> typeParameters = decl.typeParameters();
for (int i = 0; i < typeParams.length; i++) {
ITypeBinding curr = typeParams[i];
TypeParameter newTypeParam = ast.newTypeParameter();
newTypeParam.setName(ast.newSimpleName(curr.getName()));
ITypeBinding[] typeBounds = curr.getTypeBounds();
if (typeBounds.length != 1 || !"java.lang.Object".equals(typeBounds[0].getQualifiedName())) {//$NON-NLS-1$
List<Type> newTypeBounds = newTypeParam.typeBounds();
for (int k = 0; k < typeBounds.length; k++) {
newTypeBounds.add(imports.addImport(typeBounds[k], ast, context));
}
}
typeParameters.add(newTypeParam);
}
decl.setReturnType2(imports.addImport(delegate.getReturnType(), ast, context));
List<SingleVariableDeclaration> parameters = decl.parameters();
ITypeBinding[] params = delegate.getParameterTypes();
String[] paramNames = StubUtility.suggestArgumentNames(delegate);
for (int i = 0; i < params.length; i++) {
SingleVariableDeclaration varDecl = ast.newSingleVariableDeclaration();
if (params[i].isWildcardType() && !params[i].isUpperbound())
varDecl.setType(imports.addImport(params[i].getBound(), ast, context));
else {
if (delegate.isVarargs() && params[i].isArray() && i == params.length - 1) {
StringBuffer buffer = new StringBuffer(imports.addImport(params[i].getElementType(), context));
for (int dim = 1; dim < params[i].getDimensions(); dim++)
buffer.append("[]"); //$NON-NLS-1$
varDecl.setType(ASTNodeFactory.newType(ast, buffer.toString()));
varDecl.setVarargs(true);
} else
varDecl.setType(imports.addImport(params[i], ast, context));
}
varDecl.setName(ast.newSimpleName(paramNames[i]));
parameters.add(varDecl);
}
List<Name> thrownExceptions = decl.thrownExceptions();
ITypeBinding[] excTypes = delegate.getExceptionTypes();
for (int i = 0; i < excTypes.length; i++) {
String excTypeName = imports.addImport(excTypes[i], context);
thrownExceptions.add(ASTNodeFactory.newName(ast, excTypeName));
}
Block body = ast.newBlock();
decl.setBody(body);
String delimiter = StubUtility.getLineDelimiterUsed();
Statement statement = null;
MethodInvocation invocation = ast.newMethodInvocation();
invocation.setName(ast.newSimpleName(delegate.getName()));
List<Expression> arguments = invocation.arguments();
for (int i = 0; i < params.length; i++)
arguments.add(ast.newSimpleName(paramNames[i]));
if (settings.useKeywordThis) {
FieldAccess access = ast.newFieldAccess();
access.setExpression(ast.newThisExpression());
access.setName(ast.newSimpleName(delegatingField.getName()));
invocation.setExpression(access);
} else
invocation.setExpression(ast.newSimpleName(delegatingField.getName()));
if (delegate.getReturnType().isPrimitive() && delegate.getReturnType().getName().equals("void")) {//$NON-NLS-1$
statement = ast.newExpressionStatement(invocation);
} else {
ReturnStatement returnStatement = ast.newReturnStatement();
returnStatement.setExpression(invocation);
statement = returnStatement;
}
body.statements().add(statement);
ITypeBinding declaringType = delegatingField.getDeclaringClass();
if (declaringType == null) { // can be null for
return decl;
}
String qualifiedName = declaringType.getQualifiedName();
IPackageBinding packageBinding = declaringType.getPackage();
if (packageBinding != null) {
if (packageBinding.getName().length() > 0 && qualifiedName.startsWith(packageBinding.getName()))
qualifiedName = qualifiedName.substring(packageBinding.getName().length());
}
if (settings.createComments) {
/*
* TODO: have API for delegate method comments This is an inlined version of {@link
* CodeGeneration#getMethodComment(ICompilationUnit, String, MethodDeclaration, IMethodBinding, String)}
*/
// delegate = delegate.getMethodDeclaration();
// String declaringClassQualifiedName = delegate.getDeclaringClass().getQualifiedName();
// String linkToMethodName = delegate.getName();
// String[] parameterTypesQualifiedNames = StubUtility.getParameterTypeNamesForSeeTag(delegate);
// String string =
// StubUtility.getMethodComment(qualifiedName, decl, delegate.isDeprecated(), linkToMethodName,
// declaringClassQualifiedName, parameterTypesQualifiedNames, true, delimiter);
// if (string != null)
// {
// Javadoc javadoc = (Javadoc)rewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
// decl.setJavadoc(javadoc);
// }
}
return decl;
}
public static MethodDeclaration createImplementationStub(ASTRewrite rewrite, ImportRewrite imports,
ImportRewriteContext context, IMethodBinding binding, String type,
CodeGenerationSettings settings,
boolean deferred) throws CoreException {
Assert.isNotNull(imports);
Assert.isNotNull(rewrite);
AST ast = rewrite.getAST();
MethodDeclaration decl = ast.newMethodDeclaration();
decl.modifiers().addAll(getImplementationModifiers(ast, binding, deferred));
decl.setName(ast.newSimpleName(binding.getName()));
decl.setConstructor(false);
ITypeBinding bindingReturnType = binding.getReturnType();
// if (JavaModelUtil.is50OrHigher(unit.getJavaProject()))
// {
ITypeBinding[] typeParams = binding.getTypeParameters();
List<TypeParameter> typeParameters = decl.typeParameters();
for (int i = 0; i < typeParams.length; i++) {
ITypeBinding curr = typeParams[i];
TypeParameter newTypeParam = ast.newTypeParameter();
newTypeParam.setName(ast.newSimpleName(curr.getName()));
ITypeBinding[] typeBounds = curr.getTypeBounds();
if (typeBounds.length != 1 || !"java.lang.Object".equals(typeBounds[0].getQualifiedName())) {//$NON-NLS-1$
List<Type> newTypeBounds = newTypeParam.typeBounds();
for (int k = 0; k < typeBounds.length; k++) {
newTypeBounds.add(imports.addImport(typeBounds[k], ast, context));
}
}
typeParameters.add(newTypeParam);
}
// }
// else
// {
// bindingReturnType = bindingReturnType.getErasure();
// }
decl.setReturnType2(imports.addImport(bindingReturnType, ast, context));
List<SingleVariableDeclaration> parameters = createParameters(imports, context, ast, binding, decl);
List<Name> thrownExceptions = decl.thrownExceptions();
ITypeBinding[] excTypes = binding.getExceptionTypes();
for (int i = 0; i < excTypes.length; i++) {
String excTypeName = imports.addImport(excTypes[i], context);
thrownExceptions.add(ASTNodeFactory.newName(ast, excTypeName));
}
String delimiter = StubUtility.getLineDelimiterUsed();
if (!deferred) {
Map<String, String> options = JavaCore.getOptions();
Block body = ast.newBlock();
decl.setBody(body);
String bodyStatement = ""; //$NON-NLS-1$
ITypeBinding declaringType = binding.getDeclaringClass();
if (Modifier.isAbstract(binding.getModifiers()) || declaringType.isAnnotation() || declaringType.isInterface()) {
Expression expression =
ASTNodeFactory.newDefaultExpression(ast, decl.getReturnType2(), decl.getExtraDimensions());
if (expression != null) {
ReturnStatement returnStatement = ast.newReturnStatement();
returnStatement.setExpression(expression);
bodyStatement = ASTNodes.asFormattedString(returnStatement, 0, delimiter, options);
}
} else {
SuperMethodInvocation invocation = ast.newSuperMethodInvocation();
invocation.setName(ast.newSimpleName(binding.getName()));
SingleVariableDeclaration varDecl = null;
for (Iterator<SingleVariableDeclaration> iterator = parameters.iterator(); iterator.hasNext(); ) {
varDecl = iterator.next();
invocation.arguments().add(ast.newSimpleName(varDecl.getName().getIdentifier()));
}
Expression expression = invocation;
Type returnType = decl.getReturnType2();
if (returnType instanceof PrimitiveType
&& ((PrimitiveType)returnType).getPrimitiveTypeCode().equals(PrimitiveType.VOID)) {
bodyStatement =
ASTNodes.asFormattedString(ast.newExpressionStatement(expression), 0, delimiter, options);
} else {
ReturnStatement returnStatement = ast.newReturnStatement();
returnStatement.setExpression(expression);
bodyStatement = ASTNodes.asFormattedString(returnStatement, 0, delimiter, options);
}
}
String placeHolder =
StubUtility.getMethodBodyContent(false, type, binding.getName(), bodyStatement, delimiter);
// CodeGeneration.getMethodBodyContent(unit, type, binding.getName(), false, bodyStatement, delimiter);
if (placeHolder != null) {
ReturnStatement todoNode =
(ReturnStatement)rewrite.createStringPlaceholder(placeHolder, ASTNode.RETURN_STATEMENT);
body.statements().add(todoNode);
}
}
//TODO
// if (settings != null && settings.createComments)
// {
// String string = CodeGeneration.getMethodComment(unit, type, decl, binding, delimiter);
// if (string != null)
// {
// Javadoc javadoc = (Javadoc)rewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
// decl.setJavadoc(javadoc);
// }
// }
if (settings != null && settings.overrideAnnotation) {
addOverrideAnnotation(rewrite, decl, binding);
}
return decl;
}
private static List<SingleVariableDeclaration> createParameters(ImportRewrite imports, ImportRewriteContext context,
AST ast, IMethodBinding binding, MethodDeclaration decl) {
boolean is50OrHigher = true;
List<SingleVariableDeclaration> parameters = decl.parameters();
ITypeBinding[] params = binding.getParameterTypes();
String[] paramNames = StubUtility.suggestArgumentNames(binding);
for (int i = 0; i < params.length; i++) {
SingleVariableDeclaration var = ast.newSingleVariableDeclaration();
if (binding.isVarargs() && params[i].isArray() && i == params.length - 1) {
ITypeBinding type = params[i].getElementType();
if (!is50OrHigher)
type = type.getErasure();
StringBuffer buffer = new StringBuffer(imports.addImport(type, context));
for (int dim = 1; dim < params[i].getDimensions(); dim++)
buffer.append("[]"); //$NON-NLS-1$
var.setType(ASTNodeFactory.newType(ast, buffer.toString()));
var.setVarargs(true);
} else {
ITypeBinding type = params[i];
if (!is50OrHigher)
type = type.getErasure();
var.setType(imports.addImport(type, ast, context));
}
var.setName(ast.newSimpleName(paramNames[i]));
parameters.add(var);
}
return parameters;
}
private static IMethodBinding findMethodBinding(IMethodBinding method, List<IMethodBinding> allMethods) {
for (int i = 0; i < allMethods.size(); i++) {
IMethodBinding curr = allMethods.get(i);
if (Bindings.isSubsignature(method, curr)) {
return curr;
}
}
return null;
}
private static IMethodBinding findOverridingMethod(IMethodBinding method, List<IMethodBinding> allMethods) {
for (int i = 0; i < allMethods.size(); i++) {
IMethodBinding curr = allMethods.get(i);
if (Bindings.areOverriddenMethods(curr, method) || Bindings.isSubsignature(curr, method))
return curr;
}
return null;
}
private static void findUnimplementedInterfaceMethods(ITypeBinding typeBinding, HashSet<ITypeBinding> visited,
ArrayList<IMethodBinding> allMethods, IPackageBinding currPack,
ArrayList<IMethodBinding> toImplement) {
if (visited.add(typeBinding)) {
IMethodBinding[] typeMethods = typeBinding.getDeclaredMethods();
for (int i = 0; i < typeMethods.length; i++) {
IMethodBinding curr = typeMethods[i];
IMethodBinding impl = findMethodBinding(curr, allMethods);
if (impl == null || !Bindings.isVisibleInHierarchy(impl, currPack)) {
if (impl != null)
allMethods.remove(impl);
toImplement.add(curr);
allMethods.add(curr);
}
}
ITypeBinding[] superInterfaces = typeBinding.getInterfaces();
for (int i = 0; i < superInterfaces.length; i++)
findUnimplementedInterfaceMethods(superInterfaces[i], visited, allMethods, currPack, toImplement);
}
}
// public static DelegateEntry[] getDelegatableMethods(ITypeBinding binding)
// {
// final List<DelegateEntry> tuples = new ArrayList<DelegateEntry>();
// final List<IMethodBinding> declared = new ArrayList<IMethodBinding>();
// IMethodBinding[] typeMethods = binding.getDeclaredMethods();
// for (int index = 0; index < typeMethods.length; index++)
// declared.add(typeMethods[index]);
// IVariableBinding[] typeFields = binding.getDeclaredFields();
// for (int index = 0; index < typeFields.length; index++)
// {
// IVariableBinding fieldBinding = typeFields[index];
// if (fieldBinding.isField() && !fieldBinding.isEnumConstant() && !fieldBinding.isSynthetic())
// getDelegatableMethods(new ArrayList<IMethodBinding>(declared), fieldBinding, fieldBinding.getType(),
// binding, tuples);
// }
// // list of tuple<IVariableBinding, IMethodBinding>
// return tuples.toArray(new DelegateEntry[tuples.size()]);
// }
// private static void getDelegatableMethods(List<IMethodBinding> methods, IVariableBinding fieldBinding,
// ITypeBinding typeBinding, ITypeBinding binding, List<DelegateEntry> result)
// {
// boolean match = false;
// if (typeBinding.isTypeVariable())
// {
// ITypeBinding[] typeBounds = typeBinding.getTypeBounds();
// if (typeBounds.length > 0)
// {
// for (int i = 0; i < typeBounds.length; i++)
// {
// getDelegatableMethods(methods, fieldBinding, typeBounds[i], binding, result);
// }
// }
// else
// {
// ITypeBinding objectBinding = Bindings.findTypeInHierarchy(binding, "java.lang.Object"); //$NON-NLS-1$
// if (objectBinding != null)
// {
// getDelegatableMethods(methods, fieldBinding, objectBinding, binding, result);
// }
// }
// }
// else
// {
// IMethodBinding[] candidates = getDelegateCandidates(typeBinding, binding);
// for (int index = 0; index < candidates.length; index++)
// {
// match = false;
// final IMethodBinding methodBinding = candidates[index];
// for (int offset = 0; offset < methods.size() && !match; offset++)
// {
// if (Bindings.areOverriddenMethods(methods.get(offset), methodBinding))
// match = true;
// }
// if (!match)
// {
// result.add(new DelegateEntry(methodBinding, fieldBinding));
// methods.add(methodBinding);
// }
// }
// final ITypeBinding superclass = typeBinding.getSuperclass();
// if (superclass != null)
// getDelegatableMethods(methods, fieldBinding, superclass, binding, result);
// ITypeBinding[] superInterfaces = typeBinding.getInterfaces();
// for (int offset = 0; offset < superInterfaces.length; offset++)
// getDelegatableMethods(methods, fieldBinding, superInterfaces[offset], binding, result);
// }
// }
private static IMethodBinding[] getDelegateCandidates(ITypeBinding binding, ITypeBinding hierarchy) {
List<IMethodBinding> allMethods = new ArrayList<IMethodBinding>();
boolean isInterface = binding.isInterface();
IMethodBinding[] typeMethods = binding.getDeclaredMethods();
for (int index = 0; index < typeMethods.length; index++) {
final int modifiers = typeMethods[index].getModifiers();
if (!typeMethods[index].isConstructor() && !Modifier.isStatic(modifiers)
&& (isInterface || Modifier.isPublic(modifiers))) {
IMethodBinding result = Bindings.findOverriddenMethodInHierarchy(hierarchy, typeMethods[index]);
if (result != null && Flags.isFinal(result.getModifiers()))
continue;
ITypeBinding[] parameterBindings = typeMethods[index].getParameterTypes();
boolean upper = false;
for (int offset = 0; offset < parameterBindings.length; offset++) {
if (parameterBindings[offset].isWildcardType() && parameterBindings[offset].isUpperbound())
upper = true;
}
if (!upper)
allMethods.add(typeMethods[index]);
}
}
return allMethods.toArray(new IMethodBinding[allMethods.size()]);
}
private static List<Modifier> getImplementationModifiers(AST ast, IMethodBinding method, boolean deferred) {
int modifiers = method.getModifiers() & ~Modifier.ABSTRACT & ~Modifier.NATIVE & ~Modifier.PRIVATE;
if (deferred) {
modifiers = modifiers & ~Modifier.PROTECTED;
modifiers = modifiers | Modifier.PUBLIC;
}
return ASTNodeFactory.newModifiers(ast, modifiers);
}
public static IMethodBinding[] getOverridableMethods(AST ast, ITypeBinding typeBinding, boolean isSubType) {
List<IMethodBinding> allMethods = new ArrayList<IMethodBinding>();
IMethodBinding[] typeMethods = typeBinding.getDeclaredMethods();
for (int index = 0; index < typeMethods.length; index++) {
final int modifiers = typeMethods[index].getModifiers();
if (!typeMethods[index].isConstructor() && !Modifier.isStatic(modifiers) && !Modifier.isPrivate(modifiers))
allMethods.add(typeMethods[index]);
}
ITypeBinding clazz = typeBinding.getSuperclass();
while (clazz != null) {
IMethodBinding[] methods = clazz.getDeclaredMethods();
for (int offset = 0; offset < methods.length; offset++) {
final int modifiers = methods[offset].getModifiers();
if (!methods[offset].isConstructor() && !Modifier.isStatic(modifiers) && !Modifier.isPrivate(modifiers)) {
if (findOverridingMethod(methods[offset], allMethods) == null)
allMethods.add(methods[offset]);
}
}
clazz = clazz.getSuperclass();
}
clazz = typeBinding;
while (clazz != null) {
ITypeBinding[] superInterfaces = clazz.getInterfaces();
for (int index = 0; index < superInterfaces.length; index++) {
getOverridableMethods(ast, superInterfaces[index], allMethods);
}
clazz = clazz.getSuperclass();
}
if (typeBinding.isInterface())
getOverridableMethods(ast, ast.resolveWellKnownType("java.lang.Object"), allMethods); //$NON-NLS-1$
if (!isSubType)
allMethods.removeAll(Arrays.asList(typeMethods));
int modifiers = 0;
if (!typeBinding.isInterface()) {
for (int index = allMethods.size() - 1; index >= 0; index--) {
IMethodBinding method = allMethods.get(index);
modifiers = method.getModifiers();
if (Modifier.isFinal(modifiers))
allMethods.remove(index);
}
}
return allMethods.toArray(new IMethodBinding[allMethods.size()]);
}
private static void getOverridableMethods(AST ast, ITypeBinding superBinding, List<IMethodBinding> allMethods) {
IMethodBinding[] methods = superBinding.getDeclaredMethods();
for (int offset = 0; offset < methods.length; offset++) {
final int modifiers = methods[offset].getModifiers();
if (!methods[offset].isConstructor() && !Modifier.isStatic(modifiers) && !Modifier.isPrivate(modifiers)) {
if (findOverridingMethod(methods[offset], allMethods) == null && !Modifier.isStatic(modifiers))
allMethods.add(methods[offset]);
}
}
ITypeBinding[] superInterfaces = superBinding.getInterfaces();
for (int index = 0; index < superInterfaces.length; index++) {
getOverridableMethods(ast, superInterfaces[index], allMethods);
}
}
private static String suggestParameterName(IVariableBinding binding, String[] excluded) {
String name = StubUtility.getBaseName(binding);
return StubUtility.suggestArgumentName(name, excluded);
}
public static IMethodBinding[] getUnimplementedMethods(ITypeBinding typeBinding) {
return getUnimplementedMethods(typeBinding, false);
}
public static IMethodBinding[] getUnimplementedMethods(ITypeBinding typeBinding, boolean implementAbstractsOfInput) {
ArrayList<IMethodBinding> allMethods = new ArrayList<IMethodBinding>();
ArrayList<IMethodBinding> toImplement = new ArrayList<IMethodBinding>();
IMethodBinding[] typeMethods = typeBinding.getDeclaredMethods();
for (int i = 0; i < typeMethods.length; i++) {
IMethodBinding curr = typeMethods[i];
int modifiers = curr.getModifiers();
if (!curr.isConstructor() && !Modifier.isStatic(modifiers) && !Modifier.isPrivate(modifiers)) {
allMethods.add(curr);
}
}
ITypeBinding superClass = typeBinding.getSuperclass();
while (superClass != null) {
typeMethods = superClass.getDeclaredMethods();
for (int i = 0; i < typeMethods.length; i++) {
IMethodBinding curr = typeMethods[i];
int modifiers = curr.getModifiers();
if (!curr.isConstructor() && !Modifier.isStatic(modifiers) && !Modifier.isPrivate(modifiers)) {
if (findMethodBinding(curr, allMethods) == null) {
allMethods.add(curr);
}
}
}
superClass = superClass.getSuperclass();
}
for (int i = 0; i < allMethods.size(); i++) {
IMethodBinding curr = allMethods.get(i);
int modifiers = curr.getModifiers();
if ((Modifier.isAbstract(modifiers) || curr.getDeclaringClass().isInterface())
&& (implementAbstractsOfInput || typeBinding != curr.getDeclaringClass())) {
// implement all abstract methods
toImplement.add(curr);
}
}
HashSet<ITypeBinding> visited = new HashSet<ITypeBinding>();
ITypeBinding curr = typeBinding;
while (curr != null) {
ITypeBinding[] superInterfaces = curr.getInterfaces();
for (int i = 0; i < superInterfaces.length; i++) {
findUnimplementedInterfaceMethods(superInterfaces[i], visited, allMethods, typeBinding.getPackage(),
toImplement);
}
curr = curr.getSuperclass();
}
return toImplement.toArray(new IMethodBinding[toImplement.size()]);
}
public static IMethodBinding[] getVisibleConstructors(ITypeBinding binding, boolean accountExisting,
boolean proposeDefault) {
List<IMethodBinding> constructorMethods = new ArrayList<IMethodBinding>();
List<IMethodBinding> existingConstructors = null;
ITypeBinding superType = binding.getSuperclass();
if (superType == null)
return new IMethodBinding[0];
if (accountExisting) {
IMethodBinding[] methods = binding.getDeclaredMethods();
existingConstructors = new ArrayList<IMethodBinding>(methods.length);
for (int index = 0; index < methods.length; index++) {
IMethodBinding method = methods[index];
if (method.isConstructor() && !method.isDefaultConstructor())
existingConstructors.add(method);
}
}
if (existingConstructors != null)
constructorMethods.addAll(existingConstructors);
IMethodBinding[] methods = binding.getDeclaredMethods();
IMethodBinding[] superMethods = superType.getDeclaredMethods();
for (int index = 0; index < superMethods.length; index++) {
IMethodBinding method = superMethods[index];
if (method.isConstructor()) {
if (Bindings.isVisibleInHierarchy(method, binding.getPackage())
&& (!accountExisting || !Bindings.containsSignatureEquivalentConstructor(methods, method)))
constructorMethods.add(method);
}
}
if (existingConstructors != null)
constructorMethods.removeAll(existingConstructors);
if (constructorMethods.isEmpty()) {
superType = binding;
while (superType.getSuperclass() != null)
superType = superType.getSuperclass();
IMethodBinding method = Bindings.findMethodInType(superType, "Object", new ITypeBinding[0]); //$NON-NLS-1$
if (method != null) {
if ((proposeDefault || !accountExisting || existingConstructors == null || existingConstructors.isEmpty())
&& (!accountExisting || !Bindings.containsSignatureEquivalentConstructor(methods, method)))
constructorMethods.add(method);
}
}
return constructorMethods.toArray(new IMethodBinding[constructorMethods.size()]);
}
/**
* Evaluates the insertion position of a new node.
*
* @param listRewrite
* The list rewriter to which the new node will be added
* @param sibling
* The Java element before which the new element should be added.
* @return the AST node of the list to insert before or null to insert as last.
* @throws JavaModelException
* thrown if accessing the Java element failed
*/
public static ASTNode getNodeToInsertBefore(ListRewrite listRewrite, int insertPos) {
// if (sibling instanceof IMember)
// {
// ISourceRange sourceRange = ((IMember)sibling).getSourceRange();
// if (sourceRange == null)
// {
// return null;
// }
// int insertPos = sourceRange.getOffset();
List<? extends ASTNode> members = listRewrite.getOriginalList();
for (int i = 0; i < members.size(); i++) {
ASTNode curr = members.get(i);
if (curr.getStartPosition() >= insertPos) {
return curr;
}
}
// }
return null;
}
/** Creates a new stub utility. */
private StubUtility2() {
// Not for instantiation
}
}