diff --git a/build.gradle.kts b/build.gradle.kts
index 28857479f07..102632be56a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -962,6 +962,7 @@ tasks {
":prepare:ide-plugin-dependencies:sam-with-receiver-compiler-plugin-for-ide:publish",
":prepare:ide-plugin-dependencies:compiler-components-for-jps:publish",
":prepare:ide-plugin-dependencies:parcelize-compiler-plugin-for-ide:publish",
+ ":prepare:ide-plugin-dependencies:lombok-compiler-plugin-for-ide:publish",
":kotlin-script-runtime:publish",
":kotlin-script-util:publish",
":kotlin-scripting-common:publish",
diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPaths.kt b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPaths.kt
index 7ad4a76d331..bd436f30111 100644
--- a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPaths.kt
+++ b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPaths.kt
@@ -66,6 +66,9 @@ interface KotlinPaths {
val noArgPluginJarPath: File
get() = jar(Jar.NoArgPlugin)
+ val lombokPluginJarPath: File
+ get() = jar(Jar.LombokPlugin)
+
// @Deprecated("Obsolete API", ReplaceWith("jar(KotlinPaths.Jars.samWithReceiver)"))
val samWithReceiverJarPath: File
get() = jar(Jar.SamWithReceiver)
@@ -93,6 +96,7 @@ interface KotlinPaths {
JsKotlinTest(PathUtil.KOTLIN_TEST_JS_NAME),
AllOpenPlugin(PathUtil.ALLOPEN_PLUGIN_NAME),
NoArgPlugin(PathUtil.NOARG_PLUGIN_NAME),
+ LombokPlugin(PathUtil.LOMBOK_PLUGIN_NAME),
SamWithReceiver(PathUtil.SAM_WITH_RECEIVER_PLUGIN_NAME),
SerializationPlugin(PathUtil.SERIALIZATION_PLUGIN_NAME),
Trove4j(PathUtil.TROVE4J_NAME),
@@ -150,4 +154,4 @@ open class KotlinPathsFromBaseDirectory(val basePath: File) : KotlinPaths {
override fun jar(jar: KotlinPaths.Jar): File = basePath.resolve(jar.baseName + ".jar")
override fun sourcesJar(jar: KotlinPaths.Jar): File? = basePath.resolve(jar.baseName + "-sources.jar")
-}
\ No newline at end of file
+}
diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.kt b/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.kt
index 32fe3d2ba10..ffc48d6c480 100644
--- a/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.kt
+++ b/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.kt
@@ -36,6 +36,7 @@ object PathUtil {
const val SAM_WITH_RECEIVER_PLUGIN_JAR_NAME = "$SAM_WITH_RECEIVER_PLUGIN_NAME.jar"
const val SERIALIZATION_PLUGIN_NAME = "kotlinx-serialization-compiler-plugin"
const val SERIALIZATION_PLUGIN_JAR_NAME = "$SERIALIZATION_PLUGIN_NAME.jar"
+ const val LOMBOK_PLUGIN_NAME = "lombok-compiler-plugin"
const val ANDROID_EXTENSIONS_RUNTIME_PLUGIN_JAR_NAME = "android-extensions-runtime.jar"
const val PARCELIZE_RUNTIME_PLUGIN_JAR_NAME = "parcelize-runtime.jar"
const val JS_LIB_SRC_JAR_NAME = "kotlin-stdlib-js-sources.jar"
diff --git a/idea/resources/META-INF/maven.xml b/idea/resources/META-INF/maven.xml
index 61d8d60619c..10b741b106a 100644
--- a/idea/resources/META-INF/maven.xml
+++ b/idea/resources/META-INF/maven.xml
@@ -6,6 +6,7 @@
+
diff --git a/plugins/lombok/lombok-ide-plugin/build.gradle.kts b/plugins/lombok/lombok-ide-plugin/build.gradle.kts
new file mode 100644
index 00000000000..d2f934ab8c4
--- /dev/null
+++ b/plugins/lombok/lombok-ide-plugin/build.gradle.kts
@@ -0,0 +1,34 @@
+description = "Lombok IDE plugin"
+
+plugins {
+ kotlin("jvm")
+ id("jps-compatible")
+}
+
+dependencies {
+ implementation(project(":plugins:lombok:lombok-compiler-plugin"))
+
+ compileOnly(project(":idea"))
+ compileOnly(project(":idea:idea-jvm"))
+ compileOnly(project(":idea:idea-jps-common"))
+ compileOnly(project(":idea:idea-maven"))
+ compileOnly(intellijDep())
+ excludeInAndroidStudio(rootProject) { compileOnly(intellijPluginDep("maven")) }
+ compileOnly(intellijPluginDep("gradle"))
+ compileOnly(project(":idea:kotlin-gradle-tooling"))
+}
+
+sourceSets {
+ "main" { projectDefault() }
+ "test" { projectDefault() }
+}
+
+runtimeJar()
+
+sourcesJar()
+
+javadocJar()
+
+projectTest(parallel = true)
+
+apply(from = "$rootDir/gradle/kotlinPluginPublication.gradle.kts")
diff --git a/plugins/lombok/lombok-ide-plugin/src/org/jetbrains/kotlin/lombok/ide/AbstractMavenImportHandler.kt b/plugins/lombok/lombok-ide-plugin/src/org/jetbrains/kotlin/lombok/ide/AbstractMavenImportHandler.kt
new file mode 100644
index 00000000000..e54eff58221
--- /dev/null
+++ b/plugins/lombok/lombok-ide-plugin/src/org/jetbrains/kotlin/lombok/ide/AbstractMavenImportHandler.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.ide
+
+import org.jdom.Element
+import org.jdom.Text
+import org.jetbrains.idea.maven.project.MavenProject
+import org.jetbrains.kotlin.idea.facet.KotlinFacet
+import org.jetbrains.kotlin.idea.maven.MavenProjectImportHandler
+import org.jetbrains.kotlin.idea.maven.KotlinMavenImporter.Companion.KOTLIN_PLUGIN_GROUP_ID
+import org.jetbrains.kotlin.idea.maven.KotlinMavenImporter.Companion.KOTLIN_PLUGIN_ARTIFACT_ID
+import java.io.File
+import org.jetbrains.kotlin.lombok.ide.CompilerPluginSetup.PluginOption
+
+abstract class AbstractMavenImportHandler : MavenProjectImportHandler {
+ abstract val compilerPluginId: String
+ abstract val pluginName: String
+// abstract val mavenPluginArtifactName: String
+ abstract val pluginJarFileFromIdea: File
+
+ override fun invoke(facet: KotlinFacet, mavenProject: MavenProject) {
+ modifyCompilerArgumentsForPlugin(
+ facet, getPluginSetup(mavenProject),
+ compilerPluginId = compilerPluginId,
+ pluginName = pluginName
+ )
+ }
+
+ abstract fun getOptions(enabledCompilerPlugins: List, compilerPluginOptions: List): List?
+
+ private fun getPluginSetup(mavenProject: MavenProject): CompilerPluginSetup? {
+ val kotlinPlugin = mavenProject.plugins.firstOrNull {
+ it.groupId == KOTLIN_PLUGIN_GROUP_ID && it.artifactId == KOTLIN_PLUGIN_ARTIFACT_ID
+ } ?: return null
+
+ val configuration = kotlinPlugin.configurationElement ?: return null
+
+ val enabledCompilerPlugins = configuration.getElement("compilerPlugins")
+ ?.getElements()
+ ?.flatMap { plugin -> plugin.content.mapNotNull { (it as? Text)?.text } }
+ ?: emptyList()
+
+ val compilerPluginOptions = configuration.getElement("pluginOptions")
+ ?.getElements()
+ ?.flatMap { it.content }
+ ?.mapTo(mutableListOf()) { (it as Text).text }
+ ?: mutableListOf()
+
+ // We can't use the plugin from Gradle as it may have the incompatible version
+ val classpath = listOf(pluginJarFileFromIdea.absolutePath)
+
+ val options = getOptions(enabledCompilerPlugins, compilerPluginOptions) ?: return null
+ return CompilerPluginSetup(options, classpath)
+ }
+
+ private fun Element.getElement(name: String) = content.firstOrNull { it is Element && it.name == name } as? Element
+
+ @Suppress("UNCHECKED_CAST")
+ private fun Element.getElements() = content.filterIsInstance()
+}
diff --git a/plugins/lombok/lombok-ide-plugin/src/org/jetbrains/kotlin/lombok/ide/LombokMavenProjectImportHandler.kt b/plugins/lombok/lombok-ide-plugin/src/org/jetbrains/kotlin/lombok/ide/LombokMavenProjectImportHandler.kt
new file mode 100644
index 00000000000..1535a470777
--- /dev/null
+++ b/plugins/lombok/lombok-ide-plugin/src/org/jetbrains/kotlin/lombok/ide/LombokMavenProjectImportHandler.kt
@@ -0,0 +1,39 @@
+/*
+ * 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.ide
+
+import org.jetbrains.kotlin.lombok.LombokCommandLineProcessor
+import org.jetbrains.kotlin.lombok.LombokCommandLineProcessor.Companion.CONFIG_FILE_OPTION
+import org.jetbrains.kotlin.lombok.ide.CompilerPluginSetup.PluginOption
+import org.jetbrains.kotlin.utils.PathUtil
+import java.io.File
+
+class LombokMavenProjectImportHandler : AbstractMavenImportHandler() {
+ override val compilerPluginId: String = LombokCommandLineProcessor.PLUGIN_ID
+ override val pluginName: String = MAVEN_SUBPLUGIN_NAME
+ override val pluginJarFileFromIdea: File = PathUtil.kotlinPathsForIdeaPlugin.lombokPluginJarPath
+
+ override fun getOptions(
+ enabledCompilerPlugins: List,
+ compilerPluginOptions: List
+ ): List? {
+ if (!enabledCompilerPlugins.contains(pluginName)) return null
+
+ return compilerPluginOptions.mapNotNull { v ->
+ if (v.startsWith(CONFIG_FILE_PREFIX)) {
+ val location = v.substring(CONFIG_FILE_PREFIX.length)
+ PluginOption(CONFIG_FILE_OPTION.optionName, location)
+ } else {
+ null
+ }
+ }
+ }
+
+ companion object {
+ private const val MAVEN_SUBPLUGIN_NAME = "lombok"
+ private val CONFIG_FILE_PREFIX = "$MAVEN_SUBPLUGIN_NAME:${CONFIG_FILE_OPTION.optionName}="
+ }
+}
diff --git a/plugins/lombok/lombok-ide-plugin/src/org/jetbrains/kotlin/lombok/ide/idePluginUtils.kt b/plugins/lombok/lombok-ide-plugin/src/org/jetbrains/kotlin/lombok/ide/idePluginUtils.kt
new file mode 100644
index 00000000000..19e32472899
--- /dev/null
+++ b/plugins/lombok/lombok-ide-plugin/src/org/jetbrains/kotlin/lombok/ide/idePluginUtils.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.ide
+
+import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
+import org.jetbrains.kotlin.idea.facet.KotlinFacet
+import java.io.File
+
+class CompilerPluginSetup(val options: List, val classpath: List) {
+ class PluginOption(val key: String, val value: String)
+}
+
+internal fun modifyCompilerArgumentsForPlugin(
+ facet: KotlinFacet,
+ setup: CompilerPluginSetup?,
+ compilerPluginId: String,
+ pluginName: String
+) {
+ val facetSettings = facet.configuration.settings
+
+ // investigate why copyBean() sometimes throws exceptions
+ val commonArguments = facetSettings.compilerArguments ?: CommonCompilerArguments.DummyImpl()
+
+ /** See [CommonCompilerArguments.PLUGIN_OPTION_FORMAT] **/
+ val newOptionsForPlugin = setup?.options?.map { "plugin:$compilerPluginId:${it.key}=${it.value}" } ?: emptyList()
+
+ val oldAllPluginOptions =
+ (commonArguments.pluginOptions ?: emptyArray()).filterTo(mutableListOf()) { !it.startsWith("plugin:$compilerPluginId:") }
+ val newAllPluginOptions = oldAllPluginOptions + newOptionsForPlugin
+
+ val oldPluginClasspaths = (commonArguments.pluginClasspaths ?: emptyArray()).filterTo(mutableListOf()) {
+ val lastIndexOfFile = it.lastIndexOfAny(charArrayOf('/', File.separatorChar))
+ if (lastIndexOfFile < 0) {
+ return@filterTo true
+ }
+ !it.drop(lastIndexOfFile + 1).matches("(kotlin-)?(maven-)?$pluginName-.*\\.jar".toRegex())
+ }
+
+ val newPluginClasspaths = oldPluginClasspaths + (setup?.classpath ?: emptyList())
+
+ commonArguments.pluginOptions = newAllPluginOptions.toTypedArray()
+ commonArguments.pluginClasspaths = newPluginClasspaths.toTypedArray()
+
+ facetSettings.compilerArguments = commonArguments
+}
diff --git a/prepare/compiler/build.gradle.kts b/prepare/compiler/build.gradle.kts
index 2e7b7e61a56..7c4c488e0aa 100644
--- a/prepare/compiler/build.gradle.kts
+++ b/prepare/compiler/build.gradle.kts
@@ -114,7 +114,8 @@ val distCompilerPluginProjects = listOf(
":plugins:parcelize:parcelize-runtime",
":kotlin-noarg-compiler-plugin",
":kotlin-sam-with-receiver-compiler-plugin",
- ":kotlinx-serialization-compiler-plugin"
+ ":kotlinx-serialization-compiler-plugin",
+ ":plugins:lombok:lombok-compiler-plugin"
)
val distSourcesProjects = listOfNotNull(
diff --git a/prepare/ide-plugin-dependencies/lombok-compiler-plugin-for-ide/build.gradle.kts b/prepare/ide-plugin-dependencies/lombok-compiler-plugin-for-ide/build.gradle.kts
new file mode 100644
index 00000000000..87c06675b35
--- /dev/null
+++ b/prepare/ide-plugin-dependencies/lombok-compiler-plugin-for-ide/build.gradle.kts
@@ -0,0 +1,3 @@
+idePluginDependency {
+ publishProjectJars(listOf(":plugins:lombok:lombok-compiler-plugin"))
+}
diff --git a/prepare/idea-plugin/build.gradle.kts b/prepare/idea-plugin/build.gradle.kts
index c5b00c75d73..76d09302f1a 100644
--- a/prepare/idea-plugin/build.gradle.kts
+++ b/prepare/idea-plugin/build.gradle.kts
@@ -138,6 +138,7 @@ val libraryProjects = listOf(
":kotlin-allopen-compiler-plugin",
":kotlin-noarg-compiler-plugin",
":kotlin-sam-with-receiver-compiler-plugin",
+ ":plugins:lombok:lombok-compiler-plugin",
":plugins:android-extensions-compiler",
":plugins:parcelize:parcelize-compiler",
":kotlinx-serialization-compiler-plugin",
@@ -193,6 +194,7 @@ dependencies {
gradleToolingModel(project(":plugins:parcelize:parcelize-ide")) { isTransitive = false }
gradleToolingModel(project(":noarg-ide-plugin")) { isTransitive = false }
gradleToolingModel(project(":allopen-ide-plugin")) { isTransitive = false }
+ gradleToolingModel(project(":plugins:lombok:lombok-ide-plugin")) { isTransitive = false }
jpsPlugin(project(":kotlin-jps-plugin")) { isTransitive = false }
diff --git a/settings.gradle b/settings.gradle
index fa6dfb26513..f9d4aa9b142 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -347,6 +347,7 @@ include ":plugins:parcelize:parcelize-compiler",
":kotlin-parcelize-compiler"
include ":plugins:lombok:lombok-compiler-plugin",
+ ":plugins:lombok:lombok-ide-plugin",
":kotlin-lombok"
include ":prepare:ide-plugin-dependencies:android-extensions-compiler-plugin-for-ide",
@@ -361,6 +362,7 @@ include ":prepare:ide-plugin-dependencies:android-extensions-compiler-plugin-for
":prepare:ide-plugin-dependencies:noarg-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:sam-with-receiver-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:parcelize-compiler-plugin-for-ide",
+ ":prepare:ide-plugin-dependencies:lombok-compiler-plugin-for-ide",
":prepare:ide-plugin-dependencies:tests-common-tests-for-ide",
":prepare:ide-plugin-dependencies:compiler-components-for-jps"