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