Class GuiEffectTypeFactory

All Implemented Interfaces:
AnnotationProvider

public class GuiEffectTypeFactory extends BaseAnnotatedTypeFactory
Annotated type factory for the GUI Effect Checker.
  • Field Details

    • debugSpew

      protected final boolean debugSpew
    • uiLambdas

      protected final Set<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 Set<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 AnnotationMirror ALWAYSSAFE
      The @AlwaysSafe annotation.
    • POLYUI

      protected final AnnotationMirror POLYUI
      The @PolyUI annotation.
    • UI

      protected final AnnotationMirror UI
      The @UI annotation.
  • Constructor Details

    • GuiEffectTypeFactory

      public GuiEffectTypeFactory(BaseTypeChecker checker, boolean spew)
  • Method Details

    • isPolymorphicType

      public boolean isPolymorphicType(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(TypeElement cls)
    • getDeclaredEffect

      public Effect getDeclaredEffect(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(MethodInvocationTree tree, AnnotatedTypeMirror.AnnotatedDeclaredType callerReceiver, 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(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(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
    • getAnnotatedType

      public AnnotatedTypeMirror getAnnotatedType(Tree tree)
      Description copied from class: AnnotatedTypeFactory
      Returns an AnnotatedTypeMirror representing the annotated type of tree.
      Overrides:
      getAnnotatedType in class AnnotatedTypeFactory
      Parameters:
      tree - the AST node
      Returns:
      the annotated type of tree
    • findInheritedEffectRange

      public Effect.EffectRange findInheritedEffectRange(TypeElement declaringType, ExecutableElement overridingMethod)
    • findInheritedEffectRange

      public @Nullable Effect.EffectRange findInheritedEffectRange(TypeElement declaringType, ExecutableElement overridingMethod, boolean issueConflictWarning, 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
    • createTreeAnnotator

      protected TreeAnnotator createTreeAnnotator()
      Description copied from class: GenericAnnotatedTypeFactory
      Returns a TreeAnnotator that adds annotations to a type based on the contents of a tree.

      The default tree annotator is a ListTreeAnnotator of the following:

      1. PropagationTreeAnnotator: Propagates annotations from subtrees
      2. LiteralTreeAnnotator: Adds annotations based on QualifierForLiterals meta-annotations
      3. DependentTypesTreeAnnotator: Adapts dependent annotations based on context

      Subclasses may override this method to specify additional tree annotators, for example:

       new ListTreeAnnotator(super.createTreeAnnotator(), new KeyLookupTreeAnnotator(this));
       
      Overrides:
      createTreeAnnotator in class GenericAnnotatedTypeFactory<CFValue,CFStore,CFTransfer,CFAnalysis>
      Returns:
      a tree annotator
    • constrainLambdaToUI

      public void constrainLambdaToUI(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(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.