1 /* 2 * Copyright 2015 Google LLC 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 package com.google.auto.value.processor; 17 18 import static com.google.auto.value.processor.ClassNames.COPY_ANNOTATIONS_NAME; 19 20 import com.google.auto.value.extension.AutoValueExtension; 21 import com.google.auto.value.extension.AutoValueExtension.BuilderContext; 22 import com.google.common.collect.ImmutableList; 23 import com.google.common.collect.ImmutableMap; 24 import com.google.common.collect.ImmutableSet; 25 import com.google.common.collect.Maps; 26 import java.util.List; 27 import java.util.Map; 28 import java.util.Optional; 29 import java.util.Set; 30 import javax.annotation.processing.ProcessingEnvironment; 31 import javax.lang.model.element.AnnotationMirror; 32 import javax.lang.model.element.ExecutableElement; 33 import javax.lang.model.element.TypeElement; 34 import javax.lang.model.type.TypeMirror; 35 36 class ExtensionContext implements AutoValueExtension.Context { 37 38 private final ProcessingEnvironment processingEnvironment; 39 private final TypeElement autoValueClass; 40 private final ImmutableMap<String, ExecutableElement> properties; 41 private final ImmutableMap<String, TypeMirror> propertyTypes; 42 private final ImmutableSet<ExecutableElement> abstractMethods; 43 private Optional<BuilderContext> builderContext = Optional.empty(); 44 ExtensionContext( ProcessingEnvironment processingEnvironment, TypeElement autoValueClass, ImmutableMap<String, ExecutableElement> properties, ImmutableMap<ExecutableElement, TypeMirror> propertyMethodsAndTypes, ImmutableSet<ExecutableElement> abstractMethods)45 ExtensionContext( 46 ProcessingEnvironment processingEnvironment, 47 TypeElement autoValueClass, 48 ImmutableMap<String, ExecutableElement> properties, 49 ImmutableMap<ExecutableElement, TypeMirror> propertyMethodsAndTypes, 50 ImmutableSet<ExecutableElement> abstractMethods) { 51 this.processingEnvironment = processingEnvironment; 52 this.autoValueClass = autoValueClass; 53 this.properties = properties; 54 this.propertyTypes = 55 ImmutableMap.copyOf(Maps.transformValues(properties, propertyMethodsAndTypes::get)); 56 this.abstractMethods = abstractMethods; 57 } 58 setBuilderContext(BuilderContext builderContext)59 void setBuilderContext(BuilderContext builderContext) { 60 this.builderContext = Optional.of(builderContext); 61 } 62 63 @Override processingEnvironment()64 public ProcessingEnvironment processingEnvironment() { 65 return processingEnvironment; 66 } 67 68 @Override packageName()69 public String packageName() { 70 return TypeSimplifier.packageNameOf(autoValueClass); 71 } 72 73 @Override autoValueClass()74 public TypeElement autoValueClass() { 75 return autoValueClass; 76 } 77 78 @Override finalAutoValueClassName()79 public String finalAutoValueClassName() { 80 return AutoValueProcessor.generatedSubclassName(autoValueClass, 0); 81 } 82 83 @Override properties()84 public Map<String, ExecutableElement> properties() { 85 return properties; 86 } 87 88 @Override propertyTypes()89 public Map<String, TypeMirror> propertyTypes() { 90 return propertyTypes; 91 } 92 93 @Override abstractMethods()94 public Set<ExecutableElement> abstractMethods() { 95 return abstractMethods; 96 } 97 98 @Override classAnnotationsToCopy(TypeElement classToCopyFrom)99 public List<AnnotationMirror> classAnnotationsToCopy(TypeElement classToCopyFrom) { 100 // Only copy annotations from a class if it has @AutoValue.CopyAnnotations. 101 if (!AutoValueishProcessor.hasAnnotationMirror(classToCopyFrom, COPY_ANNOTATIONS_NAME)) { 102 return ImmutableList.of(); 103 } 104 105 ImmutableSet<String> excludedAnnotations = 106 ImmutableSet.<String>builder() 107 .addAll(AutoValueishProcessor.getExcludedAnnotationClassNames(classToCopyFrom)) 108 .addAll(AutoValueishProcessor.getAnnotationsMarkedWithInherited(classToCopyFrom)) 109 // 110 // Kotlin classes have an intrinsic @Metadata annotation generated 111 // onto them by kotlinc. This annotation is specific to the annotated 112 // class and should not be implicitly copied. Doing so can mislead 113 // static analysis or metaprogramming tooling that reads the data 114 // contained in these annotations. 115 // 116 // It may be surprising to see AutoValue classes written in Kotlin 117 // when they could be written as Kotlin data classes, but this can 118 // come up in cases where consumers rely on AutoValue features or 119 // extensions that are not available in data classes. 120 // 121 // See: https://github.com/google/auto/issues/1087 122 // 123 .add(ClassNames.KOTLIN_METADATA_NAME) 124 .build(); 125 126 return AutoValueishProcessor.annotationsToCopy( 127 autoValueClass, classToCopyFrom, excludedAnnotations, processingEnvironment.getTypeUtils()); 128 } 129 130 @Override methodAnnotationsToCopy(ExecutableElement method)131 public List<AnnotationMirror> methodAnnotationsToCopy(ExecutableElement method) { 132 return AutoValueishProcessor.propertyMethodAnnotations( 133 autoValueClass, method, processingEnvironment.getTypeUtils()); 134 } 135 136 @Override builder()137 public Optional<BuilderContext> builder() { 138 return builderContext; 139 } 140 } 141