private static boolean isValueOfInvocation(ExpressionTree abstractTypedTree) {
   if (!abstractTypedTree.is(Kind.METHOD_INVOCATION)) {
     return false;
   }
   Type type = abstractTypedTree.symbolType();
   MethodMatcher valueOfMatcher =
       MethodMatcher.create()
           .typeDefinition(type.fullyQualifiedName())
           .name("valueOf")
           .addParameter(((JavaType) type).primitiveType().fullyQualifiedName());
   return valueOfMatcher.matches((MethodInvocationTree) abstractTypedTree);
 }
 @Override
 public void visitNode(Tree tree) {
   ListTree<TypeTree> thrownList = ((MethodTree) tree).throwsClauses();
   Set<String> reported = new HashSet<>();
   for (TypeTree typeTree : thrownList) {
     Type symbolType = typeTree.symbolType();
     String fullyQualifiedName = symbolType.fullyQualifiedName();
     if (!reported.contains(fullyQualifiedName)) {
       String superTypeName = isSubclassOfAny(symbolType, thrownList);
       if (superTypeName != null) {
         addIssue(
             typeTree,
             "Remove the declaration of thrown exception '"
                 + fullyQualifiedName
                 + "' which is a subclass of '"
                 + superTypeName
                 + "'.");
       } else if (symbolType.isSubtypeOf("java.lang.RuntimeException")) {
         addIssue(
             typeTree,
             "Remove the declaration of thrown exception '"
                 + fullyQualifiedName
                 + "' which is a runtime exception.");
       } else if (declaredMoreThanOnce(fullyQualifiedName, thrownList)) {
         addIssue(
             typeTree,
             "Remove the redundant '" + fullyQualifiedName + "' thrown exception declaration(s).");
       }
       reported.add(fullyQualifiedName);
     }
   }
 }
 private static boolean superClassHasOnlyStaticMethods(Symbol.TypeSymbol newClassTypeSymbol) {
   Type superClass = newClassTypeSymbol.superClass();
   if (superClass != null && !superClass.is("java.lang.Object")) {
     return hasOnlyStaticMethods(superClass.symbol());
   }
   return true;
 }
 @Override
 protected void onMethodInvocationFound(MethodInvocationTree mit) {
   Type symbolType = mit.arguments().get(0).symbolType();
   if (!(symbolType.is("long") || symbolType.is("java.lang.Long"))) {
     reportIssue(MethodsHelper.methodName(mit), "Remove this \"Double.longBitsToDouble\" call.");
   }
 }
 private static String isSubclassOfAny(Type type, ListTree<TypeTree> thrownList) {
   for (TypeTree thrown : thrownList) {
     String name = thrown.symbolType().fullyQualifiedName();
     if (!type.is(name) && type.isSubtypeOf(name)) {
       return name;
     }
   }
   return null;
 }
 private static boolean isNanTest(BinaryExpressionTree tree) {
   Type leftOperandType = tree.leftOperand().symbolType();
   if (tree.is(Tree.Kind.NOT_EQUAL_TO)
       && (leftOperandType.isPrimitive(Type.Primitives.FLOAT)
           || leftOperandType.isPrimitive(Type.Primitives.DOUBLE))) {
     return true;
   }
   return false;
 }
 @Override
 public void visitAssignmentExpression(AssignmentExpressionTree tree) {
   Type wrapper = ((JavaType) tree.expression().symbolType()).primitiveWrapperType();
   if (tree.is(Kind.PLUS_ASSIGNMENT)
       && tree.variable().symbolType().is("java.lang.String")
       && wrapper != null) {
     createIssue(tree, wrapper.name());
   }
   super.visitAssignmentExpression(tree);
 }
 private SymbolicValue createIdentifierSymbolicValue(IdentifierTree identifier) {
   final Type type = identifier.symbol().type();
   if (type != null && type.is("java.lang.Boolean")) {
     if ("TRUE".equals(identifier.name())) {
       return SymbolicValue.TRUE_LITERAL;
     } else if ("FALSE".equals(identifier.name())) {
       return SymbolicValue.FALSE_LITERAL;
     }
   }
   return createDefaultSymbolicValue();
 }
 private void checkConcatenation(
     Tree tree, ExpressionTree leftOperand, ExpressionTree rightOperand) {
   Type wrapper = null;
   if (isEmptyString(leftOperand)) {
     wrapper = ((JavaType) rightOperand.symbolType()).primitiveWrapperType();
   } else if (isEmptyString(rightOperand)) {
     wrapper = ((JavaType) leftOperand.symbolType()).primitiveWrapperType();
   }
   if (wrapper != null) {
     createIssue(tree, wrapper.name());
   }
 }
  private static List<Symbol> retrieveMembers(Symbol.TypeSymbol classSymbol) {
    List<Symbol> results = Lists.newLinkedList();
    results.addAll(extractMembers(classSymbol, false));

    for (Type parentInterface : classSymbol.interfaces()) {
      results.addAll(extractMembers(parentInterface.symbol(), true));
    }
    Type superClass = classSymbol.superClass();
    if (superClass != null) {
      results.addAll(extractMembers(superClass.symbol(), true));
    }

    return results;
  }
 private void checkExpression(ExpressionTree expression, Type implicitType) {
   if (implicitType.isPrimitive()) {
     checkForBoxing(expression);
   } else {
     checkForUnboxing(expression);
   }
 }
  @Override
  protected void onMethodInvocationFound(MethodInvocationTree tree) {
    Type argumentType = tree.arguments().get(0).symbolType();
    Type collectionType = getMethodOwner(tree);
    // can be null when using raw types
    Type collectionParameterType = getTypeParameter(collectionType);

    if (collectionParameterType != null
        && !collectionParameterType.isUnknown()
        && !isArgumentCompatible(argumentType, collectionParameterType)) {
      addIssue(
          tree,
          MessageFormat.format(
              "A \"{0}<{1}>\" cannot contain a \"{2}\"",
              collectionType, collectionParameterType, argumentType));
    }
  }
 private static boolean needsClosing(Type type) {
   for (String ignoredTypes : IGNORED_CLOSEABLE_SUBTYPES) {
     if (type.is(ignoredTypes)) {
       return false;
     }
   }
   return isCloseable(type);
 }
 private static boolean hasOneAbstractMethod(ClassTree classTree) {
   TypeSymbol symbol = classTree.symbol();
   if (symbol != null) {
     List<Type> types = symbol.interfaces();
     for (Type type : types) {
       if (!type.symbol().memberSymbols().isEmpty()) {
         return false;
       }
     }
   }
   int methods = 0;
   for (Tree member : classTree.members()) {
     boolean isMethod = member.is(Tree.Kind.METHOD);
     if (!isMethod) {
       return false;
     }
     if (isNotObjectMethod((MethodTree) member) && isNonStaticNonDefaultMethod(member)) {
       methods++;
     }
   }
   return methods == 1;
 }
 private static boolean autoboxing(Type argumentType, Type collectionParameterType) {
   return argumentType.isPrimitive()
       && ((JavaType) collectionParameterType).isPrimitiveWrapper()
       && isSubtypeOf(((JavaType) argumentType).primitiveWrapperType(), collectionParameterType);
 }
 private static boolean isSubtypeOf(Type type, Type superType) {
   return type.isSubtypeOf(superType);
 }
 private static boolean isArgumentCompatible(Type argumentType, Type collectionParameterType) {
   return isSubtypeOf(argumentType.erasure(), collectionParameterType.erasure())
       || isSubtypeOf(collectionParameterType.erasure(), argumentType.erasure())
       || autoboxing(argumentType, collectionParameterType);
 }
 private static boolean isCloseable(Type type) {
   return type.isSubtypeOf(JAVA_IO_AUTO_CLOSEABLE) || type.isSubtypeOf(JAVA_IO_CLOSEABLE);
 }
 private boolean instantiateOwnClass(Tree identifier, Symbol.TypeSymbol newClassTypeSymbol) {
   Type enclosingClassType = getSemanticModel().getEnclosingClass(identifier).type();
   return enclosingClassType.equals(newClassTypeSymbol.type());
 }
 private static Type getRootElementType(Type type) {
   return type.isArray() ? getRootElementType(((ArrayType) type).elementType()) : type;
 }
 private static boolean isIntegerOrLongExpected(Type type) {
   return type.isPrimitive(Primitives.INT) || type.isPrimitive(Primitives.LONG);
 }
 private static boolean dissimilarPrimitiveTypeWrappers(Type trueExprType, Type falseExprType) {
   return isPrimitiveWrapper(trueExprType)
       && isPrimitiveWrapper(falseExprType)
       && !trueExprType.equals(falseExprType);
 }