1 /* <lambda>null2 * Copyright (C) 2015 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.ABSTRACT 19 import com.squareup.kotlinpoet.KModifier.EXPECT 20 import com.squareup.kotlinpoet.KModifier.EXTERNAL 21 import com.squareup.kotlinpoet.KModifier.INLINE 22 import com.squareup.kotlinpoet.KModifier.VARARG 23 import java.lang.reflect.Type 24 import javax.lang.model.element.Element 25 import javax.lang.model.element.ExecutableElement 26 import javax.lang.model.element.Modifier 27 import javax.lang.model.type.DeclaredType 28 import javax.lang.model.type.ExecutableType 29 import javax.lang.model.type.TypeVariable 30 import javax.lang.model.util.Types 31 import kotlin.DeprecationLevel.WARNING 32 import kotlin.reflect.KClass 33 34 /** A generated function declaration. */ 35 @OptIn(ExperimentalKotlinPoetApi::class) 36 public class FunSpec private constructor( 37 builder: Builder, 38 private val tagMap: TagMap = builder.buildTagMap(), 39 private val delegateOriginatingElementsHolder: OriginatingElementsHolder = builder.buildOriginatingElements(), 40 private val contextReceivers: ContextReceivers = builder.buildContextReceivers(), 41 ) : Taggable by tagMap, 42 OriginatingElementsHolder by delegateOriginatingElementsHolder, 43 ContextReceivable by contextReceivers, 44 Annotatable, 45 Documentable { 46 public val name: String = builder.name 47 override val kdoc: CodeBlock = builder.kdoc.build() 48 public val returnKdoc: CodeBlock = builder.returnKdoc 49 public val receiverKdoc: CodeBlock = builder.receiverKdoc 50 override val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() 51 public val modifiers: Set<KModifier> = builder.modifiers.toImmutableSet() 52 public val typeVariables: List<TypeVariableName> = builder.typeVariables.toImmutableList() 53 public val receiverType: TypeName? = builder.receiverType 54 55 public val returnType: TypeName = builder.returnType 56 public val parameters: List<ParameterSpec> = builder.parameters.toImmutableList() 57 public val delegateConstructor: String? = builder.delegateConstructor 58 public val delegateConstructorArguments: List<CodeBlock> = 59 builder.delegateConstructorArguments.toImmutableList() 60 public val body: CodeBlock = builder.body.build() 61 private val isExternalGetter = name == GETTER && builder.modifiers.contains(EXTERNAL) 62 private val isEmptySetter = name == SETTER && parameters.isEmpty() 63 64 init { 65 require(body.isEmpty() || !builder.modifiers.containsAnyOf(ABSTRACT, EXPECT)) { 66 "abstract or expect function ${builder.name} cannot have code" 67 } 68 if (name == GETTER) { 69 require(!isExternalGetter || body.isEmpty()) { 70 "external getter cannot have code" 71 } 72 } else if (name == SETTER) { 73 require(parameters.size <= 1) { 74 "$name can have at most one parameter" 75 } 76 require(parameters.isNotEmpty() || body.isEmpty()) { 77 "parameterless setter cannot have code" 78 } 79 } 80 require(INLINE in modifiers || typeVariables.none { it.isReified }) { 81 "only type parameters of inline functions can be reified!" 82 } 83 } 84 85 internal fun parameter(name: String) = parameters.firstOrNull { it.name == name } 86 87 internal fun emit( 88 codeWriter: CodeWriter, 89 enclosingName: String?, 90 implicitModifiers: Set<KModifier>, 91 includeKdocTags: Boolean = false, 92 ) { 93 if (includeKdocTags) { 94 codeWriter.emitKdoc(kdocWithTags()) 95 } else { 96 codeWriter.emitKdoc(kdoc.ensureEndsWithNewLine()) 97 } 98 codeWriter.emitContextReceivers(contextReceiverTypes, suffix = "\n") 99 codeWriter.emitAnnotations(annotations, false) 100 codeWriter.emitModifiers(modifiers, implicitModifiers) 101 102 if (!isConstructor && !name.isAccessor) { 103 codeWriter.emitCode("fun·") 104 } 105 106 if (typeVariables.isNotEmpty()) { 107 codeWriter.emitTypeVariables(typeVariables) 108 codeWriter.emit(" ") 109 } 110 emitSignature(codeWriter, enclosingName) 111 codeWriter.emitWhereBlock(typeVariables) 112 113 if (shouldOmitBody(implicitModifiers)) { 114 codeWriter.emit("\n") 115 return 116 } 117 118 val asExpressionBody = body.asExpressionBody() 119 120 if (asExpressionBody != null) { 121 codeWriter.emitCode(CodeBlock.of(" = %L", asExpressionBody), ensureTrailingNewline = true) 122 } else if (!isEmptySetter) { 123 codeWriter.emitCode("·{\n") 124 codeWriter.indent() 125 codeWriter.emitCode(body.returnsWithoutLinebreak(), ensureTrailingNewline = true) 126 codeWriter.unindent() 127 codeWriter.emit("}\n") 128 } else { 129 codeWriter.emit("\n") 130 } 131 } 132 133 private fun shouldOmitBody(implicitModifiers: Set<KModifier>): Boolean { 134 if (canNotHaveBody(implicitModifiers)) { 135 check(body.isEmpty()) { "function $name cannot have code" } 136 return true 137 } 138 return canBodyBeOmitted(implicitModifiers) && body.isEmpty() 139 } 140 141 private fun canNotHaveBody(implicitModifiers: Set<KModifier>) = 142 ABSTRACT in modifiers || EXPECT in modifiers + implicitModifiers 143 144 private fun canBodyBeOmitted(implicitModifiers: Set<KModifier>) = isConstructor || 145 EXTERNAL in (modifiers + implicitModifiers) || 146 ABSTRACT in modifiers 147 148 private fun emitSignature(codeWriter: CodeWriter, enclosingName: String?) { 149 if (isConstructor) { 150 codeWriter.emitCode("constructor", enclosingName) 151 } else if (name == GETTER) { 152 codeWriter.emitCode("get") 153 } else if (name == SETTER) { 154 codeWriter.emitCode("set") 155 } else { 156 if (receiverType != null) { 157 if (receiverType is LambdaTypeName) { 158 codeWriter.emitCode("(%T).", receiverType) 159 } else { 160 codeWriter.emitCode("%T.", receiverType) 161 } 162 } 163 codeWriter.emitCode("%N", this) 164 } 165 166 if (!isEmptySetter && !isExternalGetter) { 167 parameters.emit(codeWriter) { param -> 168 param.emit(codeWriter, includeType = name != SETTER) 169 } 170 } 171 172 if (returnType != UNIT || emitUnitReturnType()) { 173 codeWriter.emitCode(": %T", returnType) 174 } 175 176 if (delegateConstructor != null) { 177 codeWriter.emitCode( 178 delegateConstructorArguments 179 .joinToCode(prefix = " : $delegateConstructor(", suffix = ")"), 180 ) 181 } 182 } 183 184 public val isConstructor: Boolean get() = name.isConstructor 185 186 public val isAccessor: Boolean get() = name.isAccessor 187 188 private fun kdocWithTags(): CodeBlock { 189 return with(kdoc.ensureEndsWithNewLine().toBuilder()) { 190 var newLineAdded = false 191 val isNotEmpty = isNotEmpty() 192 if (receiverKdoc.isNotEmpty()) { 193 if (isNotEmpty) { 194 add("\n") 195 newLineAdded = true 196 } 197 add("@receiver %L", receiverKdoc.ensureEndsWithNewLine()) 198 } 199 parameters.forEachIndexed { index, parameterSpec -> 200 if (parameterSpec.kdoc.isNotEmpty()) { 201 if (!newLineAdded && index == 0 && isNotEmpty) { 202 add("\n") 203 newLineAdded = true 204 } 205 add("@param %L %L", parameterSpec.name, parameterSpec.kdoc.ensureEndsWithNewLine()) 206 } 207 } 208 if (returnKdoc.isNotEmpty()) { 209 if (!newLineAdded && isNotEmpty) { 210 add("\n") 211 newLineAdded = true 212 } 213 add("@return %L", returnKdoc.ensureEndsWithNewLine()) 214 } 215 build() 216 } 217 } 218 219 /** 220 * Returns whether [Unit] should be emitted as the return type. 221 * 222 * [Unit] is emitted as return type on a function only if it is an expression body. 223 */ 224 private fun emitUnitReturnType(): Boolean { 225 if (isConstructor) { 226 return false 227 } 228 if (name == GETTER || name == SETTER) { 229 // Getter/setters don't emit return types 230 return false 231 } 232 233 return body.asExpressionBody() != null 234 } 235 236 private fun CodeBlock.asExpressionBody(): CodeBlock? { 237 val codeBlock = this.trim() 238 val asReturnExpressionBody = codeBlock.withoutPrefix(RETURN_EXPRESSION_BODY_PREFIX_SPACE) 239 ?: codeBlock.withoutPrefix(RETURN_EXPRESSION_BODY_PREFIX_NBSP) 240 if (asReturnExpressionBody != null) { 241 return asReturnExpressionBody 242 } 243 if (codeBlock.withoutPrefix(THROW_EXPRESSION_BODY_PREFIX_SPACE) != null || 244 codeBlock.withoutPrefix(THROW_EXPRESSION_BODY_PREFIX_NBSP) != null 245 ) { 246 return codeBlock 247 } 248 return null 249 } 250 251 private fun CodeBlock.returnsWithoutLinebreak(): CodeBlock { 252 val returnWithSpace = RETURN_EXPRESSION_BODY_PREFIX_SPACE.formatParts[0] 253 val returnWithNbsp = RETURN_EXPRESSION_BODY_PREFIX_NBSP.formatParts[0] 254 var originCodeBlockBuilder: CodeBlock.Builder? = null 255 for ((i, formatPart) in formatParts.withIndex()) { 256 if (formatPart.startsWith(returnWithSpace)) { 257 val builder = originCodeBlockBuilder ?: toBuilder() 258 originCodeBlockBuilder = builder 259 builder.formatParts[i] = formatPart.replaceFirst(returnWithSpace, returnWithNbsp) 260 } 261 } 262 return originCodeBlockBuilder?.build() ?: this 263 } 264 265 override fun equals(other: Any?): Boolean { 266 if (this === other) return true 267 if (other == null) return false 268 if (javaClass != other.javaClass) return false 269 return toString() == other.toString() 270 } 271 272 override fun hashCode(): Int = toString().hashCode() 273 274 override fun toString(): String = buildCodeString { 275 emit( 276 codeWriter = this, 277 enclosingName = "Constructor", 278 implicitModifiers = TypeSpec.Kind.CLASS.implicitFunctionModifiers(), 279 includeKdocTags = true, 280 ) 281 } 282 283 @JvmOverloads 284 public fun toBuilder(name: String = this.name): Builder { 285 val builder = Builder(name) 286 builder.kdoc.add(kdoc) 287 builder.returnKdoc = returnKdoc 288 builder.receiverKdoc = receiverKdoc 289 builder.annotations += annotations 290 builder.modifiers += modifiers 291 builder.typeVariables += typeVariables 292 builder.returnType = returnType 293 builder.parameters += parameters 294 builder.delegateConstructor = delegateConstructor 295 builder.delegateConstructorArguments += delegateConstructorArguments 296 builder.body.add(body) 297 builder.receiverType = receiverType 298 builder.tags += tagMap.tags 299 builder.originatingElements += originatingElements 300 builder.contextReceiverTypes += contextReceiverTypes 301 return builder 302 } 303 304 public class Builder internal constructor( 305 internal val name: String, 306 ) : Taggable.Builder<Builder>, 307 OriginatingElementsHolder.Builder<Builder>, 308 ContextReceivable.Builder<Builder>, 309 Annotatable.Builder<Builder>, 310 Documentable.Builder<Builder> { 311 internal var returnKdoc = CodeBlock.EMPTY 312 internal var receiverKdoc = CodeBlock.EMPTY 313 internal var receiverType: TypeName? = null 314 internal var returnType: TypeName = UNIT 315 internal var delegateConstructor: String? = null 316 internal var delegateConstructorArguments = listOf<CodeBlock>() 317 internal val body = CodeBlock.builder() 318 override val kdoc: CodeBlock.Builder = CodeBlock.builder() 319 override val annotations: MutableList<AnnotationSpec> = mutableListOf() 320 public val modifiers: MutableList<KModifier> = mutableListOf() 321 public val typeVariables: MutableList<TypeVariableName> = mutableListOf() 322 public val parameters: MutableList<ParameterSpec> = mutableListOf() 323 override val tags: MutableMap<KClass<*>, Any> = mutableMapOf() 324 override val originatingElements: MutableList<Element> = mutableListOf() 325 326 @ExperimentalKotlinPoetApi 327 override val contextReceiverTypes: MutableList<TypeName> = mutableListOf() 328 329 public fun addModifiers(vararg modifiers: KModifier): Builder = apply { 330 this.modifiers += modifiers 331 } 332 333 public fun addModifiers(modifiers: Iterable<KModifier>): Builder = apply { 334 this.modifiers += modifiers 335 } 336 337 public fun jvmModifiers(modifiers: Iterable<Modifier>) { 338 var visibility = KModifier.INTERNAL 339 for (modifier in modifiers) { 340 when (modifier) { 341 Modifier.PUBLIC -> visibility = KModifier.PUBLIC 342 Modifier.PROTECTED -> visibility = KModifier.PROTECTED 343 Modifier.PRIVATE -> visibility = KModifier.PRIVATE 344 Modifier.ABSTRACT -> this.modifiers += KModifier.ABSTRACT 345 Modifier.FINAL -> this.modifiers += KModifier.FINAL 346 Modifier.NATIVE -> this.modifiers += KModifier.EXTERNAL 347 Modifier.DEFAULT -> Unit 348 Modifier.STATIC -> addAnnotation(JvmStatic::class) 349 Modifier.SYNCHRONIZED -> addAnnotation(Synchronized::class) 350 Modifier.STRICTFP -> addAnnotation(Strictfp::class) 351 else -> throw IllegalArgumentException("unexpected fun modifier $modifier") 352 } 353 } 354 this.modifiers += visibility 355 } 356 357 public fun addTypeVariables(typeVariables: Iterable<TypeVariableName>): Builder = apply { 358 this.typeVariables += typeVariables 359 } 360 361 public fun addTypeVariable(typeVariable: TypeVariableName): Builder = apply { 362 typeVariables += typeVariable 363 } 364 365 @ExperimentalKotlinPoetApi 366 override fun contextReceivers(receiverTypes: Iterable<TypeName>): Builder = apply { 367 check(!name.isConstructor) { "constructors cannot have context receivers" } 368 check(!name.isAccessor) { "$name cannot have context receivers" } 369 contextReceiverTypes += receiverTypes 370 } 371 372 @JvmOverloads public fun receiver( 373 receiverType: TypeName, 374 kdoc: CodeBlock = CodeBlock.EMPTY, 375 ): Builder = apply { 376 check(!name.isConstructor) { "$name cannot have receiver type" } 377 this.receiverType = receiverType 378 this.receiverKdoc = kdoc 379 } 380 381 @JvmOverloads public fun receiver( 382 receiverType: Type, 383 kdoc: CodeBlock = CodeBlock.EMPTY, 384 ): Builder = receiver(receiverType.asTypeName(), kdoc) 385 386 public fun receiver( 387 receiverType: Type, 388 kdoc: String, 389 vararg args: Any, 390 ): Builder = receiver(receiverType, CodeBlock.of(kdoc, args)) 391 392 @JvmOverloads public fun receiver( 393 receiverType: KClass<*>, 394 kdoc: CodeBlock = CodeBlock.EMPTY, 395 ): Builder = receiver(receiverType.asTypeName(), kdoc) 396 397 public fun receiver( 398 receiverType: KClass<*>, 399 kdoc: String, 400 vararg args: Any, 401 ): Builder = receiver(receiverType, CodeBlock.of(kdoc, args)) 402 403 @JvmOverloads public fun returns( 404 returnType: TypeName, 405 kdoc: CodeBlock = CodeBlock.EMPTY, 406 ): Builder = apply { 407 check(!name.isConstructor && !name.isAccessor) { "$name cannot have a return type" } 408 this.returnType = returnType 409 this.returnKdoc = kdoc 410 } 411 412 @JvmOverloads public fun returns(returnType: Type, kdoc: CodeBlock = CodeBlock.EMPTY): Builder = 413 returns(returnType.asTypeName(), kdoc) 414 415 public fun returns(returnType: Type, kdoc: String, vararg args: Any): Builder = 416 returns(returnType.asTypeName(), CodeBlock.of(kdoc, args)) 417 418 @JvmOverloads public fun returns( 419 returnType: KClass<*>, 420 kdoc: CodeBlock = CodeBlock.EMPTY, 421 ): Builder = returns(returnType.asTypeName(), kdoc) 422 423 public fun returns(returnType: KClass<*>, kdoc: String, vararg args: Any): Builder = 424 returns(returnType.asTypeName(), CodeBlock.of(kdoc, args)) 425 426 public fun addParameters(parameterSpecs: Iterable<ParameterSpec>): Builder = apply { 427 for (parameterSpec in parameterSpecs) { 428 addParameter(parameterSpec) 429 } 430 } 431 432 public fun addParameter(parameterSpec: ParameterSpec): Builder = apply { 433 parameters += parameterSpec 434 } 435 436 public fun callThisConstructor(args: List<CodeBlock>): Builder = apply { 437 callConstructor("this", args) 438 } 439 440 public fun callThisConstructor(args: Iterable<CodeBlock>): Builder = apply { 441 callConstructor("this", args.toList()) 442 } 443 444 public fun callThisConstructor(vararg args: String): Builder = apply { 445 callConstructor("this", args.map { CodeBlock.of(it) }) 446 } 447 448 public fun callThisConstructor(vararg args: CodeBlock = emptyArray()): Builder = apply { 449 callConstructor("this", args.toList()) 450 } 451 452 public fun callSuperConstructor(args: Iterable<CodeBlock>): Builder = apply { 453 callConstructor("super", args.toList()) 454 } 455 456 public fun callSuperConstructor(args: List<CodeBlock>): Builder = apply { 457 callConstructor("super", args) 458 } 459 460 public fun callSuperConstructor(vararg args: String): Builder = apply { 461 callConstructor("super", args.map { CodeBlock.of(it) }) 462 } 463 464 public fun callSuperConstructor(vararg args: CodeBlock = emptyArray()): Builder = apply { 465 callConstructor("super", args.toList()) 466 } 467 468 private fun callConstructor(constructor: String, args: List<CodeBlock>) { 469 check(name.isConstructor) { "only constructors can delegate to other constructors!" } 470 delegateConstructor = constructor 471 delegateConstructorArguments = args 472 } 473 474 public fun addParameter(name: String, type: TypeName, vararg modifiers: KModifier): Builder = 475 addParameter(ParameterSpec.builder(name, type, *modifiers).build()) 476 477 public fun addParameter(name: String, type: Type, vararg modifiers: KModifier): Builder = 478 addParameter(name, type.asTypeName(), *modifiers) 479 480 public fun addParameter(name: String, type: KClass<*>, vararg modifiers: KModifier): Builder = 481 addParameter(name, type.asTypeName(), *modifiers) 482 483 public fun addParameter(name: String, type: TypeName, modifiers: Iterable<KModifier>): Builder = 484 addParameter(ParameterSpec.builder(name, type, modifiers).build()) 485 486 public fun addParameter(name: String, type: Type, modifiers: Iterable<KModifier>): Builder = 487 addParameter(name, type.asTypeName(), modifiers) 488 489 public fun addParameter( 490 name: String, 491 type: KClass<*>, 492 modifiers: Iterable<KModifier>, 493 ): Builder = addParameter(name, type.asTypeName(), modifiers) 494 495 public fun addCode(format: String, vararg args: Any?): Builder = apply { 496 body.add(format, *args) 497 } 498 499 public fun addNamedCode(format: String, args: Map<String, *>): Builder = apply { 500 body.addNamed(format, args) 501 } 502 503 public fun addCode(codeBlock: CodeBlock): Builder = apply { 504 body.add(codeBlock) 505 } 506 507 public fun addComment(format: String, vararg args: Any): Builder = apply { 508 body.add("//·${format.replace(' ', '·')}\n", *args) 509 } 510 511 /** 512 * @param controlFlow the control flow construct and its code, such as "if (foo == 5)". 513 * * Shouldn't contain braces or newline characters. 514 */ 515 public fun beginControlFlow(controlFlow: String, vararg args: Any): Builder = apply { 516 body.beginControlFlow(controlFlow, *args) 517 } 518 519 /** 520 * @param controlFlow the control flow construct and its code, such as "else if (foo == 10)". 521 * * Shouldn't contain braces or newline characters. 522 */ 523 public fun nextControlFlow(controlFlow: String, vararg args: Any): Builder = apply { 524 body.nextControlFlow(controlFlow, *args) 525 } 526 527 public fun endControlFlow(): Builder = apply { 528 body.endControlFlow() 529 } 530 531 public fun addStatement(format: String, vararg args: Any): Builder = apply { 532 body.addStatement(format, *args) 533 } 534 535 public fun clearBody(): Builder = apply { 536 body.clear() 537 } 538 539 //region Overrides for binary compatibility 540 @Suppress("RedundantOverride") 541 override fun addAnnotation(annotationSpec: AnnotationSpec): Builder = super.addAnnotation(annotationSpec) 542 543 @Suppress("RedundantOverride") 544 override fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = 545 super.addAnnotations(annotationSpecs) 546 547 @Suppress("RedundantOverride") 548 override fun addAnnotation(annotation: ClassName): Builder = super.addAnnotation(annotation) 549 550 @DelicateKotlinPoetApi( 551 message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + 552 "using the kotlinpoet-metadata APIs instead.", 553 ) 554 override fun addAnnotation(annotation: Class<*>): Builder = super.addAnnotation(annotation) 555 556 @Suppress("RedundantOverride") 557 override fun addAnnotation(annotation: KClass<*>): Builder = super.addAnnotation(annotation) 558 559 @Suppress("RedundantOverride") 560 override fun addKdoc(format: String, vararg args: Any): Builder = super.addKdoc(format, *args) 561 562 @Suppress("RedundantOverride") 563 override fun addKdoc(block: CodeBlock): Builder = super.addKdoc(block) 564 //endregion 565 566 public fun build(): FunSpec { 567 check(typeVariables.isEmpty() || !name.isAccessor) { "$name cannot have type variables" } 568 check(!(name == GETTER && parameters.isNotEmpty())) { "$name cannot have parameters" } 569 check(!(name == SETTER && parameters.size > 1)) { "$name can have at most one parameter" } 570 return FunSpec(this) 571 } 572 } 573 574 public companion object { 575 private const val CONSTRUCTOR = "constructor()" 576 internal const val GETTER = "get()" 577 internal const val SETTER = "set()" 578 579 internal val String.isConstructor get() = this == CONSTRUCTOR 580 internal val String.isAccessor get() = this.isOneOf(GETTER, SETTER) 581 582 private val RETURN_EXPRESSION_BODY_PREFIX_SPACE = CodeBlock.of("return ") 583 private val RETURN_EXPRESSION_BODY_PREFIX_NBSP = CodeBlock.of("return·") 584 private val THROW_EXPRESSION_BODY_PREFIX_SPACE = CodeBlock.of("throw ") 585 private val THROW_EXPRESSION_BODY_PREFIX_NBSP = CodeBlock.of("throw·") 586 587 @JvmStatic public fun builder(name: String): Builder = Builder(name) 588 589 /** Create a new function builder from [MemberName.simpleName] */ 590 @JvmStatic public fun builder(memberName: MemberName): Builder = Builder(memberName.simpleName) 591 592 @JvmStatic public fun constructorBuilder(): Builder = Builder(CONSTRUCTOR) 593 594 @JvmStatic public fun getterBuilder(): Builder = Builder(GETTER) 595 596 @JvmStatic public fun setterBuilder(): Builder = Builder(SETTER) 597 598 @DelicateKotlinPoetApi( 599 message = "Element APIs don't give complete information on Kotlin types. Consider using" + 600 " the kotlinpoet-metadata APIs instead.", 601 ) 602 @JvmStatic 603 public fun overriding(method: ExecutableElement): Builder { 604 var modifiers: Set<Modifier> = method.modifiers 605 require( 606 Modifier.PRIVATE !in modifiers && 607 Modifier.FINAL !in modifiers && 608 Modifier.STATIC !in modifiers, 609 ) { 610 "cannot override method with modifiers: $modifiers" 611 } 612 613 val methodName = method.simpleName.toString() 614 val funBuilder = builder(methodName) 615 616 funBuilder.addModifiers(KModifier.OVERRIDE) 617 618 modifiers = modifiers.toMutableSet() 619 modifiers.remove(Modifier.ABSTRACT) 620 funBuilder.jvmModifiers(modifiers) 621 622 method.typeParameters 623 .map { it.asType() as TypeVariable } 624 .map { it.asTypeVariableName() } 625 .forEach { funBuilder.addTypeVariable(it) } 626 627 funBuilder.returns(method.returnType.asTypeName()) 628 funBuilder.addParameters(ParameterSpec.parametersOf(method)) 629 if (method.isVarArgs) { 630 funBuilder.parameters[funBuilder.parameters.lastIndex] = funBuilder.parameters.last() 631 .toBuilder() 632 .addModifiers(VARARG) 633 .build() 634 } 635 636 if (method.thrownTypes.isNotEmpty()) { 637 val throwsValueString = method.thrownTypes.joinToString { "%T::class" } 638 funBuilder.addAnnotation( 639 AnnotationSpec.builder(Throws::class) 640 .addMember(throwsValueString, *method.thrownTypes.toTypedArray()) 641 .build(), 642 ) 643 } 644 645 return funBuilder 646 } 647 648 @Deprecated( 649 message = "Element APIs don't give complete information on Kotlin types. Consider using" + 650 " the kotlinpoet-metadata APIs instead.", 651 level = WARNING, 652 ) 653 @JvmStatic 654 public fun overriding( 655 method: ExecutableElement, 656 enclosing: DeclaredType, 657 types: Types, 658 ): Builder { 659 val executableType = types.asMemberOf(enclosing, method) as ExecutableType 660 val resolvedParameterTypes = executableType.parameterTypes 661 val resolvedReturnType = executableType.returnType 662 663 val builder = overriding(method) 664 builder.returns(resolvedReturnType.asTypeName()) 665 var i = 0 666 val size = builder.parameters.size 667 while (i < size) { 668 val parameter = builder.parameters[i] 669 val type = resolvedParameterTypes[i].asTypeName() 670 builder.parameters[i] = parameter.toBuilder(parameter.name, type).build() 671 i++ 672 } 673 674 return builder 675 } 676 } 677 } 678