<commit_before>package com.ryanharter.auto.value.gson.factory;

import com.google.auto.common.GeneratedAnnotations;
import com.google.auto.common.Visibility;
import com.google.auto.service.AutoService;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.ryanharter.auto.value.gson.AutoValueGsonExtension;
import com.ryanharter.auto.value.gson.GsonTypeAdapterFactory;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;

import static com.google.auto.common.MoreElements.getPackage;
import static com.ryanharter.auto.value.gson.AutoValueGsonExtension.GENERATED_COMMENTS;
import static java.util.stream.Collectors.toList;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
import static javax.tools.Diagnostic.Kind.ERROR;
import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.AGGREGATING;

/**
 * Generates a Gson {@link TypeAdapterFactory} that adapts all {@link AutoValue} annotated
 * Gson serializable classes.
 */
@IncrementalAnnotationProcessor(AGGREGATING)
@AutoService(Processor.class)
public class AutoValueGsonAdapterFactoryProcessor extends AbstractProcessor {

  private Types typeUtils;
  private Elements elementUtils;

  @Override public Set<String> getSupportedAnnotationTypes() {
    return ImmutableSet.of(AutoValue.class.getName(), GsonTypeAdapterFactory.class.getName());
  }

  @Override public SourceVersion getSupportedSourceVersion() {
    return SourceVersion.latestSupported();
  }

  @Override public synchronized void init(ProcessingEnvironment processingEnv) {
    super.init(processingEnv);
    typeUtils = processingEnv.getTypeUtils();
    elementUtils = processingEnv.getElementUtils();
  }

  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    Set<? extends Element> adapterFactories = roundEnv.getElementsAnnotatedWith(GsonTypeAdapterFactory.class);
    if (adapterFactories.isEmpty()) {
      return false;
    }
    Set<? extends Element> autoValueElements = roundEnv.getElementsAnnotatedWith(AutoValue.class);
    List<TypeElement> elements = autoValueElements.stream()
        .map(e -> (TypeElement) e)
        .filter(e -> AutoValueGsonExtension.isApplicable(e, processingEnv.getMessager()))
        .sorted((o1, o2) -> {
          final String o1Name = classNameOf(o1, ".");
          final String o2Name = classNameOf(o2, ".");
          return o1Name.compareTo(o2Name);
        })
        .collect(Collectors.toList());

    if (elements.isEmpty()) {
      Element reportableElement = adapterFactories.iterator().next();
      if (!autoValueElements.isEmpty()) {
        processingEnv.getMessager().printMessage(ERROR,
            "Failed to write TypeAdapterFactory: Cannot generate class for this "
                + "@GsonTypeAdapterFactory-annotated element because while @AutoValue-annotated "
                + "elements were found on the compilation classpath, none of them contain a "
                + "requisite public static TypeAdapter-returning signature method to opt in to "
                + "being included in @GsonTypeAdapterFactory-generated factories. See the "
                + "auto-value-gson README for more information on declaring these.",
            reportableElement);
      } else {
        processingEnv.getMessager().printMessage(ERROR,
            "Failed to write TypeAdapterFactory: Cannot generate class for this "
                + "@GsonTypeAdapterFactory-annotated element because no @AutoValue-annotated "
                + "elements were found on the compilation classpath.",
            reportableElement);
      }<commit_msg>use canonical class name for sorting elements (#260)<commit_after>package com.ryanharter.auto.value.gson.factory;

import com.google.auto.common.GeneratedAnnotations;
import com.google.auto.common.Visibility;
import com.google.auto.service.AutoService;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.ryanharter.auto.value.gson.AutoValueGsonExtension;
import com.ryanharter.auto.value.gson.GsonTypeAdapterFactory;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;

import static com.google.auto.common.MoreElements.getPackage;
import static com.ryanharter.auto.value.gson.AutoValueGsonExtension.GENERATED_COMMENTS;
import static java.util.stream.Collectors.toList;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
import static javax.tools.Diagnostic.Kind.ERROR;
import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.AGGREGATING;

/**
 * Generates a Gson {@link TypeAdapterFactory} that adapts all {@link AutoValue} annotated
 * Gson serializable classes.
 */
@IncrementalAnnotationProcessor(AGGREGATING)
@AutoService(Processor.class)
public class AutoValueGsonAdapterFactoryProcessor extends AbstractProcessor {

  private Types typeUtils;
  private Elements elementUtils;

  @Override public Set<String> getSupportedAnnotationTypes() {
    return ImmutableSet.of(AutoValue.class.getName(), GsonTypeAdapterFactory.class.getName());
  }

  @Override public SourceVersion getSupportedSourceVersion() {
    return SourceVersion.latestSupported();
  }

  @Override public synchronized void init(ProcessingEnvironment processingEnv) {
    super.init(processingEnv);
    typeUtils = processingEnv.getTypeUtils();
    elementUtils = processingEnv.getElementUtils();
  }

  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    Set<? extends Element> adapterFactories = roundEnv.getElementsAnnotatedWith(GsonTypeAdapterFactory.class);
    if (adapterFactories.isEmpty()) {
      return false;
    }
    Set<? extends Element> autoValueElements = roundEnv.getElementsAnnotatedWith(AutoValue.class);
    List<TypeElement> elements = autoValueElements.stream()
        .map(e -> (TypeElement) e)
        .filter(e -> AutoValueGsonExtension.isApplicable(e, processingEnv.getMessager()))
        .sorted((o1, o2) -> {
          final String o1Name = ClassName.get(o1).canonicalName();
          final String o2Name = ClassName.get(o2).canonicalName();
          return o1Name.compareTo(o2Name);
        })
        .collect(Collectors.toList());

    if (elements.isEmpty()) {
      Element reportableElement = adapterFactories.iterator().next();
      if (!autoValueElements.isEmpty()) {
        processingEnv.getMessager().printMessage(ERROR,
            "Failed to write TypeAdapterFactory: Cannot generate class for this "
                + "@GsonTypeAdapterFactory-annotated element because while @AutoValue-annotated "
                + "elements were found on the compilation classpath, none of them contain a "
                + "requisite public static TypeAdapter-returning signature method to opt in to "
                + "being included in @GsonTypeAdapterFactory-generated factories. See the "
                + "auto-value-gson README for more information on declaring these.",
            reportableElement);
      } else {
        processingEnv.getMessager().printMessage(ERROR,
            "Failed to write TypeAdapterFactory: Cannot generate class for this "
                + "@GsonTypeAdapterFactory-annotated element because no @AutoValue-annotated "
                + "elements were found on the compilation classpath.",
            reportableElement);
      }
{'fraction_non_alphanumeric': 0.09591625011789116, 'fraction_numerical': 0.0017919456757521455, 'mean_word_length': 4.598732840549102, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2776329', 'n_tokens_mistral': 2972, 'n_tokens_neox': 2875, 'n_words': 603}