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