1 /* 2 * Copyright (C) 2015 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 com.google.common.truth.Truth.assertThat; 20 21 import androidx.room.compiler.processing.XElement; 22 import androidx.room.compiler.processing.XProcessingEnv; 23 import androidx.room.compiler.processing.XProcessingStep; 24 import androidx.room.compiler.processing.XTypeElement; 25 import androidx.room.compiler.processing.util.Source; 26 import com.google.common.collect.ImmutableSet; 27 import dagger.internal.codegen.validation.ValidationReport; 28 import dagger.testing.compile.CompilerTests; 29 import java.util.Map; 30 import java.util.Set; 31 import org.junit.Test; 32 import org.junit.runner.RunWith; 33 import org.junit.runners.JUnit4; 34 35 @RunWith(JUnit4.class) 36 public class ValidationReportTest { 37 private static final Source TEST_CLASS_FILE = 38 CompilerTests.javaSource( 39 "test.TestClass", 40 "package test;", 41 "", 42 "import javax.inject.Singleton;", 43 "", 44 "@Singleton", 45 "final class TestClass {}"); 46 47 @Test basicReport()48 public void basicReport() { 49 CompilerTests.daggerCompiler(TEST_CLASS_FILE) 50 .withProcessingSteps( 51 () -> new SimpleTestStep() { 52 @Override 53 void test() { 54 ValidationReport.about(getTypeElement("test.TestClass")) 55 .addError("simple error") 56 .build() 57 .printMessagesTo(processingEnv.getMessager()); 58 } 59 }) 60 .compile( 61 subject -> { 62 subject.hasErrorCount(1); 63 subject.hasErrorContaining("simple error") 64 .onSource(TEST_CLASS_FILE) 65 .onLine(6); 66 }); 67 } 68 69 @Test messageOnDifferentElement()70 public void messageOnDifferentElement() { 71 CompilerTests.daggerCompiler(TEST_CLASS_FILE) 72 .withProcessingSteps( 73 () -> new SimpleTestStep() { 74 @Override 75 void test() { 76 ValidationReport.about(getTypeElement("test.TestClass")) 77 .addError("simple error", getTypeElement(String.class)) 78 .build() 79 .printMessagesTo(processingEnv.getMessager()); 80 } 81 }) 82 .compile( 83 subject -> { 84 subject.hasErrorCount(1); 85 // TODO(b/249298461): The String types should match between javac and ksp. 86 switch (CompilerTests.backend(subject)) { 87 case JAVAC: 88 subject.hasErrorContaining("[java.lang.String] simple error") 89 .onSource(TEST_CLASS_FILE) 90 .onLine(6); 91 break; 92 case KSP: 93 subject.hasErrorContaining("[kotlin.String] simple error") 94 .onSource(TEST_CLASS_FILE) 95 .onLine(6); 96 } 97 }); 98 } 99 100 @Test subreport()101 public void subreport() { 102 CompilerTests.daggerCompiler(TEST_CLASS_FILE) 103 .withProcessingSteps( 104 () -> new SimpleTestStep() { 105 @Override 106 void test() { 107 ValidationReport parentReport = 108 ValidationReport.about(getTypeElement(String.class)) 109 .addSubreport( 110 ValidationReport.about(getTypeElement("test.TestClass")) 111 .addError("simple error") 112 .build()) 113 .build(); 114 assertThat(parentReport.isClean()).isFalse(); 115 parentReport.printMessagesTo(processingEnv.getMessager()); 116 } 117 }) 118 .compile( 119 subject -> { 120 subject.hasErrorCount(1); 121 subject.hasErrorContaining("simple error") 122 .onSource(TEST_CLASS_FILE) 123 .onLine(6); 124 }); 125 } 126 127 private abstract static class SimpleTestStep implements XProcessingStep { 128 protected XProcessingEnv processingEnv; 129 130 @Override annotations()131 public final ImmutableSet<String> annotations() { 132 // TODO(b/249322175): Replace this with "*" after this bug is fixed. 133 // For now, we just trigger off of annotations in the other sources in the test, but ideally 134 // this should support "*" similar to javac's Processor. 135 return ImmutableSet.of("javax.inject.Singleton"); 136 } 137 138 @Override process( XProcessingEnv env, Map<String, ? extends Set<? extends XElement>> elementsByAnnotation)139 public ImmutableSet<XElement> process( 140 XProcessingEnv env, Map<String, ? extends Set<? extends XElement>> elementsByAnnotation) { 141 this.processingEnv = env; 142 test(); 143 return ImmutableSet.of(); 144 } 145 146 @Override processOver( XProcessingEnv env, Map<String, ? extends Set<? extends XElement>> elementsByAnnotation)147 public void processOver( 148 XProcessingEnv env, Map<String, ? extends Set<? extends XElement>> elementsByAnnotation) {} 149 getTypeElement(Class<?> clazz)150 protected final XTypeElement getTypeElement(Class<?> clazz) { 151 return getTypeElement(clazz.getCanonicalName()); 152 } 153 getTypeElement(String canonicalName)154 protected final XTypeElement getTypeElement(String canonicalName) { 155 return processingEnv.requireTypeElement(canonicalName); 156 } 157 test()158 abstract void test(); 159 } 160 } 161