1 /*
2 * Copyright (C) 2017 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 com.squareup.kotlinpoet.KModifier.ACTUAL
19 import com.squareup.kotlinpoet.KModifier.INTERNAL
20 import com.squareup.kotlinpoet.KModifier.PRIVATE
21 import com.squareup.kotlinpoet.KModifier.PUBLIC
22 import java.lang.reflect.Type
23 import kotlin.reflect.KClass
24
25 /** A generated typealias declaration */
26 public class TypeAliasSpec private constructor(
27 builder: Builder,
28 private val tagMap: TagMap = builder.buildTagMap(),
<lambda>null29 ) : Taggable by tagMap {
30 public val name: String = builder.name
31 public val type: TypeName = builder.type
32 public val modifiers: Set<KModifier> = builder.modifiers.toImmutableSet()
33 public val typeVariables: List<TypeVariableName> = builder.typeVariables.toImmutableList()
34 public val kdoc: CodeBlock = builder.kdoc.build()
35 public val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList()
36
37 internal fun emit(codeWriter: CodeWriter) {
38 codeWriter.emitKdoc(kdoc.ensureEndsWithNewLine())
39 codeWriter.emitAnnotations(annotations, false)
40 codeWriter.emitModifiers(modifiers, setOf(PUBLIC))
41 codeWriter.emitCode("typealias %N", name)
42 codeWriter.emitTypeVariables(typeVariables)
43 codeWriter.emitCode(" = %T", type)
44 codeWriter.emit("\n")
45 }
46
47 override fun equals(other: Any?): Boolean {
48 if (this === other) return true
49 if (other == null) return false
50 if (javaClass != other.javaClass) return false
51 return toString() == other.toString()
52 }
53
54 override fun hashCode(): Int = toString().hashCode()
55
56 override fun toString(): String = buildCodeString { emit(this) }
57
58 @JvmOverloads
59 public fun toBuilder(name: String = this.name, type: TypeName = this.type): Builder {
60 val builder = Builder(name, type)
61 builder.modifiers += modifiers
62 builder.typeVariables += typeVariables
63 builder.kdoc.add(kdoc)
64 builder.annotations += annotations
65 builder.tags += tagMap.tags
66 return builder
67 }
68
69 public class Builder internal constructor(
70 internal val name: String,
71 internal val type: TypeName,
72 ) : Taggable.Builder<Builder> {
73 internal val kdoc = CodeBlock.builder()
74
75 public val modifiers: MutableSet<KModifier> = mutableSetOf()
76 public val typeVariables: MutableSet<TypeVariableName> = mutableSetOf()
77 public val annotations: MutableList<AnnotationSpec> = mutableListOf()
78 override val tags: MutableMap<KClass<*>, Any> = mutableMapOf()
79
80 public fun addModifiers(vararg modifiers: KModifier): Builder = apply {
81 modifiers.forEach(this::addModifier)
82 }
83
84 public fun addModifiers(modifiers: Iterable<KModifier>): Builder = apply {
85 modifiers.forEach(this::addModifier)
86 }
87
88 private fun addModifier(modifier: KModifier) {
89 this.modifiers.add(modifier)
90 }
91
92 public fun addTypeVariables(typeVariables: Iterable<TypeVariableName>): Builder = apply {
93 this.typeVariables += typeVariables
94 }
95
96 public fun addTypeVariable(typeVariable: TypeVariableName): Builder = apply {
97 typeVariables += typeVariable
98 }
99
100 public fun addKdoc(format: String, vararg args: Any): Builder = apply {
101 kdoc.add(format, *args)
102 }
103
104 public fun addKdoc(block: CodeBlock): Builder = apply {
105 kdoc.add(block)
106 }
107
108 public fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = apply {
109 this.annotations += annotationSpecs
110 }
111
112 public fun addAnnotation(annotationSpec: AnnotationSpec): Builder = apply {
113 annotations += annotationSpec
114 }
115
116 public fun addAnnotation(annotation: ClassName): Builder = apply {
117 annotations += AnnotationSpec.builder(annotation).build()
118 }
119
120 @DelicateKotlinPoetApi(
121 message = "Java reflection APIs don't give complete information on Kotlin types. Consider " +
122 "using the kotlinpoet-metadata APIs instead.",
123 )
124 public fun addAnnotation(annotation: Class<*>): Builder =
125 addAnnotation(annotation.asClassName())
126
127 public fun addAnnotation(annotation: KClass<*>): Builder =
128 addAnnotation(annotation.asClassName())
129
130 public fun build(): TypeAliasSpec {
131 for (it in modifiers) {
132 require(it in ALLOWABLE_MODIFIERS) {
133 "unexpected typealias modifier $it"
134 }
135 }
136 return TypeAliasSpec(this)
137 }
138
139 private companion object {
140 private val ALLOWABLE_MODIFIERS = setOf(PUBLIC, INTERNAL, PRIVATE, ACTUAL)
141 }
142 }
143
144 public companion object {
145 @JvmStatic public fun builder(name: String, type: TypeName): Builder = Builder(name, type)
146
147 @DelicateKotlinPoetApi(
148 message = "Java reflection APIs don't give complete information on Kotlin types. Consider " +
149 "using the kotlinpoet-metadata APIs instead.",
150 )
151 @JvmStatic
152 public fun builder(name: String, type: Type): Builder =
153 builder(name, type.asTypeName())
154
155 @JvmStatic public fun builder(name: String, type: KClass<*>): Builder =
156 builder(name, type.asTypeName())
157 }
158 }
159