private boolean isInherited(Symbol symbol) { Type methodOwnerType = symbol.owner().type().erasure(); Type innerType = classSymbol.type().erasure(); return !symbol.isStatic() && innerType.isSubtypeOf(methodOwnerType) && !classSymbol.owner().type().equals(methodOwnerType) && !innerType.equals(methodOwnerType); }
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; }
@Override public void visitClass(ClassTree tree) { // No anonymous class, no visit of new class trees. visitNode(tree, tree.simpleName(), tree.symbol().metadata()); super.visitClass(tree); classTrees.pop(); currentParents.pop(); }
@Override public void visitClass(ClassTree tree) { if (tree.is(Tree.Kind.CLASS)) { Symbol.TypeSymbol typeSymbol = tree.symbol(); if (typeSymbol != null && typeSymbol.isAbstract()) { Collection<Symbol> symbols = typeSymbol.memberSymbols(); int abstractMethod = countAbstractMethods(symbols); if (isExtendingObject(tree) && abstractMethod == symbols.size() - 2) { //emtpy abstract class or only abstract method context.addIssue(tree, this, "Convert this \"" + typeSymbol + "\" class to an interface"); } if (symbols.size() > 2 && abstractMethod == 0 && !isPartialImplementation(tree)) { //Not empty abstract class with no abstract method context.addIssue(tree, this, "Convert this \"" + typeSymbol + "\" class to a concrete class with a private constructor"); } } } super.visitClass(tree); }
@Override public void visitNode(Tree tree) { if (!hasSemantic()) { return; } ClassTree classTree = (ClassTree) tree; Type superType = classTree.symbol().superClass(); IdentifierTree className = classTree.simpleName(); if (className == null || classTree.symbol().isAbstract() || superType == null || !(superType.is("java.io.InputStream") || superType.is("java.io.FilterInputStream"))) { return; } Optional<MethodTree> readByteIntInt = findMethod(classTree, READ_BYTES_INT_INT); if (!readByteIntInt.isPresent()) { String message = findMethod(classTree, READ_INT) .filter(readIntTree -> readIntTree.block().body().isEmpty()) .map(readIntTree -> "Provide an empty override of \"read(byte[],int,int)\" for this class as well.") .orElse("Provide an override of \"read(byte[],int,int)\" for this class."); reportIssue(className, message); } }
private JavaType getAnonymousClassType(JavaType identifierType, JavaType constructedType, ClassTree classBody) { JavaType parentType = (constructedType.isTagged(JavaType.DEFERRED) || identifierType.symbol().isInterface()) ? identifierType : constructedType; ClassJavaType anonymousClassType = (ClassJavaType) classBody.symbol().type(); if (parentType.getSymbol().isInterface()) { anonymousClassType.interfaces = ImmutableList.of(parentType); anonymousClassType.supertype = symbols.objectType; } else { anonymousClassType.supertype = parentType; anonymousClassType.interfaces = ImmutableList.of(); } anonymousClassType.symbol.members.enter(new JavaSymbol.VariableJavaSymbol(Flags.FINAL, "super", anonymousClassType.supertype, anonymousClassType.symbol)); scan(classBody); return anonymousClassType; }
private void checkRedundancy(TypeTree currentInterface, List<Type> superInterfacesTypes, Set<ClassJavaType> superTypes) { Type interfaceType = currentInterface.symbolType(); for (ClassJavaType superType : superTypes) { TypeSymbol superTypeSymbol = superType.symbol(); if (superTypeSymbol.interfaces().contains(interfaceType)) { String typeOfParentMsg = "implemented by a super class"; if (superTypeSymbol.isInterface() && superInterfacesTypes.contains(superType)) { typeOfParentMsg = "already extended by \"" + superTypeSymbol.name() + "\""; } reportIssue(currentInterface, "\"" + interfaceType.name() + "\" is " + typeOfParentMsg + "; there is no need to implement it here."); break; } } }
@Override public void visitNode(Tree tree) { ClassTree node = (ClassTree) tree; Symbol.TypeSymbol symbol = node.symbol(); Symbol owner = symbol.owner(); Type ownerType = owner.type(); if (ownerType != null && ownerType.isClass() && owner.owner().isPackageSymbol()) { // raise only one issue for the first level of nesting when multiple nesting int lines = new LinesOfCodeVisitor().linesOfCode(node); if (lines > max) { reportIssue(ExpressionsHelper.reportOnClassTree(node), "Reduce this class from " + lines + " to the maximum allowed " + max + " or externalize it in a public class."); } } }
private static boolean areTypesFinalClassAndInterface(Type ownerType, Type argumentType) { return (ownerType.symbol().isInterface() && argumentType.symbol().isFinal()) || (argumentType.symbol().isInterface() && ownerType.symbol().isFinal()); }
private static boolean areNeitherInterfaces(Type ownerType, Type argumentType) { return !ownerType.symbol().isInterface() && !argumentType.symbol().isInterface(); }
private static boolean isPrivateInnerClass(ClassTree classTree) { return !classTree.symbol().owner().isPackageSymbol() && ModifiersUtils.hasModifier(classTree.modifiers(), Modifier.PRIVATE); }
private static boolean extendsOuterClass(Symbol.TypeSymbol classSymbol) { Type superType = classSymbol.superClass(); return superType != null && superType.erasure().equals(classSymbol.owner().type().erasure()); }
private static boolean hasEnumKey(Type symbolType) { Type type = symbolType; if (type instanceof MethodJavaType) { type = ((MethodJavaType) type).resultType(); } if (type instanceof ParametrizedTypeJavaType) { ParametrizedTypeJavaType parametrizedTypeJavaType = (ParametrizedTypeJavaType) type; List<TypeVariableJavaType> typeParameters = parametrizedTypeJavaType.typeParameters(); if (!typeParameters.isEmpty()) { return parametrizedTypeJavaType.substitution(typeParameters.get(0)).symbol().isEnum(); } } return false; }
private static boolean isObject(Type operandType) { return operandType.erasure().isClass() && !operandType.symbol().isEnum(); }
private boolean outerClassHasMethodWithSameName(Symbol symbol) { return !((Symbol.TypeSymbol) classSymbol.owner()).lookupSymbols(symbol.name()).isEmpty(); }
private static boolean isSwitchOnEnum(SwitchStatementTree switchStatementTree) { return switchStatementTree.expression().symbolType().symbol().isEnum(); }
@Override public void visitNode(Tree tree) { TypeTree identifier = ((NewClassTree) tree).identifier(); Symbol.TypeSymbol newClassTypeSymbol = identifier.symbolType().symbol(); if (!newClassTypeSymbol.isEnum() && hasOnlyStaticMethodsAndFields(newClassTypeSymbol) && !instantiateOwnClass(identifier, newClassTypeSymbol)) { String message = "Remove this instantiation."; String name = getNewClassName(identifier); if (name != null) { message = "Remove this instantiation of \"{0}\"."; } reportIssue(identifier, MessageFormat.format(message, name)); } }
@Override public void visitNode(Tree tree) { TypeTree identifier = ((NewClassTree) tree).identifier(); Symbol.TypeSymbol newClassTypeSymbol = identifier.symbolType().symbol(); if (!newClassTypeSymbol.isEnum() && hasOnlyStaticMethods(newClassTypeSymbol) && !instantiateOwnClass(identifier, newClassTypeSymbol)) { String message = "Remove this instantiation."; String name = getNewClassName(identifier); if (name != null) { message = "Remove this instantiation of \"{0}\"."; } addIssue(tree, MessageFormat.format(message, name)); } }
private boolean extendsOuterClass(Symbol.TypeSymbol classSymbol) { Type superType = classSymbol.superClass(); return superType != null && superType.equals(classSymbol.owner().type()); }
private static boolean isUnserializableCollection(Type type) { return !type.symbol().isInterface() && isSubtypeOfCollectionApi(type) && !implementsSerializable(type); }