diff --git a/plugins/lombok/lombok-compiler-plugin/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor b/plugins/lombok/lombok-compiler-plugin/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor new file mode 100644 index 00000000000..eb0587b3bcb --- /dev/null +++ b/plugins/lombok/lombok-compiler-plugin/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor @@ -0,0 +1 @@ +org.jetbrains.kotlin.lombok.LombokCommandLineProcessor diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokComponentRegistrar.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokComponentRegistrar.kt deleted file mode 100644 index be8920961cd..00000000000 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokComponentRegistrar.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2010-2021 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.lombok - -import com.intellij.mock.MockProject -import com.intellij.openapi.project.Project -import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.resolve.jvm.extensions.SyntheticJavaResolveExtension - -class LombokComponentRegistrar : ComponentRegistrar { - - companion object { - fun registerComponents(project: Project) { - SyntheticJavaResolveExtension.registerExtension(project, LombokResolveExtension()) - } - } - - override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { - registerComponents(project) - } -} diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokPlugin.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokPlugin.kt new file mode 100644 index 00000000000..5051049f944 --- /dev/null +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokPlugin.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2021 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.lombok + +import com.intellij.mock.MockProject +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.compiler.plugin.AbstractCliOption +import org.jetbrains.kotlin.compiler.plugin.CliOption +import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor +import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.CompilerConfigurationKey +import org.jetbrains.kotlin.lombok.LombokConfigurationKeys.CONFIG_FILE +import org.jetbrains.kotlin.resolve.jvm.extensions.SyntheticJavaResolveExtension +import java.io.File +import java.lang.IllegalArgumentException + +class LombokComponentRegistrar : ComponentRegistrar { + + companion object { + fun registerComponents(project: Project, compilerConfiguration: CompilerConfiguration) { + val config = LombokPluginConfig(compilerConfiguration[CONFIG_FILE]) + SyntheticJavaResolveExtension.registerExtension(project, LombokResolveExtension(config)) + } + } + + override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { + registerComponents(project, configuration) + } +} + +data class LombokPluginConfig(val configFile: File?) + +object LombokConfigurationKeys { + val CONFIG_FILE: CompilerConfigurationKey = CompilerConfigurationKey.create("lombok config file location") +} + +class LombokCommandLineProcessor : CommandLineProcessor { + + companion object { + const val PLUGIN_ID = "org.jetbrains.kotlin.lombok" + + val CONFIG_FILE_OPTION = CliOption( + optionName = "config", + valueDescription = "", + description = "Lombok configuration file location", + required = false + ) + } + + override val pluginId: String = PLUGIN_ID + override val pluginOptions: Collection = listOf(CONFIG_FILE_OPTION) + + override fun processOption(option: AbstractCliOption, value: String, configuration: CompilerConfiguration) { + when (option) { + CONFIG_FILE_OPTION -> configuration.put(CONFIG_FILE, File(value)) + else -> throw IllegalArgumentException("Unknown option $option") + } + } +} diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokResolveExtension.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokResolveExtension.kt index 157956f8354..ea83023f234 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokResolveExtension.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokResolveExtension.kt @@ -5,10 +5,13 @@ package org.jetbrains.kotlin.lombok +import org.jetbrains.kotlin.lombok.config.LombokConfig import org.jetbrains.kotlin.resolve.jvm.SyntheticJavaPartsProvider import org.jetbrains.kotlin.resolve.jvm.extensions.SyntheticJavaResolveExtension -class LombokResolveExtension : SyntheticJavaResolveExtension { +class LombokResolveExtension(pluginConfig: LombokPluginConfig) : SyntheticJavaResolveExtension { - override fun getProvider(): SyntheticJavaPartsProvider = LombokSyntheticJavaPartsProvider() + private val config = pluginConfig.configFile?.let(LombokConfig::parse) ?: LombokConfig.Empty + + override fun getProvider(): SyntheticJavaPartsProvider = LombokSyntheticJavaPartsProvider(config) } diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokSyntheticJavaPartsProvider.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokSyntheticJavaPartsProvider.kt index e4947eb5429..149734ddf3f 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokSyntheticJavaPartsProvider.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/LombokSyntheticJavaPartsProvider.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl +import org.jetbrains.kotlin.lombok.config.LombokConfig import org.jetbrains.kotlin.lombok.processor.GetterProcessor import org.jetbrains.kotlin.lombok.processor.Parts import org.jetbrains.kotlin.lombok.processor.Processor @@ -16,13 +17,13 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.jvm.SyntheticJavaPartsProvider import java.util.* -class LombokSyntheticJavaPartsProvider : SyntheticJavaPartsProvider { +class LombokSyntheticJavaPartsProvider(private val config: LombokConfig) : SyntheticJavaPartsProvider { private val processors = initProcessors() private fun initProcessors(): List = listOf( - GetterProcessor() + GetterProcessor(config) ) private val partsCache: MutableMap = WeakHashMap() diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/LombokConfig.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/LombokConfig.kt index 2fd9740dbe1..b16afd04071 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/LombokConfig.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/LombokConfig.kt @@ -5,5 +5,32 @@ package org.jetbrains.kotlin.lombok.config -class LombokConfig { +import java.io.File + +class LombokConfig(private val config: Map) { + + fun getString(key: String): String? = config[key] + + fun getBoolean(key: String): Boolean? = getString(key)?.toBoolean() + + fun getBooleanOrDefault(key: String, default: Boolean = false): Boolean = getBoolean(key) ?: default + + companion object { + + val Empty = LombokConfig(emptyMap()) + + fun parse(path: File): LombokConfig { + + val config = mutableMapOf() + + path.forEachLine { line -> + val parts = line.split("=", limit = 2) + if (parts.size == 2) { + config[parts[0].trim()] = parts[1].trim() + } + } + return LombokConfig(config) + } + } + } diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/GetterProcessor.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/GetterProcessor.kt index ca3ee1cd743..168da1ba190 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/GetterProcessor.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/GetterProcessor.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.lombok.config.Accessors import org.jetbrains.kotlin.lombok.config.Getter +import org.jetbrains.kotlin.lombok.config.LombokConfig import org.jetbrains.kotlin.lombok.utils.createFunction import org.jetbrains.kotlin.lombok.utils.toPreparedBase import org.jetbrains.kotlin.name.Name @@ -19,7 +20,9 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.model.SimpleTypeMarker import org.jetbrains.kotlin.types.typeUtil.isBoolean -class GetterProcessor : Processor { +class GetterProcessor(private val config: LombokConfig) : Processor { + + private val noIsPrefix by lazy { config.getBooleanOrDefault("lombok.getter.noIsPrefix") } override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts { val clAccessors = Accessors.getOrNull(classDescriptor) @@ -46,7 +49,7 @@ class GetterProcessor : Processor { if (accessors.fluent) { field.name.identifier } else { - val prefix = if (field.type.isPrimitiveBoolean()) "is" else "get" + val prefix = if (field.type.isPrimitiveBoolean() && !noIsPrefix) "is" else "get" prefix + toPreparedBase(field.name.identifier) } return createFunction( diff --git a/plugins/lombok/lombok-compiler-plugin/testData/compile/configSimple.kt b/plugins/lombok/lombok-compiler-plugin/testData/compile/configSimple.kt new file mode 100644 index 00000000000..b6f3f748271 --- /dev/null +++ b/plugins/lombok/lombok-compiler-plugin/testData/compile/configSimple.kt @@ -0,0 +1,28 @@ +//FILE: GetterTest.java + +import lombok.AccessLevel; +import lombok.Getter; + +public class GetterTest { + @Getter private boolean primitiveBoolean; + + void test() { + getPrimitiveBoolean(); + } + +} + + +//FILE: test.kt + +object Test { + fun usage() { + val obj = GetterTest() + + obj.primitiveBoolean + obj.getPrimitiveBoolean() + } +} + +//FILE: lombok.config +lombok.getter.noIsPrefix=true diff --git a/plugins/lombok/lombok-compiler-plugin/testData/compile/gettersFluent.kt b/plugins/lombok/lombok-compiler-plugin/testData/compile/gettersFluent.kt index 0547d53e107..183d62423e1 100644 --- a/plugins/lombok/lombok-compiler-plugin/testData/compile/gettersFluent.kt +++ b/plugins/lombok/lombok-compiler-plugin/testData/compile/gettersFluent.kt @@ -8,6 +8,8 @@ import lombok.experimental.Accessors; public class FluentTest { @Getter private int age = 10; + @Getter @Accessors private int overrideAnnotation = 10; + @Getter(AccessLevel.PROTECTED) private String name; @Getter private boolean primitiveBoolean; @@ -17,6 +19,7 @@ public class FluentTest { void test() { age(); primitiveBoolean(); + getOverrideAnnotation(); } } @@ -32,6 +35,9 @@ object Test { obj.primitiveBoolean() obj.boxedBoolean() + + obj.overrideAnnotation + obj.getOverrideAnnotation() } class OverridenGetterTest : FluentTest() { diff --git a/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/AbstractLombokCompileTest.kt b/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/AbstractLombokCompileTest.kt index 085a91b2794..eda43493799 100644 --- a/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/AbstractLombokCompileTest.kt +++ b/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/AbstractLombokCompileTest.kt @@ -8,7 +8,9 @@ package org.jetbrains.kotlin.lombok import lombok.Getter import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot +import org.jetbrains.kotlin.cli.jvm.config.javaSourceRoots import org.jetbrains.kotlin.codegen.CodegenTestCase +import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.utils.PathUtil import java.io.File @@ -19,7 +21,7 @@ abstract class AbstractLombokCompileTest : CodegenTestCase() { } override fun setupEnvironment(environment: KotlinCoreEnvironment) { - LombokComponentRegistrar.registerComponents(environment.project) + LombokComponentRegistrar.registerComponents(environment.project, environment.configuration) environment.updateClasspath(listOf(JvmClasspathRoot(getLombokJar()))) } @@ -27,5 +29,19 @@ abstract class AbstractLombokCompileTest : CodegenTestCase() { javaClasspath += getLombokJar().absolutePath } + override fun configureTestSpecific(configuration: CompilerConfiguration, testFiles: List) { + writeLombokConfig(configuration.javaSourceRoots.first(), testFiles)?.let { file -> + configuration.put(LombokConfigurationKeys.CONFIG_FILE, file) + } + } + + private fun writeLombokConfig(directory: String, testFiles: List): File? = + testFiles.singleOrNull { it.name == "lombok.config" }?.let { + val file = File(directory, it.name) + file.writeText(it.content) + file + } + + private fun getLombokJar(): File = PathUtil.getResourcePathForClass(Getter::class.java) } diff --git a/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/LombokCompileTestGenerated.java b/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/LombokCompileTestGenerated.java index 32fa60f56dd..0d83480107b 100644 --- a/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/LombokCompileTestGenerated.java +++ b/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/LombokCompileTestGenerated.java @@ -15,7 +15,9 @@ 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 */ +/** + * This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY + */ @SuppressWarnings("all") @TestMetadata("plugins/lombok/lombok-compiler-plugin/testData/compile") @TestDataPath("$PROJECT_ROOT") @@ -29,6 +31,11 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/lombok/lombok-compiler-plugin/testData/compile"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @TestMetadata("configSimple.kt") + public void testConfigSimple() throws Exception { + runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/configSimple.kt"); + } + @TestMetadata("gettersClassLevel.kt") public void testGettersClassLevel() throws Exception { runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/gettersClassLevel.kt");