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 equalsnull87 override fun equals(other: Any?): Boolean { 88 if (this === other) return true 89 if (javaClass != other?.javaClass) return false 90 if (!super.equals(other)) return false 91 92 other as LambdaTypeName 93 94 if (receiver != other.receiver) return false 95 if (contextReceivers != other.contextReceivers) return false 96 if (returnType != other.returnType) return false 97 if (isSuspending != other.isSuspending) return false 98 if (parameters != other.parameters) return false 99 100 return true 101 } 102 hashCodenull103 override fun hashCode(): Int { 104 var result = super.hashCode() 105 result = 31 * result + (receiver?.hashCode() ?: 0) 106 result = 31 * result + contextReceivers.hashCode() 107 result = 31 * result + returnType.hashCode() 108 result = 31 * result + isSuspending.hashCode() 109 result = 31 * result + parameters.hashCode() 110 return result 111 } 112 public companion object { 113 /** Returns a lambda type with `returnType` and parameters listed in `parameters`. */ 114 @ExperimentalKotlinPoetApi @JvmStatic getnull115 public fun get( 116 receiver: TypeName? = null, 117 parameters: List<ParameterSpec> = emptyList(), 118 returnType: TypeName, 119 contextReceivers: List<TypeName> = emptyList(), 120 ): LambdaTypeName = LambdaTypeName(receiver, contextReceivers, parameters, returnType) 121 122 /** Returns a lambda type with `returnType` and parameters listed in `parameters`. */ 123 @JvmStatic public fun get( 124 receiver: TypeName? = null, 125 parameters: List<ParameterSpec> = emptyList(), 126 returnType: TypeName, 127 ): LambdaTypeName = LambdaTypeName(receiver, emptyList(), parameters, returnType) 128 129 /** Returns a lambda type with `returnType` and parameters listed in `parameters`. */ 130 @JvmStatic public fun get( 131 receiver: TypeName? = null, 132 vararg parameters: TypeName = emptyArray(), 133 returnType: TypeName, 134 ): LambdaTypeName { 135 return LambdaTypeName( 136 receiver, 137 emptyList(), 138 parameters.toList().map { ParameterSpec.unnamed(it) }, 139 returnType, 140 ) 141 } 142 143 /** Returns a lambda type with `returnType` and parameters listed in `parameters`. */ getnull144 @JvmStatic public fun get( 145 receiver: TypeName? = null, 146 vararg parameters: ParameterSpec = emptyArray(), 147 returnType: TypeName, 148 ): LambdaTypeName = LambdaTypeName(receiver, emptyList(), parameters.toList(), returnType) 149 } 150 } 151