[Lombok] Add implementation of plugin for FIR
This commit is contained in:
committed by
teamcity
parent
e58e86932c
commit
a84ece7233
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.*
|
|||||||
import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull
|
import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull
|
||||||
import org.jetbrains.kotlin.fir.isNewPlaceForBodyGeneration
|
import org.jetbrains.kotlin.fir.isNewPlaceForBodyGeneration
|
||||||
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.getDeclaredConstructors
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ package org.jetbrains.kotlin.fir.java
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||||
|
|
||||||
internal class JavaTypeParameterStack {
|
class JavaTypeParameterStack : Iterable<Map.Entry<JavaTypeParameter, FirTypeParameterSymbol>> {
|
||||||
|
|
||||||
private val typeParameterMap = mutableMapOf<JavaTypeParameter, FirTypeParameterSymbol>()
|
private val typeParameterMap = mutableMapOf<JavaTypeParameter, FirTypeParameterSymbol>()
|
||||||
|
|
||||||
fun addParameter(javaTypeParameter: JavaTypeParameter, symbol: FirTypeParameterSymbol) {
|
fun addParameter(javaTypeParameter: JavaTypeParameter, symbol: FirTypeParameterSymbol) {
|
||||||
@@ -25,6 +24,10 @@ internal class JavaTypeParameterStack {
|
|||||||
?: throw IllegalArgumentException("Cannot find Java type parameter $javaTypeParameter in stack")
|
?: throw IllegalArgumentException("Cannot find Java type parameter $javaTypeParameter in stack")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override operator fun iterator(): Iterator<Map.Entry<JavaTypeParameter, FirTypeParameterSymbol>> {
|
||||||
|
return typeParameterMap.iterator()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY: JavaTypeParameterStack = JavaTypeParameterStack()
|
val EMPTY: JavaTypeParameterStack = JavaTypeParameterStack()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class FirJavaClass @FirImplementationDetail internal constructor(
|
|||||||
override val superTypeRefs: MutableList<FirTypeRef>,
|
override val superTypeRefs: MutableList<FirTypeRef>,
|
||||||
override val typeParameters: MutableList<FirTypeParameterRef>,
|
override val typeParameters: MutableList<FirTypeParameterRef>,
|
||||||
internal val javaPackage: JavaPackage?,
|
internal val javaPackage: JavaPackage?,
|
||||||
internal val javaTypeParameterStack: JavaTypeParameterStack,
|
val javaTypeParameterStack: JavaTypeParameterStack,
|
||||||
internal val existingNestedClassifierNames: List<Name>
|
internal val existingNestedClassifierNames: List<Name>
|
||||||
) : FirRegularClass() {
|
) : FirRegularClass() {
|
||||||
override val hasLazyNestedClassifiers: Boolean get() = true
|
override val hasLazyNestedClassifiers: Boolean get() = true
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
import org.jetbrains.kotlin.fir.visitors.transformInplace
|
import org.jetbrains.kotlin.fir.visitors.transformInplace
|
||||||
@@ -240,7 +239,7 @@ class FirJavaMethodBuilder : FirFunctionBuilder, FirTypeParametersOwnerBuilder,
|
|||||||
origin = javaOrigin(isFromSource),
|
origin = javaOrigin(isFromSource),
|
||||||
resolvePhase,
|
resolvePhase,
|
||||||
attributes,
|
attributes,
|
||||||
returnTypeRef as FirJavaTypeRef,
|
returnTypeRef,
|
||||||
typeParameters,
|
typeParameters,
|
||||||
valueParameters,
|
valueParameters,
|
||||||
name,
|
name,
|
||||||
|
|||||||
+12
-4
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|
||||||
|
|
||||||
private fun FirAnnotation.toAnnotationLookupTag(): ConeClassLikeLookupTag? =
|
private fun FirAnnotation.toAnnotationLookupTag(): ConeClassLikeLookupTag? =
|
||||||
// this cast fails when we have generic-typed annotations @T
|
// this cast fails when we have generic-typed annotations @T
|
||||||
@@ -159,10 +158,19 @@ fun FirAnnotation.findArgumentByName(name: Name): FirExpression? {
|
|||||||
return arguments.singleOrNull()
|
return arguments.singleOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FirAnnotation.getStringArgument(name: Name): String? =
|
fun FirAnnotation.getBooleanArgument(name: Name): Boolean? = getPrimitiveArgumentValue(name)
|
||||||
findArgumentByName(name)?.let { expression ->
|
fun FirAnnotation.getStringArgument(name: Name): String? = getPrimitiveArgumentValue(name)
|
||||||
expression.safeAs<FirConstExpression<*>>()?.value as? String
|
fun FirAnnotation.getIntArgument(name: Name): Int? = getPrimitiveArgumentValue(name)
|
||||||
|
fun FirAnnotation.getStringArrayArgument(name: Name): List<String>? {
|
||||||
|
val argument = findArgumentByName(name) as? FirArrayOfCall ?: return null
|
||||||
|
return argument.arguments.mapNotNull { (it as? FirConstExpression<*>)?.value as? String }
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T> FirAnnotation.getPrimitiveArgumentValue(name: Name): T? {
|
||||||
|
return findArgumentByName(name)?.let { expression ->
|
||||||
|
(expression as? FirConstExpression<*>)?.value as? T
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun FirAnnotationContainer.getJvmNameFromAnnotation(target: AnnotationUseSiteTarget? = null): String? {
|
fun FirAnnotationContainer.getJvmNameFromAnnotation(target: AnnotationUseSiteTarget? = null): String? {
|
||||||
val annotationCalls = getAnnotationsByClassId(StandardClassIds.Annotations.JvmName)
|
val annotationCalls = getAnnotationsByClassId(StandardClassIds.Annotations.JvmName)
|
||||||
|
|||||||
-1
@@ -53,7 +53,6 @@ object FirGeneratedElementsValidator : FirDefaultVisitor<Unit, Any?>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeRef(typeRef: FirTypeRef, data: Any?) {
|
override fun visitTypeRef(typeRef: FirTypeRef, data: Any?) {
|
||||||
require(typeRef is FirResolvedTypeRef)
|
|
||||||
typeRef.acceptChildren(this, null)
|
typeRef.acceptChildren(this, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,7 @@ import org.jetbrains.kotlin.kapt3.test.AbstractClassFileToSourceStubConverterTes
|
|||||||
import org.jetbrains.kotlin.kapt3.test.AbstractIrClassFileToSourceStubConverterTest
|
import org.jetbrains.kotlin.kapt3.test.AbstractIrClassFileToSourceStubConverterTest
|
||||||
import org.jetbrains.kotlin.kapt3.test.AbstractIrKotlinKaptContextTest
|
import org.jetbrains.kotlin.kapt3.test.AbstractIrKotlinKaptContextTest
|
||||||
import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptContextTest
|
import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptContextTest
|
||||||
import org.jetbrains.kotlin.lombok.AbstractBlackBoxCodegenTestForLombok
|
import org.jetbrains.kotlin.lombok.*
|
||||||
import org.jetbrains.kotlin.lombok.AbstractDiagnosticTestForLombok
|
|
||||||
import org.jetbrains.kotlin.lombok.AbstractIrBlackBoxCodegenTestForLombok
|
|
||||||
import org.jetbrains.kotlin.noarg.*
|
import org.jetbrains.kotlin.noarg.*
|
||||||
import org.jetbrains.kotlin.parcelize.test.runners.*
|
import org.jetbrains.kotlin.parcelize.test.runners.*
|
||||||
import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverScriptTest
|
import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverScriptTest
|
||||||
@@ -430,8 +428,14 @@ fun main(args: Array<String>) {
|
|||||||
testClass<AbstractIrBlackBoxCodegenTestForLombok> {
|
testClass<AbstractIrBlackBoxCodegenTestForLombok> {
|
||||||
model("box")
|
model("box")
|
||||||
}
|
}
|
||||||
|
testClass<AbstractFirBlackBoxCodegenTestForLombok> {
|
||||||
|
model("box")
|
||||||
|
}
|
||||||
testClass<AbstractDiagnosticTestForLombok> {
|
testClass<AbstractDiagnosticTestForLombok> {
|
||||||
model("diagnostics")
|
model("diagnostics", excludedPattern = excludedFirTestdataPattern)
|
||||||
|
}
|
||||||
|
testClass<AbstractFirDiagnosticTestForLombok> {
|
||||||
|
model("diagnostics", excludedPattern = excludedFirTestdataPattern)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
embedded(project(":kotlin-lombok-compiler-plugin.common"))
|
embedded(project(":kotlin-lombok-compiler-plugin.common"))
|
||||||
embedded(project(":kotlin-lombok-compiler-plugin.k1"))
|
embedded(project(":kotlin-lombok-compiler-plugin.k1"))
|
||||||
|
embedded(project(":kotlin-lombok-compiler-plugin.k2"))
|
||||||
embedded(project(":kotlin-lombok-compiler-plugin.cli"))
|
embedded(project(":kotlin-lombok-compiler-plugin.cli"))
|
||||||
|
|
||||||
testImplementation(intellijCore())
|
testImplementation(intellijCore())
|
||||||
testImplementation(project(":kotlin-lombok-compiler-plugin.common"))
|
testImplementation(project(":kotlin-lombok-compiler-plugin.common"))
|
||||||
testImplementation(project(":kotlin-lombok-compiler-plugin.k1"))
|
testImplementation(project(":kotlin-lombok-compiler-plugin.k1"))
|
||||||
|
testImplementation(project(":kotlin-lombok-compiler-plugin.k2"))
|
||||||
testImplementation(project(":kotlin-lombok-compiler-plugin.cli"))
|
testImplementation(project(":kotlin-lombok-compiler-plugin.cli"))
|
||||||
|
|
||||||
testImplementation("org.projectlombok:lombok:1.18.16")
|
testImplementation("org.projectlombok:lombok:1.18.16")
|
||||||
|
|||||||
@@ -11,9 +11,11 @@ dependencies {
|
|||||||
compileOnly(project(":compiler:plugin-api"))
|
compileOnly(project(":compiler:plugin-api"))
|
||||||
compileOnly(project(":compiler:frontend"))
|
compileOnly(project(":compiler:frontend"))
|
||||||
compileOnly(project(":compiler:frontend.java"))
|
compileOnly(project(":compiler:frontend.java"))
|
||||||
|
compileOnly(project(":compiler:fir:entrypoint"))
|
||||||
|
|
||||||
implementation(project(":kotlin-lombok-compiler-plugin.common"))
|
implementation(project(":kotlin-lombok-compiler-plugin.common"))
|
||||||
implementation(project(":kotlin-lombok-compiler-plugin.k1"))
|
implementation(project(":kotlin-lombok-compiler-plugin.k1"))
|
||||||
|
implementation(project(":kotlin-lombok-compiler-plugin.k2"))
|
||||||
|
|
||||||
compileOnly(intellijCore())
|
compileOnly(intellijCore())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,17 +15,20 @@ import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
|
|||||||
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
||||||
import org.jetbrains.kotlin.lombok.LombokConfigurationKeys.CONFIG_FILE
|
import org.jetbrains.kotlin.lombok.LombokConfigurationKeys.CONFIG_FILE
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.FirLombokRegistrar
|
||||||
import org.jetbrains.kotlin.resolve.jvm.extensions.SyntheticJavaResolveExtension
|
import org.jetbrains.kotlin.resolve.jvm.extensions.SyntheticJavaResolveExtension
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.IllegalArgumentException
|
|
||||||
|
|
||||||
class LombokComponentRegistrar : ComponentRegistrar {
|
class LombokComponentRegistrar : ComponentRegistrar {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun registerComponents(project: Project, compilerConfiguration: CompilerConfiguration) {
|
fun registerComponents(project: Project, compilerConfiguration: CompilerConfiguration) {
|
||||||
val config = LombokPluginConfig(compilerConfiguration[CONFIG_FILE])
|
val configFile = compilerConfiguration[CONFIG_FILE]
|
||||||
|
val config = LombokPluginConfig(configFile)
|
||||||
SyntheticJavaResolveExtension.registerExtension(project, LombokResolveExtension(config))
|
SyntheticJavaResolveExtension.registerExtension(project, LombokResolveExtension(config))
|
||||||
|
FirExtensionRegistrar.registerExtension(project, FirLombokRegistrar(configFile))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.lombok.utils
|
package org.jetbrains.kotlin.lombok.utils
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
object LombokNames {
|
object LombokNames {
|
||||||
@@ -20,6 +21,16 @@ object LombokNames {
|
|||||||
val REQUIRED_ARGS_CONSTRUCTOR = FqName("lombok.RequiredArgsConstructor")
|
val REQUIRED_ARGS_CONSTRUCTOR = FqName("lombok.RequiredArgsConstructor")
|
||||||
|
|
||||||
|
|
||||||
|
val ACCESSORS_ID = ClassId.topLevel(ACCESSORS)
|
||||||
|
val GETTER_ID = ClassId.topLevel(GETTER)
|
||||||
|
val SETTER_ID = ClassId.topLevel(SETTER)
|
||||||
|
val WITH_ID = ClassId.topLevel(WITH)
|
||||||
|
val DATA_ID = ClassId.topLevel(DATA)
|
||||||
|
val VALUE_ID = ClassId.topLevel(VALUE)
|
||||||
|
val NO_ARGS_CONSTRUCTOR_ID = ClassId.topLevel(NO_ARGS_CONSTRUCTOR)
|
||||||
|
val ALL_ARGS_CONSTRUCTOR_ID = ClassId.topLevel(ALL_ARGS_CONSTRUCTOR)
|
||||||
|
val REQUIRED_ARGS_CONSTRUCTOR_ID = ClassId.topLevel(REQUIRED_ARGS_CONSTRUCTOR)
|
||||||
|
|
||||||
//taken from idea lombok plugin
|
//taken from idea lombok plugin
|
||||||
val NON_NULL_ANNOTATIONS = listOf(
|
val NON_NULL_ANNOTATIONS = listOf(
|
||||||
"androidx.annotation.NonNull",
|
"androidx.annotation.NonNull",
|
||||||
|
|||||||
-19
@@ -5,31 +5,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.lombok.utils
|
package org.jetbrains.kotlin.lombok.utils
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Accessors
|
|
||||||
|
|
||||||
object AccessorNames {
|
object AccessorNames {
|
||||||
const val IS = "is"
|
const val IS = "is"
|
||||||
const val GET = "get"
|
const val GET = "get"
|
||||||
const val SET = "set"
|
const val SET = "set"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Make property name from variable name
|
|
||||||
* Returns null in case getter/setter shouldn't be generated at all
|
|
||||||
*/
|
|
||||||
fun PropertyDescriptor.toAccessorBaseName(config: Accessors): String? {
|
|
||||||
val isPrimitiveBoolean = type.isPrimitiveBoolean()
|
|
||||||
return if (config.prefix.isEmpty()) {
|
|
||||||
val prefixes = if (isPrimitiveBoolean) listOf(AccessorNames.IS) else emptyList()
|
|
||||||
toPropertyName(name.identifier, prefixes)
|
|
||||||
} else {
|
|
||||||
val id = name.identifier
|
|
||||||
val name = toPropertyName(id, config.prefix)
|
|
||||||
name.takeIf { it.length != id.length}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toPropertyName(name: String, prefixesToStrip: List<String> = emptyList()): String =
|
fun toPropertyName(name: String, prefixesToStrip: List<String> = emptyList()): String =
|
||||||
name.stripPrefixes(prefixesToStrip).decapitalize()
|
name.stripPrefixes(prefixesToStrip).decapitalize()
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Accessors
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make property name from variable name
|
||||||
|
* Returns null in case getter/setter shouldn't be generated at all
|
||||||
|
*/
|
||||||
|
fun PropertyDescriptor.toAccessorBaseName(config: Accessors): String? {
|
||||||
|
val isPrimitiveBoolean = type.isPrimitiveBoolean()
|
||||||
|
return if (config.prefix.isEmpty()) {
|
||||||
|
val prefixes = if (isPrimitiveBoolean) listOf(AccessorNames.IS) else emptyList()
|
||||||
|
toPropertyName(name.identifier, prefixes)
|
||||||
|
} else {
|
||||||
|
val id = name.identifier
|
||||||
|
val name = toPropertyName(id, config.prefix)
|
||||||
|
name.takeIf { it.length != id.length}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
description = "Lombok compiler plugin (K2)"
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
id("jps-compatible")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":kotlin-lombok-compiler-plugin.common"))
|
||||||
|
compileOnly(project(":compiler:fir:cones"))
|
||||||
|
compileOnly(project(":compiler:fir:tree"))
|
||||||
|
compileOnly(project(":compiler:fir:resolve"))
|
||||||
|
compileOnly(project(":compiler:fir:checkers"))
|
||||||
|
compileOnly(project(":compiler:fir:java"))
|
||||||
|
compileOnly(project(":compiler:fir:entrypoint"))
|
||||||
|
|
||||||
|
compileOnly(intellijCore())
|
||||||
|
runtimeOnly(kotlinStdlib())
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
"main" { projectDefault() }
|
||||||
|
"test" { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
runtimeJar()
|
||||||
|
sourcesJar()
|
||||||
|
javadocJar()
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokService
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.generators.*
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class FirLombokRegistrar(private val lombokConfigFile: File?) : FirExtensionRegistrar() {
|
||||||
|
override fun ExtensionRegistrarContext.configurePlugin() {
|
||||||
|
+LombokService.getFactory(lombokConfigFile)
|
||||||
|
+::GetterGenerator
|
||||||
|
+::SetterGenerator
|
||||||
|
+::WithGenerator
|
||||||
|
+::LombokConstructorsGenerator
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.config
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.createCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||||
|
import org.jetbrains.kotlin.fir.caches.getValue
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionSessionComponent
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionSessionComponent.Factory
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.lombok.config.LombokConfig
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.Accessors
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.AllArgsConstructor
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.Data
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.Getter
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.NoArgsConstructor
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.RequiredArgsConstructor
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.Setter
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.Value
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.With
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
class LombokService(session: FirSession, configFile: File?) : FirExtensionSessionComponent(session) {
|
||||||
|
companion object {
|
||||||
|
fun getFactory(configFile: File?): Factory {
|
||||||
|
return Factory { LombokService(it, configFile) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val config = configFile?.let(LombokConfig::parse) ?: LombokConfig.Empty
|
||||||
|
private val cachesFactory = session.firCachesFactory
|
||||||
|
|
||||||
|
private val accessorsCache: Cache<Accessors> = cachesFactory.createCache { symbol ->
|
||||||
|
Accessors.get(symbol.fir, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val accessorsIfAnnotatedCache: Cache<Accessors?> = cachesFactory.createCache { symbol ->
|
||||||
|
Accessors.getIfAnnotated(symbol.fir, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val getterCache: Cache<Getter?> = cachesFactory.createCache { symbol ->
|
||||||
|
Getter.getOrNull(symbol.fir)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val setterCache: Cache<Setter?> = cachesFactory.createCache { symbol ->
|
||||||
|
Setter.getOrNull(symbol.fir)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val withCache: Cache<With?> = cachesFactory.createCache { symbol ->
|
||||||
|
With.getOrNull(symbol.fir)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val noArgsConstructorCache: Cache<NoArgsConstructor?> = cachesFactory.createCache { symbol ->
|
||||||
|
NoArgsConstructor.getOrNull(symbol.fir)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val allArgsConstructorCache: Cache<AllArgsConstructor?> = cachesFactory.createCache { symbol ->
|
||||||
|
AllArgsConstructor.getOrNull(symbol.fir)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val requiredArgsConstructorCache: Cache<RequiredArgsConstructor?> = cachesFactory.createCache { symbol ->
|
||||||
|
RequiredArgsConstructor.getOrNull(symbol.fir)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val dataCache: Cache<Data?> = cachesFactory.createCache { symbol ->
|
||||||
|
Data.getOrNull(symbol.fir)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val valueCache: Cache<Value?> = cachesFactory.createCache { symbol ->
|
||||||
|
Value.getOrNull(symbol.fir)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAccessors(symbol: FirBasedSymbol<*>): Accessors = accessorsCache.getValue(symbol)
|
||||||
|
fun getAccessorsIfAnnotated(symbol: FirBasedSymbol<*>): Accessors? = accessorsIfAnnotatedCache.getValue(symbol)
|
||||||
|
fun getGetter(symbol: FirBasedSymbol<*>): Getter? = getterCache.getValue(symbol)
|
||||||
|
fun getSetter(symbol: FirBasedSymbol<*>): Setter? = setterCache.getValue(symbol)
|
||||||
|
fun getWith(symbol: FirBasedSymbol<*>): With? = withCache.getValue(symbol)
|
||||||
|
fun getNoArgsConstructor(symbol: FirBasedSymbol<*>): NoArgsConstructor? = noArgsConstructorCache.getValue(symbol)
|
||||||
|
fun getAllArgsConstructor(symbol: FirBasedSymbol<*>): AllArgsConstructor? = allArgsConstructorCache.getValue(symbol)
|
||||||
|
fun getRequiredArgsConstructor(symbol: FirBasedSymbol<*>): RequiredArgsConstructor? = requiredArgsConstructorCache.getValue(symbol)
|
||||||
|
fun getData(symbol: FirBasedSymbol<*>): Data? = dataCache.getValue(symbol)
|
||||||
|
fun getValue(symbol: FirBasedSymbol<*>): Value? = valueCache.getValue(symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
private typealias Cache<T> = FirCache<FirBasedSymbol<*>, T, Nothing?>
|
||||||
|
|
||||||
|
val FirSession.lombokService: LombokService by FirSession.sessionComponentAccessor()
|
||||||
+193
@@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.config
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.getBooleanArgument
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.getStringArrayArgument
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||||
|
import org.jetbrains.kotlin.lombok.config.AccessLevel
|
||||||
|
import org.jetbrains.kotlin.lombok.config.LombokConfig
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokConfigNames.ACCESS
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokConfigNames.CHAIN
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokConfigNames.CHAIN_CONFIG
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokConfigNames.FLUENT
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokConfigNames.FLUENT_CONFIG
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokConfigNames.NO_IS_PREFIX_CONFIG
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokConfigNames.PREFIX
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokConfigNames.PREFIX_CONFIG
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokConfigNames.STATIC_CONSTRUCTOR
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokConfigNames.STATIC_NAME
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.LombokNames
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lombok has two ways of configuration - lombok.config file and directly in annotations. Annotations has priority.
|
||||||
|
* Not all things can be configured in annotations
|
||||||
|
* So to make things easier I put all configuration in 'annotations' classes, but populate them from config too. So far it allows
|
||||||
|
* keeping processors' code unaware about configuration origin.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun List<FirAnnotation>.findAnnotation(classId: ClassId): FirAnnotation? {
|
||||||
|
return firstOrNull { it.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId == classId }
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ConeAnnotationCompanion<T>(val name: ClassId) {
|
||||||
|
|
||||||
|
abstract fun extract(annotation: FirAnnotation): T
|
||||||
|
|
||||||
|
fun getOrNull(annotated: FirAnnotationContainer): T? {
|
||||||
|
return annotated.annotations.findAnnotation(name)?.let(this::extract)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ConeAnnotationAndConfigCompanion<T>(val annotationName: ClassId) {
|
||||||
|
|
||||||
|
abstract fun extract(annotation: FirAnnotation?, config: LombokConfig): T
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get from annotation or config or default
|
||||||
|
*/
|
||||||
|
fun get(annotated: FirAnnotationContainer, config: LombokConfig): T =
|
||||||
|
extract(annotated.annotations.findAnnotation(annotationName), config)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If element is annotated, get from it or config or default
|
||||||
|
*/
|
||||||
|
fun getIfAnnotated(annotated: FirAnnotationContainer, config: LombokConfig): T? =
|
||||||
|
annotated.annotations.findAnnotation(annotationName)?.let { annotation ->
|
||||||
|
extract(annotation, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object ConeLombokAnnotations {
|
||||||
|
class Accessors(
|
||||||
|
val fluent: Boolean = false,
|
||||||
|
val chain: Boolean = false,
|
||||||
|
val noIsPrefix: Boolean = false,
|
||||||
|
val prefix: List<String> = emptyList()
|
||||||
|
) {
|
||||||
|
companion object : ConeAnnotationAndConfigCompanion<Accessors>(LombokNames.ACCESSORS_ID) {
|
||||||
|
override fun extract(annotation: FirAnnotation?, config: LombokConfig): Accessors {
|
||||||
|
val fluent = annotation?.getBooleanArgument(FLUENT)
|
||||||
|
?: config.getBoolean(FLUENT_CONFIG)
|
||||||
|
?: false
|
||||||
|
val chain = annotation?.getBooleanArgument(CHAIN)
|
||||||
|
?: config.getBoolean(CHAIN_CONFIG)
|
||||||
|
?: fluent
|
||||||
|
val noIsPrefix = config.getBoolean(NO_IS_PREFIX_CONFIG) ?: false
|
||||||
|
val prefix = annotation?.getStringArrayArgument(PREFIX)
|
||||||
|
?: config.getMultiString(PREFIX_CONFIG)
|
||||||
|
?: emptyList()
|
||||||
|
|
||||||
|
return Accessors(fluent, chain, noIsPrefix, prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Getter(val visibility: AccessLevel = AccessLevel.PUBLIC) {
|
||||||
|
companion object : ConeAnnotationCompanion<Getter>(LombokNames.GETTER_ID) {
|
||||||
|
override fun extract(annotation: FirAnnotation): Getter = Getter(
|
||||||
|
visibility = getAccessLevel(annotation)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Setter(val visibility: AccessLevel = AccessLevel.PUBLIC) {
|
||||||
|
companion object : ConeAnnotationCompanion<Setter>(LombokNames.SETTER_ID) {
|
||||||
|
override fun extract(annotation: FirAnnotation): Setter = Setter(
|
||||||
|
visibility = getAccessLevel(annotation)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class With(val visibility: AccessLevel = AccessLevel.PUBLIC) {
|
||||||
|
companion object : ConeAnnotationCompanion<With>(LombokNames.WITH_ID) {
|
||||||
|
override fun extract(annotation: FirAnnotation): With = With(
|
||||||
|
visibility = getAccessLevel(annotation)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConstructorAnnotation {
|
||||||
|
val visibility: Visibility
|
||||||
|
val staticName: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoArgsConstructor(
|
||||||
|
override val visibility: Visibility,
|
||||||
|
override val staticName: String?
|
||||||
|
) : ConstructorAnnotation {
|
||||||
|
companion object : ConeAnnotationCompanion<NoArgsConstructor>(LombokNames.NO_ARGS_CONSTRUCTOR_ID) {
|
||||||
|
override fun extract(annotation: FirAnnotation): NoArgsConstructor = NoArgsConstructor(
|
||||||
|
visibility = getVisibility(annotation, ACCESS),
|
||||||
|
staticName = annotation.getNonBlankStringArgument(STATIC_NAME)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AllArgsConstructor(
|
||||||
|
override val visibility: Visibility = Visibilities.Public,
|
||||||
|
override val staticName: String? = null
|
||||||
|
) : ConstructorAnnotation {
|
||||||
|
companion object : ConeAnnotationCompanion<AllArgsConstructor>(LombokNames.ALL_ARGS_CONSTRUCTOR_ID) {
|
||||||
|
override fun extract(annotation: FirAnnotation): AllArgsConstructor = AllArgsConstructor(
|
||||||
|
visibility = getVisibility(annotation, ACCESS),
|
||||||
|
staticName = annotation.getNonBlankStringArgument(STATIC_NAME)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RequiredArgsConstructor(
|
||||||
|
override val visibility: Visibility = Visibilities.Public,
|
||||||
|
override val staticName: String? = null
|
||||||
|
) : ConstructorAnnotation {
|
||||||
|
companion object : ConeAnnotationCompanion<RequiredArgsConstructor>(LombokNames.REQUIRED_ARGS_CONSTRUCTOR_ID) {
|
||||||
|
override fun extract(annotation: FirAnnotation): RequiredArgsConstructor = RequiredArgsConstructor(
|
||||||
|
visibility = getVisibility(annotation, ACCESS),
|
||||||
|
staticName = annotation.getNonBlankStringArgument(STATIC_NAME)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Data(val staticConstructor: String?) {
|
||||||
|
fun asSetter(): Setter = Setter()
|
||||||
|
fun asGetter(): Getter = Getter()
|
||||||
|
|
||||||
|
fun asRequiredArgsConstructor(): RequiredArgsConstructor = RequiredArgsConstructor(
|
||||||
|
staticName = staticConstructor
|
||||||
|
)
|
||||||
|
|
||||||
|
companion object : ConeAnnotationCompanion<Data>(LombokNames.DATA_ID) {
|
||||||
|
override fun extract(annotation: FirAnnotation): Data =
|
||||||
|
Data(
|
||||||
|
staticConstructor = annotation.getNonBlankStringArgument(STATIC_CONSTRUCTOR)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Value(val staticConstructor: String?) {
|
||||||
|
fun asGetter(): Getter = Getter()
|
||||||
|
|
||||||
|
fun asAllArgsConstructor(): AllArgsConstructor = AllArgsConstructor(
|
||||||
|
staticName = staticConstructor
|
||||||
|
)
|
||||||
|
|
||||||
|
companion object : ConeAnnotationCompanion<Value>(LombokNames.VALUE_ID) {
|
||||||
|
override fun extract(annotation: FirAnnotation): Value = Value(
|
||||||
|
staticConstructor = annotation.getNonBlankStringArgument(STATIC_CONSTRUCTOR)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.config
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.findArgumentByName
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.getStringArgument
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol
|
||||||
|
import org.jetbrains.kotlin.lombok.config.AccessLevel
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.trimToNull
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
fun getAccessLevel(annotation: FirAnnotation, field: Name = LombokConfigNames.VALUE): AccessLevel {
|
||||||
|
val value = annotation.getArgumentAsString(field) ?: return AccessLevel.PUBLIC
|
||||||
|
return AccessLevel.valueOf(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirAnnotation.getArgumentAsString(field: Name): String? {
|
||||||
|
val argument = findArgumentByName(field) ?: return null
|
||||||
|
return when (argument) {
|
||||||
|
is FirConstExpression<*> -> argument.value as? String
|
||||||
|
is FirQualifiedAccessExpression -> {
|
||||||
|
val symbol = argument.toResolvedCallableSymbol()
|
||||||
|
if (symbol is FirEnumEntrySymbol) {
|
||||||
|
symbol.callableId.callableName.identifier
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getVisibility(annotation: FirAnnotation, field: Name = LombokConfigNames.VALUE): Visibility {
|
||||||
|
return getAccessLevel(annotation, field).toVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FirAnnotation.getNonBlankStringArgument(name: Name): String? = getStringArgument(name)?.trimToNull()
|
||||||
|
|
||||||
|
object LombokConfigNames {
|
||||||
|
val VALUE = Name.identifier("value")
|
||||||
|
val FLUENT = Name.identifier("fluent")
|
||||||
|
val CHAIN = Name.identifier("chain")
|
||||||
|
val PREFIX = Name.identifier("prefix")
|
||||||
|
val ACCESS = Name.identifier("access")
|
||||||
|
val STATIC_NAME = Name.identifier("staticName")
|
||||||
|
val STATIC_CONSTRUCTOR = Name.identifier("staticConstructor")
|
||||||
|
|
||||||
|
|
||||||
|
const val FLUENT_CONFIG = "lombok.accessors.fluent"
|
||||||
|
const val CHAIN_CONFIG = "lombok.accessors.chain"
|
||||||
|
const val PREFIX_CONFIG = "lombok.accessors.prefix"
|
||||||
|
const val NO_IS_PREFIX_CONFIG = "lombok.getter.noIsPrefix"
|
||||||
|
}
|
||||||
+231
@@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.containingClassForStaticMemberAttr
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.builder.buildConstructedClassTypeParameterRef
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.builder.buildTypeParameterCopy
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.toEffectiveVisibility
|
||||||
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.jvm.buildJavaTypeRef
|
||||||
|
import org.jetbrains.kotlin.load.java.structure.*
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokService
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.lombokService
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.name.callableIdForConstructor
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
|
|
||||||
|
abstract class AbstractConstructorGeneratorPart<T : ConeLombokAnnotations.ConstructorAnnotation>(private val session: FirSession) {
|
||||||
|
protected val lombokService: LombokService
|
||||||
|
get() = session.lombokService
|
||||||
|
|
||||||
|
protected abstract fun getConstructorInfo(classSymbol: FirClassSymbol<*>): T?
|
||||||
|
protected abstract fun getFieldsForParameters(classSymbol: FirClassSymbol<*>): List<FirJavaField>
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
fun createConstructor(classSymbol: FirClassSymbol<*>): FirFunction? {
|
||||||
|
val constructorInfo = getConstructorInfo(classSymbol) ?: return null
|
||||||
|
val staticName = constructorInfo.staticName?.let { Name.identifier(it) }
|
||||||
|
|
||||||
|
val substitutor: JavaTypeSubstitutor
|
||||||
|
val builder = if (staticName == null) {
|
||||||
|
FirJavaConstructorBuilder().apply {
|
||||||
|
symbol = FirConstructorSymbol(classSymbol.classId.callableIdForConstructor())
|
||||||
|
classSymbol.fir.typeParameters.mapTo(typeParameters) {
|
||||||
|
buildConstructedClassTypeParameterRef { symbol = it.symbol }
|
||||||
|
}
|
||||||
|
substitutor = JavaTypeSubstitutor.Empty
|
||||||
|
returnTypeRef = buildResolvedTypeRef {
|
||||||
|
type = classSymbol.defaultType()
|
||||||
|
}
|
||||||
|
isInner = classSymbol.isInner
|
||||||
|
isPrimary = false
|
||||||
|
isFromSource = true
|
||||||
|
annotationBuilder = { emptyList() }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FirJavaMethodBuilder().apply {
|
||||||
|
name = staticName
|
||||||
|
val methodSymbol = FirNamedFunctionSymbol(CallableId(classSymbol.classId, staticName))
|
||||||
|
symbol = methodSymbol
|
||||||
|
|
||||||
|
val classTypeParameterSymbols = classSymbol.fir.typeParameters.map { it.symbol }
|
||||||
|
classTypeParameterSymbols.mapTo(typeParameters) {
|
||||||
|
buildTypeParameterCopy(it.fir) {
|
||||||
|
symbol = FirTypeParameterSymbol()
|
||||||
|
containingDeclarationSymbol = methodSymbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val javaClass = classSymbol.fir as FirJavaClass
|
||||||
|
val javaTypeParametersFromClass = javaClass.javaTypeParameterStack
|
||||||
|
.filter { it.value in classTypeParameterSymbols }
|
||||||
|
.map { it.key }
|
||||||
|
|
||||||
|
val functionTypeParameterToJavaTypeParameter = typeParameters.zip(javaTypeParametersFromClass)
|
||||||
|
.associate { (parameter, javaParameter) -> parameter.symbol to JavaTypeParameterStub(javaParameter) }
|
||||||
|
|
||||||
|
for ((parameter, javaParameter) in functionTypeParameterToJavaTypeParameter) {
|
||||||
|
javaClass.javaTypeParameterStack.addParameter(javaParameter, parameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
val javaTypeSubstitution: Map<JavaClassifier, JavaType> = javaTypeParametersFromClass
|
||||||
|
.zip(functionTypeParameterToJavaTypeParameter.values)
|
||||||
|
.associate { (originalParameter, newParameter) ->
|
||||||
|
originalParameter to JavaTypeParameterTypeStub(newParameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
substitutor = JavaTypeSubstitutorByMap(javaTypeSubstitution)
|
||||||
|
returnTypeRef = buildResolvedTypeRef {
|
||||||
|
type = classSymbol.classId.defaultType(functionTypeParameterToJavaTypeParameter.keys.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
isStatic = true
|
||||||
|
isFromSource = true
|
||||||
|
annotationBuilder = { emptyList() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.apply {
|
||||||
|
moduleData = classSymbol.moduleData
|
||||||
|
status = FirResolvedDeclarationStatusImpl(
|
||||||
|
constructorInfo.visibility,
|
||||||
|
Modality.FINAL,
|
||||||
|
constructorInfo.visibility.toEffectiveVisibility(classSymbol)
|
||||||
|
).apply {
|
||||||
|
if (staticName != null) {
|
||||||
|
isStatic = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val fields = getFieldsForParameters(classSymbol)
|
||||||
|
fields.mapTo(valueParameters) { field ->
|
||||||
|
buildJavaValueParameter {
|
||||||
|
moduleData = field.moduleData
|
||||||
|
returnTypeRef = when (val typeRef = field.returnTypeRef) {
|
||||||
|
is FirJavaTypeRef -> buildJavaTypeRef {
|
||||||
|
type = substitutor.substituteOrSelf(typeRef.type)
|
||||||
|
annotationBuilder = { emptyList() }
|
||||||
|
}
|
||||||
|
else -> typeRef
|
||||||
|
}
|
||||||
|
name = field.name
|
||||||
|
annotationBuilder = { emptyList() }
|
||||||
|
isVararg = false
|
||||||
|
isFromSource = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build().apply {
|
||||||
|
containingClassForStaticMemberAttr = classSymbol.toLookupTag()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JavaTypeParameterStub(val original: JavaTypeParameter) : JavaTypeParameter {
|
||||||
|
override val name: Name
|
||||||
|
get() = original.name
|
||||||
|
override val isFromSource: Boolean
|
||||||
|
get() = true
|
||||||
|
override val annotations: Collection<JavaAnnotation>
|
||||||
|
get() = original.annotations
|
||||||
|
override val isDeprecatedInJavaDoc: Boolean
|
||||||
|
get() = original.isDeprecatedInJavaDoc
|
||||||
|
|
||||||
|
override fun findAnnotation(fqName: FqName): JavaAnnotation? {
|
||||||
|
return original.findAnnotation(fqName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val upperBounds: Collection<JavaClassifierType>
|
||||||
|
get() = original.upperBounds
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JavaClassifierTypeStub(
|
||||||
|
val original: JavaClassifierType,
|
||||||
|
override val typeArguments: List<JavaType?>,
|
||||||
|
) : JavaClassifierType {
|
||||||
|
override val annotations: Collection<JavaAnnotation>
|
||||||
|
get() = original.annotations
|
||||||
|
override val isDeprecatedInJavaDoc: Boolean
|
||||||
|
get() = original.isDeprecatedInJavaDoc
|
||||||
|
override val classifier: JavaClassifier?
|
||||||
|
get() = original.classifier
|
||||||
|
override val isRaw: Boolean
|
||||||
|
get() = original.isRaw
|
||||||
|
override val classifierQualifiedName: String
|
||||||
|
get() = original.classifierQualifiedName
|
||||||
|
override val presentableText: String
|
||||||
|
get() = original.presentableText
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JavaTypeParameterTypeStub(
|
||||||
|
override val classifier: JavaTypeParameter
|
||||||
|
) : JavaClassifierType {
|
||||||
|
override val annotations: Collection<JavaAnnotation>
|
||||||
|
get() = emptyList()
|
||||||
|
override val isDeprecatedInJavaDoc: Boolean
|
||||||
|
get() = false
|
||||||
|
override val typeArguments: List<JavaType?>
|
||||||
|
get() = emptyList()
|
||||||
|
override val isRaw: Boolean
|
||||||
|
get() = false
|
||||||
|
override val classifierQualifiedName: String
|
||||||
|
get() = classifier.name.identifier
|
||||||
|
override val presentableText: String
|
||||||
|
get() = classifierQualifiedName
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class JavaTypeSubstitutor {
|
||||||
|
object Empty : JavaTypeSubstitutor() {
|
||||||
|
override fun substituteOrNull(type: JavaType): JavaType? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun substituteOrSelf(type: JavaType): JavaType {
|
||||||
|
return substituteOrNull(type) ?: type
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun substituteOrNull(type: JavaType): JavaType?
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JavaTypeSubstitutorByMap(val map: Map<JavaClassifier, JavaType>) : JavaTypeSubstitutor() {
|
||||||
|
override fun substituteOrNull(type: JavaType): JavaType? {
|
||||||
|
if (type !is JavaClassifierType) return null
|
||||||
|
map[type.classifier]?.let { return it }
|
||||||
|
var hasNewArguments = false
|
||||||
|
val newArguments = type.typeArguments.map { argument ->
|
||||||
|
if (argument == null) return@map null
|
||||||
|
val newArgument = substituteOrNull(argument)
|
||||||
|
if (newArgument !== argument) {
|
||||||
|
hasNewArguments = true
|
||||||
|
newArgument
|
||||||
|
} else {
|
||||||
|
argument
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return runIf(hasNewArguments) {
|
||||||
|
JavaClassifierTypeStub(type, newArguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.AllArgsConstructor
|
||||||
|
|
||||||
|
class AllArgsConstructorGeneratorPart(session: FirSession) : AbstractConstructorGeneratorPart<AllArgsConstructor>(session) {
|
||||||
|
override fun getConstructorInfo(classSymbol: FirClassSymbol<*>): AllArgsConstructor? {
|
||||||
|
return lombokService.getAllArgsConstructor(classSymbol)
|
||||||
|
?: lombokService.getValue(classSymbol)?.asAllArgsConstructor()
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
override fun getFieldsForParameters(classSymbol: FirClassSymbol<*>): List<FirJavaField> {
|
||||||
|
return classSymbol.fir.declarations.filterIsInstance<FirJavaField>()
|
||||||
|
}
|
||||||
|
}
|
||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.createCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||||
|
import org.jetbrains.kotlin.fir.caches.getValue
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.buildJavaMethod
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.toEffectiveVisibility
|
||||||
|
import org.jetbrains.kotlin.lombok.config.AccessLevel
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.Accessors
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.Getter
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokService
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.lombokService
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.AccessorNames
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.capitalize
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.collectWithNotNull
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
class GetterGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) {
|
||||||
|
private val lombokService: LombokService
|
||||||
|
get() = session.lombokService
|
||||||
|
|
||||||
|
private val cache: FirCache<FirClassSymbol<*>, Map<Name, FirJavaMethod>?, Nothing?> =
|
||||||
|
session.firCachesFactory.createCache(::createGetters)
|
||||||
|
|
||||||
|
override fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>): Set<Name> {
|
||||||
|
if (!classSymbol.isSuitableJavaClass()) return emptySet()
|
||||||
|
return cache.getValue(classSymbol)?.keys ?: emptySet()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateFunctions(callableId: CallableId, context: MemberGenerationContext?): List<FirNamedFunctionSymbol> {
|
||||||
|
val owner = context?.owner
|
||||||
|
if (owner == null || !owner.isSuitableJavaClass()) return emptyList()
|
||||||
|
val getter = cache.getValue(owner)?.get(callableId.callableName) ?: return emptyList()
|
||||||
|
return listOf(getter.symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createGetters(classSymbol: FirClassSymbol<*>): Map<Name, FirJavaMethod>? {
|
||||||
|
val fieldsWithGetter = computeFieldsWithGetter(classSymbol) ?: return null
|
||||||
|
val globalAccessors = lombokService.getAccessors(classSymbol)
|
||||||
|
return fieldsWithGetter.mapNotNull { (field, getterInfo) ->
|
||||||
|
val getterName = computeGetterName(field, getterInfo, globalAccessors) ?: return@mapNotNull null
|
||||||
|
val function = buildJavaMethod {
|
||||||
|
moduleData = field.moduleData
|
||||||
|
returnTypeRef = field.returnTypeRef
|
||||||
|
dispatchReceiverType = classSymbol.defaultType()
|
||||||
|
name = getterName
|
||||||
|
symbol = FirNamedFunctionSymbol(CallableId(classSymbol.classId, getterName))
|
||||||
|
val visibility = getterInfo.visibility.toVisibility()
|
||||||
|
status = FirResolvedDeclarationStatusImpl(visibility, Modality.OPEN, visibility.toEffectiveVisibility(classSymbol))
|
||||||
|
isStatic = false
|
||||||
|
isFromSource = true
|
||||||
|
annotationBuilder = { emptyList() }
|
||||||
|
}
|
||||||
|
getterName to function
|
||||||
|
}.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
private fun computeFieldsWithGetter(classSymbol: FirClassSymbol<*>): List<Pair<FirJavaField, Getter>>? {
|
||||||
|
val classGetter = lombokService.getGetter(classSymbol)
|
||||||
|
?: lombokService.getData(classSymbol)?.asGetter()
|
||||||
|
?: lombokService.getValue(classSymbol)?.asGetter()
|
||||||
|
|
||||||
|
return classSymbol.fir.declarations
|
||||||
|
.filterIsInstance<FirJavaField>()
|
||||||
|
.collectWithNotNull { lombokService.getGetter(it.symbol) ?: classGetter }
|
||||||
|
.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeGetterName(field: FirJavaField, getterInfo: Getter, globalAccessors: Accessors): Name? {
|
||||||
|
if (getterInfo.visibility == AccessLevel.NONE) return null
|
||||||
|
val accessors = lombokService.getAccessorsIfAnnotated(field.symbol) ?: globalAccessors
|
||||||
|
val propertyName = field.toAccessorBaseName(accessors) ?: return null
|
||||||
|
val functionName = if (accessors.fluent) {
|
||||||
|
propertyName
|
||||||
|
} else {
|
||||||
|
val prefix = if (field.returnTypeRef.isPrimitiveBoolean() && !accessors.noIsPrefix) AccessorNames.IS else AccessorNames.GET
|
||||||
|
prefix + propertyName.capitalize()
|
||||||
|
}
|
||||||
|
return Name.identifier(functionName)
|
||||||
|
}
|
||||||
|
}
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.createCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||||
|
import org.jetbrains.kotlin.fir.caches.getValue
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
|
|
||||||
|
class LombokConstructorsGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) {
|
||||||
|
private val parts: List<AbstractConstructorGeneratorPart<*>> = listOf(
|
||||||
|
AllArgsConstructorGeneratorPart(session),
|
||||||
|
NoArgsConstructorGeneratorPart(session),
|
||||||
|
RequiredArgsConstructorGeneratorPart(session)
|
||||||
|
)
|
||||||
|
|
||||||
|
private val cache: FirCache<FirClassSymbol<*>, Collection<FirFunctionSymbol<*>>?, Nothing?> =
|
||||||
|
session.firCachesFactory.createCache(::createConstructors)
|
||||||
|
|
||||||
|
override fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>): Set<Name> {
|
||||||
|
if (!classSymbol.isSuitableJavaClass()) return emptySet()
|
||||||
|
return cache.getValue(classSymbol)?.mapTo(mutableSetOf()) {
|
||||||
|
when (it) {
|
||||||
|
is FirConstructorSymbol -> SpecialNames.INIT
|
||||||
|
else -> it.callableId.callableName
|
||||||
|
}
|
||||||
|
} ?: emptySet()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateFunctions(callableId: CallableId, context: MemberGenerationContext?): List<FirNamedFunctionSymbol> {
|
||||||
|
val owner = context?.owner ?: return emptyList()
|
||||||
|
if (!owner.isSuitableJavaClass()) return emptyList()
|
||||||
|
return cache.getValue(owner)?.filterIsInstance<FirNamedFunctionSymbol>().orEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateConstructors(context: MemberGenerationContext): List<FirConstructorSymbol> {
|
||||||
|
val owner = context.owner
|
||||||
|
if (!owner.isSuitableJavaClass()) return emptyList()
|
||||||
|
return cache.getValue(owner)?.filterIsInstance<FirConstructorSymbol>().orEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createConstructors(classSymbol: FirClassSymbol<*>): Collection<FirFunctionSymbol<*>>? {
|
||||||
|
return parts
|
||||||
|
.mapNotNull { it.createConstructor(classSymbol) }
|
||||||
|
.takeIf { it.isNotEmpty() }
|
||||||
|
?.filterClashingDeclarations(classSymbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.NoArgsConstructor
|
||||||
|
|
||||||
|
class NoArgsConstructorGeneratorPart(session: FirSession) : AbstractConstructorGeneratorPart<NoArgsConstructor>(session) {
|
||||||
|
override fun getConstructorInfo(classSymbol: FirClassSymbol<*>): NoArgsConstructor? {
|
||||||
|
return lombokService.getNoArgsConstructor(classSymbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFieldsForParameters(classSymbol: FirClassSymbol<*>): List<FirJavaField> {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.generators
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiField
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.classId
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.RequiredArgsConstructor
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.LombokNames
|
||||||
|
import org.jetbrains.kotlin.psi
|
||||||
|
|
||||||
|
class RequiredArgsConstructorGeneratorPart(session: FirSession) : AbstractConstructorGeneratorPart<RequiredArgsConstructor>(session) {
|
||||||
|
override fun getConstructorInfo(classSymbol: FirClassSymbol<*>): RequiredArgsConstructor? {
|
||||||
|
return lombokService.getRequiredArgsConstructor(classSymbol)
|
||||||
|
?: lombokService.getData(classSymbol)?.asRequiredArgsConstructor()
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
override fun getFieldsForParameters(classSymbol: FirClassSymbol<*>): List<FirJavaField> {
|
||||||
|
return classSymbol.fir.declarations
|
||||||
|
.filterIsInstance<FirJavaField>()
|
||||||
|
.filter { it.isFieldRequired() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirJavaField.isFieldRequired(): Boolean {
|
||||||
|
// TODO: consider adding `hasInitializer` property directly to java model
|
||||||
|
val hasInitializer = (source?.psi as? PsiField)?.hasInitializer() ?: false
|
||||||
|
if (hasInitializer) return false
|
||||||
|
if (isVal) return true
|
||||||
|
return annotations.any { it.classId?.asSingleFqName() in LombokNames.NON_NULL_ANNOTATIONS }
|
||||||
|
}
|
||||||
|
}
|
||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.createCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||||
|
import org.jetbrains.kotlin.fir.caches.getValue
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.buildJavaMethod
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.buildJavaValueParameter
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.toEffectiveVisibility
|
||||||
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.lombok.config.AccessLevel
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.Accessors
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.Setter
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokService
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.lombokService
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.AccessorNames
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.capitalize
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.collectWithNotNull
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
class SetterGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) {
|
||||||
|
private val lombokService: LombokService
|
||||||
|
get() = session.lombokService
|
||||||
|
|
||||||
|
private val cache: FirCache<FirClassSymbol<*>, Map<Name, FirJavaMethod>?, Nothing?> =
|
||||||
|
session.firCachesFactory.createCache(::createSetters)
|
||||||
|
|
||||||
|
override fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>): Set<Name> {
|
||||||
|
if (!classSymbol.isSuitableForSetters()) return emptySet()
|
||||||
|
return cache.getValue(classSymbol)?.keys ?: emptySet()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateFunctions(callableId: CallableId, context: MemberGenerationContext?): List<FirNamedFunctionSymbol> {
|
||||||
|
val owner = context?.owner
|
||||||
|
if (owner == null || !owner.isSuitableForSetters()) return emptyList()
|
||||||
|
val getter = cache.getValue(owner)?.get(callableId.callableName) ?: return emptyList()
|
||||||
|
return listOf(getter.symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirClassSymbol<*>.isSuitableForSetters(): Boolean {
|
||||||
|
return isSuitableJavaClass() && classKind != ClassKind.ENUM_CLASS
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createSetters(classSymbol: FirClassSymbol<*>): Map<Name, FirJavaMethod>? {
|
||||||
|
val fieldsWithSetter = computeFieldsWithSetters(classSymbol) ?: return null
|
||||||
|
val globalAccessors = lombokService.getAccessors(classSymbol)
|
||||||
|
return fieldsWithSetter.mapNotNull { (field, setterInfo) ->
|
||||||
|
val accessors = lombokService.getAccessorsIfAnnotated(field.symbol) ?: globalAccessors
|
||||||
|
val setterName = computeSetterName(field, setterInfo, accessors) ?: return@mapNotNull null
|
||||||
|
val function = buildJavaMethod {
|
||||||
|
moduleData = field.moduleData
|
||||||
|
returnTypeRef = if (accessors.chain) {
|
||||||
|
buildResolvedTypeRef {
|
||||||
|
type = classSymbol.defaultType()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
session.builtinTypes.unitType
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchReceiverType = classSymbol.defaultType()
|
||||||
|
name = setterName
|
||||||
|
symbol = FirNamedFunctionSymbol(CallableId(classSymbol.classId, setterName))
|
||||||
|
val visibility = setterInfo.visibility.toVisibility()
|
||||||
|
status = FirResolvedDeclarationStatusImpl(visibility, Modality.OPEN, visibility.toEffectiveVisibility(classSymbol))
|
||||||
|
|
||||||
|
valueParameters += buildJavaValueParameter {
|
||||||
|
moduleData = field.moduleData
|
||||||
|
returnTypeRef = field.returnTypeRef
|
||||||
|
name = field.name
|
||||||
|
annotationBuilder = { emptyList() }
|
||||||
|
isVararg = false
|
||||||
|
isFromSource = true
|
||||||
|
}
|
||||||
|
|
||||||
|
isStatic = false
|
||||||
|
isFromSource = true
|
||||||
|
annotationBuilder = { emptyList() }
|
||||||
|
}
|
||||||
|
setterName to function
|
||||||
|
}.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
private fun computeFieldsWithSetters(classSymbol: FirClassSymbol<*>): List<Pair<FirJavaField, Setter>>? {
|
||||||
|
val classSetter = lombokService.getSetter(classSymbol)
|
||||||
|
?: lombokService.getData(classSymbol)?.asSetter()
|
||||||
|
|
||||||
|
return classSymbol.fir.declarations
|
||||||
|
.filterIsInstance<FirJavaField>()
|
||||||
|
.filter { it.isVar }
|
||||||
|
.collectWithNotNull { lombokService.getSetter(it.symbol) ?: classSetter }
|
||||||
|
.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeSetterName(field: FirJavaField, setterInfo: Setter, accessors: Accessors): Name? {
|
||||||
|
if (setterInfo.visibility == AccessLevel.NONE) return null
|
||||||
|
val propertyName = field.toAccessorBaseName(accessors) ?: return null
|
||||||
|
val functionName = if (accessors.fluent) {
|
||||||
|
propertyName
|
||||||
|
} else {
|
||||||
|
AccessorNames.SET + propertyName.capitalize()
|
||||||
|
}
|
||||||
|
return Name.identifier(functionName)
|
||||||
|
}
|
||||||
|
}
|
||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.k2.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.createCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||||
|
import org.jetbrains.kotlin.fir.caches.getValue
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.buildJavaMethod
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.buildJavaValueParameter
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.toEffectiveVisibility
|
||||||
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.lombok.config.AccessLevel
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations.With
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.LombokService
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.lombokService
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.collectWithNotNull
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.toPropertyNameCapitalized
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
class WithGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) {
|
||||||
|
private val lombokService: LombokService
|
||||||
|
get() = session.lombokService
|
||||||
|
|
||||||
|
private val cache: FirCache<FirClassSymbol<*>, Map<Name, FirJavaMethod>?, Nothing?> =
|
||||||
|
session.firCachesFactory.createCache(::createWith)
|
||||||
|
|
||||||
|
override fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>): Set<Name> {
|
||||||
|
if (!classSymbol.isSuitableJavaClass()) return emptySet()
|
||||||
|
return cache.getValue(classSymbol)?.keys ?: emptySet()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generateFunctions(callableId: CallableId, context: MemberGenerationContext?): List<FirNamedFunctionSymbol> {
|
||||||
|
val owner = context?.owner
|
||||||
|
if (owner == null || !owner.isSuitableJavaClass()) return emptyList()
|
||||||
|
val getter = cache.getValue(owner)?.get(callableId.callableName) ?: return emptyList()
|
||||||
|
return listOf(getter.symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createWith(classSymbol: FirClassSymbol<*>): Map<Name, FirJavaMethod>? {
|
||||||
|
val fieldsWithWith = computeFieldsWithWithAnnotation(classSymbol) ?: return null
|
||||||
|
return fieldsWithWith.mapNotNull { (field, withInfo) ->
|
||||||
|
val withName = computeWithName(field, withInfo) ?: return@mapNotNull null
|
||||||
|
val function = buildJavaMethod {
|
||||||
|
moduleData = field.moduleData
|
||||||
|
returnTypeRef = buildResolvedTypeRef {
|
||||||
|
type = classSymbol.defaultType()
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchReceiverType = classSymbol.defaultType()
|
||||||
|
name = withName
|
||||||
|
symbol = FirNamedFunctionSymbol(CallableId(classSymbol.classId, withName))
|
||||||
|
val visibility = withInfo.visibility.toVisibility()
|
||||||
|
status = FirResolvedDeclarationStatusImpl(visibility, Modality.OPEN, visibility.toEffectiveVisibility(classSymbol))
|
||||||
|
|
||||||
|
valueParameters += buildJavaValueParameter {
|
||||||
|
moduleData = field.moduleData
|
||||||
|
returnTypeRef = field.returnTypeRef
|
||||||
|
name = field.name
|
||||||
|
annotationBuilder = { emptyList() }
|
||||||
|
isVararg = false
|
||||||
|
isFromSource = true
|
||||||
|
}
|
||||||
|
|
||||||
|
isStatic = false
|
||||||
|
isFromSource = true
|
||||||
|
annotationBuilder = { emptyList() }
|
||||||
|
}
|
||||||
|
withName to function
|
||||||
|
}.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
private fun computeFieldsWithWithAnnotation(classSymbol: FirClassSymbol<*>): List<Pair<FirJavaField, With>>? {
|
||||||
|
val classWith = lombokService.getWith(classSymbol)
|
||||||
|
|
||||||
|
return classSymbol.fir.declarations
|
||||||
|
.filterIsInstance<FirJavaField>()
|
||||||
|
.filter { it.isVar }
|
||||||
|
.collectWithNotNull { lombokService.getWith(it.symbol) ?: classWith }
|
||||||
|
.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeWithName(field: FirJavaField, withInfo: With): Name? {
|
||||||
|
if (withInfo.visibility == AccessLevel.NONE) return null
|
||||||
|
val functionName = "with" + toPropertyNameCapitalized(field.name.identifier)
|
||||||
|
return Name.identifier(functionName)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package org.jetbrains.kotlin.lombok.k2.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
||||||
|
import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType
|
||||||
|
import org.jetbrains.kotlin.lombok.k2.config.ConeLombokAnnotations
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.AccessorNames
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.toPropertyName
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun FirJavaField.toAccessorBaseName(config: ConeLombokAnnotations.Accessors): String? {
|
||||||
|
val isPrimitiveBoolean = returnTypeRef.isPrimitiveBoolean()
|
||||||
|
return if (config.prefix.isEmpty()) {
|
||||||
|
val prefixes = if (isPrimitiveBoolean) listOf(AccessorNames.IS) else emptyList()
|
||||||
|
toPropertyName(name.identifier, prefixes)
|
||||||
|
} else {
|
||||||
|
val id = name.identifier
|
||||||
|
val name = toPropertyName(id, config.prefix)
|
||||||
|
name.takeIf { it.length != id.length}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FirTypeRef.isPrimitiveBoolean(): Boolean {
|
||||||
|
return when (this) {
|
||||||
|
is FirJavaTypeRef -> (type as? JavaPrimitiveType)?.type == PrimitiveType.BOOLEAN
|
||||||
|
else -> this.coneTypeSafe<ConeKotlinType>()?.lowerBoundIfFlexible()?.isBoolean ?: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
fun FirClassSymbol<*>.isSuitableJavaClass(): Boolean {
|
||||||
|
contract {
|
||||||
|
returns(true) implies (this@isSuitableJavaClass is FirRegularClassSymbol)
|
||||||
|
}
|
||||||
|
return (this is FirRegularClassSymbol) && origin == FirDeclarationOrigin.Java.Source
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
fun List<FirFunction>.filterClashingDeclarations(classSymbol: FirClassSymbol<*>): List<FirFunctionSymbol<*>> {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val allStaticFunctionsAndConstructors = classSymbol.fir.declarations.filterIsInstance<FirFunction>().toMutableList()
|
||||||
|
val result = mutableListOf<FirFunction>()
|
||||||
|
for (function in this) {
|
||||||
|
if (allStaticFunctionsAndConstructors.none { sameSignature(it, function) }) {
|
||||||
|
allStaticFunctionsAndConstructors += function
|
||||||
|
result += function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.map { it.symbol }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lombok treat functions as having the same signature by arguments count only
|
||||||
|
* Corresponding code in lombok - https://github.com/projectlombok/lombok/blob/v1.18.20/src/core/lombok/javac/handlers/JavacHandlerUtil.java#L752
|
||||||
|
*/
|
||||||
|
private fun sameSignature(a: FirFunction, b: FirFunction): Boolean {
|
||||||
|
if (a is FirConstructor && b !is FirConstructor || a !is FirConstructor && b is FirConstructor) return false
|
||||||
|
if (a.symbol.callableId.callableName != b.symbol.callableId.callableName) return false
|
||||||
|
val aVararg = a.valueParameters.any { it.isVararg }
|
||||||
|
val bVararg = b.valueParameters.any { it.isVararg }
|
||||||
|
val aSize = a.valueParameters.size
|
||||||
|
val bSize = b.valueParameters.size
|
||||||
|
return aVararg && bVararg ||
|
||||||
|
aVararg && bSize >= (aSize - 1) ||
|
||||||
|
bVararg && aSize >= (bSize - 1) ||
|
||||||
|
aSize == bSize
|
||||||
|
}
|
||||||
Vendored
+7
-2
@@ -1,6 +1,10 @@
|
|||||||
|
// FULL_JDK
|
||||||
|
// WITH_STDLIB
|
||||||
// FILE: DataExample.java
|
// FILE: DataExample.java
|
||||||
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
@Data public class DataExample {
|
@Data public class DataExample {
|
||||||
private final String name;
|
private final String name;
|
||||||
@@ -13,6 +17,7 @@ import lombok.*;
|
|||||||
public static class Exercise<T> {
|
public static class Exercise<T> {
|
||||||
private final String name;
|
private final String name;
|
||||||
private final T value;
|
private final T value;
|
||||||
|
private final List<T> list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void usage() {
|
public static void usage() {
|
||||||
@@ -21,7 +26,7 @@ import lombok.*;
|
|||||||
obj.getTags();
|
obj.getTags();
|
||||||
obj.setScore(1.5);
|
obj.setScore(1.5);
|
||||||
|
|
||||||
Exercise<Integer> ex = Exercise.of("name", 12);
|
Exercise<Integer> ex = Exercise.of("name", 12, Arrays.asList(1, 2, 3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +43,6 @@ fun box(): String {
|
|||||||
obj.score = 2.5
|
obj.score = 2.5
|
||||||
assertEquals(obj.score, 2.5)
|
assertEquals(obj.score, 2.5)
|
||||||
|
|
||||||
val ex: DataExample.Exercise<Int> = DataExample.Exercise.of("name", 12)
|
val ex: DataExample.Exercise<Int> = DataExample.Exercise.of("name", 12, listOf(1, 2, 3))
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// KT-46529
|
||||||
|
|
||||||
|
// FILE: PrefixJava.java
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.*;
|
||||||
|
|
||||||
|
@Getter @Setter @Accessors(chain = false, fluent = true, prefix = {"pxo"})
|
||||||
|
public class PrefixJava {
|
||||||
|
private String pxaPropA = "A";
|
||||||
|
@Accessors(chain = true) private String pxoPropC = "C";
|
||||||
|
@Accessors private String pxaPropD = "D";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
//not generated because doesn't have prefix from class level @Accessors
|
||||||
|
assertEquals(<!ARGUMENT_TYPE_MISMATCH!>PrefixJava().<!UNRESOLVED_REFERENCE!>propA<!><!>, "A")
|
||||||
|
//not generated because doesn't have prefix from config
|
||||||
|
assertEquals(<!ARGUMENT_TYPE_MISMATCH!>PrefixJava().<!UNRESOLVED_REFERENCE!>propC<!><!>, "C")
|
||||||
|
assertEquals(PrefixJava().propD, "D")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: lombok.config
|
||||||
|
lombok.accessors.prefix += pxa
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// KT-46529
|
// KT-46529
|
||||||
|
|
||||||
// FILE: PrefixJava.java
|
// FILE: PrefixJava.java
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// FILE: GetterTest.java
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
public class GetterTest {
|
||||||
|
@Getter private int age = 10;
|
||||||
|
|
||||||
|
@Getter(AccessLevel.PROTECTED) private String name;
|
||||||
|
|
||||||
|
@Getter private boolean primitiveBoolean;
|
||||||
|
|
||||||
|
@Getter private Boolean boxedBoolean;
|
||||||
|
|
||||||
|
@Getter(AccessLevel.NONE) private Boolean invisible;
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
getAge();
|
||||||
|
isPrimitiveBoolean();
|
||||||
|
// getInvisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val obj = GetterTest()
|
||||||
|
val getter = obj.getAge()
|
||||||
|
val property = obj.age
|
||||||
|
|
||||||
|
//todo kotlin doesn't seee isBoolean methods as property
|
||||||
|
obj.<!INVISIBLE_REFERENCE!>primitiveBoolean<!>
|
||||||
|
obj.isPrimitiveBoolean()
|
||||||
|
|
||||||
|
obj.boxedBoolean
|
||||||
|
obj.getBoxedBoolean()
|
||||||
|
|
||||||
|
//shouldn't be accesible from here
|
||||||
|
obj.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
|
||||||
|
obj.<!UNRESOLVED_REFERENCE!>getInvisible<!>()
|
||||||
|
|
||||||
|
OverridenGetterTest().usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
class OverridenGetterTest : GetterTest() {
|
||||||
|
fun usage() {
|
||||||
|
getName()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// FILE: GetterTest.java
|
// FILE: GetterTest.java
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
// FILE: ClassLevelGetterTest.java
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class ClassLevelGetterTest {
|
||||||
|
private int age = 10;
|
||||||
|
|
||||||
|
@Getter(AccessLevel.PROTECTED) private String name;
|
||||||
|
|
||||||
|
private boolean primitiveBoolean;
|
||||||
|
|
||||||
|
private Boolean boxedBoolean;
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
getAge();
|
||||||
|
isPrimitiveBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val obj = ClassLevelGetterTest()
|
||||||
|
val getter = obj.getAge()
|
||||||
|
val property = obj.age
|
||||||
|
|
||||||
|
obj.isPrimitiveBoolean()
|
||||||
|
|
||||||
|
obj.boxedBoolean
|
||||||
|
obj.getBoxedBoolean()
|
||||||
|
|
||||||
|
//shouldn't be accesible from here
|
||||||
|
obj.<!INVISIBLE_REFERENCE!>getName<!>()
|
||||||
|
|
||||||
|
OverridenGetterTest().usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
class OverridenGetterTest : ClassLevelGetterTest() {
|
||||||
|
fun usage() {
|
||||||
|
getName()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// FILE: ClassLevelGetterTest.java
|
// FILE: ClassLevelGetterTest.java
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// FILE: SetterTest.java
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
public class SetterTest {
|
||||||
|
@Getter @Setter private int age = 10;
|
||||||
|
|
||||||
|
@Setter(AccessLevel.PROTECTED) private String name;
|
||||||
|
|
||||||
|
@Setter private boolean primitiveBoolean;
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
setAge(12);
|
||||||
|
setPrimitiveBoolean(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val obj = SetterTest()
|
||||||
|
obj.setAge(42)
|
||||||
|
obj.age = 42
|
||||||
|
|
||||||
|
//synthetic property generated only when there is a getter
|
||||||
|
obj.<!INVISIBLE_REFERENCE!>primitiveBoolean<!> = false
|
||||||
|
obj.setPrimitiveBoolean(true)
|
||||||
|
|
||||||
|
//shouldn't be accesible from here
|
||||||
|
obj.<!INVISIBLE_REFERENCE!>setName<!>("abc")
|
||||||
|
|
||||||
|
OverridenGetterTest().usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
class OverridenGetterTest : SetterTest() {
|
||||||
|
fun usage() {
|
||||||
|
setName("abc")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// FILE: SetterTest.java
|
// FILE: SetterTest.java
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
|||||||
Generated
+1
-1
@@ -27,7 +27,7 @@ public class DiagnosticTestForLombokGenerated extends AbstractDiagnosticTestForL
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAllFilesPresentInDiagnostics() throws Exception {
|
public void testAllFilesPresentInDiagnostics() throws Exception {
|
||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/lombok/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/lombok/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Generated
+165
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* 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.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("plugins/lombok/testData/box")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class FirBlackBoxCodegenTestForLombokGenerated extends AbstractFirBlackBoxCodegenTestForLombok {
|
||||||
|
@Test
|
||||||
|
@TestMetadata("accessorsStripPrefix.kt")
|
||||||
|
public void testAccessorsStripPrefix() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/accessorsStripPrefix.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("accessorsStripPrefixConfig.kt")
|
||||||
|
public void testAccessorsStripPrefixConfig() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/accessorsStripPrefixConfig.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("allArgsConstructor.kt")
|
||||||
|
public void testAllArgsConstructor() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/allArgsConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("allArgsConstructorStatic.kt")
|
||||||
|
public void testAllArgsConstructorStatic() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/allArgsConstructorStatic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInBox() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/lombok/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("configAccessors.kt")
|
||||||
|
public void testConfigAccessors() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/configAccessors.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("configAccessorsOverride.kt")
|
||||||
|
public void testConfigAccessorsOverride() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/configAccessorsOverride.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("configCaseInsensitive.kt")
|
||||||
|
public void testConfigCaseInsensitive() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/configCaseInsensitive.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("configSimple.kt")
|
||||||
|
public void testConfigSimple() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/configSimple.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("data.kt")
|
||||||
|
public void testData() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/data.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("genericsAccessors.kt")
|
||||||
|
public void testGenericsAccessors() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/genericsAccessors.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("genericsConstructors.kt")
|
||||||
|
public void testGenericsConstructors() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/genericsConstructors.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("genericsConstructorsStatic.kt")
|
||||||
|
public void testGenericsConstructorsStatic() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/genericsConstructorsStatic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("gettersFluent.kt")
|
||||||
|
public void testGettersFluent() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/gettersFluent.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("noArgsConstructor.kt")
|
||||||
|
public void testNoArgsConstructor() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/noArgsConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("noArgsConstructorStatic.kt")
|
||||||
|
public void testNoArgsConstructorStatic() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/noArgsConstructorStatic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nullability.kt")
|
||||||
|
public void testNullability() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/nullability.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("propertyFromSuper.kt")
|
||||||
|
public void testPropertyFromSuper() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/propertyFromSuper.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("requiredArgsConstructor.kt")
|
||||||
|
public void testRequiredArgsConstructor() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/requiredArgsConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("requiredArgsConstructorStatic.kt")
|
||||||
|
public void testRequiredArgsConstructorStatic() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/requiredArgsConstructorStatic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("settersVariations.kt")
|
||||||
|
public void testSettersVariations() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/settersVariations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/simple.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("value.kt")
|
||||||
|
public void testValue() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/value.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("with.kt")
|
||||||
|
public void testWith() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/with.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+68
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("plugins/lombok/testData/diagnostics")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class FirDiagnosticTestForLombokGenerated extends AbstractFirDiagnosticTestForLombok {
|
||||||
|
@Test
|
||||||
|
@TestMetadata("accessorsStripPrefixCombined.kt")
|
||||||
|
public void testAccessorsStripPrefixCombined() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/diagnostics/accessorsStripPrefixCombined.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDiagnostics() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/lombok/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("annotationTypes.kt")
|
||||||
|
public void testAnnotationTypes() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/diagnostics/annotationTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("clashAccessors.kt")
|
||||||
|
public void testClashAccessors() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/diagnostics/clashAccessors.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("getters.kt")
|
||||||
|
public void testGetters() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/diagnostics/getters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("gettersClassLevel.kt")
|
||||||
|
public void testGettersClassLevel() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/diagnostics/gettersClassLevel.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("setters.kt")
|
||||||
|
public void testSetters() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/diagnostics/setters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("settersClassLevel.kt")
|
||||||
|
public void testSettersClassLevel() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/diagnostics/settersClassLevel.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,8 +14,11 @@ import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
|
|||||||
import org.jetbrains.kotlin.test.model.TestFile
|
import org.jetbrains.kotlin.test.model.TestFile
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
import org.jetbrains.kotlin.test.runners.AbstractDiagnosticTest
|
import org.jetbrains.kotlin.test.runners.AbstractDiagnosticTest
|
||||||
|
import org.jetbrains.kotlin.test.runners.AbstractFirDiagnosticTest
|
||||||
import org.jetbrains.kotlin.test.runners.codegen.AbstractBlackBoxCodegenTest
|
import org.jetbrains.kotlin.test.runners.codegen.AbstractBlackBoxCodegenTest
|
||||||
|
import org.jetbrains.kotlin.test.runners.codegen.AbstractFirBlackBoxCodegenTest
|
||||||
import org.jetbrains.kotlin.test.runners.codegen.AbstractIrBlackBoxCodegenTest
|
import org.jetbrains.kotlin.test.runners.codegen.AbstractIrBlackBoxCodegenTest
|
||||||
|
import org.jetbrains.kotlin.test.runners.configurationForClassicAndFirTestsAlongside
|
||||||
import org.jetbrains.kotlin.test.services.*
|
import org.jetbrains.kotlin.test.services.*
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -36,6 +39,13 @@ open class AbstractIrBlackBoxCodegenTestForLombok : AbstractIrBlackBoxCodegenTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open class AbstractFirBlackBoxCodegenTestForLombok : AbstractFirBlackBoxCodegenTest() {
|
||||||
|
override fun configure(builder: TestConfigurationBuilder) {
|
||||||
|
super.configure(builder)
|
||||||
|
builder.enableLombok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------- diagnostics ----------------------------
|
// ---------------------------- diagnostics ----------------------------
|
||||||
|
|
||||||
open class AbstractDiagnosticTestForLombok : AbstractDiagnosticTest() {
|
open class AbstractDiagnosticTestForLombok : AbstractDiagnosticTest() {
|
||||||
@@ -45,6 +55,14 @@ open class AbstractDiagnosticTestForLombok : AbstractDiagnosticTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open class AbstractFirDiagnosticTestForLombok : AbstractFirDiagnosticTest() {
|
||||||
|
override fun configure(builder: TestConfigurationBuilder) {
|
||||||
|
super.configure(builder)
|
||||||
|
builder.configurationForClassicAndFirTestsAlongside()
|
||||||
|
builder.enableLombok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------- configuration ----------------------------
|
// ---------------------------- configuration ----------------------------
|
||||||
|
|
||||||
fun TestConfigurationBuilder.enableLombok() {
|
fun TestConfigurationBuilder.enableLombok() {
|
||||||
|
|||||||
@@ -355,6 +355,7 @@ include ":plugins:parcelize:parcelize-compiler",
|
|||||||
include ":kotlin-lombok-compiler-plugin",
|
include ":kotlin-lombok-compiler-plugin",
|
||||||
":kotlin-lombok-compiler-plugin.common",
|
":kotlin-lombok-compiler-plugin.common",
|
||||||
":kotlin-lombok-compiler-plugin.k1",
|
":kotlin-lombok-compiler-plugin.k1",
|
||||||
|
":kotlin-lombok-compiler-plugin.k2",
|
||||||
":kotlin-lombok-compiler-plugin.cli",
|
":kotlin-lombok-compiler-plugin.cli",
|
||||||
":kotlin-lombok"
|
":kotlin-lombok"
|
||||||
|
|
||||||
@@ -699,6 +700,7 @@ project(':kotlin-allopen-compiler-plugin.k2').projectDir = "$rootDir/plugins/all
|
|||||||
project(':kotlin-lombok-compiler-plugin').projectDir = "$rootDir/plugins/lombok" as File
|
project(':kotlin-lombok-compiler-plugin').projectDir = "$rootDir/plugins/lombok" as File
|
||||||
project(':kotlin-lombok-compiler-plugin.cli').projectDir = "$rootDir/plugins/lombok/lombok.cli" as File
|
project(':kotlin-lombok-compiler-plugin.cli').projectDir = "$rootDir/plugins/lombok/lombok.cli" as File
|
||||||
project(':kotlin-lombok-compiler-plugin.k1').projectDir = "$rootDir/plugins/lombok/lombok.k1" as File
|
project(':kotlin-lombok-compiler-plugin.k1').projectDir = "$rootDir/plugins/lombok/lombok.k1" as File
|
||||||
|
project(':kotlin-lombok-compiler-plugin.k2').projectDir = "$rootDir/plugins/lombok/lombok.k2" as File
|
||||||
project(':kotlin-lombok-compiler-plugin.common').projectDir = "$rootDir/plugins/lombok/lombok.common" as File
|
project(':kotlin-lombok-compiler-plugin.common').projectDir = "$rootDir/plugins/lombok/lombok.common" as File
|
||||||
|
|
||||||
project(':kotlin-noarg-compiler-plugin').projectDir = "$rootDir/plugins/noarg" as File
|
project(':kotlin-noarg-compiler-plugin').projectDir = "$rootDir/plugins/noarg" as File
|
||||||
|
|||||||
Reference in New Issue
Block a user