Repository: JetBrains/kotlin
File: compiler/frontend/src/org/jetbrains/kotlin/idea/MainFunctionDetector.kt (Kotlin)

Code before:
        declaration: KtDeclaration,
        checkJvmStaticAnnotation: Boolean
    ) = declaration is KtNamedFunction && isMain(declaration, checkJvmStaticAnnotation, allowParameterless = false)

    fun getMainFunction(module: ModuleDescriptor): FunctionDescriptor? = getMainFunction(module, module.getPackage(FqName.ROOT))

    private fun getMainFunction(module: ModuleDescriptor, packageView: PackageViewDescriptor): FunctionDescriptor? {
        for (packageFragment in packageView.fragments.filter { it.module == module }) {
            DescriptorUtils.getAllDescriptors(packageFragment.getMemberScope())
                .filterIsInstance<FunctionDescriptor>()
                .firstOrNull { isMain(it) }
                ?.let { return it }
        }

        for (subpackageName in module.getSubPackagesOf(packageView.fqName, MemberScope.ALL_NAME_FILTER)) {
            getMainFunction(module, module.getPackage(subpackageName))?.let { return it }
        }

        return null
    }

    fun findMainFunction(declarations: List<KtElement>): KtNamedFunction? =
        declarations
            .ifEmpty { return@findMainFunction null }
            .filterIsInstance<KtNamedFunction>().find { isMain(it) }
            ?: findMainFunction(declarations.flatMap { it.getChildrenOfType<KtElement>().toList() })

    private fun isParameterNumberSuitsForMain(
        parametersCount: Int,
        isTopLevel: Boolean,
        allowParameterless: Boolean
    ) = when (parametersCount) {
        1 -> true
        0 -> isTopLevel && allowParameterless && languageVersionSettings.supportsFeature(LanguageFeature.ExtendedMainConvention)
        else -> false
    }

    companion object {
        private fun isMainReturnType(descriptor: FunctionDescriptor): Boolean {
            val returnType = descriptor.returnType
            return returnType != null && KotlinBuiltIns.isUnit(returnType)
        }

        private fun getJVMFunctionName(functionDescriptor: FunctionDescriptor): String {
            return DescriptorUtils.getJvmName(functionDescriptor) ?: functionDescriptor.name.asString()
        }

        private fun hasAnnotationWithExactNumberOfArguments(function: KtNamedFunction, number: Int) =
            function.annotationEntries.any { it.valueArguments.size == number }
    }


Review comment (suggestion):
I suggest to rewrite it a bit, so that in case there are several `main`s in the same file, we would avoid writing any of them to the manifest (might be worth adding a test for this case). Just like we do when several files declare top-level `main`.
```
    fun findMainFunction(container: KtDeclarationContainer): KtNamedFunction? =
        container.declarations.mapNotNull { declaration ->
            when (declaration) {
                is KtNamedFunction -> declaration.takeIf(mainFunctionDetector::isMain)
                is KtDeclarationContainer -> findMainFunction(declaration)
                else -> null
            }
        }.singleOrNull()
```

Code after:
    ) = declaration is KtNamedFunction && isMain(declaration, checkJvmStaticAnnotation, allowParameterless = false)

    fun getMainFunction(module: ModuleDescriptor): FunctionDescriptor? = getMainFunction(module, module.getPackage(FqName.ROOT))

    private fun getMainFunction(module: ModuleDescriptor, packageView: PackageViewDescriptor): FunctionDescriptor? {
        for (packageFragment in packageView.fragments.filter { it.module == module }) {
            DescriptorUtils.getAllDescriptors(packageFragment.getMemberScope())
                .filterIsInstance<FunctionDescriptor>()
                .firstOrNull { isMain(it) }
                ?.let { return it }
        }

        for (subpackageName in module.getSubPackagesOf(packageView.fqName, MemberScope.ALL_NAME_FILTER)) {
            getMainFunction(module, module.getPackage(subpackageName))?.let { return it }
        }

        return null
    }

    private fun isParameterNumberSuitsForMain(
        parametersCount: Int,
        isTopLevel: Boolean,
        allowParameterless: Boolean
    ) = when (parametersCount) {
        1 -> true
        0 -> isTopLevel && allowParameterless && languageVersionSettings.supportsFeature(LanguageFeature.ExtendedMainConvention)
        else -> false
    }

    companion object {
        private fun isMainReturnType(descriptor: FunctionDescriptor): Boolean {
            val returnType = descriptor.returnType
            return returnType != null && KotlinBuiltIns.isUnit(returnType)
        }

        private fun getJVMFunctionName(functionDescriptor: FunctionDescriptor): String {
            return DescriptorUtils.getJvmName(functionDescriptor) ?: functionDescriptor.name.asString()
        }

        private fun hasAnnotationWithExactNumberOfArguments(function: KtNamedFunction, number: Int) =
            function.annotationEntries.any { it.valueArguments.size == number }
    }

    interface Factory {
        fun createMainFunctionDetector(trace: BindingTrace, languageVersionSettings: LanguageVersionSettings): MainFunctionDetector

        class Ordinary : Factory {
            override fun createMainFunctionDetector(
                trace: BindingTrace,
                languageVersionSettings: LanguageVersionSettings
            ): MainFunctionDetector {