/** * Returns a set of triples {@code (expr, (result, annotation))} of conditional postconditions * according to the given {@link EnsuresQualifierIf}. */ private Set<Pair<String, Pair<Boolean, String>>> getConditionalPostcondition( AnnotationMirror ensuresAnnotationIf) { if (ensuresAnnotationIf == null) { return Collections.emptySet(); } Set<Pair<String, Pair<Boolean, String>>> result = new HashSet<>(); List<String> expressions = AnnotationUtils.getElementValueArray( ensuresAnnotationIf, "expression", String.class, false); String annotation = AnnotationUtils.getElementValueClassName(ensuresAnnotationIf, "qualifier", false) .toString(); boolean annoResult = AnnotationUtils.getElementValue(ensuresAnnotationIf, "result", Boolean.class, false); for (String expr : expressions) { result.add(Pair.of(expr, Pair.of(annoResult, annotation))); } return result; }
/** * Given a category string that may be prepended with "fixable-", return the category enum that * corresponds with the category and whether or not it is a isFixable error */ private static Pair<DiagnosticKind, Boolean> parseCategoryString(String category) { final String fixable = "fixable-"; final boolean isFixable = category.startsWith(fixable); if (isFixable) { category = category.substring(fixable.length()); } DiagnosticKind categoryEnum = DiagnosticKind.fromParseString(category); return Pair.of(categoryEnum, isFixable); }
/** * Returns a set of triples {@code (expr, (result, annotation))} of conditional postconditions on * the method {@code methodElement}. */ public Set<Pair<String, Pair<Boolean, String>>> getConditionalPostconditions( ExecutableElement methodElement) { Set<Pair<String, Pair<Boolean, String>>> result = new HashSet<>(); // Check for a single contract. AnnotationMirror ensuresAnnotationIf = factory.getDeclAnnotation(methodElement, EnsuresQualifierIf.class); result.addAll(getConditionalPostcondition(ensuresAnnotationIf)); // Check for multiple contracts. AnnotationMirror ensuresAnnotationsIf = factory.getDeclAnnotation(methodElement, EnsuresQualifiersIf.class); if (ensuresAnnotationsIf != null) { List<AnnotationMirror> annotations = AnnotationUtils.getElementValueArray( ensuresAnnotationsIf, "value", AnnotationMirror.class, false); for (AnnotationMirror a : annotations) { result.addAll(getConditionalPostcondition(a)); } } // Check type-system specific annotations. Class<ConditionalPostconditionAnnotation> metaAnnotation = ConditionalPostconditionAnnotation.class; List<Pair<AnnotationMirror, AnnotationMirror>> declAnnotations = factory.getDeclAnnotationWithMetaAnnotation(methodElement, metaAnnotation); for (Pair<AnnotationMirror, AnnotationMirror> r : declAnnotations) { AnnotationMirror anno = r.first; AnnotationMirror metaAnno = r.second; List<String> expressions = AnnotationUtils.getElementValueArray(anno, "expression", String.class, false); String annotationString = AnnotationUtils.getElementValueClassName(metaAnno, "qualifier", false).toString(); boolean annoResult = AnnotationUtils.getElementValue(anno, "result", Boolean.class, false); for (String expr : expressions) { result.add(Pair.of(expr, Pair.of(annoResult, annotationString))); } } return result; }
/** * Returns a set of pairs {@code (expr, annotation)} of preconditions according to the given * {@link RequiresQualifier}. */ private Set<Pair<String, String>> getPrecondition(AnnotationMirror requiresAnnotation) { if (requiresAnnotation == null) { return Collections.emptySet(); } Set<Pair<String, String>> result = new HashSet<>(); List<String> expressions = AnnotationUtils.getElementValueArray(requiresAnnotation, "expression", String.class, false); String annotation = AnnotationUtils.getElementValueClassName(requiresAnnotation, "qualifier", false).toString(); for (String expr : expressions) { result.add(Pair.of(expr, annotation)); } return result; }
/** * Returns a set of pairs {@code (expr, annotation)} of preconditions on the element {@code * element}. */ public Set<Pair<String, String>> getPreconditions(Element element) { Set<Pair<String, String>> result = new HashSet<>(); // Check for a single contract. AnnotationMirror requiresAnnotation = factory.getDeclAnnotation(element, RequiresQualifier.class); result.addAll(getPrecondition(requiresAnnotation)); // Check for multiple contracts. AnnotationMirror requiresAnnotations = factory.getDeclAnnotation(element, RequiresQualifiers.class); if (requiresAnnotations != null) { List<AnnotationMirror> annotations = AnnotationUtils.getElementValueArray( requiresAnnotations, "value", AnnotationMirror.class, false); for (AnnotationMirror a : annotations) { result.addAll(getPrecondition(a)); } } // Check type-system specific annotations. Class<PreconditionAnnotation> metaAnnotation = PreconditionAnnotation.class; List<Pair<AnnotationMirror, AnnotationMirror>> declAnnotations = factory.getDeclAnnotationWithMetaAnnotation(element, metaAnnotation); for (Pair<AnnotationMirror, AnnotationMirror> r : declAnnotations) { AnnotationMirror anno = r.first; AnnotationMirror metaAnno = r.second; List<String> expressions = AnnotationUtils.getElementValueArray(anno, "value", String.class, false); String annotationString = AnnotationUtils.getElementValueClassName(metaAnno, "qualifier", false).toString(); for (String expr : expressions) { result.add(Pair.of(expr, annotationString)); } } return result; }
static Pair<Boolean, String> dropParentheses(final String str) { if (str.charAt(0) == '(' && str.charAt(str.length() - 1) == ')') { return Pair.of(true, str.substring(1, str.length() - 1)); } return Pair.of(false, str); }
private Pair<ParameterizedTypeTree, AnnotatedDeclaredType> extractParameterizedTypeTree( Tree tree, AnnotatedDeclaredType type) { ParameterizedTypeTree typeargtree = null; switch (tree.getKind()) { case VARIABLE: Tree lt = ((VariableTree) tree).getType(); if (lt instanceof ParameterizedTypeTree) { typeargtree = (ParameterizedTypeTree) lt; } else { // System.out.println("Found a: " + lt); } break; case PARAMETERIZED_TYPE: typeargtree = (ParameterizedTypeTree) tree; break; case NEW_CLASS: NewClassTree nct = (NewClassTree) tree; ExpressionTree nctid = nct.getIdentifier(); if (nctid.getKind() == Tree.Kind.PARAMETERIZED_TYPE) { typeargtree = (ParameterizedTypeTree) nctid; /* * This is quite tricky... for anonymous class instantiations, * the type at this point has no type arguments. By doing the * following, we get the type arguments again. */ type = (AnnotatedDeclaredType) atypeFactory.getAnnotatedType(typeargtree); } break; case ANNOTATED_TYPE: AnnotatedTypeTree tr = (AnnotatedTypeTree) tree; ExpressionTree undtr = tr.getUnderlyingType(); if (undtr instanceof ParameterizedTypeTree) { typeargtree = (ParameterizedTypeTree) undtr; } else if (undtr instanceof IdentifierTree) { // @Something D -> Nothing to do } else { // TODO: add more test cases to ensure that nested types are // handled correctly, // e.g. @Nullable() List<@Nullable Object>[][] Pair<ParameterizedTypeTree, AnnotatedDeclaredType> p = extractParameterizedTypeTree(undtr, type); typeargtree = p.first; type = p.second; } break; case IDENTIFIER: case ARRAY_TYPE: case NEW_ARRAY: case MEMBER_SELECT: case UNBOUNDED_WILDCARD: case EXTENDS_WILDCARD: case SUPER_WILDCARD: case TYPE_PARAMETER: // Nothing to do. // System.out.println("Found a: " + (tree instanceof // ParameterizedTypeTree)); break; default: // the parameterized type is the result of some expression tree. // No need to do anything further. break; // System.err.printf("TypeValidator.visitDeclared unhandled tree: %s of kind %s\n", // tree, tree.getKind()); } return Pair.of(typeargtree, type); }