| /******************************************************************************* |
| * 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.fix; |
| |
| import java.util.ArrayList; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.text.edits.TextEditGroup; |
| |
| import org.eclipse.core.runtime.CoreException; |
| |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.compiler.IProblem; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.Assignment; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.Expression; |
| import org.eclipse.jdt.core.dom.FieldAccess; |
| import org.eclipse.jdt.core.dom.IBinding; |
| import org.eclipse.jdt.core.dom.IMethodBinding; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| import org.eclipse.jdt.core.dom.IVariableBinding; |
| import org.eclipse.jdt.core.dom.Initializer; |
| import org.eclipse.jdt.core.dom.MethodInvocation; |
| import org.eclipse.jdt.core.dom.Modifier; |
| import org.eclipse.jdt.core.dom.Name; |
| import org.eclipse.jdt.core.dom.QualifiedName; |
| import org.eclipse.jdt.core.dom.SimpleName; |
| import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; |
| import org.eclipse.jdt.core.dom.SuperFieldAccess; |
| import org.eclipse.jdt.core.dom.SwitchCase; |
| 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.VariableDeclarationFragment; |
| import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; |
| |
| import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; |
| import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
| import org.eclipse.jdt.internal.corext.dom.Bindings; |
| import org.eclipse.jdt.internal.corext.dom.GenericVisitor; |
| import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| |
| import org.eclipse.jdt.ui.text.java.IProblemLocation; |
| |
| import org.eclipse.jdt.internal.ui.text.correction.ProblemLocation; |
| |
| /** |
| * A fix which fixes code style issues. |
| */ |
| public class CodeStyleFix extends AbstractFix { |
| |
| private final static class CodeStyleVisitor extends GenericVisitor { |
| |
| private final List/*<IFixRewriteOperation>*/ fResult; |
| private final ImportRewrite fImportRewrite; |
| private final boolean fFindUnqualifiedAccesses; |
| private final boolean fFindUnqualifiedStaticAccesses; |
| private final boolean fFindUnqualifiedMethodAccesses; |
| private final boolean fFindUnqualifiedStaticMethodAccesses; |
| |
| public CodeStyleVisitor(CompilationUnit compilationUnit, |
| boolean findUnqualifiedAccesses, |
| boolean findUnqualifiedStaticAccesses, |
| boolean findUnqualifiedMethodAccesses, |
| boolean findUnqualifiedStaticMethodAccesses, |
| List resultingCollection) throws CoreException { |
| |
| fFindUnqualifiedAccesses= findUnqualifiedAccesses; |
| fFindUnqualifiedStaticAccesses= findUnqualifiedStaticAccesses; |
| fFindUnqualifiedMethodAccesses= findUnqualifiedMethodAccesses; |
| fFindUnqualifiedStaticMethodAccesses= findUnqualifiedStaticMethodAccesses; |
| fImportRewrite= StubUtility.createImportRewrite(compilationUnit, true); |
| fResult= resultingCollection; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean visit(TypeDeclaration node) { |
| if (!fFindUnqualifiedStaticAccesses && !fFindUnqualifiedStaticMethodAccesses && node.isInterface()) |
| return false; |
| |
| return super.visit(node); |
| } |
| |
| public boolean visit(QualifiedName node) { |
| if (fFindUnqualifiedAccesses || fFindUnqualifiedStaticAccesses) { |
| ASTNode simpleName= node; |
| while (simpleName instanceof QualifiedName) { |
| simpleName= ((QualifiedName) simpleName).getQualifier(); |
| } |
| if (simpleName instanceof SimpleName) { |
| handleSimpleName((SimpleName)simpleName); |
| } |
| } |
| return false; |
| } |
| |
| public boolean visit(SimpleName node) { |
| if (fFindUnqualifiedAccesses || fFindUnqualifiedStaticAccesses) { |
| handleSimpleName(node); |
| } |
| return false; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean visit(MethodInvocation node) { |
| if (!fFindUnqualifiedMethodAccesses && !fFindUnqualifiedStaticMethodAccesses) |
| return true; |
| |
| if (node.getExpression() != null) |
| return true; |
| |
| IBinding binding= node.getName().resolveBinding(); |
| if (!(binding instanceof IMethodBinding)) |
| return true; |
| |
| handleMethod(node.getName(), (IMethodBinding)binding); |
| return true; |
| } |
| |
| private void handleSimpleName(SimpleName node) { |
| ASTNode firstExpression= node.getParent(); |
| if (firstExpression instanceof FieldAccess) { |
| while (firstExpression instanceof FieldAccess) { |
| firstExpression= ((FieldAccess)firstExpression).getExpression(); |
| } |
| if (!(firstExpression instanceof SimpleName)) |
| return; |
| |
| node= (SimpleName)firstExpression; |
| } else if (firstExpression instanceof SuperFieldAccess) |
| return; |
| |
| StructuralPropertyDescriptor parentDescription= node.getLocationInParent(); |
| if (parentDescription == VariableDeclarationFragment.NAME_PROPERTY || parentDescription == SwitchCase.EXPRESSION_PROPERTY) |
| return; |
| |
| IBinding binding= node.resolveBinding(); |
| if (!(binding instanceof IVariableBinding)) |
| return; |
| |
| handleVariable(node, (IVariableBinding) binding); |
| } |
| |
| private void handleVariable(SimpleName node, IVariableBinding varbinding) { |
| if (!varbinding.isField()) |
| return; |
| |
| if (varbinding.isEnumConstant()) |
| return; |
| |
| ITypeBinding declaringClass= varbinding.getDeclaringClass(); |
| if (Modifier.isStatic(varbinding.getModifiers())) { |
| if (fFindUnqualifiedStaticAccesses) { |
| Initializer initializer= (Initializer) ASTNodes.getParent(node, Initializer.class); |
| //Do not qualify assignments to static final fields in static initializers (would result in compile error) |
| StructuralPropertyDescriptor parentDescription= node.getLocationInParent(); |
| if (initializer != null && Modifier.isStatic(initializer.getModifiers()) |
| && Modifier.isFinal(varbinding.getModifiers()) && parentDescription == Assignment.LEFT_HAND_SIDE_PROPERTY) |
| return; |
| |
| //Do not qualify static fields if defined inside an anonymous class |
| if (declaringClass.isAnonymous()) |
| return; |
| |
| fResult.add(new AddStaticQualifierOperation(declaringClass, node)); |
| } |
| } else if (fFindUnqualifiedAccesses){ |
| String qualifier= getNonStaticQualifier(declaringClass, fImportRewrite, node); |
| if (qualifier == null) |
| return; |
| |
| fResult.add(new AddThisQualifierOperation(qualifier, node)); |
| } |
| } |
| |
| private void handleMethod(SimpleName node, IMethodBinding binding) { |
| ITypeBinding declaringClass= binding.getDeclaringClass(); |
| if (Modifier.isStatic(binding.getModifiers())) { |
| if (fFindUnqualifiedStaticMethodAccesses) { |
| //Do not qualify static fields if defined inside an anonymous class |
| if (declaringClass.isAnonymous()) |
| return; |
| |
| fResult.add(new AddStaticQualifierOperation(declaringClass, node)); |
| } |
| } else { |
| if (fFindUnqualifiedMethodAccesses) { |
| String qualifier= getNonStaticQualifier(declaringClass, fImportRewrite, node); |
| if (qualifier == null) |
| return; |
| |
| fResult.add(new AddThisQualifierOperation(qualifier, node)); |
| } |
| } |
| } |
| } |
| |
| private static class ThisQualifierVisitor extends GenericVisitor { |
| |
| private final CompilationUnit fCompilationUnit; |
| private final List fOperations; |
| private final boolean fRemoveFieldQualifiers; |
| private final boolean fRemoveMethodQualifiers; |
| |
| public ThisQualifierVisitor(boolean removeFieldQualifiers, |
| boolean removeMethodQualifiers, |
| CompilationUnit compilationUnit, |
| List result) { |
| fRemoveFieldQualifiers= removeFieldQualifiers; |
| fRemoveMethodQualifiers= removeMethodQualifiers; |
| fCompilationUnit= compilationUnit; |
| fOperations= result; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean visit(final FieldAccess node) { |
| if (!fRemoveFieldQualifiers) |
| return true; |
| |
| Expression expression= node.getExpression(); |
| if (!(expression instanceof ThisExpression)) |
| return true; |
| |
| final SimpleName name= node.getName(); |
| if (hasConflict(expression.getStartPosition(), name, ScopeAnalyzer.VARIABLES)) |
| return true; |
| |
| fOperations.add(new AbstractFixRewriteOperation() { |
| public void rewriteAST(CompilationUnitRewrite cuRewrite, List textEditGroups) throws CoreException { |
| ASTRewrite rewrite= cuRewrite.getASTRewrite(); |
| |
| TextEditGroup group= createTextEditGroup(FixMessages.CodeStyleFix_removeThis_groupDescription); |
| textEditGroups.add(group); |
| |
| rewrite.replace(node, rewrite.createCopyTarget(name), group); |
| } |
| }); |
| return super.visit(node); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean visit(final MethodInvocation node) { |
| if (!fRemoveMethodQualifiers) |
| return true; |
| |
| Expression expression= node.getExpression(); |
| if (!(expression instanceof ThisExpression)) |
| return true; |
| |
| if (((ThisExpression)expression).getQualifier() != null) |
| return true; |
| |
| final SimpleName name= node.getName(); |
| if (hasConflict(expression.getStartPosition(), name, ScopeAnalyzer.METHODS)) |
| return true; |
| |
| fOperations.add(new AbstractFixRewriteOperation() { |
| public void rewriteAST(CompilationUnitRewrite cuRewrite, List textEditGroups) throws CoreException { |
| ASTRewrite rewrite= cuRewrite.getASTRewrite(); |
| |
| TextEditGroup group= createTextEditGroup(FixMessages.CodeStyleFix_removeThis_groupDescription); |
| textEditGroups.add(group); |
| |
| rewrite.remove(node.getExpression(), group); |
| } |
| }); |
| return super.visit(node); |
| } |
| |
| private boolean hasConflict(int startPosition, SimpleName name, int flag) { |
| ScopeAnalyzer analyzer= new ScopeAnalyzer(fCompilationUnit); |
| IBinding[] declarationsInScope= analyzer.getDeclarationsInScope(startPosition, flag); |
| for (int i= 0; i < declarationsInScope.length; i++) { |
| IBinding decl= declarationsInScope[i]; |
| if (decl.getName().equals(name.getIdentifier()) && name.resolveBinding() != decl) |
| return true; |
| } |
| return false; |
| } |
| } |
| |
| private final static class AddThisQualifierOperation extends AbstractFixRewriteOperation { |
| |
| private final String fQualifier; |
| private final SimpleName fName; |
| |
| public AddThisQualifierOperation(String qualifier, SimpleName name) { |
| fQualifier= qualifier; |
| fName= name; |
| } |
| |
| public String getDescription() { |
| return Messages.format(FixMessages.CodeStyleFix_QualifyWithThis_description, new Object[] {fName.getIdentifier(), fQualifier}); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.fix.AbstractFix.IFixRewriteOperation#rewriteAST(org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite, java.util.List) |
| */ |
| public void rewriteAST(CompilationUnitRewrite cuRewrite, List textEditGroups) throws CoreException { |
| ASTRewrite rewrite= cuRewrite.getASTRewrite(); |
| TextEditGroup group; |
| if (fName.resolveBinding() instanceof IMethodBinding) { |
| group= createTextEditGroup(FixMessages.CodeStyleFix_QualifyMethodWithThis_description); |
| } else { |
| group= createTextEditGroup(FixMessages.CodeStyleFix_QualifyFieldWithThis_description); |
| } |
| textEditGroups.add(group); |
| rewrite.replace(fName, rewrite.createStringPlaceholder(fQualifier + '.' + fName.getIdentifier(), ASTNode.SIMPLE_NAME), group); |
| } |
| } |
| |
| private final static class AddStaticQualifierOperation extends AbstractFixRewriteOperation { |
| |
| private final SimpleName fName; |
| private final ITypeBinding fDeclaringClass; |
| |
| public AddStaticQualifierOperation(ITypeBinding declaringClass, SimpleName name) { |
| super(); |
| fDeclaringClass= declaringClass; |
| fName= name; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.fix.AbstractFix.IFixRewriteOperation#rewriteAST(org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite, java.util.List) |
| */ |
| public void rewriteAST(CompilationUnitRewrite cuRewrite, List textEditGroups) throws CoreException { |
| ASTRewrite rewrite= cuRewrite.getASTRewrite(); |
| CompilationUnit compilationUnit= cuRewrite.getRoot(); |
| importType(fDeclaringClass, fName, cuRewrite.getImportRewrite(), compilationUnit); |
| TextEditGroup group; |
| if (fName.resolveBinding() instanceof IMethodBinding) { |
| group= createTextEditGroup(FixMessages.CodeStyleFix_QualifyMethodWithDeclClass_description); |
| } else { |
| group= createTextEditGroup(FixMessages.CodeStyleFix_QualifyFieldWithDeclClass_description); |
| } |
| textEditGroups.add(group); |
| IJavaElement javaElement= fDeclaringClass.getJavaElement(); |
| if (javaElement instanceof IType) { |
| Name qualifierName= compilationUnit.getAST().newName(((IType)javaElement).getElementName()); |
| SimpleName simpleName= (SimpleName)rewrite.createMoveTarget(fName); |
| QualifiedName qualifiedName= compilationUnit.getAST().newQualifiedName(qualifierName, simpleName); |
| rewrite.replace(fName, qualifiedName, group); |
| } |
| } |
| |
| } |
| |
| private final static class ToStaticAccessOperation extends AbstractFixRewriteOperation { |
| |
| private final ITypeBinding fDeclaringTypeBinding; |
| private final Expression fQualifier; |
| |
| public ToStaticAccessOperation(ITypeBinding declaringTypeBinding, Expression qualifier) { |
| super(); |
| fDeclaringTypeBinding= declaringTypeBinding; |
| fQualifier= qualifier; |
| } |
| |
| public String getAccessorName() { |
| return fDeclaringTypeBinding.getName(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.corext.fix.AbstractFix.IFixRewriteOperation#rewriteAST(org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite, java.util.List) |
| */ |
| public void rewriteAST(CompilationUnitRewrite cuRewrite, List textEditGroups) throws CoreException { |
| Type type= importType(fDeclaringTypeBinding, fQualifier, cuRewrite.getImportRewrite(), cuRewrite.getRoot()); |
| TextEditGroup group= createTextEditGroup(FixMessages.CodeStyleFix_ChangeAccessUsingDeclaring_description); |
| textEditGroups.add(group); |
| cuRewrite.getASTRewrite().replace(fQualifier, type, group); |
| } |
| } |
| |
| public static CodeStyleFix[] createNonStaticAccessFixes(CompilationUnit compilationUnit, IProblemLocation problem) throws CoreException { |
| if (!isNonStaticAccess(problem)) |
| return null; |
| |
| ToStaticAccessOperation operations[]= createNonStaticAccessResolveOperations(compilationUnit, problem); |
| if (operations == null) |
| return null; |
| |
| String label1= Messages.format(FixMessages.CodeStyleFix_ChangeAccessToStatic_description, operations[0].getAccessorName()); |
| CodeStyleFix fix1= new CodeStyleFix(label1, compilationUnit, new IFixRewriteOperation[] {operations[0]}); |
| |
| if (operations.length > 1) { |
| String label2= Messages.format(FixMessages.CodeStyleFix_ChangeAccessToStaticUsingInstanceType_description, operations[1].getAccessorName()); |
| CodeStyleFix fix2= new CodeStyleFix(label2, compilationUnit, new IFixRewriteOperation[] {operations[1]}); |
| return new CodeStyleFix[] {fix1, fix2}; |
| } |
| return new CodeStyleFix[] {fix1}; |
| } |
| |
| public static CodeStyleFix createAddFieldQualifierFix(CompilationUnit compilationUnit, IProblemLocation problem) throws CoreException { |
| if (IProblem.UnqualifiedFieldAccess != problem.getProblemId()) |
| return null; |
| |
| AddThisQualifierOperation operation= getUnqualifiedFieldAccessResolveOperation(compilationUnit, problem); |
| if (operation == null) |
| return null; |
| |
| String groupName= operation.getDescription(); |
| return new CodeStyleFix(groupName, compilationUnit, new IFixRewriteOperation[] {operation}); |
| } |
| |
| public static CodeStyleFix createIndirectAccessToStaticFix(CompilationUnit compilationUnit, IProblemLocation problem) throws CoreException { |
| if (!isIndirectStaticAccess(problem)) |
| return null; |
| |
| ToStaticAccessOperation operations[]= createNonStaticAccessResolveOperations(compilationUnit, problem); |
| if (operations == null) |
| return null; |
| |
| String label= Messages.format(FixMessages.CodeStyleFix_ChangeStaticAccess_description, operations[0].getAccessorName()); |
| return new CodeStyleFix(label, compilationUnit, new IFixRewriteOperation[] {operations[0]}); |
| } |
| |
| public static CodeStyleFix createCleanUp(CompilationUnit compilationUnit, |
| boolean addThisQualifier, |
| boolean changeNonStaticAccessToStatic, |
| boolean qualifyStaticFieldAccess, |
| boolean changeIndirectStaticAccessToDirect, |
| boolean qualifyMethodAccess, |
| boolean qualifyStaticMethodAccess, |
| boolean removeFieldQualifier, |
| boolean removeMethodQualifier) throws CoreException { |
| |
| if (!addThisQualifier && !changeNonStaticAccessToStatic && !qualifyStaticFieldAccess && !changeIndirectStaticAccessToDirect && !qualifyMethodAccess && !qualifyStaticMethodAccess && !removeFieldQualifier && !removeMethodQualifier) |
| return null; |
| |
| List/*<IFixRewriteOperation>*/ operations= new ArrayList(); |
| if (addThisQualifier || qualifyStaticFieldAccess || qualifyMethodAccess || qualifyStaticMethodAccess) { |
| CodeStyleVisitor codeStyleVisitor= new CodeStyleVisitor(compilationUnit, addThisQualifier, qualifyStaticFieldAccess, qualifyMethodAccess, qualifyStaticMethodAccess, operations); |
| compilationUnit.accept(codeStyleVisitor); |
| } |
| |
| IProblem[] problems= compilationUnit.getProblems(); |
| IProblemLocation[] locations= new IProblemLocation[problems.length]; |
| for (int i= 0; i < problems.length; i++) { |
| locations[i]= new ProblemLocation(problems[i]); |
| } |
| addToStaticAccessOperations(compilationUnit, locations, changeNonStaticAccessToStatic, changeIndirectStaticAccessToDirect, operations); |
| |
| if (removeFieldQualifier || removeMethodQualifier) { |
| ThisQualifierVisitor visitor= new ThisQualifierVisitor(removeFieldQualifier, removeMethodQualifier, compilationUnit, operations); |
| compilationUnit.accept(visitor); |
| } |
| |
| if (operations.isEmpty()) |
| return null; |
| |
| IFixRewriteOperation[] operationsArray= (IFixRewriteOperation[])operations.toArray(new IFixRewriteOperation[operations.size()]); |
| return new CodeStyleFix("", compilationUnit, operationsArray); //$NON-NLS-1$ |
| } |
| |
| public static CodeStyleFix createCleanUp(CompilationUnit compilationUnit, IProblemLocation[] problems, |
| boolean addThisQualifier, |
| boolean changeNonStaticAccessToStatic, |
| boolean changeIndirectStaticAccessToDirect) throws CoreException { |
| |
| if (!addThisQualifier && !changeNonStaticAccessToStatic && !changeIndirectStaticAccessToDirect) |
| return null; |
| |
| List/*<IFixRewriteOperation>*/ operations= new ArrayList(); |
| if (addThisQualifier) { |
| for (int i= 0; i < problems.length; i++) { |
| IProblemLocation problem= problems[i]; |
| if (problem.getProblemId() == IProblem.UnqualifiedFieldAccess) { |
| AddThisQualifierOperation operation= getUnqualifiedFieldAccessResolveOperation(compilationUnit, problem); |
| if (operation != null) |
| operations.add(operation); |
| } |
| } |
| } |
| |
| addToStaticAccessOperations(compilationUnit, problems, changeNonStaticAccessToStatic, changeIndirectStaticAccessToDirect, operations); |
| |
| if (operations.isEmpty()) |
| return null; |
| |
| IFixRewriteOperation[] operationsArray= (IFixRewriteOperation[])operations.toArray(new IFixRewriteOperation[operations.size()]); |
| return new CodeStyleFix("", compilationUnit, operationsArray); //$NON-NLS-1$ |
| } |
| |
| private static void addToStaticAccessOperations(CompilationUnit compilationUnit, IProblemLocation[] problems, boolean changeNonStaticAccessToStatic, boolean changeIndirectStaticAccessToDirect, List result) { |
| Hashtable nonStaticAccessOps= new Hashtable(); |
| if (changeNonStaticAccessToStatic || changeIndirectStaticAccessToDirect) { |
| for (int i= 0; i < problems.length; i++) { |
| IProblemLocation problem= problems[i]; |
| boolean isNonStaticAccess= changeNonStaticAccessToStatic && isNonStaticAccess(problem); |
| boolean isIndirectStaticAccess= changeIndirectStaticAccessToDirect && isIndirectStaticAccess(problem); |
| if (isNonStaticAccess || isIndirectStaticAccess) { |
| ToStaticAccessOperation[] nonStaticAccessInformation= createNonStaticAccessResolveOperations(compilationUnit, problem); |
| if (nonStaticAccessInformation != null) { |
| ToStaticAccessOperation op= nonStaticAccessInformation[0]; |
| nonStaticAccessOps.put(op.fQualifier, op); |
| } |
| } |
| } |
| } |
| for (Iterator iter= nonStaticAccessOps.values().iterator(); iter.hasNext();) { |
| ToStaticAccessOperation op= (ToStaticAccessOperation)iter.next(); |
| if (!nonStaticAccessOps.containsKey(op.fQualifier.getParent())) |
| result.add(op); |
| } |
| } |
| |
| private static boolean isIndirectStaticAccess(IProblemLocation problem) { |
| return (problem.getProblemId() == IProblem.IndirectAccessToStaticField |
| || problem.getProblemId() == IProblem.IndirectAccessToStaticMethod); |
| } |
| |
| private static boolean isNonStaticAccess(IProblemLocation problem) { |
| return (problem.getProblemId() == IProblem.NonStaticAccessToStaticField |
| || problem.getProblemId() == IProblem.NonStaticAccessToStaticMethod); |
| } |
| |
| private static ToStaticAccessOperation[] createNonStaticAccessResolveOperations(CompilationUnit astRoot, IProblemLocation problem) { |
| ASTNode selectedNode= problem.getCoveringNode(astRoot); |
| if (selectedNode == null) { |
| return null; |
| } |
| |
| Expression qualifier= null; |
| IBinding accessBinding= null; |
| |
| if (selectedNode instanceof QualifiedName) { |
| QualifiedName name= (QualifiedName) selectedNode; |
| qualifier= name.getQualifier(); |
| accessBinding= name.resolveBinding(); |
| } else if (selectedNode instanceof SimpleName) { |
| ASTNode parent= selectedNode.getParent(); |
| if (parent instanceof FieldAccess) { |
| FieldAccess fieldAccess= (FieldAccess) parent; |
| qualifier= fieldAccess.getExpression(); |
| accessBinding= fieldAccess.getName().resolveBinding(); |
| } else if (parent instanceof QualifiedName) { |
| QualifiedName qualifiedName= (QualifiedName) parent; |
| qualifier= qualifiedName.getQualifier(); |
| accessBinding= qualifiedName.getName().resolveBinding(); |
| } |
| } else if (selectedNode instanceof MethodInvocation) { |
| MethodInvocation methodInvocation= (MethodInvocation) selectedNode; |
| qualifier= methodInvocation.getExpression(); |
| accessBinding= methodInvocation.getName().resolveBinding(); |
| } else if (selectedNode instanceof FieldAccess) { |
| FieldAccess fieldAccess= (FieldAccess) selectedNode; |
| qualifier= fieldAccess.getExpression(); |
| accessBinding= fieldAccess.getName().resolveBinding(); |
| } |
| |
| if (accessBinding != null && qualifier != null) { |
| ToStaticAccessOperation declaring= null; |
| ITypeBinding declaringTypeBinding= getDeclaringTypeBinding(accessBinding); |
| if (declaringTypeBinding != null) { |
| declaringTypeBinding= declaringTypeBinding.getTypeDeclaration(); // use generic to avoid any type arguments |
| |
| declaring= new ToStaticAccessOperation(declaringTypeBinding, qualifier); |
| } |
| ToStaticAccessOperation instance= null; |
| ITypeBinding instanceTypeBinding= Bindings.normalizeTypeBinding(qualifier.resolveTypeBinding()); |
| if (instanceTypeBinding != null) { |
| instanceTypeBinding= instanceTypeBinding.getTypeDeclaration(); // use generic to avoid any type arguments |
| if (instanceTypeBinding.getTypeDeclaration() != declaringTypeBinding) { |
| instance= new ToStaticAccessOperation(instanceTypeBinding, qualifier); |
| } |
| } |
| if (declaring != null && instance != null) { |
| return new ToStaticAccessOperation[] {declaring, instance}; |
| } else { |
| return new ToStaticAccessOperation[] {declaring}; |
| } |
| } |
| return null; |
| } |
| |
| private static ITypeBinding getDeclaringTypeBinding(IBinding accessBinding) { |
| if (accessBinding instanceof IMethodBinding) { |
| return ((IMethodBinding) accessBinding).getDeclaringClass(); |
| } else if (accessBinding instanceof IVariableBinding) { |
| return ((IVariableBinding) accessBinding).getDeclaringClass(); |
| } |
| return null; |
| } |
| |
| private static AddThisQualifierOperation getUnqualifiedFieldAccessResolveOperation(CompilationUnit compilationUnit, IProblemLocation problem) throws CoreException { |
| SimpleName name= getName(compilationUnit, problem); |
| if (name == null) |
| return null; |
| |
| IBinding binding= name.resolveBinding(); |
| if (binding == null || binding.getKind() != IBinding.VARIABLE) |
| return null; |
| |
| ImportRewrite imports= StubUtility.createImportRewrite(compilationUnit, true); |
| |
| String replacement= getQualifier((IVariableBinding)binding, imports, name); |
| if (replacement == null) |
| return null; |
| |
| return new AddThisQualifierOperation(replacement, name); |
| } |
| |
| private static String getQualifier(IVariableBinding binding, ImportRewrite imports, SimpleName name) { |
| ITypeBinding declaringClass= binding.getDeclaringClass(); |
| if (Modifier.isStatic(binding.getModifiers())) { |
| IJavaElement javaElement= declaringClass.getJavaElement(); |
| if (javaElement instanceof IType) { |
| return ((IType)javaElement).getElementName(); |
| } |
| } else { |
| return getNonStaticQualifier(declaringClass, imports, name); |
| } |
| |
| return null; |
| } |
| |
| private static String getNonStaticQualifier(ITypeBinding declaringClass, ImportRewrite imports, SimpleName name) { |
| ITypeBinding parentType= Bindings.getBindingOfParentType(name); |
| ITypeBinding currType= parentType; |
| while (currType != null && !Bindings.isSuperType(declaringClass, currType)) { |
| currType= currType.getDeclaringClass(); |
| } |
| if (currType == null) { |
| declaringClass= declaringClass.getTypeDeclaration(); |
| currType= parentType; |
| while (currType != null && !Bindings.isSuperType(declaringClass, currType)) { |
| currType= currType.getDeclaringClass(); |
| } |
| } |
| if (currType != parentType) { |
| if (currType == null) |
| return null; |
| |
| if (currType.isAnonymous()) |
| //If we access a field of a super class of an anonymous class |
| //then we can only qualify with 'this' but not with outer.this |
| //see bug 115277 |
| return null; |
| |
| String outer= imports.addImport(currType); |
| return outer + ".this"; //$NON-NLS-1$ |
| } else { |
| return "this"; //$NON-NLS-1$ |
| } |
| } |
| |
| private static SimpleName getName(CompilationUnit compilationUnit, IProblemLocation problem) { |
| ASTNode selectedNode= problem.getCoveringNode(compilationUnit); |
| |
| while (selectedNode instanceof QualifiedName) { |
| selectedNode= ((QualifiedName) selectedNode).getQualifier(); |
| } |
| if (!(selectedNode instanceof SimpleName)) { |
| return null; |
| } |
| return (SimpleName) selectedNode; |
| } |
| |
| private CodeStyleFix(String name, CompilationUnit compilationUnit, IFixRewriteOperation[] fixRewriteOperations) { |
| super(name, compilationUnit, fixRewriteOperations); |
| } |
| } |