[lombok] Support @RequiredArgsConstructor
This commit is contained in:
committed by
TeamCityServer
parent
b336a335bf
commit
afcb2ca904
@@ -26,7 +26,7 @@ Features support:
|
||||
[~] [@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor](https://projectlombok.org/features/constructor)
|
||||
- [x] @NoArgsConstructor
|
||||
- [x] @AllArgsConstructor
|
||||
- [ ] @RequiredArgsConstructor
|
||||
- [x] @RequiredArgsConstructor
|
||||
|
||||
[ ] [@Data](https://projectlombok.org/features/Data)
|
||||
|
||||
|
||||
+2
-1
@@ -26,7 +26,8 @@ class LombokSyntheticJavaPartsProvider(private val config: LombokConfig) : Synth
|
||||
SetterProcessor(config),
|
||||
WithProcessor(config),
|
||||
NoArgsConstructorProcessor(),
|
||||
AllArgsConstructorProcessor()
|
||||
AllArgsConstructorProcessor(),
|
||||
RequiredArgsConstructorProcessor()
|
||||
)
|
||||
|
||||
private val partsCache: MutableMap<ClassDescriptor, Parts> = WeakHashMap()
|
||||
|
||||
+28
-8
@@ -72,31 +72,51 @@ data class With(val visibility: DescriptorVisibility) {
|
||||
}
|
||||
}
|
||||
|
||||
data class NoArgsConstructor(
|
||||
val visibility: DescriptorVisibility,
|
||||
interface ConstructorAnnotation {
|
||||
val visibility: DescriptorVisibility
|
||||
val staticName: String?
|
||||
) {
|
||||
}
|
||||
|
||||
data class NoArgsConstructor(
|
||||
override val visibility: DescriptorVisibility,
|
||||
override val staticName: String?
|
||||
) : ConstructorAnnotation {
|
||||
companion object : AnnotationCompanion<NoArgsConstructor>() {
|
||||
override val name: FqName = LombokNames.NO_ARGS_CONSTRUCTOR
|
||||
|
||||
override fun extract(annotation: AnnotationDescriptor): NoArgsConstructor =
|
||||
NoArgsConstructor(
|
||||
visibility = getVisibility(annotation),
|
||||
visibility = getVisibility(annotation, "access"),
|
||||
staticName = annotation.getNonBlankStringArgument("staticName")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class AllArgsConstructor(
|
||||
val visibility: DescriptorVisibility,
|
||||
val staticName: String?
|
||||
) {
|
||||
override val visibility: DescriptorVisibility,
|
||||
override val staticName: String?
|
||||
) : ConstructorAnnotation {
|
||||
companion object : AnnotationCompanion<AllArgsConstructor>() {
|
||||
override val name: FqName = LombokNames.ALL_ARGS_CONSTRUCTOR
|
||||
|
||||
override fun extract(annotation: AnnotationDescriptor): AllArgsConstructor =
|
||||
AllArgsConstructor(
|
||||
visibility = getVisibility(annotation),
|
||||
visibility = getVisibility(annotation, "access"),
|
||||
staticName = annotation.getNonBlankStringArgument("staticName")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class RequiredArgsConstructor(
|
||||
override val visibility: DescriptorVisibility,
|
||||
override val staticName: String?
|
||||
) : ConstructorAnnotation {
|
||||
companion object : AnnotationCompanion<RequiredArgsConstructor>() {
|
||||
override val name: FqName = LombokNames.REQUIRED_ARGS_CONSTRUCTOR
|
||||
|
||||
override fun extract(annotation: AnnotationDescriptor): RequiredArgsConstructor =
|
||||
RequiredArgsConstructor(
|
||||
visibility = getVisibility(annotation, "access"),
|
||||
staticName = annotation.getNonBlankStringArgument("staticName")
|
||||
)
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.processor
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
|
||||
import org.jetbrains.kotlin.lombok.config.AllArgsConstructor
|
||||
import org.jetbrains.kotlin.lombok.config.AnnotationCompanion
|
||||
import org.jetbrains.kotlin.lombok.config.ConstructorAnnotation
|
||||
import org.jetbrains.kotlin.lombok.utils.ValueParameter
|
||||
import org.jetbrains.kotlin.lombok.utils.createConstructor
|
||||
import org.jetbrains.kotlin.lombok.utils.createFunction
|
||||
import org.jetbrains.kotlin.lombok.utils.getJavaFields
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class AbstractConstructorProcessor<A : ConstructorAnnotation>(
|
||||
private val annotationCompanion: AnnotationCompanion<A>
|
||||
) : Processor {
|
||||
|
||||
override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts {
|
||||
val valueParameters = getPropertiesForParameters(classDescriptor).map { property ->
|
||||
ValueParameter(property.name, property.type)
|
||||
}
|
||||
|
||||
val result = annotationCompanion.getOrNull(classDescriptor)?.let { annotation ->
|
||||
if (annotation.staticName == null) {
|
||||
val constructor = classDescriptor.createConstructor(
|
||||
valueParameters = valueParameters,
|
||||
visibility = annotation.visibility
|
||||
)
|
||||
Parts(constructors = listOfNotNull(constructor))
|
||||
} else {
|
||||
val function = classDescriptor.createFunction(
|
||||
Name.identifier(annotation.staticName!!),
|
||||
valueParameters,
|
||||
classDescriptor.defaultType,
|
||||
visibility = annotation.visibility,
|
||||
receiver = null
|
||||
)
|
||||
Parts(staticFunctions = listOf(function))
|
||||
}
|
||||
}
|
||||
return result ?: Parts.Empty
|
||||
}
|
||||
|
||||
protected abstract fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor>
|
||||
|
||||
|
||||
}
|
||||
+3
-32
@@ -6,41 +6,12 @@
|
||||
package org.jetbrains.kotlin.lombok.processor
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.lombok.config.AllArgsConstructor
|
||||
import org.jetbrains.kotlin.lombok.utils.ValueParameter
|
||||
import org.jetbrains.kotlin.lombok.utils.createConstructor
|
||||
import org.jetbrains.kotlin.lombok.utils.createFunction
|
||||
import org.jetbrains.kotlin.lombok.utils.getJavaFields
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class AllArgsConstructorProcessor : Processor {
|
||||
class AllArgsConstructorProcessor : AbstractConstructorProcessor<AllArgsConstructor>(AllArgsConstructor) {
|
||||
|
||||
override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts {
|
||||
|
||||
val valueParameters = classDescriptor.getJavaFields().map { property ->
|
||||
ValueParameter(property.name, property.type)
|
||||
}
|
||||
|
||||
val result = AllArgsConstructor.getOrNull(classDescriptor)?.let { annotation ->
|
||||
if (annotation.staticName == null) {
|
||||
val constructor = classDescriptor.createConstructor(
|
||||
valueParameters = valueParameters,
|
||||
visibility = annotation.visibility
|
||||
)
|
||||
Parts(constructors = listOfNotNull(constructor))
|
||||
} else {
|
||||
val function = classDescriptor.createFunction(
|
||||
Name.identifier(annotation.staticName),
|
||||
valueParameters,
|
||||
classDescriptor.defaultType,
|
||||
visibility = annotation.visibility,
|
||||
receiver = null
|
||||
)
|
||||
Parts(staticFunctions = listOf(function))
|
||||
}
|
||||
}
|
||||
return result ?: Parts.Empty
|
||||
}
|
||||
override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor> = classDescriptor.getJavaFields()
|
||||
|
||||
}
|
||||
|
||||
+3
-27
@@ -6,34 +6,10 @@
|
||||
package org.jetbrains.kotlin.lombok.processor
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.lombok.config.NoArgsConstructor
|
||||
import org.jetbrains.kotlin.lombok.utils.createConstructor
|
||||
import org.jetbrains.kotlin.lombok.utils.createFunction
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class NoArgsConstructorProcessor : Processor {
|
||||
|
||||
override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts {
|
||||
val result = NoArgsConstructor.getOrNull(classDescriptor)?.let { annotation ->
|
||||
if (annotation.staticName == null) {
|
||||
val constructor = classDescriptor.createConstructor(
|
||||
valueParameters = emptyList(),
|
||||
visibility = annotation.visibility
|
||||
)
|
||||
Parts(constructors = listOfNotNull(constructor))
|
||||
} else {
|
||||
val function = classDescriptor.createFunction(
|
||||
Name.identifier(annotation.staticName),
|
||||
emptyList(),
|
||||
classDescriptor.defaultType,
|
||||
visibility = annotation.visibility,
|
||||
receiver = null
|
||||
)
|
||||
Parts(staticFunctions = listOf(function))
|
||||
}
|
||||
}
|
||||
return result ?: Parts.Empty
|
||||
}
|
||||
class NoArgsConstructorProcessor : AbstractConstructorProcessor<NoArgsConstructor>(NoArgsConstructor) {
|
||||
|
||||
override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor> = emptyList()
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.processor
|
||||
|
||||
import com.intellij.psi.PsiField
|
||||
import com.intellij.psi.PsiModifier
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.lombok.config.RequiredArgsConstructor
|
||||
import org.jetbrains.kotlin.lombok.utils.LombokNames
|
||||
import org.jetbrains.kotlin.lombok.utils.getJavaFields
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
|
||||
class RequiredArgsConstructorProcessor : AbstractConstructorProcessor<RequiredArgsConstructor>(RequiredArgsConstructor) {
|
||||
|
||||
override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor> =
|
||||
classDescriptor.getJavaFields().filter(this::isFieldRequired)
|
||||
|
||||
private fun isFieldRequired(field: PropertyDescriptor): Boolean {
|
||||
val psi = field.source.getPsi()!! as PsiField
|
||||
|
||||
val final = psi.modifierList?.hasModifierProperty(PsiModifier.FINAL) ?: false ||
|
||||
field.annotations.any { annotation -> LombokNames.NON_NULL_ANNOTATIONS.contains(annotation.fqName) }
|
||||
|
||||
return final && !psi.hasInitializer()
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -13,7 +13,27 @@ object LombokNames {
|
||||
val GETTER = FqName("lombok.Getter")
|
||||
val SETTER = FqName("lombok.Setter")
|
||||
val WITH = FqName("lombok.With")
|
||||
val VALUE = FqName("lombok.lombok.Value")
|
||||
val NO_ARGS_CONSTRUCTOR = FqName("lombok.NoArgsConstructor")
|
||||
val ALL_ARGS_CONSTRUCTOR = FqName("lombok.AllArgsConstructor")
|
||||
val REQUIRED_ARGS_CONSTRUCTOR = FqName("lombok.RequiredArgsConstructor")
|
||||
|
||||
|
||||
//taken from idea lombok plugin
|
||||
val NON_NULL_ANNOTATIONS = listOf(
|
||||
"androidx.annotation.NonNull",
|
||||
"android.support.annotation.NonNull",
|
||||
"com.sun.istack.internal.NotNull",
|
||||
"edu.umd.cs.findbugs.annotations.NonNull",
|
||||
"javax.annotation.Nonnull",
|
||||
"lombok.NonNull",
|
||||
"org.checkerframework.checker.nullness.qual.NonNull",
|
||||
"org.eclipse.jdt.annotation.NonNull",
|
||||
"org.eclipse.jgit.annotations.NonNull",
|
||||
"org.jetbrains.annotations.NotNull",
|
||||
"org.jmlspecs.annotation.NonNull",
|
||||
"org.netbeans.api.annotations.common.NonNull",
|
||||
"org.springframework.lang.NonNull"
|
||||
).map { FqName(it) }.toSet()
|
||||
|
||||
}
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
//FILE: ConstructorExample.java
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ConstructorExample {
|
||||
|
||||
//not required
|
||||
@Getter @Setter private int age;
|
||||
|
||||
//required final
|
||||
@Getter @Setter private final String foo;
|
||||
|
||||
//not required final, because has initializer
|
||||
@Getter @Setter private final int bar = 234;
|
||||
|
||||
//not required
|
||||
@Getter(AccessLevel.PROTECTED) private String name;
|
||||
|
||||
//required by annotation
|
||||
@NonNull
|
||||
private boolean otherField;
|
||||
|
||||
//not required by annotation, because has initializer
|
||||
@NonNull
|
||||
private Long zzzz = 23L;
|
||||
|
||||
static void javaUsage() {
|
||||
ConstructorExample generated = new ConstructorExample("foo", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//FILE: test.kt
|
||||
|
||||
object Test {
|
||||
fun usage() {
|
||||
val generated = ConstructorExample("foo", true)
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
//FILE: ConstructorExample.java
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@RequiredArgsConstructor(staticName = "build")
|
||||
public class ConstructorExample {
|
||||
|
||||
//not required
|
||||
@Getter @Setter private int age;
|
||||
|
||||
//required final
|
||||
@Getter @Setter private final String foo;
|
||||
|
||||
//not required final, because has initializer
|
||||
@Getter @Setter private final int bar = 234;
|
||||
|
||||
//not required
|
||||
@Getter(AccessLevel.PROTECTED) private String name;
|
||||
|
||||
//required by annotation
|
||||
@NonNull
|
||||
private boolean otherField;
|
||||
|
||||
//not required by annotation, because has initializer
|
||||
@NonNull
|
||||
private Long zzzz = 23L;
|
||||
|
||||
@NonNull Integer somethingElse;
|
||||
|
||||
static void javaUsage() {
|
||||
ConstructorExample generated = ConstructorExample.build("foo", true, 12);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//FILE: test.kt
|
||||
|
||||
object Test {
|
||||
fun usage() {
|
||||
val generated = ConstructorExample.build("foo", true, 12)
|
||||
}
|
||||
}
|
||||
+10
@@ -66,6 +66,16 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest {
|
||||
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/noArgsConstructorStatic.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("requiredArgsConstructor.kt")
|
||||
public void testRequiredArgsConstructor() throws Exception {
|
||||
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/requiredArgsConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("requiredArgsConstructorStatic.kt")
|
||||
public void testRequiredArgsConstructorStatic() throws Exception {
|
||||
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/requiredArgsConstructorStatic.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("getters.kt")
|
||||
public void testGetters() throws Exception {
|
||||
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/getters.kt");
|
||||
|
||||
Reference in New Issue
Block a user