All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dailystudio.devbricksx.ksp.processors.step.view.AbsDiffUtilStep.kt Maven / Gradle / Ivy

package com.dailystudio.devbricksx.ksp.processors.step.view

import com.dailystudio.devbricksx.annotations.view.Adapter
import com.dailystudio.devbricksx.annotations.view.FragmentAdapter
import com.dailystudio.devbricksx.ksp.helper.GeneratedNames
import com.dailystudio.devbricksx.ksp.processors.BaseSymbolProcessor
import com.dailystudio.devbricksx.ksp.processors.GeneratedClassResult
import com.dailystudio.devbricksx.ksp.processors.GeneratedResult
import com.dailystudio.devbricksx.ksp.processors.step.SingleSymbolProcessStep
import com.dailystudio.devbricksx.ksp.utils.*
import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.Modifier
import com.squareup.kotlinpoet.AnnotationSpec
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.TypeSpec
import kotlin.reflect.KClass

abstract class AbsDiffUtilStep(classOfAnnotation: KClass,
                               processor: BaseSymbolProcessor
) : SingleSymbolProcessStep(classOfAnnotation, processor) {

    override fun filterSymbols(
        resolver: Resolver,
        symbols: Sequence
    ): Sequence {
        return symbols.mapToShadowClass(resolver)
    }

    override fun processSymbol(
        resolver: Resolver,
        symbol: KSClassDeclaration
    ): List {
        val typeName = symbol.typeName()
        val packageName = symbol.packageName()
        warn("diff for: [pack: $packageName, type: $typeName]")

        val typeNameToGenerate = GeneratedNames.getDiffUtilName(typeName)
        val typeOfObject = ClassName(packageName, typeName)

        val matched = needToDiffUtil(symbol, resolver)
        if (!matched) {
            return emptyResult
        }

        val itemCallbackTypeName = TypeNameUtils
            .typeOfItemCallbackOf(typeOfObject)

        val annotationSpec = AnnotationSpec.builder(
            TypeNameUtils.typeOfSuppressLintAnnotation()
        ).addMember("\"DiffUtilEquals\"").build()

        val classBuilder = TypeSpec.classBuilder(typeNameToGenerate)
            .superclass(itemCallbackTypeName)
            .addModifiers(KModifier.OPEN)

        val methodItemsSameBuilder: FunSpec.Builder = FunSpec.builder("areItemsTheSame")
            .addModifiers(KModifier.PUBLIC)
            .addModifiers(KModifier.OVERRIDE)
            .addParameter("oldObject", typeOfObject)
            .addParameter("newObject", typeOfObject)
            .returns(Boolean::class)

        val methodContentsSameBuilder: FunSpec.Builder = FunSpec.builder("areContentsTheSame")
            .addAnnotation(annotationSpec)
            .addModifiers(KModifier.PUBLIC)
            .addModifiers(KModifier.OVERRIDE)
            .addParameter("oldObject", typeOfObject)
            .addParameter("newObject", typeOfObject)
            .returns(Boolean::class)

        attachEqualsStatements(resolver, symbol, methodItemsSameBuilder, methodContentsSameBuilder)

        classBuilder.addFunction(methodItemsSameBuilder.build())
        classBuilder.addFunction(methodContentsSameBuilder.build())

        return singleClassResult(GeneratedResult.setWithShadowClass(symbol, resolver), packageName, classBuilder)
    }

    protected open fun needToDiffUtil(symbol: KSClassDeclaration, resolver: Resolver): Boolean {
        val typeName = symbol.typeName()
        val packageName = symbol.packageName()

        val typeNameToGenerate = GeneratedNames.getDiffUtilName(typeName)
        val typeOfDiffUtils = ClassName(packageName, typeNameToGenerate)

        val hasAdapterAnnotated =
            symbol.hasAnnotation(Adapter::class, resolver)
                    || symbol.hasAnnotation(FragmentAdapter::class, resolver)
        val openedClass = symbol.modifiers.contains(Modifier.OPEN)
        warn("check necessity: modifiers = ${symbol.modifiers}, open = $openedClass, hasAdapterAnnotated = $hasAdapterAnnotated")

        val matched = (hasAdapterAnnotated || openedClass)
        if (!matched) {
            warn("final class [$symbol] is NOT annotated by @Adapter, skip DiffUtils generation")
        }

        val existed = resolver.getClassDeclarationByName(
            resolver.getKSNameFromString(typeOfDiffUtils.canonicalName)
        ) != null


        return matched && !existed
    }

    abstract fun attachEqualsStatements(resolver: Resolver,
                                        symbol: KSClassDeclaration,
                                        methodItemsSameBuilder: FunSpec.Builder,
                                        methodContentsSameBuilder: FunSpec.Builder)

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy