@Override public Void visitBinary(BinaryTree node, Void p) { // No checking unless the operator is "==" or "!=". if (!(node.getKind() == Tree.Kind.EQUAL_TO || node.getKind() == Tree.Kind.NOT_EQUAL_TO)) return super.visitBinary(node, p); ExpressionTree leftOp = node.getLeftOperand(); ExpressionTree rightOp = node.getRightOperand(); // Check passes if either arg is null. if (leftOp.getKind() == Tree.Kind.NULL_LITERAL || rightOp.getKind() == Tree.Kind.NULL_LITERAL) return super.visitBinary(node, p); AnnotatedTypeMirror left = atypeFactory.getAnnotatedType(leftOp); AnnotatedTypeMirror right = atypeFactory.getAnnotatedType(rightOp); // If either argument is a primitive, check passes due to auto-unboxing if (left.getKind().isPrimitive() || right.getKind().isPrimitive()) return super.visitBinary(node, p); if (!(shouldCheckFor(leftOp) && shouldCheckFor(rightOp))) return super.visitBinary(node, p); // Syntactic checks for legal uses of == if (suppressInsideComparison(node)) return super.visitBinary(node, p); if (suppressEarlyEquals(node)) return super.visitBinary(node, p); if (suppressEarlyCompareTo(node)) return super.visitBinary(node, p); if (suppressClassAnnotation(left, right)) { return super.visitBinary(node, p); } Element leftElt = null; Element rightElt = null; if (left instanceof org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) { leftElt = ((DeclaredType) left.getUnderlyingType()).asElement(); } if (right instanceof org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) { rightElt = ((DeclaredType) right.getUnderlyingType()).asElement(); } // if neither @Interned or @UsesObjectEquals, report error if (!(left.hasEffectiveAnnotation(INTERNED) || (leftElt != null && leftElt.getAnnotation(UsesObjectEquals.class) != null))) checker.report(Result.failure("not.interned", left), leftOp); if (!(right.hasEffectiveAnnotation(INTERNED) || (rightElt != null && rightElt.getAnnotation(UsesObjectEquals.class) != null))) checker.report(Result.failure("not.interned", right), rightOp); return super.visitBinary(node, p); }
protected void reportValidityResult( final /*@CompilerMessageKey*/ String errorType, final AnnotatedTypeMirror type, final Tree p) { checker.report(Result.failure(errorType, type.getAnnotations(), type.toString()), p); isValid = false; }
@Override public Void visitAnnotation(AnnotationTree node, Void p) { Element anno = TreeInfo.symbol((JCTree) node.getAnnotationType()); if (anno.toString().equals(DefaultType.class.getName())) { checker.report(Result.failure("annotation.not.allowed.in.src", anno.toString()), node); } return super.visitAnnotation(node, p); }
/* * Method to implement the @UsesObjectEquals functionality. * If a class is marked @UsesObjectEquals, it must: * * -not override .equals(Object) * -be a subclass of Object or another class marked @UsesObjectEquals * * If a class is not marked @UsesObjectEquals, it must: * * -not have a superclass marked @UsesObjectEquals * * * @see org.checkerframework.common.basetype.BaseTypeVisitor#visitClass(com.sun.source.tree.ClassTree, java.lang.Object) */ @Override public Void visitClass(ClassTree node, Void p) { // Looking for an @UsesObjectEquals class declaration TypeElement elt = TreeUtils.elementFromDeclaration(node); UsesObjectEquals annotation = elt.getAnnotation(UsesObjectEquals.class); Tree superClass = node.getExtendsClause(); Element elmt = null; if (superClass != null && (superClass instanceof IdentifierTree || superClass instanceof MemberSelectTree)) { elmt = TreeUtils.elementFromUse((ExpressionTree) superClass); } // if it's there, check to make sure does not override equals // and supertype is Object or @UsesObjectEquals if (annotation != null) { // check methods to ensure no .equals if (overridesEquals(node)) { checker.report(Result.failure("overrides.equals"), node); } if (!(superClass == null || (elmt != null && elmt.getAnnotation(UsesObjectEquals.class) != null))) { checker.report(Result.failure("superclass.unmarked"), node); } } else { // the class is not marked @UsesObjectEquals -> make sure its superclass isn't either. // this is impossible after design change making @UsesObjectEquals inherited? // check left in case of future design change back to non-inherited. if (superClass != null && (elmt != null && elmt.getAnnotation(UsesObjectEquals.class) != null)) { checker.report(Result.failure("superclass.marked"), node); } } return super.visitClass(node, p); }
@Override public Void visitNewArray(NewArrayTree node, Void p) { AnnotatedArrayType type = atypeFactory.getAnnotatedType(node); AnnotatedTypeMirror componentType = type.getComponentType(); if (componentType.hasEffectiveAnnotation(NONNULL) && !isNewArrayAllZeroDims(node) && !isNewArrayInToArray(node) && !TypesUtils.isPrimitive(componentType.getUnderlyingType()) && checker.getLintOption("forbidnonnullarraycomponents", false)) { checker.report( Result.failure("new.array.type.invalid", componentType.getAnnotations(), type.toString()), node); } return super.visitNewArray(node, p); }
/** * Issues a 'dereference.of.nullable' if the type is not of a {@link NonNull} type. * * @param tree the tree where the error is to reported * @param errMsg the error message (must be {@link CompilerMessageKey}) */ private void checkForNullability(ExpressionTree tree, /*@CompilerMessageKey*/ String errMsg) { AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(tree); if (!type.hasEffectiveAnnotation(NONNULL)) { checker.report(Result.failure(errMsg, tree), tree); } }