[lombok] Basic config support

This commit is contained in:
Andrey Zinovyev
2021-03-25 16:08:23 +03:00
committed by TeamCityServer
parent 5ceefa3e3b
commit 70e3877efc
11 changed files with 164 additions and 34 deletions
@@ -0,0 +1 @@
org.jetbrains.kotlin.lombok.LombokCommandLineProcessor
@@ -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)
}
}
@@ -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<File> = 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 = "<path>",
description = "Lombok configuration file location",
required = false
)
}
override val pluginId: String = PLUGIN_ID
override val pluginOptions: Collection<AbstractCliOption> = 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")
}
}
}
@@ -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)
}
@@ -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<Processor> =
listOf(
GetterProcessor()
GetterProcessor(config)
)
private val partsCache: MutableMap<ClassDescriptor, Parts> = WeakHashMap()
@@ -5,5 +5,32 @@
package org.jetbrains.kotlin.lombok.config
class LombokConfig {
import java.io.File
class LombokConfig(private val config: Map<String, String>) {
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<String, String>()
path.forEachLine { line ->
val parts = line.split("=", limit = 2)
if (parts.size == 2) {
config[parts[0].trim()] = parts[1].trim()
}
}
return LombokConfig(config)
}
}
}
@@ -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(
@@ -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
@@ -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() {
@@ -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<TestFile>) {
writeLombokConfig(configuration.javaSourceRoots.first(), testFiles)?.let { file ->
configuration.put(LombokConfigurationKeys.CONFIG_FILE, file)
}
}
private fun writeLombokConfig(directory: String, testFiles: List<TestFile>): 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)
}
@@ -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");