1*f585d8a3SJacky Wang /* 2*f585d8a3SJacky Wang * Copyright (C) 2021 The Dagger Authors. 3*f585d8a3SJacky Wang * 4*f585d8a3SJacky Wang * Licensed under the Apache License, Version 2.0 (the "License"); 5*f585d8a3SJacky Wang * you may not use this file except in compliance with the License. 6*f585d8a3SJacky Wang * You may obtain a copy of the License at 7*f585d8a3SJacky Wang * 8*f585d8a3SJacky Wang * http://www.apache.org/licenses/LICENSE-2.0 9*f585d8a3SJacky Wang * 10*f585d8a3SJacky Wang * Unless required by applicable law or agreed to in writing, software 11*f585d8a3SJacky Wang * distributed under the License is distributed on an "AS IS" BASIS, 12*f585d8a3SJacky Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*f585d8a3SJacky Wang * See the License for the specific language governing permissions and 14*f585d8a3SJacky Wang * limitations under the License. 15*f585d8a3SJacky Wang */ 16*f585d8a3SJacky Wang 17*f585d8a3SJacky Wang package dagger.internal.codegen; 18*f585d8a3SJacky Wang 19*f585d8a3SJacky Wang import static com.google.common.truth.Truth.assertThat; 20*f585d8a3SJacky Wang 21*f585d8a3SJacky Wang import androidx.room.compiler.processing.XProcessingEnv; 22*f585d8a3SJacky Wang import androidx.room.compiler.processing.util.Source; 23*f585d8a3SJacky Wang import com.google.common.collect.ImmutableMap; 24*f585d8a3SJacky Wang import dagger.testing.compile.CompilerTests; 25*f585d8a3SJacky Wang import org.junit.Test; 26*f585d8a3SJacky Wang import org.junit.runner.RunWith; 27*f585d8a3SJacky Wang import org.junit.runners.JUnit4; 28*f585d8a3SJacky Wang 29*f585d8a3SJacky Wang @RunWith(JUnit4.class) 30*f585d8a3SJacky Wang public final class UnresolvableDependencyTest { 31*f585d8a3SJacky Wang 32*f585d8a3SJacky Wang @Test referencesUnresolvableDependency()33*f585d8a3SJacky Wang public void referencesUnresolvableDependency() { 34*f585d8a3SJacky Wang Source fooComponent = 35*f585d8a3SJacky Wang CompilerTests.javaSource( 36*f585d8a3SJacky Wang "test.FooComponent", 37*f585d8a3SJacky Wang "package test;", 38*f585d8a3SJacky Wang "", 39*f585d8a3SJacky Wang "import dagger.Component;", 40*f585d8a3SJacky Wang "", 41*f585d8a3SJacky Wang "@Component", 42*f585d8a3SJacky Wang "interface FooComponent {", 43*f585d8a3SJacky Wang " Foo foo();", 44*f585d8a3SJacky Wang "}"); 45*f585d8a3SJacky Wang 46*f585d8a3SJacky Wang Source foo = 47*f585d8a3SJacky Wang CompilerTests.javaSource( 48*f585d8a3SJacky Wang "test.Foo", 49*f585d8a3SJacky Wang "package test;", 50*f585d8a3SJacky Wang "", 51*f585d8a3SJacky Wang "import javax.inject.Inject;", 52*f585d8a3SJacky Wang "", 53*f585d8a3SJacky Wang "class Foo {", 54*f585d8a3SJacky Wang " @Inject", 55*f585d8a3SJacky Wang " Foo(Bar bar) {}", 56*f585d8a3SJacky Wang "}"); 57*f585d8a3SJacky Wang 58*f585d8a3SJacky Wang Source bar = 59*f585d8a3SJacky Wang CompilerTests.javaSource( 60*f585d8a3SJacky Wang "test.Bar", 61*f585d8a3SJacky Wang "package test;", 62*f585d8a3SJacky Wang "", 63*f585d8a3SJacky Wang "import javax.inject.Inject;", 64*f585d8a3SJacky Wang "", 65*f585d8a3SJacky Wang "class Bar {", 66*f585d8a3SJacky Wang " @Inject", 67*f585d8a3SJacky Wang " Bar(UnresolvableDependency dep) {}", 68*f585d8a3SJacky Wang "}"); 69*f585d8a3SJacky Wang 70*f585d8a3SJacky Wang // Only include a minimal portion of the stacktrace to minimize breaking tests due to refactors. 71*f585d8a3SJacky Wang String stacktraceErrorMessage = 72*f585d8a3SJacky Wang "dagger.internal.codegen.base" 73*f585d8a3SJacky Wang + ".DaggerSuperficialValidation$ValidationException$KnownErrorType"; 74*f585d8a3SJacky Wang CompilerTests.daggerCompiler(fooComponent, foo, bar) 75*f585d8a3SJacky Wang .compile( 76*f585d8a3SJacky Wang subject -> { 77*f585d8a3SJacky Wang switch (CompilerTests.backend(subject)) { 78*f585d8a3SJacky Wang case JAVAC: 79*f585d8a3SJacky Wang subject.hasErrorCount(3); 80*f585d8a3SJacky Wang subject.hasErrorContaining( 81*f585d8a3SJacky Wang "cannot find symbol" 82*f585d8a3SJacky Wang + "\n symbol: class UnresolvableDependency" 83*f585d8a3SJacky Wang + "\n location: class test.Bar"); 84*f585d8a3SJacky Wang break; 85*f585d8a3SJacky Wang case KSP: 86*f585d8a3SJacky Wang subject.hasErrorCount(2); 87*f585d8a3SJacky Wang break; 88*f585d8a3SJacky Wang } 89*f585d8a3SJacky Wang // TODO(b/248552462): Javac and KSP should match once this bug is fixed. 90*f585d8a3SJacky Wang boolean isJavac = CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC; 91*f585d8a3SJacky Wang String trace = "\n " 92*f585d8a3SJacky Wang + "\n Dependency trace:" 93*f585d8a3SJacky Wang + "\n => element (CLASS): test.Bar" 94*f585d8a3SJacky Wang + "\n => element (CONSTRUCTOR): Bar(%1$s)" 95*f585d8a3SJacky Wang + "\n => type (EXECUTABLE constructor): (%1$s)void" 96*f585d8a3SJacky Wang + "\n => type (ERROR parameter type): %1$s"; 97*f585d8a3SJacky Wang subject.hasErrorContaining( 98*f585d8a3SJacky Wang String.format( 99*f585d8a3SJacky Wang "InjectProcessingStep was unable to process 'Bar(%1$s)' because '%1$s' could " 100*f585d8a3SJacky Wang + "not be resolved." + trace, 101*f585d8a3SJacky Wang isJavac ? "UnresolvableDependency" : "error.NonExistentClass")); 102*f585d8a3SJacky Wang subject.hasErrorContaining( 103*f585d8a3SJacky Wang String.format( 104*f585d8a3SJacky Wang "ComponentProcessingStep was unable to process 'test.FooComponent' because " 105*f585d8a3SJacky Wang + "'%1$s' could not be resolved." + trace, 106*f585d8a3SJacky Wang isJavac ? "UnresolvableDependency" : "error.NonExistentClass")); 107*f585d8a3SJacky Wang 108*f585d8a3SJacky Wang // Check that the stacktrace is not included in the error message by default. 109*f585d8a3SJacky Wang assertThat(subject.getCompilationResult().rawOutput()) 110*f585d8a3SJacky Wang .doesNotContain(stacktraceErrorMessage); 111*f585d8a3SJacky Wang }); 112*f585d8a3SJacky Wang 113*f585d8a3SJacky Wang 114*f585d8a3SJacky Wang CompilerTests.daggerCompiler(fooComponent, foo, bar) 115*f585d8a3SJacky Wang .withProcessingOptions( 116*f585d8a3SJacky Wang ImmutableMap.of("dagger.includeStacktraceWithDeferredErrorMessages", "ENABLED")) 117*f585d8a3SJacky Wang .compile( 118*f585d8a3SJacky Wang subject -> { 119*f585d8a3SJacky Wang switch (CompilerTests.backend(subject)) { 120*f585d8a3SJacky Wang case JAVAC: 121*f585d8a3SJacky Wang subject.hasErrorCount(3); 122*f585d8a3SJacky Wang break; 123*f585d8a3SJacky Wang case KSP: 124*f585d8a3SJacky Wang subject.hasErrorCount(2); 125*f585d8a3SJacky Wang break; 126*f585d8a3SJacky Wang } 127*f585d8a3SJacky Wang subject.hasErrorContaining(stacktraceErrorMessage); 128*f585d8a3SJacky Wang }); 129*f585d8a3SJacky Wang } 130*f585d8a3SJacky Wang 131*f585d8a3SJacky Wang @Test referencesUnresolvableAnnotationOnType()132*f585d8a3SJacky Wang public void referencesUnresolvableAnnotationOnType() { 133*f585d8a3SJacky Wang Source fooComponent = 134*f585d8a3SJacky Wang CompilerTests.javaSource( 135*f585d8a3SJacky Wang "test.FooComponent", 136*f585d8a3SJacky Wang "package test;", 137*f585d8a3SJacky Wang "", 138*f585d8a3SJacky Wang "import dagger.Component;", 139*f585d8a3SJacky Wang "", 140*f585d8a3SJacky Wang "@Component", 141*f585d8a3SJacky Wang "interface FooComponent {", 142*f585d8a3SJacky Wang " Foo foo();", 143*f585d8a3SJacky Wang "}"); 144*f585d8a3SJacky Wang 145*f585d8a3SJacky Wang Source foo = 146*f585d8a3SJacky Wang CompilerTests.javaSource( 147*f585d8a3SJacky Wang "test.Foo", 148*f585d8a3SJacky Wang "package test;", 149*f585d8a3SJacky Wang "", 150*f585d8a3SJacky Wang "import javax.inject.Inject;", 151*f585d8a3SJacky Wang "", 152*f585d8a3SJacky Wang "class Foo {", 153*f585d8a3SJacky Wang " @Inject", 154*f585d8a3SJacky Wang " Foo(Bar bar) {}", 155*f585d8a3SJacky Wang "}"); 156*f585d8a3SJacky Wang 157*f585d8a3SJacky Wang Source bar = 158*f585d8a3SJacky Wang CompilerTests.javaSource( 159*f585d8a3SJacky Wang "test.Bar", 160*f585d8a3SJacky Wang "package test;", 161*f585d8a3SJacky Wang "", 162*f585d8a3SJacky Wang "import javax.inject.Inject;", 163*f585d8a3SJacky Wang "", 164*f585d8a3SJacky Wang "@UnresolvableAnnotation", 165*f585d8a3SJacky Wang "class Bar {", 166*f585d8a3SJacky Wang " @Inject", 167*f585d8a3SJacky Wang " Bar(String dep) {}", 168*f585d8a3SJacky Wang "}"); 169*f585d8a3SJacky Wang 170*f585d8a3SJacky Wang CompilerTests.daggerCompiler(fooComponent, foo, bar) 171*f585d8a3SJacky Wang .compile( 172*f585d8a3SJacky Wang subject -> { 173*f585d8a3SJacky Wang switch (CompilerTests.backend(subject)) { 174*f585d8a3SJacky Wang case JAVAC: 175*f585d8a3SJacky Wang subject.hasErrorCount(3); 176*f585d8a3SJacky Wang subject.hasErrorContaining( 177*f585d8a3SJacky Wang "cannot find symbol" 178*f585d8a3SJacky Wang + "\n symbol: class UnresolvableAnnotation"); 179*f585d8a3SJacky Wang break; 180*f585d8a3SJacky Wang case KSP: 181*f585d8a3SJacky Wang subject.hasErrorCount(2); 182*f585d8a3SJacky Wang break; 183*f585d8a3SJacky Wang } 184*f585d8a3SJacky Wang // TODO(b/248552462): Javac and KSP should match once this bug is fixed. 185*f585d8a3SJacky Wang boolean isJavac = CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC; 186*f585d8a3SJacky Wang String trace = "\n " 187*f585d8a3SJacky Wang + "\n Dependency trace:" 188*f585d8a3SJacky Wang + "\n => element (CLASS): test.Bar" 189*f585d8a3SJacky Wang + "\n => annotation: @UnresolvableAnnotation" 190*f585d8a3SJacky Wang + "\n => type (ERROR annotation type): %1$s"; 191*f585d8a3SJacky Wang subject.hasErrorContaining( 192*f585d8a3SJacky Wang String.format( 193*f585d8a3SJacky Wang "InjectProcessingStep was unable to process 'Bar(java.lang.String)' because " 194*f585d8a3SJacky Wang + "'%1$s' could not be resolved." + trace, 195*f585d8a3SJacky Wang isJavac ? "UnresolvableAnnotation" : "error.NonExistentClass")); 196*f585d8a3SJacky Wang subject.hasErrorContaining( 197*f585d8a3SJacky Wang String.format( 198*f585d8a3SJacky Wang "ComponentProcessingStep was unable to process 'test.FooComponent' because " 199*f585d8a3SJacky Wang + "'%1$s' could not be resolved." + trace, 200*f585d8a3SJacky Wang isJavac ? "UnresolvableAnnotation" : "error.NonExistentClass")); 201*f585d8a3SJacky Wang }); 202*f585d8a3SJacky Wang } 203*f585d8a3SJacky Wang 204*f585d8a3SJacky Wang @Test referencesUnresolvableAnnotationOnTypeOnParameter()205*f585d8a3SJacky Wang public void referencesUnresolvableAnnotationOnTypeOnParameter() { 206*f585d8a3SJacky Wang Source fooComponent = 207*f585d8a3SJacky Wang CompilerTests.javaSource( 208*f585d8a3SJacky Wang "test.FooComponent", 209*f585d8a3SJacky Wang "package test;", 210*f585d8a3SJacky Wang "", 211*f585d8a3SJacky Wang "import dagger.Component;", 212*f585d8a3SJacky Wang "", 213*f585d8a3SJacky Wang "@Component", 214*f585d8a3SJacky Wang "interface FooComponent {", 215*f585d8a3SJacky Wang " Foo foo();", 216*f585d8a3SJacky Wang "}"); 217*f585d8a3SJacky Wang 218*f585d8a3SJacky Wang Source foo = 219*f585d8a3SJacky Wang CompilerTests.javaSource( 220*f585d8a3SJacky Wang "test.Foo", 221*f585d8a3SJacky Wang "package test;", 222*f585d8a3SJacky Wang "", 223*f585d8a3SJacky Wang "import javax.inject.Inject;", 224*f585d8a3SJacky Wang "", 225*f585d8a3SJacky Wang "class Foo {", 226*f585d8a3SJacky Wang " @Inject", 227*f585d8a3SJacky Wang " Foo(Bar bar) {}", 228*f585d8a3SJacky Wang "}"); 229*f585d8a3SJacky Wang 230*f585d8a3SJacky Wang Source bar = 231*f585d8a3SJacky Wang CompilerTests.javaSource( 232*f585d8a3SJacky Wang "test.Bar", 233*f585d8a3SJacky Wang "package test;", 234*f585d8a3SJacky Wang "", 235*f585d8a3SJacky Wang "import javax.inject.Inject;", 236*f585d8a3SJacky Wang "", 237*f585d8a3SJacky Wang "class Bar {", 238*f585d8a3SJacky Wang " @Inject", 239*f585d8a3SJacky Wang " Bar(@UnresolvableAnnotation String dep) {}", 240*f585d8a3SJacky Wang "}"); 241*f585d8a3SJacky Wang 242*f585d8a3SJacky Wang CompilerTests.daggerCompiler(fooComponent, foo, bar) 243*f585d8a3SJacky Wang .compile( 244*f585d8a3SJacky Wang subject -> { 245*f585d8a3SJacky Wang switch (CompilerTests.backend(subject)) { 246*f585d8a3SJacky Wang case JAVAC: 247*f585d8a3SJacky Wang subject.hasErrorCount(3); 248*f585d8a3SJacky Wang subject.hasErrorContaining( 249*f585d8a3SJacky Wang "cannot find symbol" 250*f585d8a3SJacky Wang + "\n symbol: class UnresolvableAnnotation" 251*f585d8a3SJacky Wang + "\n location: class test.Bar"); 252*f585d8a3SJacky Wang break; 253*f585d8a3SJacky Wang case KSP: 254*f585d8a3SJacky Wang subject.hasErrorCount(2); 255*f585d8a3SJacky Wang break; 256*f585d8a3SJacky Wang } 257*f585d8a3SJacky Wang // TODO(b/248552462): Javac and KSP should match once this bug is fixed. 258*f585d8a3SJacky Wang boolean isJavac = CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC; 259*f585d8a3SJacky Wang String trace = "\n " 260*f585d8a3SJacky Wang + "\n Dependency trace:" 261*f585d8a3SJacky Wang + "\n => element (CLASS): test.Bar" 262*f585d8a3SJacky Wang + "\n => element (CONSTRUCTOR): Bar(java.lang.String)" 263*f585d8a3SJacky Wang + "\n => element (PARAMETER): dep" 264*f585d8a3SJacky Wang + "\n => annotation: @UnresolvableAnnotation" 265*f585d8a3SJacky Wang + "\n => type (ERROR annotation type): %1$s"; 266*f585d8a3SJacky Wang subject.hasErrorContaining( 267*f585d8a3SJacky Wang String.format( 268*f585d8a3SJacky Wang "InjectProcessingStep was unable to process 'Bar(java.lang.String)' because " 269*f585d8a3SJacky Wang + "'%1$s' could not be resolved." + trace, 270*f585d8a3SJacky Wang isJavac ? "UnresolvableAnnotation" : "error.NonExistentClass")); 271*f585d8a3SJacky Wang subject.hasErrorContaining( 272*f585d8a3SJacky Wang String.format( 273*f585d8a3SJacky Wang "ComponentProcessingStep was unable to process 'test.FooComponent' because " 274*f585d8a3SJacky Wang + "'%1$s' could not be resolved." + trace, 275*f585d8a3SJacky Wang isJavac ? "UnresolvableAnnotation" : "error.NonExistentClass")); 276*f585d8a3SJacky Wang }); 277*f585d8a3SJacky Wang } 278*f585d8a3SJacky Wang } 279