package org.realityforge.arez.processor;

import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeVariableName;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;

final class ProcessorUtil
{
  private ProcessorUtil()
  {
  }

  @Nonnull
  static List<TypeVariableName> getTypeArgumentsAsNames( @Nonnull final DeclaredType declaredType )
  {
    final List<TypeVariableName> variables = new ArrayList<>();
    for ( final TypeMirror argument : declaredType.getTypeArguments() )
    {
      variables.add( TypeVariableName.get( (TypeVariable) argument ) );
    }
    return variables;
  }

  @Nonnull
  static TypeName[] getTypeArgumentsAsTypeNames( @Nonnull final DeclaredType declaredType )
  {
    final List<TypeVariableName> variables = getTypeArgumentsAsNames( declaredType );
    return variables.toArray( new TypeName[ variables.size() ] );
  }
}

@@ -172,43 +172,279 @@
 l.Li
-st;%0Aimport javax.annotation.Nonnull
+nkedHashMap;%0Aimport java.util.List;%0Aimport java.util.Map;%0Aimport javax.annotation.Nonnull;%0Aimport javax.lang.model.element.Element;%0Aimport javax.lang.model.element.ElementKind;%0Aimport javax.lang.model.element.ExecutableElement;%0Aimport javax.lang.model.element.TypeElement
 ;%0Aim
@@ -1256,11 +1256,932 @@
 %5D );%0A  %7D
+%0A%0A  @Nonnull%0A  static List%3CExecutableElement%3E getMethods( @Nonnull final TypeElement element )%0A  %7B%0A    final Map%3CString, ExecutableElement%3E methodMap = new LinkedHashMap%3C%3E();%0A    enumerateMethods( element, methodMap );%0A    return new ArrayList%3C%3E( methodMap.values() );%0A  %7D%0A%0A  private static void enumerateMethods( @Nonnull final TypeElement element,%0A                                        @Nonnull final Map%3CString, ExecutableElement%3E methods )%0A  %7B%0A    for ( final TypeMirror interfaceType : element.getInterfaces() )%0A    %7B%0A      final TypeElement interfaceElement = (TypeElement) ( (DeclaredType) interfaceType ).asElement();%0A      enumerateMethods( interfaceElement, methods );%0A    %7D%0A    for ( final Element member : element.getEnclosedElements() )%0A    %7B%0A      if ( member.getKind() == ElementKind.METHOD )%0A      %7B%0A        methods.put( member.getSimpleName().toString(), (ExecutableElement) member );%0A      %7D%0A    %7D%0A  %7D
 %0A%7D%0A

Add method that collects all methods, ensuring defaults are replaced in required order