// Path: compiller/src/main/java/com/yheriatovych/reductor/processor/Env.java
// public class Env {
//     private final Types types;
//     private final Elements elements;
//     private final Messager messager;
//     private final Filer filer;
// 
//     public Env(Types types, Elements elements, Messager messager, Filer filer) {
//         this.types = types;
//         this.elements = elements;
//         this.messager = messager;
//         this.filer = filer;
//     }
// 
//     public void printError(Element element, String message, Object... args) {
//         printMessage(Diagnostic.Kind.ERROR, element, message, args);
//     }
// 
//     private void printMessage(Diagnostic.Kind level, Element element, String message, Object... args) {
//         messager.printMessage(level, String.format(message, args), element);
//     }
// 
//     public Types getTypes() {
//         return types;
//     }
// 
//     public Filer getFiler() {
//         return filer;
//     }
// 
//     public String getPackageName(Element element) {
//         return elements.getPackageOf(element).getQualifiedName().toString();
//     }
// 
//     public TypeMirror asType(Class<?> clazz) {
//         return elements.getTypeElement(clazz.getCanonicalName())
//                 .asType();
//     }
// 
//     public Elements getElements() {
//         return elements;
//     }
// }
// 
// Path: compiller/src/main/java/com/yheriatovych/reductor/processor/ValidationException.java
// public class ValidationException extends Exception {
//     private final Element element;
//     private final String message;
// 
//     public ValidationException(Element element, String message, Object... args) {
//         this.element = element;
//         this.message = String.format(message, args);
//     }
// 
//     public Element getElement() {
//         return element;
//     }
// 
//     @Override
//     public String getMessage() {
//         return message;
//     }
// 
// }


import com.google.auto.service.AutoService;
import com.google.auto.value.extension.AutoValueExtension;
import com.squareup.javapoet.ClassName;
import com.yheriatovych.reductor.annotations.CombinedState;
import com.yheriatovych.reductor.processor.Env;
import com.yheriatovych.reductor.processor.ValidationException;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
package com.yheriatovych.reductor.processor.combinedstate;



@AutoService(AutoValueExtension.class)
public class CombinedStateAutoValueExtension extends AutoValueExtension {
    @Override
    public String generateClass(Context context, String className, String classToExtend, boolean isFinal) {
        //So yeah, we are generating code in `applicable` method, not here
        //The reason for it: If we declare that some class is applicable for this extension, we need to contribute to
        //value class hierarchy. But we don't need it actually.
        //The only thing we need to do is to generate another class (Reducer)

        return null;
    }

    @Override
    public boolean applicable(Context context) {
        TypeElement typeElement = context.autoValueClass();
        boolean isApplicable = typeElement.getAnnotation(CombinedState.class) != null;
        if (isApplicable) {
            ProcessingEnvironment processingEnvironment = context.processingEnvironment();
// Path: compiller/src/main/java/com/yheriatovych/reductor/processor/Env.java
// public class Env {
//     private final Types types;
//     private final Elements elements;
//     private final Messager messager;
//     private final Filer filer;
// 
//     public Env(Types types, Elements elements, Messager messager, Filer filer) {
//         this.types = types;
//         this.elements = elements;
//         this.messager = messager;
//         this.filer = filer;
//     }
// 
//     public void printError(Element element, String message, Object... args) {
//         printMessage(Diagnostic.Kind.ERROR, element, message, args);
//     }
// 
//     private void printMessage(Diagnostic.Kind level, Element element, String message, Object... args) {
//         messager.printMessage(level, String.format(message, args), element);
//     }
// 
//     public Types getTypes() {
//         return types;
//     }
// 
//     public Filer getFiler() {
//         return filer;
//     }
// 
//     public String getPackageName(Element element) {
//         return elements.getPackageOf(element).getQualifiedName().toString();
//     }
// 
//     public TypeMirror asType(Class<?> clazz) {
//         return elements.getTypeElement(clazz.getCanonicalName())
//                 .asType();
//     }
// 
//     public Elements getElements() {
//         return elements;
//     }
// }
// 
// Path: compiller/src/main/java/com/yheriatovych/reductor/processor/ValidationException.java
// public class ValidationException extends Exception {
//     private final Element element;
//     private final String message;
// 
//     public ValidationException(Element element, String message, Object... args) {
//         this.element = element;
//         this.message = String.format(message, args);
//     }
// 
//     public Element getElement() {
//         return element;
//     }
// 
//     @Override
//     public String getMessage() {
//         return message;
//     }
// 
// }


// Path: compiller/src/main/java/com/yheriatovych/reductor/processor/combinedstate/CombinedStateAutoValueExtension.java
import com.google.auto.service.AutoService;
import com.google.auto.value.extension.AutoValueExtension;
import com.squareup.javapoet.ClassName;
import com.yheriatovych.reductor.annotations.CombinedState;
import com.yheriatovych.reductor.processor.Env;
import com.yheriatovych.reductor.processor.ValidationException;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;

package com.yheriatovych.reductor.processor.combinedstate;



@AutoService(AutoValueExtension.class)
public class CombinedStateAutoValueExtension extends AutoValueExtension {
    @Override
    public String generateClass(Context context, String className, String classToExtend, boolean isFinal) {
        //So yeah, we are generating code in `applicable` method, not here
        //The reason for it: If we declare that some class is applicable for this extension, we need to contribute to
        //value class hierarchy. But we don't need it actually.
        //The only thing we need to do is to generate another class (Reducer)

        return null;
    }

    @Override
    public boolean applicable(Context context) {
        TypeElement typeElement = context.autoValueClass();
        boolean isApplicable = typeElement.getAnnotation(CombinedState.class) != null;
        if (isApplicable) {
            ProcessingEnvironment processingEnvironment = context.processingEnvironment();
            Env env = new Env(processingEnvironment.getTypeUtils(), processingEnvironment.getElementUtils(), processingEnvironment.getMessager(), processingEnvironment.getFiler());