@Override
 public void visitVariable(VariableTree tree) {
   Symbol symbol = tree.symbol();
   if (symbol != null && !symbol.isStatic()) {
     super.visitVariable(tree);
   }
 }
 private static Multimap<String, Symbol> sortByName(List<Symbol> members) {
   Multimap<String, Symbol> membersByName = LinkedListMultimap.create();
   for (Symbol member : members) {
     membersByName.put(member.name(), member);
   }
   return membersByName;
 }
 private static boolean isVariableToExtract(Symbol symbol) {
   String name = symbol.name();
   return !symbol.isEnum()
       && symbol.isVariableSymbol()
       && !"this".equals(name)
       && !"super".equals(name);
 }
 private void checkForIssue(Symbol symbol, Multimap<String, Symbol> membersByName) {
   String name = symbol.name();
   for (String knownMemberName : membersByName.keySet()) {
     if (name.equalsIgnoreCase(knownMemberName)) {
       for (Symbol knownMemberSymbol : membersByName.get(knownMemberName)) {
         if (!symbol.equals(knownMemberSymbol)
             && isValidIssueLocation(symbol, knownMemberSymbol)
             && isInvalidMember(symbol, knownMemberSymbol)) {
           addIssue(
               symbol.declaration(),
               "Rename "
                   + getSymbolTypeName(symbol)
                   + " \""
                   + name
                   + "\" "
                   + "to prevent any misunderstanding/clash with "
                   + getSymbolTypeName(knownMemberSymbol)
                   + " \""
                   + knownMemberName
                   + "\" "
                   + "defined "
                   + getDefinitionPlace(symbol, knownMemberSymbol)
                   + ".");
           break;
         }
       }
     }
   }
 }
 @Override
 public void visitNode(Tree tree) {
   if (hasSemantic()) {
     TypeParameters typeParameters;
     String messageEnd;
     if (tree.is(Tree.Kind.METHOD)) {
       typeParameters = ((MethodTree) tree).typeParameters();
       messageEnd = "method.";
     } else {
       typeParameters = ((ClassTree) tree).typeParameters();
       messageEnd = "class.";
       if (tree.is(Tree.Kind.INTERFACE)) {
         messageEnd = "interface.";
       }
     }
     for (TypeParameterTree typeParameter : typeParameters) {
       Symbol symbol = getSemanticModel().getSymbol(typeParameter);
       if (symbol.usages().isEmpty()) {
         String message =
             new StringBuilder(typeParameter.identifier().name())
                 .append(" is not used in the ")
                 .append(messageEnd)
                 .toString();
         addIssue(typeParameter, message);
       }
     }
   }
 }
 private static Collection<MethodSymbol> filterMethods(Collection<Symbol> symbols) {
   List<MethodSymbol> methods = Lists.newArrayList();
   for (Symbol symbol : symbols) {
     if (symbol.isMethodSymbol() && !isConstructor(symbol)) {
       methods.add((MethodSymbol) symbol);
     }
   }
   return methods;
 }
 private static String getDefinitionPlace(Symbol symbol, Symbol knownMemberSymbol) {
   if (sameOwner(symbol, knownMemberSymbol)) {
     return "on line " + getDeclarationLine(knownMemberSymbol);
   }
   return "in "
       + (knownMemberSymbol.owner().isInterface() ? "interface" : "superclass")
       + " \""
       + knownMemberSymbol.owner().type().fullyQualifiedName()
       + "\"";
 }
 private static List<Symbol> extractMembers(Symbol.TypeSymbol classSymbol, boolean ignorePrivate) {
   List<Symbol> results = Lists.newLinkedList();
   for (Symbol symbol : classSymbol.memberSymbols()) {
     if ((isVariableToExtract(symbol) || isMethodToExtract(symbol))
         && !(symbol.isPrivate() && ignorePrivate)) {
       results.add(symbol);
     }
   }
   return results;
 }
 private static boolean isFirstParentStatic(Deque<Symbol> outerClasses) {
   if (outerClasses.size() == 1) {
     return true;
   }
   for (Symbol outerClass : outerClasses) {
     if (outerClass.isStatic()) {
       return true;
     }
   }
   return false;
 }
 public void checkIfUnused(VariableTree tree) {
   if (tree.modifiers().annotations().isEmpty()) {
     Symbol symbol = tree.symbol();
     String name = symbol.name();
     if (symbol.isPrivate()
         && !"serialVersionUID".equals(name)
         && symbol.usages().size() == assignments.get(symbol).size()) {
       addIssue(tree, "Remove this unused \"" + name + "\" private field.");
     }
   }
 }
 @Override
 public void visitCatch(CatchTree tree) {
   if (!isExcludedType(tree.parameter().type())) {
     Symbol exception = tree.parameter().symbol();
     validUsagesStack.addFirst(exception.usages());
     super.visitCatch(tree);
     Collection<IdentifierTree> usages = validUsagesStack.pop();
     if (usages.isEmpty()) {
       context.reportIssue(this, tree.parameter(), "Either log or rethrow this exception.");
     }
   }
 }
 private int fromInstance(Symbol symbol, Symbol owner) {
   int i = -1;
   Type ownerType = owner.type();
   for (Symbol outerClass : outerClasses) {
     i++;
     if (symbol.equals(outerClass)
         || (ownerType != null
             && owner.isTypeSymbol()
             && outerClass.type().isSubtypeOf(ownerType))) {
       return i;
     }
   }
   return -1;
 }
 private void addBoxingIssue(Tree tree, Symbol classSymbol, Tree boxingArg) {
   if (boxingArg.is(Tree.Kind.IDENTIFIER)) {
     IdentifierTree identifier = (IdentifierTree) boxingArg;
     reportIssue(tree, "Remove the boxing of \"" + identifier.name() + "\".");
   } else {
     reportIssue(tree, "Remove the boxing to \"" + classSymbol.name() + "\".");
   }
 }
 private void visitMethodInvocationTree(MethodInvocationTree methodInvocationTree) {
   if (isValueOfInvocation(methodInvocationTree)) {
     checkForUnboxing(methodInvocationTree.arguments().get(0));
   } else if (isUnboxingMethodInvocation(methodInvocationTree)) {
     ExpressionTree methodSelect = methodInvocationTree.methodSelect();
     if (methodSelect.is(Tree.Kind.MEMBER_SELECT)) {
       MemberSelectExpressionTree memberSelectExpressionTree =
           (MemberSelectExpressionTree) methodSelect;
       checkForBoxing(memberSelectExpressionTree.expression());
     }
   } else {
     Symbol symbol = methodInvocationTree.symbol();
     if (symbol.isMethodSymbol()) {
       List<Type> parametersTypes = ((Symbol.MethodSymbol) symbol).parameterTypes();
       checkMethodInvocationArguments(methodInvocationTree, parametersTypes);
     }
   }
 }
 private int referenceInstance(Symbol symbol) {
   Symbol owner = symbol.owner();
   if (owner != null && owner.isMethodSymbol()) {
     // local variable, use owner of the method
     owner = owner.owner();
   }
   int result = -1;
   if (owner != null && !outerClasses.peek().equals(owner)) {
     if (symbol.isUnknown()) {
       result = atLeastOneReference.size() - 1;
     } else if (!symbol.isStatic()) {
       result = fromInstance(symbol, owner);
     }
   }
   return result;
 }
 private static boolean bothProtected(Symbol s1, Symbol s2) {
   return s1.isProtected() && s2.isProtected();
 }
 private static boolean isMethodToExtract(Symbol symbol) {
   return symbol.isMethodSymbol() && !"<init>".equals(symbol.name());
 }
 private static boolean isMethodMatchingName(Symbol symbol, String matchName) {
   return symbol.isMethodSymbol() && matchName.equals(symbol.name());
 }
 private static boolean isConstructor(Symbol symbol) {
   return "<init>".equals(symbol.name());
 }
 private static String getSymbolTypeName(Symbol symbol) {
   return symbol.isMethodSymbol() ? "method" : "field";
 }
 private static int getDeclarationLine(Symbol symbol) {
   if (symbol.isVariableSymbol()) {
     return ((Symbol.VariableSymbol) symbol).declaration().simpleName().identifierToken().line();
   }
   return ((Symbol.MethodSymbol) symbol).declaration().simpleName().identifierToken().line();
 }
 private static boolean variableAndMethod(Symbol s1, Symbol s2) {
   return s1.isVariableSymbol() && s2.isMethodSymbol();
 }
 private static boolean sameName(Symbol currentMember, Symbol knownMember) {
   return currentMember.name().equals(knownMember.name());
 }
 private static boolean sameOwner(Symbol currentMember, Symbol knownMember) {
   return currentMember.owner().equals(knownMember.owner());
 }
 private static boolean isObjectsMethod(Symbol symbol, String methodName) {
   return symbol.isMethodSymbol()
       && symbol.owner().type().is("java.util.Objects")
       && methodName.equals(symbol.name());
 }
 private static boolean bothPackageVisibility(Symbol s1, Symbol s2) {
   return s1.isPackageVisibility() && s2.isPackageVisibility();
 }
 private static boolean isOverriding(Symbol symbol) {
   return symbol.isMethodSymbol()
       && BooleanUtils.isTrue(((MethodTreeImpl) symbol.declaration()).isOverriding());
 }
 private void addAssignment(IdentifierTree identifier) {
   Symbol reference = identifier.symbol();
   if (!reference.isUnknown()) {
     assignments.put(reference, identifier);
   }
 }
 private static boolean bothPublic(Symbol s1, Symbol s2) {
   return s1.isPublic() && s2.isPublic();
 }