blob: a5652b3361988e31d5958b95b70e8cd65491b20c [file] [log] [blame]
/*******************************************************************************
* 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
* N.Metchev@teamphone.com - contributed fixes for
* - convert anonymous to nested should sometimes declare class as static [refactoring]
* (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=43360)
* - Convert anonymous to nested: should show error if field form outer anonymous type is references [refactoring]
* (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=48282)
*******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.code;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.NamingConventions;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.TypeParameter;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
import org.eclipse.jdt.core.refactoring.descriptors.ConvertAnonymousDescriptor;
import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder;
import org.eclipse.jdt.internal.corext.fix.LinkedProposalModel;
import org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroup;
import org.eclipse.jdt.internal.corext.refactoring.Checks;
import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
import org.eclipse.jdt.internal.corext.util.JdtFlags;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.CodeGeneration;
import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.internal.ui.text.correction.ModifierCorrectionSubProcessor;
import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
public class ConvertAnonymousToNestedRefactoring extends Refactoring {
private static final String ATTRIBUTE_VISIBILITY= "visibility"; //$NON-NLS-1$
private static final String ATTRIBUTE_FINAL= "final"; //$NON-NLS-1$
private static final String ATTRIBUTE_STATIC= "static"; //$NON-NLS-1$
private static final String KEY_TYPE_NAME= "type_name"; //$NON-NLS-1$
private static final String KEY_PARAM_NAME_EXT= "param_name_ext"; //$NON-NLS-1$
private static final String KEY_PARAM_NAME_CONST= "param_name_const"; //$NON-NLS-1$
private static final String KEY_FIELD_NAME_EXT= "field_name_ext"; //$NON-NLS-1$
public static class TypeVariableFinder extends ASTVisitor {
private final Map<String, ITypeBinding> fBindings= new HashMap<String, ITypeBinding>();
private final List<ITypeBinding> fFound= new ArrayList<ITypeBinding>();
@Override
public final boolean visit(final SimpleName node) {
Assert.isNotNull(node);
final ITypeBinding binding= node.resolveTypeBinding();
if (binding != null && binding.isTypeVariable() && !fBindings.containsKey(binding.getKey())) {
fBindings.put(binding.getKey(), binding);
fFound.add(binding);
}
return true;
}
public final ITypeBinding[] getResult() {
final ITypeBinding[] result= new ITypeBinding[fFound.size()];
fFound.toArray(result);
return result;
}
}
private int fSelectionStart;
private int fSelectionLength;
private ICompilationUnit fCu;
private int fVisibility; /* see Modifier */
private boolean fDeclareFinal= true;
private boolean fDeclareStatic;
private String fClassName= ""; //$NON-NLS-1$
private CompilationUnit fCompilationUnitNode;
private AnonymousClassDeclaration fAnonymousInnerClassNode;
private Set<String> fClassNamesUsed;
private boolean fSelfInitializing= false;
private LinkedProposalModel fLinkedProposalModel;
/**
* Creates a new convert anonymous to nested refactoring.
*
* @param unit the compilation unit, or <code>null</code> if invoked by scripting
* @param selectionStart start
* @param selectionLength length
*/
public ConvertAnonymousToNestedRefactoring(ICompilationUnit unit, int selectionStart, int selectionLength) {
Assert.isTrue(selectionStart >= 0);
Assert.isTrue(selectionLength >= 0);
Assert.isTrue(unit == null || unit.exists());
fSelectionStart= selectionStart;
fSelectionLength= selectionLength;
fCu= unit;
fAnonymousInnerClassNode= null;
fCompilationUnitNode= null;
}
public ConvertAnonymousToNestedRefactoring(AnonymousClassDeclaration declaration) {
Assert.isTrue(declaration != null);
ASTNode astRoot= declaration.getRoot();
Assert.isTrue(astRoot instanceof CompilationUnit);
fCompilationUnitNode= (CompilationUnit) astRoot;
IJavaElement javaElement= fCompilationUnitNode.getJavaElement();
Assert.isTrue(javaElement instanceof ICompilationUnit);
fCu= (ICompilationUnit) javaElement;
fSelectionStart= declaration.getStartPosition();
fSelectionLength= declaration.getLength();
}
public ConvertAnonymousToNestedRefactoring(JavaRefactoringArguments arguments, RefactoringStatus status) {
this(null, 0, 0);
RefactoringStatus initializeStatus= initialize(arguments);
status.merge(initializeStatus);
}
public void setLinkedProposalModel(LinkedProposalModel linkedProposalModel) {
fLinkedProposalModel= linkedProposalModel;
}
public int[] getAvailableVisibilities() {
if (isLocalInnerType()) {
return new int[] { Modifier.NONE };
} else {
return new int[] { Modifier.PUBLIC, Modifier.PROTECTED, Modifier.NONE, Modifier.PRIVATE };
}
}
public boolean isLocalInnerType() {
return ASTNodes.getParent(ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class), ASTNode.ANONYMOUS_CLASS_DECLARATION) != null;
}
public int getVisibility() {
return fVisibility;
}
public void setVisibility(int visibility) {
Assert.isTrue(visibility == Modifier.PRIVATE || visibility == Modifier.NONE || visibility == Modifier.PROTECTED || visibility == Modifier.PUBLIC);
fVisibility= visibility;
}
public void setClassName(String className) {
Assert.isNotNull(className);
fClassName= className;
}
public boolean canEnableSettingFinal() {
return true;
}
public boolean getDeclareFinal() {
return fDeclareFinal;
}
public boolean getDeclareStatic() {
return fDeclareStatic;
}
public void setDeclareFinal(boolean declareFinal) {
fDeclareFinal= declareFinal;
}
public void setDeclareStatic(boolean declareStatic) {
fDeclareStatic= declareStatic;
}
@Override
public String getName() {
return RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_name;
}
private boolean useThisForFieldAccess() {
return StubUtility.useThisForFieldAccess(fCu.getJavaProject());
}
private boolean doAddComments() {
return StubUtility.doAddComments(fCu.getJavaProject());
}
@Override
public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
RefactoringStatus result= Checks.validateModifiesFiles(
ResourceUtil.getFiles(new ICompilationUnit[]{fCu}),
getValidationContext());
if (result.hasFatalError())
return result;
initAST(pm);
if (fAnonymousInnerClassNode == null)
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_place_caret);
if (!fSelfInitializing)
initializeDefaults();
if (getSuperConstructorBinding() == null)
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_compile_errors);
if (getSuperTypeBinding().isLocal())
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_extends_local_class);
return new RefactoringStatus();
}
private void initializeDefaults() {
fVisibility= isLocalInnerType() ? Modifier.NONE : Modifier.PRIVATE;
fDeclareStatic = mustInnerClassBeStatic();
}
private void initAST(IProgressMonitor pm) {
if (fCompilationUnitNode == null) {
fCompilationUnitNode= RefactoringASTParser.parseWithASTProvider(fCu, true, pm);
}
if (fAnonymousInnerClassNode == null) {
fAnonymousInnerClassNode= getAnonymousInnerClass(NodeFinder.perform(fCompilationUnitNode, fSelectionStart, fSelectionLength));
}
if (fAnonymousInnerClassNode != null) {
final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class);
if (declaration instanceof TypeDeclaration) {
final AbstractTypeDeclaration[] nested= ((TypeDeclaration) declaration).getTypes();
fClassNamesUsed= new HashSet<String>(nested.length);
for (int index= 0; index < nested.length; index++)
fClassNamesUsed.add(nested[index].getName().getIdentifier());
} else
fClassNamesUsed= Collections.emptySet();
}
}
private static AnonymousClassDeclaration getAnonymousInnerClass(ASTNode node) {
if (node == null)
return null;
if (node instanceof AnonymousClassDeclaration)
return (AnonymousClassDeclaration)node;
if (node instanceof ClassInstanceCreation) {
AnonymousClassDeclaration anon= ((ClassInstanceCreation)node).getAnonymousClassDeclaration();
if (anon != null)
return anon;
}
node= ASTNodes.getNormalizedNode(node);
if (node.getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY) {
AnonymousClassDeclaration anon= ((ClassInstanceCreation)node.getParent()).getAnonymousClassDeclaration();
if (anon != null)
return anon;
}
return (AnonymousClassDeclaration)ASTNodes.getParent(node, AnonymousClassDeclaration.class);
}
public RefactoringStatus validateInput() {
RefactoringStatus result= Checks.checkTypeName(fClassName, fCu);
if (result.hasFatalError())
return result;
if (fClassNamesUsed.contains(fClassName))
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_type_exists);
IMethodBinding superConstructorBinding = getSuperConstructorBinding();
if (superConstructorBinding == null)
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_compile_errors);
if (fClassName.equals(superConstructorBinding.getDeclaringClass().getName()))
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_another_name);
if (classNameHidesEnclosingType())
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_name_hides);
return result;
}
private boolean accessesAnonymousFields() {
List<IVariableBinding> anonymousInnerFieldTypes = getAllEnclosingAnonymousTypesField();
List<IBinding> accessedField = getAllAccessedFields();
final Iterator<IVariableBinding> it = anonymousInnerFieldTypes.iterator();
while(it.hasNext()) {
final IVariableBinding variableBinding = it.next();
final Iterator<IBinding> it2 = accessedField.iterator();
while (it2.hasNext()) {
IVariableBinding variableBinding2 = (IVariableBinding) it2.next();
if(Bindings.equals(variableBinding, variableBinding2)) {
return true;
}
}
}
return false;
}
private List<IBinding> getAllAccessedFields() {
final List<IBinding> accessedFields= new ArrayList<IBinding>();
ASTVisitor visitor= new ASTVisitor() {
@Override
public boolean visit(FieldAccess node) {
final IVariableBinding binding= node.resolveFieldBinding();
if (binding != null && !binding.isEnumConstant())
accessedFields.add(binding);
return super.visit(node);
}
@Override
public boolean visit(QualifiedName node) {
final IBinding binding= node.resolveBinding();
if (binding != null && binding instanceof IVariableBinding) {
IVariableBinding variable= (IVariableBinding) binding;
if (!variable.isEnumConstant() && variable.isField())
accessedFields.add(binding);
}
return super.visit(node);
}
@Override
public boolean visit(SimpleName node) {
final IBinding binding= node.resolveBinding();
if (binding != null && binding instanceof IVariableBinding) {
IVariableBinding variable= (IVariableBinding) binding;
if (!variable.isEnumConstant() && variable.isField())
accessedFields.add(binding);
}
return super.visit(node);
}
@Override
public boolean visit(SuperFieldAccess node) {
final IVariableBinding binding= node.resolveFieldBinding();
if (binding != null && !binding.isEnumConstant())
accessedFields.add(binding);
return super.visit(node);
}
};
fAnonymousInnerClassNode.accept(visitor);
return accessedFields;
}
private List<IVariableBinding> getAllEnclosingAnonymousTypesField() {
final List<IVariableBinding> ans= new ArrayList<IVariableBinding>();
final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class);
AnonymousClassDeclaration anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, ASTNode.ANONYMOUS_CLASS_DECLARATION);
while (anonymous != null) {
if (ASTNodes.isParent(anonymous, declaration)) {
ITypeBinding binding= anonymous.resolveBinding();
if (binding != null) {
ans.addAll(Arrays.asList(binding.getDeclaredFields()));
}
} else {
break;
}
anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(anonymous, ASTNode.ANONYMOUS_CLASS_DECLARATION);
}
return ans;
}
private boolean classNameHidesEnclosingType() {
ITypeBinding type= ((AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class)).resolveBinding();
while (type != null) {
if (fClassName.equals(type.getName()))
return true;
type= type.getDeclaringClass();
}
return false;
}
/*
* @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkInput(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
try {
RefactoringStatus status= validateInput();
if (accessesAnonymousFields())
status.merge(RefactoringStatus.createErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_anonymous_field_access));
return status;
} finally {
pm.done();
}
}
public CompilationUnitChange createCompilationUnitChange(IProgressMonitor pm) throws CoreException {
final CompilationUnitRewrite rewrite= new CompilationUnitRewrite(fCu, fCompilationUnitNode);
final ITypeBinding[] typeParameters= getTypeParameters();
addNestedClass(rewrite, typeParameters);
modifyConstructorCall(rewrite, typeParameters);
return rewrite.createChange(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_name, false, pm);
}
/*
* @see org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring#createChange(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public Change createChange(IProgressMonitor pm) throws CoreException {
final CompilationUnitChange result= createCompilationUnitChange(pm);
result.setDescriptor(createRefactoringDescriptor());
return result;
}
private ITypeBinding[] getTypeParameters() {
final List<ITypeBinding> parameters= new ArrayList<ITypeBinding>(4);
final ClassInstanceCreation creation= (ClassInstanceCreation) fAnonymousInnerClassNode.getParent();
if (fDeclareStatic) {
final TypeVariableFinder finder= new TypeVariableFinder();
creation.accept(finder);
return finder.getResult();
} else {
final MethodDeclaration declaration= getEnclosingMethodDeclaration(creation);
if (declaration != null) {
ITypeBinding binding= null;
TypeParameter parameter= null;
for (final Iterator<TypeParameter> iterator= declaration.typeParameters().iterator(); iterator.hasNext();) {
parameter= iterator.next();
binding= parameter.resolveBinding();
if (binding != null)
parameters.add(binding);
}
}
}
final TypeVariableFinder finder= new TypeVariableFinder();
creation.accept(finder);
final ITypeBinding[] variables= finder.getResult();
final List<ITypeBinding> remove= new ArrayList<ITypeBinding>(4);
boolean match= false;
ITypeBinding binding= null;
ITypeBinding variable= null;
for (final Iterator<ITypeBinding> iterator= parameters.iterator(); iterator.hasNext();) {
match= false;
binding= iterator.next();
for (int index= 0; index < variables.length; index++) {
variable= variables[index];
if (variable.equals(binding))
match= true;
}
if (!match)
remove.add(binding);
}
parameters.removeAll(remove);
final ITypeBinding[] result= new ITypeBinding[parameters.size()];
parameters.toArray(result);
return result;
}
private MethodDeclaration getEnclosingMethodDeclaration(ASTNode node) {
ASTNode parent= node.getParent();
if (parent != null) {
if (parent instanceof AbstractTypeDeclaration)
return null;
else if (parent instanceof MethodDeclaration)
return (MethodDeclaration) parent;
return getEnclosingMethodDeclaration(parent);
}
return null;
}
private RefactoringChangeDescriptor createRefactoringDescriptor() {
final ITypeBinding binding= fAnonymousInnerClassNode.resolveBinding();
final String[] labels= new String[] { BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED), BindingLabelProvider.getBindingLabel(binding.getDeclaringMethod(), JavaElementLabels.ALL_FULLY_QUALIFIED)};
final Map<String, String> arguments= new HashMap<String, String>();
final String projectName= fCu.getJavaProject().getElementName();
final int flags= RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
final String description= RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_descriptor_description_short;
final String header= Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_descriptor_description, labels);
final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(projectName, this, header);
comment.addSetting(Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_original_pattern, BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED)));
comment.addSetting(Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_class_name_pattern, BasicElementLabels.getJavaElementName(fClassName)));
String visibility= JdtFlags.getVisibilityString(fVisibility);
if (visibility.length() == 0)
visibility= RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_default_visibility;
comment.addSetting(Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_visibility_pattern, visibility));
if (fDeclareFinal && fDeclareStatic)
comment.addSetting(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_declare_final_static);
else if (fDeclareFinal)
comment.addSetting(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_declare_final);
else if (fDeclareStatic)
comment.addSetting(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_declare_static);
arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(projectName, fCu));
arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME, fClassName);
arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION, new Integer(fSelectionStart).toString() + ' ' + new Integer(fSelectionLength).toString());
arguments.put(ATTRIBUTE_FINAL, Boolean.valueOf(fDeclareFinal).toString());
arguments.put(ATTRIBUTE_STATIC, Boolean.valueOf(fDeclareStatic).toString());
arguments.put(ATTRIBUTE_VISIBILITY, new Integer(fVisibility).toString());
ConvertAnonymousDescriptor descriptor= RefactoringSignatureDescriptorFactory.createConvertAnonymousDescriptor(projectName, description, comment.asString(), arguments, flags);
return new RefactoringChangeDescriptor(descriptor);
}
private void modifyConstructorCall(CompilationUnitRewrite rewrite, ITypeBinding[] parameters) {
rewrite.getASTRewrite().replace(fAnonymousInnerClassNode.getParent(), createNewClassInstanceCreation(rewrite, parameters), null);
}
private ASTNode createNewClassInstanceCreation(CompilationUnitRewrite rewrite, ITypeBinding[] parameters) {
AST ast= fAnonymousInnerClassNode.getAST();
ClassInstanceCreation newClassCreation= ast.newClassInstanceCreation();
newClassCreation.setAnonymousClassDeclaration(null);
Type type= null;
SimpleName newNameNode= ast.newSimpleName(fClassName);
if (parameters.length > 0) {
final ParameterizedType parameterized= ast.newParameterizedType(ast.newSimpleType(newNameNode));
for (int index= 0; index < parameters.length; index++)
parameterized.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getName())));
type= parameterized;
} else
type= ast.newSimpleType(newNameNode);
newClassCreation.setType(type);
copyArguments(rewrite, newClassCreation);
addArgumentsForLocalsUsedInInnerClass(newClassCreation);
addLinkedPosition(KEY_TYPE_NAME, newNameNode, rewrite.getASTRewrite(), true);
return newClassCreation;
}
private void addArgumentsForLocalsUsedInInnerClass(ClassInstanceCreation newClassCreation) {
IVariableBinding[] usedLocals= getUsedLocalVariables();
for (int i= 0; i < usedLocals.length; i++) {
final AST ast= fAnonymousInnerClassNode.getAST();
final IVariableBinding binding= usedLocals[i];
Name name= null;
if (binding.isEnumConstant())
name= ast.newQualifiedName(ast.newSimpleName(binding.getDeclaringClass().getName()), ast.newSimpleName(binding.getName()));
else
name= ast.newSimpleName(binding.getName());
newClassCreation.arguments().add(name);
}
}
private void copyArguments(CompilationUnitRewrite rewrite, ClassInstanceCreation newClassCreation) {
Iterator<Expression> iter= ((ClassInstanceCreation) fAnonymousInnerClassNode.getParent()).arguments().iterator();
if (!iter.hasNext())
return;
IMethodBinding superConstructorBinding= getSuperConstructorBinding();
ITypeBinding[] parameterTypes= superConstructorBinding.getParameterTypes();
List<Expression> arguments= newClassCreation.arguments();
ASTRewrite astRewrite= rewrite.getASTRewrite();
int last= parameterTypes.length - 1;
for (int i= 0; i < last; i++) {
arguments.add((Expression) astRewrite.createCopyTarget(iter.next()));
}
if (superConstructorBinding.isVarargs()) {
AST ast= astRewrite.getAST();
ArrayCreation arrayCreation= ast.newArrayCreation();
arrayCreation.setType((ArrayType) rewrite.getImportRewrite().addImport(parameterTypes[last], ast));
ArrayInitializer initializer= ast.newArrayInitializer();
arrayCreation.setInitializer(initializer);
arguments.add(arrayCreation);
arguments= initializer.expressions();
}
while (iter.hasNext()) {
arguments.add((Expression) astRewrite.createCopyTarget(iter.next()));
}
}
private void addNestedClass(CompilationUnitRewrite rewrite, ITypeBinding[] typeParameters) throws CoreException {
final AbstractTypeDeclaration declarations= (AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class);
int index= findIndexOfFistNestedClass(declarations.bodyDeclarations());
if (index == -1)
index= 0;
rewrite.getASTRewrite().getListRewrite(declarations, declarations.getBodyDeclarationsProperty()).insertAt(createNewNestedClass(rewrite, typeParameters), index, null);
}
private static int findIndexOfFistNestedClass(List<BodyDeclaration> list) {
for (int i= 0, n= list.size(); i < n; i++) {
BodyDeclaration each= list.get(i);
if (isNestedType(each))
return i;
}
return -1;
}
private static boolean isNestedType(BodyDeclaration each) {
if (!(each instanceof AbstractTypeDeclaration))
return false;
return (each.getParent() instanceof AbstractTypeDeclaration);
}
private AbstractTypeDeclaration createNewNestedClass(CompilationUnitRewrite rewrite, ITypeBinding[] typeParameters) throws CoreException {
final AST ast= fAnonymousInnerClassNode.getAST();
final TypeDeclaration newDeclaration= ast.newTypeDeclaration();
newDeclaration.setInterface(false);
newDeclaration.setJavadoc(null);
newDeclaration.modifiers().addAll(ASTNodeFactory.newModifiers(ast, createModifiersForNestedClass()));
newDeclaration.setName(ast.newSimpleName(fClassName));
TypeParameter parameter= null;
for (int index= 0; index < typeParameters.length; index++) {
parameter= ast.newTypeParameter();
parameter.setName(ast.newSimpleName(typeParameters[index].getName()));
newDeclaration.typeParameters().add(parameter);
}
setSuperType(newDeclaration);
IJavaProject project= fCu.getJavaProject();
IVariableBinding[] bindings= getUsedLocalVariables();
ArrayList<String> fieldNames= new ArrayList<String>();
for (int i= 0; i < bindings.length; i++) {
String name= StubUtility.getBaseName(bindings[i], project);
String[] fieldNameProposals= StubUtility.getVariableNameSuggestions(NamingConventions.VK_INSTANCE_FIELD, project, name, 0, fieldNames, true);
fieldNames.add(fieldNameProposals[0]);
if (fLinkedProposalModel != null) {
LinkedProposalPositionGroup positionGroup= fLinkedProposalModel.getPositionGroup(KEY_FIELD_NAME_EXT + i, true);
for (int k= 0; k < fieldNameProposals.length; k++) {
positionGroup.addProposal(fieldNameProposals[k], null, fieldNameProposals.length - k);
}
}
}
String[] allFieldNames= fieldNames.toArray(new String[fieldNames.size()]);
List<BodyDeclaration> newBodyDeclarations= newDeclaration.bodyDeclarations();
createFieldsForAccessedLocals(rewrite, bindings, allFieldNames, newBodyDeclarations);
MethodDeclaration newConstructorDecl= createNewConstructor(rewrite, bindings, allFieldNames);
if (newConstructorDecl != null) {
newBodyDeclarations.add(newConstructorDecl);
}
updateAndMoveBodyDeclarations(rewrite, bindings, allFieldNames, newBodyDeclarations, newConstructorDecl);
if (doAddComments()) {
String[] parameterNames= new String[typeParameters.length];
for (int index= 0; index < parameterNames.length; index++) {
parameterNames[index]= typeParameters[index].getName();
}
String string= CodeGeneration.getTypeComment(rewrite.getCu(), fClassName, parameterNames, StubUtility.getLineDelimiterUsed(fCu));
if (string != null) {
Javadoc javadoc= (Javadoc) rewrite.getASTRewrite().createStringPlaceholder(string, ASTNode.JAVADOC);
newDeclaration.setJavadoc(javadoc);
}
}
if (fLinkedProposalModel != null) {
addLinkedPosition(KEY_TYPE_NAME, newDeclaration.getName(), rewrite.getASTRewrite(), false);
ModifierCorrectionSubProcessor.installLinkedVisibilityProposals(fLinkedProposalModel, rewrite.getASTRewrite(), newDeclaration.modifiers(), false);
}
return newDeclaration;
}
private void updateAndMoveBodyDeclarations(CompilationUnitRewrite rewriter, IVariableBinding[] bindings, String[] fieldNames, List<BodyDeclaration> newBodyDeclarations, MethodDeclaration newConstructorDecl) {
final ASTRewrite astRewrite= rewriter.getASTRewrite();
final AST ast= astRewrite.getAST();
final boolean useThisAccess= useThisForFieldAccess();
int fieldInsertIndex= newConstructorDecl != null ? newBodyDeclarations.lastIndexOf(newConstructorDecl) : newBodyDeclarations.size();
for (Iterator<BodyDeclaration> iterator= fAnonymousInnerClassNode.bodyDeclarations().iterator(); iterator.hasNext();) {
BodyDeclaration body= iterator.next();
for (int i= 0; i < bindings.length; i++) {
SimpleName[] names= LinkedNodeFinder.findByBinding(body, bindings[i]);
String fieldName= fieldNames[i];
for (int k= 0; k < names.length; k++) {
SimpleName newNode= ast.newSimpleName(fieldName);
if (useThisAccess) {
FieldAccess access= ast.newFieldAccess();
access.setExpression(ast.newThisExpression());
access.setName(newNode);
astRewrite.replace(names[k], access, null);
} else {
astRewrite.replace(names[k], newNode, null);
}
addLinkedPosition(KEY_FIELD_NAME_EXT + i, newNode, astRewrite, false);
}
}
if (body instanceof Initializer || body instanceof FieldDeclaration) {
newBodyDeclarations.add(fieldInsertIndex++, (BodyDeclaration) astRewrite.createMoveTarget(body));
} else {
newBodyDeclarations.add((BodyDeclaration) astRewrite.createMoveTarget(body));
}
}
if (newConstructorDecl != null) {
// move initialization of existing fields to constructor if an outer is referenced
List<Statement> bodyStatements= newConstructorDecl.getBody().statements();
List<VariableDeclarationFragment> fieldsToInitializeInConstructor= getFieldsToInitializeInConstructor();
for (Iterator<VariableDeclarationFragment> iter= fieldsToInitializeInConstructor.iterator(); iter.hasNext();) {
VariableDeclarationFragment fragment= iter.next();
Expression initializer= fragment.getInitializer();
Expression replacement= (Expression) astRewrite.get(fragment, VariableDeclarationFragment.INITIALIZER_PROPERTY);
if (replacement == initializer) {
replacement= (Expression) astRewrite.createMoveTarget(initializer);
}
astRewrite.remove(initializer, null);
SimpleName fieldNameNode= ast.newSimpleName(fragment.getName().getIdentifier());
bodyStatements.add(newFieldAssignment(ast, fieldNameNode, replacement, useThisAccess));
}
}
}
private void createFieldsForAccessedLocals(CompilationUnitRewrite rewrite, IVariableBinding[] varBindings, String[] fieldNames, List<BodyDeclaration> newBodyDeclarations) throws CoreException {
final ImportRewrite importRewrite= rewrite.getImportRewrite();
final ASTRewrite astRewrite= rewrite.getASTRewrite();
final AST ast= astRewrite.getAST();
for (int i= 0; i < varBindings.length; i++) {
VariableDeclarationFragment fragment= ast.newVariableDeclarationFragment();
fragment.setExtraDimensions(0);
fragment.setInitializer(null);
fragment.setName(ast.newSimpleName(fieldNames[i]));
FieldDeclaration field= ast.newFieldDeclaration(fragment);
ITypeBinding varType= varBindings[i].getType();
field.setType(importRewrite.addImport(varType, ast));
field.modifiers().addAll(ASTNodeFactory.newModifiers(ast, Modifier.PRIVATE | Modifier.FINAL));
if (doAddComments()) {
String string= CodeGeneration.getFieldComment(rewrite.getCu(), varType.getName(), fieldNames[i], StubUtility.getLineDelimiterUsed(fCu));
if (string != null) {
Javadoc javadoc= (Javadoc) astRewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
field.setJavadoc(javadoc);
}
}
newBodyDeclarations.add(field);
addLinkedPosition(KEY_FIELD_NAME_EXT + i, fragment.getName(), astRewrite, false);
}
}
private void addLinkedPosition(String key, ASTNode nodeToTrack, ASTRewrite rewrite, boolean isFirst) {
if (fLinkedProposalModel != null) {
fLinkedProposalModel.getPositionGroup(key, true).addPosition(rewrite.track(nodeToTrack), isFirst);
}
}
private IVariableBinding[] getUsedLocalVariables() {
final Set<IBinding> result= new HashSet<IBinding>(0);
collectRefrencedVariables(fAnonymousInnerClassNode, result);
ArrayList<IVariableBinding> usedLocals= new ArrayList<IVariableBinding>();
for (Iterator<IBinding> iterator= result.iterator(); iterator.hasNext();) {
IVariableBinding next= (IVariableBinding) iterator.next();
if (isBindingToTemp(next)) {
usedLocals.add(next);
}
}
return usedLocals.toArray(new IVariableBinding[usedLocals.size()]);
}
private void collectRefrencedVariables(ASTNode root, final Set<IBinding> result) {
root.accept(new ASTVisitor() {
@Override
public boolean visit(SimpleName node) {
IBinding binding= node.resolveBinding();
if (binding instanceof IVariableBinding)
result.add(binding);
return true;
}
});
}
private boolean isBindingToTemp(IVariableBinding variable) {
if (variable.isField())
return false;
if (!Modifier.isFinal(variable.getModifiers()))
return false;
ASTNode declaringNode= fCompilationUnitNode.findDeclaringNode(variable);
if (declaringNode == null)
return false;
if (ASTNodes.isParent(declaringNode, fAnonymousInnerClassNode))
return false;
return true;
}
private MethodDeclaration createNewConstructor(CompilationUnitRewrite rewrite, IVariableBinding[] bindings, String[] fieldNames) throws JavaModelException {
ClassInstanceCreation instanceCreation= (ClassInstanceCreation) fAnonymousInnerClassNode.getParent();
if (instanceCreation.arguments().isEmpty() && bindings.length == 0)
return null;
IJavaProject project= fCu.getJavaProject();
AST ast= rewrite.getAST();
ImportRewrite importRewrite= rewrite.getImportRewrite();
ASTRewrite astRewrite= rewrite.getASTRewrite();
MethodDeclaration newConstructor= ast.newMethodDeclaration();
newConstructor.setConstructor(true);
newConstructor.setExtraDimensions(0);
newConstructor.setJavadoc(null);
newConstructor.modifiers().addAll(ASTNodeFactory.newModifiers(ast, fVisibility));
newConstructor.setName(ast.newSimpleName(fClassName));
addLinkedPosition(KEY_TYPE_NAME, newConstructor.getName(), astRewrite, false);
newConstructor.setBody(ast.newBlock());
List<Statement> newStatements= newConstructor.getBody().statements();
List<SingleVariableDeclaration> newParameters= newConstructor.parameters();
List<String> newParameterNames= new ArrayList<String>();
// add parameters for elements passed with the instance creation
if (!instanceCreation.arguments().isEmpty()) {
IMethodBinding constructorBinding= getSuperConstructorBinding();
if (constructorBinding != null) {
SuperConstructorInvocation superConstructorInvocation= ast.newSuperConstructorInvocation();
ITypeBinding[] parameterTypes= constructorBinding.getParameterTypes();
String[][] parameterNames= StubUtility.suggestArgumentNamesWithProposals(project, constructorBinding);
for (int i= 0; i < parameterNames.length; i++) {
String[] nameProposals= parameterNames[i];
String paramName= nameProposals[0];
SingleVariableDeclaration param= newParameterDeclaration(ast, importRewrite, paramName, parameterTypes[i]);
newParameters.add(param);
newParameterNames.add(paramName);
SimpleName newSIArgument= ast.newSimpleName(paramName);
superConstructorInvocation.arguments().add(newSIArgument);
if (fLinkedProposalModel != null) {
LinkedProposalPositionGroup positionGroup= fLinkedProposalModel.getPositionGroup(KEY_PARAM_NAME_CONST+ String.valueOf(i), true);
positionGroup.addPosition(astRewrite.track(param.getName()), false);
positionGroup.addPosition(astRewrite.track(newSIArgument), false);
for (int k= 0; k < nameProposals.length; k++) {
positionGroup.addProposal(nameProposals[k], null, nameProposals.length - k);
}
}
}
newStatements.add(superConstructorInvocation);
}
}
// add parameters for all outer variables used
boolean useThisAccess= useThisForFieldAccess();
for (int i= 0; i < bindings.length; i++) {
String baseName= StubUtility.getBaseName(bindings[i], project);
String[] paramNameProposals= StubUtility.getVariableNameSuggestions(NamingConventions.VK_PARAMETER, project, baseName, 0, newParameterNames, true);
String paramName= paramNameProposals[0];
SingleVariableDeclaration param= newParameterDeclaration(ast, importRewrite, paramName, bindings[i].getType());
newParameters.add(param);
newParameterNames.add(paramName);
String fieldName= fieldNames[i];
SimpleName fieldNameNode= ast.newSimpleName(fieldName);
SimpleName paramNameNode= ast.newSimpleName(paramName);
newStatements.add(newFieldAssignment(ast, fieldNameNode, paramNameNode, useThisAccess || newParameterNames.contains(fieldName)));
if (fLinkedProposalModel != null) {
LinkedProposalPositionGroup positionGroup= fLinkedProposalModel.getPositionGroup(KEY_PARAM_NAME_EXT+ String.valueOf(i), true);
positionGroup.addPosition(astRewrite.track(param.getName()), false);
positionGroup.addPosition(astRewrite.track(paramNameNode), false);
for (int k= 0; k < paramNameProposals.length; k++) {
positionGroup.addProposal(paramNameProposals[k], null, paramNameProposals.length - k);
}
fLinkedProposalModel.getPositionGroup(KEY_FIELD_NAME_EXT + i, true).addPosition(astRewrite.track(fieldNameNode), false);
}
}
addExceptionsToNewConstructor(newConstructor);
if (doAddComments()) {
try {
String[] allParamNames= newParameterNames.toArray(new String[newParameterNames.size()]);
String string= CodeGeneration.getMethodComment(fCu, fClassName, fClassName, allParamNames, new String[0], null, new String[0], null, StubUtility.getLineDelimiterUsed(fCu));
if (string != null) {
Javadoc javadoc= (Javadoc) astRewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
newConstructor.setJavadoc(javadoc);
}
} catch (CoreException exception) {
throw new JavaModelException(exception);
}
}
return newConstructor;
}
private Statement newFieldAssignment(AST ast, SimpleName fieldNameNode, Expression initializer, boolean useThisAccess) {
Assignment assignment= ast.newAssignment();
if (useThisAccess) {
FieldAccess access= ast.newFieldAccess();
access.setExpression(ast.newThisExpression());
access.setName(fieldNameNode);
assignment.setLeftHandSide(access);
} else {
assignment.setLeftHandSide(fieldNameNode);
}
assignment.setOperator(Assignment.Operator.ASSIGN);
assignment.setRightHandSide(initializer);
return ast.newExpressionStatement(assignment);
}
// live List of VariableDeclarationFragments
private List<VariableDeclarationFragment> getFieldsToInitializeInConstructor() {
List<VariableDeclarationFragment> result= new ArrayList<VariableDeclarationFragment>(0);
for (Iterator<BodyDeclaration> iter= fAnonymousInnerClassNode.bodyDeclarations().iterator(); iter.hasNext(); ) {
Object element= iter.next();
if (element instanceof FieldDeclaration) {
List<VariableDeclarationFragment> fragments= ((FieldDeclaration) element).fragments();
for (Iterator<VariableDeclarationFragment> fragmentIter= fragments.iterator(); fragmentIter.hasNext(); ) {
VariableDeclarationFragment fragment= fragmentIter.next();
if (isToBeInitializerInConstructor(fragment, result))
result.add(fragment);
}
}
}
return result;
}
private boolean isToBeInitializerInConstructor(VariableDeclarationFragment fragment, List<VariableDeclarationFragment> fieldsToInitialize) {
return fragment.getInitializer() != null && areLocalsUsedIn(fragment.getInitializer(), fieldsToInitialize);
}
private boolean areLocalsUsedIn(Expression fieldInitializer, List<VariableDeclarationFragment> fieldsToInitialize) {
Set<IBinding> localsUsed= new HashSet<IBinding>(0);
collectRefrencedVariables(fieldInitializer, localsUsed);
ITypeBinding anonType= fAnonymousInnerClassNode.resolveBinding();
for (Iterator<IBinding> iterator= localsUsed.iterator(); iterator.hasNext();) {
IVariableBinding curr= (IVariableBinding) iterator.next();
if (isBindingToTemp(curr)) { // reference a local from outside
return true;
} else if (curr.isField() && (curr.getDeclaringClass() == anonType) && fieldsToInitialize.contains(fCompilationUnitNode.findDeclaringNode(curr))) {
return true; // references a field that references a local from outside
}
}
return false;
}
private IMethodBinding getSuperConstructorBinding() {
//workaround for missing java core functionality - finding a
// super constructor for an anonymous class creation
IMethodBinding anonConstr= ((ClassInstanceCreation) fAnonymousInnerClassNode.getParent()).resolveConstructorBinding();
if (anonConstr == null)
return null;
ITypeBinding superClass= anonConstr.getDeclaringClass().getSuperclass();
IMethodBinding[] superMethods= superClass.getDeclaredMethods();
for (int i= 0; i < superMethods.length; i++) {
IMethodBinding superMethod= superMethods[i];
if (superMethod.isConstructor() && parameterTypesMatch(superMethod, anonConstr))
return superMethod;
}
Assert.isTrue(false);//there's no way - it must be there
return null;
}
private static boolean parameterTypesMatch(IMethodBinding m1, IMethodBinding m2) {
ITypeBinding[] m1Params= m1.getParameterTypes();
ITypeBinding[] m2Params= m2.getParameterTypes();
if (m1Params.length != m2Params.length)
return false;
for (int i= 0; i < m2Params.length; i++) {
if (!m1Params[i].equals(m2Params[i]))
return false;
}
return true;
}
private void addExceptionsToNewConstructor(MethodDeclaration newConstructor) {
IMethodBinding constructorBinding= getSuperConstructorBinding();
if (constructorBinding == null)
return;
ITypeBinding[] exceptions= constructorBinding.getExceptionTypes();
for (int i= 0; i < exceptions.length; i++) {
Name exceptionTypeName= fAnonymousInnerClassNode.getAST().newName(Bindings.getNameComponents(exceptions[i]));
newConstructor.thrownExceptions().add(exceptionTypeName);
}
}
private SingleVariableDeclaration newParameterDeclaration(AST ast, ImportRewrite importRewrite, String paramName, ITypeBinding paramType) {
SingleVariableDeclaration param= ast.newSingleVariableDeclaration();
param.setExtraDimensions(0);
param.setInitializer(null);
param.setType(importRewrite.addImport(paramType, ast));
param.setName(ast.newSimpleName(paramName));
return param;
}
private void setSuperType(TypeDeclaration declaration) {
ClassInstanceCreation classInstanceCreation= (ClassInstanceCreation) fAnonymousInnerClassNode.getParent();
ITypeBinding binding= classInstanceCreation.resolveTypeBinding();
if (binding == null)
return;
Type newType= (Type) ASTNode.copySubtree(fAnonymousInnerClassNode.getAST(), classInstanceCreation.getType());
if (binding.getSuperclass().getQualifiedName().equals("java.lang.Object")) { //$NON-NLS-1$
Assert.isTrue(binding.getInterfaces().length <= 1);
if (binding.getInterfaces().length == 0)
return;
declaration.superInterfaceTypes().add(0, newType);
} else {
declaration.setSuperclassType(newType);
}
}
private ITypeBinding getSuperTypeBinding() {
ITypeBinding types= fAnonymousInnerClassNode.resolveBinding();
ITypeBinding[] interfaces= types.getInterfaces();
if (interfaces.length > 0)
return interfaces[0];
else
return types.getSuperclass();
}
private int createModifiersForNestedClass() {
int flags= fVisibility;
if (fDeclareFinal)
flags|= Modifier.FINAL;
if (mustInnerClassBeStatic() || fDeclareStatic)
flags|= Modifier.STATIC;
return flags;
}
public boolean mustInnerClassBeStatic() {
ITypeBinding typeBinding = ((AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class)).resolveBinding();
ASTNode current = fAnonymousInnerClassNode.getParent();
boolean ans = false;
while(current != null) {
switch(current.getNodeType()) {
case ASTNode.ANONYMOUS_CLASS_DECLARATION:
{
AnonymousClassDeclaration enclosingAnonymousClassDeclaration= (AnonymousClassDeclaration)current;
ITypeBinding binding= enclosingAnonymousClassDeclaration.resolveBinding();
if (binding != null && Bindings.isSuperType(typeBinding, binding.getSuperclass())) {
return false;
}
break;
}
case ASTNode.FIELD_DECLARATION:
{
FieldDeclaration enclosingFieldDeclaration= (FieldDeclaration)current;
if (Modifier.isStatic(enclosingFieldDeclaration.getModifiers())) {
ans = true;
}
break;
}
case ASTNode.METHOD_DECLARATION:
{
MethodDeclaration enclosingMethodDeclaration = (MethodDeclaration)current;
if (Modifier.isStatic(enclosingMethodDeclaration.getModifiers())) {
ans = true;
}
break;
}
case ASTNode.TYPE_DECLARATION:
{
return ans;
}
}
current = current.getParent();
}
return ans;
}
private RefactoringStatus initialize(JavaRefactoringArguments arguments) {
fSelfInitializing= true;
final String handle= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
if (handle != null) {
final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), handle, false);
if (element == null || !element.exists() || element.getElementType() != IJavaElement.COMPILATION_UNIT)
return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.CONVERT_ANONYMOUS);
else {
fCu= (ICompilationUnit) element;
}
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
final String name= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
if (name != null && !"".equals(name)) //$NON-NLS-1$
fClassName= name;
else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
final String visibility= arguments.getAttribute(ATTRIBUTE_VISIBILITY);
if (visibility != null && !"".equals(visibility)) {//$NON-NLS-1$
int flag= 0;
try {
flag= Integer.parseInt(visibility);
} catch (NumberFormatException exception) {
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_VISIBILITY));
}
fVisibility= flag;
}
final String selection= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION);
if (selection != null) {
int offset= -1;
int length= -1;
final StringTokenizer tokenizer= new StringTokenizer(selection);
if (tokenizer.hasMoreTokens())
offset= Integer.valueOf(tokenizer.nextToken()).intValue();
if (tokenizer.hasMoreTokens())
length= Integer.valueOf(tokenizer.nextToken()).intValue();
if (offset >= 0 && length >= 0) {
fSelectionStart= offset;
fSelectionLength= length;
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { selection, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION}));
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION));
final String declareStatic= arguments.getAttribute(ATTRIBUTE_STATIC);
if (declareStatic != null) {
fDeclareStatic= Boolean.valueOf(declareStatic).booleanValue();
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_STATIC));
final String declareFinal= arguments.getAttribute(ATTRIBUTE_FINAL);
if (declareFinal != null) {
fDeclareFinal= Boolean.valueOf(declareStatic).booleanValue();
} else
return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FINAL));
return new RefactoringStatus();
}
}