NTP-7108 | Add Money Manager feature to the SuperApp (#12804)
Signed-off-by: namankhurmi <naman.khurmi@navi.com> Signed-off-by: kishan kumar <kishan.kumar@navi.com> Co-authored-by: Sanjay P <sanjay.p@navi.com> Co-authored-by: Venkat Praneeth Reddy <venkat.praneeth@navi.com> Co-authored-by: Naman Khurmi <naman.khurmi@navi.com> Co-authored-by: Ankit Yadav <ankit.yadav@navi.com> Co-authored-by: Hitesh Kumar <hitesh.kumar@navi.com> Co-authored-by: nikhil kumar <nikhil.kumar@navi.com> Co-authored-by: Abhinav Gupta <abhinav.g@navi.com> Co-authored-by: Kishan Kumar <kishan.kumar@navi.com> Co-authored-by: Soumya Ranjan Patra <soumya.ranjan@navi.com> Co-authored-by: Girish Suragani <girish.suragani@navi.com> Co-authored-by: Aparna Vadlamani <aparna.vadlamani@navi.com> Co-authored-by: Siddiboina Susai <siddiboina.susai@navi.com> Co-authored-by: Ayushman Sharma <ayushman.sharma@navi.com> Co-authored-by: Kamalesh Garnayak <kamalesh.garnayak@navi.com>
This commit is contained in:
1
android/navi-code/.gitignore
vendored
Normal file
1
android/navi-code/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
17
android/navi-code/build.gradle
Normal file
17
android/navi-code/build.gradle
Normal file
@@ -0,0 +1,17 @@
|
||||
plugins {
|
||||
alias libs.plugins.kotlin.jvm
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir "${buildDir.absolutePath}/generated/ksp/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation libs.ksp.symbolProcessingApi
|
||||
implementation libs.squareup.kotlinpoet
|
||||
implementation libs.squareup.kotlinpoet.ksp
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.code.annotations
|
||||
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class AutoGenerate
|
||||
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class EventName(val name: String)
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.code.generation
|
||||
|
||||
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
|
||||
import com.google.devtools.ksp.processing.SymbolProcessorProvider
|
||||
import com.navi.code.processors.EventTrackerProcessor
|
||||
|
||||
class EventTrackerProcessorProvider : SymbolProcessorProvider {
|
||||
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
|
||||
return EventTrackerProcessor(environment.codeGenerator, environment.logger)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.code.processors
|
||||
|
||||
import com.google.devtools.ksp.processing.CodeGenerator
|
||||
import com.google.devtools.ksp.processing.Dependencies
|
||||
import com.google.devtools.ksp.processing.KSPLogger
|
||||
import com.google.devtools.ksp.processing.Resolver
|
||||
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||
import com.google.devtools.ksp.symbol.ClassKind
|
||||
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
||||
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
|
||||
import com.google.devtools.ksp.validate
|
||||
import com.navi.code.annotations.AutoGenerate
|
||||
import com.navi.code.annotations.EventName
|
||||
import com.navi.code.utils.isDefaultKotlinFunction
|
||||
import com.navi.code.utils.toSnakeCase
|
||||
import com.squareup.kotlinpoet.FileSpec
|
||||
import com.squareup.kotlinpoet.FunSpec
|
||||
import com.squareup.kotlinpoet.KModifier
|
||||
import com.squareup.kotlinpoet.ParameterSpec
|
||||
import com.squareup.kotlinpoet.TypeSpec
|
||||
import com.squareup.kotlinpoet.ksp.toClassName
|
||||
import java.io.OutputStreamWriter
|
||||
|
||||
class EventTrackerProcessor(
|
||||
private val codeGenerator: CodeGenerator,
|
||||
private val logger: KSPLogger
|
||||
) : SymbolProcessor {
|
||||
|
||||
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||
|
||||
logger.info("Starting the processing of symbols with @AutoGenerate annotation.")
|
||||
|
||||
val symbols =
|
||||
resolver
|
||||
.getSymbolsWithAnnotation(AutoGenerate::class.qualifiedName!!)
|
||||
.filterIsInstance<KSClassDeclaration>()
|
||||
.validateAndGetSymbols()
|
||||
|
||||
symbols.forEach(::generateAnalyticsClass)
|
||||
|
||||
return symbols.filterNot { it.validate() }.toList()
|
||||
}
|
||||
|
||||
private fun Sequence<KSClassDeclaration>.validateAndGetSymbols(): Sequence<KSClassDeclaration> {
|
||||
return filter { classDeclaration ->
|
||||
when (classDeclaration.classKind) {
|
||||
ClassKind.INTERFACE -> true
|
||||
else -> {
|
||||
throw IllegalArgumentException(
|
||||
"Don't mark ${AutoGenerate::class.simpleName} on non-interface kind: ${classDeclaration.simpleName.asString()}."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateAnalyticsClass(classDeclaration: KSClassDeclaration) {
|
||||
|
||||
val packageName = classDeclaration.packageName.asString()
|
||||
|
||||
val className = classDeclaration.simpleName.asString()
|
||||
|
||||
val generatedClassName = "${className}Impl"
|
||||
|
||||
val fileSpecBuilder =
|
||||
FileSpec.builder(packageName, generatedClassName)
|
||||
.addImport("com.navi.analytics.utils", "NaviTrackEvent")
|
||||
|
||||
val classBuilder =
|
||||
TypeSpec.objectBuilder(generatedClassName).addModifiers(KModifier.INTERNAL)
|
||||
|
||||
classDeclaration
|
||||
.getAllFunctions()
|
||||
.filterNot { it.isDefaultKotlinFunction() }
|
||||
.forEach { function -> classBuilder.addFunction(generateMethod(function)) }
|
||||
|
||||
fileSpecBuilder.addType(classBuilder.build())
|
||||
|
||||
val file =
|
||||
codeGenerator.createNewFile(
|
||||
dependencies = Dependencies.ALL_FILES,
|
||||
packageName = packageName,
|
||||
fileName = generatedClassName
|
||||
)
|
||||
|
||||
OutputStreamWriter(file).use { writer -> fileSpecBuilder.build().writeTo(writer) }
|
||||
}
|
||||
|
||||
private fun generateMethod(function: KSFunctionDeclaration): FunSpec {
|
||||
|
||||
val methodName = function.simpleName.asString()
|
||||
|
||||
val parameters = function.parameters
|
||||
|
||||
val eventName =
|
||||
function.annotations
|
||||
.find { it.shortName.asString() == EventName::class.simpleName }
|
||||
?.arguments
|
||||
?.firstOrNull()
|
||||
?.value as? String
|
||||
?: throw IllegalArgumentException("Event Name is missing for method $methodName.")
|
||||
|
||||
if (eventName.isEmpty()) {
|
||||
throw IllegalArgumentException("Event Name is missing for method $methodName.")
|
||||
}
|
||||
|
||||
val paramList =
|
||||
parameters.map { param ->
|
||||
val paramName =
|
||||
param.name?.asString()
|
||||
?: throw IllegalArgumentException(
|
||||
"Parameter name is missing for method $methodName."
|
||||
)
|
||||
val paramType = param.type.resolve().toClassName()
|
||||
ParameterSpec.builder(paramName, paramType).build()
|
||||
}
|
||||
|
||||
val paramEntries =
|
||||
parameters.joinToString(", ") { param ->
|
||||
val paramName = param.name?.asString() ?: "param"
|
||||
"\"${paramName.toSnakeCase()}\" to $paramName.toString()"
|
||||
}
|
||||
|
||||
return FunSpec.builder(methodName)
|
||||
.addParameters(paramList)
|
||||
.addStatement(
|
||||
"NaviTrackEvent.trackEventOnClickStream(eventName = %S, eventValues = mapOf($paramEntries))",
|
||||
eventName
|
||||
)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.code.utils
|
||||
|
||||
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
|
||||
import com.squareup.kotlinpoet.ClassName
|
||||
import com.squareup.kotlinpoet.FunSpec
|
||||
import com.squareup.kotlinpoet.KModifier
|
||||
|
||||
fun KSFunctionDeclaration.isDefaultKotlinFunction(): Boolean {
|
||||
return simpleName.asString() in listOf("equals", "hashCode", "toString")
|
||||
}
|
||||
|
||||
fun KSFunctionDeclaration.generateOverrideMethodWithDefaultSuperCall(): FunSpec {
|
||||
val methodName = simpleName.asString()
|
||||
|
||||
val methodBuilder = FunSpec.builder(methodName).addModifiers(KModifier.OVERRIDE)
|
||||
|
||||
parameters.forEach { param ->
|
||||
val paramName =
|
||||
param.name?.asString()
|
||||
?: throw IllegalArgumentException(
|
||||
"Parameter name is missing for method $methodName."
|
||||
)
|
||||
|
||||
val paramType = param.type.resolve()
|
||||
methodBuilder.addParameter(
|
||||
paramName,
|
||||
ClassName(
|
||||
paramType.declaration.packageName.asString(),
|
||||
paramType.declaration.simpleName.asString()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
methodBuilder.addCode(
|
||||
"super.%L(%L)\n",
|
||||
methodName,
|
||||
parameters.joinToString(", ") { it.name?.asString().toString() }
|
||||
)
|
||||
return methodBuilder.build()
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.code.utils
|
||||
|
||||
fun String.toSnakeCase(): String {
|
||||
return this.replace(Regex("([a-z])([A-Z])"), "$1_$2").lowercase()
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
com.navi.code.generation.EventTrackerProcessorProvider
|
||||
Reference in New Issue
Block a user