diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 6534ab2f8e4..cc3c6d9ebd8 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -166,8 +166,7 @@ import org.jetbrains.kotlin.nj2k.AbstractTextNewJavaToKotlinCopyPasteConversionT import org.jetbrains.kotlin.nj2k.inference.common.AbstractCommonConstraintCollectorTest import org.jetbrains.kotlin.nj2k.inference.mutability.AbstractMutabilityInferenceTest import org.jetbrains.kotlin.nj2k.inference.nullability.AbstractNullabilityInferenceTest -import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg -import org.jetbrains.kotlin.noarg.AbstractBytecodeListingTestForNoArg +import org.jetbrains.kotlin.noarg.* import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeBoxTest import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeBytecodeListingTest import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeIrBoxTest @@ -1664,6 +1663,8 @@ fun main(args: Array) { } testGroup("plugins/noarg/noarg-cli/test", "plugins/noarg/noarg-cli/testData") { + testClass { model("diagnostics", extension = "kt") } + testClass { model("bytecodeListing", extension = "kt") } diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as41 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as41 index 94e55acbead..dbcad1d5ecc 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as41 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as41 @@ -146,8 +146,7 @@ import org.jetbrains.kotlin.nj2k.AbstractTextNewJavaToKotlinCopyPasteConversionT import org.jetbrains.kotlin.nj2k.inference.common.AbstractCommonConstraintCollectorTest import org.jetbrains.kotlin.nj2k.inference.mutability.AbstractMutabilityInferenceTest import org.jetbrains.kotlin.nj2k.inference.nullability.AbstractNullabilityInferenceTest -import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg -import org.jetbrains.kotlin.noarg.AbstractBytecodeListingTestForNoArg +import org.jetbrains.kotlin.noarg.* import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeBoxTest import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeBytecodeListingTest import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeIrBoxTest @@ -1188,6 +1187,8 @@ fun main(args: Array) { } testGroup("plugins/noarg/noarg-cli/test", "plugins/noarg/noarg-cli/testData") { + testClass { model("diagnostics", extension = "kt") } + testClass { model("bytecodeListing", extension = "kt") } diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as42 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as42 index 3414ed8fbf0..5ce7e754ae1 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as42 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as42 @@ -149,8 +149,7 @@ import org.jetbrains.kotlin.nj2k.AbstractTextNewJavaToKotlinCopyPasteConversionT import org.jetbrains.kotlin.nj2k.inference.common.AbstractCommonConstraintCollectorTest import org.jetbrains.kotlin.nj2k.inference.mutability.AbstractMutabilityInferenceTest import org.jetbrains.kotlin.nj2k.inference.nullability.AbstractNullabilityInferenceTest -import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg -import org.jetbrains.kotlin.noarg.AbstractBytecodeListingTestForNoArg +import org.jetbrains.kotlin.noarg.* import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverScriptTest import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverTest @@ -1112,6 +1111,8 @@ fun main(args: Array) { } testGroup("plugins/noarg/noarg-cli/test", "plugins/noarg/noarg-cli/testData") { + testClass { model("diagnostics", extension = "kt") } + testClass { model("bytecodeListing", extension = "kt") } diff --git a/plugins/noarg/noarg-cli/src/NoArgPlugin.kt b/plugins/noarg/noarg-cli/src/NoArgPlugin.kt index 348887eefdc..547bc853155 100644 --- a/plugins/noarg/noarg-cli/src/NoArgPlugin.kt +++ b/plugins/noarg/noarg-cli/src/NoArgPlugin.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension import org.jetbrains.kotlin.compiler.plugin.* import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfigurationKey +import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.useInstance import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -88,24 +89,29 @@ class NoArgComponentRegistrar : ComponentRegistrar { SUPPORTED_PRESETS[preset]?.let { annotations += it } } if (annotations.isNotEmpty()) { - registerNoArgComponents(project, annotations, configuration.getBoolean(INVOKE_INITIALIZERS)) + registerNoArgComponents( + project, annotations, configuration.getBoolean(JVMConfigurationKeys.IR), configuration.getBoolean(INVOKE_INITIALIZERS), + ) } } internal companion object { - fun registerNoArgComponents(project: Project, annotations: List, invokeInitializers: Boolean) { - StorageComponentContainerContributor.registerExtension(project, CliNoArgComponentContainerContributor(annotations)) + fun registerNoArgComponents(project: Project, annotations: List, useIr: Boolean, invokeInitializers: Boolean) { + StorageComponentContainerContributor.registerExtension(project, CliNoArgComponentContainerContributor(annotations, useIr)) ExpressionCodegenExtension.registerExtension(project, CliNoArgExpressionCodegenExtension(annotations, invokeInitializers)) } } } -class CliNoArgComponentContainerContributor(val annotations: List) : StorageComponentContainerContributor { +private class CliNoArgComponentContainerContributor( + private val annotations: List, + private val useIr: Boolean, +) : StorageComponentContainerContributor { override fun registerModuleComponents( container: StorageComponentContainer, platform: TargetPlatform, moduleDescriptor: ModuleDescriptor ) { if (!platform.isJvm()) return - container.useInstance(CliNoArgDeclarationChecker(annotations)) + container.useInstance(CliNoArgDeclarationChecker(annotations, useIr)) } } diff --git a/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/CliNoArgDeclarationChecker.kt b/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/CliNoArgDeclarationChecker.kt index abce7d90a50..8094adf16dc 100644 --- a/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/CliNoArgDeclarationChecker.kt +++ b/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/CliNoArgDeclarationChecker.kt @@ -16,32 +16,48 @@ package org.jetbrains.kotlin.noarg.diagnostic +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.extensions.AnnotationBasedExtension +import org.jetbrains.kotlin.noarg.diagnostic.ErrorsNoArg.* import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny -class CliNoArgDeclarationChecker(private val noArgAnnotationFqNames: List) : AbstractNoArgDeclarationChecker() { - override fun getAnnotationFqNames(modifierListOwner: KtModifierListOwner?) = noArgAnnotationFqNames +internal class CliNoArgDeclarationChecker( + private val noArgAnnotationFqNames: List, + useIr: Boolean, +) : AbstractNoArgDeclarationChecker(useIr) { + override fun getAnnotationFqNames(modifierListOwner: KtModifierListOwner?): List = noArgAnnotationFqNames } -abstract class AbstractNoArgDeclarationChecker : DeclarationChecker, AnnotationBasedExtension { +internal abstract class AbstractNoArgDeclarationChecker(private val useIr: Boolean) : DeclarationChecker, AnnotationBasedExtension { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { - // Handle only classes if (descriptor !is ClassDescriptor || declaration !is KtClass) return if (descriptor.kind != ClassKind.CLASS) return if (!descriptor.hasSpecialAnnotation(declaration)) return + if (descriptor.isInner) { + val diagnostic = if (useIr) NOARG_ON_INNER_CLASS_ERROR else NOARG_ON_INNER_CLASS + context.trace.report(diagnostic.on(declaration.reportTarget)) + } else if (DescriptorUtils.isLocal(descriptor)) { + val diagnostic = if (useIr) NOARG_ON_LOCAL_CLASS_ERROR else NOARG_ON_LOCAL_CLASS + context.trace.report(diagnostic.on(declaration.reportTarget)) + } + val superClass = descriptor.getSuperClassOrAny() if (superClass.constructors.none { it.isNoArgConstructor() } && !superClass.hasSpecialAnnotation(declaration)) { - val reportTarget = declaration.nameIdentifier ?: declaration.getClassOrInterfaceKeyword() ?: declaration - context.trace.report(ErrorsNoArg.NO_NOARG_CONSTRUCTOR_IN_SUPERCLASS.on(reportTarget)) + context.trace.report(NO_NOARG_CONSTRUCTOR_IN_SUPERCLASS.on(declaration.reportTarget)) } } - private fun ConstructorDescriptor.isNoArgConstructor() = valueParameters.all(ValueParameterDescriptor::declaresDefaultValue) + private val KtClass.reportTarget: PsiElement + get() = nameIdentifier ?: getClassOrInterfaceKeyword() ?: this + + private fun ConstructorDescriptor.isNoArgConstructor(): Boolean = + valueParameters.all(ValueParameterDescriptor::declaresDefaultValue) } diff --git a/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/DefaultErrorMessagesNoArg.kt b/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/DefaultErrorMessagesNoArg.kt index baea39626f0..1c90da11d73 100644 --- a/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/DefaultErrorMessagesNoArg.kt +++ b/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/DefaultErrorMessagesNoArg.kt @@ -25,5 +25,15 @@ object DefaultErrorMessagesNoArg : DefaultErrorMessages.Extension { init { MAP.put(ErrorsNoArg.NO_NOARG_CONSTRUCTOR_IN_SUPERCLASS, "Zero-argument constructor was not found in the superclass") + MAP.put( + ErrorsNoArg.NOARG_ON_INNER_CLASS, + "Noarg constructor generation for inner classes is deprecated and will be prohibited soon" + ) + MAP.put(ErrorsNoArg.NOARG_ON_INNER_CLASS_ERROR, "Noarg constructor generation is not possible for inner classes") + MAP.put( + ErrorsNoArg.NOARG_ON_LOCAL_CLASS, + "Noarg constructor generation for local classes is deprecated and will be prohibited soon" + ) + MAP.put(ErrorsNoArg.NOARG_ON_LOCAL_CLASS_ERROR, "Noarg constructor generation is not possible for local classes") } -} \ No newline at end of file +} diff --git a/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/ErrorsNoArg.java b/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/ErrorsNoArg.java index cc0e61d78fc..5f7652c44da 100644 --- a/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/ErrorsNoArg.java +++ b/plugins/noarg/noarg-cli/src/org/jetbrains/kotlin/noarg/diagnostic/ErrorsNoArg.java @@ -20,10 +20,15 @@ import com.intellij.psi.PsiElement; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0; import org.jetbrains.kotlin.diagnostics.Errors; +import static org.jetbrains.kotlin.diagnostics.Severity.ERROR; import static org.jetbrains.kotlin.diagnostics.Severity.WARNING; public interface ErrorsNoArg { DiagnosticFactory0 NO_NOARG_CONSTRUCTOR_IN_SUPERCLASS = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0 NOARG_ON_INNER_CLASS = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0 NOARG_ON_INNER_CLASS_ERROR = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 NOARG_ON_LOCAL_CLASS = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0 NOARG_ON_LOCAL_CLASS_ERROR = DiagnosticFactory0.create(ERROR); @SuppressWarnings("UnusedDeclaration") Object _initializer = new Object() { @@ -31,5 +36,4 @@ public interface ErrorsNoArg { Errors.Initializer.initializeFactoryNamesAndDefaultErrorMessages(ErrorsNoArg.class, DefaultErrorMessagesNoArg.INSTANCE); } }; - } diff --git a/plugins/noarg/noarg-cli/test/org/jetbrains/kotlin/noarg/DiagnosticsTestForNoArgGenerated.java b/plugins/noarg/noarg-cli/test/org/jetbrains/kotlin/noarg/DiagnosticsTestForNoArgGenerated.java new file mode 100644 index 00000000000..ed4e047208b --- /dev/null +++ b/plugins/noarg/noarg-cli/test/org/jetbrains/kotlin/noarg/DiagnosticsTestForNoArgGenerated.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2020 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.noarg; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("plugins/noarg/noarg-cli/testData/diagnostics") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class DiagnosticsTestForNoArgGenerated extends AbstractDiagnosticsTestForNoArg { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInDiagnostics() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/noarg/noarg-cli/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("innerClass.kt") + public void testInnerClass() throws Exception { + runTest("plugins/noarg/noarg-cli/testData/diagnostics/innerClass.kt"); + } + + @TestMetadata("noNoargCtorInSuperclass.kt") + public void testNoNoargCtorInSuperclass() throws Exception { + runTest("plugins/noarg/noarg-cli/testData/diagnostics/noNoargCtorInSuperclass.kt"); + } +} diff --git a/plugins/noarg/noarg-cli/test/org/jetbrains/kotlin/noarg/NoArgTests.kt b/plugins/noarg/noarg-cli/test/org/jetbrains/kotlin/noarg/NoArgTests.kt index 07c557dd2de..577a3e92051 100644 --- a/plugins/noarg/noarg-cli/test/org/jetbrains/kotlin/noarg/NoArgTests.kt +++ b/plugins/noarg/noarg-cli/test/org/jetbrains/kotlin/noarg/NoArgTests.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.noarg +import org.jetbrains.kotlin.checkers.AbstractDiagnosticsTest import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.codegen.AbstractBlackBoxCodegenTest import org.jetbrains.kotlin.codegen.AbstractBytecodeListingTest @@ -16,6 +17,7 @@ abstract class AbstractBlackBoxCodegenTestForNoArg : AbstractBlackBoxCodegenTest NoArgComponentRegistrar.registerNoArgComponents( myEnvironment.project, NOARG_ANNOTATIONS, + backend.isIR, files.any { it.directives.contains("INVOKE_INITIALIZERS") }, ) @@ -25,6 +27,12 @@ abstract class AbstractBlackBoxCodegenTestForNoArg : AbstractBlackBoxCodegenTest abstract class AbstractBytecodeListingTestForNoArg : AbstractBytecodeListingTest() { override fun setupEnvironment(environment: KotlinCoreEnvironment) { - NoArgComponentRegistrar.registerNoArgComponents(environment.project, NOARG_ANNOTATIONS, false) + NoArgComponentRegistrar.registerNoArgComponents(environment.project, NOARG_ANNOTATIONS, backend.isIR, false) + } +} + +abstract class AbstractDiagnosticsTestForNoArg : AbstractDiagnosticsTest() { + override fun setupEnvironment(environment: KotlinCoreEnvironment) { + NoArgComponentRegistrar.registerNoArgComponents(environment.project, NOARG_ANNOTATIONS, backend.isIR, false) } } diff --git a/plugins/noarg/noarg-cli/testData/diagnostics/innerClass.kt b/plugins/noarg/noarg-cli/testData/diagnostics/innerClass.kt new file mode 100644 index 00000000000..f7bbfb9d26c --- /dev/null +++ b/plugins/noarg/noarg-cli/testData/diagnostics/innerClass.kt @@ -0,0 +1,14 @@ +annotation class NoArg + +class Outer { + @NoArg + inner class Inner(val b: Any) +} + +fun local() { + @NoArg + class Local(val l: Any) { + @NoArg + inner class InnerLocal(val x: Any) + } +} diff --git a/plugins/noarg/noarg-cli/testData/diagnostics/innerClass.txt b/plugins/noarg/noarg-cli/testData/diagnostics/innerClass.txt new file mode 100644 index 00000000000..221183e7ad5 --- /dev/null +++ b/plugins/noarg/noarg-cli/testData/diagnostics/innerClass.txt @@ -0,0 +1,25 @@ +package + +public fun local(): kotlin.Unit + +public final annotation class NoArg : kotlin.Annotation { + public constructor NoArg() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Outer { + public constructor Outer() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + @NoArg public final inner class Inner { + public constructor Inner(/*0*/ b: kotlin.Any) + public final val b: kotlin.Any + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/plugins/noarg/noarg-cli/testData/diagnostics/noNoargCtorInSuperclass.kt b/plugins/noarg/noarg-cli/testData/diagnostics/noNoargCtorInSuperclass.kt new file mode 100644 index 00000000000..46a160ea2a5 --- /dev/null +++ b/plugins/noarg/noarg-cli/testData/diagnostics/noNoargCtorInSuperclass.kt @@ -0,0 +1,6 @@ +annotation class NoArg + +open class Base(val s: String) + +@NoArg +class Derived(s: String) : Base(s) diff --git a/plugins/noarg/noarg-cli/testData/diagnostics/noNoargCtorInSuperclass.txt b/plugins/noarg/noarg-cli/testData/diagnostics/noNoargCtorInSuperclass.txt new file mode 100644 index 00000000000..b8bdbdabe7a --- /dev/null +++ b/plugins/noarg/noarg-cli/testData/diagnostics/noNoargCtorInSuperclass.txt @@ -0,0 +1,24 @@ +package + +public open class Base { + public constructor Base(/*0*/ s: kotlin.String) + public final val s: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@NoArg public final class Derived : Base { + public constructor Derived(/*0*/ s: kotlin.String) + public final override /*1*/ /*fake_override*/ val s: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final annotation class NoArg : kotlin.Annotation { + public constructor NoArg() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +}