1 /* 2 * Copyright (C) 2018 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.internal.codegen; 18 19 import static dagger.internal.codegen.Compilers.compilerWithOptions; 20 import static dagger.internal.codegen.base.ComponentCreatorKind.FACTORY; 21 import static dagger.internal.codegen.binding.ErrorMessages.creatorMessagesFor; 22 import static java.util.stream.Collectors.joining; 23 24 import com.google.testing.compile.Compilation; 25 import com.google.testing.compile.JavaFileObjects; 26 import dagger.internal.codegen.base.ComponentCreatorAnnotation; 27 import dagger.internal.codegen.base.ComponentCreatorKind; 28 import dagger.internal.codegen.binding.ErrorMessages; 29 import java.util.Arrays; 30 import java.util.stream.Stream; 31 import javax.tools.JavaFileObject; 32 33 /** 34 * Base class for component creator codegen tests that are written in terms of builders and 35 * transformed, either by automatic string processing or using a {@code JavaFileBuilder}, to test 36 * factories as well. 37 */ 38 abstract class ComponentCreatorTestHelper { 39 40 private final CompilerMode compilerMode; 41 42 protected final ComponentCreatorKind creatorKind; 43 protected final ErrorMessages.ComponentCreatorMessages messages; 44 ComponentCreatorTestHelper( CompilerMode compilerMode, ComponentCreatorAnnotation componentCreatorAnnotation)45 ComponentCreatorTestHelper( 46 CompilerMode compilerMode, ComponentCreatorAnnotation componentCreatorAnnotation) { 47 this.compilerMode = compilerMode; 48 this.creatorKind = componentCreatorAnnotation.creatorKind(); 49 this.messages = creatorMessagesFor(componentCreatorAnnotation); 50 } 51 52 // For tests where code for both builders and factories can be largely equivalent, i.e. when there 53 // is nothing to set, just preprocess the lines to change code written for a builder to code for a 54 // factory. 55 // For more complicated code, use a JavaFileBuilder to add different code depending on the creator 56 // kind. 57 58 /** 59 * Processes the given lines, replacing builder-related names with factory-related names if the 60 * creator kind is {@code FACTORY}. 61 */ process(String... lines)62 String process(String... lines) { 63 Stream<String> stream = Arrays.stream(lines); 64 if (creatorKind.equals(FACTORY)) { 65 stream = 66 stream.map( 67 line -> 68 line.replace("Builder", "Factory") 69 .replace("builder", "factory") 70 .replace("build", "createComponent")); 71 } 72 return stream.collect(joining("\n")); 73 } 74 75 /** 76 * Returns a Java file with the {@linkplain #process(String...)} processed} versions of the given 77 * lines. 78 */ preprocessedJavaFile(String fullyQualifiedName, String... lines)79 JavaFileObject preprocessedJavaFile(String fullyQualifiedName, String... lines) { 80 return JavaFileObjects.forSourceString(fullyQualifiedName, process(lines)); 81 } 82 83 /** Returns a file builder for the current creator kind. */ javaFileBuilder(String qualifiedName)84 JavaFileBuilder javaFileBuilder(String qualifiedName) { 85 return new JavaFileBuilder(qualifiedName).withSettings(compilerMode, creatorKind); 86 } 87 88 /** Compiles the given files with the set compiler mode's javacopts. */ compile(JavaFileObject... files)89 Compilation compile(JavaFileObject... files) { 90 return compilerWithOptions(compilerMode.javacopts()).compile(files); 91 } 92 } 93