[Lombok] Constructor can have only non-final or not initialized fields
When using the AllArgsConstructor annotation (directly or via meta-annotation), only fields that are not final or not initialized should be added as arguments. Previously, all fields were being included regardless of modality or initialization, which is not consistent with the behavior of Lombok. ^KT-54054 Fixed
This commit is contained in:
+10
-1
@@ -5,11 +5,14 @@
|
||||
|
||||
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.LombokAnnotations.AllArgsConstructor
|
||||
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Value
|
||||
import org.jetbrains.kotlin.lombok.utils.getJavaFields
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
|
||||
class AllArgsConstructorProcessor : AbstractConstructorProcessor<AllArgsConstructor>() {
|
||||
|
||||
@@ -17,6 +20,12 @@ class AllArgsConstructorProcessor : AbstractConstructorProcessor<AllArgsConstruc
|
||||
AllArgsConstructor.getOrNull(classDescriptor) ?: Value.getOrNull(classDescriptor)?.asAllArgsConstructor()
|
||||
|
||||
override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor> =
|
||||
classDescriptor.getJavaFields()
|
||||
classDescriptor.getJavaFields().filter(this::isFieldAllowed)
|
||||
|
||||
private fun isFieldAllowed(field: PropertyDescriptor): Boolean {
|
||||
val psi = field.source.getPsi() as? PsiField ?: return true
|
||||
|
||||
val final = psi.modifierList?.hasModifierProperty(PsiModifier.FINAL) ?: false
|
||||
return !final || !psi.hasInitializer()
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -5,11 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.lombok.k2.generators
|
||||
|
||||
import com.intellij.psi.PsiField
|
||||
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
|
||||
import org.jetbrains.kotlin.psi
|
||||
|
||||
class AllArgsConstructorGeneratorPart(session: FirSession) : AbstractConstructorGeneratorPart<AllArgsConstructor>(session) {
|
||||
override fun getConstructorInfo(classSymbol: FirClassSymbol<*>): AllArgsConstructor? {
|
||||
@@ -19,6 +21,14 @@ class AllArgsConstructorGeneratorPart(session: FirSession) : AbstractConstructor
|
||||
|
||||
@OptIn(SymbolInternals::class)
|
||||
override fun getFieldsForParameters(classSymbol: FirClassSymbol<*>): List<FirJavaField> {
|
||||
return classSymbol.fir.declarations.filterIsInstance<FirJavaField>()
|
||||
return classSymbol.fir.declarations
|
||||
.filterIsInstance<FirJavaField>()
|
||||
.filter { it.isFieldAllowed() }
|
||||
}
|
||||
|
||||
private fun FirJavaField.isFieldAllowed(): Boolean {
|
||||
// TODO: consider adding `hasInitializer` property directly to java model
|
||||
val hasInitializer = (source?.psi as? PsiField)?.hasInitializer() ?: false
|
||||
return isVar || !hasInitializer
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -5,11 +5,17 @@ import lombok.*;
|
||||
@AllArgsConstructor
|
||||
public class ConstructorExample {
|
||||
|
||||
// Part of constructor because not final.
|
||||
@Getter @Setter private int age = 10;
|
||||
|
||||
// Part of constructor because not initialized.
|
||||
@Getter(AccessLevel.PROTECTED) private String name;
|
||||
|
||||
private boolean otherField;
|
||||
// Part of constructor because not initialized.
|
||||
private final boolean otherField;
|
||||
|
||||
// Not part of constructor because final and initialized.
|
||||
@Getter private final String result = "OK";
|
||||
|
||||
static void javaUsage() {
|
||||
val generated = new ConstructorExample(12, "sdf", true);
|
||||
@@ -21,5 +27,5 @@ public class ConstructorExample {
|
||||
|
||||
fun box(): String {
|
||||
val generated = ConstructorExample(12, "sdf", true)
|
||||
return "OK"
|
||||
return generated.getResult()
|
||||
}
|
||||
|
||||
+7
-1
@@ -5,12 +5,18 @@ import lombok.*;
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
public class ConstructorExample {
|
||||
|
||||
// Part of constructor because not final.
|
||||
@Getter @Setter private int age = 10;
|
||||
|
||||
// Part of constructor because not initialized.
|
||||
@Getter(AccessLevel.PROTECTED) private String name;
|
||||
|
||||
// Part of constructor because not initialized.
|
||||
private boolean otherField;
|
||||
|
||||
// Not part of constructor because final and initialized.
|
||||
@Getter private final String result = "OK";
|
||||
|
||||
public ConstructorExample(String arg) {
|
||||
|
||||
}
|
||||
@@ -27,5 +33,5 @@ public class ConstructorExample {
|
||||
fun box(): String {
|
||||
val existing: ConstructorExample = ConstructorExample("existing")
|
||||
val generated: ConstructorExample = ConstructorExample.of(45, "234", false)
|
||||
return "OK"
|
||||
return generated.getResult()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user