diff --git a/examples/android-coffee-maker/build.gradle.kts b/examples/android-coffee-maker/build.gradle.kts index 5b26aa4..2c027ba 100644 --- a/examples/android-coffee-maker/build.gradle.kts +++ b/examples/android-coffee-maker/build.gradle.kts @@ -48,5 +48,5 @@ dependencies { ksp { arg("KOIN_CONFIG_CHECK","true") - arg("KOIN_DEFAULT_MODULE","false") +// arg("KOIN_DEFAULT_MODULE","false") } \ No newline at end of file diff --git a/examples/android-coffee-maker/src/test/java/AndroidModuleTest.kt b/examples/android-coffee-maker/src/test/java/AndroidModuleTest.kt index dbeb88e..f706657 100644 --- a/examples/android-coffee-maker/src/test/java/AndroidModuleTest.kt +++ b/examples/android-coffee-maker/src/test/java/AndroidModuleTest.kt @@ -7,6 +7,8 @@ import org.koin.ksp.generated.module import org.koin.sample.android.library.CommonRepository import org.koin.sample.android.library.MyScope import org.koin.sample.androidx.app.ScopedStuff +import org.koin.sample.androidx.data.DataConsumer +import org.koin.sample.androidx.data.MyDataConsumer import org.koin.sample.androidx.di.AppModule import org.koin.sample.androidx.di.DataModule import org.koin.sample.androidx.repository.RepositoryModule @@ -31,6 +33,9 @@ class AndroidModuleTest { val scope = koin.createScope() scope.get() + assert(koin.getOrNull() != null) + assert(koin.getOrNull() != null) + stopKoin() } } \ No newline at end of file diff --git a/examples/android-library/build.gradle.kts b/examples/android-library/build.gradle.kts index ad98062..ea43236 100644 --- a/examples/android-library/build.gradle.kts +++ b/examples/android-library/build.gradle.kts @@ -35,4 +35,5 @@ dependencies { ksp { arg("KOIN_CONFIG_CHECK","true") +// arg("KOIN_DEFAULT_MODULE","false") } \ No newline at end of file diff --git a/examples/android-library/src/main/java/org/koin/sample/androidx/data/DataConsumer.kt b/examples/android-library/src/main/java/org/koin/sample/androidx/data/DataConsumer.kt new file mode 100644 index 0000000..a53517b --- /dev/null +++ b/examples/android-library/src/main/java/org/koin/sample/androidx/data/DataConsumer.kt @@ -0,0 +1,11 @@ +package org.koin.sample.androidx.data + +import org.koin.core.annotation.Factory + +@Factory +class DataConsumer + +class MyDataConsumer(val dc : DataConsumer) + +@Factory +fun funDataConsumer(dc : DataConsumer) = MyDataConsumer(dc) \ No newline at end of file diff --git a/examples/coffee-maker-module/src/main/kotlin/org/koin/example/coffee/DetachedComponents.kt b/examples/coffee-maker-module/src/main/kotlin/org/koin/example/coffee/DetachedComponents.kt new file mode 100644 index 0000000..c59977e --- /dev/null +++ b/examples/coffee-maker-module/src/main/kotlin/org/koin/example/coffee/DetachedComponents.kt @@ -0,0 +1,6 @@ +package org.koin.example.coffee + +import org.koin.core.annotation.Single + +@Single +class MyDetachCoffeeComponent \ No newline at end of file diff --git a/examples/coffee-maker/build.gradle.kts b/examples/coffee-maker/build.gradle.kts index 4eade17..a48d1a8 100644 --- a/examples/coffee-maker/build.gradle.kts +++ b/examples/coffee-maker/build.gradle.kts @@ -22,6 +22,7 @@ dependencies { implementation(project(":coffee-maker-module")) testImplementation(libs.koin.test) + testImplementation(libs.junit) } ksp { diff --git a/examples/coffee-maker/src/test/java/CoffeeAppTest.kt b/examples/coffee-maker/src/test/java/CoffeeAppTest.kt index fd87f38..393cea1 100644 --- a/examples/coffee-maker/src/test/java/CoffeeAppTest.kt +++ b/examples/coffee-maker/src/test/java/CoffeeAppTest.kt @@ -7,6 +7,7 @@ import org.koin.core.qualifier.StringQualifier import org.koin.core.qualifier.named import org.koin.example.CoffeeApp import org.koin.example.coffee.CoffeePumpList +import org.koin.example.coffee.MyDetachCoffeeComponent import org.koin.example.coffee.pump.PumpCounter import org.koin.example.di.CoffeeAppModule import org.koin.example.di.CoffeeTesterModule @@ -81,6 +82,8 @@ class CoffeeAppTest { assert(koin.get().list.size == 2) assert(koin.get().count == 2) + assert(koin.getOrNull() != null) + stopKoin() } } \ No newline at end of file diff --git a/projects/koin-annotations/src/commonMain/kotlin/org/koin/core/annotation/CoreAnnotations.kt b/projects/koin-annotations/src/commonMain/kotlin/org/koin/core/annotation/CoreAnnotations.kt index 6d950cb..a73d95b 100644 --- a/projects/koin-annotations/src/commonMain/kotlin/org/koin/core/annotation/CoreAnnotations.kt +++ b/projects/koin-annotations/src/commonMain/kotlin/org/koin/core/annotation/CoreAnnotations.kt @@ -194,4 +194,12 @@ annotation class Module(val includes: Array> = [], val createdAtStart: * @param value: package to scan */ @Target(AnnotationTarget.CLASS, AnnotationTarget.FIELD) -annotation class ComponentScan(val value: String = "") \ No newline at end of file +annotation class ComponentScan(val value: String = "") + +/** + * + * + * @param value: package of declared definition + */ +@Target(AnnotationTarget.CLASS, AnnotationTarget.FIELD, AnnotationTarget.FUNCTION) +annotation class Definition(val value: String = "") \ No newline at end of file diff --git a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/BuilderProcessor.kt b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/BuilderProcessor.kt index aada1a3..c38ae62 100644 --- a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/BuilderProcessor.kt +++ b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/BuilderProcessor.kt @@ -17,7 +17,7 @@ package org.koin.compiler import com.google.devtools.ksp.processing.* import com.google.devtools.ksp.symbol.KSAnnotated -import org.koin.compiler.KspOptions.KOIN_CONFIG_CHECK +import org.koin.compiler.KspOptions.* import org.koin.compiler.generator.KoinGenerator import org.koin.compiler.metadata.KoinMetaData import org.koin.compiler.scanner.KoinMetaDataScanner @@ -36,7 +36,6 @@ class BuilderProcessor( override fun process(resolver: Resolver): List { logger.logging("Scanning symbols ...") - //TODO Handle allowDefaultModule option val invalidSymbols = koinMetaDataScanner.scanSymbols(resolver) if (invalidSymbols.isNotEmpty()) { @@ -53,17 +52,8 @@ class BuilderProcessor( logger.logging("Scan metadata ...") val moduleList = koinMetaDataScanner.scanKoinModules(defaultModule) - if (isDefaultModuleDisabled()){ - if (defaultModule.definitions.isNotEmpty()){ - logger.error("Default module is disabled!") - defaultModule.definitions.forEach { def -> - logger.error("definition '${def.packageName}.${def.label}' needs to be defined in a module") - } - } - } - logger.logging("Generate code ...") - koinCodeGenerator.generateModules(moduleList, defaultModule) + koinCodeGenerator.generateModules(moduleList, defaultModule, isDefaultModuleActive()) if (isConfigCheckActive()) { logger.warn("[Experimental] Koin Configuration Check") @@ -74,11 +64,12 @@ class BuilderProcessor( } private fun isConfigCheckActive(): Boolean { - return options[KOIN_CONFIG_CHECK.name] == true.toString() + return options.getOrDefault(KOIN_CONFIG_CHECK.name, "true") == true.toString() } - private fun isDefaultModuleDisabled(): Boolean { - return options[KspOptions.KOIN_DEFAULT_MODULE.name] == false.toString() + //TODO turn KOIN_DEFAULT_MODULE to false by default - Next Major version (breaking) + private fun isDefaultModuleActive(): Boolean { + return options.getOrDefault(KOIN_DEFAULT_MODULE.name, "true") == true.toString() } } diff --git a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/DefinitionGenerationExt.kt b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/DefinitionGenerationExt.kt index 386040d..5c6bd20 100644 --- a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/DefinitionGenerationExt.kt +++ b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/DefinitionGenerationExt.kt @@ -16,13 +16,15 @@ import com.google.devtools.ksp.symbol.KSDeclaration import org.koin.compiler.generator.KoinGenerator.Companion.LOGGER import org.koin.compiler.metadata.KoinMetaData +import org.koin.compiler.metadata.KoinMetaData.Module.Companion.DEFINE_PREFIX import org.koin.compiler.metadata.SINGLE import org.koin.compiler.scanner.filterForbiddenKeywords import java.io.OutputStream const val NEW_LINE = "\n\t" -fun OutputStream.generateDefinition(def: KoinMetaData.Definition, label: () -> String) { + +fun OutputStream.generateDefinition(def: KoinMetaData.Definition, isExternalDefinition: Boolean = false, label: () -> String) { LOGGER.logging("generate ${def.label} - $def") val param = def.parameters.generateParamFunction() val ctor = generateConstructor(def.parameters) @@ -32,9 +34,41 @@ fun OutputStream.generateDefinition(def: KoinMetaData.Definition, label: () -> S if (qualifier == "") CREATED_AT_START else ",$CREATED_AT_START" } else "" val space = if (def.isScoped()) NEW_LINE + "\t" else NEW_LINE + + if (isExternalDefinition) { + writeExternalDefinitionFunction(def, qualifier, createAtStart, param, label, ctor, binds) + } + else { + writeDefinition(space, def, qualifier, createAtStart, param, label, ctor, binds) + } +} + +private fun OutputStream.writeDefinition( + space: String, + def: KoinMetaData.Definition, + qualifier: String, + createAtStart: String, + param: String, + label: () -> String, + ctor: String, + binds: String +) { appendText("$space${def.keyword.keyword}($qualifier$createAtStart) { ${param}${label()}$ctor } $binds") } +private fun OutputStream.writeExternalDefinitionFunction( + def: KoinMetaData.Definition, + qualifier: String, + createAtStart: String, + param: String, + label: () -> String, + ctor: String, + binds: String +) { + appendText("\n@Definition(\"${def.packageName}\")\n") + appendText("fun Module.$DEFINE_PREFIX${def.label}() = ${def.keyword.keyword}($qualifier$createAtStart) { ${param}${label()}$ctor } $binds") +} + fun OutputStream.generateModuleFunctionDeclarationDefinition(def: KoinMetaData.Definition.FunctionDefinition) { generateDefinition(def) { "moduleInstance.${def.functionName}" } } @@ -43,15 +77,26 @@ fun OutputStream.generateObjectModuleFunctionDeclarationDefinition( def: KoinMetaData.Definition.FunctionDefinition, modulePath: String ) { - generateDefinition(def) { "$modulePath.${def.functionName}" } + generateDefinition(def ) { "$modulePath.${def.functionName}" } +} + +fun OutputStream.generateFunctionDeclarationDefinition(def: KoinMetaData.Definition.FunctionDefinition,isExternalDefinition: Boolean = false) { + generateDefinition(def,isExternalDefinition) { "${def.packageNamePrefix}${def.functionName}" } +} + +fun OutputStream.generateClassDeclarationDefinition( + def: KoinMetaData.Definition.ClassDefinition, + isExternalDefinition: Boolean = false +) { + generateDefinition(def,isExternalDefinition) { "${def.packageNamePrefix}${def.className}" } } -fun OutputStream.generateFunctionDeclarationDefinition(def: KoinMetaData.Definition.FunctionDefinition) { - generateDefinition(def) { "${def.packageNamePrefix}${def.functionName}" } +internal fun OutputStream.generateExternalDefinitionCalls(module: KoinMetaData.Module) { + generateExternalDefinitionCalls(module.externalDefinitions) } -fun OutputStream.generateClassDeclarationDefinition(def: KoinMetaData.Definition.ClassDefinition) { - generateDefinition(def) { "${def.packageNamePrefix}${def.className}" } +internal fun OutputStream.generateExternalDefinitionCalls(externalDefinitions : List) { + this.appendText("${NEW_LINE}${externalDefinitions.joinToString(separator = "\n${NEW_LINE}") { "${it.name}()" }}") } const val CREATED_AT_START = "createdAtStart=true" diff --git a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/KoinGenerator.kt b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/KoinGenerator.kt index ca263eb..43c0307 100644 --- a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/KoinGenerator.kt +++ b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/KoinGenerator.kt @@ -20,7 +20,9 @@ import com.google.devtools.ksp.processing.Dependencies import com.google.devtools.ksp.processing.KSPLogger import generateClassModule import generateDefaultModuleFooter +import generateDefaultModuleFunction import generateDefaultModuleHeader +import generateExternalDefinitionCalls import generateFieldDefaultModule import org.koin.compiler.metadata.KoinMetaData import java.io.OutputStream @@ -36,35 +38,51 @@ class KoinGenerator( fun generateModules( moduleList: List, - defaultModule: KoinMetaData.Module + defaultModule: KoinMetaData.Module, + generateDefaultModule : Boolean ) { logger.logging("generate ${moduleList.size} modules ...") moduleList.forEach { generateModule(it) } if (defaultModule.definitions.isNotEmpty()) { - logger.logging("generate default module ...") - val defaultModuleFile = codeGenerator.getFile(fileName = "Default") - defaultModuleFile.generateDefaultModuleHeader(defaultModule.definitions) - generateModule(defaultModule, defaultModuleFile) - defaultModuleFile.generateDefaultModuleFooter() - defaultModuleFile.close() + generateDefaultFile(defaultModule, generateDefaultModule) } } - private fun generateModule(module: KoinMetaData.Module, defaultFile: OutputStream? = null) { - logger.logging("generate $module - ${module.type}") + private fun generateDefaultFile( + defaultModule: KoinMetaData.Module, + generateDefaultModule: Boolean + ) { + logger.logging("generate default file ...") + val defaultModuleFile = codeGenerator.getFile(fileName = "Default") + defaultModuleFile.generateDefaultModuleHeader(defaultModule.definitions) + generateAllExternalDefinitions(defaultModule, defaultModuleFile) + + if (generateDefaultModule) { + generateDefaultModule(defaultModule, defaultModuleFile) + } + defaultModuleFile.close() + } - val isFieldModule = module.type == KoinMetaData.ModuleType.FIELD && module.definitions.isNotEmpty() - if (isFieldModule){ - // generate field module - defaultFile!!.generateFieldDefaultModule(module.definitions) - } else { - // generate class module - val moduleFile = codeGenerator.getFile(fileName = module.generateModuleFileName()) - generateClassModule(moduleFile, module) + private fun generateAllExternalDefinitions(defaultModule: KoinMetaData.Module, defaultModuleFile: OutputStream) { + defaultModuleFile.generateFieldDefaultModule(defaultModule.definitions, generateExternalDefinitions = true) + } + + private fun generateDefaultModule(defaultModule: KoinMetaData.Module, defaultModuleFile: OutputStream) { + with(defaultModuleFile){ + generateDefaultModuleFunction() + generateExternalDefinitionCalls(defaultModule.getDefinitionsAsExternals()) + generateDefaultModuleFooter() } } + private fun generateModule(module: KoinMetaData.Module) { + logger.logging("generate $module - ${module.type}") + // generate class module + val moduleFile = codeGenerator.getFile(fileName = module.generateModuleFileName()) + generateClassModule(moduleFile, module) + } + private fun KoinMetaData.Module.generateModuleFileName(): String { val extensionName = packageName("$") return "${name}Gen${extensionName}" diff --git a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/ModuleGenerationExt.kt b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/ModuleGenerationExt.kt index 011ee38..f7c05d5 100644 --- a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/ModuleGenerationExt.kt +++ b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/ModuleGenerationExt.kt @@ -18,27 +18,31 @@ import org.koin.compiler.generator.* import org.koin.compiler.metadata.KoinMetaData import java.io.OutputStream -fun OutputStream.generateFieldDefaultModule(definitions: List) { +fun OutputStream.generateFieldDefaultModule(definitions: List, generateExternalDefinitions : Boolean) { val standardDefinitions = definitions.filter { it.isNotScoped() }.toSet() val scopeDefinitions = definitions.filter { it.isScoped() }.toSet() - standardDefinitions.forEach { generateDefaultModuleDefinition(it) } + standardDefinitions.forEach { generateDefaultModuleDefinition(it,generateExternalDefinitions) } + //TODO Scope in function? scopeDefinitions .groupBy { it.scope } .forEach { (scope, definitions) -> appendText(generateScope(scope!!)) definitions.forEach { definition -> - generateDefaultModuleDefinition(definition) + generateDefaultModuleDefinition(definition, generateExternalDefinitions) } appendText(generateScopeClosing()) } } -fun OutputStream.generateDefaultModuleDefinition(definition: KoinMetaData.Definition) { +fun OutputStream.generateDefaultModuleDefinition( + definition: KoinMetaData.Definition, + generateExternalDefinitions: Boolean +) { if (definition is KoinMetaData.Definition.ClassDefinition){ - generateClassDeclarationDefinition(definition) + generateClassDeclarationDefinition(definition, isExternalDefinition = generateExternalDefinitions) } else if (definition is KoinMetaData.Definition.FunctionDefinition && !definition.isClassFunction) { - generateFunctionDeclarationDefinition(definition) + generateFunctionDeclarationDefinition(definition, isExternalDefinition = generateExternalDefinitions) } } @@ -67,6 +71,10 @@ fun generateClassModule(classFile: OutputStream, module: KoinMetaData.Module) { generateDefinitions(module, classFile) } + if (module.externalDefinitions.isNotEmpty()){ + classFile.generateExternalDefinitionCalls(module) + } + classFile.appendText("\n}") val visibilityString = module.visibility.toSourceString() classFile.appendText( @@ -140,6 +148,10 @@ private fun KoinMetaData.Module.generateModuleField( fun OutputStream.generateDefaultModuleHeader(definitions: List) { appendText(DEFAULT_MODULE_HEADER) appendText(definitions.generateImports()) +} + +fun OutputStream.generateDefaultModuleFunction() { + appendText("\n\n") appendText(DEFAULT_MODULE_FUNCTION) } diff --git a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/Templates.kt b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/Templates.kt index d09a88a..e46f3dc 100644 --- a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/Templates.kt +++ b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/generator/Templates.kt @@ -20,6 +20,7 @@ val DEFAULT_MODULE_HEADER = """ import org.koin.core.KoinApplication import org.koin.core.module.Module + import org.koin.core.annotation.Definition import org.koin.dsl.* """.trimIndent() diff --git a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/metadata/KoinMetaData.kt b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/metadata/KoinMetaData.kt index 11413c7..b13d35d 100644 --- a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/metadata/KoinMetaData.kt +++ b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/metadata/KoinMetaData.kt @@ -26,6 +26,7 @@ sealed class KoinMetaData { val packageName: String, val name: String, val definitions: MutableList = mutableListOf(), + val externalDefinitions: MutableList = mutableListOf(), val type: ModuleType = ModuleType.FIELD, val componentScan: ComponentScan? = null, val includes: List? = null, @@ -53,6 +54,14 @@ sealed class KoinMetaData { else -> false } } + + fun getDefinitionsAsExternals(): List { + return definitions.map { ExternalDefinition(it.packageName, "$DEFINE_PREFIX${it.label}") } + } + + companion object { + const val DEFINE_PREFIX = "define" + } } enum class ModuleType { @@ -98,6 +107,8 @@ sealed class KoinMetaData { } } + data class ExternalDefinition(val targetPackage: String,val name: String) + sealed class Definition( val label: String, val parameters: List, diff --git a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/scanner/KoinMetaDataScanner.kt b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/scanner/KoinMetaDataScanner.kt index 83a3344..df6676e 100644 --- a/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/scanner/KoinMetaDataScanner.kt +++ b/projects/koin-ksp-compiler/src/jvmMain/kotlin/org/koin/compiler/scanner/KoinMetaDataScanner.kt @@ -15,14 +15,17 @@ */ package org.koin.compiler.scanner +import com.google.devtools.ksp.KspExperimental import com.google.devtools.ksp.processing.KSPLogger import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.symbol.KSAnnotated import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.KSDeclaration import com.google.devtools.ksp.symbol.KSFunctionDeclaration import com.google.devtools.ksp.validate import org.koin.compiler.metadata.DEFINITION_ANNOTATION_LIST_TYPES import org.koin.compiler.metadata.KoinMetaData +import org.koin.core.annotation.Definition import org.koin.core.annotation.Module class KoinMetaDataScanner( @@ -35,7 +38,11 @@ class KoinMetaDataScanner( private var validModuleSymbols = mutableListOf() private var validDefinitionSymbols = mutableListOf() + private var externalDefinitions = listOf() + private val definitionAnnotationName = Definition::class.simpleName + + @OptIn(KspExperimental::class) fun scanSymbols(resolver: Resolver): List { val moduleSymbols = resolver.getSymbolsWithAnnotation(Module::class.qualifiedName!!).toList() val definitionSymbols = DEFINITION_ANNOTATION_LIST_TYPES.flatMap { annotation -> @@ -55,6 +62,17 @@ class KoinMetaDataScanner( } logger.logging("All symbols are valid") + + externalDefinitions = resolver.getDeclarationsFromPackage("org.koin.ksp.generated") + .filter { it.annotations.any { it.shortName.asString() == definitionAnnotationName } } + .toList() + + if (externalDefinitions.isNotEmpty()) { + logger.logging("external definitions: ${externalDefinitions.size}") + } else { + logger.logging("no external definition") + } + return emptyList() } @@ -63,9 +81,26 @@ class KoinMetaDataScanner( val index = moduleList.generateScanComponentIndex() scanClassComponents(defaultModule, index) scanFunctionComponents(defaultModule, index) + scanExternalDefinitions(index) return moduleList } + private fun scanExternalDefinitions(index: List) { + externalDefinitions + .mapNotNull { def -> + def.annotations + .first { it.shortName.asString() == definitionAnnotationName }.arguments.first().value?.toString() + ?.let { + KoinMetaData.ExternalDefinition(targetPackage = it, name = def.simpleName.asString()) + } + } + .forEach { extDef -> + // add to first module that accept + val module = index.firstOrNull { it.acceptDefinition(extDef.targetPackage) } + module?.externalDefinitions?.add(extDef) + } + } + private fun scanClassModules(): List { logger.logging("scan modules ...") return validModuleSymbols