From a78dae93aed426984dfb889ff0a0e2796685a80e Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Mon, 16 Feb 2026 18:10:57 +0400 Subject: [PATCH 1/4] feat: add parameter to ignore methods by annotation packages --- .../epam/drill/agent/test2code/Test2Code.kt | 16 +++++++++++++++- .../Test2CodeParameterDefinitions.kt | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt index 8adcf4fa..67145bde 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt @@ -149,10 +149,24 @@ class Test2Code( } var classCount = 0 var methodCount = 0 + + val excludeMethodsByAnnotationPackage = + configuration.parameters[Test2CodeParameterDefinitions.EXCLUDE_METHODS_BY_ANNOTATION_PACKAGE] as List + val hasAnnotationsExclusions = excludeMethodsByAnnotationPackage.isNotEmpty() + scanClasses { classes -> classes .also { classCount += it.size } - .flatMap { parseAstClass(it.entityName(), it.bytes()) } + .asSequence() + .flatMap { parseAstClass(it.entityName(), it.bytes()).asSequence() } + .filter { method -> + !hasAnnotationsExclusions || + method.annotations?.keys?.none { key -> + excludeMethodsByAnnotationPackage.any { key.contains(it) } + } + ?: false + } + .toList() .also { methodCount += it.size } .chunked(configuration.parameters[Test2CodeParameterDefinitions.METHODS_SEND_PAGE_SIZE]) .forEach(::sendClassMetadata) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/configuration/Test2CodeParameterDefinitions.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/configuration/Test2CodeParameterDefinitions.kt index fdc5547c..10625a34 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/configuration/Test2CodeParameterDefinitions.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/configuration/Test2CodeParameterDefinitions.kt @@ -21,6 +21,7 @@ import com.epam.drill.agent.common.configuration.AgentParameterDefinitionCollect import com.epam.drill.agent.common.configuration.BaseAgentParameterDefinition import com.epam.drill.agent.common.configuration.ValidationType import com.epam.drill.agent.configuration.isNotBlank +import com.epam.drill.agent.configuration.isValidPackage import com.epam.drill.agent.configuration.minDuration object Test2CodeParameterDefinitions : AgentParameterDefinitionCollection() { @@ -68,5 +69,23 @@ object Test2CodeParameterDefinitions : AgentParameterDefinitionCollection() { description = "Enable/disable application classes scanning", defaultValue = true ).register() + val EXCLUDE_METHODS_BY_ANNOTATION_PACKAGE = AgentParameterDefinition.forList( + name = "excludeMethodsByAnnotationPackage", + description = """ + Excludes methods with annotations from the specified packages from code scanning process. + Matches exact packages and descendants. + + Package names must be delimited with / (forward slash) and separated by ; + + Example: exclude methods autogenerated by SLF4J and Lombok + org/slf4j;lombok + """.trimIndent(), + defaultValue = emptyList(), + parser = { it.split(";") }, + validation = ValidationType.SOFT, + itemValidator = { + isValidPackage() + } + ).register() } From fb0703bc1eff403c233a60c7960ef9ce69a88f9d Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Mon, 16 Feb 2026 18:27:48 +0400 Subject: [PATCH 2/4] feat: add lazy chunking and keep track of number of filtered methods --- .../epam/drill/agent/test2code/Test2Code.kt | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt index 67145bde..160e937b 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt @@ -149,6 +149,7 @@ class Test2Code( } var classCount = 0 var methodCount = 0 + var filteredMethods = 0 val excludeMethodsByAnnotationPackage = configuration.parameters[Test2CodeParameterDefinitions.EXCLUDE_METHODS_BY_ANNOTATION_PACKAGE] as List @@ -160,18 +161,23 @@ class Test2Code( .asSequence() .flatMap { parseAstClass(it.entityName(), it.bytes()).asSequence() } .filter { method -> - !hasAnnotationsExclusions || - method.annotations?.keys?.none { key -> - excludeMethodsByAnnotationPackage.any { key.contains(it) } + val keepMethod = !hasAnnotationsExclusions || + method.annotations?.keys?.none { key -> + excludeMethodsByAnnotationPackage.any { key.contains(it) } + } ?: false + if (keepMethod) { + methodCount++ + } else { + filteredMethods++ } - ?: false + keepMethod } - .toList() - .also { methodCount += it.size } - .chunked(configuration.parameters[Test2CodeParameterDefinitions.METHODS_SEND_PAGE_SIZE]) + .chunkedLazy(configuration.parameters[Test2CodeParameterDefinitions.METHODS_SEND_PAGE_SIZE]) .forEach(::sendClassMetadata) } - logger.info { "Scanned $classCount classes with $methodCount methods" } + logger.info { """Scanned $classCount classes with $methodCount methods + | total methods: ${methodCount + filteredMethods}, but $filteredMethods methods were excluded by annotations + | from packages specified in ${Test2CodeParameterDefinitions.EXCLUDE_METHODS_BY_ANNOTATION_PACKAGE.name} parameter""".trimMargin() } } private val classMetadataDestination = AgentMessageDestination("PUT", "methods") @@ -188,5 +194,16 @@ class Test2Code( logger.debug { "sendClassMetadata: Sending methods: $message" } sender.send(classMetadataDestination, message, ClassMetadata.serializer()) } +} +private fun Sequence.chunkedLazy(size: Int): Sequence> = sequence { + val buffer = mutableListOf() + for (item in this@chunkedLazy) { + buffer += item + if (buffer.size == size) { + yield(buffer.toList()) + buffer.clear() + } + } + if (buffer.isNotEmpty()) yield(buffer.toList()) } From 6fe29308bed963eea583e6f678f11db5761cc11b Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Mon, 16 Feb 2026 18:34:11 +0400 Subject: [PATCH 3/4] feat: add lazy chunking and keep track of number of filtered methods --- .../main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt index 160e937b..677c1e6b 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt @@ -176,8 +176,9 @@ class Test2Code( .forEach(::sendClassMetadata) } logger.info { """Scanned $classCount classes with $methodCount methods - | total methods: ${methodCount + filteredMethods}, but $filteredMethods methods were excluded by annotations - | from packages specified in ${Test2CodeParameterDefinitions.EXCLUDE_METHODS_BY_ANNOTATION_PACKAGE.name} parameter""".trimMargin() } + | total methods: ${methodCount + filteredMethods}; + | methods excluded by annotations: $filteredMethods + | packages for annotations-based exclusion are specified in ${Test2CodeParameterDefinitions.EXCLUDE_METHODS_BY_ANNOTATION_PACKAGE.name} parameter """.trimMargin() } } private val classMetadataDestination = AgentMessageDestination("PUT", "methods") From dfe115c8d1e7286a062b2c62fdd13dd8f928d418 Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Mon, 16 Feb 2026 19:15:12 +0400 Subject: [PATCH 4/4] refactor: remove branching from filtered methods counting --- .../epam/drill/agent/test2code/Test2Code.kt | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt index 677c1e6b..fca9400b 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt @@ -148,8 +148,8 @@ class Test2Code( return } var classCount = 0 - var methodCount = 0 - var filteredMethods = 0 + var totalMethodsCount = 0 + var filteredMethodsCount = 0 val excludeMethodsByAnnotationPackage = configuration.parameters[Test2CodeParameterDefinitions.EXCLUDE_METHODS_BY_ANNOTATION_PACKAGE] as List @@ -160,24 +160,20 @@ class Test2Code( .also { classCount += it.size } .asSequence() .flatMap { parseAstClass(it.entityName(), it.bytes()).asSequence() } + .onEach { totalMethodsCount++ } .filter { method -> - val keepMethod = !hasAnnotationsExclusions || + !hasAnnotationsExclusions || method.annotations?.keys?.none { key -> excludeMethodsByAnnotationPackage.any { key.contains(it) } } ?: false - if (keepMethod) { - methodCount++ - } else { - filteredMethods++ - } - keepMethod } + .onEach { filteredMethodsCount++ } .chunkedLazy(configuration.parameters[Test2CodeParameterDefinitions.METHODS_SEND_PAGE_SIZE]) .forEach(::sendClassMetadata) } - logger.info { """Scanned $classCount classes with $methodCount methods - | total methods: ${methodCount + filteredMethods}; - | methods excluded by annotations: $filteredMethods + logger.info { """Scanned $classCount classes with $filteredMethodsCount methods + | total methods: ${totalMethodsCount + filteredMethodsCount}; + | methods excluded by annotations: ${totalMethodsCount - filteredMethodsCount} | packages for annotations-based exclusion are specified in ${Test2CodeParameterDefinitions.EXCLUDE_METHODS_BY_ANNOTATION_PACKAGE.name} parameter """.trimMargin() } }