blob: df26b6092d147cae4d2885f0ceb3a9ce1da6d95f [file] [log] [blame]
/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.squareup.kotlinpoet
import java.io.IOException
import java.lang.reflect.Modifier
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.ArrayList
import java.util.Arrays
import java.util.LinkedHashMap
import kotlin.reflect.KClass
class ParameterizedTypeName internal constructor(
private val enclosingType: ParameterizedTypeName?,
val rawType: ClassName,
typeArguments: List<TypeName>,
annotations: List<AnnotationSpec> = ArrayList<AnnotationSpec>())
: TypeName(annotations) {
val typeArguments: List<TypeName> = Util.immutableList(typeArguments)
init {
require(!this.typeArguments.isEmpty() || enclosingType != null) {
"no type arguments: $rawType"
}
}
override fun annotated(annotations: List<AnnotationSpec>)
= ParameterizedTypeName(enclosingType, rawType, typeArguments, this.annotations + annotations)
override fun withoutAnnotations()
= ParameterizedTypeName(enclosingType, rawType, typeArguments, ArrayList<AnnotationSpec>())
@Throws(IOException::class)
override fun abstractEmit(out: CodeWriter): CodeWriter {
if (enclosingType != null) {
enclosingType.emitAnnotations(out)
enclosingType.emit(out)
out.emit("." + rawType.simpleName())
} else {
rawType.emitAnnotations(out)
rawType.emit(out)
}
if (!typeArguments.isEmpty()) {
out.emitAndIndent("<")
var firstParameter = true
for (parameter in typeArguments) {
if (!firstParameter) out.emitAndIndent(", ")
parameter.emitAnnotations(out)
parameter.abstractEmit(out)
firstParameter = false
}
out.emitAndIndent(">")
}
return out
}
/**
* Returns a new [ParameterizedTypeName] instance for the specified `name` as nested inside this
* class.
*/
fun nestedClass(name: String)
= ParameterizedTypeName(
this, rawType.nestedClass(name), ArrayList<TypeName>(), ArrayList<AnnotationSpec>())
/**
* Returns a new [ParameterizedTypeName] instance for the specified `name` as nested inside this
* class, with the specified `typeArguments`.
*/
fun nestedClass(name: String, typeArguments: List<TypeName>)
= ParameterizedTypeName(
this, rawType.nestedClass(name), typeArguments, ArrayList<AnnotationSpec>())
companion object {
/** Returns a parameterized type, applying `typeArguments` to `rawType`. */
@JvmStatic fun get(rawType: ClassName, vararg typeArguments: TypeName)
= ParameterizedTypeName(null, rawType, Arrays.asList(*typeArguments))
/** Returns a parameterized type, applying `typeArguments` to `rawType`. */
@JvmStatic fun get(rawType: KClass<*>, vararg typeArguments: KClass<*>)
= ParameterizedTypeName(null, ClassName.get(rawType), TypeName.list(*typeArguments))
/** Returns a parameterized type, applying `typeArguments` to `rawType`. */
@JvmStatic fun get(rawType: Class<*>, vararg typeArguments: Type)
= ParameterizedTypeName(null, ClassName.get(rawType), list(*typeArguments))
/** Returns a parameterized type equivalent to `type`. */
@JvmStatic fun get(type: ParameterizedType)
= get(type, LinkedHashMap<Type, TypeVariableName>())
/** Returns a parameterized type equivalent to `type`. */
internal fun get(
type: ParameterizedType,
map: MutableMap<Type, TypeVariableName>): ParameterizedTypeName {
val rawType = ClassName.get(type.rawType as Class<*>)
val ownerType = if (type.ownerType is ParameterizedType
&& !Modifier.isStatic((type.rawType as Class<*>).modifiers))
type.ownerType as ParameterizedType else
null
val typeArguments = TypeName.list(*type.actualTypeArguments, map = map)
return if (ownerType != null)
get(ownerType, map).nestedClass(rawType.simpleName(), typeArguments) else
ParameterizedTypeName(null, rawType, typeArguments)
}
}
}