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.ANNOTATION 20 import com.squareup.kotlinpoet.KModifier.COMPANION 21 import com.squareup.kotlinpoet.KModifier.ENUM 22 import com.squareup.kotlinpoet.KModifier.EXPECT 23 import com.squareup.kotlinpoet.KModifier.EXTERNAL 24 import com.squareup.kotlinpoet.KModifier.FUN 25 import com.squareup.kotlinpoet.KModifier.INLINE 26 import com.squareup.kotlinpoet.KModifier.INTERNAL 27 import com.squareup.kotlinpoet.KModifier.PRIVATE 28 import com.squareup.kotlinpoet.KModifier.PROTECTED 29 import com.squareup.kotlinpoet.KModifier.PUBLIC 30 import com.squareup.kotlinpoet.KModifier.SEALED 31 import com.squareup.kotlinpoet.KModifier.VALUE 32 import java.lang.reflect.Type 33 import javax.lang.model.element.Element 34 import kotlin.DeprecationLevel.ERROR 35 import kotlin.reflect.KClass 36 37 /** A generated class, interface, or enum declaration. */ 38 @OptIn(ExperimentalKotlinPoetApi::class) 39 public class TypeSpec private constructor( 40 builder: Builder, 41 private val tagMap: TagMap = builder.buildTagMap(), 42 private val delegateOriginatingElements: OriginatingElementsHolder = builder.originatingElements 43 .plus(builder.typeSpecs.flatMap(TypeSpec::originatingElements)) 44 .buildOriginatingElements(), 45 private val contextReceivers: ContextReceivers = builder.buildContextReceivers(), 46 ) : Taggable by tagMap, 47 OriginatingElementsHolder by delegateOriginatingElements, 48 ContextReceivable by contextReceivers, 49 Annotatable, 50 Documentable, 51 TypeSpecHolder, 52 MemberSpecHolder { 53 public val kind: Kind = builder.kind 54 public val name: String? = builder.name 55 override val kdoc: CodeBlock = builder.kdoc.build() 56 override val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() 57 public val modifiers: Set<KModifier> = builder.modifiers.toImmutableSet() 58 public val typeVariables: List<TypeVariableName> = builder.typeVariables.toImmutableList() 59 public val primaryConstructor: FunSpec? = builder.primaryConstructor 60 public val superclass: TypeName = builder.superclass 61 public val superclassConstructorParameters: List<CodeBlock> = 62 builder.superclassConstructorParameters.toImmutableList() 63 64 public val isEnum: Boolean = builder.isEnum 65 public val isAnnotation: Boolean = builder.isAnnotation 66 public val isCompanion: Boolean = builder.isCompanion 67 public val isAnonymousClass: Boolean = builder.isAnonymousClass 68 public val isFunctionalInterface: Boolean = builder.isFunInterface 69 70 /** 71 * Map of superinterfaces - entries with a null value represent a regular superinterface (with 72 * no delegation), while non-null [CodeBlock] values represent delegates 73 * for the corresponding [TypeSpec] interface (key) value 74 */ 75 public val superinterfaces: Map<TypeName, CodeBlock?> = builder.superinterfaces.toImmutableMap() 76 public val enumConstants: Map<String, TypeSpec> = builder.enumConstants.toImmutableMap() 77 override val propertySpecs: List<PropertySpec> = builder.propertySpecs.toImmutableList() 78 public val initializerBlock: CodeBlock = builder.initializerBlock.build() 79 public val initializerIndex: Int = builder.initializerIndex 80 override val funSpecs: List<FunSpec> = builder.funSpecs.toImmutableList() 81 public override val typeSpecs: List<TypeSpec> = builder.typeSpecs.toImmutableList() 82 internal val nestedTypesSimpleNames = typeSpecs.map { it.name }.toImmutableSet() 83 84 @Deprecated("Use annotations property", ReplaceWith("annotations"), ERROR) 85 public val annotationSpecs: List<AnnotationSpec> get() = annotations 86 87 @JvmOverloads 88 public fun toBuilder(kind: Kind = this.kind, name: String? = this.name): Builder { 89 val builder = Builder(kind, name) 90 builder.modifiers += modifiers 91 builder.kdoc.add(kdoc) 92 builder.annotations += annotations 93 builder.typeVariables += typeVariables 94 builder.superclass = superclass 95 builder.superclassConstructorParameters += superclassConstructorParameters 96 builder.enumConstants += enumConstants 97 builder.propertySpecs += propertySpecs 98 builder.funSpecs += funSpecs 99 builder.typeSpecs += typeSpecs 100 builder.initializerBlock.add(initializerBlock) 101 builder.initializerIndex = initializerIndex 102 builder.superinterfaces.putAll(superinterfaces) 103 builder.primaryConstructor = primaryConstructor 104 builder.tags += tagMap.tags 105 builder.originatingElements += originatingElements 106 builder.contextReceiverTypes += contextReceiverTypes 107 return builder 108 } 109 110 internal fun emit( 111 codeWriter: CodeWriter, 112 enumName: String?, 113 implicitModifiers: Set<KModifier> = emptySet(), 114 isNestedExternal: Boolean = false, 115 ) { 116 // Types. 117 val areNestedExternal = EXTERNAL in modifiers || isNestedExternal 118 119 // Nested classes interrupt wrapped line indentation. Stash the current wrapping state and put 120 // it back afterwards when this type is complete. 121 val previousStatementLine = codeWriter.statementLine 122 codeWriter.statementLine = -1 123 124 val constructorProperties: Map<String, PropertySpec> = constructorProperties() 125 val superclassConstructorParametersBlock = superclassConstructorParameters.joinToCode() 126 127 try { 128 if (enumName != null) { 129 codeWriter.emitKdoc(kdocWithConstructorDocs()) 130 codeWriter.emitAnnotations(annotations, false) 131 codeWriter.emitCode("%N", enumName) 132 if (superclassConstructorParametersBlock.isNotEmpty()) { 133 codeWriter.emit("(") 134 codeWriter.emitCode(superclassConstructorParametersBlock) 135 codeWriter.emit(")") 136 } 137 if (hasNoBody) { 138 return // Avoid unnecessary braces "{}". 139 } 140 codeWriter.emit(" {\n") 141 } else if (isAnonymousClass) { 142 codeWriter.emitCode("object") 143 val supertype = if (superclass != ANY) { 144 if (!areNestedExternal && !modifiers.contains(EXPECT)) { 145 listOf(CodeBlock.of(" %T(%L)", superclass, superclassConstructorParametersBlock)) 146 } else { 147 listOf(CodeBlock.of(" %T", superclass)) 148 } 149 } else { 150 listOf() 151 } 152 153 val allSuperTypes = supertype + if (superinterfaces.isNotEmpty()) { 154 superinterfaces.keys.map { CodeBlock.of(" %T", it) } 155 } else { 156 emptyList() 157 } 158 159 if (allSuperTypes.isNotEmpty()) { 160 codeWriter.emitCode(" :") 161 codeWriter.emitCode(allSuperTypes.joinToCode(",")) 162 } 163 if (hasNoBody) { 164 codeWriter.emit(" {\n}") 165 return 166 } 167 codeWriter.emit(" {\n") 168 } else { 169 codeWriter.emitKdoc(kdocWithConstructorDocs()) 170 codeWriter.emitContextReceivers(contextReceiverTypes, suffix = "\n") 171 codeWriter.emitAnnotations(annotations, false) 172 codeWriter.emitModifiers( 173 modifiers, 174 if (isNestedExternal) setOf(PUBLIC, EXTERNAL) else setOf(PUBLIC), 175 ) 176 codeWriter.emit(kind.declarationKeyword) 177 if (name != null) { 178 codeWriter.emitCode(" %N", this) 179 } 180 codeWriter.emitTypeVariables(typeVariables) 181 182 var wrapSupertypes = false 183 primaryConstructor?.let { 184 codeWriter.pushType(this) // avoid name collisions when emitting primary constructor 185 val emittedAnnotations = it.annotations.isNotEmpty() 186 val useKeyword = it.annotations.isNotEmpty() || it.modifiers.isNotEmpty() 187 188 if (it.annotations.isNotEmpty()) { 189 codeWriter.emit(" ") 190 codeWriter.emitAnnotations(it.annotations, true) 191 } 192 193 if (it.modifiers.isNotEmpty()) { 194 if (!emittedAnnotations) codeWriter.emit(" ") 195 codeWriter.emitModifiers(it.modifiers) 196 } 197 198 if (useKeyword) { 199 codeWriter.emit("constructor") 200 } 201 202 it.parameters.emit(codeWriter, forceNewLines = true) { param -> 203 wrapSupertypes = true 204 205 val property = constructorProperties[param.name] 206 if (property != null) { 207 property.emit( 208 codeWriter, 209 setOf(PUBLIC), 210 withInitializer = false, 211 inline = true, 212 inlineAnnotations = false, 213 ) 214 param.emitDefaultValue(codeWriter) 215 } else { 216 param.emit(codeWriter, inlineAnnotations = false) 217 } 218 } 219 220 codeWriter.popType() 221 } 222 223 val types = listOf(superclass).filter { it != ANY }.map { 224 if (primaryConstructor != null || funSpecs.none(FunSpec::isConstructor)) { 225 if (!areNestedExternal && !modifiers.contains(EXPECT)) { 226 CodeBlock.of("%T(%L)", it, superclassConstructorParametersBlock) 227 } else { 228 CodeBlock.of("%T", it) 229 } 230 } else { 231 CodeBlock.of("%T", it) 232 } 233 } 234 val superTypes = types + superinterfaces.entries.map { (type, init) -> 235 if (init == null) CodeBlock.of("%T", type) else CodeBlock.of("%T by %L", type, init) 236 } 237 238 if (superTypes.isNotEmpty()) { 239 val separator = if (wrapSupertypes) ",\n " else ", " 240 codeWriter.emitCode(superTypes.joinToCode(separator = separator, prefix = " : ")) 241 } 242 243 codeWriter.emitWhereBlock(typeVariables) 244 245 if (hasNoBody) { 246 codeWriter.emit("\n") 247 return // Avoid unnecessary braces "{}". 248 } 249 codeWriter.emit(" {\n") 250 } 251 252 codeWriter.pushType(this) 253 codeWriter.indent() 254 var firstMember = true 255 for ((key, value) in enumConstants.entries) { 256 if (!firstMember) codeWriter.emit("\n") 257 value.emit(codeWriter, key) 258 codeWriter.emit(",") 259 firstMember = false 260 } 261 if (isEnum) { 262 if (!firstMember) { 263 codeWriter.emit("\n") 264 } 265 if (propertySpecs.isNotEmpty() || funSpecs.isNotEmpty() || typeSpecs.isNotEmpty()) { 266 codeWriter.emit(";\n") 267 } 268 } 269 270 val cachedHasInitializer = hasInitializer 271 var initializerEmitted = false 272 fun possiblyEmitInitializer() { 273 if (initializerEmitted) return 274 initializerEmitted = true 275 if (cachedHasInitializer) { 276 if (!firstMember) codeWriter.emit("\n") 277 codeWriter.emitCode(initializerBlock) 278 firstMember = false 279 } 280 } 281 282 // Properties and initializer block. 283 for ((index, propertySpec) in propertySpecs.withIndex()) { 284 // Initializer block. 285 if (index == initializerIndex) { 286 possiblyEmitInitializer() 287 } 288 if (constructorProperties.containsKey(propertySpec.name)) { 289 continue 290 } 291 if (!firstMember) codeWriter.emit("\n") 292 propertySpec.emit(codeWriter, kind.implicitPropertyModifiers(modifiers)) 293 firstMember = false 294 } 295 296 // One last try in case the initializer index is after all properties 297 possiblyEmitInitializer() 298 299 if (primaryConstructor != null && primaryConstructor.body.isNotEmpty()) { 300 codeWriter.emit("init {\n") 301 codeWriter.indent() 302 codeWriter.emitCode(primaryConstructor.body) 303 codeWriter.unindent() 304 codeWriter.emit("}\n") 305 } 306 307 // Constructors. 308 for (funSpec in funSpecs) { 309 if (!funSpec.isConstructor) continue 310 if (!firstMember) codeWriter.emit("\n") 311 funSpec.emit(codeWriter, name, kind.implicitFunctionModifiers(modifiers + implicitModifiers), false) 312 firstMember = false 313 } 314 315 // Functions. 316 for (funSpec in funSpecs) { 317 if (funSpec.isConstructor) continue 318 if (!firstMember) codeWriter.emit("\n") 319 funSpec.emit(codeWriter, name, kind.implicitFunctionModifiers(modifiers + implicitModifiers), true) 320 firstMember = false 321 } 322 323 for (typeSpec in typeSpecs) { 324 if (!firstMember) codeWriter.emit("\n") 325 typeSpec.emit(codeWriter, null, kind.implicitTypeModifiers(modifiers + implicitModifiers), isNestedExternal = areNestedExternal) 326 firstMember = false 327 } 328 329 codeWriter.unindent() 330 codeWriter.popType() 331 332 codeWriter.emit("}") 333 if (enumName == null && !isAnonymousClass) { 334 codeWriter.emit("\n") // If this type isn't also a value, include a trailing newline. 335 } 336 } finally { 337 codeWriter.statementLine = previousStatementLine 338 } 339 } 340 341 /** Returns the properties that can be declared inline as constructor parameters. */ 342 private fun constructorProperties(): Map<String, PropertySpec> { 343 if (primaryConstructor == null) return emptyMap() 344 345 // Properties added after the initializer are not permitted to be inlined into the constructor 346 // due to ordering concerns. 347 val range = if (hasInitializer) { 348 0..<initializerIndex 349 } else { 350 propertySpecs.indices 351 } 352 val result: MutableMap<String, PropertySpec> = LinkedHashMap() 353 for (propertyIndex in range) { 354 val property = propertySpecs[propertyIndex] 355 if (property.getter != null || property.setter != null) continue 356 val parameter = primaryConstructor.parameter(property.name) ?: continue 357 if (parameter.type != property.type) continue 358 if (!isPropertyInitializerConstructorParameter(property, parameter)) { 359 continue 360 } 361 362 result[property.name] = property.fromPrimaryConstructorParameter(parameter) 363 } 364 return result 365 } 366 367 /** 368 * Returns true if the property can be declared inline as a constructor parameter 369 */ 370 private fun isPropertyInitializerConstructorParameter( 371 property: PropertySpec, 372 parameter: ParameterSpec, 373 ): Boolean { 374 val parameterName = CodeBlock.of("%N", parameter).toString() 375 val initializerCode = property.initializer.toString().escapeIfNecessary(validate = false) 376 return parameterName == initializerCode 377 } 378 379 /** 380 * Returns KDoc comments including those of the primary constructor and its parameters. 381 * 382 * Parameters' KDocs, if present, will always be printed in the type header. 383 */ 384 private fun kdocWithConstructorDocs(): CodeBlock { 385 val classKdoc = kdoc.ensureEndsWithNewLine() 386 val constructorKdoc = buildCodeBlock { 387 if (primaryConstructor != null) { 388 if (primaryConstructor.kdoc.isNotEmpty()) { 389 add("@constructor %L", primaryConstructor.kdoc.ensureEndsWithNewLine()) 390 } 391 primaryConstructor.parameters.forEach { parameter -> 392 if (parameter.kdoc.isNotEmpty()) { 393 add("@param %L %L", parameter.name, parameter.kdoc.ensureEndsWithNewLine()) 394 } 395 } 396 } 397 } 398 return listOf(classKdoc, constructorKdoc) 399 .filter(CodeBlock::isNotEmpty) 400 .joinToCode(separator = "\n") 401 } 402 403 private val hasInitializer: Boolean get() = initializerIndex != -1 && initializerBlock.isNotEmpty() 404 405 private val hasNoBody: Boolean 406 get() { 407 if (propertySpecs.isNotEmpty()) { 408 val constructorProperties = constructorProperties() 409 for (propertySpec in propertySpecs) { 410 if (!constructorProperties.containsKey(propertySpec.name)) { 411 return false 412 } 413 } 414 } 415 return enumConstants.isEmpty() && 416 initializerBlock.isEmpty() && 417 (primaryConstructor?.body?.isEmpty() ?: true) && 418 funSpecs.isEmpty() && 419 typeSpecs.isEmpty() 420 } 421 422 override fun equals(other: Any?): Boolean { 423 if (this === other) return true 424 if (other == null) return false 425 if (javaClass != other.javaClass) return false 426 return toString() == other.toString() 427 } 428 429 override fun hashCode(): Int = toString().hashCode() 430 431 override fun toString(): String = buildCodeString { emit(this, null) } 432 433 public enum class Kind( 434 internal val declarationKeyword: String, 435 internal val defaultImplicitPropertyModifiers: Set<KModifier>, 436 internal val defaultImplicitFunctionModifiers: Set<KModifier>, 437 internal val defaultImplicitTypeModifiers: Set<KModifier>, 438 ) { 439 CLASS("class", setOf(PUBLIC), setOf(PUBLIC), setOf()), 440 OBJECT("object", setOf(PUBLIC), setOf(PUBLIC), setOf()), 441 INTERFACE("interface", setOf(PUBLIC, ABSTRACT), setOf(PUBLIC, ABSTRACT), setOf()), 442 ; 443 444 internal fun implicitPropertyModifiers(modifiers: Set<KModifier>): Set<KModifier> { 445 return defaultImplicitPropertyModifiers + when { 446 ANNOTATION in modifiers -> emptySet() 447 EXPECT in modifiers -> setOf(EXPECT) 448 EXTERNAL in modifiers -> setOf(EXTERNAL) 449 else -> emptySet() 450 } 451 } 452 453 internal fun implicitFunctionModifiers(modifiers: Set<KModifier> = setOf()): Set<KModifier> { 454 return defaultImplicitFunctionModifiers + when { 455 EXPECT in modifiers -> setOf(EXPECT) 456 EXTERNAL in modifiers -> setOf(EXTERNAL) 457 else -> emptySet() 458 } 459 } 460 461 internal fun implicitTypeModifiers(modifiers: Set<KModifier> = setOf()): Set<KModifier> { 462 return defaultImplicitTypeModifiers + when { 463 EXPECT in modifiers -> setOf(EXPECT) 464 EXTERNAL in modifiers -> setOf(EXTERNAL) 465 else -> emptySet() 466 } 467 } 468 } 469 470 public class Builder internal constructor( 471 internal var kind: Kind, 472 internal val name: String?, 473 vararg modifiers: KModifier, 474 ) : Taggable.Builder<Builder>, 475 OriginatingElementsHolder.Builder<Builder>, 476 ContextReceivable.Builder<Builder>, 477 Annotatable.Builder<Builder>, 478 Documentable.Builder<Builder>, 479 TypeSpecHolder.Builder<Builder>, 480 MemberSpecHolder.Builder<Builder> { 481 internal var primaryConstructor: FunSpec? = null 482 internal var superclass: TypeName = ANY 483 internal val initializerBlock = CodeBlock.builder() 484 public var initializerIndex: Int = -1 485 internal val isAnonymousClass get() = name == null && kind == Kind.CLASS 486 internal val isExternal get() = EXTERNAL in modifiers 487 internal val isEnum get() = kind == Kind.CLASS && ENUM in modifiers 488 internal val isAnnotation get() = kind == Kind.CLASS && ANNOTATION in modifiers 489 internal val isCompanion get() = kind == Kind.OBJECT && COMPANION in modifiers 490 internal val isInlineOrValClass get() = kind == Kind.CLASS && 491 (INLINE in modifiers || VALUE in modifiers) 492 internal val isSimpleClass get() = kind == Kind.CLASS && !isEnum && !isAnnotation 493 internal val isFunInterface get() = kind == Kind.INTERFACE && FUN in modifiers 494 495 override val tags: MutableMap<KClass<*>, Any> = mutableMapOf() 496 override val kdoc: CodeBlock.Builder = CodeBlock.builder() 497 override val originatingElements: MutableList<Element> = mutableListOf() 498 override val annotations: MutableList<AnnotationSpec> = mutableListOf() 499 500 @ExperimentalKotlinPoetApi 501 override val contextReceiverTypes: MutableList<TypeName> = mutableListOf() 502 public val modifiers: MutableSet<KModifier> = mutableSetOf(*modifiers) 503 public val superinterfaces: MutableMap<TypeName, CodeBlock?> = mutableMapOf() 504 public val enumConstants: MutableMap<String, TypeSpec> = mutableMapOf() 505 public val typeVariables: MutableList<TypeVariableName> = mutableListOf() 506 public val superclassConstructorParameters: MutableList<CodeBlock> = mutableListOf() 507 public val propertySpecs: MutableList<PropertySpec> = mutableListOf() 508 public val funSpecs: MutableList<FunSpec> = mutableListOf() 509 public val typeSpecs: MutableList<TypeSpec> = mutableListOf() 510 511 @Deprecated("Use annotations property", ReplaceWith("annotations"), ERROR) 512 public val annotationSpecs: MutableList<AnnotationSpec> get() = annotations 513 514 public fun addModifiers(vararg modifiers: KModifier): Builder = apply { 515 check(!isAnonymousClass) { "forbidden on anonymous types." } 516 this.modifiers += modifiers 517 } 518 519 public fun addModifiers(modifiers: Iterable<KModifier>): Builder = apply { 520 check(!isAnonymousClass) { "forbidden on anonymous types." } 521 this.modifiers += modifiers 522 } 523 524 public fun addTypeVariables(typeVariables: Iterable<TypeVariableName>): Builder = apply { 525 this.typeVariables += typeVariables 526 } 527 528 public fun addTypeVariable(typeVariable: TypeVariableName): Builder = apply { 529 typeVariables += typeVariable 530 } 531 532 public fun primaryConstructor(primaryConstructor: FunSpec?): Builder = apply { 533 check(kind == Kind.CLASS) { 534 "$kind can't have a primary constructor" 535 } 536 if (primaryConstructor != null) { 537 require(primaryConstructor.isConstructor) { 538 "expected a constructor but was ${primaryConstructor.name}" 539 } 540 541 if (isInlineOrValClass) { 542 check(primaryConstructor.parameters.size == 1) { 543 "value/inline classes must have 1 parameter in constructor" 544 } 545 } 546 547 require( 548 primaryConstructor.delegateConstructor == null && 549 primaryConstructor.delegateConstructorArguments.isEmpty(), 550 ) { 551 "primary constructor can't delegate to other constructors" 552 } 553 } 554 this.primaryConstructor = primaryConstructor 555 } 556 557 public fun superclass(superclass: TypeName): Builder = apply { 558 checkCanHaveSuperclass() 559 check(this.superclass === ANY) { "superclass already set to ${this.superclass}" } 560 this.superclass = superclass 561 } 562 563 private fun checkCanHaveSuperclass() { 564 check(isSimpleClass || kind == Kind.OBJECT) { 565 "only classes can have super classes, not $kind" 566 } 567 check(!isInlineOrValClass) { 568 "value/inline classes cannot have super classes" 569 } 570 } 571 572 private fun checkCanHaveInitializerBlocks() { 573 check(isSimpleClass || isEnum || kind == Kind.OBJECT) { 574 "$kind can't have initializer blocks" 575 } 576 check(EXPECT !in modifiers) { 577 "expect $kind can't have initializer blocks" 578 } 579 } 580 581 @DelicateKotlinPoetApi( 582 message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + 583 "using the kotlinpoet-metadata APIs instead.", 584 ) 585 public fun superclass(superclass: Type): Builder = superclass(superclass.asTypeName()) 586 587 public fun superclass(superclass: KClass<*>): Builder = superclass(superclass.asTypeName()) 588 589 public fun addSuperclassConstructorParameter( 590 format: String, 591 vararg args: Any, 592 ): Builder = apply { 593 addSuperclassConstructorParameter(CodeBlock.of(format, *args)) 594 } 595 596 public fun addSuperclassConstructorParameter(codeBlock: CodeBlock): Builder = apply { 597 checkCanHaveSuperclass() 598 this.superclassConstructorParameters += codeBlock 599 } 600 601 public fun addSuperinterfaces(superinterfaces: Iterable<TypeName>): Builder = apply { 602 this.superinterfaces.putAll(superinterfaces.map { it to null }) 603 } 604 605 public fun addSuperinterface( 606 superinterface: TypeName, 607 delegate: CodeBlock = CodeBlock.EMPTY, 608 ): Builder = apply { 609 if (delegate.isEmpty()) { 610 this.superinterfaces[superinterface] = null 611 } else { 612 require(isSimpleClass || kind == Kind.OBJECT) { 613 "delegation only allowed for classes and objects (found $kind '$name')" 614 } 615 require(!superinterface.isNullable) { 616 "expected non-nullable type but was '${superinterface.copy(nullable = false)}'" 617 } 618 require(this.superinterfaces[superinterface] == null) { 619 "'$name' can not delegate to $superinterface by $delegate with existing declaration by " + 620 "${this.superinterfaces[superinterface]}" 621 } 622 this.superinterfaces[superinterface] = delegate 623 } 624 } 625 626 @DelicateKotlinPoetApi( 627 message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + 628 "using the kotlinpoet-metadata APIs instead.", 629 ) 630 public fun addSuperinterface( 631 superinterface: Type, 632 delegate: CodeBlock = CodeBlock.EMPTY, 633 ): Builder = addSuperinterface(superinterface.asTypeName(), delegate) 634 635 public fun addSuperinterface( 636 superinterface: KClass<*>, 637 delegate: CodeBlock = CodeBlock.EMPTY, 638 ): Builder = addSuperinterface(superinterface.asTypeName(), delegate) 639 640 public fun addSuperinterface( 641 superinterface: KClass<*>, 642 constructorParameterName: String, 643 ): Builder = addSuperinterface(superinterface.asTypeName(), constructorParameterName) 644 645 public fun addSuperinterface( 646 superinterface: TypeName, 647 constructorParameter: String, 648 ): Builder = apply { 649 requireNotNull(primaryConstructor) { 650 "delegating to constructor parameter requires not-null constructor" 651 } 652 val parameter = primaryConstructor?.parameter(constructorParameter) 653 requireNotNull(parameter) { 654 "no such constructor parameter '$constructorParameter' to delegate to for type '$name'" 655 } 656 addSuperinterface(superinterface, CodeBlock.of(constructorParameter)) 657 } 658 659 @JvmOverloads public fun addEnumConstant( 660 name: String, 661 typeSpec: TypeSpec = anonymousClassBuilder().build(), 662 ): Builder = apply { 663 require(name != "name" && name != "ordinal") { 664 "constant with name \"$name\" conflicts with a supertype member with the same name" 665 } 666 enumConstants[name] = typeSpec 667 } 668 669 override fun addProperty(propertySpec: PropertySpec): Builder = apply { 670 if (EXPECT in modifiers) { 671 require(propertySpec.initializer == null) { 672 "properties in expect classes can't have initializers" 673 } 674 require(propertySpec.getter == null && propertySpec.setter == null) { 675 "properties in expect classes can't have getters and setters" 676 } 677 } 678 if (isEnum) { 679 require(propertySpec.name != "name" && propertySpec.name != "ordinal") { 680 "${propertySpec.name} is a final supertype member and can't be redeclared or overridden" 681 } 682 } 683 propertySpecs += propertySpec 684 } 685 686 public fun addInitializerBlock(block: CodeBlock): Builder = apply { 687 checkCanHaveInitializerBlocks() 688 // Set index to however many properties we have 689 // All properties added after this point are declared as such, including any that initialize 690 // to a constructor param. 691 initializerIndex = propertySpecs.size 692 initializerBlock.add("init {\n") 693 .indent() 694 .add(block) 695 .unindent() 696 .add("}\n") 697 } 698 699 override fun addFunction(funSpec: FunSpec): Builder = apply { 700 funSpecs += funSpec 701 } 702 703 override fun addType(typeSpec: TypeSpec): Builder = apply { 704 typeSpecs += typeSpec 705 } 706 707 @ExperimentalKotlinPoetApi 708 override fun contextReceivers(receiverTypes: Iterable<TypeName>): Builder = apply { 709 check(isSimpleClass) { "contextReceivers can only be applied on simple classes" } 710 contextReceiverTypes += receiverTypes 711 } 712 713 //region Overrides for binary compatibility 714 @Suppress("RedundantOverride") 715 override fun addAnnotation(annotationSpec: AnnotationSpec): Builder = super.addAnnotation(annotationSpec) 716 717 @Suppress("RedundantOverride") 718 override fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = 719 super.addAnnotations(annotationSpecs) 720 721 @Suppress("RedundantOverride") 722 override fun addAnnotation(annotation: ClassName): Builder = super.addAnnotation(annotation) 723 724 @DelicateKotlinPoetApi( 725 message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + 726 "using the kotlinpoet-metadata APIs instead.", 727 ) 728 override fun addAnnotation(annotation: Class<*>): Builder = super.addAnnotation(annotation) 729 730 @Suppress("RedundantOverride") 731 override fun addAnnotation(annotation: KClass<*>): Builder = super.addAnnotation(annotation) 732 733 @Suppress("RedundantOverride") 734 override fun addKdoc(format: String, vararg args: Any): Builder = super.addKdoc(format, *args) 735 736 @Suppress("RedundantOverride") 737 override fun addKdoc(block: CodeBlock): Builder = super.addKdoc(block) 738 739 @Suppress("RedundantOverride") 740 override fun addTypes(typeSpecs: Iterable<TypeSpec>): Builder = super.addTypes(typeSpecs) 741 742 @Suppress("RedundantOverride") 743 override fun addProperties(propertySpecs: Iterable<PropertySpec>): Builder = 744 super.addProperties(propertySpecs) 745 746 @Suppress("RedundantOverride") 747 override fun addProperty(name: String, type: TypeName, vararg modifiers: KModifier): Builder = 748 super.addProperty(name, type, *modifiers) 749 750 @DelicateKotlinPoetApi( 751 message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + 752 "using the kotlinpoet-metadata APIs instead.", 753 ) 754 override fun addProperty(name: String, type: Type, vararg modifiers: KModifier): Builder = 755 super.addProperty(name, type, *modifiers) 756 757 @Suppress("RedundantOverride") 758 override fun addProperty(name: String, type: KClass<*>, vararg modifiers: KModifier): Builder = 759 super.addProperty(name, type, *modifiers) 760 761 @Suppress("RedundantOverride") 762 override fun addProperty(name: String, type: TypeName, modifiers: Iterable<KModifier>): Builder = 763 super.addProperty(name, type, modifiers) 764 765 @DelicateKotlinPoetApi( 766 message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + 767 "using the kotlinpoet-metadata APIs instead.", 768 ) 769 override fun addProperty(name: String, type: Type, modifiers: Iterable<KModifier>): Builder = 770 super.addProperty(name, type, modifiers) 771 772 @Suppress("RedundantOverride") 773 override fun addProperty(name: String, type: KClass<*>, modifiers: Iterable<KModifier>): Builder = 774 super.addProperty(name, type, modifiers) 775 776 @Suppress("RedundantOverride") 777 override fun addFunctions(funSpecs: Iterable<FunSpec>): Builder = super.addFunctions(funSpecs) 778 //endregion 779 780 public fun build(): TypeSpec { 781 if (enumConstants.isNotEmpty()) { 782 check(isEnum) { "$name is not an enum and cannot have enum constants" } 783 } 784 785 if (superclassConstructorParameters.isNotEmpty()) { 786 checkCanHaveSuperclass() 787 788 check(!isExternal) { 789 "delegated constructor call in external class is not allowed" 790 } 791 } 792 check(!(isExternal && funSpecs.any { it.delegateConstructor != null })) { 793 "delegated constructor call in external class is not allowed" 794 } 795 796 check(!(isAnonymousClass && typeVariables.isNotEmpty())) { 797 "typevariables are forbidden on anonymous types" 798 } 799 800 val isAbstract = ABSTRACT in modifiers || SEALED in modifiers || kind == Kind.INTERFACE || isEnum 801 for (funSpec in funSpecs) { 802 require(isAbstract || ABSTRACT !in funSpec.modifiers) { 803 "non-abstract type $name cannot declare abstract function ${funSpec.name}" 804 } 805 when { 806 kind == Kind.INTERFACE -> { 807 requireNoneOf(funSpec.modifiers, INTERNAL, PROTECTED) 808 requireNoneOrOneOf(funSpec.modifiers, ABSTRACT, PRIVATE) 809 } 810 isAnnotation -> { 811 throw IllegalArgumentException("annotation class $name cannot declare member function ${funSpec.name}") 812 } 813 EXPECT in modifiers -> require(funSpec.body.isEmpty()) { 814 "functions in expect classes can't have bodies" 815 } 816 } 817 } 818 819 for (propertySpec in propertySpecs) { 820 require(isAbstract || ABSTRACT !in propertySpec.modifiers) { 821 "non-abstract type $name cannot declare abstract property ${propertySpec.name}" 822 } 823 if (propertySpec.contextReceiverTypes.isNotEmpty()) { 824 if (ABSTRACT !in kind.implicitPropertyModifiers(modifiers) + propertySpec.modifiers) { 825 requireNotNull(propertySpec.getter) { "non-abstract properties with context receivers require a ${FunSpec.GETTER}" } 826 if (propertySpec.mutable) { 827 requireNotNull(propertySpec.setter) { "non-abstract mutable properties with context receivers require a ${FunSpec.SETTER}" } 828 } 829 } 830 } 831 } 832 833 if (isAnnotation) { 834 primaryConstructor?.let { 835 requireNoneOf(it.modifiers, INTERNAL, PROTECTED, PRIVATE, ABSTRACT) 836 } 837 } 838 839 if (primaryConstructor == null) { 840 require(funSpecs.none { it.isConstructor } || superclassConstructorParameters.isEmpty()) { 841 "types without a primary constructor cannot specify secondary constructors and " + 842 "superclass constructor parameters" 843 } 844 } 845 846 if (isInlineOrValClass) { 847 primaryConstructor?.let { 848 check(it.parameters.size == 1) { 849 "value/inline classes must have 1 parameter in constructor" 850 } 851 } 852 853 check(propertySpecs.size > 0) { 854 "value/inline classes must have at least 1 property" 855 } 856 857 val constructorParamName = primaryConstructor?.parameters?.firstOrNull()?.name 858 constructorParamName?.let { paramName -> 859 val underlyingProperty = propertySpecs.find { it.name == paramName } 860 requireNotNull(underlyingProperty) { 861 "value/inline classes must have a single read-only (val) property parameter." 862 } 863 check(!underlyingProperty.mutable) { 864 "value/inline classes must have a single read-only (val) property parameter." 865 } 866 } 867 check(superclass == Any::class.asTypeName()) { 868 "value/inline classes cannot have super classes" 869 } 870 } 871 872 if (isFunInterface) { 873 // Note: Functional interfaces can contain any number of non-abstract functions. 874 val abstractFunSpecs = funSpecs.filter { ABSTRACT in it.modifiers } 875 check(abstractFunSpecs.size == 1) { 876 "Functional interfaces must have exactly one abstract function. Contained " + 877 "${abstractFunSpecs.size}: ${abstractFunSpecs.map { it.name }}" 878 } 879 } 880 881 when (typeSpecs.count { it.isCompanion }) { 882 0 -> Unit 883 1 -> { 884 require(isSimpleClass || kind == Kind.INTERFACE || isEnum || isAnnotation) { 885 "$kind types can't have a companion object" 886 } 887 } 888 else -> { 889 throw IllegalArgumentException("Multiple companion objects are present but only one is allowed.") 890 } 891 } 892 893 return TypeSpec(this) 894 } 895 } 896 897 public companion object { 898 @JvmStatic public fun classBuilder(name: String): Builder = Builder(Kind.CLASS, name) 899 900 @JvmStatic public fun classBuilder(className: ClassName): Builder = classBuilder(className.simpleName) 901 902 @Deprecated( 903 "Use classBuilder() instead. This function will be removed in KotlinPoet 2.0.", 904 ReplaceWith("TypeSpec.classBuilder(name).addModifiers(KModifier.EXPECT)"), 905 ) 906 @JvmStatic 907 public fun expectClassBuilder(name: String): Builder = Builder(Kind.CLASS, name, EXPECT) 908 909 @Deprecated( 910 "Use classBuilder() instead. This function will be removed in KotlinPoet 2.0.", 911 ReplaceWith("TypeSpec.classBuilder(className).addModifiers(KModifier.EXPECT)"), 912 ) 913 @JvmStatic 914 public fun expectClassBuilder(className: ClassName): Builder = classBuilder(className.simpleName).addModifiers(EXPECT) 915 916 @Deprecated( 917 "Use classBuilder() instead. This function will be removed in KotlinPoet 2.0.", 918 ReplaceWith("TypeSpec.classBuilder(name).addModifiers(KModifier.VALUE)"), 919 ) 920 @JvmStatic 921 public fun valueClassBuilder(name: String): Builder = Builder(Kind.CLASS, name, VALUE) 922 923 @JvmStatic public fun objectBuilder(name: String): Builder = Builder(Kind.OBJECT, name) 924 925 @JvmStatic public fun objectBuilder(className: ClassName): Builder = objectBuilder(className.simpleName) 926 927 @JvmStatic @JvmOverloads 928 public fun companionObjectBuilder(name: String? = null): Builder = 929 Builder(Kind.OBJECT, name, COMPANION) 930 931 @JvmStatic public fun interfaceBuilder(name: String): Builder = Builder(Kind.INTERFACE, name) 932 933 @JvmStatic public fun interfaceBuilder(className: ClassName): Builder = 934 interfaceBuilder(className.simpleName) 935 936 @JvmStatic public fun funInterfaceBuilder(name: String): Builder = 937 Builder(Kind.INTERFACE, name, FUN) 938 939 @JvmStatic public fun funInterfaceBuilder(className: ClassName): Builder = 940 funInterfaceBuilder(className.simpleName) 941 942 @JvmStatic public fun enumBuilder(name: String): Builder = Builder(Kind.CLASS, name, ENUM) 943 944 @JvmStatic public fun enumBuilder(className: ClassName): Builder = 945 enumBuilder(className.simpleName) 946 947 @JvmStatic public fun anonymousClassBuilder(): Builder = Builder(Kind.CLASS, null) 948 949 @JvmStatic public fun annotationBuilder(name: String): Builder = 950 Builder(Kind.CLASS, name, ANNOTATION) 951 952 @JvmStatic public fun annotationBuilder(className: ClassName): Builder = 953 annotationBuilder(className.simpleName) 954 } 955 } 956