1 /******************************************************************************* 2 * Copyright (c) 2000, 2019 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Microsoft Corporation - copied to jdt.core.manipulation 14 *******************************************************************************/ 15 package org.eclipse.jdt.internal.corext.refactoring.structure; 16 17 import java.util.HashSet; 18 import java.util.Set; 19 20 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 21 22 import org.eclipse.jdt.core.dom.AST; 23 import org.eclipse.jdt.core.dom.ASTNode; 24 import org.eclipse.jdt.core.dom.ASTVisitor; 25 import org.eclipse.jdt.core.dom.Expression; 26 import org.eclipse.jdt.core.dom.FieldAccess; 27 import org.eclipse.jdt.core.dom.IBinding; 28 import org.eclipse.jdt.core.dom.IPackageBinding; 29 import org.eclipse.jdt.core.dom.ITypeBinding; 30 import org.eclipse.jdt.core.dom.MemberRef; 31 import org.eclipse.jdt.core.dom.MethodInvocation; 32 import org.eclipse.jdt.core.dom.MethodRef; 33 import org.eclipse.jdt.core.dom.Name; 34 import org.eclipse.jdt.core.dom.QualifiedName; 35 import org.eclipse.jdt.core.dom.SimpleName; 36 import org.eclipse.jdt.core.dom.Type; 37 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; 38 39 import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext; 40 import org.eclipse.jdt.internal.corext.dom.ASTFlattener; 41 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; 42 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 43 import org.eclipse.jdt.internal.corext.dom.Bindings; 44 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 45 import org.eclipse.jdt.internal.corext.refactoring.util.JavaStatusContext; 46 47 /* package */ class MoveStaticMemberAnalyzer extends ASTVisitor { 48 49 protected RefactoringStatus fStatus; 50 51 protected ITypeBinding fSource; 52 protected ITypeBinding fTarget; 53 protected CompilationUnitRewrite fCuRewrite; 54 protected IBinding[] fMembers; 55 56 protected boolean fNeedsImport; 57 58 protected Set<SimpleName> fProcessed; 59 60 protected static final String REFERENCE_UPDATE= RefactoringCoreMessages.MoveMembersRefactoring_referenceUpdate; 61 MoveStaticMemberAnalyzer(CompilationUnitRewrite cuRewrite, IBinding[] members, ITypeBinding source, ITypeBinding target)62 public MoveStaticMemberAnalyzer(CompilationUnitRewrite cuRewrite, IBinding[] members, ITypeBinding source, ITypeBinding target) { 63 super(true); 64 fStatus= new RefactoringStatus(); 65 fCuRewrite= cuRewrite; 66 fMembers= members; 67 fSource= source; 68 fTarget= target; 69 fProcessed= new HashSet<>(); 70 } 71 getStatus()72 public RefactoringStatus getStatus() { 73 return fStatus; 74 } 75 isProcessed(ASTNode node)76 protected boolean isProcessed(ASTNode node) { 77 return fProcessed.contains(node); 78 } 79 rewrite(SimpleName node, ITypeBinding type)80 protected void rewrite(SimpleName node, ITypeBinding type) { 81 AST ast= node.getAST(); 82 ImportRewriteContext context= new ContextSensitiveImportRewriteContext(node, fCuRewrite.getImportRewrite()); 83 Type result= fCuRewrite.getImportRewrite().addImport(type, fCuRewrite.getAST(), context); 84 fCuRewrite.getImportRemover().registerAddedImport(type.getQualifiedName()); 85 Name dummy= ASTNodeFactory.newName(fCuRewrite.getAST(), ASTFlattener.asString(result)); 86 QualifiedName name= ast.newQualifiedName(dummy, ast.newSimpleName(node.getIdentifier())); 87 fCuRewrite.getASTRewrite().replace(node, name, fCuRewrite.createGroupDescription(REFERENCE_UPDATE)); 88 fCuRewrite.getImportRemover().registerRemovedNode(node); 89 fProcessed.add(node); 90 fNeedsImport= true; 91 } 92 rewrite(QualifiedName node, ITypeBinding type)93 protected void rewrite(QualifiedName node, ITypeBinding type) { 94 rewriteName(node.getQualifier(), type); 95 fProcessed.add(node.getName()); 96 } 97 rewrite(FieldAccess node, ITypeBinding type)98 protected void rewrite(FieldAccess node, ITypeBinding type) { 99 Expression exp= node.getExpression(); 100 if (exp == null) { 101 ImportRewriteContext context= new ContextSensitiveImportRewriteContext(node, fCuRewrite.getImportRewrite()); 102 Type result= fCuRewrite.getImportRewrite().addImport(type, fCuRewrite.getAST(), context); 103 fCuRewrite.getImportRemover().registerAddedImport(type.getQualifiedName()); 104 exp= ASTNodeFactory.newName(fCuRewrite.getAST(), ASTFlattener.asString(result)); 105 fCuRewrite.getASTRewrite().set(node, FieldAccess.EXPRESSION_PROPERTY, exp, fCuRewrite.createGroupDescription(REFERENCE_UPDATE)); 106 fNeedsImport= true; 107 } else if (exp instanceof Name) { 108 rewriteName((Name)exp, type); 109 } else { 110 rewriteExpression(node, exp, type); 111 } 112 fProcessed.add(node.getName()); 113 } 114 rewrite(MethodInvocation node, ITypeBinding type)115 protected void rewrite(MethodInvocation node, ITypeBinding type) { 116 Expression exp= node.getExpression(); 117 if (exp == null) { 118 ImportRewriteContext context= new ContextSensitiveImportRewriteContext(node, fCuRewrite.getImportRewrite()); 119 Type result= fCuRewrite.getImportRewrite().addImport(type, fCuRewrite.getAST(), context); 120 fCuRewrite.getImportRemover().registerAddedImport(type.getQualifiedName()); 121 exp= ASTNodeFactory.newName(fCuRewrite.getAST(), ASTFlattener.asString(result)); 122 fCuRewrite.getASTRewrite().set(node, MethodInvocation.EXPRESSION_PROPERTY, exp, fCuRewrite.createGroupDescription(REFERENCE_UPDATE)); 123 fNeedsImport= true; 124 } else if (exp instanceof Name) { 125 rewriteName((Name)exp, type); 126 } else { 127 rewriteExpression(node, exp, type); 128 } 129 fProcessed.add(node.getName()); 130 } 131 rewrite(MemberRef node, ITypeBinding type)132 protected void rewrite(MemberRef node, ITypeBinding type) { 133 Name qualifier= node.getQualifier(); 134 if (qualifier == null) { 135 ImportRewriteContext context= new ContextSensitiveImportRewriteContext(node, fCuRewrite.getImportRewrite()); 136 Type result= fCuRewrite.getImportRewrite().addImport(type, fCuRewrite.getAST(), context); 137 fCuRewrite.getImportRemover().registerAddedImport(type.getQualifiedName()); 138 qualifier= ASTNodeFactory.newName(fCuRewrite.getAST(), ASTFlattener.asString(result)); 139 fCuRewrite.getASTRewrite().set(node, MemberRef.QUALIFIER_PROPERTY, qualifier, fCuRewrite.createGroupDescription(REFERENCE_UPDATE)); 140 fNeedsImport= true; 141 } else { 142 rewriteName(qualifier, type); 143 } 144 fProcessed.add(node.getName()); 145 } 146 rewrite(MethodRef node, ITypeBinding type)147 protected void rewrite(MethodRef node, ITypeBinding type) { 148 Name qualifier= node.getQualifier(); 149 if (qualifier == null) { 150 ImportRewriteContext context= new ContextSensitiveImportRewriteContext(node, fCuRewrite.getImportRewrite()); 151 Type result= fCuRewrite.getImportRewrite().addImport(type, fCuRewrite.getAST(), context); 152 fCuRewrite.getImportRemover().registerAddedImport(type.getQualifiedName()); 153 qualifier= ASTNodeFactory.newName(fCuRewrite.getAST(), ASTFlattener.asString(result)); 154 fCuRewrite.getASTRewrite().set(node, MethodRef.QUALIFIER_PROPERTY, qualifier, fCuRewrite.createGroupDescription(REFERENCE_UPDATE)); 155 fNeedsImport= true; 156 } else { 157 rewriteName(qualifier, type); 158 } 159 fProcessed.add(node.getName()); 160 } 161 rewriteName(Name name, ITypeBinding type)162 private void rewriteName(Name name, ITypeBinding type) { 163 AST creator= name.getAST(); 164 boolean fullyQualified= false; 165 if (name instanceof QualifiedName) { 166 SimpleName left= ASTNodes.getLeftMostSimpleName(name); 167 if (left.resolveBinding() instanceof IPackageBinding) 168 fullyQualified= true; 169 } 170 if (fullyQualified) { 171 fCuRewrite.getASTRewrite().replace( 172 name, 173 ASTNodeFactory.newName(creator, type.getQualifiedName()), 174 fCuRewrite.createGroupDescription(REFERENCE_UPDATE)); 175 fCuRewrite.getImportRemover().registerRemovedNode(name); 176 } else { 177 ImportRewriteContext context= new ContextSensitiveImportRewriteContext(name, fCuRewrite.getImportRewrite()); 178 Type result= fCuRewrite.getImportRewrite().addImport(type, fCuRewrite.getAST(), context); 179 fCuRewrite.getImportRemover().registerAddedImport(type.getQualifiedName()); 180 Name n= ASTNodeFactory.newName(fCuRewrite.getAST(), ASTFlattener.asString(result)); 181 fCuRewrite.getASTRewrite().replace( 182 name, 183 n, 184 fCuRewrite.createGroupDescription(REFERENCE_UPDATE)); 185 fCuRewrite.getImportRemover().registerRemovedNode(name); 186 fNeedsImport= true; 187 } 188 } 189 rewriteExpression(ASTNode node, Expression exp, ITypeBinding type)190 private void rewriteExpression(ASTNode node, Expression exp, ITypeBinding type) { 191 ImportRewriteContext context= new ContextSensitiveImportRewriteContext(exp, fCuRewrite.getImportRewrite()); 192 Type typeNode= fCuRewrite.getImportRewrite().addImport(type, fCuRewrite.getAST(), context); 193 fCuRewrite.getASTRewrite().replace(exp, typeNode, fCuRewrite.createGroupDescription(REFERENCE_UPDATE)); 194 fCuRewrite.getImportRemover().registerAddedImport(type.getQualifiedName()); 195 fCuRewrite.getImportRemover().registerRemovedNode(exp); 196 fNeedsImport= true; 197 nonStaticAccess(node); 198 } 199 nonStaticAccess(ASTNode node)200 protected void nonStaticAccess(ASTNode node) { 201 fStatus.addWarning(RefactoringCoreMessages.MoveStaticMemberAnalyzer_nonStatic, 202 JavaStatusContext.create(fCuRewrite.getCu(), node)); 203 } 204 isStaticAccess(Expression exp, ITypeBinding type)205 protected boolean isStaticAccess(Expression exp, ITypeBinding type) { 206 if (!(exp instanceof Name)) 207 return false; 208 return Bindings.equals(type, ((Name)exp).resolveBinding()); 209 } 210 isMovedMember(IBinding binding)211 protected boolean isMovedMember(IBinding binding) { 212 if (binding == null) 213 return false; 214 for (IBinding member : fMembers) { 215 if (Bindings.equalDeclarations(member, binding)) 216 return true; 217 } 218 return false; 219 } 220 } 221