public IBinding[] getDeclarationsInScope(SimpleName selector, int flags) {
    try {
      // special case for switch on enum
      if (selector.getLocationInParent() == SwitchCase.EXPRESSION_PROPERTY) {
        ITypeBinding binding =
            ((SwitchStatement) selector.getParent().getParent())
                .getExpression()
                .resolveTypeBinding();
        if (binding != null && binding.isEnum()) {
          return getEnumContants(binding);
        }
      }

      ITypeBinding parentTypeBinding = Bindings.getBindingOfParentType(selector);
      if (parentTypeBinding != null) {
        ITypeBinding binding = getQualifier(selector);
        DefaultBindingRequestor requestor = new DefaultBindingRequestor(parentTypeBinding, flags);
        if (binding == null) {
          addLocalDeclarations(selector, flags, requestor);
          addTypeDeclarations(parentTypeBinding, flags, requestor);
        } else {
          addInherited(binding, flags, requestor);
        }

        List<IBinding> result = requestor.getResult();
        return result.toArray(new IBinding[result.size()]);
      }
      return NO_BINDING;
    } finally {
      clearLists();
    }
  }
  public boolean isDeclaredInScope(IBinding declaration, SimpleName selector, int flags) {
    try {
      // special case for switch on enum
      if (selector.getLocationInParent() == SwitchCase.EXPRESSION_PROPERTY) {
        ITypeBinding binding =
            ((SwitchStatement) selector.getParent().getParent())
                .getExpression()
                .resolveTypeBinding();
        if (binding != null && binding.isEnum()) {
          return hasEnumContants(declaration, binding.getTypeDeclaration());
        }
      }

      ITypeBinding parentTypeBinding = Bindings.getBindingOfParentTypeContext(selector);
      if (parentTypeBinding != null) {
        ITypeBinding binding = getQualifier(selector);
        SearchRequestor requestor = new SearchRequestor(declaration, parentTypeBinding, flags);
        if (binding == null) {
          addLocalDeclarations(selector, flags, requestor);
          if (requestor.found()) return requestor.isVisible();
          addTypeDeclarations(parentTypeBinding, flags, requestor);
          if (requestor.found()) return requestor.isVisible();
        } else {
          addInherited(binding, flags, requestor);
          if (requestor.found()) return requestor.isVisible();
        }
      }
      return false;
    } finally {
      clearLists();
    }
  }
  public static UnusedCodeFix createUnusedMemberFix(
      CompilationUnit compilationUnit,
      IProblemLocation problem,
      boolean removeAllAssignements,
      Document document) {
    if (isUnusedMember(problem)) {
      SimpleName name = getUnusedName(compilationUnit, problem);
      if (name != null) {
        IBinding binding = name.resolveBinding();
        if (binding != null) {
          if (isFormalParameterInEnhancedForStatement(name)) return null;

          String label = getDisplayString(name, binding, removeAllAssignements);
          RemoveUnusedMemberOperation operation =
              new RemoveUnusedMemberOperation(new SimpleName[] {name}, removeAllAssignements);
          return new UnusedCodeFix(
              label,
              compilationUnit,
              new CompilationUnitRewriteOperation[] {operation},
              getCleanUpOptions(binding, removeAllAssignements),
              document);
        }
      }
    }
    return null;
  }
 private static boolean isSideEffectFree(SimpleName simpleName, CompilationUnit completeRoot) {
   SimpleName nameNode =
       (SimpleName)
           NodeFinder.perform(completeRoot, simpleName.getStartPosition(), simpleName.getLength());
   SimpleName[] references =
       LinkedNodeFinder.findByBinding(completeRoot, nameNode.resolveBinding());
   for (int i = 0; i < references.length; i++) {
     if (hasSideEffect(references[i])) return false;
   }
   return true;
 }
  private static boolean hasSideEffect(SimpleName reference) {
    ASTNode parent = reference.getParent();
    while (parent instanceof QualifiedName) {
      parent = parent.getParent();
    }
    if (parent instanceof FieldAccess) {
      parent = parent.getParent();
    }

    ASTNode node = null;
    int nameParentType = parent.getNodeType();
    if (nameParentType == ASTNode.ASSIGNMENT) {
      Assignment assignment = (Assignment) parent;
      node = assignment.getRightHandSide();
    } else if (nameParentType == ASTNode.SINGLE_VARIABLE_DECLARATION) {
      SingleVariableDeclaration decl = (SingleVariableDeclaration) parent;
      node = decl.getInitializer();
      if (node == null) return false;
    } else if (nameParentType == ASTNode.VARIABLE_DECLARATION_FRAGMENT) {
      node = parent;
    } else {
      return false;
    }

    ArrayList<Expression> sideEffects = new ArrayList<Expression>();
    node.accept(new SideEffectFinder(sideEffects));
    return sideEffects.size() > 0;
  }
 private static ITypeBinding getQualifier(SimpleName selector) {
   ASTNode parent = selector.getParent();
   switch (parent.getNodeType()) {
     case ASTNode.METHOD_INVOCATION:
       MethodInvocation decl = (MethodInvocation) parent;
       if (selector == decl.getName()) {
         return getBinding(decl.getExpression());
       }
       return null;
     case ASTNode.QUALIFIED_NAME:
       QualifiedName qualifiedName = (QualifiedName) parent;
       if (selector == qualifiedName.getName()) {
         return getBinding(qualifiedName.getQualifier());
       }
       return null;
     case ASTNode.FIELD_ACCESS:
       FieldAccess fieldAccess = (FieldAccess) parent;
       if (selector == fieldAccess.getName()) {
         return getBinding(fieldAccess.getExpression());
       }
       return null;
     case ASTNode.SUPER_FIELD_ACCESS:
       {
         ITypeBinding curr = Bindings.getBindingOfParentType(parent);
         return curr.getSuperclass();
       }
     case ASTNode.SUPER_METHOD_INVOCATION:
       {
         SuperMethodInvocation superInv = (SuperMethodInvocation) parent;
         if (selector == superInv.getName()) {
           ITypeBinding curr = Bindings.getBindingOfParentType(parent);
           return curr.getSuperclass();
         }
         return null;
       }
     default:
       if (parent instanceof Type) {
         // bug 67644: in 'a.new X()', all member types of A are visible as location of X.
         ASTNode normalizedNode = ASTNodes.getNormalizedNode(parent);
         if (normalizedNode.getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY) {
           ClassInstanceCreation creation = (ClassInstanceCreation) normalizedNode.getParent();
           return getBinding(creation.getExpression());
         }
       }
       return null;
   }
 }
 private static String getDisplayString(
     SimpleName simpleName, IBinding binding, boolean removeAllAssignements) {
   String name = simpleName.getIdentifier();
   switch (binding.getKind()) {
     case IBinding.TYPE:
       return FixMessages.INSTANCE.UnusedCodeFix_RemoveType_description(name);
     case IBinding.METHOD:
       if (((IMethodBinding) binding).isConstructor()) {
         return FixMessages.INSTANCE.UnusedCodeFix_RemoveConstructor_description(name);
       } else {
         return FixMessages.INSTANCE.UnusedCodeFix_RemoveMethod_description(name);
       }
     case IBinding.VARIABLE:
       if (removeAllAssignements) {
         return FixMessages.INSTANCE.UnusedCodeFix_RemoveFieldOrLocalWithInitializer_description(
             name);
       } else {
         return FixMessages.INSTANCE.UnusedCodeFix_RemoveFieldOrLocal_description(name);
       }
     default:
       return ""; //$NON-NLS-1$
   }
 }
    private void removeUnusedName(CompilationUnitRewrite cuRewrite, SimpleName simpleName) {
      ASTRewrite rewrite = cuRewrite.getASTRewrite();
      CompilationUnit completeRoot = cuRewrite.getRoot();

      IBinding binding = simpleName.resolveBinding();
      CompilationUnit root = (CompilationUnit) simpleName.getRoot();
      String displayString = getDisplayString(binding);
      TextEditGroup group = createTextEditGroup(displayString, cuRewrite);
      if (binding.getKind() == IBinding.METHOD) {
        IMethodBinding decl = ((IMethodBinding) binding).getMethodDeclaration();
        ASTNode declaration = root.findDeclaringNode(decl);
        rewrite.remove(declaration, group);
      } else if (binding.getKind() == IBinding.TYPE) {
        ITypeBinding decl = ((ITypeBinding) binding).getTypeDeclaration();
        ASTNode declaration = root.findDeclaringNode(decl);
        if (declaration.getParent() instanceof TypeDeclarationStatement) {
          declaration = declaration.getParent();
        }
        rewrite.remove(declaration, group);
      } else if (binding.getKind() == IBinding.VARIABLE) {
        SimpleName nameNode =
            (SimpleName)
                NodeFinder.perform(
                    completeRoot, simpleName.getStartPosition(), simpleName.getLength());
        SimpleName[] references =
            LinkedNodeFinder.findByBinding(completeRoot, nameNode.resolveBinding());
        for (int i = 0; i < references.length; i++) {
          removeVariableReferences(rewrite, references[i], group);
        }

        IVariableBinding bindingDecl =
            ((IVariableBinding) nameNode.resolveBinding()).getVariableDeclaration();
        ASTNode declaringNode = completeRoot.findDeclaringNode(bindingDecl);
        if (declaringNode instanceof SingleVariableDeclaration) {
          removeParamTag(rewrite, (SingleVariableDeclaration) declaringNode, group);
        }
      } else {
        // unexpected
      }
    }
 private static boolean isFormalParameterInEnhancedForStatement(SimpleName name) {
   return name.getParent() instanceof SingleVariableDeclaration
       && name.getParent().getLocationInParent() == EnhancedForStatement.PARAMETER_PROPERTY;
 }
  public static ICleanUpFix createCleanUp(
      CompilationUnit compilationUnit,
      IProblemLocation[] problems,
      boolean removeUnusedPrivateMethods,
      boolean removeUnusedPrivateConstructors,
      boolean removeUnusedPrivateFields,
      boolean removeUnusedPrivateTypes,
      boolean removeUnusedLocalVariables,
      boolean removeUnusedImports,
      boolean removeUnusedCast,
      Document document) {

    List<CompilationUnitRewriteOperation> result = new ArrayList<CompilationUnitRewriteOperation>();
    HashMap<ASTNode, List<SimpleName>> variableDeclarations =
        new HashMap<ASTNode, List<SimpleName>>();
    HashSet<CastExpression> unnecessaryCasts = new HashSet<CastExpression>();
    for (int i = 0; i < problems.length; i++) {
      IProblemLocation problem = problems[i];
      int id = problem.getProblemId();

      if (removeUnusedImports
          && (id == IProblem.UnusedImport
              || id == IProblem.DuplicateImport
              || id == IProblem.ConflictingImport
              || id == IProblem.CannotImportPackage
              || id == IProblem.ImportNotFound)) {
        ImportDeclaration node = UnusedCodeFix.getImportDeclaration(problem, compilationUnit);
        if (node != null) {
          result.add(new RemoveImportOperation(node));
        }
      }

      if ((removeUnusedPrivateMethods && id == IProblem.UnusedPrivateMethod)
          || (removeUnusedPrivateConstructors && id == IProblem.UnusedPrivateConstructor)
          || (removeUnusedPrivateTypes && id == IProblem.UnusedPrivateType)) {

        SimpleName name = getUnusedName(compilationUnit, problem);
        if (name != null) {
          IBinding binding = name.resolveBinding();
          if (binding != null) {
            result.add(new RemoveUnusedMemberOperation(new SimpleName[] {name}, false));
          }
        }
      }

      if ((removeUnusedLocalVariables && id == IProblem.LocalVariableIsNeverUsed)
          || (removeUnusedPrivateFields && id == IProblem.UnusedPrivateField)) {
        SimpleName name = getUnusedName(compilationUnit, problem);
        if (name != null) {
          IBinding binding = name.resolveBinding();
          if (binding instanceof IVariableBinding
              && !isFormalParameterInEnhancedForStatement(name)
              && (!((IVariableBinding) binding).isField()
                  || isSideEffectFree(name, compilationUnit))) {
            VariableDeclarationFragment parent =
                (VariableDeclarationFragment)
                    ASTNodes.getParent(
                        name, VariableDeclarationFragment.VARIABLE_DECLARATION_FRAGMENT);
            if (parent != null) {
              ASTNode varDecl = parent.getParent();
              if (!variableDeclarations.containsKey(varDecl)) {
                variableDeclarations.put(varDecl, new ArrayList<SimpleName>());
              }
              variableDeclarations.get(varDecl).add(name);
            } else {
              result.add(new RemoveUnusedMemberOperation(new SimpleName[] {name}, false));
            }
          }
        }
      }

      if (removeUnusedCast && id == IProblem.UnnecessaryCast) {
        ASTNode selectedNode = problem.getCoveringNode(compilationUnit);

        ASTNode curr = selectedNode;
        while (curr instanceof ParenthesizedExpression) {
          curr = ((ParenthesizedExpression) curr).getExpression();
        }

        if (curr instanceof CastExpression) {
          unnecessaryCasts.add((CastExpression) curr);
        }
      }
    }
    for (Iterator<ASTNode> iter = variableDeclarations.keySet().iterator(); iter.hasNext(); ) {
      ASTNode node = iter.next();
      List<SimpleName> names = variableDeclarations.get(node);
      result.add(
          new RemoveUnusedMemberOperation(names.toArray(new SimpleName[names.size()]), false));
    }
    if (unnecessaryCasts.size() > 0) result.add(new RemoveAllCastOperation(unnecessaryCasts));

    if (result.size() == 0) return null;

    return new UnusedCodeFix(
        FixMessages.INSTANCE.UnusedCodeFix_change_name(), compilationUnit,
        result.toArray(new CompilationUnitRewriteOperation[result.size()]), document);
  }
    /**
     * Remove the field or variable declaration including the initializer.
     *
     * @param rewrite the AST rewriter to use
     * @param reference a reference to the variable to remove
     * @param group the text edit group to use
     */
    private void removeVariableReferences(
        ASTRewrite rewrite, SimpleName reference, TextEditGroup group) {
      ASTNode parent = reference.getParent();
      while (parent instanceof QualifiedName) {
        parent = parent.getParent();
      }
      if (parent instanceof FieldAccess) {
        parent = parent.getParent();
      }

      int nameParentType = parent.getNodeType();
      if (nameParentType == ASTNode.ASSIGNMENT) {
        Assignment assignment = (Assignment) parent;
        Expression rightHand = assignment.getRightHandSide();

        ASTNode assignParent = assignment.getParent();
        if (assignParent.getNodeType() == ASTNode.EXPRESSION_STATEMENT
            && rightHand.getNodeType() != ASTNode.ASSIGNMENT) {
          removeVariableWithInitializer(rewrite, rightHand, assignParent, group);
        } else {
          rewrite.replace(assignment, rewrite.createCopyTarget(rightHand), group);
        }
      } else if (nameParentType == ASTNode.SINGLE_VARIABLE_DECLARATION) {
        rewrite.remove(parent, group);
      } else if (nameParentType == ASTNode.VARIABLE_DECLARATION_FRAGMENT) {
        VariableDeclarationFragment frag = (VariableDeclarationFragment) parent;
        ASTNode varDecl = frag.getParent();
        List<VariableDeclarationFragment> fragments;
        if (varDecl instanceof VariableDeclarationExpression) {
          fragments = ((VariableDeclarationExpression) varDecl).fragments();
        } else if (varDecl instanceof FieldDeclaration) {
          fragments = ((FieldDeclaration) varDecl).fragments();
        } else {
          fragments = ((VariableDeclarationStatement) varDecl).fragments();
        }
        Expression initializer = frag.getInitializer();
        if (initializer instanceof CastExpression) {
          initializer = ((CastExpression) initializer).getExpression();
        }
        boolean sideEffectInitializer =
            initializer instanceof MethodInvocation || initializer instanceof ClassInstanceCreation;
        if (fragments.size() == fUnusedNames.length) {
          if (fForceRemove) {
            rewrite.remove(varDecl, group);
            return;
          }
          if (parent.getParent() instanceof FieldDeclaration) {
            rewrite.remove(varDecl, group);
            return;
          }
          if (sideEffectInitializer) {
            Expression movedInit = (Expression) rewrite.createMoveTarget(initializer);
            ExpressionStatement wrapped = rewrite.getAST().newExpressionStatement(movedInit);
            rewrite.replace(varDecl, wrapped, group);
          } else {
            rewrite.remove(varDecl, group);
          }
        } else {
          if (fForceRemove) {
            rewrite.remove(frag, group);
            return;
          }
          // multiple declarations in one line
          ASTNode declaration = parent.getParent();
          if (declaration instanceof FieldDeclaration) {
            rewrite.remove(frag, group);
            return;
          }
          if (declaration instanceof VariableDeclarationStatement) {
            ASTNode lst = declaration.getParent();
            ListRewrite listRewrite = null;
            if (lst instanceof Block) {
              listRewrite = rewrite.getListRewrite(lst, Block.STATEMENTS_PROPERTY);
            } else if (lst instanceof SwitchStatement) {
              listRewrite = rewrite.getListRewrite(lst, SwitchStatement.STATEMENTS_PROPERTY);
            } else {
              Assert.isTrue(false);
            }
            splitUpDeclarations(
                rewrite, group, frag, listRewrite, (VariableDeclarationStatement) declaration);
            rewrite.remove(frag, group);
            return;
          }
          if (declaration instanceof VariableDeclarationExpression) {
            // keep constructors and method invocations
            if (!sideEffectInitializer) {
              rewrite.remove(frag, group);
            }
          }
        }
      } else if (nameParentType == ASTNode.POSTFIX_EXPRESSION
          || nameParentType == ASTNode.PREFIX_EXPRESSION) {
        Expression expression = (Expression) parent;
        ASTNode expressionParent = expression.getParent();
        if (expressionParent.getNodeType() == ASTNode.EXPRESSION_STATEMENT) {
          removeStatement(rewrite, expressionParent, group);
        } else {
          rewrite.remove(expression, group);
        }
      }
    }