package com.sora.util.akatsuki; import java.util.stream.Collectors; import java.util.stream.IntStream; import javax.lang.model.element.Modifier; import javax.tools.JavaFileObject; import javax.tools.StandardLocation; import org.junit.experimental.theories.DataPoint; import org.junit.experimental.theories.Theories; import org.junit.experimental.theories.Theory; import org.junit.runner.RunWith; import com.google.testing.compile.CompileTester.SuccessfulCompilationClause; import com.google.testing.compile.JavaFileObjects; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.TypeSpec.Builder; @RunWith(Theories.class) public class AkatsukiProcessorSourceNameTest extends IntegrationTestBase { static class GeneratedClassWithName { final JavaFileObject object; final String[] names; public GeneratedClassWithName(JavaFileObject object, String... names) { this.object = object; this.names = names; } } private static GeneratedClassWithName staticInnerClass(String... classes) { // maybe (String first, String...more) ? if (classes.length == 0) throw new IllegalArgumentException(""); String[] generatedClasses = new String[classes.length]; TypeSpec.Builder lastBuilder = null; for (int i = classes.length - 1; i >= 0; i--) { String clazz = classes[i]; final Builder currentBuilder = TypeSpec.classBuilder(clazz) .addModifiers((i == 0 ? Modifier.PUBLIC : Modifier.STATIC)) .addField(field(STRING_TYPE, clazz.toLowerCase(), Retained.class)); if (lastBuilder != null) { currentBuilder.addType(lastBuilder.build()); } // we generate static inner class names eg A.B -> A$B generatedClasses[i] = IntStream.range(0, i + 1).boxed().map(n -> classes[n]) .collect(Collectors.joining("$")); lastBuilder = currentBuilder; } final JavaFile file = JavaFile.builder(TEST_PACKAGE, lastBuilder.build()).build(); final JavaFileObject object = JavaFileObjects .forSourceString(TEST_PACKAGE + "." + classes[0], file.toString()); return new GeneratedClassWithName(object, generatedClasses); } @DataPoint public static GeneratedClassWithName simpleClass() { final JavaFileObject object = CodeGenUtils .createTestClass(field(STRING_TYPE, "foo", Retained.class)); return new GeneratedClassWithName(object, TEST_CLASS); } @DataPoint public static final GeneratedClassWithName STATIC_INNER_SIMPLE = staticInnerClass( "A", "B"); @DataPoint public static final GeneratedClassWithName STATIC_INNER_COMPLEX = staticInnerClass( "A", "B", "C", "D"); @Theory public void testSourceGeneratedWithCorrectName(GeneratedClassWithName generated) { final SuccessfulCompilationClause clause = assertTestClass(generated.object) .compilesWithoutError(); for (String name : generated.names) { clause.and().generatesFileNamed(StandardLocation.SOURCE_OUTPUT, TEST_PACKAGE, Internal.generateRetainerClassName(name) + ".java"); } } }