content: /*******************************************************************************
   * Copyright (c) 2000, 2008 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.wst.jsdt.internal.corext.refactoring.structure;
  
  import org.eclipse.wst.jsdt.core.dom.FieldAccess;
  import org.eclipse.wst.jsdt.core.dom.IBinding;
  import org.eclipse.wst.jsdt.core.dom.IFunctionBinding;
  import org.eclipse.wst.jsdt.core.dom.ITypeBinding;
  import org.eclipse.wst.jsdt.core.dom.IVariableBinding;
  import org.eclipse.wst.jsdt.core.dom.MemberRef;
  import org.eclipse.wst.jsdt.core.dom.FunctionInvocation;
  import org.eclipse.wst.jsdt.core.dom.FunctionRef;
  import org.eclipse.wst.jsdt.core.dom.Modifier;
  import org.eclipse.wst.jsdt.core.dom.QualifiedName;
  import org.eclipse.wst.jsdt.core.dom.SimpleName;
  import org.eclipse.wst.jsdt.internal.corext.dom.Bindings;
  
  /**
   * Updates references in moved static members.
   * Accepts <code>BodyDeclaration</code>s.
   */
  /* package */ class MovedMemberAnalyzer extends MoveStaticMemberAnalyzer {
  /*
   * cases:
   * - access to moved member (or to member of moved member) -> do nothing.
   * - (static) access to source -> change to source, import source.
   * - (static) access to target -> change to target.
   * - access to other type -> do nothing (import is done in MoveStaticMembersRefactoring#getUpdatedMemberSource())
   */
  // TW: Adapted references to type
  //	- Reference to type inside moved type:
  //	  - if originally resolved by qualification -> no problem
  //	  - if originally resolved by import -> must add import in target too (qualify if import ambiguous)
  	
  	public MovedMemberAnalyzer(CompilationUnitRewrite cuRewrite,
  			IBinding[] members, ITypeBinding source, ITypeBinding target) {
  		super(cuRewrite, members, source, target);
  	}
  	
  	public boolean targetNeedsSourceImport() {
  		return fNeedsImport;
  	}
  	
  	//---- types and fields --------------------------
  		
  	public boolean visit(SimpleName node) {
  		if (node.isDeclaration() || isProcessed(node))
  			return super.visit(node);
  		IBinding binding= node.resolveBinding();
  		if (isMovedMember(binding))
  			return super.visit(node);
  			
  		if (isSourceAccess(binding))
  			rewrite(node, fSource);
  		return super.visit(node);
  	}
  	
  	public boolean visit(QualifiedName node) {
  		IBinding binding= node.resolveBinding();
  		if (isSourceAccess(binding)) {
  			if (isMovedMember(binding)) {
  				rewrite(node, fTarget);
  				return false;
  			} else {
  				rewrite(node, fSource);
  				return false;
  			}
  		} else if (isTargetAccess(binding)) {
  			// remove qualifier:
  			SimpleName replace= (SimpleName)fCuRewrite.getASTRewrite().createCopyTarget(node.getName());
  			fCuRewrite.getASTRewrite().replace(node, replace, null);
  			fCuRewrite.getImportRemover().registerRemovedNode(node);
  			return false;
  		}
  		return super.visit(node);
  	}
  	
  	public boolean visit(FieldAccess node) {
  		IBinding binding= node.resolveFieldBinding();
  		if (isSourceAccess(binding)) {
  			if (isMovedMember(binding)) {
  				if (node.getExpression() != null)
  					rewrite(node, fTarget);
  			} else
  				rewrite(node, fSource);
  			
  		} else if (isTargetAccess(binding)) {
  			fCuRewrite.getASTRewrite().remove(node.getExpression(), null);
  			fCuRewrite.getImportRemover().registerRemovedNode(node.getExpression());
  		}	
  		return super.visit(node);
  	}
  	
  	//---- method invocations ----------------------------------
  	
  	public boolean visit(FunctionInvocation node) {
  		IBinding binding= node.resolveMethodBinding();
  		if (isSourceAccess(binding)) {
  			if (isMovedMember(binding)) {
  				if (node.getExpression() != null)
  					rewrite(node, fTarget);
  			} else
  				rewrite(node, fSource);
  			
  		} else if (isTargetAccess(binding)) {
  			if (node.getExpression() != null) {
  				fCuRewrite.getASTRewrite().remove(node.getExpression(), null);
  				fCuRewrite.getImportRemover().registerRemovedNode(node.getExpression());
  			}
  		}	
  		return super.visit(node);
  	}
  	
  	//---- javadoc references ----------------------------------
  	
  	public boolean visit(MemberRef node) {
  		IBinding binding= node.resolveBinding();
  		if (isSourceAccess(binding)) {
  			if (isMovedMember(binding)) {
  				if (node.getQualifier() != null)
  					rewrite(node, fTarget);
  			} else
  				rewrite(node, fSource);
  			
  		} else if (isTargetAccess(binding)) {
  			// remove qualifier:
  			SimpleName replace= (SimpleName)fCuRewrite.getASTRewrite().createCopyTarget(node.getName());
  			fCuRewrite.getASTRewrite().replace(node, replace, null);
  			fCuRewrite.getImportRemover().registerRemovedNode(node);
  		}	
  		return super.visit(node);
  	}
  	
  	public boolean visit(FunctionRef node) {
  		IBinding binding= node.resolveBinding();
  		if (isSourceAccess(binding)) {
  			if (isMovedMember(binding)) {
  				if (node.getQualifier() != null)
  					rewrite(node, fTarget);
  			} else
  				rewrite(node, fSource);
  			
  		} else if (isTargetAccess(binding)) {
  			// remove qualifier:
  			SimpleName replace= (SimpleName)fCuRewrite.getASTRewrite().createCopyTarget(node.getName());
  			fCuRewrite.getASTRewrite().replace(node, replace, null);
  			fCuRewrite.getImportRemover().registerRemovedNode(node);
  		}	
  		return super.visit(node);
  	}
  
  	//---- helper methods --------------------------------------
  	
  	private boolean isSourceAccess(IBinding binding) {
  		if (binding instanceof IFunctionBinding) {
  			IFunctionBinding method= (IFunctionBinding)binding;
  			return Modifier.isStatic(method.getModifiers()) && Bindings.equals(fSource, method.getDeclaringClass());
  		} else if (binding instanceof ITypeBinding) {
  			ITypeBinding type= (ITypeBinding)binding;
  			return Modifier.isStatic(type.getModifiers()) && Bindings.equals(fSource, type.getDeclaringClass());			
  		} else if (binding instanceof IVariableBinding) {
  			IVariableBinding field= (IVariableBinding)binding;
  			return field.isField() && Modifier.isStatic(field.getModifiers()) && Bindings.equals(fSource, field.getDeclaringClass());
  		}
  		return false;
  	}
  	
  	private boolean isTargetAccess(IBinding binding) {
  		if (binding instanceof IFunctionBinding) {
  			IFunctionBinding method= (IFunctionBinding)binding;
  			return Modifier.isStatic(method.getModifiers()) && Bindings.equals(fTarget, method.getDeclaringClass());
  		} else if (binding instanceof ITypeBinding) {
  			ITypeBinding type= (ITypeBinding)binding;
  			return Modifier.isStatic(type.getModifiers()) && Bindings.equals(fTarget, type.getDeclaringClass());			
  		} else if (binding instanceof IVariableBinding) {
  			IVariableBinding field= (IVariableBinding)binding;
  			return field.isField() && Modifier.isStatic(field.getModifiers()) && Bindings.equals(fTarget, field.getDeclaringClass());
  		}
  		return false;
  	}
  }
  