| /* |
| * Copyright (C) 2019 The Dagger Authors. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package dagger.internal.codegen; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import com.google.testing.compile.CompilationRule; |
| import dagger.internal.codegen.langmodel.DaggerElements; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.stream.Collectors; |
| import javax.lang.model.element.TypeElement; |
| import javax.lang.model.util.ElementFilter; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| @RunWith(JUnit4.class) |
| public class ElementDescriptorsTest { |
| |
| @Rule public CompilationRule compilation = new CompilationRule(); |
| |
| static class TestClassA<T> { |
| int field1; |
| String field2; |
| T field3; |
| List<String> field4; |
| } |
| |
| @Test |
| public void fieldDescriptor() { |
| assertThat(getFieldDescriptors(TestClassA.class.getCanonicalName())) |
| .containsExactly( |
| "field1:I", |
| "field2:Ljava/lang/String;", |
| "field3:Ljava/lang/Object;", |
| "field4:Ljava/util/List;"); |
| } |
| |
| static class TestClassB<T> { |
| void method1(boolean yesOrNo, int number) {} |
| |
| byte method2(char letter) { |
| return 0; |
| } |
| |
| void method3(double realNumber1, float realNummber2) {} |
| |
| void method4(long bigNumber, short littlerNumber) {} |
| } |
| |
| @Test |
| public void methodDescriptor_primitives() { |
| assertThat(getMethodDescriptors(TestClassB.class.getCanonicalName())) |
| .containsExactly("method1(ZI)V", "method2(C)B", "method3(DF)V", "method4(JS)V"); |
| } |
| |
| static class TestClassC<T> { |
| void method1(Object something) {} |
| |
| Object method2() { |
| return null; |
| } |
| |
| List<String> method3(ArrayList<Integer> list) { |
| return null; |
| } |
| |
| Map<String, Object> method4() { |
| return null; |
| } |
| } |
| |
| @Test |
| public void methodDescriptor_javaTypes() { |
| assertThat(getMethodDescriptors(TestClassC.class.getCanonicalName())) |
| .containsExactly( |
| "method1(Ljava/lang/Object;)V", |
| "method2()Ljava/lang/Object;", |
| "method3(Ljava/util/ArrayList;)Ljava/util/List;", |
| "method4()Ljava/util/Map;"); |
| } |
| |
| static class TestClassD<T> { |
| void method1(TestDataClass data) {} |
| |
| TestDataClass method2() { |
| return null; |
| } |
| } |
| |
| @Test |
| public void methodDescriptor_testTypes() { |
| assertThat(getMethodDescriptors(TestClassD.class.getCanonicalName())) |
| .containsExactly( |
| "method1(Ldagger/internal/codegen/TestDataClass;)V", |
| "method2()Ldagger/internal/codegen/TestDataClass;"); |
| } |
| |
| static class TestClassE<T> { |
| void method1(TestDataClass[] data) {} |
| |
| TestDataClass[] method2() { |
| return null; |
| } |
| |
| void method3(int[] array) {} |
| |
| void method4(int... array) {} |
| } |
| |
| @Test |
| public void methodDescriptor_arrays() { |
| assertThat(getMethodDescriptors(TestClassE.class.getCanonicalName())) |
| .containsExactly( |
| "method1([Ldagger/internal/codegen/TestDataClass;)V", |
| "method2()[Ldagger/internal/codegen/TestDataClass;", |
| "method3([I)V", |
| "method4([I)V"); |
| } |
| |
| static class TestClassF<T> { |
| void method1(TestDataClass.MemberInnerData data) {} |
| |
| void method2(TestDataClass.StaticInnerData data) {} |
| |
| void method3(TestDataClass.EnumData enumData) {} |
| |
| TestDataClass.StaticInnerData method4() { |
| return null; |
| } |
| } |
| |
| @Test |
| public void methodDescriptor_innerTestType() { |
| assertThat(getMethodDescriptors(TestClassF.class.getCanonicalName())) |
| .containsExactly( |
| "method1(Ldagger/internal/codegen/TestDataClass$MemberInnerData;)V", |
| "method2(Ldagger/internal/codegen/TestDataClass$StaticInnerData;)V", |
| "method3(Ldagger/internal/codegen/TestDataClass$EnumData;)V", |
| "method4()Ldagger/internal/codegen/TestDataClass$StaticInnerData;"); |
| } |
| |
| @SuppressWarnings("TypeParameterUnusedInFormals") |
| static class TestClassG<T> { |
| void method1(T something) {} |
| |
| T method2() { |
| return null; |
| } |
| |
| List<? extends String> method3() { |
| return null; |
| } |
| |
| Map<T, String> method4() { |
| return null; |
| } |
| |
| ArrayList<Map<T, String>> method5() { |
| return null; |
| } |
| |
| static <I, O extends I> O method6(I input) { |
| return null; |
| } |
| |
| static <I, O extends String> O method7(I input) { |
| return null; |
| } |
| |
| static <P extends Collection<String> & Comparable<String>> P method8() { |
| return null; |
| } |
| |
| static <P extends String & List<Character>> P method9() { |
| return null; |
| } |
| } |
| |
| @Test |
| public void methodDescriptor_erasure() { |
| assertThat(getMethodDescriptors(TestClassG.class.getCanonicalName())) |
| .containsExactly( |
| "method1(Ljava/lang/Object;)V", |
| "method2()Ljava/lang/Object;", |
| "method3()Ljava/util/List;", |
| "method4()Ljava/util/Map;", |
| "method5()Ljava/util/ArrayList;", |
| "method6(Ljava/lang/Object;)Ljava/lang/Object;", |
| "method7(Ljava/lang/Object;)Ljava/lang/String;", |
| "method8()Ljava/util/Collection;", |
| "method9()Ljava/lang/String;"); |
| } |
| |
| private Set<String> getFieldDescriptors(String className) { |
| TypeElement testElement = compilation.getElements().getTypeElement(className); |
| return ElementFilter.fieldsIn(testElement.getEnclosedElements()).stream() |
| .map(DaggerElements::getFieldDescriptor) |
| .collect(Collectors.toSet()); |
| } |
| |
| private Set<String> getMethodDescriptors(String className) { |
| TypeElement testElement = compilation.getElements().getTypeElement(className); |
| return ElementFilter.methodsIn(testElement.getEnclosedElements()).stream() |
| .map(DaggerElements::getMethodDescriptor) |
| .collect(Collectors.toSet()); |
| } |
| } |
| |
| @SuppressWarnings("ClassCanBeStatic") |
| class TestDataClass { |
| class MemberInnerData {} |
| |
| static class StaticInnerData {} |
| |
| enum EnumData { |
| VALUE1, |
| VALUE2 |
| } |
| } |