Class DependentTypesHelper

  • Direct Known Subclasses:
    OffsetDependentTypesHelper

    public class DependentTypesHelper
    extends java.lang.Object
    A class that helps checkers use qualifiers that are represented by annotations with Java expression strings. This class performs the following main functions:
    1. Converts the expression strings in an AnnotationMirror am, by creating a new annotation whose Java expression elements are the result of the conversion. See convertAnnotationMirror(StringToJavaExpression, AnnotationMirror), though clients do not call it (they call other methods in this class, which eventually call it). Subclasses can specialize this process by overriding methods in this class. Methods in this class always standardize Java expressions and may additionally viewpoint-adapt or delocalize expressions. Below is an explanation of each kind of conversion.
      • Standardization: the expressions in the annotations are converted such that two expression strings that are equivalent are made to be equal. For example, an instance field f may appear in an expression string as "f" or "this.f"; this class standardizes both strings to "this.f". All dependent type annotations must be standardized so that the implementation of QualifierHierarchy.isSubtypeShallow(AnnotationMirror, TypeMirror, AnnotationMirror, TypeMirror) can assume that two expressions are equivalent if their string representations are equals().
      • Viewpoint-adaption: converts an expression to some use site. For example, in method bodies, formal parameter references such as "#2" are converted to the name of the formal parameter. Another example, is at method call site, "this" is converted to the receiver of the method invocation.
      • Delocalization: removes all expressions with references to local variables that are not parameters and changes parameters to the "#1" syntax.
    2. If any of the conversions above results in an invalid expression, this class changes invalid expression strings to an error string that includes the reason why the expression is invalid. For example, @KeyFor("m") would be changed to @KeyFor("[error for expression: m error: m: identifier not found]") if m is not a valid identifier. This allows subtyping checks to assume that if two strings are equal and not errors, they reference the same valid Java expression.
    3. Checks annotated types for error strings that have been added by this class and issues an error if any are found.

    Steps 2 and 3 are separated so that an error is issued only once per invalid expression string rather than every time the expression string is parsed. (The expression string is parsed multiple times because annotated types are created multiple times.)

    • Field Detail

      • objectTM

        protected final javax.lang.model.type.TypeMirror objectTM
        The type mirror for java.lang.Object.
    • Constructor Detail

      • DependentTypesHelper

        public DependentTypesHelper​(AnnotatedTypeFactory atypeFactory)
        Creates a DependentTypesHelper.
        Parameters:
        atypeFactory - annotated type factory
    • Method Detail

      • hasDependentAnnotations

        public boolean hasDependentAnnotations()
        Returns true if any qualifier in the type system is a dependent type annotation.
        Returns:
        true if any qualifier in the type system is a dependent type annotation
      • createDependentTypesTreeAnnotator

        public TreeAnnotator createDependentTypesTreeAnnotator()
        Creates a TreeAnnotator that viewpoint-adapts dependent type annotations.
        Returns:
        a new TreeAnnotator that viewpoint-adapts dependent type annotations
      • atParameterizedTypeUse

        public void atParameterizedTypeUse​(java.util.List<AnnotatedTypeParameterBounds> bounds,
                                           javax.lang.model.element.TypeElement typeUse)
        Viewpoint-adapts the dependent type annotations on the bounds of the type parameters of the declaration of typeUse to typeUse.
        Parameters:
        bounds - annotated types of the bounds of the type parameters; its elements are side-effected by this method (but the list itself is not side-effected)
        typeUse - a use of a type with type parameter bounds bounds
      • atMethodInvocation

        public void atMethodInvocation​(AnnotatedTypeMirror.AnnotatedExecutableType methodType,
                                       com.sun.source.tree.MethodInvocationTree methodInvocationTree)
        Viewpoint-adapts the dependent type annotations in the methodType to the methodInvocationTree.

        methodType has been viewpoint-adapted to the call site, except for any dependent type annotations. This method viewpoint-adapts the dependent type annotations.

        Parameters:
        methodType - type of the method invocation; is side-effected by this method
        methodInvocationTree - use of the method
      • atConstructorInvocation

        public void atConstructorInvocation​(AnnotatedTypeMirror.AnnotatedExecutableType constructorType,
                                            com.sun.source.tree.NewClassTree newClassTree)
        Viewpoint-adapts the dependent type annotations in the constructorType to the newClassTree.

        constructorType has been viewpoint-adapted to the call site, except for any dependent type annotations. This method viewpoint-adapts the dependent type annotations.

        Parameters:
        constructorType - type of the constructor invocation; is side-effected by this method
        newClassTree - invocation of the constructor
      • atFieldAccess

        public void atFieldAccess​(AnnotatedTypeMirror type,
                                  com.sun.source.tree.MemberSelectTree fieldAccess)
        Viewpoint-adapts the Java expressions in annotations written on a field declaration to the use at fieldAccess.
        Parameters:
        type - its type; is side-effected by this method
        fieldAccess - a field access
      • atMethodBody

        public void atMethodBody​(AnnotatedTypeMirror atm,
                                 com.sun.source.tree.MethodTree methodDeclTree)
        Viewpoint-adapts the Java expressions in annotations written on the signature of the method declaration (for example, a return type) to the body of the method. This means the parameter syntax, e.g. "#2", is converted to the names of the parameter.
        Parameters:
        atm - a type at the method signature; is side-effected by this method
        methodDeclTree - a method declaration
      • atTypeDecl

        public void atTypeDecl​(AnnotatedTypeMirror type,
                               javax.lang.model.element.TypeElement typeElt)
        Standardizes the Java expressions in annotations to a type declaration.
        Parameters:
        type - the type of the type declaration; is side-effected by this method
        typeElt - the element of the type declaration
      • atVariableDeclaration

        public void atVariableDeclaration​(AnnotatedTypeMirror type,
                                          com.sun.source.tree.Tree declarationTree,
                                          javax.lang.model.element.VariableElement variableElt)
        Standardize the Java expressions in annotations in a variable declaration. Converts the parameter syntax, e.g "#1", to the parameter name.
        Parameters:
        type - the type of the variable declaration; is side-effected by this method
        declarationTree - the variable declaration
        variableElt - the element of the variable declaration
      • atExpression

        public void atExpression​(AnnotatedTypeMirror annotatedType,
                                 com.sun.source.tree.ExpressionTree expressionTree)
        Standardize the Java expressions in annotations in written in the expressionTree. Also, converts the parameter syntax, e.g. "#1", to the parameter name.

        expressionTree must be an expressions which can contain explicitly written annotations, namely a NewClassTree, NewArrayTree, or TypeCastTree. For example, this method standardizes the KeyFor annotation in (@KeyFor("map") String) key .

        Parameters:
        annotatedType - its type; is side-effected by this method
        expressionTree - a NewClassTree, NewArrayTree, or TypeCastTree
      • atLocalVariable

        public void atLocalVariable​(AnnotatedTypeMirror type,
                                    javax.lang.model.element.Element elt)
        Standardize the Java expressions in annotations in a type. Converts the parameter syntax, e.g. "#2", to the parameter name.
        Parameters:
        type - the type to standardize; is side-effected by this method
        elt - the element whose type is type
      • delocalize

        public void delocalize​(AnnotatedTypeMirror atm,
                               com.sun.source.tree.MethodTree methodDeclTree)
        Viewpoint-adapt all dependent type annotations to the method declaration, methodDeclTree. This method changes occurrences of formal parameter names to the "#2" syntax, and it removes expressions that contain other local variables.

        If a Java expression in atm references local variables (other than formal parameters), the expression is removed from the annotation. This could result in dependent type annotations with empty lists of expressions. If this is a problem, a subclass can override buildAnnotation(AnnotationMirror, Map) to do something besides creating an annotation with a empty list.

        Parameters:
        atm - type to viewpoint-adapt; is side-effected by this method
        methodDeclTree - the method declaration to which the annotations are viewpoint-adapted
      • delocalizeAtCallsite

        public void delocalizeAtCallsite​(AnnotatedTypeMirror atm,
                                         com.sun.source.tree.Tree invocationTree,
                                         java.util.List<Node> arguments,
                                         @Nullable Node receiver,
                                         javax.lang.model.element.ExecutableElement methodElt)
        Delocalizes dependent type annotations in atm so that they can be placed on the declaration of the given method or constructor being invoked. Used by whole program inference to infer dependent types for method/constructor parameters based on the actual arguments used at call sites.
        Parameters:
        atm - the annotated type mirror to delocalize
        invocationTree - the method or constructor invocation
        arguments - the actual arguments to the method or constructor
        receiver - the actual receiver, if there was one; null if not
        methodElt - the declaration of the method or constructor being invoked
      • convertAnnotationMirror

        public @Nullable javax.lang.model.element.AnnotationMirror convertAnnotationMirror​(StringToJavaExpression stringToJavaExpr,
                                                                                           javax.lang.model.element.AnnotationMirror anno)
        Given an annotation anno, this method builds a new annotation with the Java expressions transformed according to stringToJavaExpr. If anno is not a dependent type annotation, null is returned.

        If stringToJavaExpr returns null, then that expression is removed from the returned annotation.

        Instead of overriding this method, subclasses can override the following methods to change the behavior of this class:

        Parameters:
        stringToJavaExpr - function that converts strings to JavaExpressions
        anno - annotation mirror
        Returns:
        an annotation created by applying stringToJavaExpr to all expression strings in anno, or null if there would be no effect
      • transform

        protected @Nullable JavaExpression transform​(JavaExpression javaExpr)
        This method is for subclasses to override to change JavaExpressions in some way before they are inserted into new annotations. This method is called after parsing and viewpoint-adaptation have occurred. javaExpr may be a DependentTypesHelper.PassThroughExpression.

        If null is returned then the expression is not added to the new annotation.

        The default implementation returns the argument, but subclasses may override it.

        Parameters:
        javaExpr - a JavaExpression
        Returns:
        a transformed JavaExpression or null if no transformation exists
      • shouldPassThroughExpression

        protected boolean shouldPassThroughExpression​(java.lang.String expression)
        Whether or not expression should be passed to the new annotation unchanged. If this method returns true, the expression is not parsed.

        The default implementation returns true if the expression is an expression error according to DependentTypesError.isExpressionError(String). Subclasses may override this method to add additional logic.

        Parameters:
        expression - an expression string in a dependent types annotation
        Returns:
        whether or not expression should be passed through unchanged to the new annotation
      • createError

        protected org.checkerframework.framework.util.dependenttypes.DependentTypesHelper.PassThroughExpression createError​(java.lang.String expression,
                                                                                                                            JavaExpressionParseUtil.JavaExpressionParseException e)
        Creates a JavaExpression representing the exception thrown when parsing expression.
        Parameters:
        expression - an expression that caused e when parsed
        e - the exception thrown when parsing expression
        Returns:
        a Java expression
      • createError

        protected org.checkerframework.framework.util.dependenttypes.DependentTypesHelper.PassThroughExpression createError​(java.lang.String expression,
                                                                                                                            java.lang.String error)
        Creates a JavaExpression representing the error caused when parsing expression
        Parameters:
        expression - an expression that caused error when parsed
        error - the error message caused by expression
        Returns:
        a Java expression
      • checkTypeForErrorExpressions

        public void checkTypeForErrorExpressions​(AnnotatedTypeMirror atm,
                                                 com.sun.source.tree.Tree errorTree)
        Reports an expression.unparsable.type.invalid error for each Java expression in the given type that is an expression error string.
        Parameters:
        atm - annotated type to check for expression errors
        errorTree - the tree at which to report any found errors
      • reportErrors

        protected void reportErrors​(com.sun.source.tree.Tree errorTree,
                                    java.util.List<DependentTypesError> errors)
        Report the given errors as "expression.unparsable.type.invalid".
        Parameters:
        errorTree - where to report the errors
        errors - the errors to report
      • checkAnnotationForErrorExpressions

        public void checkAnnotationForErrorExpressions​(javax.lang.model.element.AnnotationMirror annotation,
                                                       com.sun.source.tree.Tree errorTree)
        Reports a flowexpr.parse.error error for each Java expression in the given annotation that is an expression error string.
        Parameters:
        annotation - annotation to check
        errorTree - location at which to issue errors
      • checkClassForErrorExpressions

        public void checkClassForErrorExpressions​(com.sun.source.tree.ClassTree classTree,
                                                  AnnotatedTypeMirror.AnnotatedDeclaredType type)
        Reports an expression.unparsable.type.invalid error for each Java expression in the given class declaration AnnotatedTypeMirror that is an expression error string. Note that this reports errors in the class declaration itself, not the body or extends/implements clauses.
        Parameters:
        classTree - class to check
        type - annotated type of the class
      • checkMethodForErrorExpressions

        public void checkMethodForErrorExpressions​(com.sun.source.tree.MethodTree methodDeclTree,
                                                   AnnotatedTypeMirror.AnnotatedExecutableType type)
        Reports an expression.unparsable.type.invalid error for each Java expression in the method declaration AnnotatedTypeMirror that is an expression error string.
        Parameters:
        methodDeclTree - method to check
        type - annotated type of the method