Add language feature for extended main convention
- suspend - parameterless #KT-17679 Fixed #KT-26574 Fixed
This commit is contained in:
@@ -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<KtDeclaration>) =
|
||||
declarations.filterIsInstance<KtNamedFunction>().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)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun main() {}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// !LANGUAGE: -ExtendedMainConvention
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun main() {}
|
||||
@@ -0,0 +1,4 @@
|
||||
@kotlin.Metadata
|
||||
public final class ParameterlessMain_beforeKt {
|
||||
public final static method main(): void
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
suspend fun main(args: Array<String>) {}
|
||||
@@ -0,0 +1,12 @@
|
||||
@kotlin.Metadata
|
||||
synthetic final class SuspendMainKt$$$main {
|
||||
private final field args: java.lang.String[]
|
||||
synthetic method <init>(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
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// !LANGUAGE: -ExtendedMainConvention -ReleaseCoroutines
|
||||
// WITH_RUNTIME
|
||||
|
||||
suspend fun main(args: Array<String>) {}
|
||||
@@ -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
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
// !LANGUAGE: -ExtendedMainConvention
|
||||
|
||||
// FILE: a.kt
|
||||
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
|
||||
|
||||
// FILE: b.kt
|
||||
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun main(): kotlin.Unit
|
||||
public fun main(): kotlin.Unit
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
// !LANGUAGE: -ExtendedMainConvention
|
||||
|
||||
// FILE: a.kt
|
||||
<!CONFLICTING_OVERLOADS!>suspend fun main(<!UNUSED_PARAMETER!>args<!>: Array<String>)<!> {}
|
||||
|
||||
// FILE: b.kt
|
||||
<!CONFLICTING_OVERLOADS!>suspend fun main(<!UNUSED_PARAMETER!>args<!>: Array<String>)<!> {}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public suspend fun main(/*0*/ args: kotlin.Array<kotlin.String>): kotlin.Unit
|
||||
public suspend fun main(/*0*/ args: kotlin.Array<kotlin.String>): kotlin.Unit
|
||||
@@ -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");
|
||||
|
||||
Generated
+10
@@ -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");
|
||||
|
||||
+33
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user