generator/src/org/immutables/generator/SourceOrdering.java
public static AccessorProvider getAllAccessorsProvider(
      final Elements elements,
      final Types types,
      final TypeElement originatingType) {

    class CollectedOrdering extends Ordering<Element> {
      class Intratype {
        final String inType;
        final Ordering<String> ordering;
        final int rank;

        Intratype(String inType, int rank, List<String> accessors) {
          this.inType = inType;
          this.rank = rank;
          this.ordering = Ordering.explicit(accessors);
        }

        @Override
        public String toString() {
          return "(<=> " + inType + ", " + rank + ", " + ordering + ")";
        }
      }

      final Map<String, Intratype> accessorOrderings = new LinkedHashMap<>();
      final Set<TypeElement> linearizedTypes = new LinkedHashSet<>();
      final ArrayListMultimap<String, TypeElement> accessorMapping = ArrayListMultimap.create();

      CollectedOrdering() {
        traverse(originatingType);
        collectAccessors();
      }

      void traverse(@Nullable TypeElement element) {
        if (element == null || isJavaLangObject(element)) {
          return;
        }
        for (TypeMirror implementedInterface : element.getInterfaces()) {
          traverse(toElement(implementedInterface));
        }
        if (element.getKind().isClass()) {
          // collectEnclosing(element);
          traverse(toElement(element.getSuperclass()));
        }
        // we add this after so we start with the deepest
        linearizedTypes.add(element);
      }

      @Nullable
      TypeElement toElement(TypeMirror type) {
        if (type.getKind() == TypeKind.DECLARED) {
          return (TypeElement) ((DeclaredType) type).asElement();
        }
        return null;
      }

      void collectAccessors() {
        int i = 0;
        for (TypeElement type : linearizedTypes) {
          List<String> accessorsInType =
              FluentIterable.from(SourceOrdering.getEnclosedElements(type))
                  .filter(IsParameterlessNonstaticNonobject.PREDICATE)
                  .transform(ToSimpleName.FUNCTION)
                  .toList();

          String typeTag = type.getSimpleName().toString();
          Intratype intratype = new Intratype(typeTag, i++, accessorsInType);

          for (String name : accessorsInType) {
            // we override accessors by the ones redeclared in later types
            accessorMapping.put(name, type);
            accessorOrderings.put(name, intratype);
          }
        }
      }

      @Override
      public int compare(Element left, Element right) {
        String leftKey = ToSimpleName.FUNCTION.apply(left);
        String rightKey = ToSimpleName.FUNCTION.apply(right);
        Intratype leftIntratype = accessorOrderings.get(leftKey);
        Intratype rightIntratype = accessorOrderings.get(rightKey);
        return leftIntratype == rightIntratype
            ? leftIntratype.ordering.compare(leftKey, rightKey)
            : Integer.compare(leftIntratype.rank, rightIntratype.rank);
      }
    }

    final CollectedOrdering ordering = new CollectedOrdering();

    final ImmutableList<ExecutableElement> sortedList =
        ordering.immutableSortedCopy(
            disambiguateMethods(ElementFilter.methodsIn(
                elements.getAllMembers(originatingType))));

    return new AccessorProvider() {
      ImmutableListMultimap<String, TypeElement> accessorMapping =
          ImmutableListMultimap.copyOf(ordering.accessorMapping);

      @Override
      public ImmutableListMultimap<String, TypeElement> accessorMapping() {
        return accessorMapping;
      }

      @Override
      public ImmutableList<ExecutableElement> get() {
        return sortedList;
      }
    };
  }
public static AccessorProvider getAllAccessorsProvider(
      final Elements elements,
      final Types types,
      final TypeElement originatingType) {

    class CollectedOrdering extends Ordering<Element> {
      class Intratype {
        final String inType;
        final Ordering<String> ordering;
        final int rank;

        Intratype(String inType, int rank, List<String> accessors) {
          this.inType = inType;
          this.rank = rank;
          this.ordering = Ordering.explicit(accessors);
        }

        @Override
        public String toString() {
          return "(<=> " + inType + ", " + rank + ", " + ordering + ")";
        }
      }

      final Map<String, Intratype> accessorOrderings = new LinkedHashMap<>();
      final Set<TypeElement> linearizedTypes = new LinkedHashSet<>();
      final ArrayListMultimap<String, TypeElement> accessorMapping = ArrayListMultimap.create();

      CollectedOrdering() {
        traverse(originatingType);
        collectAccessors();
      }

      void traverse(@Nullable TypeElement element) {
        if (element == null || isJavaLangObject(element)) {
          return;
        }
        for (TypeMirror implementedInterface : element.getInterfaces()) {
          traverse(toElement(implementedInterface));
        }
        if (element.getKind().isClass()) {
          // collectEnclosing(element);
          traverse(toElement(element.getSuperclass()));
        }
        // we add this after so we start with the deepest
        linearizedTypes.add(element);
      }

      @Nullable
      TypeElement toElement(TypeMirror type) {
        if (type.getKind() == TypeKind.DECLARED) {
          return (TypeElement) ((DeclaredType) type).asElement();
        }
        return null;
      }

      void collectAccessors() {
        int i = 0;
        for (TypeElement type : linearizedTypes) {
          List<String> accessorsInType =
              FluentIterable.from(SourceOrdering.getEnclosedElements(type))
                  .filter(IsParameterlessNonstaticNonobject.PREDICATE)
                  .transform(ToSimpleName.FUNCTION)
                  .toList();

          String typeTag = type.getSimpleName().toString();
          Intratype intratype = new Intratype(typeTag, i++, accessorsInType);

          for (String name : accessorsInType) {
            // we override accessors by the ones redeclared in later types
            accessorMapping.put(name, type);
            accessorOrderings.put(name, intratype);
          }
        }
      }

      @Override
      public int compare(Element left, Element right) {
        String leftKey = ToSimpleName.FUNCTION.apply(left);
        String rightKey = ToSimpleName.FUNCTION.apply(right);
        Intratype leftIntratype = accessorOrderings.get(leftKey);
        Intratype rightIntratype = accessorOrderings.get(rightKey);
        return leftIntratype == rightIntratype
            ? leftIntratype.ordering.compare(leftKey, rightKey)
            : Integer.compare(leftIntratype.rank, rightIntratype.rank);
      }
    }

    final CollectedOrdering ordering = new CollectedOrdering();

    final ImmutableList<ExecutableElement> sortedList =
        ordering.immutableSortedCopy(
            disambiguateMethods(ElementFilter.methodsIn(
                elements.getAllMembers(originatingType))));

    return new AccessorProvider() {
      ImmutableListMultimap<String, TypeElement> accessorMapping =
          ImmutableListMultimap.copyOf(ordering.accessorMapping);

      @Override
      public ImmutableListMultimap<String, TypeElement> accessorMapping() {
        return accessorMapping;
      }

      @Override
      public ImmutableList<ExecutableElement> get() {
        return sortedList;
      }
    };
  }
public static AccessorProvider getAllAccessorsProvider ( final Elements elements , final Types types , final TypeElement originatingType ) { class CollectedOrdering extends Ordering < Element > { class Intratype { final String inType ; final Ordering < String > ordering ; final int rank ; Intratype ( String inType , int rank , List < String > accessors ) { this . inType = inType ; this . rank = rank ; this . ordering = Ordering . explicit ( accessors ) ; } @ Override public String toString ( ) { return "(<=> " + inType + ", " + rank + ", " + ordering + ")" ; } } final Map < String , Intratype > accessorOrderings = new LinkedHashMap <> ( ) ; final Set < TypeElement > linearizedTypes = new LinkedHashSet <> ( ) ; final ArrayListMultimap < String , TypeElement > accessorMapping = ArrayListMultimap . create ( ) ; CollectedOrdering ( ) { traverse ( originatingType ) ; collectAccessors ( ) ; } void traverse ( @ Nullable TypeElement element ) { if ( element == null || isJavaLangObject ( element ) ) { return ; } for ( TypeMirror implementedInterface : element . getInterfaces ( ) ) { traverse ( toElement ( implementedInterface ) ) ; } if ( element . getKind ( ) . isClass ( ) ) { // collectEnclosing(element); traverse ( toElement ( element . getSuperclass ( ) ) ) ; } // we add this after so we start with the deepest linearizedTypes . add ( element ) ; } @ Nullable TypeElement toElement ( TypeMirror type ) { if ( type . getKind ( ) == TypeKind . DECLARED ) { return ( TypeElement ) ( ( DeclaredType ) type ) . asElement ( ) ; } return null ; } void collectAccessors ( ) { int i = 0 ; for ( TypeElement type : linearizedTypes ) { List < String > accessorsInType = FluentIterable . from ( SourceOrdering . getEnclosedElements ( type ) ) . filter ( IsParameterlessNonstaticNonobject . PREDICATE ) . transform ( ToSimpleName . FUNCTION ) . toList ( ) ; String typeTag = type . getSimpleName ( ) . toString ( ) ; Intratype intratype = new Intratype ( typeTag , i ++ , accessorsInType ) ; for ( String name : accessorsInType ) { // we override accessors by the ones redeclared in later types accessorMapping . put ( name , type ) ; accessorOrderings . put ( name , intratype ) ; } } } @ Override public int compare ( Element left , Element right ) { String leftKey = ToSimpleName . FUNCTION . apply ( left ) ; String rightKey = ToSimpleName . FUNCTION . apply ( right ) ; Intratype leftIntratype = accessorOrderings . get ( leftKey ) ; Intratype rightIntratype = accessorOrderings . get ( rightKey ) ; return leftIntratype == rightIntratype ? leftIntratype . ordering . compare ( leftKey , rightKey ) : Integer . compare ( leftIntratype . rank , rightIntratype . rank ) ; } } final CollectedOrdering ordering = new CollectedOrdering ( ) ; final ImmutableList < ExecutableElement > sortedList = ordering . immutableSortedCopy ( disambiguateMethods ( ElementFilter . methodsIn ( elements . getAllMembers ( originatingType ) ) ) ) ; return new AccessorProvider ( ) { ImmutableListMultimap < String , TypeElement > accessorMapping = ImmutableListMultimap . copyOf ( ordering . accessorMapping ) ; @ Override public ImmutableListMultimap < String , TypeElement > accessorMapping ( ) { return accessorMapping ; } @ Override public ImmutableList < ExecutableElement > get ( ) { return sortedList ; } } ; }
While we have {@link SourceOrdering}, there's still a problem: We have inheritance hierarchy
and
we want to have all defined or inherited accessors returned as members of target type, like
{@link Elements#getAllMembers(TypeElement)}, but we need to have them properly and stably
sorted.
This implementation doesn't try to correctly resolve order for accessors inherited from
different supertypes(interfaces), just something that stable and reasonable wrt source ordering
without handling complex cases.
@param elements the elements utility
@param types the types utility
@param originatingType the type to traverse
@return provider of all accessors in source order and mapping
While we have {