All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dagger.internal.codegen.binding.AnnotationExpression Maven / Gradle / Ivy

/*
 * Copyright (C) 2016 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.binding;

import static com.google.auto.common.AnnotationMirrors.getAnnotationValuesWithDefaults;
import static dagger.internal.codegen.binding.SourceFiles.classFileName;
import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
import static java.util.stream.Collectors.toList;

import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableList;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.TypeName;
import java.util.List;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.SimpleAnnotationValueVisitor6;
import javax.lang.model.util.SimpleTypeVisitor6;

/**
 * Returns an expression creating an instance of the visited annotation type. Its parameter must be
 * a class as generated by {@link dagger.internal.codegen.writing.AnnotationCreatorGenerator}.
 *
 * 

Note that {@link AnnotationValue#toString()} is the source-code representation of the value * when used in an annotation, which is not always the same as the representation needed * when creating the value in a method body. * *

For example, inside an annotation, a nested array of {@code int}s is simply {@code {1, 2, 3}}, * but in code it would have to be {@code new int[] {1, 2, 3}}. */ public class AnnotationExpression extends SimpleAnnotationValueVisitor6 { private final AnnotationMirror annotation; private final ClassName creatorClass; AnnotationExpression(AnnotationMirror annotation) { this.annotation = annotation; this.creatorClass = getAnnotationCreatorClassName( MoreTypes.asTypeElement(annotation.getAnnotationType())); } /** * Returns an expression that calls static methods on the annotation's creator class to create an * annotation instance equivalent the annotation passed to the constructor. */ CodeBlock getAnnotationInstanceExpression() { return getAnnotationInstanceExpression(annotation); } private CodeBlock getAnnotationInstanceExpression(AnnotationMirror annotation) { return CodeBlock.of( "$T.$L($L)", creatorClass, createMethodName( MoreElements.asType(annotation.getAnnotationType().asElement())), makeParametersCodeBlock( getAnnotationValuesWithDefaults(annotation) .entrySet() .stream() .map(entry -> getValueExpression(entry.getKey().getReturnType(), entry.getValue())) .collect(toList()))); } /** * Returns the name of the generated class that contains the static {@code create} methods for an * annotation type. */ public static ClassName getAnnotationCreatorClassName(TypeElement annotationType) { ClassName annotationTypeName = ClassName.get(annotationType); return annotationTypeName .topLevelClassName() .peerClass(classFileName(annotationTypeName) + "Creator"); } public static String createMethodName(TypeElement annotationType) { return "create" + annotationType.getSimpleName(); } /** * Returns an expression that evaluates to a {@code value} of a given type on an {@code * annotation}. */ CodeBlock getValueExpression(TypeMirror valueType, AnnotationValue value) { return ARRAY_LITERAL_PREFIX.visit(valueType, this.visit(value, value)); } @Override public CodeBlock visitEnumConstant(VariableElement c, AnnotationValue p) { return CodeBlock.of("$T.$L", c.getEnclosingElement(), c.getSimpleName()); } @Override public CodeBlock visitAnnotation(AnnotationMirror a, AnnotationValue p) { return getAnnotationInstanceExpression(a); } @Override public CodeBlock visitType(TypeMirror t, AnnotationValue p) { return CodeBlock.of("$T.class", t); } @Override public CodeBlock visitString(String s, AnnotationValue p) { return CodeBlock.of("$S", s); } @Override public CodeBlock visitByte(byte b, AnnotationValue p) { return CodeBlock.of("(byte) $L", b); } @Override public CodeBlock visitChar(char c, AnnotationValue p) { return CodeBlock.of("$L", p); } @Override public CodeBlock visitDouble(double d, AnnotationValue p) { return CodeBlock.of("$LD", d); } @Override public CodeBlock visitFloat(float f, AnnotationValue p) { return CodeBlock.of("$LF", f); } @Override public CodeBlock visitLong(long i, AnnotationValue p) { return CodeBlock.of("$LL", i); } @Override public CodeBlock visitShort(short s, AnnotationValue p) { return CodeBlock.of("(short) $L", s); } @Override protected CodeBlock defaultAction(Object o, AnnotationValue p) { return CodeBlock.of("$L", o); } @Override public CodeBlock visitArray(List values, AnnotationValue p) { ImmutableList.Builder codeBlocks = ImmutableList.builder(); for (AnnotationValue value : values) { codeBlocks.add(this.visit(value, p)); } return CodeBlock.of("{$L}", makeParametersCodeBlock(codeBlocks.build())); } /** * If the visited type is an array, prefixes the parameter code block with {@code new T[]}, where * {@code T} is the raw array component type. */ private static final SimpleTypeVisitor6 ARRAY_LITERAL_PREFIX = new SimpleTypeVisitor6() { @Override public CodeBlock visitArray(ArrayType t, CodeBlock p) { return CodeBlock.of("new $T[] $L", RAW_TYPE_NAME.visit(t.getComponentType()), p); } @Override protected CodeBlock defaultAction(TypeMirror e, CodeBlock p) { return p; } }; /** * If the visited type is an array, returns the name of its raw component type; otherwise returns * the name of the type itself. */ private static final SimpleTypeVisitor6 RAW_TYPE_NAME = new SimpleTypeVisitor6() { @Override public TypeName visitDeclared(DeclaredType t, Void p) { return ClassName.get(MoreTypes.asTypeElement(t)); } @Override protected TypeName defaultAction(TypeMirror e, Void p) { return TypeName.get(e); } }; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy