[lombok] IDEA-313149 Fix renaming class fields for Lombok Builder with custom prefix

GitOrigin-RevId: c9e91009dcef823a0bf1c233ebcb5e3cd901240d
This commit is contained in:
Michail Plushnikov
2023-09-03 17:22:31 +02:00
committed by intellij-monorepo-bot
parent 247cef0f82
commit c6effba899
7 changed files with 96 additions and 19 deletions

View File

@@ -5,6 +5,7 @@ import com.intellij.refactoring.rename.RenameJavaVariableProcessor;
import com.intellij.util.containers.ContainerUtil;
import de.plushnikov.intellij.plugin.LombokClassNames;
import de.plushnikov.intellij.plugin.processor.field.AccessorsInfo;
import de.plushnikov.intellij.plugin.processor.handler.BuilderHandler;
import de.plushnikov.intellij.plugin.processor.handler.singular.BuilderElementHandler;
import de.plushnikov.intellij.plugin.processor.handler.singular.SingularHandlerFactory;
import de.plushnikov.intellij.plugin.psi.LombokLightClassBuilder;
@@ -12,6 +13,7 @@ import de.plushnikov.intellij.plugin.psi.LombokLightFieldBuilder;
import de.plushnikov.intellij.plugin.psi.LombokLightMethodBuilder;
import de.plushnikov.intellij.plugin.thirdparty.LombokUtils;
import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil;
import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
@@ -23,10 +25,10 @@ public class LombokRenameFieldReferenceProcessor extends RenameJavaVariableProce
@Override
public boolean canProcessElement(@NotNull PsiElement element) {
if (element instanceof PsiField && !(element instanceof LombokLightFieldBuilder)) {
final PsiClass containingClass = ((PsiField) element).getContainingClass();
final PsiClass containingClass = ((PsiField)element).getContainingClass();
if (null != containingClass) {
return ContainerUtil.exists(containingClass.getMethods(), LombokLightMethodBuilder.class::isInstance) ||
ContainerUtil.exists(containingClass.getInnerClasses(), LombokLightClassBuilder.class::isInstance);
ContainerUtil.exists(containingClass.getInnerClasses(), LombokLightClassBuilder.class::isInstance);
}
}
return false;
@@ -34,7 +36,7 @@ public class LombokRenameFieldReferenceProcessor extends RenameJavaVariableProce
@Override
public void prepareRenaming(@NotNull PsiElement element, @NotNull String newFieldName, @NotNull Map<PsiElement, String> allRenames) {
final PsiField psiField = (PsiField) element;
final PsiField psiField = (PsiField)element;
final PsiClass containingClass = psiField.getContainingClass();
final String currentFieldName = psiField.getName();
if (null != containingClass) {
@@ -62,12 +64,23 @@ public class LombokRenameFieldReferenceProcessor extends RenameJavaVariableProce
}
}
final PsiAnnotation builderAnnotation = PsiAnnotationSearchUtil.findAnnotation(containingClass, LombokClassNames.BUILDER, LombokClassNames.SUPER_BUILDER);
final PsiAnnotation builderAnnotation =
PsiAnnotationSearchUtil.findAnnotation(containingClass, LombokClassNames.BUILDER, LombokClassNames.SUPER_BUILDER);
if (null != builderAnnotation) {
final PsiAnnotation singularAnnotation = PsiAnnotationSearchUtil.findAnnotation(psiField, LombokClassNames.SINGULAR);
final BuilderElementHandler handler = SingularHandlerFactory.getHandlerFor(psiField, null!=singularAnnotation);
final List<String> currentBuilderMethodNames = handler.getBuilderMethodNames(accessorsInfo.removePrefix(currentFieldName), singularAnnotation, accessorsInfo.getCapitalizationStrategy());
final List<String> newBuilderMethodNames = handler.getBuilderMethodNames(accessorsInfo.removePrefix(newFieldName), singularAnnotation, accessorsInfo.getCapitalizationStrategy());
final BuilderElementHandler handler = SingularHandlerFactory.getHandlerFor(psiField, null != singularAnnotation);
final String setterPrefix =
PsiAnnotationUtil.getStringAnnotationValue(builderAnnotation, BuilderHandler.ANNOTATION_SETTER_PREFIX, "");
final List<String> currentBuilderMethodNames = handler.getBuilderMethodNames(accessorsInfo.removePrefix(currentFieldName),
setterPrefix,
singularAnnotation,
accessorsInfo.getCapitalizationStrategy());
final List<String> newBuilderMethodNames = handler.getBuilderMethodNames(accessorsInfo.removePrefix(newFieldName),
setterPrefix,
singularAnnotation,
accessorsInfo.getCapitalizationStrategy());
if (currentBuilderMethodNames.size() == newBuilderMethodNames.size()) {
Arrays.stream(containingClass.getInnerClasses())
@@ -84,7 +97,8 @@ public class LombokRenameFieldReferenceProcessor extends RenameJavaVariableProce
}
}
final boolean hasFieldNameConstantAnnotation = PsiAnnotationSearchUtil.isAnnotatedWith(containingClass, LombokClassNames.FIELD_NAME_CONSTANTS);
final boolean hasFieldNameConstantAnnotation =
PsiAnnotationSearchUtil.isAnnotatedWith(containingClass, LombokClassNames.FIELD_NAME_CONSTANTS);
if (hasFieldNameConstantAnnotation) {
Arrays.stream(containingClass.getInnerClasses())
.map(PsiClass::getFields)
@@ -95,5 +109,4 @@ public class LombokRenameFieldReferenceProcessor extends RenameJavaVariableProce
}
}
}
}

View File

@@ -47,7 +47,7 @@ public class BuilderHandler {
private final static String ANNOTATION_BUILDER_CLASS_NAME = "builderClassName";
private static final String ANNOTATION_BUILD_METHOD_NAME = "buildMethodName";
private static final String ANNOTATION_BUILDER_METHOD_NAME = "builderMethodName";
private static final String ANNOTATION_SETTER_PREFIX = "setterPrefix";
public static final String ANNOTATION_SETTER_PREFIX = "setterPrefix";
private final static String BUILD_METHOD_NAME = "build";
private final static String BUILDER_METHOD_NAME = "builder";

View File

@@ -119,10 +119,11 @@ public abstract class AbstractSingularHandler implements BuilderElementHandler {
}
@Override
public List<String> getBuilderMethodNames(@NotNull String fieldName, @Nullable PsiAnnotation singularAnnotation,
public List<String> getBuilderMethodNames(@NotNull String fieldName, @NotNull String prefix, @Nullable PsiAnnotation singularAnnotation,
CapitalizationStrategy capitalizationStrategy) {
return Arrays.asList(createSingularName(singularAnnotation, fieldName),
fieldName,
final String accessorName = LombokUtils.buildAccessorName(prefix, fieldName, capitalizationStrategy);
return Arrays.asList(createSingularName(singularAnnotation, accessorName),
accessorName,
createSingularClearMethodName(fieldName, capitalizationStrategy));
}

View File

@@ -45,6 +45,6 @@ public interface BuilderElementHandler {
Collection<PsiMethod> renderBuilderMethod(@NotNull BuilderInfo info);
List<String> getBuilderMethodNames(@NotNull String newName, @Nullable PsiAnnotation singularAnnotation,
CapitalizationStrategy capitalizationStrategy);
List<String> getBuilderMethodNames(@NotNull String fieldName, @NotNull String prefix,
@Nullable PsiAnnotation singularAnnotation, CapitalizationStrategy capitalizationStrategy);
}

View File

@@ -30,8 +30,8 @@ class EmptyBuilderElementHandler implements BuilderElementHandler {
}
@Override
public List<String> getBuilderMethodNames(@NotNull String newName, @Nullable PsiAnnotation singularAnnotation,
CapitalizationStrategy capitalizationStrategy) {
public List<String> getBuilderMethodNames(@NotNull String fieldName, @NotNull String prefix,
@Nullable PsiAnnotation singularAnnotation, CapitalizationStrategy capitalizationStrategy) {
return Collections.emptyList();
}

View File

@@ -6,6 +6,7 @@ import de.plushnikov.intellij.plugin.psi.LombokLightFieldBuilder;
import de.plushnikov.intellij.plugin.psi.LombokLightMethodBuilder;
import de.plushnikov.intellij.plugin.thirdparty.CapitalizationStrategy;
import de.plushnikov.intellij.plugin.thirdparty.LombokCopyableAnnotations;
import de.plushnikov.intellij.plugin.thirdparty.LombokUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -59,9 +60,9 @@ class NonSingularHandler implements BuilderElementHandler {
}
@Override
public List<String> getBuilderMethodNames(@NotNull String newName, @Nullable PsiAnnotation singularAnnotation,
public List<String> getBuilderMethodNames(@NotNull String fieldName, @NotNull String prefix, @Nullable PsiAnnotation singularAnnotation,
CapitalizationStrategy capitalizationStrategy) {
return Collections.singletonList(newName);
return Collections.singletonList(LombokUtils.buildAccessorName(prefix, fieldName, capitalizationStrategy));
}
@Override

View File

@@ -0,0 +1,62 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.lomboktest;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import de.plushnikov.intellij.plugin.LombokTestUtil;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
public class LombokRenameTest extends LightJavaCodeInsightFixtureTestCase {
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return LombokTestUtil.LOMBOK_NEW_DESCRIPTOR;
}
public void testLombokRenameFieldInBuilderWithPrefix() {
final @Language("JAVA") String testFileData = """
import lombok.Builder;
import lombok.Data;
import lombok.Singular;
import java.util.List;
@Data
@Builder(setterPrefix = "with")
public class App {
private String firmPartyGfcId<caret>;
@Singular
private List<String> someStrValues;
public static App doSomething() {
return App.builder()
.withFirmPartyGfcId("firm_party_gfcid")
.withSomeStrValue("someValue")
.withSomeStrValues(List.of("xyz"))
.clearSomeStrValues()
.build();
}
public static void main(String[] args) {
}
}""";
myFixture.configureByText(JavaFileType.INSTANCE, testFileData);
myFixture.renameElementAtCaret("firmPartyGfcId_NewName");
final PsiClass appBuilderClass = myFixture.findClass("App.AppBuilder");
assertEquals(1, appBuilderClass.findMethodsByName("withFirmPartyGfcId_NewName", false).length);
final PsiMethod doSomethingMethod = appBuilderClass.getContainingClass().findMethodsByName("doSomething", false)[0];
assertTrue(doSomethingMethod.getBody().getText().contains("withFirmPartyGfcId_NewName(\"firm_party_gfcid\")"));
}
}