blob: 9690691ebfe0b5bfa8e1d7fe4f34aa54721642d5 [file] [log] [blame]
/*
* 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.base;
import static com.google.common.base.Preconditions.checkArgument;
import static javax.lang.model.util.ElementFilter.methodsIn;
import com.google.auto.common.MoreTypes;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
/** A representation of an annotation. */
public final class SimpleAnnotationMirror implements AnnotationMirror {
private final TypeElement annotationType;
private final ImmutableMap<String, ? extends AnnotationValue> namedValues;
private final ImmutableMap<ExecutableElement, ? extends AnnotationValue> elementValues;
private SimpleAnnotationMirror(
TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) {
checkArgument(
annotationType.getKind().equals(ElementKind.ANNOTATION_TYPE),
"annotationType must be an annotation: %s",
annotationType);
checkArgument(
FluentIterable.from(methodsIn(annotationType.getEnclosedElements()))
.transform(element -> element.getSimpleName().toString())
.toSet()
.equals(namedValues.keySet()),
"namedValues must have values for exactly the members in %s: %s",
annotationType,
namedValues);
this.annotationType = annotationType;
this.namedValues = ImmutableMap.copyOf(namedValues);
this.elementValues =
Maps.toMap(
methodsIn(annotationType.getEnclosedElements()),
Functions.compose(
Functions.forMap(namedValues), element -> element.getSimpleName().toString()));
}
@Override
public DeclaredType getAnnotationType() {
return MoreTypes.asDeclared(annotationType.asType());
}
@Override
public Map<ExecutableElement, ? extends AnnotationValue> getElementValues() {
return elementValues;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("@").append(annotationType.getQualifiedName());
if (!namedValues.isEmpty()) {
builder
.append('(')
.append(Joiner.on(", ").withKeyValueSeparator(" = ").join(namedValues))
.append(')');
}
return builder.toString();
}
/**
* An object representing an annotation instance.
*
* @param annotationType must be an annotation type with no members
*/
public static AnnotationMirror of(TypeElement annotationType) {
return of(annotationType, ImmutableMap.<String, AnnotationValue>of());
}
/**
* An object representing an annotation instance.
*
* @param annotationType must be an annotation type
* @param namedValues a value for every annotation member, including those with defaults, indexed
* by simple name
*/
private static AnnotationMirror of(
TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) {
return new SimpleAnnotationMirror(annotationType, namedValues);
}
}