Skip to content

Commit

Permalink
Add more utils
Browse files Browse the repository at this point in the history
  • Loading branch information
Takhion committed Jul 30, 2017
1 parent 1d4096d commit 992f476
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ package me.eugeniomarletti.kotlin.metadata

const val kaptGeneratedOption = "kapt.kotlin.generated"
const val kotlinMetadataAnnotation = "kotlin.Metadata"
const val kotlinPropertyAnnotationsFunPostfix = "\$annotations"
18 changes: 18 additions & 0 deletions lib/src/main/kotlin/me/eugeniomarletti/kotlin/metadata/JvmUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package me.eugeniomarletti.kotlin.metadata

import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil

/**
* Returns JVM signature in the format: "equals(Ljava/lang/Object;)Z"
*/
fun ProtoBuf.Function.getJvmMethodSignature(nameResolver: NameResolver, typeTable: ProtoBuf.TypeTable = this.typeTable) =
JvmProtoBufUtil.getJvmMethodSignature(this, nameResolver, TypeTable(typeTable))

fun ProtoBuf.Constructor.getJvmConstructorSignature(nameResolver: NameResolver, typeTable: ProtoBuf.TypeTable) =
JvmProtoBufUtil.getJvmConstructorSignature(this, nameResolver, TypeTable(typeTable))

fun ProtoBuf.Property.getJvmFieldSignature(nameResolver: NameResolver, typeTable: ProtoBuf.TypeTable) =
JvmProtoBufUtil.getJvmFieldSignature(this, nameResolver, TypeTable(typeTable))
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package me.eugeniomarletti.kotlin.metadata

import me.eugeniomarletti.kotlin.processing.KotlinProcessingUtils
import javax.lang.model.element.ExecutableElement
import javax.lang.model.element.TypeElement
import javax.lang.model.type.ArrayType
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.ErrorType
import javax.lang.model.type.ExecutableType
import javax.lang.model.type.NoType
import javax.lang.model.type.NullType
import javax.lang.model.type.PrimitiveType
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
import javax.lang.model.type.TypeVariable
import javax.lang.model.type.WildcardType
import javax.lang.model.util.AbstractTypeVisitor6
import javax.lang.model.util.Types

interface KotlinMetadataUtils : KotlinProcessingUtils {

val ExecutableElement.jvmMethodSignature: String get() {
fun TypeMirror.jvmDeclaration(): String = accept(JvmDeclarationTypeVisitor, typeUtils)
val params = parameters.joinToString(separator = "") { it.asType().jvmDeclaration() }
val returnType = returnType.jvmDeclaration()
return "$simpleName($params)$returnType"
}
}

/**
* When applied over a method, it returns the JVM signature in the form "name(descriptor)returnValue", for example: "equals(Ljava/lang/Object;)Z".
*
* See the [JVM specification, section 4.3](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3)
* @see getJvmMethodSignature
*/
private object JvmDeclarationTypeVisitor : AbstractTypeVisitor6<String, Types>() {

override fun visitTypeVariable(t: TypeVariable, typeUtils: Types): String =
typeUtils.erasure(t).accept(this, typeUtils)

override fun visitArray(t: ArrayType, typeUtils: Types): String =
"[" + t.componentType.accept(this, typeUtils)

override fun visitNoType(t: NoType, typeUtils: Types): String =
"V"

override fun visitDeclared(t: DeclaredType, typeUtils: Types): String {
val internalName = (t.asElement() as TypeElement).qualifiedName.toString().replace('.', '/')
return "L$internalName;"
}

override fun visitPrimitive(t: PrimitiveType, typeUtils: Types): String =
when (t.kind) {
TypeKind.BYTE -> "B"
TypeKind.CHAR -> "C"
TypeKind.DOUBLE -> "D"
TypeKind.FLOAT -> "F"
TypeKind.INT -> "I"
TypeKind.LONG -> "J"
TypeKind.SHORT -> "S"
TypeKind.BOOLEAN -> "Z"
else -> error("Unknown primitive type $t")
}

override fun visitExecutable(t: ExecutableType, typeUtils: Types): String = visitUnknown(t, typeUtils)
override fun visitWildcard(t: WildcardType, typeUtils: Types): String = visitUnknown(t, typeUtils)
override fun visitError(t: ErrorType, typeUtils: Types): String = visitUnknown(t, typeUtils)
override fun visitNull(t: NullType, typeUtils: Types): String = visitUnknown(t, typeUtils)

override fun visitUnknown(t: TypeMirror, typeUtils: Types): String = error("Unsupported type $t")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package me.eugeniomarletti.kotlin.metadata

import org.jetbrains.kotlin.protobuf.GeneratedMessageLite.ExtendableMessage
import org.jetbrains.kotlin.protobuf.GeneratedMessageLite.GeneratedExtension
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf

fun <MessageType : ExtendableMessage<MessageType>, Type>
MessageType.getExtensionOrNull(extension: GeneratedExtension<MessageType, Type>)
= takeIf { hasExtension(extension) }?.let { getExtension(extension) }

val ProtoBuf.Constructor.jvmConstructorSignature get() = getExtensionOrNull(JvmProtoBuf.constructorSignature)
val ProtoBuf.Function.jvmMethodSignature get() = getExtensionOrNull(JvmProtoBuf.methodSignature)
val ProtoBuf.Property.jvmPropertySignature get() = getExtensionOrNull(JvmProtoBuf.propertySignature)
val ProtoBuf.Type.jvmTypeAnnotation get() = getExtensionOrNull(JvmProtoBuf.typeAnnotation) as List<ProtoBuf.Annotation>?
val ProtoBuf.Type.jvmIsRaw get() = getExtensionOrNull(JvmProtoBuf.isRaw)
val ProtoBuf.TypeParameter.jvmTypeParameterAnnotation get() = getExtensionOrNull(JvmProtoBuf.typeParameterAnnotation) as List<ProtoBuf.Annotation>?
val ProtoBuf.Class.jvmClassModuleName get() = getExtensionOrNull(JvmProtoBuf.classModuleName)
val ProtoBuf.Package.jvmPackageModuleName get() = getExtensionOrNull(JvmProtoBuf.packageModuleName)
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package me.eugeniomarletti.kotlin.processing

import java.util.Locale
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.Completion
import javax.annotation.processing.Filer
import javax.annotation.processing.Messager
import javax.annotation.processing.ProcessingEnvironment
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.SourceVersion
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.Element
import javax.lang.model.element.ExecutableElement
import javax.lang.model.element.TypeElement
import javax.lang.model.util.Elements
import javax.lang.model.util.Types

abstract class KotlinAbstractProcessor : AbstractProcessor(), KotlinProcessingUtils {

override fun getSupportedOptions(): Set<String> = super.getSupportedOptions()
override fun getSupportedSourceVersion(): SourceVersion = super.getSupportedSourceVersion()
override fun getSupportedAnnotationTypes(): Set<String> = super.getSupportedAnnotationTypes()
override fun init(processingEnv: ProcessingEnvironment) = super.init(processingEnv)

override fun getCompletions(
element: Element?,
annotation: AnnotationMirror?,
member: ExecutableElement?,
userText: String?
): Iterable<Completion>
= super.getCompletions(element, annotation, member, userText)

override abstract fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean

override val options: Map<String, String> get() = processingEnv.options
override val messager: Messager get() = processingEnv.messager
override val filer: Filer get() = processingEnv.filer
override val elementUtils: Elements get() = processingEnv.elementUtils
override val typeUtils: Types get() = processingEnv.typeUtils
override val sourceVersion: SourceVersion get() = processingEnv.sourceVersion
override val locale: Locale get() = processingEnv.locale
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package me.eugeniomarletti.kotlin.processing

import java.util.Locale
import javax.annotation.processing.Filer
import javax.annotation.processing.Messager
import javax.lang.model.SourceVersion
import javax.lang.model.util.Elements
import javax.lang.model.util.Types

interface KotlinProcessingUtils {
val options: Map<String, String>
val messager: Messager
val filer: Filer
val elementUtils: Elements
val typeUtils: Types
val sourceVersion: SourceVersion
val locale: Locale
}

0 comments on commit 992f476

Please sign in to comment.