| /******************************************************************************* |
| * Copyright (c) 2000, 2006 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.jdt.internal.corext.refactoring.structure; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.text.edits.TextEdit; |
| import org.eclipse.text.edits.TextEditGroup; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.ltk.core.refactoring.IRefactoringStatusEntryComparator; |
| import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; |
| import org.eclipse.ltk.core.refactoring.TextChange; |
| import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; |
| |
| import org.eclipse.jdt.core.Flags; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IField; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.ITypeHierarchy; |
| import org.eclipse.jdt.core.ITypeParameter; |
| 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.ASTParser; |
| 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.Assignment; |
| import org.eclipse.jdt.core.dom.Block; |
| import org.eclipse.jdt.core.dom.ClassInstanceCreation; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.ConstructorInvocation; |
| import org.eclipse.jdt.core.dom.EnumDeclaration; |
| 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.ImportDeclaration; |
| import org.eclipse.jdt.core.dom.Javadoc; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.MethodInvocation; |
| import org.eclipse.jdt.core.dom.Modifier; |
| import org.eclipse.jdt.core.dom.Name; |
| import org.eclipse.jdt.core.dom.ParameterizedType; |
| import org.eclipse.jdt.core.dom.QualifiedName; |
| import org.eclipse.jdt.core.dom.QualifiedType; |
| import org.eclipse.jdt.core.dom.SimpleName; |
| import org.eclipse.jdt.core.dom.SimpleType; |
| 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.ThisExpression; |
| import org.eclipse.jdt.core.dom.Type; |
| import org.eclipse.jdt.core.dom.TypeDeclaration; |
| import org.eclipse.jdt.core.dom.TypeDeclarationStatement; |
| import org.eclipse.jdt.core.dom.TypeParameter; |
| import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
| import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; |
| import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ListRewrite; |
| import org.eclipse.jdt.core.search.IJavaSearchConstants; |
| import org.eclipse.jdt.core.search.SearchMatch; |
| import org.eclipse.jdt.core.search.SearchPattern; |
| |
| import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; |
| 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.ModifierRewrite; |
| import org.eclipse.jdt.internal.corext.refactoring.Checks; |
| import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; |
| import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptor; |
| import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorComment; |
| import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; |
| import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; |
| import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2; |
| import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; |
| import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; |
| import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange; |
| import org.eclipse.jdt.internal.corext.refactoring.changes.CreateCompilationUnitChange; |
| import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; |
| import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor.OutgoingMemberVisibilityAdjustment; |
| import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil; |
| import org.eclipse.jdt.internal.corext.refactoring.util.JavadocUtil; |
| import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; |
| import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; |
| import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; |
| import org.eclipse.jdt.internal.corext.util.JavaModelUtil; |
| import org.eclipse.jdt.internal.corext.util.JdtFlags; |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| import org.eclipse.jdt.internal.corext.util.SearchUtils; |
| import org.eclipse.jdt.internal.corext.util.Strings; |
| |
| import org.eclipse.jdt.ui.CodeGeneration; |
| import org.eclipse.jdt.ui.JavaElementLabels; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings; |
| import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider; |
| |
| public final class MoveInnerToTopRefactoring extends ScriptableRefactoring { |
| |
| private static final String ID_MOVE_INNER= "org.eclipse.jdt.ui.move.inner"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_FIELD= "field"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_MANDATORY= "mandatory"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_POSSIBLE= "possible"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_FINAL= "final"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_FIELD_NAME= "fieldName"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_PARAMETER_NAME= "parameterName"; //$NON-NLS-1$ |
| |
| private static class MemberAccessNodeCollector extends ASTVisitor { |
| |
| private final List fFieldAccesses= new ArrayList(0); |
| |
| private final ITypeHierarchy fHierarchy; |
| |
| private final List fMethodAccesses= new ArrayList(0); |
| |
| private final List fSimpleNames= new ArrayList(0); |
| |
| MemberAccessNodeCollector(ITypeHierarchy hierarchy) { |
| Assert.isNotNull(hierarchy); |
| fHierarchy= hierarchy; |
| } |
| |
| FieldAccess[] getFieldAccesses() { |
| return (FieldAccess[]) fFieldAccesses.toArray(new FieldAccess[fFieldAccesses.size()]); |
| } |
| |
| MethodInvocation[] getMethodInvocations() { |
| return (MethodInvocation[]) fMethodAccesses.toArray(new MethodInvocation[fMethodAccesses.size()]); |
| } |
| |
| SimpleName[] getSimpleFieldNames() { |
| return (SimpleName[]) fSimpleNames.toArray(new SimpleName[fSimpleNames.size()]); |
| } |
| |
| public boolean visit(FieldAccess node) { |
| final ITypeBinding declaring= MoveInnerToTopRefactoring.getDeclaringTypeBinding(node); |
| if (declaring != null) { |
| final IType type= (IType) declaring.getJavaElement(); |
| if (type != null && fHierarchy.contains(type)) |
| fFieldAccesses.add(node); |
| } |
| return super.visit(node); |
| } |
| |
| public boolean visit(MethodInvocation node) { |
| final ITypeBinding declaring= MoveInnerToTopRefactoring.getDeclaringTypeBinding(node); |
| if (declaring != null) { |
| final IType type= (IType) declaring.getJavaElement(); |
| if (type != null && fHierarchy.contains(type)) |
| fMethodAccesses.add(node); |
| } |
| return super.visit(node); |
| } |
| |
| public boolean visit(SimpleName node) { |
| if (node.getParent() instanceof QualifiedName) |
| return super.visit(node); |
| IBinding binding= node.resolveBinding(); |
| if (binding instanceof IVariableBinding) { |
| IVariableBinding variable= (IVariableBinding) binding; |
| ITypeBinding declaring= variable.getDeclaringClass(); |
| if (variable.isField() && declaring != null) { |
| final IType type= (IType) declaring.getJavaElement(); |
| if (type != null && fHierarchy.contains(type)) { |
| fSimpleNames.add(node); |
| return false; |
| } |
| } |
| } |
| return super.visit(node); |
| } |
| |
| public boolean visit(ThisExpression node) { |
| final Name qualifier= node.getQualifier(); |
| if (qualifier != null) { |
| final ITypeBinding binding= qualifier.resolveTypeBinding(); |
| if (binding != null) { |
| final IType type= (IType) binding.getJavaElement(); |
| if (type != null && fHierarchy.contains(type)) { |
| fSimpleNames.add(qualifier); |
| return false; |
| } |
| } |
| } |
| return super.visit(node); |
| } |
| } |
| |
| private class TypeReferenceQualifier extends ASTVisitor { |
| |
| private final TextEditGroup fGroup; |
| |
| private final ITypeBinding fTypeBinding; |
| |
| public TypeReferenceQualifier(final ITypeBinding type, final TextEditGroup group) { |
| Assert.isNotNull(type); |
| Assert.isNotNull(type.getDeclaringClass()); |
| fTypeBinding= type; |
| fGroup= group; |
| } |
| |
| public boolean visit(final ClassInstanceCreation node) { |
| Assert.isNotNull(node); |
| if (fCreateInstanceField) { |
| final AST ast= node.getAST(); |
| final Type type= node.getType(); |
| final ITypeBinding binding= type.resolveBinding(); |
| if (binding != null && binding.getDeclaringClass() != null && !Bindings.equals(binding, fTypeBinding) && fSourceRewrite.getRoot().findDeclaringNode(binding) != null) { |
| if (!Modifier.isStatic(binding.getModifiers())) { |
| Expression expression= null; |
| if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) { |
| final FieldAccess access= ast.newFieldAccess(); |
| access.setExpression(ast.newThisExpression()); |
| access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); |
| expression= access; |
| } else |
| expression= ast.newSimpleName(fEnclosingInstanceFieldName); |
| if (node.getExpression() != null) |
| fSourceRewrite.getImportRemover().registerRemovedNode(node.getExpression()); |
| fSourceRewrite.getASTRewrite().set(node, ClassInstanceCreation.EXPRESSION_PROPERTY, expression, fGroup); |
| } else |
| addTypeQualification(type, fSourceRewrite, fGroup); |
| } |
| } |
| return true; |
| } |
| |
| public boolean visit(final QualifiedType node) { |
| Assert.isNotNull(node); |
| return false; |
| } |
| |
| public boolean visit(final SimpleType node) { |
| Assert.isNotNull(node); |
| if (!(node.getParent() instanceof ClassInstanceCreation)) { |
| final ITypeBinding binding= node.resolveBinding(); |
| if (binding != null) { |
| final ITypeBinding declaring= binding.getDeclaringClass(); |
| if (declaring != null && !Bindings.equals(declaring, fTypeBinding.getDeclaringClass()) && !Bindings.equals(binding, fTypeBinding) && fSourceRewrite.getRoot().findDeclaringNode(binding) != null && Modifier.isStatic(binding.getModifiers())) |
| addTypeQualification(node, fSourceRewrite, fGroup); |
| } |
| } |
| return super.visit(node); |
| } |
| |
| public boolean visit(final ThisExpression node) { |
| Assert.isNotNull(node); |
| final Name name= node.getQualifier(); |
| if (name != null && name.isSimpleName()) { |
| final AST ast= node.getAST(); |
| Expression expression= null; |
| if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) { |
| final FieldAccess access= ast.newFieldAccess(); |
| access.setExpression(ast.newThisExpression()); |
| access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); |
| expression= access; |
| } else |
| expression= ast.newSimpleName(fEnclosingInstanceFieldName); |
| fSourceRewrite.getASTRewrite().replace(node, expression, null); |
| } |
| return super.visit(node); |
| } |
| } |
| |
| private static void addTypeParameters(final CompilationUnit unit, final IType type, final Map map) throws JavaModelException { |
| Assert.isNotNull(unit); |
| Assert.isNotNull(type); |
| Assert.isNotNull(map); |
| final AbstractTypeDeclaration declaration= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(type, unit); |
| if (declaration instanceof TypeDeclaration) { |
| ITypeBinding binding= null; |
| TypeParameter parameter= null; |
| for (final Iterator iterator= ((TypeDeclaration) declaration).typeParameters().iterator(); iterator.hasNext();) { |
| parameter= (TypeParameter) iterator.next(); |
| binding= parameter.resolveBinding(); |
| if (binding != null && !map.containsKey(binding.getKey())) |
| map.put(binding.getKey(), binding); |
| } |
| final IType declaring= type.getDeclaringType(); |
| if (declaring != null && !Flags.isStatic(type.getFlags())) |
| addTypeParameters(unit, declaring, map); |
| } |
| } |
| |
| private static boolean containsNonStatic(FieldAccess[] accesses) { |
| for (int i= 0; i < accesses.length; i++) { |
| if (!isStatic(accesses[i])) |
| return true; |
| } |
| return false; |
| } |
| |
| private static boolean containsNonStatic(MethodInvocation[] invocations) { |
| for (int i= 0; i < invocations.length; i++) { |
| if (!isStatic(invocations[i])) |
| return true; |
| } |
| return false; |
| } |
| |
| private static boolean containsNonStatic(SimpleName[] fieldNames) { |
| for (int i= 0; i < fieldNames.length; i++) { |
| if (!isStaticFieldName(fieldNames[i])) |
| return true; |
| } |
| return false; |
| } |
| |
| private static boolean containsStatusEntry(final RefactoringStatus status, final RefactoringStatusEntry other) { |
| return status.getEntries(new IRefactoringStatusEntryComparator() { |
| |
| public final int compare(final RefactoringStatusEntry entry1, final RefactoringStatusEntry entry2) { |
| return entry1.getMessage().compareTo(entry2.getMessage()); |
| } |
| }, other).length > 0; |
| } |
| |
| private static AbstractTypeDeclaration findTypeDeclaration(IType enclosing, AbstractTypeDeclaration[] declarations) { |
| String typeName= enclosing.getElementName(); |
| for (int i= 0; i < declarations.length; i++) { |
| AbstractTypeDeclaration declaration= declarations[i]; |
| if (declaration.getName().getIdentifier().equals(typeName)) |
| return declaration; |
| } |
| return null; |
| } |
| |
| private static AbstractTypeDeclaration findTypeDeclaration(IType type, CompilationUnit unit) { |
| final List types= getDeclaringTypes(type); |
| types.add(type); |
| AbstractTypeDeclaration[] declarations= (AbstractTypeDeclaration[]) unit.types().toArray(new AbstractTypeDeclaration[unit.types().size()]); |
| AbstractTypeDeclaration declaration= null; |
| for (final Iterator iterator= types.iterator(); iterator.hasNext();) { |
| IType enclosing= (IType) iterator.next(); |
| declaration= findTypeDeclaration(enclosing, declarations); |
| Assert.isNotNull(declaration); |
| declarations= getAbstractTypeDeclarations(declaration); |
| } |
| Assert.isNotNull(declaration); |
| return declaration; |
| } |
| |
| public static AbstractTypeDeclaration[] getAbstractTypeDeclarations(final AbstractTypeDeclaration declaration) { |
| int typeCount= 0; |
| for (Iterator iterator= declaration.bodyDeclarations().listIterator(); iterator.hasNext();) { |
| if (iterator.next() instanceof AbstractTypeDeclaration) { |
| typeCount++; |
| } |
| } |
| AbstractTypeDeclaration[] declarations= new AbstractTypeDeclaration[typeCount]; |
| int next= 0; |
| for (final Iterator iterator= declaration.bodyDeclarations().listIterator(); iterator.hasNext();) { |
| Object object= iterator.next(); |
| if (object instanceof AbstractTypeDeclaration) { |
| declarations[next++]= (AbstractTypeDeclaration) object; |
| } |
| } |
| return declarations; |
| } |
| |
| private static ITypeBinding getDeclaringTypeBinding(FieldAccess fieldAccess) { |
| IVariableBinding varBinding= fieldAccess.resolveFieldBinding(); |
| if (varBinding == null) |
| return null; |
| return varBinding.getDeclaringClass(); |
| } |
| |
| private static ITypeBinding getDeclaringTypeBinding(MethodInvocation methodInvocation) { |
| IMethodBinding binding= methodInvocation.resolveMethodBinding(); |
| if (binding == null) |
| return null; |
| return binding.getDeclaringClass(); |
| } |
| |
| // List of ITypes |
| private static List getDeclaringTypes(IType type) { |
| IType declaringType= type.getDeclaringType(); |
| if (declaringType == null) |
| return new ArrayList(0); |
| List result= getDeclaringTypes(declaringType); |
| result.add(declaringType); |
| return result; |
| } |
| |
| private static String[] getFieldNames(IType type) { |
| try { |
| IField[] fields= type.getFields(); |
| List result= new ArrayList(fields.length); |
| for (int i= 0; i < fields.length; i++) { |
| result.add(fields[i].getElementName()); |
| } |
| return (String[]) result.toArray(new String[result.size()]); |
| } catch (JavaModelException e) { |
| return null; |
| } |
| } |
| |
| private static Set getMergedSet(Set s1, Set s2) { |
| Set result= new HashSet(); |
| result.addAll(s1); |
| result.addAll(s2); |
| return result; |
| } |
| |
| private static String[] getParameterNamesOfAllConstructors(IType type) throws JavaModelException { |
| IMethod[] constructors= JavaElementUtil.getAllConstructors(type); |
| Set result= new HashSet(); |
| for (int i= 0; i < constructors.length; i++) { |
| result.addAll(Arrays.asList(constructors[i].getParameterNames())); |
| } |
| return (String[]) result.toArray(new String[result.size()]); |
| } |
| |
| private static ASTNode[] getReferenceNodesIn(CompilationUnit cuNode, Map references, ICompilationUnit cu) { |
| SearchMatch[] results= (SearchMatch[]) references.get(cu); |
| if (results == null) |
| return new ASTNode[0]; |
| return ASTNodeSearchUtil.getAstNodes(results, cuNode); |
| } |
| |
| private static boolean isCorrespondingTypeBinding(ITypeBinding binding, IType type) { |
| if (binding == null) |
| return false; |
| return Bindings.getFullyQualifiedName(binding).equals(JavaElementUtil.createSignature(type)); |
| } |
| |
| private static boolean isStatic(FieldAccess access) { |
| IVariableBinding fieldBinding= access.resolveFieldBinding(); |
| if (fieldBinding == null) |
| return false; |
| return JdtFlags.isStatic(fieldBinding); |
| } |
| |
| private static boolean isStatic(MethodInvocation invocation) { |
| IMethodBinding methodBinding= invocation.resolveMethodBinding(); |
| if (methodBinding == null) |
| return false; |
| return JdtFlags.isStatic(methodBinding); |
| } |
| |
| private static boolean isStaticFieldName(SimpleName name) { |
| IBinding binding= name.resolveBinding(); |
| if (!(binding instanceof IVariableBinding)) |
| return false; |
| IVariableBinding variableBinding= (IVariableBinding) binding; |
| if (!variableBinding.isField()) |
| return false; |
| return JdtFlags.isStatic(variableBinding); |
| } |
| |
| private TextChangeManager fChangeManager; |
| |
| private CodeGenerationSettings fCodeGenerationSettings; |
| |
| private boolean fCreateInstanceField; |
| |
| private String fEnclosingInstanceFieldName; |
| |
| private boolean fIsInstanceFieldCreationMandatory; |
| |
| private boolean fIsInstanceFieldCreationPossible; |
| |
| private boolean fMarkInstanceFieldAsFinal; |
| |
| private String fNameForEnclosingInstanceConstructorParameter; |
| |
| private String fNewSourceOfInputType; |
| |
| private CompilationUnitRewrite fSourceRewrite; |
| |
| private Collection fStaticImports; |
| |
| private IType fType; |
| |
| private String fQualifiedTypeName; |
| |
| private Collection fTypeImports; |
| |
| /** |
| * Creates a new move inner to top refactoring. |
| * @param type the type, or <code>null</code> if invoked by scripting |
| * @param settings the code generation settings, or <code>null</code> if invoked by scripting |
| * @throws JavaModelException |
| */ |
| public MoveInnerToTopRefactoring(IType type, CodeGenerationSettings settings) throws JavaModelException { |
| fType= type; |
| fCodeGenerationSettings= settings; |
| fMarkInstanceFieldAsFinal= true; // default |
| if (fType != null) |
| initialize(); |
| } |
| |
| private void initialize() throws JavaModelException { |
| fQualifiedTypeName= JavaModelUtil.concatenateName(fType.getPackageFragment().getElementName(), fType.getElementName()); |
| fEnclosingInstanceFieldName= getInitialNameForEnclosingInstanceField(); |
| fSourceRewrite= new CompilationUnitRewrite(fType.getCompilationUnit()); |
| fIsInstanceFieldCreationPossible= !(JdtFlags.isStatic(fType) || fType.isAnnotation() || fType.isEnum()); |
| fIsInstanceFieldCreationMandatory= fIsInstanceFieldCreationPossible && isInstanceFieldCreationMandatory(); |
| fCreateInstanceField= fIsInstanceFieldCreationMandatory; |
| } |
| |
| private void addEnclosingInstanceDeclaration(final AbstractTypeDeclaration declaration, final ASTRewrite rewrite) throws CoreException { |
| Assert.isNotNull(declaration); |
| Assert.isNotNull(rewrite); |
| final AST ast= declaration.getAST(); |
| final VariableDeclarationFragment fragment= ast.newVariableDeclarationFragment(); |
| fragment.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); |
| final FieldDeclaration newField= ast.newFieldDeclaration(fragment); |
| newField.modifiers().addAll(ASTNodeFactory.newModifiers(ast, getEnclosingInstanceAccessModifiers())); |
| newField.setType(createEnclosingType(ast)); |
| final String comment= CodeGeneration.getFieldComment(fType.getCompilationUnit(), declaration.getName().getIdentifier(), fEnclosingInstanceFieldName, StubUtility.getLineDelimiterUsed(fType.getJavaProject())); |
| if (comment != null && comment.length() > 0) { |
| final Javadoc doc= (Javadoc) rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC); |
| newField.setJavadoc(doc); |
| } |
| rewrite.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertFirst(newField, null); |
| } |
| |
| private void addEnclosingInstanceTypeParameters(final ITypeBinding[] parameters, final AbstractTypeDeclaration declaration, final ASTRewrite rewrite) { |
| Assert.isNotNull(parameters); |
| Assert.isNotNull(declaration); |
| Assert.isNotNull(rewrite); |
| if (declaration instanceof TypeDeclaration) { |
| final TypeDeclaration type= (TypeDeclaration) declaration; |
| final List existing= type.typeParameters(); |
| final Set names= new HashSet(); |
| TypeParameter parameter= null; |
| for (final Iterator iterator= existing.iterator(); iterator.hasNext();) { |
| parameter= (TypeParameter) iterator.next(); |
| names.add(parameter.getName().getIdentifier()); |
| } |
| final ListRewrite rewriter= rewrite.getListRewrite(type, TypeDeclaration.TYPE_PARAMETERS_PROPERTY); |
| String name= null; |
| for (int index= 0; index < parameters.length; index++) { |
| name= parameters[index].getName(); |
| if (!names.contains(name)) { |
| parameter= type.getAST().newTypeParameter(); |
| parameter.setName(type.getAST().newSimpleName(name)); |
| rewriter.insertLast(parameter, null); |
| } |
| } |
| } |
| } |
| |
| private void addImportsToTargetUnit(final ICompilationUnit targetUnit, final IProgressMonitor monitor) throws CoreException, JavaModelException { |
| monitor.beginTask("", 2); //$NON-NLS-1$ |
| try { |
| ImportRewrite rewrite= StubUtility.createImportRewrite(targetUnit, true); |
| if (fTypeImports != null) { |
| ITypeBinding type= null; |
| for (final Iterator iterator= fTypeImports.iterator(); iterator.hasNext();) { |
| type= (ITypeBinding) iterator.next(); |
| rewrite.addImport(type); |
| } |
| } |
| if (fStaticImports != null) { |
| IBinding binding= null; |
| for (final Iterator iterator= fStaticImports.iterator(); iterator.hasNext();) { |
| binding= (IBinding) iterator.next(); |
| rewrite.addStaticImport(binding); |
| } |
| } |
| fTypeImports= null; |
| fStaticImports= null; |
| TextEdit edits= rewrite.rewriteImports(new SubProgressMonitor(monitor, 1)); |
| JavaModelUtil.applyEdit(targetUnit, edits, false, new SubProgressMonitor(monitor, 1)); |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| private void addInheritedTypeQualifications(final AbstractTypeDeclaration declaration, final CompilationUnitRewrite targetRewrite, final TextEditGroup group) { |
| Assert.isNotNull(declaration); |
| Assert.isNotNull(targetRewrite); |
| final CompilationUnit unit= (CompilationUnit) declaration.getRoot(); |
| final ITypeBinding binding= declaration.resolveBinding(); |
| if (binding != null) { |
| Type type= null; |
| if (declaration instanceof TypeDeclaration) { |
| type= ((TypeDeclaration) declaration).getSuperclassType(); |
| if (type != null && unit.findDeclaringNode(binding) != null) |
| addTypeQualification(type, targetRewrite, group); |
| } |
| List types= null; |
| if (declaration instanceof TypeDeclaration) |
| types= ((TypeDeclaration) declaration).superInterfaceTypes(); |
| else if (declaration instanceof EnumDeclaration) |
| types= ((EnumDeclaration) declaration).superInterfaceTypes(); |
| if (types != null) { |
| for (final Iterator iterator= types.iterator(); iterator.hasNext();) { |
| type= (Type) iterator.next(); |
| if (unit.findDeclaringNode(type.resolveBinding()) != null) |
| addTypeQualification(type, targetRewrite, group); |
| } |
| } |
| } |
| } |
| |
| private void addParameterToConstructor(final ASTRewrite rewrite, final MethodDeclaration declaration) throws JavaModelException { |
| Assert.isNotNull(rewrite); |
| Assert.isNotNull(declaration); |
| final AST ast= declaration.getAST(); |
| final String name= getNameForEnclosingInstanceConstructorParameter(); |
| final SingleVariableDeclaration variable= ast.newSingleVariableDeclaration(); |
| variable.setType(createEnclosingType(ast)); |
| variable.setName(ast.newSimpleName(name)); |
| rewrite.getListRewrite(declaration, MethodDeclaration.PARAMETERS_PROPERTY).insertFirst(variable, null); |
| JavadocUtil.addParamJavadoc(name, declaration, rewrite, fType.getJavaProject(), null); |
| } |
| |
| private void addSimpleTypeQualification(final CompilationUnitRewrite targetRewrite, final ITypeBinding declaring, final SimpleType simpleType, final TextEditGroup group) { |
| Assert.isNotNull(targetRewrite); |
| Assert.isNotNull(declaring); |
| Assert.isNotNull(simpleType); |
| final AST ast= targetRewrite.getRoot().getAST(); |
| if (!(simpleType.getName() instanceof QualifiedName)) { |
| targetRewrite.getASTRewrite().replace(simpleType, ast.newQualifiedType(targetRewrite.getImportRewrite().addImport(declaring, ast), ast.newSimpleName(simpleType.getName().getFullyQualifiedName())), group); |
| targetRewrite.getImportRemover().registerRemovedNode(simpleType); |
| } |
| } |
| |
| private void addTypeQualification(final Type type, final CompilationUnitRewrite targetRewrite, final TextEditGroup group) { |
| Assert.isNotNull(type); |
| Assert.isNotNull(targetRewrite); |
| final ITypeBinding binding= type.resolveBinding(); |
| if (binding != null) { |
| final ITypeBinding declaring= binding.getDeclaringClass(); |
| if (declaring != null) { |
| if (type instanceof SimpleType) { |
| final SimpleType simpleType= (SimpleType) type; |
| addSimpleTypeQualification(targetRewrite, declaring, simpleType, group); |
| } else if (type instanceof ParameterizedType) { |
| final ParameterizedType parameterizedType= (ParameterizedType) type; |
| final Type rawType= parameterizedType.getType(); |
| if (rawType instanceof SimpleType) |
| addSimpleTypeQualification(targetRewrite, declaring, (SimpleType) rawType, group); |
| } |
| } |
| } |
| } |
| |
| private RefactoringStatus checkConstructorParameterNames() { |
| RefactoringStatus result= new RefactoringStatus(); |
| CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(fType.getCompilationUnit(), false); |
| MethodDeclaration[] nodes= getConstructorDeclarationNodes(findTypeDeclaration(fType, cuNode)); |
| for (int i= 0; i < nodes.length; i++) { |
| MethodDeclaration constructor= nodes[i]; |
| for (Iterator iter= constructor.parameters().iterator(); iter.hasNext();) { |
| SingleVariableDeclaration param= (SingleVariableDeclaration) iter.next(); |
| if (fEnclosingInstanceFieldName.equals(param.getName().getIdentifier())) { |
| String msg= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_name_used, new String[] { param.getName().getIdentifier(), fType.getElementName()}); |
| result.addError(msg, JavaStatusContext.create(fType.getCompilationUnit(), param)); |
| } |
| } |
| } |
| return result; |
| } |
| |
| public RefactoringStatus checkEnclosingInstanceName(String name) { |
| if (!fCreateInstanceField) |
| return new RefactoringStatus(); |
| RefactoringStatus result= Checks.checkFieldName(name); |
| if (!Checks.startsWithLowerCase(name)) |
| result.addWarning(RefactoringCoreMessages.MoveInnerToTopRefactoring_names_start_lowercase); |
| |
| if (fType.getField(name).exists()) { |
| Object[] keys= new String[] { name, fType.getElementName()}; |
| String msg= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_already_declared, keys); |
| result.addError(msg, JavaStatusContext.create(fType.getField(name))); |
| } |
| return result; |
| } |
| |
| public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException { |
| pm.beginTask("", 2);//$NON-NLS-1$ |
| try { |
| RefactoringStatus result= new RefactoringStatus(); |
| |
| if (JdtFlags.isStatic(fType)) |
| result.merge(checkEnclosingInstanceName(fEnclosingInstanceFieldName)); |
| |
| if (fType.getPackageFragment().getCompilationUnit((JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName()))).exists()) { |
| String message= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_compilation_Unit_exists, new String[] { (JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())), fType.getPackageFragment().getElementName()}); |
| result.addFatalError(message); |
| } |
| result.merge(checkEnclosingInstanceName(fEnclosingInstanceFieldName)); |
| result.merge(Checks.checkCompilationUnitName((JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())))); |
| result.merge(checkConstructorParameterNames()); |
| result.merge(checkTypeNameInPackage()); |
| fChangeManager= createChangeManager(new SubProgressMonitor(pm, 1), result); |
| result.merge(Checks.validateModifiesFiles(ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits()), getValidationContext())); |
| return result; |
| } finally { |
| pm.done(); |
| } |
| } |
| |
| public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException { |
| return Checks.checkIfCuBroken(fType); |
| } |
| |
| private RefactoringStatus checkTypeNameInPackage() throws JavaModelException { |
| IType type= Checks.findTypeInPackage(fType.getPackageFragment(), fType.getElementName()); |
| if (type == null || !type.exists()) |
| return null; |
| String message= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_type_exists, new String[] { fType.getElementName(), fType.getPackageFragment().getElementName()}); |
| return RefactoringStatus.createErrorStatus(message); |
| } |
| |
| private Expression createAccessExpressionToEnclosingInstanceFieldText(ASTNode node, IBinding binding, AbstractTypeDeclaration declaration) { |
| if (Modifier.isStatic(binding.getModifiers())) |
| return node.getAST().newName(JavaModelUtil.getTypeQualifiedName(fType.getDeclaringType())); |
| else if ((isInAnonymousTypeInsideInputType(node, declaration) || isInLocalTypeInsideInputType(node, declaration) || isInNonStaticMemberTypeInsideInputType(node, declaration))) |
| return createQualifiedReadAccessExpressionForEnclosingInstance(node.getAST()); |
| else |
| return createReadAccessExpressionForEnclosingInstance(node.getAST()); |
| } |
| |
| public Change createChange(final IProgressMonitor monitor) throws CoreException { |
| monitor.beginTask(RefactoringCoreMessages.MoveInnerToTopRefactoring_creating_change, 1); |
| final Map arguments= new HashMap(); |
| String project= null; |
| IJavaProject javaProject= fType.getJavaProject(); |
| if (javaProject != null) |
| project= javaProject.getElementName(); |
| final String description= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_descriptor_description_short, fType.getElementName()); |
| final String header= Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_descriptor_description, new String[] { JavaElementLabels.getElementLabel(fType, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fType.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED)}); |
| final JavaRefactoringDescriptorComment comment= new JavaRefactoringDescriptorComment(this, header); |
| comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_original_pattern, JavaElementLabels.getElementLabel(fType, JavaElementLabels.ALL_FULLY_QUALIFIED))); |
| final boolean enclosing= fEnclosingInstanceFieldName != null && !"".equals(fEnclosingInstanceFieldName); //$NON-NLS-1$ |
| if (enclosing) |
| comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_field_pattern, fEnclosingInstanceFieldName)); |
| if (fNameForEnclosingInstanceConstructorParameter != null && !"".equals(fNameForEnclosingInstanceConstructorParameter)) //$NON-NLS-1$ |
| comment.addSetting(Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_parameter_pattern, fNameForEnclosingInstanceConstructorParameter)); |
| if (enclosing && fMarkInstanceFieldAsFinal) |
| comment.addSetting(RefactoringCoreMessages.MoveInnerToTopRefactoring_declare_final); |
| final JavaRefactoringDescriptor descriptor= new JavaRefactoringDescriptor(ID_MOVE_INNER, project, description, comment.asString(), arguments, RefactoringDescriptor.MULTI_CHANGE | RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORABLE | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT); |
| arguments.put(JavaRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fType)); |
| if (enclosing) |
| arguments.put(ATTRIBUTE_FIELD_NAME, fEnclosingInstanceFieldName); |
| if (fNameForEnclosingInstanceConstructorParameter != null && !"".equals(fNameForEnclosingInstanceConstructorParameter)) //$NON-NLS-1$ |
| arguments.put(ATTRIBUTE_PARAMETER_NAME, fNameForEnclosingInstanceConstructorParameter); |
| arguments.put(ATTRIBUTE_FIELD, Boolean.valueOf(fCreateInstanceField).toString()); |
| arguments.put(ATTRIBUTE_FINAL, Boolean.valueOf(fMarkInstanceFieldAsFinal).toString()); |
| arguments.put(ATTRIBUTE_POSSIBLE, Boolean.valueOf(fIsInstanceFieldCreationPossible).toString()); |
| arguments.put(ATTRIBUTE_MANDATORY, Boolean.valueOf(fIsInstanceFieldCreationMandatory).toString()); |
| final DynamicValidationRefactoringChange result= new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.MoveInnerToTopRefactoring_move_to_Top); |
| result.addAll(fChangeManager.getAllChanges()); |
| result.add(createCompilationUnitForMovedType(new SubProgressMonitor(monitor, 1))); |
| return result; |
| } |
| |
| private TextChangeManager createChangeManager(final IProgressMonitor monitor, final RefactoringStatus status) throws CoreException { |
| Assert.isNotNull(monitor); |
| Assert.isNotNull(status); |
| final TextChangeManager manager= new TextChangeManager(); |
| try { |
| monitor.beginTask(RefactoringCoreMessages.MoveInnerToTopRefactoring_creating_preview, 4); |
| final Map rewrites= new HashMap(2); |
| fSourceRewrite.clearASTAndImportRewrites(); |
| rewrites.put(fSourceRewrite.getCu(), fSourceRewrite); |
| final MemberVisibilityAdjustor adjustor= new MemberVisibilityAdjustor(fType.getPackageFragment(), fType); |
| adjustor.setRewrites(rewrites); |
| adjustor.setVisibilitySeverity(RefactoringStatus.WARNING); |
| adjustor.setFailureSeverity(RefactoringStatus.WARNING); |
| adjustor.setStatus(status); |
| adjustor.adjustVisibility(new SubProgressMonitor(monitor, 1)); |
| final Map parameters= new LinkedHashMap(); |
| addTypeParameters(fSourceRewrite.getRoot(), fType, parameters); |
| final ITypeBinding[] bindings= new ITypeBinding[parameters.values().size()]; |
| parameters.values().toArray(bindings); |
| final Map typeReferences= createTypeReferencesMapping(new SubProgressMonitor(monitor, 1), status); |
| Map constructorReferences= null; |
| if (JdtFlags.isStatic(fType)) |
| constructorReferences= new HashMap(0); |
| else |
| constructorReferences= createConstructorReferencesMapping(new SubProgressMonitor(monitor, 1), status); |
| if (fCreateInstanceField) { |
| // must increase visibility of all member types up |
| // to the top level type to allow this |
| IType type= fType; |
| ModifierKeyword keyword= null; |
| while ( (type= type.getDeclaringType()) != null) { |
| if ((!adjustor.getAdjustments().containsKey(type)) && (Modifier.isPrivate(type.getFlags()))) |
| adjustor.getAdjustments().put(type, new OutgoingMemberVisibilityAdjustment(type, keyword, RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_type_warning, new String[] { MemberVisibilityAdjustor.getLabel(type), MemberVisibilityAdjustor.getLabel(keyword) }), JavaStatusContext.create(type.getCompilationUnit(), type.getSourceRange())))); |
| } |
| } |
| monitor.worked(1); |
| for (final Iterator iterator= getMergedSet(typeReferences.keySet(), constructorReferences.keySet()).iterator(); iterator.hasNext();) { |
| final ICompilationUnit unit= (ICompilationUnit) iterator.next(); |
| final CompilationUnitRewrite targetRewrite= getCompilationUnitRewrite(unit); |
| createCompilationUnitRewrite(bindings, targetRewrite, typeReferences, constructorReferences, adjustor.getAdjustments().containsKey(fType), fType.getCompilationUnit(), unit, false, status, monitor); |
| if (unit.equals(fType.getCompilationUnit())) { |
| try { |
| adjustor.setStatus(new RefactoringStatus()); |
| adjustor.rewriteVisibility(targetRewrite.getCu(), new SubProgressMonitor(monitor, 1)); |
| } finally { |
| adjustor.setStatus(status); |
| } |
| fNewSourceOfInputType= createNewSource(targetRewrite, unit); |
| targetRewrite.clearASTAndImportRewrites(); |
| createCompilationUnitRewrite(bindings, targetRewrite, typeReferences, constructorReferences, adjustor.getAdjustments().containsKey(fType), fType.getCompilationUnit(), unit, true, status, monitor); |
| } |
| adjustor.rewriteVisibility(targetRewrite.getCu(), new SubProgressMonitor(monitor, 1)); |
| manager.manage(unit, targetRewrite.createChange()); |
| } |
| } finally { |
| monitor.done(); |
| } |
| return manager; |
| } |
| |
| private Change createCompilationUnitForMovedType(IProgressMonitor pm) throws CoreException { |
| ICompilationUnit newCuWC= null; |
| try { |
| newCuWC= fType.getPackageFragment().getCompilationUnit(JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())).getWorkingCopy(null); |
| String source= createSourceForNewCu(newCuWC, pm); |
| return new CreateCompilationUnitChange(fType.getPackageFragment().getCompilationUnit(JavaModelUtil.getRenamedCUName(fType.getCompilationUnit(), fType.getElementName())), source, null); |
| } finally { |
| if (newCuWC != null) |
| newCuWC.discardWorkingCopy(); |
| } |
| } |
| |
| private void createCompilationUnitRewrite(final ITypeBinding[] parameters, final CompilationUnitRewrite targetRewrite, final Map typeReferences, final Map constructorReferences, boolean visibilityWasAdjusted, final ICompilationUnit sourceUnit, final ICompilationUnit targetUnit, final boolean remove, final RefactoringStatus status, final IProgressMonitor monitor) throws CoreException { |
| Assert.isNotNull(parameters); |
| Assert.isNotNull(targetRewrite); |
| Assert.isNotNull(typeReferences); |
| Assert.isNotNull(constructorReferences); |
| Assert.isNotNull(sourceUnit); |
| Assert.isNotNull(targetUnit); |
| final CompilationUnit root= targetRewrite.getRoot(); |
| final ASTRewrite rewrite= targetRewrite.getASTRewrite(); |
| if (targetUnit.equals(sourceUnit)) { |
| final AbstractTypeDeclaration declaration= findTypeDeclaration(fType, root); |
| final TextEditGroup qualifierGroup= fSourceRewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_change_qualifier); |
| ITypeBinding binding= declaration.resolveBinding(); |
| if (!remove) { |
| if (!JdtFlags.isStatic(fType) && fCreateInstanceField) { |
| if (JavaElementUtil.getAllConstructors(fType).length == 0) |
| createConstructor(declaration, rewrite); |
| else |
| modifyConstructors(declaration, rewrite); |
| addInheritedTypeQualifications(declaration, targetRewrite, qualifierGroup); |
| addEnclosingInstanceDeclaration(declaration, rewrite); |
| } |
| fTypeImports= new HashSet(); |
| fStaticImports= new HashSet(); |
| ImportRewriteUtil.collectImports(fType.getJavaProject(), declaration, fTypeImports, fStaticImports, false); |
| if (binding != null) |
| fTypeImports.remove(binding); |
| } |
| addEnclosingInstanceTypeParameters(parameters, declaration, rewrite); |
| modifyAccessToEnclosingInstance(targetRewrite, declaration, status, monitor); |
| if (binding != null) { |
| modifyInterfaceMemberModifiers(binding); |
| final ITypeBinding declaring= binding.getDeclaringClass(); |
| if (declaring != null) |
| declaration.accept(new TypeReferenceQualifier(binding, null)); |
| } |
| final TextEditGroup groupMove= targetRewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_change_label); |
| if (remove) { |
| rewrite.remove(declaration, groupMove); |
| targetRewrite.getImportRemover().registerRemovedNode(declaration); |
| } else { |
| // Bug 101017/96308: Rewrite the visibility of the element to be |
| // moved and add a warning. |
| |
| // Note that this cannot be done in the MemberVisibilityAdjustor, as the private and |
| // static flags must always be cleared when moving to new type. |
| int newFlags= JdtFlags.clearFlag(Modifier.STATIC, declaration.getModifiers()); |
| |
| if (!visibilityWasAdjusted) { |
| if (Modifier.isPrivate(declaration.getModifiers()) || Modifier.isProtected(declaration.getModifiers())) { |
| newFlags= JdtFlags.clearFlag(Modifier.PROTECTED | Modifier.PRIVATE, newFlags); |
| final RefactoringStatusEntry entry= new RefactoringStatusEntry(RefactoringStatus.WARNING, Messages.format(RefactoringCoreMessages.MoveInnerToTopRefactoring_change_visibility_type_warning, new String[] { BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED)}), JavaStatusContext.create(fSourceRewrite.getCu())); |
| if (!containsStatusEntry(status, entry)) |
| status.addEntry(entry); |
| } |
| } |
| |
| ModifierRewrite.create(rewrite, declaration).setModifiers(newFlags, groupMove); |
| } |
| } |
| ASTNode[] references= getReferenceNodesIn(root, typeReferences, targetUnit); |
| for (int index= 0; index < references.length; index++) |
| updateTypeReference(parameters, references[index], targetRewrite, targetUnit); |
| references= getReferenceNodesIn(root, constructorReferences, targetUnit); |
| for (int index= 0; index < references.length; index++) |
| updateConstructorReference(parameters, references[index], targetRewrite, targetUnit); |
| } |
| |
| private void createConstructor(final AbstractTypeDeclaration declaration, final ASTRewrite rewrite) throws CoreException { |
| Assert.isNotNull(declaration); |
| Assert.isNotNull(rewrite); |
| final AST ast= declaration.getAST(); |
| final MethodDeclaration constructor= ast.newMethodDeclaration(); |
| constructor.setConstructor(true); |
| constructor.setName(ast.newSimpleName(declaration.getName().getIdentifier())); |
| final String comment= CodeGeneration.getMethodComment(fType.getCompilationUnit(), fType.getElementName(), fType.getElementName(), getNewConstructorParameterNames(), new String[0], null, null, StubUtility.getLineDelimiterUsed(fType.getJavaProject())); |
| if (comment != null && comment.length() > 0) { |
| final Javadoc doc= (Javadoc) rewrite.createStringPlaceholder(comment, ASTNode.JAVADOC); |
| constructor.setJavadoc(doc); |
| } |
| if (fCreateInstanceField) { |
| final SingleVariableDeclaration variable= ast.newSingleVariableDeclaration(); |
| final String name= getNameForEnclosingInstanceConstructorParameter(); |
| variable.setName(ast.newSimpleName(name)); |
| variable.setType(createEnclosingType(ast)); |
| constructor.parameters().add(variable); |
| final Block body= ast.newBlock(); |
| final Assignment assignment= ast.newAssignment(); |
| if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) { |
| final FieldAccess access= ast.newFieldAccess(); |
| access.setExpression(ast.newThisExpression()); |
| access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); |
| assignment.setLeftHandSide(access); |
| } else |
| assignment.setLeftHandSide(ast.newSimpleName(fEnclosingInstanceFieldName)); |
| assignment.setRightHandSide(ast.newSimpleName(name)); |
| final Statement statement= ast.newExpressionStatement(assignment); |
| body.statements().add(statement); |
| constructor.setBody(body); |
| } else |
| constructor.setBody(ast.newBlock()); |
| rewrite.getListRewrite(declaration, declaration.getBodyDeclarationsProperty()).insertFirst(constructor, null); |
| } |
| |
| // Map<ICompilationUnit, SearchMatch[]> |
| private Map createConstructorReferencesMapping(IProgressMonitor pm, RefactoringStatus status) throws JavaModelException { |
| SearchResultGroup[] groups= ConstructorReferenceFinder.getConstructorReferences(fType, pm, status); |
| Map result= new HashMap(); |
| for (int i= 0; i < groups.length; i++) { |
| SearchResultGroup group= groups[i]; |
| ICompilationUnit cu= group.getCompilationUnit(); |
| if (cu == null) |
| continue; |
| result.put(cu, group.getSearchResults()); |
| } |
| return result; |
| } |
| |
| private Expression createEnclosingInstanceCreationString(final ASTNode node, final ICompilationUnit cu) throws JavaModelException { |
| Assert.isTrue((node instanceof ClassInstanceCreation) || (node instanceof SuperConstructorInvocation)); |
| Assert.isNotNull(cu); |
| Expression expression= null; |
| if (node instanceof ClassInstanceCreation) |
| expression= ((ClassInstanceCreation) node).getExpression(); |
| else |
| expression= ((SuperConstructorInvocation) node).getExpression(); |
| final AST ast= node.getAST(); |
| if (expression != null) |
| return expression; |
| else if (JdtFlags.isStatic(fType)) |
| return null; |
| else if (isInsideSubclassOfDeclaringType(node)) |
| return ast.newThisExpression(); |
| else if ((node.getStartPosition() >= fType.getSourceRange().getOffset() && ASTNodes.getExclusiveEnd(node) <= fType.getSourceRange().getOffset() + fType.getSourceRange().getLength())) { |
| if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) { |
| final FieldAccess access= ast.newFieldAccess(); |
| access.setExpression(ast.newThisExpression()); |
| access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); |
| return access; |
| } else |
| return ast.newSimpleName(fEnclosingInstanceFieldName); |
| } else if (isInsideTypeNestedInDeclaringType(node)) { |
| final ThisExpression qualified= ast.newThisExpression(); |
| qualified.setQualifier(ast.newSimpleName(fType.getDeclaringType().getElementName())); |
| return qualified; |
| } |
| return null; |
| } |
| |
| private Type createEnclosingType(final AST ast) throws JavaModelException { |
| Assert.isNotNull(ast); |
| final ITypeParameter[] parameters= fType.getDeclaringType().getTypeParameters(); |
| final Type type= ASTNodeFactory.newType(ast, JavaModelUtil.getTypeQualifiedName(fType.getDeclaringType())); |
| if (parameters.length > 0) { |
| final ParameterizedType parameterized= ast.newParameterizedType(type); |
| for (int index= 0; index < parameters.length; index++) |
| parameterized.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getElementName()))); |
| return parameterized; |
| } |
| return type; |
| } |
| |
| private String createNewSource(final CompilationUnitRewrite targetRewrite, final ICompilationUnit unit) throws CoreException, JavaModelException { |
| Assert.isNotNull(targetRewrite); |
| Assert.isNotNull(unit); |
| TextChange change= targetRewrite.createChange(); |
| if (change == null) |
| change= new CompilationUnitChange("", unit); //$NON-NLS-1$ |
| final String source= change.getPreviewContent(new NullProgressMonitor()); |
| final ASTParser parser= ASTParser.newParser(AST.JLS3); |
| parser.setProject(fType.getJavaProject()); |
| parser.setResolveBindings(false); |
| parser.setSource(source.toCharArray()); |
| final AbstractTypeDeclaration declaration= findTypeDeclaration(fType, (CompilationUnit) parser.createAST(null)); |
| return source.substring(declaration.getStartPosition(), ASTNodes.getExclusiveEnd(declaration)); |
| } |
| |
| private Expression createQualifiedReadAccessExpressionForEnclosingInstance(AST ast) { |
| ThisExpression expression= ast.newThisExpression(); |
| expression.setQualifier(ast.newName(new String[] { fType.getElementName()})); |
| FieldAccess access= ast.newFieldAccess(); |
| access.setExpression(expression); |
| access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); |
| return access; |
| } |
| |
| private Expression createReadAccessExpressionForEnclosingInstance(AST ast) { |
| if (fCodeGenerationSettings.useKeywordThis || fEnclosingInstanceFieldName.equals(fNameForEnclosingInstanceConstructorParameter)) { |
| final FieldAccess access= ast.newFieldAccess(); |
| access.setExpression(ast.newThisExpression()); |
| access.setName(ast.newSimpleName(fEnclosingInstanceFieldName)); |
| return access; |
| } |
| return ast.newSimpleName(fEnclosingInstanceFieldName); |
| } |
| |
| private String createSourceForNewCu(final ICompilationUnit unit, final IProgressMonitor monitor) throws CoreException { |
| Assert.isNotNull(unit); |
| Assert.isNotNull(monitor); |
| try { |
| monitor.beginTask("", 2); //$NON-NLS-1$ |
| final String separator= StubUtility.getLineDelimiterUsed(fType.getJavaProject()); |
| final String block= getAlignedSourceBlock(unit, fNewSourceOfInputType); |
| String content= CodeGeneration.getCompilationUnitContent(unit, null, block, separator); |
| if (content == null || block.startsWith("/*") || block.startsWith("//")) { //$NON-NLS-1$//$NON-NLS-2$ |
| final StringBuffer buffer= new StringBuffer(); |
| if (!fType.getPackageFragment().isDefaultPackage()) { |
| buffer.append("package ").append(fType.getPackageFragment().getElementName()).append(';'); //$NON-NLS-1$ |
| } |
| buffer.append(separator).append(separator); |
| buffer.append(block); |
| content= buffer.toString(); |
| } |
| unit.getBuffer().setContents(content); |
| addImportsToTargetUnit(unit, new SubProgressMonitor(monitor, 1)); |
| } finally { |
| monitor.done(); |
| } |
| return unit.getSource(); |
| } |
| |
| // Map<ICompilationUnit, SearchMatch[]> |
| private Map createTypeReferencesMapping(IProgressMonitor pm, RefactoringStatus status) throws JavaModelException { |
| final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(SearchPattern.createPattern(fType, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE)); |
| engine.setFiltering(true, true); |
| engine.setScope(RefactoringScopeFactory.create(fType)); |
| engine.setStatus(status); |
| engine.searchPattern(new SubProgressMonitor(pm, 1)); |
| final SearchResultGroup[] groups= (SearchResultGroup[]) engine.getResults(); |
| Map result= new HashMap(); |
| for (int i= 0; i < groups.length; i++) { |
| SearchResultGroup group= groups[i]; |
| ICompilationUnit cu= group.getCompilationUnit(); |
| if (cu == null) |
| continue; |
| result.put(cu, group.getSearchResults()); |
| } |
| return result; |
| } |
| |
| private String getAlignedSourceBlock(final ICompilationUnit unit, final String block) { |
| Assert.isNotNull(block); |
| final String[] lines= Strings.convertIntoLines(block); |
| Strings.trimIndentation(lines, unit.getJavaProject(), false); |
| return Strings.concatenate(lines, StubUtility.getLineDelimiterUsed(fType.getJavaProject())); |
| } |
| |
| private CompilationUnitRewrite getCompilationUnitRewrite(final ICompilationUnit unit) { |
| Assert.isNotNull(unit); |
| if (unit.equals(fType.getCompilationUnit())) |
| return fSourceRewrite; |
| return new CompilationUnitRewrite(unit); |
| } |
| |
| private MethodDeclaration[] getConstructorDeclarationNodes(final AbstractTypeDeclaration declaration) { |
| if (declaration instanceof TypeDeclaration) { |
| final MethodDeclaration[] declarations= ((TypeDeclaration) declaration).getMethods(); |
| final List result= new ArrayList(2); |
| for (int index= 0; index < declarations.length; index++) { |
| if (declarations[index].isConstructor()) |
| result.add(declarations[index]); |
| } |
| return (MethodDeclaration[]) result.toArray(new MethodDeclaration[result.size()]); |
| } |
| return new MethodDeclaration[] {}; |
| } |
| |
| public boolean getCreateInstanceField() { |
| return fCreateInstanceField; |
| } |
| |
| private int getEnclosingInstanceAccessModifiers() { |
| if (fMarkInstanceFieldAsFinal) |
| return Modifier.PRIVATE | Modifier.FINAL; |
| else |
| return Modifier.PRIVATE; |
| } |
| |
| public String getEnclosingInstanceName() { |
| return fEnclosingInstanceFieldName; |
| } |
| |
| private String getInitialNameForEnclosingInstanceField() { |
| IType enclosingType= fType.getDeclaringType(); |
| if (enclosingType == null) |
| return ""; //$NON-NLS-1$ |
| String[] suggestedNames= NamingConventions.suggestFieldNames(enclosingType.getJavaProject(), enclosingType.getPackageFragment().getElementName(), JavaModelUtil.getTypeQualifiedName(fType.getDeclaringType()), 0, getEnclosingInstanceAccessModifiers(), getFieldNames(fType)); |
| if (suggestedNames.length > 0) |
| return suggestedNames[0]; |
| String name= enclosingType.getElementName(); |
| if (name.equals("")) //$NON-NLS-1$ |
| return ""; //$NON-NLS-1$ |
| return Character.toLowerCase(name.charAt(0)) + name.substring(1); |
| } |
| |
| public IType getInputType() { |
| return fType; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring#getName() |
| */ |
| public String getName() { |
| return RefactoringCoreMessages.MoveInnerToTopRefactoring_name; |
| } |
| |
| private String getNameForEnclosingInstanceConstructorParameter() throws JavaModelException { |
| if (fNameForEnclosingInstanceConstructorParameter != null) |
| return fNameForEnclosingInstanceConstructorParameter; |
| |
| IType enclosingType= fType.getDeclaringType(); |
| String[] suggestedNames= NamingConventions.suggestArgumentNames(enclosingType.getJavaProject(), enclosingType.getPackageFragment().getElementName(), JavaModelUtil.getTypeQualifiedName(fType.getDeclaringType()), 0, getParameterNamesOfAllConstructors(fType)); |
| if (suggestedNames.length > 0) |
| fNameForEnclosingInstanceConstructorParameter= suggestedNames[0]; |
| else |
| fNameForEnclosingInstanceConstructorParameter= fEnclosingInstanceFieldName; |
| return fNameForEnclosingInstanceConstructorParameter; |
| } |
| |
| private String[] getNewConstructorParameterNames() throws JavaModelException { |
| if (!fCreateInstanceField) |
| return new String[0]; |
| return new String[] { getNameForEnclosingInstanceConstructorParameter()}; |
| } |
| |
| private ASTNode getNewQualifiedNameNode(ITypeBinding[] parameters, Name name) { |
| final AST ast= name.getAST(); |
| boolean raw= false; |
| final ITypeBinding binding= name.resolveTypeBinding(); |
| if (binding != null && binding.isRawType()) |
| raw= true; |
| if (parameters != null && parameters.length > 0 && !raw) { |
| final ParameterizedType type= ast.newParameterizedType(ast.newSimpleType(ast.newName(fQualifiedTypeName))); |
| for (int index= 0; index < parameters.length; index++) |
| type.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getName()))); |
| return type; |
| } |
| return ast.newName(fQualifiedTypeName); |
| } |
| |
| private ASTNode getNewUnqualifiedTypeNode(ITypeBinding[] parameters, Name name) { |
| final AST ast= name.getAST(); |
| boolean raw= false; |
| final ITypeBinding binding= name.resolveTypeBinding(); |
| if (binding != null && binding.isRawType()) |
| raw= true; |
| if (parameters != null && parameters.length > 0 && !raw) { |
| final ParameterizedType type= ast.newParameterizedType(ast.newSimpleType(ast.newSimpleName(fType.getElementName()))); |
| for (int index= 0; index < parameters.length; index++) |
| type.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getName()))); |
| return type; |
| } |
| return ast.newSimpleType(ast.newSimpleName(fType.getElementName())); |
| } |
| |
| private boolean insertExpressionAsParameter(ClassInstanceCreation cic, ASTRewrite rewrite, ICompilationUnit cu, TextEditGroup group) throws JavaModelException { |
| final Expression expression= createEnclosingInstanceCreationString(cic, cu); |
| if (expression == null) |
| return false; |
| rewrite.getListRewrite(cic, ClassInstanceCreation.ARGUMENTS_PROPERTY).insertFirst(expression, group); |
| return true; |
| } |
| |
| private boolean insertExpressionAsParameter(SuperConstructorInvocation sci, ASTRewrite rewrite, ICompilationUnit cu, TextEditGroup group) throws JavaModelException { |
| final Expression expression= createEnclosingInstanceCreationString(sci, cu); |
| if (expression == null) |
| return false; |
| rewrite.getListRewrite(sci, SuperConstructorInvocation.ARGUMENTS_PROPERTY).insertFirst(expression, group); |
| return true; |
| } |
| |
| public boolean isCreatingInstanceFieldMandatory() { |
| return fIsInstanceFieldCreationMandatory; |
| } |
| |
| public boolean isCreatingInstanceFieldPossible() { |
| return fIsInstanceFieldCreationPossible; |
| } |
| |
| private boolean isInAnonymousTypeInsideInputType(ASTNode node, AbstractTypeDeclaration declaration) { |
| final AnonymousClassDeclaration anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(node, AnonymousClassDeclaration.class); |
| return anonymous != null && ASTNodes.isParent(anonymous, declaration); |
| } |
| |
| private boolean isInLocalTypeInsideInputType(ASTNode node, AbstractTypeDeclaration declaration) { |
| final TypeDeclarationStatement statement= (TypeDeclarationStatement) ASTNodes.getParent(node, TypeDeclarationStatement.class); |
| return statement != null && ASTNodes.isParent(statement, declaration); |
| } |
| |
| private boolean isInNonStaticMemberTypeInsideInputType(ASTNode node, AbstractTypeDeclaration declaration) { |
| final AbstractTypeDeclaration nested= (AbstractTypeDeclaration) ASTNodes.getParent(node, AbstractTypeDeclaration.class); |
| return nested != null && !declaration.equals(nested) && !Modifier.isStatic(nested.getFlags()) && ASTNodes.isParent(nested, declaration); |
| } |
| |
| private boolean isInsideSubclassOfDeclaringType(ASTNode node) { |
| Assert.isTrue((node instanceof ClassInstanceCreation) || (node instanceof SuperConstructorInvocation)); |
| final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(node, AbstractTypeDeclaration.class); |
| Assert.isNotNull(declaration); |
| |
| final AnonymousClassDeclaration anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(node, AnonymousClassDeclaration.class); |
| boolean isAnonymous= anonymous != null && ASTNodes.isParent(anonymous, declaration); |
| if (isAnonymous) |
| return anonymous != null && isSubclassBindingOfEnclosingType(anonymous.resolveBinding()); |
| return isSubclassBindingOfEnclosingType(declaration.resolveBinding()); |
| } |
| |
| private boolean isInsideTypeNestedInDeclaringType(ASTNode node) { |
| Assert.isTrue((node instanceof ClassInstanceCreation) || (node instanceof SuperConstructorInvocation)); |
| final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(node, AbstractTypeDeclaration.class); |
| Assert.isNotNull(declaration); |
| ITypeBinding enclosing= declaration.resolveBinding(); |
| while (enclosing != null) { |
| if (isCorrespondingTypeBinding(enclosing, fType.getDeclaringType())) |
| return true; |
| enclosing= enclosing.getDeclaringClass(); |
| } |
| return false; |
| } |
| |
| private boolean isInstanceFieldCreationMandatory() throws JavaModelException { |
| final MemberAccessNodeCollector collector= new MemberAccessNodeCollector(fType.getDeclaringType().newSupertypeHierarchy(new NullProgressMonitor())); |
| findTypeDeclaration(fType, fSourceRewrite.getRoot()).accept(collector); |
| return containsNonStatic(collector.getFieldAccesses()) || containsNonStatic(collector.getMethodInvocations()) || containsNonStatic(collector.getSimpleFieldNames()); |
| } |
| |
| public boolean isInstanceFieldMarkedFinal() { |
| return fMarkInstanceFieldAsFinal; |
| } |
| |
| private boolean isSubclassBindingOfEnclosingType(ITypeBinding binding) { |
| while (binding != null) { |
| if (isCorrespondingTypeBinding(binding, fType.getDeclaringType())) |
| return true; |
| binding= binding.getSuperclass(); |
| } |
| return false; |
| } |
| |
| /* |
| * This method qualifies accesses from within the moved type to the (now former) enclosed |
| * type of the moved type. Note that all visibility changes have already been scheduled |
| * in the visibility adjustor. |
| */ |
| private void modifyAccessToEnclosingInstance(final CompilationUnitRewrite targetRewrite, final AbstractTypeDeclaration declaration, final RefactoringStatus status, final IProgressMonitor monitor) throws JavaModelException { |
| Assert.isNotNull(targetRewrite); |
| Assert.isNotNull(declaration); |
| Assert.isNotNull(monitor); |
| final Set handledMethods= new HashSet(); |
| final Set handledFields= new HashSet(); |
| final MemberAccessNodeCollector collector= new MemberAccessNodeCollector(fType.getDeclaringType().newSupertypeHierarchy(new SubProgressMonitor(monitor, 1))); |
| declaration.accept(collector); |
| modifyAccessToMethodsFromEnclosingInstance(targetRewrite, handledMethods, collector.getMethodInvocations(), declaration, status); |
| modifyAccessToFieldsFromEnclosingInstance(targetRewrite, handledFields, collector.getFieldAccesses(), declaration, status); |
| modifyAccessToFieldsFromEnclosingInstance(targetRewrite, handledFields, collector.getSimpleFieldNames(), declaration, status); |
| } |
| |
| private void modifyAccessToFieldsFromEnclosingInstance(CompilationUnitRewrite targetRewrite, Set handledFields, FieldAccess[] fieldAccesses, AbstractTypeDeclaration declaration, RefactoringStatus status) { |
| FieldAccess access= null; |
| for (int index= 0; index < fieldAccesses.length; index++) { |
| access= fieldAccesses[index]; |
| Assert.isNotNull(access.getExpression()); |
| if (!(access.getExpression() instanceof ThisExpression) || (!(((ThisExpression) access.getExpression()).getQualifier() != null))) |
| continue; |
| |
| final IVariableBinding binding= access.resolveFieldBinding(); |
| if (binding != null) { |
| targetRewrite.getASTRewrite().replace(access.getExpression(), createAccessExpressionToEnclosingInstanceFieldText(access, binding, declaration), null); |
| targetRewrite.getImportRemover().registerRemovedNode(access.getExpression()); |
| } |
| } |
| } |
| |
| private void modifyAccessToFieldsFromEnclosingInstance(CompilationUnitRewrite targetRewrite, Set handledFields, SimpleName[] simpleNames, AbstractTypeDeclaration declaration, RefactoringStatus status) { |
| IBinding binding= null; |
| SimpleName simpleName= null; |
| IVariableBinding variable= null; |
| for (int index= 0; index < simpleNames.length; index++) { |
| simpleName= simpleNames[index]; |
| binding= simpleName.resolveBinding(); |
| if (binding != null && binding instanceof IVariableBinding && !(simpleName.getParent() instanceof FieldAccess)) { |
| variable= (IVariableBinding) binding; |
| final FieldAccess access= simpleName.getAST().newFieldAccess(); |
| access.setExpression(createAccessExpressionToEnclosingInstanceFieldText(simpleName, variable, declaration)); |
| access.setName(simpleName.getAST().newSimpleName(simpleName.getIdentifier())); |
| targetRewrite.getASTRewrite().replace(simpleName, access, null); |
| targetRewrite.getImportRemover().registerRemovedNode(simpleName); |
| } |
| } |
| } |
| |
| private void modifyAccessToMethodsFromEnclosingInstance(CompilationUnitRewrite targetRewrite, Set handledMethods, MethodInvocation[] methodInvocations, AbstractTypeDeclaration declaration, RefactoringStatus status) { |
| IMethodBinding binding= null; |
| MethodInvocation invocation= null; |
| for (int index= 0; index < methodInvocations.length; index++) { |
| invocation= methodInvocations[index]; |
| binding= invocation.resolveMethodBinding(); |
| if (binding != null) { |
| final Expression target= invocation.getExpression(); |
| if (target == null) { |
| final Expression expression= createAccessExpressionToEnclosingInstanceFieldText(invocation, binding, declaration); |
| targetRewrite.getASTRewrite().set(invocation, MethodInvocation.EXPRESSION_PROPERTY, expression, null); |
| } else { |
| if (!(invocation.getExpression() instanceof ThisExpression) || !(((ThisExpression) invocation.getExpression()).getQualifier() != null)) |
| continue; |
| targetRewrite.getASTRewrite().replace(target, createAccessExpressionToEnclosingInstanceFieldText(invocation, binding, declaration), null); |
| targetRewrite.getImportRemover().registerRemovedNode(target); |
| } |
| } |
| } |
| } |
| |
| private void modifyConstructors(AbstractTypeDeclaration declaration, ASTRewrite rewrite) throws CoreException { |
| final MethodDeclaration[] declarations= getConstructorDeclarationNodes(declaration); |
| for (int index= 0; index < declarations.length; index++) { |
| Assert.isTrue(declarations[index].isConstructor()); |
| addParameterToConstructor(rewrite, declarations[index]); |
| setEnclosingInstanceFieldInConstructor(rewrite, declarations[index]); |
| } |
| } |
| |
| private void modifyInterfaceMemberModifiers(final ITypeBinding binding) { |
| Assert.isNotNull(binding); |
| ITypeBinding declaring= binding.getDeclaringClass(); |
| while (declaring != null && !declaring.isInterface()) { |
| declaring= declaring.getDeclaringClass(); |
| } |
| if (declaring != null) { |
| final ASTNode node= ASTNodes.findDeclaration(binding, fSourceRewrite.getRoot()); |
| if (node instanceof AbstractTypeDeclaration) { |
| ModifierRewrite.create(fSourceRewrite.getASTRewrite(), node).setVisibility(Modifier.PUBLIC, null); |
| } |
| } |
| } |
| |
| public void setCreateInstanceField(boolean create) { |
| Assert.isTrue(fIsInstanceFieldCreationPossible); |
| Assert.isTrue(!fIsInstanceFieldCreationMandatory); |
| fCreateInstanceField= create; |
| } |
| |
| private void setEnclosingInstanceFieldInConstructor(ASTRewrite rewrite, MethodDeclaration decl) throws JavaModelException { |
| final AST ast= decl.getAST(); |
| final Block body= decl.getBody(); |
| final List statements= body.statements(); |
| if (statements.isEmpty()) { |
| final Assignment assignment= ast.newAssignment(); |
| assignment.setLeftHandSide(createReadAccessExpressionForEnclosingInstance(ast)); |
| assignment.setRightHandSide(ast.newSimpleName(getNameForEnclosingInstanceConstructorParameter())); |
| rewrite.getListRewrite(body, Block.STATEMENTS_PROPERTY).insertFirst(ast.newExpressionStatement(assignment), null); |
| } else { |
| final Statement first= (Statement) statements.get(0); |
| if (first instanceof ConstructorInvocation) { |
| rewrite.getListRewrite(first, ConstructorInvocation.ARGUMENTS_PROPERTY).insertFirst(ast.newSimpleName(fEnclosingInstanceFieldName), null); |
| } else { |
| int index= 0; |
| if (first instanceof SuperConstructorInvocation) |
| index++; |
| final Assignment assignment= ast.newAssignment(); |
| assignment.setLeftHandSide(createReadAccessExpressionForEnclosingInstance(ast)); |
| assignment.setRightHandSide(ast.newSimpleName(getNameForEnclosingInstanceConstructorParameter())); |
| rewrite.getListRewrite(body, Block.STATEMENTS_PROPERTY).insertAt(ast.newExpressionStatement(assignment), index, null); |
| } |
| } |
| } |
| |
| public void setEnclosingInstanceName(String name) { |
| Assert.isNotNull(name); |
| fEnclosingInstanceFieldName= name; |
| } |
| |
| public void setMarkInstanceFieldAsFinal(boolean mark) { |
| fMarkInstanceFieldAsFinal= mark; |
| } |
| |
| private void updateConstructorReference(final ClassInstanceCreation creation, final CompilationUnitRewrite targetRewrite, final ICompilationUnit unit, TextEditGroup group) throws JavaModelException { |
| Assert.isNotNull(creation); |
| Assert.isNotNull(targetRewrite); |
| Assert.isNotNull(unit); |
| final ASTRewrite rewrite= targetRewrite.getASTRewrite(); |
| if (fCreateInstanceField) |
| insertExpressionAsParameter(creation, rewrite, unit, group); |
| final Expression expression= creation.getExpression(); |
| if (expression != null) { |
| rewrite.remove(expression, null); |
| targetRewrite.getImportRemover().registerRemovedNode(expression); |
| } |
| } |
| |
| private void updateConstructorReference(ITypeBinding[] parameters, ASTNode reference, CompilationUnitRewrite targetRewrite, ICompilationUnit cu) throws CoreException { |
| final TextEditGroup group= targetRewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_update_constructor_reference); |
| if (reference instanceof SuperConstructorInvocation) |
| updateConstructorReference((SuperConstructorInvocation) reference, targetRewrite, cu, group); |
| else if (reference instanceof ClassInstanceCreation) |
| updateConstructorReference((ClassInstanceCreation) reference, targetRewrite, cu, group); |
| else if (reference.getParent() instanceof ClassInstanceCreation) |
| updateConstructorReference((ClassInstanceCreation) reference.getParent(), targetRewrite, cu, group); |
| else if (reference.getParent() instanceof ParameterizedType && reference.getParent().getParent() instanceof ClassInstanceCreation) |
| updateConstructorReference(parameters, (ParameterizedType) reference.getParent(), targetRewrite, cu, group); |
| } |
| |
| private void updateConstructorReference(ITypeBinding[] parameters, ParameterizedType type, CompilationUnitRewrite targetRewrite, ICompilationUnit cu, TextEditGroup group) throws CoreException { |
| final ListRewrite rewrite= targetRewrite.getASTRewrite().getListRewrite(type, ParameterizedType.TYPE_ARGUMENTS_PROPERTY); |
| TypeParameter parameter= null; |
| for (int index= type.typeArguments().size(); index < parameters.length; index++) { |
| parameter= targetRewrite.getRoot().getAST().newTypeParameter(); |
| parameter.setName(targetRewrite.getRoot().getAST().newSimpleName(parameters[index].getName())); |
| rewrite.insertLast(parameter, group); |
| } |
| if (type.getParent() instanceof ClassInstanceCreation) |
| updateConstructorReference((ClassInstanceCreation) type.getParent(), targetRewrite, cu, group); |
| } |
| |
| private void updateConstructorReference(final SuperConstructorInvocation invocation, final CompilationUnitRewrite targetRewrite, final ICompilationUnit unit, TextEditGroup group) throws CoreException { |
| Assert.isNotNull(invocation); |
| Assert.isNotNull(targetRewrite); |
| Assert.isNotNull(unit); |
| final ASTRewrite rewrite= targetRewrite.getASTRewrite(); |
| if (fCreateInstanceField) |
| insertExpressionAsParameter(invocation, rewrite, unit, group); |
| final Expression expression= invocation.getExpression(); |
| if (expression != null) { |
| rewrite.remove(expression, null); |
| targetRewrite.getImportRemover().registerRemovedNode(expression); |
| } |
| } |
| |
| private boolean updateNameReference(ITypeBinding[] parameters, Name name, CompilationUnitRewrite targetRewrite, TextEditGroup group) { |
| if (ASTNodes.asString(name).equals(fType.getFullyQualifiedName('.'))) { |
| targetRewrite.getASTRewrite().replace(name, getNewQualifiedNameNode(parameters, name), group); |
| targetRewrite.getImportRemover().registerRemovedNode(name); |
| return true; |
| } |
| targetRewrite.getASTRewrite().replace(name, getNewUnqualifiedTypeNode(parameters, name), group); |
| targetRewrite.getImportRemover().registerRemovedNode(name); |
| return true; |
| } |
| |
| private boolean updateParameterizedTypeReference(ITypeBinding[] parameters, ParameterizedType type, CompilationUnitRewrite targetRewrite, TextEditGroup group) { |
| if (!(type.getParent() instanceof ClassInstanceCreation)) { |
| final ListRewrite rewrite= targetRewrite.getASTRewrite().getListRewrite(type, ParameterizedType.TYPE_ARGUMENTS_PROPERTY); |
| final AST ast= targetRewrite.getRoot().getAST(); |
| Type simpleType= null; |
| for (int index= type.typeArguments().size(); index < parameters.length; index++) { |
| simpleType= ast.newSimpleType(ast.newSimpleName(parameters[index].getName())); |
| rewrite.insertLast(simpleType, group); |
| } |
| } |
| return true; |
| } |
| |
| private boolean updateReference(ITypeBinding[] parameters, ASTNode node, CompilationUnitRewrite rewrite, TextEditGroup group) { |
| if (node.getLocationInParent() == ParameterizedType.TYPE_PROPERTY) { |
| updateParameterizedTypeReference(parameters, (ParameterizedType) node.getParent(), rewrite, group); |
| return updateNameReference(new ITypeBinding[] {}, ((SimpleType) node).getName(), rewrite, group); |
| } else if (node instanceof QualifiedName) |
| return updateNameReference(parameters, (QualifiedName) node, rewrite, group); |
| else if (node instanceof SimpleType) |
| return updateNameReference(parameters, ((SimpleType) node).getName(), rewrite, group); |
| else |
| return false; |
| } |
| |
| private void updateReferenceInImport(ImportDeclaration enclosingImport, ASTNode node, CompilationUnitRewrite rewrite) throws CoreException { |
| final IBinding binding= enclosingImport.resolveBinding(); |
| if (binding instanceof ITypeBinding) { |
| final ITypeBinding type= (ITypeBinding) binding; |
| final ImportRewrite rewriter= rewrite.getImportRewrite(); |
| if (enclosingImport.isStatic()) { |
| final String oldImport= ASTNodes.asString(node); |
| final StringBuffer buffer= new StringBuffer(oldImport); |
| final String typeName= fType.getDeclaringType().getElementName(); |
| final int index= buffer.indexOf(typeName); |
| if (index >= 0) { |
| buffer.delete(index, index + typeName.length() + 1); |
| final String newImport= buffer.toString(); |
| if (enclosingImport.isOnDemand()) { |
| rewriter.removeStaticImport(oldImport + ".*"); //$NON-NLS-1$ |
| rewriter.addStaticImport(newImport, "*", false); //$NON-NLS-1$ |
| } else { |
| rewriter.removeStaticImport(oldImport); |
| final int offset= newImport.lastIndexOf('.'); |
| if (offset >= 0 && offset < newImport.length() - 1) { |
| rewriter.addStaticImport(newImport.substring(0, offset), newImport.substring(offset + 1), false); |
| } |
| } |
| } |
| } else |
| rewriter.removeImport(type.getQualifiedName()); |
| } |
| } |
| |
| private void updateTypeReference(ITypeBinding[] parameters, ASTNode node, CompilationUnitRewrite rewrite, ICompilationUnit cu) throws CoreException { |
| ImportDeclaration enclosingImport= (ImportDeclaration) ASTNodes.getParent(node, ImportDeclaration.class); |
| if (enclosingImport != null) |
| updateReferenceInImport(enclosingImport, node, rewrite); |
| else { |
| final TextEditGroup group= rewrite.createGroupDescription(RefactoringCoreMessages.MoveInnerToTopRefactoring_update_type_reference); |
| updateReference(parameters, node, rewrite, group); |
| if (!fType.getPackageFragment().equals(cu.getParent())) { |
| final String name= fType.getPackageFragment().getElementName() + '.' + fType.getElementName(); |
| rewrite.getImportRemover().registerAddedImport(name); |
| rewrite.getImportRewrite().addImport(name); |
| } |
| } |
| } |
| |
| public RefactoringStatus initialize(final RefactoringArguments arguments) { |
| if (arguments instanceof JavaRefactoringArguments) { |
| final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments; |
| final String handle= extended.getAttribute(JavaRefactoringDescriptor.ATTRIBUTE_INPUT); |
| if (handle != null) { |
| final IJavaElement element= JavaRefactoringDescriptor.handleToElement(extended.getProject(), handle, false); |
| if (element == null || !element.exists() || element.getElementType() != IJavaElement.TYPE) |
| return createInputFatalStatus(element, ID_MOVE_INNER); |
| else { |
| fType= (IType) element; |
| fCodeGenerationSettings= JavaPreferencesSettings.getCodeGenerationSettings(fType.getJavaProject()); |
| try { |
| initialize(); |
| } catch (JavaModelException exception) { |
| JavaPlugin.log(exception); |
| } |
| } |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptor.ATTRIBUTE_INPUT)); |
| final String fieldName= extended.getAttribute(ATTRIBUTE_FIELD_NAME); |
| if (fieldName != null && !"".equals(fieldName)) //$NON-NLS-1$ |
| fEnclosingInstanceFieldName= fieldName; |
| final String parameterName= extended.getAttribute(ATTRIBUTE_PARAMETER_NAME); |
| if (parameterName != null && !"".equals(parameterName)) //$NON-NLS-1$ |
| fNameForEnclosingInstanceConstructorParameter= parameterName; |
| final String createField= extended.getAttribute(ATTRIBUTE_FIELD); |
| if (createField != null) { |
| fCreateInstanceField= Boolean.valueOf(createField).booleanValue(); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FIELD)); |
| final String markFinal= extended.getAttribute(ATTRIBUTE_FINAL); |
| if (markFinal != null) { |
| fMarkInstanceFieldAsFinal= Boolean.valueOf(markFinal).booleanValue(); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FINAL)); |
| final String possible= extended.getAttribute(ATTRIBUTE_POSSIBLE); |
| if (possible != null) { |
| fIsInstanceFieldCreationPossible= Boolean.valueOf(possible).booleanValue(); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_POSSIBLE)); |
| final String mandatory= extended.getAttribute(ATTRIBUTE_MANDATORY); |
| if (mandatory != null) |
| fIsInstanceFieldCreationMandatory= Boolean.valueOf(mandatory).booleanValue(); |
| else |
| return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_MANDATORY)); |
| } else |
| return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments); |
| return new RefactoringStatus(); |
| } |
| } |