1 /* 2 * Copyright (C) 2021 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 @OptIn(ExperimentalKotlinPoetApi::class) 21 public class LambdaTypeName private constructor( 22 public val receiver: TypeName? = null, 23 @property:ExperimentalKotlinPoetApi 24 public val contextReceivers: List<TypeName> = emptyList(), 25 parameters: List<ParameterSpec> = emptyList(), 26 public val returnType: TypeName = UNIT, 27 nullable: Boolean = false, 28 public val isSuspending: Boolean = false, 29 annotations: List<AnnotationSpec> = emptyList(), 30 tags: Map<KClass<*>, Any> = emptyMap(), 31 ) : TypeName(nullable, annotations, TagMap(tags)) { 32 public val parameters: List<ParameterSpec> = parameters.toImmutableList() 33 34 init { 35 for (param in parameters) { <lambda>null36 require(param.annotations.isEmpty()) { "Parameters with annotations are not allowed" } <lambda>null37 require(param.modifiers.isEmpty()) { "Parameters with modifiers are not allowed" } <lambda>null38 require(param.defaultValue == null) { "Parameters with default values are not allowed" } 39 } 40 } 41 copynull42 override fun copy( 43 nullable: Boolean, 44 annotations: List<AnnotationSpec>, 45 tags: Map<KClass<*>, Any>, 46 ): LambdaTypeName { 47 return copy(nullable, annotations, this.isSuspending, tags) 48 } 49 copynull50 public fun copy( 51 nullable: Boolean = this.isNullable, 52 annotations: List<AnnotationSpec> = this.annotations.toList(), 53 suspending: Boolean = this.isSuspending, 54 tags: Map<KClass<*>, Any> = this.tags.toMap(), 55 ): LambdaTypeName { 56 return LambdaTypeName(receiver, contextReceivers, parameters, returnType, nullable, suspending, annotations, tags) 57 } 58 emitnull59 override fun emit(out: CodeWriter): CodeWriter { 60 if (isNullable) { 61 out.emit("(") 62 } 63 64 if (isSuspending) { 65 out.emit("suspend·") 66 } 67 68 out.emitContextReceivers(contextReceivers, suffix = "·") 69 70 receiver?.let { 71 if (it.isAnnotated) { 72 out.emitCode("(%T).", it) 73 } else { 74 out.emitCode("%T.", it) 75 } 76 } 77 78 parameters.emit(out) 79 out.emitCode(if (returnType is LambdaTypeName) "·->·(%T)" else "·->·%T", returnType) 80 81 if (isNullable) { 82 out.emit(")") 83 } 84 return out 85 } 86 87 public companion object { 88 /** Returns a lambda type with `returnType` and parameters listed in `parameters`. */ 89 @ExperimentalKotlinPoetApi @JvmStatic getnull90 public fun get( 91 receiver: TypeName? = null, 92 parameters: List<ParameterSpec> = emptyList(), 93 returnType: TypeName, 94 contextReceivers: List<TypeName> = emptyList(), 95 ): LambdaTypeName = LambdaTypeName(receiver, contextReceivers, parameters, returnType) 96 97 /** Returns a lambda type with `returnType` and parameters listed in `parameters`. */ 98 @JvmStatic public fun get( 99 receiver: TypeName? = null, 100 parameters: List<ParameterSpec> = emptyList(), 101 returnType: TypeName, 102 ): LambdaTypeName = LambdaTypeName(receiver, emptyList(), parameters, returnType) 103 104 /** Returns a lambda type with `returnType` and parameters listed in `parameters`. */ 105 @JvmStatic public fun get( 106 receiver: TypeName? = null, 107 vararg parameters: TypeName = emptyArray(), 108 returnType: TypeName, 109 ): LambdaTypeName { 110 return LambdaTypeName( 111 receiver, 112 emptyList(), 113 parameters.toList().map { ParameterSpec.unnamed(it) }, 114 returnType, 115 ) 116 } 117 118 /** Returns a lambda type with `returnType` and parameters listed in `parameters`. */ getnull119 @JvmStatic public fun get( 120 receiver: TypeName? = null, 121 vararg parameters: ParameterSpec = emptyArray(), 122 returnType: TypeName, 123 ): LambdaTypeName = LambdaTypeName(receiver, emptyList(), parameters.toList(), returnType) 124 } 125 } 126