• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 Square, Inc.
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  * https://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.squareup.kotlinpoet
17 
18 import kotlin.reflect.KClass
19 
20 /** A type that can be tagged with extra metadata of the user's choice. */
21 public interface Taggable {
22 
23   /** Returns all tags. */
24   public val tags: Map<KClass<*>, Any> get() = emptyMap()
25 
26   /** Returns the tag attached with [type] as a key, or null if no tag is attached with that key. */
tagnull27   public fun <T : Any> tag(type: Class<T>): T? = tag(type.kotlin)
28 
29   /** Returns the tag attached with [type] as a key, or null if no tag is attached with that key. */
30   public fun <T : Any> tag(type: KClass<T>): T? {
31     @Suppress("UNCHECKED_CAST")
32     return tags[type] as T?
33   }
34 
35   /** The builder analogue to [Taggable] types. */
36   public interface Builder<out T : Builder<T>> {
37 
38     /** Mutable map of the current tags this builder contains. */
39     public val tags: MutableMap<KClass<*>, Any>
40 
41     /**
42      * Attaches [tag] to the request using [type] as a key. Tags can be read from a
43      * request using [Taggable.tag]. Use `null` to remove any existing tag assigned for
44      * [type].
45      *
46      * Use this API to attach originating elements, debugging, or other application data to a spec
47      * so that you may read it in other APIs or callbacks.
48      */
tagnull49     public fun tag(type: Class<*>, tag: Any?): T = tag(type.kotlin, tag)
50 
51     /**
52      * Attaches [tag] to the request using [type] as a key. Tags can be read from a
53      * request using [Taggable.tag]. Use `null` to remove any existing tag assigned for
54      * [type].
55      *
56      * Use this API to attach originating elements, debugging, or other application data to a spec
57      * so that you may read it in other APIs or callbacks.
58      */
59     @Suppress("UNCHECKED_CAST")
60     public fun tag(type: KClass<*>, tag: Any?): T = apply {
61       if (tag == null) {
62         this.tags.remove(type)
63       } else {
64         this.tags[type] = tag
65       }
66     } as T
67   }
68 }
69 
70 /** Returns the tag attached with [T] as a key, or null if no tag is attached with that key. */
tagnull71 public inline fun <reified T : Any> Taggable.tag(): T? = tag(T::class)
72 
73 /**
74  * Attaches [tag] to the request using [T] as a key. Tags can be read from a
75  * request using [Taggable.tag]. Use `null` to remove any existing tag assigned for
76  * [T].
77  *
78  * Use this API to attach debugging or other application data to a spec so that you may read it in
79  * other APIs or callbacks.
80  */
81 
82 public inline fun <reified T : Any> AnnotationSpec.Builder.tag(tag: T?): AnnotationSpec.Builder =
83   tag(T::class, tag)
84 
85 /**
86  * Attaches [tag] to the request using [T] as a key. Tags can be read from a
87  * request using [Taggable.tag]. Use `null` to remove any existing tag assigned for
88  * [T].
89  *
90  * Use this API to attach debugging or other application data to a spec so that you may read it in
91  * other APIs or callbacks.
92  */
93 public inline fun <reified T : Any> FileSpec.Builder.tag(tag: T?): FileSpec.Builder =
94   tag(T::class, tag)
95 
96 /**
97  * Attaches [tag] to the request using [T] as a key. Tags can be read from a
98  * request using [Taggable.tag]. Use `null` to remove any existing tag assigned for
99  * [T].
100  *
101  * Use this API to attach debugging or other application data to a spec so that you may read it in
102  * other APIs or callbacks.
103  */
104 public inline fun <reified T : Any> FunSpec.Builder.tag(tag: T?): FunSpec.Builder =
105   tag(T::class, tag)
106 
107 /**
108  * Attaches [tag] to the request using [T] as a key. Tags can be read from a
109  * request using [Taggable.tag]. Use `null` to remove any existing tag assigned for
110  * [T].
111  *
112  * Use this API to attach debugging or other application data to a spec so that you may read it in
113  * other APIs or callbacks.
114  */
115 public inline fun <reified T : Any> ParameterSpec.Builder.tag(tag: T?): ParameterSpec.Builder =
116   tag(T::class, tag)
117 
118 /**
119  * Attaches [tag] to the request using [T] as a key. Tags can be read from a
120  * request using [Taggable.tag]. Use `null` to remove any existing tag assigned for
121  * [T].
122  *
123  * Use this API to attach debugging or other application data to a spec so that you may read it in
124  * other APIs or callbacks.
125  */
126 public inline fun <reified T : Any> PropertySpec.Builder.tag(tag: T?): PropertySpec.Builder =
127   tag(T::class, tag)
128 
129 /**
130  * Attaches [tag] to the request using [T] as a key. Tags can be read from a
131  * request using [Taggable.tag]. Use `null` to remove any existing tag assigned for
132  * [T].
133  *
134  * Use this API to attach debugging or other application data to a spec so that you may read it in
135  * other APIs or callbacks.
136  */
137 public inline fun <reified T : Any> TypeAliasSpec.Builder.tag(tag: T?): TypeAliasSpec.Builder =
138   tag(T::class, tag)
139 
140 /**
141  * Attaches [tag] to the request using [T] as a key. Tags can be read from a
142  * request using [Taggable.tag]. Use `null` to remove any existing tag assigned for
143  * [T].
144  *
145  * Use this API to attach debugging or other application data to a spec so that you may read it in
146  * other APIs or callbacks.
147  */
148 public inline fun <reified T : Any> TypeSpec.Builder.tag(tag: T?): TypeSpec.Builder =
149   tag(T::class, tag)
150 
151 internal fun Taggable.Builder<*>.buildTagMap(): TagMap = TagMap(tags)
152 
153 @JvmInline
154 internal value class TagMap private constructor(override val tags: Map<KClass<*>, Any>) : Taggable {
155   companion object {
156     operator fun invoke(tags: Map<KClass<*>, Any>): TagMap = TagMap(tags.toImmutableMap())
157   }
158 }
159