diff --git a/compiler/frontend/src/org/jetbrains/kotlin/idea/MainFunctionDetector.kt b/compiler/frontend/src/org/jetbrains/kotlin/idea/MainFunctionDetector.kt index f65a28e19c4..5793d9bb626 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/idea/MainFunctionDetector.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/idea/MainFunctionDetector.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.idea import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.name.FqName @@ -138,6 +139,8 @@ class MainFunctionDetector { } } + if (descriptor.isSuspend && !languageVersionSettings.supportsFeature(LanguageFeature.ExtendedMainConvention)) return false + if (checkReturnType && !isMainReturnType(descriptor)) return false if (DescriptorUtils.isTopLevelDeclaration(descriptor)) return true @@ -173,17 +176,17 @@ class MainFunctionDetector { private fun findMainFunction(declarations: List) = declarations.filterIsInstance().find { isMain(it) } - companion object { - private fun isParameterNumberSuitsForMain( - parametersCount: Int, - isTopLevel: Boolean, - allowParameterless: Boolean - ) = when (parametersCount) { - 1 -> true - 0 -> isTopLevel && allowParameterless - else -> false - } + 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) diff --git a/compiler/testData/codegen/bytecodeListing/main/parameterlessMain.kt b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain.kt new file mode 100644 index 00000000000..1eb139e269f --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain.kt @@ -0,0 +1,3 @@ +// WITH_RUNTIME + +fun main() {} diff --git a/compiler/testData/codegen/bytecodeListing/main/parameterlessMain.txt b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain.txt new file mode 100644 index 00000000000..303ca34ece5 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain.txt @@ -0,0 +1,5 @@ +@kotlin.Metadata +public final class ParameterlessMainKt { + public final static method main(): void + public synthetic static method main(p0: java.lang.String[]): void +} diff --git a/compiler/testData/codegen/bytecodeListing/main/parameterlessMain_before.kt b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain_before.kt new file mode 100644 index 00000000000..a80ef8e8d6c --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain_before.kt @@ -0,0 +1,4 @@ +// !LANGUAGE: -ExtendedMainConvention +// WITH_RUNTIME + +fun main() {} diff --git a/compiler/testData/codegen/bytecodeListing/main/parameterlessMain_before.txt b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain_before.txt new file mode 100644 index 00000000000..c77e75f9271 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain_before.txt @@ -0,0 +1,4 @@ +@kotlin.Metadata +public final class ParameterlessMain_beforeKt { + public final static method main(): void +} diff --git a/compiler/testData/codegen/bytecodeListing/main/suspendMain.kt b/compiler/testData/codegen/bytecodeListing/main/suspendMain.kt new file mode 100644 index 00000000000..6bce5e92de0 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/suspendMain.kt @@ -0,0 +1,3 @@ +// WITH_RUNTIME + +suspend fun main(args: Array) {} diff --git a/compiler/testData/codegen/bytecodeListing/main/suspendMain.txt b/compiler/testData/codegen/bytecodeListing/main/suspendMain.txt new file mode 100644 index 00000000000..e98f84dbc6a --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/suspendMain.txt @@ -0,0 +1,12 @@ +@kotlin.Metadata +synthetic final class SuspendMainKt$$$main { + private final field args: java.lang.String[] + synthetic method (p0: java.lang.String[]): void + public synthetic final method invoke(p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class SuspendMainKt { + public final static @org.jetbrains.annotations.Nullable method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[], @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object + public synthetic static method main(p0: java.lang.String[]): void +} diff --git a/compiler/testData/codegen/bytecodeListing/main/suspendMain_before.kt b/compiler/testData/codegen/bytecodeListing/main/suspendMain_before.kt new file mode 100644 index 00000000000..d1ea8d0fe44 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/suspendMain_before.kt @@ -0,0 +1,4 @@ +// !LANGUAGE: -ExtendedMainConvention -ReleaseCoroutines +// WITH_RUNTIME + +suspend fun main(args: Array) {} diff --git a/compiler/testData/codegen/bytecodeListing/main/suspendMain_before.txt b/compiler/testData/codegen/bytecodeListing/main/suspendMain_before.txt new file mode 100644 index 00000000000..074312b130d --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/suspendMain_before.txt @@ -0,0 +1,4 @@ +@kotlin.Metadata +public final class SuspendMain_beforeKt { + public final static @org.jetbrains.annotations.Nullable method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[], @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object +} diff --git a/compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.kt b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.kt new file mode 100644 index 00000000000..c874ae58ffd --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.kt @@ -0,0 +1,7 @@ +// !LANGUAGE: -ExtendedMainConvention + +// FILE: a.kt +fun main() {} + +// FILE: b.kt +fun main() {} diff --git a/compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.txt b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.txt new file mode 100644 index 00000000000..0bff3544466 --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.txt @@ -0,0 +1,4 @@ +package + +public fun main(): kotlin.Unit +public fun main(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.kt b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.kt new file mode 100644 index 00000000000..d4de3428e37 --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.kt @@ -0,0 +1,7 @@ +// !LANGUAGE: -ExtendedMainConvention + +// FILE: a.kt +suspend fun main(args: Array) {} + +// FILE: b.kt +suspend fun main(args: Array) {} diff --git a/compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.txt b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.txt new file mode 100644 index 00000000000..6b214ad3854 --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.txt @@ -0,0 +1,4 @@ +package + +public suspend fun main(/*0*/ args: kotlin.Array): kotlin.Unit +public suspend fun main(/*0*/ args: kotlin.Array): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 30c48561874..42cd7a672e1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -15936,11 +15936,21 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMainInvalid.kt"); } + @TestMetadata("RedeclarationParameterlessMain_before.kt") + public void testRedeclarationParameterlessMain_before() throws Exception { + runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.kt"); + } + @TestMetadata("RedeclarationSuspendMainInMultiFile.kt") public void testRedeclarationSuspendMainInMultiFile() throws Exception { runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile.kt"); } + @TestMetadata("RedeclarationSuspendMainInMultiFile_before.kt") + public void testRedeclarationSuspendMainInMultiFile_before() throws Exception { + runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.kt"); + } + @TestMetadata("Redeclarations.kt") public void testRedeclarations() throws Exception { runTest("compiler/testData/diagnostics/tests/redeclarations/Redeclarations.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 779bf53c521..3a792aaaf12 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -15936,11 +15936,21 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMainInvalid.kt"); } + @TestMetadata("RedeclarationParameterlessMain_before.kt") + public void testRedeclarationParameterlessMain_before() throws Exception { + runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.kt"); + } + @TestMetadata("RedeclarationSuspendMainInMultiFile.kt") public void testRedeclarationSuspendMainInMultiFile() throws Exception { runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile.kt"); } + @TestMetadata("RedeclarationSuspendMainInMultiFile_before.kt") + public void testRedeclarationSuspendMainInMultiFile_before() throws Exception { + runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.kt"); + } + @TestMetadata("Redeclarations.kt") public void testRedeclarations() throws Exception { runTest("compiler/testData/diagnostics/tests/redeclarations/Redeclarations.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 730074b492a..18d8d2d7ed5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -320,6 +320,39 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { } } + @TestMetadata("compiler/testData/codegen/bytecodeListing/main") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Main extends AbstractBytecodeListingTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInMain() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/main"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("parameterlessMain.kt") + public void testParameterlessMain() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/main/parameterlessMain.kt"); + } + + @TestMetadata("parameterlessMain_before.kt") + public void testParameterlessMain_before() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/main/parameterlessMain_before.kt"); + } + + @TestMetadata("suspendMain.kt") + public void testSuspendMain() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/main/suspendMain.kt"); + } + + @TestMetadata("suspendMain_before.kt") + public void testSuspendMain_before() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/main/suspendMain_before.kt"); + } + } + @TestMetadata("compiler/testData/codegen/bytecodeListing/multiplatform") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index acb867e33a0..a1c76f8a443 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -88,6 +88,7 @@ enum class LanguageFeature( DslMarkerOnFunctionTypeReceiver(KOTLIN_1_4, kind = BUG_FIX), ProhibitErroneousExpressionsInAnnotationsWithUseSiteTargets(KOTLIN_1_3, kind = BUG_FIX), NewCapturedReceiverFieldNamingConvention(KOTLIN_1_3, kind = BUG_FIX), + ExtendedMainConvention(KOTLIN_1_3), RestrictReturnStatementTarget(KOTLIN_1_4, kind = BUG_FIX), NoConstantValueAttributeForNonConstVals(KOTLIN_1_4, kind = BUG_FIX), diff --git a/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt b/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt index 052ee5c28f5..31a89314206 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt @@ -39,6 +39,7 @@ import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.* +import org.jetbrains.kotlin.idea.test.configureLanguageAndApiVersion import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.allChildren @@ -55,6 +56,9 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() { fun testMainInTest() { val createResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!) + configureLanguageAndApiVersion( + createResult.module.project, createResult.module, LanguageVersionSettingsImpl.DEFAULT.languageVersion.versionString + ) ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createResult.module, addJdk(testRootDisposable, ::mockJdk)) val runConfiguration = createConfigurationFromMain("some.main")