Class GuiEffectTypeFactory

    • Field Detail

      • debugSpew

        protected final boolean debugSpew
      • uiLambdas

        protected final java.util.Set<com.sun.source.tree.LambdaExpressionTree> uiLambdas
        Keeps track of all lambda expressions with inferred UIEffect.

        constrainLambdaToUI adds lambda expressions to this set, and is called from GuiEffectVisitor whenever a lambda expression calls a @UIEffect method. Afterwards getInferedEffectForLambdaExpression uses this set and the type annotations of the functional interface of the lambda to figure out if it can affect the UI or not.

      • uiAnonClasses

        protected final java.util.Set<javax.lang.model.element.TypeElement> uiAnonClasses
        Keeps track of all anonymous inner classes with inferred UIEffect.

        constrainAnonymousClassToUI adds anonymous inner classes to this set, and is called from GuiEffectVisitor whenever an anonymous inner class calls a @UIEffect method. Afterwards isUIType and getAnnotatedType will treat this inner class as if it had been annotated with @UI.

      • ALWAYSSAFE

        protected final javax.lang.model.element.AnnotationMirror ALWAYSSAFE
        The @AlwaysSafe annotation.
      • POLYUI

        protected final javax.lang.model.element.AnnotationMirror POLYUI
        The @PolyUI annotation.
      • UI

        protected final javax.lang.model.element.AnnotationMirror UI
        The @UI annotation.
    • Constructor Detail

      • GuiEffectTypeFactory

        public GuiEffectTypeFactory​(BaseTypeChecker checker,
                                    boolean spew)
    • Method Detail

      • isPolymorphicType

        public boolean isPolymorphicType​(javax.lang.model.element.TypeElement cls)
        Returns true if the given type is polymorphic.
        Parameters:
        cls - the type to test
        Returns:
        true if the given type is polymorphic
      • isUIType

        public boolean isUIType​(javax.lang.model.element.TypeElement cls)
      • getDeclaredEffect

        public Effect getDeclaredEffect​(javax.lang.model.element.ExecutableElement methodElt)
        Calling context annotations.

        To make anon-inner-classes work, I need to climb the inheritance DAG, until I:

        • find the class/interface that declares this calling method (an anon inner class is a separate class that implements an interface)
        • check whether *that* declaration specifies @UI on either the type or method
        A method has the UI effect when:
        1. A method is UI if annotated @UIEffect
        2. A method is UI if the enclosing class is annotated @UI or @UIType and the method is not annotated @AlwaysSafe
        3. A method is UI if the corresponding method in the super-class/interface is UI, and this method is not annotated @AlwaysSafe, and this method resides in an anonymous inner class (named classes still require a package/class/method annotation to make it UI, only anon inner classes have this inheritance-by-default)
          • A method must be *annotated* UI if the method it overrides is *annotated* UI
          • A method must be *annotated* UI if it overrides a UI method and the enclosing class is not UI
        4. It is an error if a method is UI but the same method in a super-type is not UI
        5. It is an error if two super-types specify the same method, where one type says it's UI and one says it's not (it's possible to simply enforce the weaker (safe) effect, but this seems more principled, it's easier --- backwards-compatible --- to change our minds about this later)
      • getComputedEffectAtCallsite

        public Effect getComputedEffectAtCallsite​(com.sun.source.tree.MethodInvocationTree tree,
                                                  AnnotatedTypeMirror.AnnotatedDeclaredType callerReceiver,
                                                  javax.lang.model.element.ExecutableElement methodElt)
        Get the effect of a method call at its callsite, acknowledging polymorphic instantiation using type use annotations.
        Parameters:
        tree - the method invocation as an AST node
        callerReceiver - the type of the receiver object if available. Used to resolve direct calls like "super()"
        methodElt - the element of the callee method
        Returns:
        the computed effect (SafeEffect or UIEffect) for the method call
      • getInferedEffectForLambdaExpression

        public Effect getInferedEffectForLambdaExpression​(com.sun.source.tree.LambdaExpressionTree lambdaTree)
        Get the inferred effect of a lambda expression based on the type annotations of its functional interface and the effects of the calls in its body.

        This relies on GuiEffectVisitor to perform the actual inference step and mark lambdas with @PolyUIEffect functional interfaces as being explicitly UI-affecting using the constrainLambdaToUI method.

        Parameters:
        lambdaTree - a lambda expression's AST node
        Returns:
        the inferred effect of the lambda
      • isDirectlyMarkedUIThroughInference

        public boolean isDirectlyMarkedUIThroughInference​(com.sun.source.tree.Tree tree)
        Test if this tree corresponds to a lambda expression or new class marked as UI affecting by either constrainLambdaToUI} or constrainAnonymousClassToUI(TypeElement). Only explicit markings due to inference are considered here, for the properly computed type of the expression, use getAnnotatedType(Tree) instead.
        Parameters:
        tree - the tree to check
        Returns:
        whether it is a lambda expression or new class marked as UI by inference
      • findInheritedEffectRange

        public Effect.EffectRange findInheritedEffectRange​(javax.lang.model.element.TypeElement declaringType,
                                                           javax.lang.model.element.ExecutableElement overridingMethod)
      • findInheritedEffectRange

        public @Nullable Effect.EffectRange findInheritedEffectRange​(javax.lang.model.element.TypeElement declaringType,
                                                                     javax.lang.model.element.ExecutableElement overridingMethod,
                                                                     boolean issueConflictWarning,
                                                                     com.sun.source.tree.Tree errorTree)
        Find the greatest and least effects of methods the specified definition overrides. This method is used for two reasons:

        1. GuiEffectVisitor.visitMethod calls this to perform an effect override check (that a method's effect is less than or equal to the effect of any method it overrides). This use passes true for the issueConflictWarning in order to trigger warning messages.

        2. getDeclaredEffect in this class uses this to infer the default effect of methods in anonymous inner classes. This use passes false for issueConflictWarning, because it only needs the return value.

        Parameters:
        declaringType - the type declaring the override
        overridingMethod - the method override itself
        issueConflictWarning - whether or not to issue warnings
        errorTree - the method declaration AST node; used for reporting errors
        Returns:
        the min and max inherited effects, or null if none were discovered
      • getDefaultTypeDeclarationBounds

        protected AnnotationMirrorSet getDefaultTypeDeclarationBounds()
        Description copied from class: AnnotatedTypeFactory
        Returns the set of qualifiers that are the upper bound for a type use if no other bound is specified for the type.

        This implementation returns the top qualifiers by default. Subclass may override to return different qualifiers.

        Overrides:
        getDefaultTypeDeclarationBounds in class AnnotatedTypeFactory
        Returns:
        the set of qualifiers that are the upper bound for a type use if no other bound is specified for the type
      • constrainLambdaToUI

        public void constrainLambdaToUI​(com.sun.source.tree.LambdaExpressionTree lambdaExpressionTree)
        Force the given lambda expression to have UIEffect.

        Used by GuiEffectVisitor to mark as UIEffect all lambdas that perform UIEffect calls inside their bodies.

        Parameters:
        lambdaExpressionTree - a lambda expression's AST node
      • constrainAnonymousClassToUI

        public void constrainAnonymousClassToUI​(javax.lang.model.element.TypeElement classElt)
        Force the given anonymous inner class to be an @UI instantiation of its base class.

        Used by GuiEffectVisitor to mark as @UI all anonymous inner classes which: inherit from a PolyUIType annotated superclass, override a PolyUIEffect method from said superclass, and perform UIEffect calls inside the body of this method.

        Parameters:
        classElt - the TypeElement corresponding to the anonymous inner class to mark as an @UI instantiation of an UI-polymorphic superclass.