@ClassVisitor public boolean checkClass(TypeDefinition td) { return td.isPublic(); }
@MethodVisitor public boolean checkMethod(MethodDefinition md, TypeDefinition td) { return td.isPublic() && !td.isFinal() && !md.isStatic(); }
@ClassVisitor public void visitClass(TypeDefinition td, ClassContext cc) { if (td.isAnonymous() || td.isSynthetic()) return; String name = td.getSimpleName(); if (Character.isLetter(name.charAt(0)) && !Character.isUpperCase(name.charAt(0)) && name.indexOf('_') == -1) { cc.report("BadNameOfClass", td.isPublic() ? 0 : 15); } if (name.endsWith("Exception") && !Types.isInstance(td, "java/lang/Throwable")) { cc.report("BadNameOfClassException", td.isPublic() ? 0 : 15); } TypeReference superClass = td.getBaseType(); if (superClass != null && superClass.getSimpleName().equals(name)) { cc.report("BadNameOfClassSameAsSuperclass", td.isPublic() ? 0 : 15, Roles.SUPERCLASS.create(superClass)); } for (TypeReference iface : td.getExplicitInterfaces()) { if (iface.getSimpleName().equals(name)) { cc.report("BadNameOfClassSameAsInterface", td.isPublic() ? 0 : 15, Roles.INTERFACE.create(iface)); } } }
@MethodVisitor public boolean checkMethod(MethodDefinition md, TypeDefinition td) { return td.isPublic() && !td.isFinal() && !md.isPrivate() && !md.isPackagePrivate(); }
@AstVisitor(nodes = AstNodes.EXPRESSIONS, methodName = "hasNext", methodSignature = "()Z") public void visitHasNext(Expression expr, MethodContext mc, TypeDefinition td) { if (expr.getCode() == AstCode.InvokeVirtual) { MethodReference mr = (MethodReference) expr.getOperand(); if (mr.getName().equals("next") && mr.getParameters().isEmpty() && Exprs.isThis(Exprs.getChild(expr, 0))) { mc.report("IteratorHasNextCallsNext", td.isPublic() ? 0 : 30, expr); } } }
@Override protected void visitType(TypeDefinition td) { if(!td.isPublic()) return; for(FieldDefinition fd : td.getDeclaredFields()) { if(!fd.isStatic() && !fd.isFinal() && fd.isPublic()) { getOrCreate(td); return; } } }
@AstVisitor(nodes = AstNodes.EXPRESSIONS) public void visit(Expression expr, MethodContext mc) { if (expr.getCode() != AstCode.InvokeVirtual) return; MethodReference mr = (MethodReference) expr.getOperand(); String name = mr.getName(); if (!Types.isObject(mr.getDeclaringType()) || (!name.equals("wait") && !name.startsWith("notify"))) return; TypeReference type = ValuesFlow.reduceType(expr.getArguments().get(0)); if (type == null || !type.getInternalName().startsWith("java/util/concurrent/")) return; TypeDefinition target = type.resolve(); if (target == null || !target.isPublic()) return; MethodDefinition replacement = findReplacement(name, target); if(replacement != null) { mc.report("IncorrectConcurrentMethod", 0, expr, TARGET.create(target), Roles.REPLACEMENT_METHOD.create(replacement)); } }
@ClassVisitor public void visit(TypeDefinition td, ClassContext cc) { TypeDefinition baseType = td.getBaseType().resolve(); if(baseType == null || Types.isObject(baseType)) return; for(TypeReference tr : td.getExplicitInterfaces()) { if(tr.getInternalName().equals("java/io/Serializable")) { continue; } if(Types.isInstance(baseType, tr)) { cc.report("RedundantInterface", td.isPublic() ? 0 : 10, Roles.INTERFACE.create(tr)); } } } }
if(md.isPrivate() || td.isPrivate()) priority += 20; else if(!md.isPublic() || !td.isPublic()) priority += 10; else if(md.isConstructor())
return; int priority = 0; if (!td.isPublic()) priority += 20; else {
@FieldVisitor public void visitField(FieldDefinition fd, FieldContext fc, TypeDefinition td) { if((fd.isPublic() || fd.isProtected()) && (td.isPublic() || td.isProtected()) && fd.isStatic() && !fd.isEnumConstant()) { TypeReference fieldType = fd.getFieldType(); if(!isNotThreadSafe(fieldType)) return; fc.report("StaticNotThreadSafeField", AccessLevel.of(fd).select(0, 20, 100, 100), Roles.FIELD_TYPE.create(fieldType)); } }
@AstVisitor(nodes = AstNodes.EXPRESSIONS) public void visit(Expression expr, NodeChain nc, MethodContext mc, MethodDefinition md, TypeDefinition td) { if (expr.getCode() == AstCode.Return && !expr.getArguments().isEmpty()) { Expression child = Exprs.getChild(expr, 0); if (child.getCode() == AstCode.AConstNull) { MethodDefinition curMethod = nc.getLambdaMethod(); if (curMethod == null) curMethod = md; String warningType = curMethod.getReturnType().isArray() ? "ArrayReturnNull" : TYPE_TO_WARNING .get(curMethod.getReturnType().getInternalName()); if (warningType != null) { int priority = 0; if (!td.isPublic() || md.isPrivate() || md.isPackagePrivate()) priority = 20; else if (md.isProtected() || md != curMethod) priority = 10; // Method which simply contains "return null": probably stub or something if(nc.getParent() == null && nc.isOnlyChild(expr)) priority += 10; mc.report(warningType, priority, expr.getArguments().get(0), RETURN_TYPE.create(md .getReturnType())); } } } } }
if(fd.isStatic() && (fd.isPublic() || fd.isProtected()) && (td.isPublic() || td.isProtected())) { boolean mutable = fieldRecord != null && fieldRecord.mutable; if(!fd.isFinal() && Flags.testAny(flags, FieldStats.WRITE_CONSTRUCTOR) && if(fieldRecord != null && (td.isPublic() || td.isProtected()) && (fd.isPrivate() || fd.isPackagePrivate())) { MethodLocation expose = fieldRecord.expose; if(fieldRecord.mutable && expose != null && (expose.md.isPublic() || expose.md.isProtected())) {