From be4a518a2550282809ddb8dd052ea1d1ecf36f5d Mon Sep 17 00:00:00 2001 From: Andrey Zinovyev Date: Wed, 31 Mar 2021 14:26:02 +0300 Subject: [PATCH] [lombok] Support for lombok.accessors.prefix config --- .../lombok/lombok-compiler-plugin/README.md | 6 +- .../kotlin/lombok/config/LombokConfig.kt | 72 +++++++++++++++--- .../kotlin/lombok/config/annotationConfig.kt | 6 +- .../testData/compile/accessorsStripPrefix.kt | 6 +- .../compile/accessorsStripPrefixConfig.kt | 74 +++++++++++++++++++ .../lombok/LombokCompileTestGenerated.java | 5 ++ 6 files changed, 151 insertions(+), 18 deletions(-) create mode 100644 plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefixConfig.kt diff --git a/plugins/lombok/lombok-compiler-plugin/README.md b/plugins/lombok/lombok-compiler-plugin/README.md index fdd84e2e55e..6fb3a6313bd 100644 --- a/plugins/lombok/lombok-compiler-plugin/README.md +++ b/plugins/lombok/lombok-compiler-plugin/README.md @@ -17,11 +17,11 @@ Features support: - [x] lombok.getter.noIsPrefix - [x] lombok.accessors.fluent - [x] lombok.accessors.chain - - [ ] lombok.accessors.prefix - - [ ] lombok.noArgsConstructor.extraPrivate + - [x] lombok.accessors.prefix + - [ ] lombok.noArgsConstructor.extraPrivate (probably we don't need to support it - it is private after all) - [ ] lombok.copyableAnnotations - [ ] Copy annotations - - [~] Strip defined prefixes - in config and @Accessors + - [x] Strip defined prefixes - in config and @Accessors - [ ] Skip generation with AccessLevel.NONE - [x] Strip 'is' prefix for boolean fields 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 b16afd04071..b9a9391b6e1 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 @@ -7,30 +7,82 @@ package org.jetbrains.kotlin.lombok.config import java.io.File -class LombokConfig(private val config: Map) { +class LombokConfig(private val config: Map>) { - fun getString(key: String): String? = config[key] + fun getString(key: String): String? = config[key]?.firstOrNull() fun getBoolean(key: String): Boolean? = getString(key)?.toBoolean() - fun getBooleanOrDefault(key: String, default: Boolean = false): Boolean = getBoolean(key) ?: default + fun getMultiString(key: String): List? = config[key] companion object { val Empty = LombokConfig(emptyMap()) - fun parse(path: File): LombokConfig { + fun parse(path: File): LombokConfig = ConfigParser.parse(path) + } - val config = mutableMapOf() +} - path.forEachLine { line -> - val parts = line.split("=", limit = 2) - if (parts.size == 2) { - config[parts[0].trim()] = parts[1].trim() +/** + * Simplified Lombok config parser. + * Ignores everything it doesn't understand + */ +object ConfigParser { + + //regex is from lombok source code + private val LINE = "(?:clear\\s+([^=]+))|(?:(\\S*?)\\s*([-+]?=)\\s*(.*?))".toRegex() + + fun parse(path: File): LombokConfig { + val builder = ConfigBuilder() + path.forEachLine { parseLine(it, builder) } + return builder.build() + } + + private fun parseLine(line: String, builder: ConfigBuilder) { + LINE.matchEntire(line)?.let { matchResult -> + if (matchResult.groups[1] == null) { + val keyName = matchResult.groupValues[2] + val operator = matchResult.groupValues[3] + val stringValue = matchResult.groupValues[4] + when (operator) { + "=" -> builder.setValue(keyName, stringValue) + "+=" -> builder.plusValue(keyName, stringValue) + "-=" -> builder.minusValue(keyName, stringValue) + else -> { + //do nothing + } } + } else { + //clear + val keyName = matchResult.groupValues[1] + builder.clearValue(keyName) } - return LombokConfig(config) } } } + +class ConfigBuilder { + private val state: MutableMap> = mutableMapOf() + + fun setValue(name: String, value: String) { + state[name] = listOf(value) + } + + fun clearValue(name: String) { + state.remove(name) + } + + fun plusValue(name: String, value: String) { + state.merge(name, listOf(value)) { a, b -> a + b } + } + + fun minusValue(name: String, value: String) { + state.merge(name, listOf(value)) { a, b -> a - b } + } + + fun build(): LombokConfig = LombokConfig(state) +} + + diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/annotationConfig.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/annotationConfig.kt index 78cf3e70856..9ebcd2aff2d 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/annotationConfig.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/annotationConfig.kt @@ -73,8 +73,10 @@ data class Accessors( ?: config.getBoolean("lombok.accessors.chain") ?: fluent val noIsPrefix = config.getBoolean("lombok.getter.noIsPrefix") ?: false - val prefix = annotation?.getStringArrayArgument("prefix") - ?: emptyList() + val prefix = + annotation?.getStringArrayArgument("prefix") + ?: config.getMultiString("lombok.accessors.prefix") + ?: emptyList() return Accessors(fluent, chain, noIsPrefix, prefix) } diff --git a/plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefix.kt b/plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefix.kt index 0b7234a550d..ecc57b7fc5a 100644 --- a/plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefix.kt +++ b/plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefix.kt @@ -6,7 +6,7 @@ import lombok.experimental.*; @Getter @Setter @Accessors(prefix = {"f", "field"}) public class AccessorsTest { - @Accessors +// @Accessors private int age = 10; private int fTarget = 42; private String fieldValue; @@ -48,8 +48,8 @@ class Test { fun run() { val obj = AccessorsTest() - obj.getAge() - obj.setAge(123) +// obj.getAge() +// obj.setAge(123) obj.getTarget() obj.setTarget(34) diff --git a/plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefixConfig.kt b/plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefixConfig.kt new file mode 100644 index 00000000000..d6e3e267864 --- /dev/null +++ b/plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefixConfig.kt @@ -0,0 +1,74 @@ +//FILE: AccessorsTest.java + +import lombok.*; +import lombok.experimental.*; + +@Getter @Setter +public class AccessorsTest { +// @Accessors + private int age = 10; + private int fTarget = 42; + private String fieldValue; + + @Accessors(prefix = {}) + private boolean isHuman; + private boolean fPrefixedBoolean; + @Accessors(prefix = {}) + private Boolean isNonPrimitiveHuman; + + static void test() { + val obj = new AccessorsTest(); + +// obj.getAge(); +// obj.setAge(123); + + obj.getTarget(); + obj.setTarget(34); + + obj.getValue(); + obj.setValue("sdf"); + + obj.isHuman(); + obj.setHuman(true); + + obj.isPrefixedBoolean(); + obj.setPrefixedBoolean(false); + + obj.getIsNonPrimitiveHuman(); + obj.setIsNonPrimitiveHuman(false); + } + +} + + +//FILE: test.kt + +class Test { + fun run() { + val obj = AccessorsTest() + +// obj.getAge() +// obj.setAge(123) + + obj.getTarget() + obj.setTarget(34) + + obj.getValue() + obj.setValue("sdf") + + obj.isHuman() + obj.setHuman(true) + + obj.isPrefixedBoolean() + obj.setPrefixedBoolean(false) + + obj.getIsNonPrimitiveHuman() + obj.setIsNonPrimitiveHuman(false) + + } + +} + +//FILE: lombok.config +lombok.accessors.prefix += f +lombok.accessors.prefix+=field 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 dc6f4d24f36..8c7b2c87cb8 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 @@ -36,6 +36,11 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest { runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefix.kt"); } + @TestMetadata("accessorsStripPrefixConfig.kt") + public void testAccessorsStripPrefixConfig() throws Exception { + runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefixConfig.kt"); + } + @TestMetadata("allArgsConstructor.kt") public void testAllArgsConstructor() throws Exception { runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/allArgsConstructor.kt");