diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt index 0ee2ef31138..0d224f6fca8 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt @@ -43,4 +43,5 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin { object SYNTHETIC_INLINE_CLASS_MEMBER : IrDeclarationOriginImpl("SYNTHETIC_INLINE_CLASS_MEMBER", isSynthetic = true) object INLINE_CLASS_GENERATED_IMPL_METHOD : IrDeclarationOriginImpl("INLINE_CLASS_GENERATED_IMPL_METHOD") object GENERATED_ASSERTION_ENABLED_FIELD : IrDeclarationOriginImpl("GENERATED_ASSERTION_ENABLED_FIELD", isSynthetic = true) + object GENERATED_MAIN_FOR_PARAMETERLESS_MAIN_METHOD : IrDeclarationOriginImpl("GENERATED_MAIN_FOR_PARAMETERLESS_MAIN_METHOD", isSynthetic = true) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 1a7dee23032..c9af2cb9a4b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -172,8 +172,15 @@ private val syntheticAccessorPhase = makeIrFilePhase( prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase, interfacePhase) ) +private val mainMethodGenerationPhase = makeIrFilePhase( + ::MainMethodGenerationLowering, + name = "MainMethodGeneration", + description = "Identify parameterless main methods and generate bridge main-methods" +) + @Suppress("Reformat") private val jvmFilePhases = + mainMethodGenerationPhase then typeAliasAnnotationMethodsPhase then stripTypeAliasDeclarationsPhase then provisionalFunctionExpressionPhase then diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt index 1122c2e4f61..652a3183c98 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.lower.allOverridden import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.ir.getJvmNameFromAnnotation import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault import org.jetbrains.kotlin.backend.jvm.ir.propertyIfAccessor import org.jetbrains.kotlin.builtins.KotlinBuiltIns @@ -122,11 +123,6 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { getJvmModuleNameForDeserializedDescriptor(function.descriptor) else null) ?: context.state.moduleName - private fun IrDeclaration.getJvmNameFromAnnotation(): String? { - val const = getAnnotation(DescriptorUtils.JVM_NAME)?.getValueArgument(0) as? IrConst<*> - return const?.value as? String - } - private fun IrFunction.isPublishedApi(): Boolean = propertyIfAccessor.annotations.hasAnnotation(KotlinBuiltIns.FQ_NAMES.publishedApi) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt index e9d17b03d38..0f64b1239c5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.builders.Scope import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin +import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol @@ -25,6 +26,7 @@ import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME /** @@ -82,6 +84,12 @@ val IrType.erasedUpperBound: IrClass else -> throw IllegalStateException() } + +fun IrDeclaration.getJvmNameFromAnnotation(): String? { + val const = getAnnotation(DescriptorUtils.JVM_NAME)?.getValueArgument(0) as? IrConst<*> + return const?.value as? String +} + val IrFunction.propertyIfAccessor: IrDeclaration get() = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: this diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt new file mode 100644 index 00000000000..327802083aa --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.jvm.lower + +import org.jetbrains.kotlin.backend.common.ClassLoweringPass +import org.jetbrains.kotlin.backend.common.ir.allParameters +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.ir.getJvmNameFromAnnotation +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.ir.builders.declarations.addFunction +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irReturn +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.functions +import org.jetbrains.kotlin.ir.util.getAnnotation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.types.Variance + +internal class MainMethodGenerationLowering(val context: JvmBackendContext) : ClassLoweringPass { + + override fun lower(irClass: IrClass) { + if (!context.configuration.languageVersionSettings.supportsFeature(LanguageFeature.ExtendedMainConvention)) return + if (irClass.origin != IrDeclarationOrigin.FILE_CLASS) return + + val parameterlessMain = irClass.functions.find { it.isParameterlessMainMethod() } ?: return + + if (irClass.functions.any { it.isMainMethod() }) return + + generateMainMethod(irClass, parameterlessMain) + } + + private fun generateMainMethod(irClass: IrClass, parameterlessMain: IrSimpleFunction) { + irClass.addFunction { + name = Name.identifier("main") + visibility = Visibilities.PUBLIC + returnType = context.irBuiltIns.unitType + modality = Modality.FINAL + origin = JvmLoweredDeclarationOrigin.GENERATED_MAIN_FOR_PARAMETERLESS_MAIN_METHOD + }.apply { + addValueParameter { + name = Name.identifier("args") + type = context.irBuiltIns.arrayClass.typeWith(context.irBuiltIns.stringType) + } + body = context.createIrBuilder(this.symbol).irBlockBody { + +irReturn(this.irCall(parameterlessMain)) + } + } + } + + private fun IrSimpleFunction.isParameterlessMainMethod(): Boolean = + typeParameters.isEmpty() && valueParameters.isEmpty() && returnType.isUnit() && name.asString() == "main" + + + private fun IrSimpleFunction.isMainMethod(): Boolean { + if (getJvmNameFromAnnotation() ?: name.asString() != "main") return false + if (!returnType.isUnit()) return false + + val parameter = allParameters.singleOrNull() ?: return false + if (!parameter.type.isArray() && !parameter.type.isNullableArray()) return false + + val argType = (parameter.type as IrSimpleType).arguments.first() + return when (argType) { + is IrTypeProjection -> { + (argType.variance != Variance.IN_VARIANCE) && argType.type.isStringClassType() + } + else -> false + } + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt new file mode 100644 index 00000000000..3b5d9bffb4e --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt @@ -0,0 +1,8 @@ +fun main() { + +} + +@JvmName("main") +fun foo(args: Array) { + +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt new file mode 100644 index 00000000000..04e40fe1209 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt @@ -0,0 +1,7 @@ +fun main() { + +} + +fun main(args: Array) { + +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMainExtension.kt b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMainExtension.kt new file mode 100644 index 00000000000..d5123b42bdc --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMainExtension.kt @@ -0,0 +1,7 @@ +fun main() { + +} + +fun Array.main() { + +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt new file mode 100644 index 00000000000..fdf3af46276 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt @@ -0,0 +1,7 @@ +fun main() { + +} + +fun main(args: Array?) { + +} \ No newline at end of file diff --git a/compiler/testData/writeSignature/parameterlessMain/arrayWithContravariantStringIsNotMainMethod.kt b/compiler/testData/writeSignature/parameterlessMain/arrayWithContravariantStringIsNotMainMethod.kt new file mode 100644 index 00000000000..ee02777fc74 --- /dev/null +++ b/compiler/testData/writeSignature/parameterlessMain/arrayWithContravariantStringIsNotMainMethod.kt @@ -0,0 +1,11 @@ +fun main() { + +} + +fun main(args: Array) { + +} + +// method: ArrayWithContravariantStringIsNotMainMethodKt::main +// jvm signature: ([Ljava/lang/String;)V +// generic signature: null diff --git a/compiler/testData/writeSignature/parameterlessMain/impostorMains.kt b/compiler/testData/writeSignature/parameterlessMain/impostorMains.kt new file mode 100644 index 00000000000..cd7e6207806 --- /dev/null +++ b/compiler/testData/writeSignature/parameterlessMain/impostorMains.kt @@ -0,0 +1,24 @@ +fun main() { + +} + +fun main(args: Array) { + +} + +fun main(args: Array) { + +} + +fun main(args: Array): Unit? { + + return Unit +} + +fun Any.main(args: Array) { + +} + +// method: ImpostorMainsKt::main +// jvm signature: ([Ljava/lang/String;)V +// generic signature: null diff --git a/compiler/testData/writeSignature/parameterlessMain/main.kt b/compiler/testData/writeSignature/parameterlessMain/main.kt new file mode 100644 index 00000000000..1362df30029 --- /dev/null +++ b/compiler/testData/writeSignature/parameterlessMain/main.kt @@ -0,0 +1,7 @@ +fun main(args: Array) { + +} + +// method: MainKt::main +// jvm signature: ([Ljava/lang/String;)V +// generic signature: null diff --git a/compiler/testData/writeSignature/parameterlessMain/notJvmMainName.kt b/compiler/testData/writeSignature/parameterlessMain/notJvmMainName.kt new file mode 100644 index 00000000000..a0160d60347 --- /dev/null +++ b/compiler/testData/writeSignature/parameterlessMain/notJvmMainName.kt @@ -0,0 +1,21 @@ +// WITH_RUNTIME +fun main() { + +} + +@JvmName("notMain") +fun main(args: Array) { + +} + +// method: NotJvmMainNameKt::main +// jvm signature: ()V +// generic signature: null + +// method: NotJvmMainNameKt::main +// jvm signature: ([Ljava/lang/String;)V +// generic signature: null + +// method: NotJvmMainNameKt::notMain +// jvm signature: ([Ljava/lang/String;)V +// generic signature: null diff --git a/compiler/testData/writeSignature/parameterlessMain/simple.kt b/compiler/testData/writeSignature/parameterlessMain/simple.kt new file mode 100644 index 00000000000..224a3ded0e0 --- /dev/null +++ b/compiler/testData/writeSignature/parameterlessMain/simple.kt @@ -0,0 +1,11 @@ +fun main() { + +} + +// method: SimpleKt::main +// jvm signature: ()V +// generic signature: null + +// method: SimpleKt::main +// jvm signature: ([Ljava/lang/String;)V +// generic signature: null diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 99a4c84d9b0..82d6c40927a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -3438,6 +3438,39 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { } } + @TestMetadata("compiler/testData/codegen/bytecodeText/parameterlessMain") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ParameterlessMain extends AbstractBytecodeTextTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInParameterlessMain() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/parameterlessMain"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("dontGenerateOnJvmNameMain.kt") + public void testDontGenerateOnJvmNameMain() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt"); + } + + @TestMetadata("dontGenerateOnMain.kt") + public void testDontGenerateOnMain() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt"); + } + + @TestMetadata("dontGenerateOnMainExtension.kt") + public void testDontGenerateOnMainExtension() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMainExtension.kt"); + } + + @TestMetadata("dontGenerateOnNullableArray.kt") + public void testDontGenerateOnNullableArray() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt"); + } + } + @TestMetadata("compiler/testData/codegen/bytecodeText/properties") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index 2c335061983..1bdb1744727 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -3408,6 +3408,39 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { } } + @TestMetadata("compiler/testData/codegen/bytecodeText/parameterlessMain") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ParameterlessMain extends AbstractIrBytecodeTextTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInParameterlessMain() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/parameterlessMain"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); + } + + @TestMetadata("dontGenerateOnJvmNameMain.kt") + public void testDontGenerateOnJvmNameMain() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnJvmNameMain.kt"); + } + + @TestMetadata("dontGenerateOnMain.kt") + public void testDontGenerateOnMain() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMain.kt"); + } + + @TestMetadata("dontGenerateOnMainExtension.kt") + public void testDontGenerateOnMainExtension() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnMainExtension.kt"); + } + + @TestMetadata("dontGenerateOnNullableArray.kt") + public void testDontGenerateOnNullableArray() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/parameterlessMain/dontGenerateOnNullableArray.kt"); + } + } + @TestMetadata("compiler/testData/codegen/bytecodeText/properties") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrWriteSignatureTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrWriteSignatureTestGenerated.java index 51972ca49f0..ce2129ac17c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrWriteSignatureTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrWriteSignatureTestGenerated.java @@ -613,4 +613,42 @@ public class IrWriteSignatureTestGenerated extends AbstractIrWriteSignatureTest runTest("compiler/testData/writeSignature/nothing/nullableNothing.kt"); } } + + @TestMetadata("compiler/testData/writeSignature/parameterlessMain") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ParameterlessMain extends AbstractIrWriteSignatureTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInParameterlessMain() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeSignature/parameterlessMain"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); + } + + @TestMetadata("arrayWithContravariantStringIsNotMainMethod.kt") + public void testArrayWithContravariantStringIsNotMainMethod() throws Exception { + runTest("compiler/testData/writeSignature/parameterlessMain/arrayWithContravariantStringIsNotMainMethod.kt"); + } + + @TestMetadata("impostorMains.kt") + public void testImpostorMains() throws Exception { + runTest("compiler/testData/writeSignature/parameterlessMain/impostorMains.kt"); + } + + @TestMetadata("main.kt") + public void testMain() throws Exception { + runTest("compiler/testData/writeSignature/parameterlessMain/main.kt"); + } + + @TestMetadata("notJvmMainName.kt") + public void testNotJvmMainName() throws Exception { + runTest("compiler/testData/writeSignature/parameterlessMain/notJvmMainName.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/writeSignature/parameterlessMain/simple.kt"); + } + } } diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/WriteSignatureTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/WriteSignatureTestGenerated.java index ffa83efdf97..16732aaabc4 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/WriteSignatureTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/WriteSignatureTestGenerated.java @@ -613,4 +613,42 @@ public class WriteSignatureTestGenerated extends AbstractWriteSignatureTest { runTest("compiler/testData/writeSignature/nothing/nullableNothing.kt"); } } + + @TestMetadata("compiler/testData/writeSignature/parameterlessMain") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ParameterlessMain extends AbstractWriteSignatureTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInParameterlessMain() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeSignature/parameterlessMain"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("arrayWithContravariantStringIsNotMainMethod.kt") + public void testArrayWithContravariantStringIsNotMainMethod() throws Exception { + runTest("compiler/testData/writeSignature/parameterlessMain/arrayWithContravariantStringIsNotMainMethod.kt"); + } + + @TestMetadata("impostorMains.kt") + public void testImpostorMains() throws Exception { + runTest("compiler/testData/writeSignature/parameterlessMain/impostorMains.kt"); + } + + @TestMetadata("main.kt") + public void testMain() throws Exception { + runTest("compiler/testData/writeSignature/parameterlessMain/main.kt"); + } + + @TestMetadata("notJvmMainName.kt") + public void testNotJvmMainName() throws Exception { + runTest("compiler/testData/writeSignature/parameterlessMain/notJvmMainName.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/writeSignature/parameterlessMain/simple.kt"); + } + } }