protected SFlowGraphQualifierHierarchy(GraphFactory f) { super(f); reimQuals = AnnotationUtils.createAnnotationSet(); reimQuals.add(SFlowChecker.READONLY); reimQuals.add(SFlowChecker.POLYREAD); reimQuals.add(SFlowChecker.MUTABLE); }
@Override public boolean isSubtype(Collection<AnnotationMirror> rhs, Collection<AnnotationMirror> lhs) { if (lhs.isEmpty() || rhs.isEmpty()) { // throw new RuntimeException("QualifierHierarchy: Empty annotations in lhs: " + // lhs + " or rhs: " + rhs); // System.err.println("WARN: QualifierHierarchy: Empty annotations in lhs: " + lhs // + " or rhs: " + rhs + " -- ignored"); return false; } // check if lhs contains Readonly and remove all ReIm annotations // I don't trust the equal method for AnnotationMirror... // FIXME: The following code is very ugly!!! boolean isLhsReadonly = false; for (Iterator<AnnotationMirror> it = lhs.iterator(); it.hasNext(); ) { AnnotationMirror anno = it.next(); if (anno.toString().equals(SFlowChecker.READONLY.toString())) { isLhsReadonly = true; } } Set<AnnotationMirror> rSet = AnnotationUtils.createAnnotationSet(); rSet.addAll(rhs); Set<AnnotationMirror> lSet = AnnotationUtils.createAnnotationSet(); lSet.addAll(lhs); rSet = InferenceUtils.differAnnotations(rSet, reimQuals); lSet = InferenceUtils.differAnnotations(lSet, reimQuals); for (AnnotationMirror lhsAnno : lSet) { for (AnnotationMirror rhsAnno : rSet) { if (isLhsReadonly || rhsAnno.toString().equals(SFlowChecker.BOTTOM.toString())) { if (isSubtype(rhsAnno, lhsAnno)) { return true; } } else { // We enforce equality if (rhsAnno.toString().equals(lhsAnno.toString())) return true; } } } return false; }
@Override public Void visitVariable(VariableTree node, AnnotatedTypeMirror p) { typeAnnotator.visit(p); VariableElement varElt = TreeUtils.elementFromDeclaration((VariableTree) node); if (!p.isAnnotated() && ElementUtils.isStatic(varElt)) { p.clearAnnotations(); Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet(); set.add(checker.ANY); set.add(checker.PEER); annotateConstants(p, set); } return super.visitVariable(node, p); }
@Override public Void visitLiteral(LiteralTree tree, AnnotatedTypeMirror type) { if (!type.isAnnotated()) { // if (type.getKind() == TypeKind.NULL) { type.clearAnnotations(); Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet(); set.add(checker.BOTTOM); annotateConstants(type, set); // } // else // type.addAnnotation(checker.READONLY); } return super.visitLiteral(tree, type); }
private void annotateMethod(ExecutableElement methodElt, AnnotatedExecutableType methodType) { if (checker.isChecking() || methodType.isAnnotated()) { return; } // First annotate the receiver annotateThis(methodType.getReceiverType()); // If it is from library if (checker.isFromLibrary(methodElt)) { Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet(); set.add(checker.PEER); annotateConstants(methodType, set); } // methodType.isAnnotated() only checks the annotations on methodType, // but not the type of its receiver, parameters or return; if (!methodType.isAnnotated()) methodType.addAnnotation(checker.BOTTOM); }
@Override public Void visitDeclared(AnnotatedDeclaredType type, ElementKind p) { Element elt = type.getElement(); if (!type.isAnnotated() && ( /*checker.isDefaultAnyType(type) ||*/ elt != null && ElementUtils.isStatic(elt) && (elt.getKind() == ElementKind.FIELD || elt.getKind() == ElementKind.LOCAL_VARIABLE || elt.getKind() == ElementKind.EXCEPTION_PARAMETER || elt.getKind() == ElementKind.ENUM_CONSTANT || elt.getKind() == ElementKind.PARAMETER))) { type.clearAnnotations(); Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet(); set.add(checker.ANY); if (elt != null && ElementUtils.isStatic(elt)) set.add(checker.PEER); annotateConstants(type, set); } return super.visitDeclared(type, p); }