이 글은 기존 운영했던 WordPress 블로그인 PyxisPub: Development Life (pyxispub.uzuki.live) 에서 가져온 글 입니다. 모든 글을 가져오지는 않으며, 작성 시점과 현재 시점에는 차이가 많이 존재합니다.
작성 시점: 2018-03-16
먼저 이 글은 아래의 글을 참조로 하였다.
KotlinPoet を使って Android プロジェクトでコードジェネレーションする (KotlinPoet를 사용해 Android 프로젝트의 코드 제네레이션을 한다)
はじめて KotlinPoet を使ったときのメモ (처음 KotlinPoet를 사용했을 때의 메모)
만약 아래의 코드를 작성하고 싶다고 해보자.
Log.d("TAG", "Something new!");
그러면, 아래의 코드를 사용할 수도 있다.
val tag = "TAG"
val message = "Something new!"
builder.addCode("android.util.Log.d(\\"$tag\\", \\"$message\\");")
아니면, 아래의 코드를 사용할 수도 있다.
val tag = "TAG"
val message = "Something new!"
builder.addStatement("%T.d(%S, %S)", ClassName.bestGuess("android.util", "Log"), tag, message);
당연히 후자가 마음에 든다.
이 처럼, %S, %L, %T 등을 이용하여 표현식을 작성할 수 있다.
Static 를 하고자 하는 메서드의 생성 Spec(FunSpec) 에 .addAnnotation(JvmStatic::class)
를 추가하면 된다.
val parameterName = "person"
val typeName = ClassName.bestGuess("pyxis.uzuki.live.demo", "Person);
PropertySpec.builder(parameterName, typeName, KModifier.PRIVATE).initializer("Person()").build()
builder 의 3번째 파라미터는 KModifier 의 가변 인자(vararg) 로, Modifier 를 여러 개 붙일 수 있다.
val parameterName = "person"
val typeName = ClassName.bestGuess("pyxis.uzuki.live.demo", "Person);
PropertySpec.builder(parameterName, typeName, KModifier.PRIVATE).initializer("Person()").mutable(true).build()
간단하게 mutable(true) 만 추가해주면 된다.
val parameterName = "person"
val typeName =ClassName.bestGuess("pyxis.uzuki.live.demo", "Person)
FunSpec.builder("apply")
.addModifier(KModifier.PUBLIC)
.addParameter(parameterName, typeName)
해당 FunSpec의 builder 에 addParameter 메서드를 사용하면 된다.
this.beginControlFlow("if ($variableName.length == 0)")
.addCode(String.format("%s = %s;\\n", variableName, defValue))
.endControlFlow()
중요한건 beginControlFlow 등은 중괄호만 생성해준다는 것이다. 따라서 if 나 for 는 저렇게 하드코딩 하거나 위의 %L, %S 등을 이용해 적절하게 표시해야 한다.
Int, Double 등을 처리할 때 Primitive 는 ClassName 로 처리할 수 없다는 오류를 발생시킬 수 있는데, 아래 메서드를 사용하면 된다.
val ANY = ClassName("kotlin", "Any")
val ARRAY = ClassName("kotlin", "Array")
val UNIT = Unit::class.asClassName()
val BOOLEAN = ClassName("kotlin", "Boolean")
val BYTE = ClassName("kotlin", "Byte")
val SHORT = ClassName("kotlin", "Short")
val INT = ClassName("kotlin", "Int")
val LONG = ClassName("kotlin", "Long")
val CHAR = ClassName("kotlin", "Char")
val FLOAT = ClassName("kotlin", "Float")
val DOUBLE = ClassName("kotlin", "Double")
val STRING = ClassName("kotlin", "String")
fun String.bestGuess(): TypeName {
return when (this) {
"int" -> INT
"byte" -> BYTE
"short" -> SHORT
"long" -> LONG
"char" -> CHAR
"float" -> FLOAT
"double" -> DOUBLE
"String" -> STRING
"java.lang.String" -> STRING
"boolean" -> BOOLEAN
"Unit" -> UNIT
"Any" -> ANY
else -> ClassName.bestGuess(this)
}
}