@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); }
private void handleInitalizers( List<? extends ExpressionTree> initializers, AnnotatedArrayType type) { List<Integer> array = new ArrayList<>(); array.add(initializers.size()); type.replaceAnnotation(createArrayLenAnnotation(array)); boolean singleDem = type.getComponentType().getKind() != TypeKind.ARRAY; if (singleDem) { return; } List<List<Integer>> summarylengths = new ArrayList<>(); for (ExpressionTree init : initializers) { AnnotatedArrayType subArrayType = (AnnotatedArrayType) getAnnotatedType(init); AnnotatedTypeMirror componentType = subArrayType; int count = 0; while (componentType.getKind() == TypeKind.ARRAY) { AnnotationMirror arrayLen = componentType.getAnnotation(ArrayLen.class); List<Integer> currentLengths; if (arrayLen != null) { currentLengths = getArrayLength(arrayLen); } else { currentLengths = (new ArrayList<Integer>()); } if (count == summarylengths.size()) { summarylengths.add(new ArrayList<Integer>()); } summarylengths.get(count).addAll(currentLengths); count++; componentType = ((AnnotatedArrayType) componentType).getComponentType(); } } AnnotatedTypeMirror componentType = type.getComponentType(); int i = 0; while (componentType.getKind() == TypeKind.ARRAY) { componentType.addAnnotation(createArrayLenAnnotation(summarylengths.get(i))); componentType = ((AnnotatedArrayType) componentType).getComponentType(); i++; } }
@Override public Void visitArray(AnnotatedArrayType type, Tree tree) { // TODO: is there already or add a helper method // to determine the non-array component type AnnotatedTypeMirror comp = type; do { comp = ((AnnotatedArrayType) comp).getComponentType(); } while (comp.getKind() == TypeKind.ARRAY); if (comp != null && comp.getKind() == TypeKind.DECLARED && checker.shouldSkipUses(((AnnotatedDeclaredType) comp).getUnderlyingType().asElement())) { return super.visitArray(type, tree); } if (!visitor.isValidUse(type, tree)) { reportError(type, tree); } return super.visitArray(type, tree); }
@Override public Void visitTypeCast(TypeCastTree tree, AnnotatedTypeMirror type) { if (isUnderlyingTypeAValue(type)) { AnnotatedTypeMirror castedAnnotation = getAnnotatedType(tree.getExpression()); List<?> values = getValues(castedAnnotation, type.getUnderlyingType()); type.replaceAnnotation(resultAnnotationHandler(type.getUnderlyingType(), values, tree)); } else if (type.getKind() == TypeKind.ARRAY) { if (tree.getExpression().getKind() == Kind.NULL_LITERAL) { type.replaceAnnotation(BOTTOMVAL); } } return null; }
@Override public Void visitMemberSelect(MemberSelectTree tree, AnnotatedTypeMirror type) { if (TreeUtils.isFieldAccess(tree) && isUnderlyingTypeAValue(type)) { VariableElement elem = (VariableElement) InternalUtils.symbol(tree); Object value = elem.getConstantValue(); if (value != null) { // compile time constant type.replaceAnnotation( resultAnnotationHandler( type.getUnderlyingType(), Collections.singletonList(value), tree)); return null; } if (ElementUtils.isStatic(elem) && ElementUtils.isFinal(elem)) { Element e = InternalUtils.symbol(tree.getExpression()); if (e != null) { String classname = ElementUtils.getQualifiedClassName(e).toString(); String fieldName = tree.getIdentifier().toString(); value = evalutator.evaluateStaticFieldAccess(classname, fieldName, tree); if (value != null) type.replaceAnnotation( resultAnnotationHandler( type.getUnderlyingType(), Collections.singletonList(value), tree)); return null; } } if (tree.getIdentifier().toString().equals("length")) { AnnotatedTypeMirror receiverType = getAnnotatedType(tree.getExpression()); if (receiverType.getKind() == TypeKind.ARRAY) { AnnotationMirror arrayAnno = receiverType.getAnnotation(ArrayLen.class); if (arrayAnno != null) { // array.length, where array : @ArrayLen(x) List<Integer> lengths = ValueAnnotatedTypeFactory.getArrayLength(arrayAnno); type.replaceAnnotation(createNumberAnnotationMirror(new ArrayList<Number>(lengths))); return null; } } } } return null; }