package org.reflection_no_reflection.processor;

import com.google.common.base.Joiner;
import com.google.testing.compile.JavaFileObjects;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.tools.JavaFileObject;
import org.junit.Before;
import org.junit.Test;
import org.reflection_no_reflection.Annotation;
import org.reflection_no_reflection.Class;
import org.reflection_no_reflection.Method;

import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.truth0.Truth.ASSERT;

public class MethodTest {

    private static Processor processor;

    @Before
    public void setup() {
        processor = new Processor();
    }

    @Test
    public void mapsSimpleAnnotatedMethod() throws ClassNotFoundException {
        JavaFileObject source = JavaFileObjects.forSourceString("test.Foo", Joiner.on('\n').join( //
                                                                                                  "package test;", //
                                                                                                  "public class Foo {",//
                                                                                                  "@Deprecated protected String s() {return \"foo\"; }", //
                                                                                                  "}" //
        ));

        configureProcessor(new String[] {"java.lang.Deprecated"});
        ASSERT.about(javaSource())
            .that(source)
            .processedWith(rnrProcessors())
            .compilesWithoutError();

        final Set<Class> annotatedClasses = processor.getAnnotatedClasses();
        assertThat(annotatedClasses.contains(new Class("test.Foo")), is(true));

        final Class aClass = Class.forName("test.Foo");
        assertThat(aClass.getMethods().size(), is(1));

        final Method method = (Method) aClass.getMethods().get(0);
        final Method expected = new Method(aClass, "s", new Class[0], new Class("java.lang.String"), new Class[0], Modifier.PROTECTED);
        assertThat(method, is(expected));
        assertThat(method.getModifiers(), is(Modifier.PROTECTED));

        final Annotation[] annotations = method.getDeclaredAnnotations();
        assertThat(annotations.length, is(1));

        final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated");
        assertThat(annotations[0].annotationType(), is(deprecatedAnnotationClass));
        assertThat(method.getAnnotation(deprecatedAnnotationClass).annotationType(), is(deprecatedAnnotationClass));
    }

    private void configureProcessor(String[] annotations) {
        processor.setAnnotatedClasses(new HashSet<>(Arrays.asList(annotations)));
    }

    static Iterable<? extends javax.annotation.processing.Processor> rnrProcessors() {
        return Arrays.asList(processor);
    }
}

@@ -2725,24 +2725,2330 @@
 s));%0A    %7D%0A%0A
+    @Test%0A    public void mapsSimpleAnnotatedMethodWithParams() throws ClassNotFoundException %7B%0A        JavaFileObject source = JavaFileObjects.forSourceString(%22test.Foo%22, Joiner.on('%5Cn').join( //%0A                                                                                                  %22package test;%22, //%0A                                                                                                  %22public class Foo %7B%22,//%0A                                                                                                  %22@Deprecated protected String s(String a) %7Breturn a; %7D%22, //%0A                                                                                                  %22%7D%22 //%0A        ));%0A%0A        configureProcessor(new String%5B%5D %7B%22java.lang.Deprecated%22%7D);%0A        ASSERT.about(javaSource())%0A            .that(source)%0A            .processedWith(rnrProcessors())%0A            .compilesWithoutError();%0A%0A        final Set%3CClass%3E annotatedClasses = processor.getAnnotatedClasses();%0A        assertThat(annotatedClasses.contains(new Class(%22test.Foo%22)), is(true));%0A%0A        final Class expectedParamType = Class.forName(%22java.lang.String%22);%0A        final Class aClass = Class.forName(%22test.Foo%22);%0A        assertThat(aClass.getMethods().size(), is(1));%0A%0A        final Method method = (Method) aClass.getMethods().get(0);%0A        final Method expected = new Method(aClass, %22s%22, new Class%5B%5D %7BexpectedParamType%7D, new Class(%22java.lang.String%22), new Class%5B0%5D, Modifier.PROTECTED);%0A        assertThat(method, is(expected));%0A        assertThat(method.getModifiers(), is(Modifier.PROTECTED));%0A%0A        final Annotation%5B%5D annotations = method.getDeclaredAnnotations();%0A        assertThat(annotations.length, is(1));%0A%0A        final Class deprecatedAnnotationClass = Class.forName(%22java.lang.Deprecated%22);%0A        assertThat(annotations%5B0%5D.annotationType(), is(deprecatedAnnotationClass));%0A        assertThat(method.getAnnotation(deprecatedAnnotationClass).annotationType(), is(deprecatedAnnotationClass));%0A%0A        final Class%3C?%3E%5B%5D paramTypes = method.getParameterTypes();%0A        assertThat(paramTypes.length, is(1));%0A        assertThat(paramTypes%5B0%5D, is(expectedParamType));%0A%0A        assertThat(method.getAnnotation(deprecatedAnnotationClass).annotationType(), is(deprecatedAnnotationClass));%0A    %7D%0A%0A
     private 

test params