NoArg: Do not invoke initializers by default. Require "invokeInitializers" option to be set explicitly (KT-18667, KT-18668)
This commit is contained in:
committed by
Yan Zhulanow
parent
a983137978
commit
b99007961f
+7
@@ -165,6 +165,13 @@ class SimpleKotlinGradleIT : BaseGradleIT() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNoArgKt18668() {
|
||||
Project("noArgKt18668", GRADLE_VERSION).build("build") {
|
||||
assertSuccessful()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSamWithReceiverSimple() {
|
||||
Project("samWithReceiverSimple", GRADLE_VERSION).build("build") {
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: "kotlin"
|
||||
apply plugin: "kotlin-noarg"
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
noArg {
|
||||
annotation("test.NoArg")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.kotlin.srcDir 'src'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
annotation class NoArg
|
||||
|
||||
@NoArg
|
||||
class AuthenticationConfiguration(tokenExpiresIn: Long) {
|
||||
var tokenExpiryDate: String
|
||||
|
||||
init {
|
||||
tokenExpiryDate = tokenExpiresIn.toString()
|
||||
}
|
||||
}
|
||||
+2
@@ -20,6 +20,8 @@ open class NoArgExtension {
|
||||
internal val myAnnotations = mutableListOf<String>()
|
||||
internal val myPresets = mutableListOf<String>()
|
||||
|
||||
open var invokeInitializers: Boolean = false
|
||||
|
||||
open fun annotation(fqName: String) {
|
||||
myAnnotations.add(fqName)
|
||||
}
|
||||
|
||||
+5
@@ -71,6 +71,7 @@ class NoArgKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
|
||||
private val ANNOTATION_ARG_NAME = "annotation"
|
||||
private val PRESET_ARG_NAME = "preset"
|
||||
private val INVOKE_INITIALIZERS_ARG_NAME = "invokeInitializers"
|
||||
}
|
||||
|
||||
override fun isApplicable(project: Project, task: AbstractCompile) = NoArgGradleSubplugin.isEnabled(project)
|
||||
@@ -96,6 +97,10 @@ class NoArgKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
options += SubpluginOption(PRESET_ARG_NAME, preset)
|
||||
}
|
||||
|
||||
if (noArgExtension.invokeInitializers) {
|
||||
options += SubpluginOption(INVOKE_INITIALIZERS_ARG_NAME, "true")
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.noarg
|
||||
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.context.ConstructorContext
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -32,9 +31,8 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy.CodegenBased
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class NoArgExpressionCodegenExtension : ExpressionCodegenExtension {
|
||||
class NoArgExpressionCodegenExtension(val invokeInitializers: Boolean = false) : ExpressionCodegenExtension {
|
||||
override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) = with(codegen) {
|
||||
if (shouldGenerateNoArgConstructor()) {
|
||||
generateNoArgConstructor()
|
||||
@@ -50,7 +48,11 @@ class NoArgExpressionCodegenExtension : ExpressionCodegenExtension {
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
codegen.v.load(0, AsmTypes.OBJECT_TYPE)
|
||||
codegen.v.visitMethodInsn(Opcodes.INVOKESPECIAL, superClassInternalName, "<init>", "()V", false)
|
||||
generateInitializers(codegen)
|
||||
|
||||
if (invokeInitializers) {
|
||||
generateInitializers(codegen)
|
||||
}
|
||||
|
||||
codegen.v.visitInsn(Opcodes.RETURN)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.noarg
|
||||
import com.intellij.mock.MockProject
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import org.jetbrains.kotlin.noarg.diagnostic.DefaultErrorMessagesNoArg
|
||||
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||
import org.jetbrains.kotlin.compiler.plugin.CliOption
|
||||
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
|
||||
@@ -33,6 +32,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
||||
import org.jetbrains.kotlin.noarg.NoArgCommandLineProcessor.Companion.SUPPORTED_PRESETS
|
||||
import org.jetbrains.kotlin.noarg.NoArgConfigurationKeys.ANNOTATION
|
||||
import org.jetbrains.kotlin.noarg.NoArgConfigurationKeys.INVOKE_INITIALIZERS
|
||||
import org.jetbrains.kotlin.noarg.NoArgConfigurationKeys.PRESET
|
||||
import org.jetbrains.kotlin.noarg.diagnostic.CliNoArgDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
@@ -43,6 +43,9 @@ object NoArgConfigurationKeys {
|
||||
CompilerConfigurationKey.create("annotation qualified name")
|
||||
|
||||
val PRESET: CompilerConfigurationKey<List<String>> = CompilerConfigurationKey.create("annotation preset")
|
||||
|
||||
val INVOKE_INITIALIZERS: CompilerConfigurationKey<Boolean> = CompilerConfigurationKey.create(
|
||||
"invoke instance initializers in a no-arg constructor")
|
||||
}
|
||||
|
||||
class NoArgCommandLineProcessor : CommandLineProcessor {
|
||||
@@ -55,15 +58,20 @@ class NoArgCommandLineProcessor : CommandLineProcessor {
|
||||
val PRESET_OPTION = CliOption("preset", "<name>", "Preset name (${SUPPORTED_PRESETS.keys.joinToString()})",
|
||||
required = false, allowMultipleOccurrences = true)
|
||||
|
||||
val INVOKE_INITIALIZERS_OPTION = CliOption("invokeInitializers", "true/false",
|
||||
"Invoke instance initializers in a no-arg constructor",
|
||||
required = false, allowMultipleOccurrences = false)
|
||||
|
||||
val PLUGIN_ID = "org.jetbrains.kotlin.noarg"
|
||||
}
|
||||
|
||||
override val pluginId = PLUGIN_ID
|
||||
override val pluginOptions = listOf(ANNOTATION_OPTION, PRESET_OPTION)
|
||||
override val pluginOptions = listOf(ANNOTATION_OPTION, PRESET_OPTION, INVOKE_INITIALIZERS_OPTION)
|
||||
|
||||
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) = when (option) {
|
||||
ANNOTATION_OPTION -> configuration.appendList(ANNOTATION, value)
|
||||
PRESET_OPTION -> configuration.appendList(PRESET, value)
|
||||
INVOKE_INITIALIZERS_OPTION -> configuration.put(INVOKE_INITIALIZERS, value == "true")
|
||||
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
|
||||
}
|
||||
}
|
||||
@@ -79,7 +87,8 @@ class NoArgComponentRegistrar : ComponentRegistrar {
|
||||
Extensions.getRootArea().getExtensionPoint(DefaultErrorMessages.Extension.EP_NAME).registerExtension(DefaultErrorMessagesNoArg())
|
||||
StorageComponentContainerContributor.registerExtension(project, CliNoArgComponentContainerContributor(annotations))
|
||||
|
||||
ExpressionCodegenExtension.registerExtension(project, NoArgExpressionCodegenExtension())
|
||||
val invokeInitializers = configuration[INVOKE_INITIALIZERS] ?: false
|
||||
ExpressionCodegenExtension.registerExtension(project, NoArgExpressionCodegenExtension(invokeInitializers))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// WITH_RUNTIME
|
||||
// INVOKE_INITIALIZERS
|
||||
|
||||
annotation class NoArg
|
||||
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
annotation class NoArg
|
||||
|
||||
class Simple(val a: String)
|
||||
|
||||
@NoArg
|
||||
class Test(val a: String) {
|
||||
val x = 5
|
||||
val y: Simple? = Simple("Hello, world!")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
try {
|
||||
val test = Test::class.java.newInstance()
|
||||
|
||||
if (test.x != 0) {
|
||||
return "Bad 5"
|
||||
}
|
||||
|
||||
if (test.y != null) {
|
||||
return "Bad Hello, world!"
|
||||
}
|
||||
|
||||
return "OK"
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
return "Fail"
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
annotation class NoArg
|
||||
|
||||
@NoArg
|
||||
class Foo(val s1: String) {
|
||||
val s2: String = ""
|
||||
val l: List<String> = listOf()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val instance = Foo::class.java.newInstance()
|
||||
return "OK"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
annotation class NoArg
|
||||
|
||||
@NoArg
|
||||
class AuthenticationConfiguration(tokenExpiresIn: Long) {
|
||||
var tokenExpiryDate: String?
|
||||
|
||||
init {
|
||||
tokenExpiryDate = tokenExpiresIn.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val instance = AuthenticationConfiguration::class.java.newInstance()
|
||||
|
||||
if (instance.tokenExpiryDate != null) {
|
||||
return "Initializer invoked"
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+2
-1
@@ -30,7 +30,8 @@ abstract class AbstractBlackBoxCodegenTestForNoArg : AbstractBlackBoxCodegenTest
|
||||
|
||||
val project = myEnvironment.project
|
||||
registerExtension(project, CliNoArgComponentContainerContributor(NOARG_ANNOTATIONS))
|
||||
ExpressionCodegenExtension.registerExtension(project, NoArgExpressionCodegenExtension())
|
||||
val invokeInitializers = files.any { "// INVOKE_INITIALIZERS" in it.content }
|
||||
ExpressionCodegenExtension.registerExtension(project, NoArgExpressionCodegenExtension(invokeInitializers))
|
||||
|
||||
super.loadMultiFiles(files)
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,6 +34,6 @@ abstract class AbstractBytecodeListingTestForNoArg : AbstractBytecodeListingTest
|
||||
|
||||
val project = environment.project
|
||||
StorageComponentContainerContributor.registerExtension(project, CliNoArgComponentContainerContributor(NOARG_ANNOTATIONS))
|
||||
ExpressionCodegenExtension.registerExtension(project, NoArgExpressionCodegenExtension())
|
||||
ExpressionCodegenExtension.registerExtension(project, NoArgExpressionCodegenExtension(false))
|
||||
}
|
||||
}
|
||||
+18
@@ -42,6 +42,24 @@ public class BlackBoxCodegenTestForNoArgGenerated extends AbstractBlackBoxCodege
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("initializersWithoutInvokeInitializers.kt")
|
||||
public void testInitializersWithoutInvokeInitializers() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/noarg/noarg-cli/testData/box/initializersWithoutInvokeInitializers.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt18667.kt")
|
||||
public void testKt18667() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/noarg/noarg-cli/testData/box/kt18667.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt18668.kt")
|
||||
public void testKt18668() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/noarg/noarg-cli/testData/box/kt18668.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/noarg/noarg-cli/testData/box/simple.kt");
|
||||
|
||||
Reference in New Issue
Block a user