Skip to content

Commit

Permalink
Merge pull request #41 from SchwarzIT/bugfix/errorHandling
Browse files Browse the repository at this point in the history
# improved error-handling in mapper generation
  • Loading branch information
sbra0902 authored Apr 12, 2021
2 parents c79eb25 + 0be95ab commit 21c9ad8
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class CoachBaseBinderProcessor : AbstractProcessor() {

private var useSuspend: Boolean = false

private lateinit var workers : Set<Worker<*>>
private lateinit var workers: Set<Worker<*>>

companion object {
const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated"
Expand Down Expand Up @@ -67,10 +67,16 @@ class CoachBaseBinderProcessor : AbstractProcessor() {
ProcessingContext.roundEnv = roundEnv

for (worker in workers) {
if(!worker.invoke(roundEnv, useSuspend)){
//error in worker no further processing
try {
if (!worker.invoke(roundEnv, useSuspend)) {
//error in worker no further processing
return true
}
} catch (e: PostValidationException) {
mLogger.abortWithError(e)
return true
}

}

return true // no further processing of this annotation type
Expand Down
11 changes: 11 additions & 0 deletions couchbase-entity/src/main/java/com/kaufland/Logger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,15 @@ class Logger internal constructor(processingEnv: ProcessingEnvironment) {
fun hasErrors(): Boolean {
return hasErrors
}

fun abortWithError(e: PostValidationException) {
if(e.causingElements.isNotEmpty()){
for (causingElement in e.causingElements) {
error(e.message ?: "unknown", causingElement)
}
}else{
error(e.message ?: "unknown", null)
}
throw e
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.kaufland

import java.lang.Exception
import javax.lang.model.element.Element

class PostValidationException : Exception {

var causingElements : List<Element> = emptyList()

constructor(message: String, vararg causingElement : Element) : super(message){
this.causingElements = causingElement.toList()
}

constructor(throwable: Throwable, vararg causingElement : Element) : super(throwable){
this.causingElements = causingElement.toList()
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.kaufland.generation.mapper

import com.kaufland.PostValidationException
import com.kaufland.ProcessingContext
import com.kaufland.ProcessingContext.isAssignable
import com.kaufland.generation.MapifyableImplGeneration
Expand Down Expand Up @@ -52,36 +53,44 @@ class MapperGeneration {


val addedHelpers = mutableSetOf<String>()
for (mapifyHelper in holder.fields.values.filter { it.typeHandleMode == MapifyHolder.TypeHandleMode.MAPPER && it.declaringName.typeParams.isNotEmpty() }.map { it.declaringName.typeParams }.flatten()) {
val helperClazzName = buildHelperClazzName(mapifyHelper)
for (fieldWithTypeParam in holder.fields.values.filter { it.typeHandleMode == MapifyHolder.TypeHandleMode.MAPPER && it.declaringName.typeParams.isNotEmpty() }) {

if (addedHelpers.contains(helperClazzName)) {
continue
}
addedHelpers.add(helperClazzName)
for (mapifyHelper in fieldWithTypeParam.declaringName.typeParams) {

val helperClazzName = buildHelperClazzName(mapifyHelper)

val param = ResolverParam()
if (addedHelpers.contains(helperClazzName)) {
continue
}
addedHelpers.add(helperClazzName)

param.fromMapBuilder.beginControlFlow("return map[%S].let", "value")
param.toMapBuilder.addStatement("val map = %T()", TypeUtil.hashMapStringAny())
param.toMapBuilder.beginControlFlow("obj?.let")
resolveDeclaringName(mapifyHelper, param, "", emptyList())
param.fromMapBuilder.endControlFlow()
param.toMapBuilder.endControlFlow()
param.toMapBuilder.beginControlFlow("?.apply")
param.toMapBuilder.addStatement("map[%S] = this", "value")
param.toMapBuilder.endControlFlow()
param.toMapBuilder.addStatement("return map")

val param = ResolverParam()
try {
param.fromMapBuilder.beginControlFlow("return map[%S].let", "value")
param.toMapBuilder.addStatement("val map = %T()", TypeUtil.hashMapStringAny())
param.toMapBuilder.beginControlFlow("obj?.let")
resolveDeclaringName(mapifyHelper, param, "", emptyList())
param.fromMapBuilder.endControlFlow()
param.toMapBuilder.endControlFlow()
param.toMapBuilder.beginControlFlow("?.apply")
param.toMapBuilder.addStatement("map[%S] = this", "value")
param.toMapBuilder.endControlFlow()
param.toMapBuilder.addStatement("return map")


} catch (e: Exception) {
throw PostValidationException(e, *fieldWithTypeParam.elements)
}

typeSpec.addType(MapifyableImplGeneration.typeSpec(MapifyableImplGeneration.Config(
modifiers = arrayOf(KModifier.PRIVATE),
clazzName = helperClazzName,
typeParam = mapifyHelper.asFullTypeName()!!.copy(nullable = true),
fromMap = { it.addCode(param.fromMapBuilder.build()).build() },
toMap = { it.addCode(param.toMapBuilder.build()).build() })))
typeSpec.addType(MapifyableImplGeneration.typeSpec(MapifyableImplGeneration.Config(
modifiers = arrayOf(KModifier.PRIVATE),
clazzName = helperClazzName,
typeParam = mapifyHelper.asFullTypeName()!!.copy(nullable = true),
fromMap = { it.addCode(param.fromMapBuilder.build()).build() },
toMap = { it.addCode(param.toMapBuilder.build()).build() })))

}
}


Expand All @@ -95,27 +104,30 @@ class MapperGeneration {
.setter(field.setterFunSpec())
.build())

val resolverParam = ResolverParam()


resolverParam?.apply {
resolverParam.fromMapBuilder.beginControlFlow("map[%S]?.let", field.mapName)
resolverParam.toMapBuilder.beginControlFlow("obj.%N?.let", field.accessorName)
resolveDeclaringName(field.declaringName, resolverParam, field.accessorName, holder.typeParams)
resolverParam.fromMapBuilder.endControlFlow()
resolverParam.fromMapBuilder.beginControlFlow("?.apply")
resolverParam.fromMapBuilder.addStatement("obj.%N=this", field.accessorName)
resolverParam.fromMapBuilder.endControlFlow()
resolverParam.toMapBuilder.endControlFlow()
resolverParam.toMapBuilder.beginControlFlow("?.apply")
resolverParam.toMapBuilder.addStatement("map[%S]=this", field.mapName)
resolverParam.toMapBuilder.endControlFlow()

fromMap.addCode(resolverParam.fromMapBuilder.build())
toMap.addCode(resolverParam.toMapBuilder.build())
}

try {
val resolverParam = ResolverParam()
resolverParam?.apply {
resolverParam.fromMapBuilder.beginControlFlow("map[%S]?.let", field.mapName)
resolverParam.toMapBuilder.beginControlFlow("obj.%N?.let", field.accessorName)
resolveDeclaringName(field.declaringName, resolverParam, field.accessorName, holder.typeParams)
resolverParam.fromMapBuilder.endControlFlow()
resolverParam.fromMapBuilder.beginControlFlow("?.apply")
resolverParam.fromMapBuilder.addStatement("obj.%N=this", field.accessorName)
resolverParam.fromMapBuilder.endControlFlow()
resolverParam.toMapBuilder.endControlFlow()
resolverParam.toMapBuilder.beginControlFlow("?.apply")
resolverParam.toMapBuilder.addStatement("map[%S]=this", field.mapName)
resolverParam.toMapBuilder.endControlFlow()

fromMap.addCode(resolverParam.fromMapBuilder.build())
toMap.addCode(resolverParam.toMapBuilder.build())
}
} catch (e: Exception) {
throw PostValidationException(e, *field.mapifyElement.elements)
}
}

toMap.addStatement("return map")
Expand All @@ -132,6 +144,7 @@ class MapperGeneration {

private data class ResolverParam(val fromMapBuilder: CodeBlock.Builder = CodeBlock.builder(), val toMapBuilder: CodeBlock.Builder = CodeBlock.builder())

@Throws(Exception::class)
private fun resolveDeclaringName(name: ProcessingContext.DeclaringName, resolverParam: ResolverParam, accessorName: String, typeParams: List<ProcessingContext.DeclaringName>) {

if (name.isProcessingType()) {
Expand Down Expand Up @@ -170,9 +183,9 @@ class MapperGeneration {
val fullTypeName = name.asFullTypeName()
val helperInit = name.typeParams.map { "${buildHelperClazzName(it)}()" }.joinToString()

if(name.hasEmptyConstructor()){
if (name.hasEmptyConstructor()) {
resolverParam.fromMapBuilder.addStatement("val myObj = obj.%N ?: %T()", accessorName, fullTypeName)
}else{
} else {
resolverParam.fromMapBuilder.addStatement("val myObj = obj.%N", accessorName)
}

Expand Down Expand Up @@ -229,7 +242,7 @@ class MapperGeneration {
resolverParam.toMapBuilder.addStatement("%T().toMap(it)", TypeUtil.serializableMapifyable(name.asFullTypeName()!!.copy(nullable = false)))
}
else -> {
throw Exception("unknown field type ${name.name}")
throw Exception("${name.name} is not ${Mapifyable::class.java.simpleName} or plain or any other parseable type.")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeName
import com.squareup.kotlinpoet.asTypeName
import javax.lang.model.element.Element
import javax.lang.model.element.Modifier

interface MapifyElementType {

val elements: Array<Element>

val fieldName : String

val mapName : String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import javax.lang.model.element.Element
import javax.lang.model.element.Modifier

class MapifyElementTypeField(val element: Element, val mapify: Mapify) : MapifyElementType {
override val elements: Array<Element> = arrayOf(element)

override val fieldName = element.simpleName.toString()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.squareup.kotlinpoet.*
import com.sun.tools.javac.code.Symbol
import kaufland.com.coachbasebinderapi.mapify.Mapify
import java.lang.reflect.Method
import javax.lang.model.element.Element
import javax.lang.model.element.Modifier

class MapifyElementTypeGetterSetter(val getterSetter: GetterSetter, override val fieldName : String) : MapifyElementType {
Expand All @@ -33,6 +34,8 @@ class MapifyElementTypeGetterSetter(val getterSetter: GetterSetter, override val
}
}

override val elements: Array<Element> = arrayOf(getterSetter.getterElement, getterSetter.setterElement).map { it as? Element }?.filterNotNull().toTypedArray()

override val mapName = getterSetter.mapify?.name?.let { if(it.isNotBlank()) it else null } ?: fieldName

override val typeName = getterSetter.setterElement!!.params()[0]!!.asType().asTypeName().javaToKotlinType()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ interface Worker<T : WorkSet> {
if (logger.hasErrors()) {
return false
}

doWork(workSet, useSuspend)
return true
}
Expand Down

0 comments on commit 21c9ad8

Please sign in to comment.