KotlinPoet
Kotlinのソースコードをプログラム的に生成するためのKotlinライブラリです。
記法になれることと、よく使いそうな記法を書いておきたいと思います。
Hello World!
println("Hello, World!")
を含むmain
関数を持つKotlinファイルを生成
fun helloWorld() {
val printValue = "Hello, World!"
val fileName = "HelloWorld"
val file = FileSpec.builder("", fileName)
.addFunction(
FunSpec.builder("main")
.addParameter("args", String::class, KModifier.VARARG)
.addStatement("println(%S)", printValue)
.build()
)
.build()
file.writeTo(System.out)
}
プロパティとコンストラクタの追加
name
とage
の2つのプロパティと、それらのプロパティを初期化するコンストラクタを持つクラスPerson
を生成
fun personWithAge() {
val fileName = "Person"
val className = ClassName("", "Person")
val file = FileSpec.builder("", fileName)
.addType(
TypeSpec.classBuilder(className)
.primaryConstructor(
FunSpec.constructorBuilder()
.addParameter("name", String::class)
.addParameter("age", Int::class)
.build()
)
.addProperty(
PropertySpec
.builder("name", String::class)
.initializer("name")
.build()
)
.addProperty(
PropertySpec
.builder("age", Int::class)
.initializer("age")
.build()
)
.build()
)
.build()
file.writeTo(System.out)
}
関数の追加
greet
という名前の関数を持つクラスPerson
を生成。この関数は、"Hello, $name!"
というメッセージを返す
fun personWithGreet() {
val fileName = "PersonWithGreet"
val returnValue = "Hello, " + "$" + "name"
val className = ClassName("", fileName)
val file = FileSpec.builder("", fileName)
.addType(
TypeSpec.classBuilder(className)
.primaryConstructor(
FunSpec.constructorBuilder()
.addParameter("name", String::class)
.build()
)
.addProperty(
PropertySpec.builder("name", String::class)
.initializer("name")
.build()
)
.addFunction(
FunSpec.builder("greet")
.returns(String::class)
.addStatement("return %P", returnValue)
.build()
)
.build()
)
.build()
file.writeTo(System.out)
}
拡張関数の生成
Stringクラスの拡張関数
exclaimを生成。この関数は、文字列の末尾に
"!"`を追加する
fun extensionFn() {
val returnValue = "this" + "$" + "!"
val func = FunSpec.builder(
"exclaim"
)
.receiver(String::class)
.returns(String::class)
.addStatement("return this + %S", "!")
.build()
FileSpec.builder("", "extensionFn")
.addFunction(func)
.build()
.writeTo(System.out)
}
ジェネリクスの使用
任意の型T
のリストを受け取り、そのリストの最初の要素を返す関数firstElement
を生成
fun generateFirstElementFunction() {
val fileName = "GenericsExample"
val file = FileSpec.builder("", fileName)
.addFunction(
FunSpec.builder("firstElement")
.addTypeVariable(TypeVariableName("T"))
.addParameter("list", List::class.asClassName().parameterizedBy(TypeVariableName("T")))
.returns(TypeVariableName("T"))
.addStatement("return list.first()")
.build()
)
.build()
file.writeTo(System.out)
}
アノテーションの追加
@Deprecatedアノテーションを持つ関数
oldFunction`を生成。
fun generateDeprecatedFunction() {
val fileName = "DeprecatedExample"
val file = FileSpec.builder("", fileName)
.addFunction(
FunSpec.builder("oldFunction")
.addAnnotation(
AnnotationSpec.builder(Deprecated::class)
.addMember("%S", "This function is deprecated.")
.build()
)
.addStatement("println(%S)", "This is the old function.")
.build()
)
.build()
file.writeTo(System.out)
}
インターフェースの実装
Flyableというインターフェースを持つクラス
Birdを生成。このクラスは、
flyという関数を持ち、
"I can fly!"`というメッセージを返す。
interface Flyable { fun fly() }
fun generateFlyable() {
val fileName = "Bard"
val file = FileSpec.builder("", fileName)
.addType(
TypeSpec.classBuilder(ClassName("", fileName))
.addSuperinterface(Flyable::class)
.addFunction(
FunSpec.builder("fly")
.addModifiers(KModifier.OVERRIDE)
.returns(String::class)
.addStatement("return %S", "I can fly!")
.build()
)
.build()
)
.build()
file.writeTo(System.out)
}
コンパニオンオブジェクトの追加
DEFAULT_NAMEという名前の
String型のコンパニオンオブジェクトを持つクラス
Person`を生成
fun generatePersonWithCompanionObject() {
val fileName = "PersonWithCompanion"
val file = FileSpec.builder("", fileName)
.addType(
TypeSpec.classBuilder("Person")
.addType(
TypeSpec.companionObjectBuilder()
.addProperty(
PropertySpec.builder("DEFAULT_NAME", String::class)
.initializer("%S", "Default Name")
.build()
)
.build()
)
.build()
)
.build()
file.writeTo(System.out)
}
プロパティのカスタムゲッター
isAdultという名前の
Boolean型のプロパティを持つクラス
Personを生成。このプロパティは、
ageプロパティが18以上の場合に
true`を返すカスタムゲッターを持つ
fun generatePersonWithCustomGetter() {
val fileName = "PersonWithCustomGetter"
val file = FileSpec.builder("", fileName)
.addType(
TypeSpec.classBuilder("Person")
.addProperty(
PropertySpec.builder("age", Int::class)
.initializer("0")
.build()
)
.addProperty(
PropertySpec.builder("isAdult", Boolean::class)
.getter(
FunSpec.getterBuilder()
.addStatement("return age >= 18")
.build()
)
.build()
)
.build()
)
.build()
file.writeTo(System.out)
}
公式ドキュメント通りですね〜