From 7a57880871faa967a6626cf48a9b14ba21a9fc8f Mon Sep 17 00:00:00 2001 From: David Rawson Date: Fri, 17 Nov 2023 08:44:42 +1300 Subject: [PATCH] Extract interface for constructs that can hold a TypeSpec and their builders (#1723) --- kotlinpoet/api/kotlinpoet.api | 31 ++++++++++++++----- .../com/squareup/kotlinpoet/FileSpec.kt | 12 +++++-- .../com/squareup/kotlinpoet/TypeSpec.kt | 17 +++++----- .../com/squareup/kotlinpoet/TypeSpecHolder.kt | 31 +++++++++++++++++++ 4 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpecHolder.kt diff --git a/kotlinpoet/api/kotlinpoet.api b/kotlinpoet/api/kotlinpoet.api index 5e1513d5e5..62b6afbecc 100644 --- a/kotlinpoet/api/kotlinpoet.api +++ b/kotlinpoet/api/kotlinpoet.api @@ -181,7 +181,7 @@ public final class com/squareup/kotlinpoet/Dynamic : com/squareup/kotlinpoet/Typ public abstract interface annotation class com/squareup/kotlinpoet/ExperimentalKotlinPoetApi : java/lang/annotation/Annotation { } -public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/Taggable { +public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/Taggable, com/squareup/kotlinpoet/TypeSpecHolder { public static final field Companion Lcom/squareup/kotlinpoet/FileSpec$Companion; public static final fun builder (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public static final fun builder (Lcom/squareup/kotlinpoet/MemberName;)Lcom/squareup/kotlinpoet/FileSpec$Builder; @@ -197,6 +197,7 @@ public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/An public final fun getPackageName ()Ljava/lang/String; public final fun getRelativePath ()Ljava/lang/String; public fun getTags ()Ljava/util/Map; + public fun getTypeSpecs ()Ljava/util/List; public fun hashCode ()I public final fun isScript ()Z public static final fun scriptBuilder (Ljava/lang/String;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; @@ -216,7 +217,7 @@ public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/An public final fun writeTo (Ljavax/annotation/processing/Filer;)V } -public final class com/squareup/kotlinpoet/FileSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/Taggable$Builder { +public final class com/squareup/kotlinpoet/FileSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/Taggable$Builder, com/squareup/kotlinpoet/TypeSpecHolder$Builder { public final fun addAliasedImport (Lcom/squareup/kotlinpoet/ClassName;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addAliasedImport (Lcom/squareup/kotlinpoet/ClassName;Ljava/lang/String;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addAliasedImport (Lcom/squareup/kotlinpoet/MemberName;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; @@ -254,8 +255,11 @@ public final class com/squareup/kotlinpoet/FileSpec$Builder : com/squareup/kotli public final fun addNamedCode (Ljava/lang/String;Ljava/util/Map;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addProperty (Lcom/squareup/kotlinpoet/PropertySpec;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addStatement (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder; - public final fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public synthetic fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder; public final fun addTypeAlias (Lcom/squareup/kotlinpoet/TypeAliasSpec;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public synthetic fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder; public final fun beginControlFlow (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun build ()Lcom/squareup/kotlinpoet/FileSpec; public final fun clearBody ()Lcom/squareup/kotlinpoet/FileSpec$Builder; @@ -928,7 +932,7 @@ public final class com/squareup/kotlinpoet/TypeNames { public static final fun get (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/ClassName; } -public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/ContextReceivable, com/squareup/kotlinpoet/Documentable, com/squareup/kotlinpoet/OriginatingElementsHolder, com/squareup/kotlinpoet/Taggable { +public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/ContextReceivable, com/squareup/kotlinpoet/Documentable, com/squareup/kotlinpoet/OriginatingElementsHolder, com/squareup/kotlinpoet/Taggable, com/squareup/kotlinpoet/TypeSpecHolder { public static final field Companion Lcom/squareup/kotlinpoet/TypeSpec$Companion; public static final fun annotationBuilder (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public static final fun annotationBuilder (Ljava/lang/String;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; @@ -962,7 +966,7 @@ public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/An public final fun getSuperclassConstructorParameters ()Ljava/util/List; public final fun getSuperinterfaces ()Ljava/util/Map; public fun getTags ()Ljava/util/Map; - public final fun getTypeSpecs ()Ljava/util/List; + public fun getTypeSpecs ()Ljava/util/List; public final fun getTypeVariables ()Ljava/util/List; public fun hashCode ()I public static final fun interfaceBuilder (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; @@ -984,7 +988,7 @@ public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/An public static final fun valueClassBuilder (Ljava/lang/String;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; } -public final class com/squareup/kotlinpoet/TypeSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/ContextReceivable$Builder, com/squareup/kotlinpoet/Documentable$Builder, com/squareup/kotlinpoet/OriginatingElementsHolder$Builder, com/squareup/kotlinpoet/Taggable$Builder { +public final class com/squareup/kotlinpoet/TypeSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/ContextReceivable$Builder, com/squareup/kotlinpoet/Documentable$Builder, com/squareup/kotlinpoet/OriginatingElementsHolder$Builder, com/squareup/kotlinpoet/Taggable$Builder, com/squareup/kotlinpoet/TypeSpecHolder$Builder { public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/Annotatable$Builder; public fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/Annotatable$Builder; @@ -1026,10 +1030,12 @@ public final class com/squareup/kotlinpoet/TypeSpec$Builder : com/squareup/kotli public static synthetic fun addSuperinterface$default (Lcom/squareup/kotlinpoet/TypeSpec$Builder;Ljava/lang/reflect/Type;Lcom/squareup/kotlinpoet/CodeBlock;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public static synthetic fun addSuperinterface$default (Lcom/squareup/kotlinpoet/TypeSpec$Builder;Lkotlin/reflect/KClass;Lcom/squareup/kotlinpoet/CodeBlock;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addSuperinterfaces (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public final fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; + public fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; + public synthetic fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder; public final fun addTypeVariable (Lcom/squareup/kotlinpoet/TypeVariableName;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addTypeVariables (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public final fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; + public fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; + public synthetic fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder; public final fun build ()Lcom/squareup/kotlinpoet/TypeSpec; public synthetic fun contextReceivers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/ContextReceivable$Builder; public final fun getAnnotationSpecs ()Ljava/util/List; @@ -1084,6 +1090,15 @@ public final class com/squareup/kotlinpoet/TypeSpec$Kind : java/lang/Enum { public static fun values ()[Lcom/squareup/kotlinpoet/TypeSpec$Kind; } +public abstract interface class com/squareup/kotlinpoet/TypeSpecHolder { + public abstract fun getTypeSpecs ()Ljava/util/List; +} + +public abstract interface class com/squareup/kotlinpoet/TypeSpecHolder$Builder { + public abstract fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder; + public fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder; +} + public final class com/squareup/kotlinpoet/TypeVariableName : com/squareup/kotlinpoet/TypeName { public static final field Companion Lcom/squareup/kotlinpoet/TypeVariableName$Companion; public final fun copy (ZLjava/util/List;Ljava/util/List;ZLjava/util/Map;)Lcom/squareup/kotlinpoet/TypeVariableName; diff --git a/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/FileSpec.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/FileSpec.kt index 26bfcda700..288848c9a1 100644 --- a/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/FileSpec.kt +++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/FileSpec.kt @@ -49,8 +49,9 @@ import kotlin.reflect.KClass public class FileSpec private constructor( builder: Builder, private val tagMap: TagMap = builder.buildTagMap(), -) : Taggable by tagMap, Annotatable { +) : Taggable by tagMap, Annotatable, TypeSpecHolder { override val annotations: List = builder.annotations.toImmutableList() + override val typeSpecs: List = builder.members.filterIsInstance().toImmutableList() public val comment: CodeBlock = builder.comment.build() public val packageName: String = builder.packageName public val name: String = builder.name @@ -252,7 +253,7 @@ public class FileSpec private constructor( public val packageName: String, public val name: String, public val isScript: Boolean, - ) : Taggable.Builder, Annotatable.Builder { + ) : Taggable.Builder, Annotatable.Builder, TypeSpecHolder.Builder { override val annotations: MutableList = mutableListOf() internal val comment = CodeBlock.builder() internal val memberImports = sortedSetOf() @@ -297,7 +298,7 @@ public class FileSpec private constructor( comment.clear() } - public fun addType(typeSpec: TypeSpec): Builder = apply { + override fun addType(typeSpec: TypeSpec): Builder = apply { if (isScript) { body.add("%L", typeSpec) } else { @@ -305,6 +306,11 @@ public class FileSpec private constructor( } } + //region Overrides for binary compatibility + @Suppress("RedundantOverride") + override fun addTypes(typeSpecs: Iterable): Builder = super.addTypes(typeSpecs) + //endregion + public fun addFunction(funSpec: FunSpec): Builder = apply { require(!funSpec.isConstructor && !funSpec.isAccessor) { "cannot add ${funSpec.name} to file $name" diff --git a/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpec.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpec.kt index 5f52e4ff84..42549f272e 100644 --- a/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpec.kt +++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpec.kt @@ -47,7 +47,8 @@ public class TypeSpec private constructor( OriginatingElementsHolder by delegateOriginatingElements, ContextReceivable by contextReceivers, Annotatable, - Documentable { + Documentable, + TypeSpecHolder { public val kind: Kind = builder.kind public val name: String? = builder.name override val kdoc: CodeBlock = builder.kdoc.build() @@ -76,7 +77,7 @@ public class TypeSpec private constructor( public val initializerBlock: CodeBlock = builder.initializerBlock.build() public val initializerIndex: Int = builder.initializerIndex public val funSpecs: List = builder.funSpecs.toImmutableList() - public val typeSpecs: List = builder.typeSpecs.toImmutableList() + public override val typeSpecs: List = builder.typeSpecs.toImmutableList() internal val nestedTypesSimpleNames = typeSpecs.map { it.name }.toImmutableSet() @Deprecated("Use annotations property", ReplaceWith("annotations"), ERROR) @@ -475,7 +476,8 @@ public class TypeSpec private constructor( OriginatingElementsHolder.Builder, ContextReceivable.Builder, Annotatable.Builder, - Documentable.Builder { + Documentable.Builder, + TypeSpecHolder.Builder { internal var primaryConstructor: FunSpec? = null internal var superclass: TypeName = ANY internal val initializerBlock = CodeBlock.builder() @@ -725,11 +727,7 @@ public class TypeSpec private constructor( funSpecs += funSpec } - public fun addTypes(typeSpecs: Iterable): Builder = apply { - this.typeSpecs += typeSpecs - } - - public fun addType(typeSpec: TypeSpec): Builder = apply { + override fun addType(typeSpec: TypeSpec): Builder = apply { typeSpecs += typeSpec } @@ -764,6 +762,9 @@ public class TypeSpec private constructor( @Suppress("RedundantOverride") override fun addKdoc(block: CodeBlock): Builder = super.addKdoc(block) + + @Suppress("RedundantOverride") + override fun addTypes(typeSpecs: Iterable): Builder = super.addTypes(typeSpecs) //endregion public fun build(): TypeSpec { diff --git a/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpecHolder.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpecHolder.kt new file mode 100644 index 0000000000..aad67e6329 --- /dev/null +++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpecHolder.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.squareup.kotlinpoet + +/** A spec which can contain other [TypeSpec] */ +public interface TypeSpecHolder { + public val typeSpecs: List + + public interface Builder> { + + public fun addType(typeSpec: TypeSpec): T + + @Suppress("UNCHECKED_CAST") + public fun addTypes(typeSpecs: Iterable): T = apply { + for (typeSpec in typeSpecs) addType(typeSpec) + } as T + } +}