[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)
|
[~] [@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor](https://projectlombok.org/features/constructor)
|
||||||
- [x] @NoArgsConstructor
|
- [x] @NoArgsConstructor
|
||||||
- [x] @AllArgsConstructor
|
- [x] @AllArgsConstructor
|
||||||
- [ ] @RequiredArgsConstructor
|
- [x] @RequiredArgsConstructor
|
||||||
|
|
||||||
[ ] [@Data](https://projectlombok.org/features/Data)
|
[ ] [@Data](https://projectlombok.org/features/Data)
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -26,7 +26,8 @@ class LombokSyntheticJavaPartsProvider(private val config: LombokConfig) : Synth
|
|||||||
SetterProcessor(config),
|
SetterProcessor(config),
|
||||||
WithProcessor(config),
|
WithProcessor(config),
|
||||||
NoArgsConstructorProcessor(),
|
NoArgsConstructorProcessor(),
|
||||||
AllArgsConstructorProcessor()
|
AllArgsConstructorProcessor(),
|
||||||
|
RequiredArgsConstructorProcessor()
|
||||||
)
|
)
|
||||||
|
|
||||||
private val partsCache: MutableMap<ClassDescriptor, Parts> = WeakHashMap()
|
private val partsCache: MutableMap<ClassDescriptor, Parts> = WeakHashMap()
|
||||||
|
|||||||
+28
-8
@@ -72,31 +72,51 @@ data class With(val visibility: DescriptorVisibility) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class NoArgsConstructor(
|
interface ConstructorAnnotation {
|
||||||
val visibility: DescriptorVisibility,
|
val visibility: DescriptorVisibility
|
||||||
val staticName: String?
|
val staticName: String?
|
||||||
) {
|
}
|
||||||
|
|
||||||
|
data class NoArgsConstructor(
|
||||||
|
override val visibility: DescriptorVisibility,
|
||||||
|
override val staticName: String?
|
||||||
|
) : ConstructorAnnotation {
|
||||||
companion object : AnnotationCompanion<NoArgsConstructor>() {
|
companion object : AnnotationCompanion<NoArgsConstructor>() {
|
||||||
override val name: FqName = LombokNames.NO_ARGS_CONSTRUCTOR
|
override val name: FqName = LombokNames.NO_ARGS_CONSTRUCTOR
|
||||||
|
|
||||||
override fun extract(annotation: AnnotationDescriptor): NoArgsConstructor =
|
override fun extract(annotation: AnnotationDescriptor): NoArgsConstructor =
|
||||||
NoArgsConstructor(
|
NoArgsConstructor(
|
||||||
visibility = getVisibility(annotation),
|
visibility = getVisibility(annotation, "access"),
|
||||||
staticName = annotation.getNonBlankStringArgument("staticName")
|
staticName = annotation.getNonBlankStringArgument("staticName")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AllArgsConstructor(
|
data class AllArgsConstructor(
|
||||||
val visibility: DescriptorVisibility,
|
override val visibility: DescriptorVisibility,
|
||||||
val staticName: String?
|
override val staticName: String?
|
||||||
) {
|
) : ConstructorAnnotation {
|
||||||
companion object : AnnotationCompanion<AllArgsConstructor>() {
|
companion object : AnnotationCompanion<AllArgsConstructor>() {
|
||||||
override val name: FqName = LombokNames.ALL_ARGS_CONSTRUCTOR
|
override val name: FqName = LombokNames.ALL_ARGS_CONSTRUCTOR
|
||||||
|
|
||||||
override fun extract(annotation: AnnotationDescriptor): AllArgsConstructor =
|
override fun extract(annotation: AnnotationDescriptor): AllArgsConstructor =
|
||||||
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")
|
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
|
package org.jetbrains.kotlin.lombok.processor
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
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.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.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 {
|
override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor> = classDescriptor.getJavaFields()
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-27
@@ -6,34 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.lombok.processor
|
package org.jetbrains.kotlin.lombok.processor
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
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.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 {
|
class NoArgsConstructorProcessor : AbstractConstructorProcessor<NoArgsConstructor>(NoArgsConstructor) {
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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 GETTER = FqName("lombok.Getter")
|
||||||
val SETTER = FqName("lombok.Setter")
|
val SETTER = FqName("lombok.Setter")
|
||||||
val WITH = FqName("lombok.With")
|
val WITH = FqName("lombok.With")
|
||||||
|
val VALUE = FqName("lombok.lombok.Value")
|
||||||
val NO_ARGS_CONSTRUCTOR = FqName("lombok.NoArgsConstructor")
|
val NO_ARGS_CONSTRUCTOR = FqName("lombok.NoArgsConstructor")
|
||||||
val ALL_ARGS_CONSTRUCTOR = FqName("lombok.AllArgsConstructor")
|
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");
|
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")
|
@TestMetadata("getters.kt")
|
||||||
public void testGetters() throws Exception {
|
public void testGetters() throws Exception {
|
||||||
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/getters.kt");
|
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/getters.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user