Class Analyser


  • class Analyser
    extends java.lang.Object
    Analyses a FreeBuilder datatype type, returning a GeneratedType for a Builder superclass derived from its API.

    Any deviations from the FreeBuilder spec in the user's class will result in errors being issued, but unless code generation is totally impossible, a type will still be returned. This allows the user to extend an existing type without worrying that a mistake will cause compiler errors in all dependent code—which would make it very hard to find the real error.

    • Field Summary

      Fields 
      Modifier and Type Field Description
      private static java.lang.String BUILDER_SIMPLE_NAME_TEMPLATE  
      private static javax.lang.model.util.SimpleTypeVisitor8<java.lang.Boolean,​?> CAST_IS_FULLY_CHECKED
      Visitor that returns true if a cast to the visited type is guaranteed to be fully checked at runtime.
      private javax.lang.model.util.Elements elements  
      private javax.annotation.processing.ProcessingEnvironment env  
      private static javax.lang.model.util.SimpleTypeVisitor8<java.lang.Boolean,​?> IS_UNBOUNDED_WILDCARD
      Visitor that returns true if the visited type is an unbounded wildcard, i.e.
      private javax.annotation.processing.Messager messager  
      private javax.lang.model.util.Types types  
      private static java.lang.String USER_BUILDER_NAME  
    • Constructor Summary

      Constructors 
      Constructor Description
      Analyser​(javax.annotation.processing.ProcessingEnvironment env, javax.annotation.processing.Messager messager)  
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      private void addPropertyData​(Property.Builder propertyBuilder, javax.lang.model.element.TypeElement valueType, javax.lang.model.element.ExecutableElement method, java.util.Optional<JacksonSupport> jacksonSupport)
      Introspects method, as found on valueType.
      (package private) GeneratedType analyse​(javax.lang.model.element.TypeElement type)
      Returns a Builder GeneratedType for type.
      private static java.lang.String camelCaseToAllCaps​(java.lang.String camelCase)
      Converts camelCaseConvention to ALL_CAPS_CONVENTION.
      private Datatype.Builder constructionAndExtension​(javax.lang.model.type.DeclaredType builder)  
      private static PropertyCodeGenerator createCodeGenerator​(PropertyCodeGenerator.Config config)  
      private java.util.Map<Datatype.StandardMethod,​Datatype.UnderrideLevel> findUnderriddenMethods​(java.lang.Iterable<javax.lang.model.element.ExecutableElement> methods)
      Find any standard methods the user has 'underridden' in their type.
      private java.lang.String generatedBuilderSimpleName​(javax.lang.model.element.TypeElement type)
      Returns the simple name of the builder class that should be generated for the given type.
      private java.util.Set<java.lang.String> getMethodsInvokedInBuilderConstructor​(javax.lang.model.element.TypeElement builder)  
      private boolean hasToBuilderMethod​(javax.lang.model.type.DeclaredType builder, boolean isExtensible, java.lang.Iterable<javax.lang.model.element.ExecutableElement> methods)
      Find a toBuilder method, if the user has provided one.
      private java.util.function.Predicate<javax.lang.model.type.TypeMirror> isEqualTo​(java.lang.Class<?> cls)  
      private boolean isToBuilderMethod​(javax.lang.model.type.DeclaredType declaredType, javax.lang.model.element.ExecutableElement method)  
      private static boolean isUnderride​(javax.lang.model.element.ExecutableElement method)  
      private static java.util.Optional<Datatype.StandardMethod> maybeStandardMethod​(javax.lang.model.element.ExecutableElement method)
      Returns whether a method is one of the Datatype.StandardMethods, and if so, which.
      private java.util.Map<Property,​PropertyCodeGenerator> pickPropertyGenerators​(javax.lang.model.element.TypeElement type, Datatype datatype, javax.lang.model.type.DeclaredType builder, java.lang.Iterable<javax.lang.model.element.ExecutableElement> methods)  
      private java.util.Set<javax.lang.model.element.ExecutableElement> removeNonGetterMethods​(javax.lang.model.type.DeclaredType builder, java.lang.Iterable<javax.lang.model.element.ExecutableElement> methods)  
      private boolean shouldBuilderBeSerializable​(javax.lang.model.type.DeclaredType builder)  
      private java.util.Optional<javax.lang.model.type.DeclaredType> tryFindBuilder​(QualifiedName superclass, javax.lang.model.element.TypeElement valueType)
      Looks for a nested type in valueType called Builder, and verifies it extends the autogenerated superclass.
      private void verifyType​(javax.lang.model.element.TypeElement type, javax.lang.model.element.PackageElement pkg)
      Basic sanity-checking to ensure we can fulfil the @FreeBuilder contract for this type.
      private void verifyTypeIsConstructible​(javax.lang.model.element.TypeElement type)
      Issues an error if type does not have a package-visible no-args constructor.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • BUILDER_SIMPLE_NAME_TEMPLATE

        private static final java.lang.String BUILDER_SIMPLE_NAME_TEMPLATE
        See Also:
        Constant Field Values
      • USER_BUILDER_NAME

        private static final java.lang.String USER_BUILDER_NAME
        See Also:
        Constant Field Values
      • env

        private final javax.annotation.processing.ProcessingEnvironment env
      • elements

        private final javax.lang.model.util.Elements elements
      • messager

        private final javax.annotation.processing.Messager messager
      • types

        private final javax.lang.model.util.Types types
      • CAST_IS_FULLY_CHECKED

        private static final javax.lang.model.util.SimpleTypeVisitor8<java.lang.Boolean,​?> CAST_IS_FULLY_CHECKED
        Visitor that returns true if a cast to the visited type is guaranteed to be fully checked at runtime. This is true for any type that is non-generic, raw, or parameterized with unbounded wildcards, such as Integer, List or Map<?, ?>.
      • IS_UNBOUNDED_WILDCARD

        private static final javax.lang.model.util.SimpleTypeVisitor8<java.lang.Boolean,​?> IS_UNBOUNDED_WILDCARD
        Visitor that returns true if the visited type is an unbounded wildcard, i.e. <?>.
    • Constructor Detail

      • Analyser

        Analyser​(javax.annotation.processing.ProcessingEnvironment env,
                 javax.annotation.processing.Messager messager)
    • Method Detail

      • findUnderriddenMethods

        private java.util.Map<Datatype.StandardMethod,​Datatype.UnderrideLevel> findUnderriddenMethods​(java.lang.Iterable<javax.lang.model.element.ExecutableElement> methods)
        Find any standard methods the user has 'underridden' in their type.
      • hasToBuilderMethod

        private boolean hasToBuilderMethod​(javax.lang.model.type.DeclaredType builder,
                                           boolean isExtensible,
                                           java.lang.Iterable<javax.lang.model.element.ExecutableElement> methods)
        Find a toBuilder method, if the user has provided one.
      • isToBuilderMethod

        private boolean isToBuilderMethod​(javax.lang.model.type.DeclaredType declaredType,
                                          javax.lang.model.element.ExecutableElement method)
      • removeNonGetterMethods

        private java.util.Set<javax.lang.model.element.ExecutableElement> removeNonGetterMethods​(javax.lang.model.type.DeclaredType builder,
                                                                                                 java.lang.Iterable<javax.lang.model.element.ExecutableElement> methods)
      • isUnderride

        private static boolean isUnderride​(javax.lang.model.element.ExecutableElement method)
      • tryFindBuilder

        private java.util.Optional<javax.lang.model.type.DeclaredType> tryFindBuilder​(QualifiedName superclass,
                                                                                      javax.lang.model.element.TypeElement valueType)
        Looks for a nested type in valueType called Builder, and verifies it extends the autogenerated superclass.

        If the value type is generic, the builder type must match, and the returned DeclaredType will be parameterized with the type variables from the value type, not the builder. (This makes type checking massively easier.)

        Issues an error if the wrong type is being subclassed—a typical copy-and-paste error when renaming an existing @FreeBuilder type, or using one as a template.

      • constructionAndExtension

        private Datatype.Builder constructionAndExtension​(javax.lang.model.type.DeclaredType builder)
      • pickPropertyGenerators

        private java.util.Map<Property,​PropertyCodeGenerator> pickPropertyGenerators​(javax.lang.model.element.TypeElement type,
                                                                                           Datatype datatype,
                                                                                           javax.lang.model.type.DeclaredType builder,
                                                                                           java.lang.Iterable<javax.lang.model.element.ExecutableElement> methods)
      • getMethodsInvokedInBuilderConstructor

        private java.util.Set<java.lang.String> getMethodsInvokedInBuilderConstructor​(javax.lang.model.element.TypeElement builder)
      • addPropertyData

        private void addPropertyData​(Property.Builder propertyBuilder,
                                     javax.lang.model.element.TypeElement valueType,
                                     javax.lang.model.element.ExecutableElement method,
                                     java.util.Optional<JacksonSupport> jacksonSupport)
        Introspects method, as found on valueType.
      • generatedBuilderSimpleName

        private java.lang.String generatedBuilderSimpleName​(javax.lang.model.element.TypeElement type)
        Returns the simple name of the builder class that should be generated for the given type.

        This is simply the BUILDER_SIMPLE_NAME_TEMPLATE with the original type name substituted in. (If the original type is nested, its enclosing classes will be included, separated with underscores, to ensure uniqueness.)

      • shouldBuilderBeSerializable

        private boolean shouldBuilderBeSerializable​(javax.lang.model.type.DeclaredType builder)
      • maybeStandardMethod

        private static java.util.Optional<Datatype.StandardMethod> maybeStandardMethod​(javax.lang.model.element.ExecutableElement method)
        Returns whether a method is one of the Datatype.StandardMethods, and if so, which.
      • camelCaseToAllCaps

        private static java.lang.String camelCaseToAllCaps​(java.lang.String camelCase)
        Converts camelCaseConvention to ALL_CAPS_CONVENTION.
      • isEqualTo

        private java.util.function.Predicate<javax.lang.model.type.TypeMirror> isEqualTo​(java.lang.Class<?> cls)