1 /*
2  * Copyright (C) 2019 The Dagger Authors.
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 dagger.internal.codegen.kotlin;
18 
19 import static com.google.auto.common.MoreElements.isAnnotationPresent;
20 import static dagger.internal.codegen.langmodel.DaggerElements.closestEnclosingTypeElement;
21 
22 import dagger.internal.codegen.base.ClearableCache;
23 import java.util.HashMap;
24 import java.util.Map;
25 import javax.inject.Inject;
26 import javax.inject.Singleton;
27 import javax.lang.model.element.Element;
28 import javax.lang.model.element.TypeElement;
29 import kotlin.Metadata;
30 
31 /**
32  * Factory creating Kotlin metadata data objects.
33  *
34  * <p>The metadata is cache since it can be expensive to parse the information stored in a proto
35  * binary string format in the metadata annotation values.
36  */
37 @Singleton
38 public final class KotlinMetadataFactory implements ClearableCache {
39   private final Map<TypeElement, KotlinMetadata> metadataCache = new HashMap<>();
40 
41   @Inject
KotlinMetadataFactory()42   KotlinMetadataFactory() {}
43 
44   /**
45    * Parses and returns the {@link KotlinMetadata} out of a given element.
46    *
47    * @throws IllegalStateException if the element has no metadata or is not enclosed in a type
48    *     element with metadata. To check if an element has metadata use {@link
49    *     KotlinMetadataUtil#hasMetadata(Element)}
50    */
create(Element element)51   public KotlinMetadata create(Element element) {
52     TypeElement enclosingElement = closestEnclosingTypeElement(element);
53     if (!isAnnotationPresent(enclosingElement, Metadata.class)) {
54       throw new IllegalStateException("Missing @Metadata for: " + enclosingElement);
55     }
56     return metadataCache.computeIfAbsent(enclosingElement, KotlinMetadata::from);
57   }
58 
59   @Override
clearCache()60   public void clearCache() {
61     metadataCache.clear();
62   }
63 }
64