Skip to content

Commit

Permalink
Extract utility methods in processor to ProcessorUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
raulraja committed Apr 6, 2018
1 parent dadab60 commit 1d3be3e
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,46 +13,70 @@ import javax.lang.model.element.VariableElement

interface ProcessorUtils : KotlinMetadataUtils {

fun KotlinMetadata.asClassOrPackageDataWrapper(classElement: TypeElement): ClassOrPackageDataWrapper? {
val `package` = elementUtils.getPackageOf(classElement).toString()
return when (this) {
is KotlinClassMetadata -> data.asClassOrPackageDataWrapper(`package`)
is KotlinPackageMetadata -> data.asClassOrPackageDataWrapper(`package`)
else -> null
fun getConstructorParamNames(element: Element): List<String> = element.kotlinMetadata
.let { it as KotlinClassMetadata }.data
.let { (nameResolver, classProto) ->
classProto.constructorOrBuilderList
.first()
.valueParameterList
.map(ProtoBuf.ValueParameter::getName)
.map(nameResolver::getString)
}

fun getClassData(element: Element) = element.kotlinMetadata
.let { it as KotlinClassMetadata }
.data
.asClassOrPackageDataWrapper(elementUtils.getPackageOf(element).toString())

fun getConstructorTypesNames(element: Element): List<String> = element.kotlinMetadata
.let { it as KotlinClassMetadata }.data
.let { data ->
data.proto.constructorOrBuilderList
.first()
.valueParameterList
.map { it.type.extractFullName(data) }
}

fun KotlinMetadata.asClassOrPackageDataWrapper(classElement: TypeElement): ClassOrPackageDataWrapper? {
val `package` = elementUtils.getPackageOf(classElement).toString()
return when (this) {
is KotlinClassMetadata -> data.asClassOrPackageDataWrapper(`package`)
is KotlinPackageMetadata -> data.asClassOrPackageDataWrapper(`package`)
else -> null
}
}
}

fun getClassOrPackageDataWrapper(classElement: TypeElement): ClassOrPackageDataWrapper {
val metadata = classElement.kotlinMetadata ?: knownError("These annotations can only be used in Kotlin")
return metadata.asClassOrPackageDataWrapper(classElement)
?: knownError("This annotation can't be used on this element")
}
fun getClassOrPackageDataWrapper(classElement: TypeElement): ClassOrPackageDataWrapper {
val metadata = classElement.kotlinMetadata ?: knownError("These annotations can only be used in Kotlin")
return metadata.asClassOrPackageDataWrapper(classElement)
?: knownError("This annotation can't be used on this element")
}

fun TypeElement.methods(): List<MethodElement> =
enclosedElements.mapNotNull { if (it is MethodElement) it as MethodElement else null }
fun TypeElement.methods(): List<MethodElement> =
enclosedElements.mapNotNull { if (it is MethodElement) it as MethodElement else null }

fun ClassOrPackageDataWrapper.getFunction(methodElement: ExecutableElement) =
getFunctionOrNull(methodElement, nameResolver, functionList)
?: knownError("Can't find annotated method ${methodElement.jvmMethodSignature}")
fun ClassOrPackageDataWrapper.getFunction(methodElement: ExecutableElement) =
getFunctionOrNull(methodElement, nameResolver, functionList)
?: knownError("Can't find annotated method ${methodElement.jvmMethodSignature}")

private fun kindedRex() = "(?i)Kind<(.)>".toRegex()
private fun kindedRex() = "(?i)Kind<(.)>".toRegex()

fun ProtoBuf.Function.overrides(o: ProtoBuf.Function): Boolean = false
fun ProtoBuf.Function.overrides(o: ProtoBuf.Function): Boolean = false

fun ClassOrPackageDataWrapper.Class.declaredTypeClassInterfaces(
typeTable: TypeTable): List<ClassOrPackageDataWrapper> {
val interfaces = this.classProto.supertypes(typeTable).map {
it.extractFullName(this)
}.filter {
it != "`arrow`.`TC`"
}
return interfaces.map { i ->
val className = i.removeBackticks().substringBefore("<")
val typeClassElement = elementUtils.getTypeElement(className)
val parentInterface = getClassOrPackageDataWrapper(typeClassElement)
parentInterface as ClassOrPackageDataWrapper.Class
fun ClassOrPackageDataWrapper.Class.declaredTypeClassInterfaces(
typeTable: TypeTable): List<ClassOrPackageDataWrapper> {
val interfaces = this.classProto.supertypes(typeTable).map {
it.extractFullName(this)
}.filter {
it != "`arrow`.`TC`"
}
return interfaces.map { i ->
val className = i.removeBackticks().substringBefore("<")
val typeClassElement = elementUtils.getTypeElement(className)
val parentInterface = getClassOrPackageDataWrapper(typeClassElement)
parentInterface as ClassOrPackageDataWrapper.Class
}
}
}

fun recurseTypeclassInterfaces(
current: ClassOrPackageDataWrapper.Class,
Expand All @@ -61,8 +85,8 @@ interface ProcessorUtils : KotlinMetadataUtils {
val interfaces = current.classProto.supertypes(typeTable).map {
it.extractFullName(current)
}.filter {
it != "`kotlin`.`Any`"
}
it != "`kotlin`.`Any`"
}
return when {
interfaces.isEmpty() -> acc
else -> {
Expand All @@ -87,53 +111,53 @@ fun String.removeBackticks() = this.replace("`", "")
fun knownError(message: String, element: Element? = null): Nothing = throw KnownException(message, element)

val ProtoBuf.Class.Kind.isCompanionOrObject
get() = when (this) {
ProtoBuf.Class.Kind.OBJECT,
ProtoBuf.Class.Kind.COMPANION_OBJECT -> true
else -> false
}
get() = when (this) {
ProtoBuf.Class.Kind.OBJECT,
ProtoBuf.Class.Kind.COMPANION_OBJECT -> true
else -> false
}

val ProtoBuf.Class.isSealed
get() = modality == ProtoBuf.Modality.SEALED
get() = modality == ProtoBuf.Modality.SEALED

val ClassOrPackageDataWrapper.Class.fullName: String
get() = nameResolver.getName(classProto.fqName).asString()
get() = nameResolver.getName(classProto.fqName).asString()

fun ClassOrPackageDataWrapper.getParameter(function: ProtoBuf.Function, parameterElement: VariableElement) =
getValueParameterOrNull(nameResolver, function, parameterElement)
?: knownError("Can't find annotated parameter ${parameterElement.simpleName} in ${function.getJvmMethodSignature(nameResolver)}")
getValueParameterOrNull(nameResolver, function, parameterElement)
?: knownError("Can't find annotated parameter ${parameterElement.simpleName} in ${function.getJvmMethodSignature(nameResolver)}")

fun ClassOrPackageDataWrapper.getPropertyOrNull(methodElement: ExecutableElement) =
getPropertyOrNull(methodElement, nameResolver, this::propertyList)
getPropertyOrNull(methodElement, nameResolver, this::propertyList)

fun ProtoBuf.Type.extractFullName(
classData: ClassOrPackageDataWrapper,
outputTypeAlias: Boolean = true
classData: ClassOrPackageDataWrapper,
outputTypeAlias: Boolean = true
): String =
extractFullName(
nameResolver = classData.nameResolver,
getTypeParameter = { classData.getTypeParameter(it)!! },
outputTypeAlias = outputTypeAlias,
throwOnGeneric = null
)
extractFullName(
nameResolver = classData.nameResolver,
getTypeParameter = { classData.getTypeParameter(it)!! },
outputTypeAlias = outputTypeAlias,
throwOnGeneric = null
)

fun ClassOrPackageDataWrapper.typeConstraints(): String =
typeParameters.flatMap { typeParameter ->
val name = nameResolver.getString(typeParameter.name)
typeParameter.upperBoundList.map { constraint ->
name to constraint
.extractFullName(this)
.removeBackticks()
}
}.let { constraints ->
if (constraints.isNotEmpty()) {
constraints.joinToString(
prefix = " where ",
separator = ", ",
transform = { (a, b) -> "$a : $b" }
)
} else {
""
}
}
typeParameters.flatMap { typeParameter ->
val name = nameResolver.getString(typeParameter.name)
typeParameter.upperBoundList.map { constraint ->
name to constraint
.extractFullName(this)
.removeBackticks()
}
}.let { constraints ->
if (constraints.isNotEmpty()) {
constraints.joinToString(
prefix = " where ",
separator = ", ",
transform = { (a, b) -> "$a : $b" }
)
} else {
""
}
}

Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
package arrow.generic

import com.google.auto.service.AutoService
import arrow.common.utils.AbstractProcessor
import arrow.common.utils.asClassOrPackageDataWrapper
import arrow.common.utils.knownError
import com.google.auto.service.AutoService
import me.eugeniomarletti.kotlin.metadata.KotlinClassMetadata
import me.eugeniomarletti.kotlin.metadata.extractFullName
import me.eugeniomarletti.kotlin.metadata.isDataClass
import me.eugeniomarletti.kotlin.metadata.kotlinMetadata
import me.eugeniomarletti.kotlin.metadata.proto
import org.jetbrains.kotlin.serialization.ProtoBuf
import java.io.File
import javax.annotation.processing.Processor
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.SourceVersion
import javax.lang.model.element.TypeElement

import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement

@AutoService(Processor::class)
class ProductProcessor : AbstractProcessor() {
Expand Down Expand Up @@ -57,28 +52,5 @@ class ProductProcessor : AbstractProcessor() {
else -> knownError(productAnnotationError(element, productAnnotationName, productAnnotationTarget))
}

private fun getConstructorTypesNames(element: Element): List<String> = element.kotlinMetadata
.let { it as KotlinClassMetadata }.data
.let { data ->
data.proto.constructorOrBuilderList
.first()
.valueParameterList
.map { it.type.extractFullName(data) }
}

private fun getConstructorParamNames(element: Element): List<String> = element.kotlinMetadata
.let { it as KotlinClassMetadata }.data
.let { (nameResolver, classProto) ->
classProto.constructorOrBuilderList
.first()
.valueParameterList
.map(ProtoBuf.ValueParameter::getName)
.map(nameResolver::getString)
}

private fun getClassData(element: Element) = element.kotlinMetadata
.let { it as KotlinClassMetadata }
.data
.asClassOrPackageDataWrapper(elementUtils.getPackageOf(element).toString())

}
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
package arrow.optics

import com.google.auto.service.AutoService
import arrow.common.utils.AbstractProcessor
import arrow.common.utils.asClassOrPackageDataWrapper
import arrow.common.utils.isSealed
import arrow.common.utils.knownError
import com.google.auto.service.AutoService
import me.eugeniomarletti.kotlin.metadata.KotlinClassMetadata
import me.eugeniomarletti.kotlin.metadata.extractFullName
import me.eugeniomarletti.kotlin.metadata.isDataClass
import me.eugeniomarletti.kotlin.metadata.kotlinMetadata
import me.eugeniomarletti.kotlin.metadata.proto
import org.jetbrains.kotlin.serialization.ProtoBuf
import java.io.File
import javax.annotation.processing.Processor
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.SourceVersion
import javax.lang.model.element.TypeElement

import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement

@AutoService(Processor::class)
class OptikalProcessor : AbstractProcessor() {
Expand Down Expand Up @@ -109,28 +104,4 @@ class OptikalProcessor : AbstractProcessor() {
else -> knownError(opticsAnnotationError(element, isosAnnotationName, isosAnnotationTarget))
}

private fun getConstructorTypesNames(element: Element): List<String> = element.kotlinMetadata
.let { it as KotlinClassMetadata }.data
.let { data ->
data.proto.constructorOrBuilderList
.first()
.valueParameterList
.map { it.type.extractFullName(data) }
}

private fun getConstructorParamNames(element: Element): List<String> = element.kotlinMetadata
.let { it as KotlinClassMetadata }.data
.let { (nameResolver, classProto) ->
classProto.constructorOrBuilderList
.first()
.valueParameterList
.map(ProtoBuf.ValueParameter::getName)
.map(nameResolver::getString)
}

private fun getClassData(element: Element) = element.kotlinMetadata
.let { it as KotlinClassMetadata }
.data
.asClassOrPackageDataWrapper(elementUtils.getPackageOf(element).toString())

}

0 comments on commit 1d3be3e

Please sign in to comment.