1 /* 2 * Copyright (C) 2021 The Android Open Source Project 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 com.android.annotationvisitor; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import com.google.common.base.Joiner; 22 import com.google.common.collect.ImmutableMap; 23 24 import org.apache.bcel.classfile.AnnotationEntry; 25 import org.junit.Before; 26 import org.junit.Test; 27 28 import java.io.IOException; 29 import java.util.ArrayList; 30 import java.util.List; 31 import java.util.Map; 32 33 public class RepeatedAnnotationHandlerTest extends AnnotationHandlerTestBase { 34 35 @Before setup()36 public void setup() { 37 // To keep the test simpler and more concise, we don't use a real annotation here, but use 38 // our own @Annotation and @Annotation.Multi that have the same relationship. 39 mJavac.addSource("annotation.Annotation", Joiner.on('\n').join( 40 "package annotation;", 41 "import static java.lang.annotation.RetentionPolicy.CLASS;", 42 "import java.lang.annotation.Repeatable;", 43 "import java.lang.annotation.Retention;", 44 "@Repeatable(Annotation.Multi.class)", 45 "@Retention(CLASS)", 46 "public @interface Annotation {", 47 " Class<?> clazz();", 48 " @Retention(CLASS)", 49 " @interface Multi {", 50 " Annotation[] value();", 51 " }", 52 "}")); 53 } 54 55 @Test testRepeated()56 public void testRepeated() throws IOException { 57 mJavac.addSource("a.b.Class", Joiner.on('\n').join( 58 "package a.b;", 59 "import annotation.Annotation;", 60 "public class Class {", 61 " @Annotation(clazz=Integer.class)", 62 " @Annotation(clazz=Long.class)", 63 " public String method() {return null;}", 64 "}")); 65 mJavac.compile(); 66 67 TestAnnotationHandler handler = new TestAnnotationHandler(); 68 Map<String, AnnotationHandler> handlerMap = 69 ImmutableMap.of("Lannotation/Annotation$Multi;", 70 new RepeatedAnnotationHandler("Lannotation/Annotation;", handler)); 71 new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit(); 72 73 assertNoErrors(); 74 assertThat(handler.getClasses()).containsExactly( 75 "Ljava/lang/Integer;", 76 "Ljava/lang/Long;"); 77 } 78 79 private static class TestAnnotationHandler extends AnnotationHandler { 80 81 private final List<String> classes; 82 TestAnnotationHandler()83 private TestAnnotationHandler() { 84 this.classes = new ArrayList<>(); 85 } 86 87 @Override handleAnnotation(AnnotationEntry annotation, AnnotationContext context)88 protected void handleAnnotation(AnnotationEntry annotation, 89 AnnotationContext context) { 90 classes.add(annotation.getElementValuePairs()[0].getValue().stringifyValue()); 91 } 92 getClasses()93 private List<String> getClasses() { 94 return classes; 95 } 96 } 97 } 98