diff --git a/java/java-impl/resources/META-INF/JavaPlugin.xml b/java/java-impl/resources/META-INF/JavaPlugin.xml
index a162ff38780c..412a9cbeaf9b 100644
--- a/java/java-impl/resources/META-INF/JavaPlugin.xml
+++ b/java/java-impl/resources/META-INF/JavaPlugin.xml
@@ -106,6 +106,8 @@
+
diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/call/CallerMethodsTreeStructure.java b/java/java-impl/src/com/intellij/ide/hierarchy/call/CallerMethodsTreeStructure.java
index 2f870dfd7a0d..3deee1646f35 100644
--- a/java/java-impl/src/com/intellij/ide/hierarchy/call/CallerMethodsTreeStructure.java
+++ b/java/java-impl/src/com/intellij/ide/hierarchy/call/CallerMethodsTreeStructure.java
@@ -17,10 +17,8 @@ import com.intellij.util.ArrayUtilRt;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
+import java.util.stream.Stream;
public final class CallerMethodsTreeStructure extends HierarchyTreeStructure {
private final String myScopeType;
@@ -119,6 +117,11 @@ public final class CallerMethodsTreeStructure extends HierarchyTreeStructure {
}
return true;
});
+
+ // add other method elements without references
+ for (CallHierarchyElementProvider provider : CallHierarchyElementProvider.EP_NAME.getExtensionList()) {
+ provider.appendReferencedMethods(methodToFind, data);
+ }
}
return ArrayUtil.toObjectArray(methodToDescriptorMap.values());
@@ -127,9 +130,19 @@ public final class CallerMethodsTreeStructure extends HierarchyTreeStructure {
assert enclosingElement instanceof PsiField || enclosingElement instanceof PsiRecordComponent
: "Enclosing element should be a field, but was " + enclosingElement.getClass() + ", text: " + enclosingElement.getText();
- return ReferencesSearch
+ final Stream<@NotNull PsiElement> referencedElements = ReferencesSearch
.search(enclosingElement, searchScope).findAll().stream()
- .map(PsiReference::getElement)
+ .map(PsiReference::getElement);
+
+ // collect other field elements without references
+ Collection<@NotNull PsiElement> providedElements = new ArrayList<>();
+ for (CallHierarchyElementProvider provider : CallHierarchyElementProvider.EP_NAME.getExtensionList()) {
+ if(provider.canProvide(enclosingElement)) {
+ providedElements.addAll(provider.provideReferencedMembers(enclosingElement));
+ }
+ }
+
+ return Stream.concat(referencedElements, providedElements.stream())
.distinct()
.map(e -> new CallHierarchyNodeDescriptor(myProject, nodeDescriptor, e, false, false))
.filter(n -> n.getEnclosingElement() != null)
diff --git a/java/openapi/src/com/intellij/ide/hierarchy/call/CallHierarchyElementProvider.java b/java/openapi/src/com/intellij/ide/hierarchy/call/CallHierarchyElementProvider.java
new file mode 100644
index 000000000000..ea4eefce278f
--- /dev/null
+++ b/java/openapi/src/com/intellij/ide/hierarchy/call/CallHierarchyElementProvider.java
@@ -0,0 +1,22 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.intellij.ide.hierarchy.call;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMember;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.search.SearchScope;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public interface CallHierarchyElementProvider {
+ ExtensionPointName EP_NAME =
+ ExtensionPointName.create("com.intellij.hierarchy.elementProvider");
+
+ boolean canProvide(@NotNull PsiMember element);
+
+ Collection provideReferencedMembers(@NotNull PsiMember reference);
+
+ void appendReferencedMethods(@NotNull PsiMethod methodToFind, @NotNull JavaCallHierarchyData hierarchyData);
+}
diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/hierarchy/LombokFieldHierarchyElementProvider.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/hierarchy/LombokFieldHierarchyElementProvider.java
new file mode 100644
index 000000000000..bf4ec2160b7e
--- /dev/null
+++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/hierarchy/LombokFieldHierarchyElementProvider.java
@@ -0,0 +1,69 @@
+package de.plushnikov.intellij.plugin.hierarchy;
+
+import com.intellij.ide.hierarchy.call.CallHierarchyElementProvider;
+import com.intellij.ide.hierarchy.call.CallHierarchyNodeDescriptor;
+import com.intellij.ide.hierarchy.call.JavaCallHierarchyData;
+import com.intellij.ide.util.treeView.NodeDescriptor;
+import com.intellij.psi.*;
+import com.intellij.psi.search.SearchScope;
+import de.plushnikov.intellij.plugin.psi.LombokLightMethodBuilder;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+public class LombokFieldHierarchyElementProvider implements CallHierarchyElementProvider {
+
+ @Override
+ public boolean canProvide(@NotNull PsiMember element) {
+ return element instanceof PsiField;
+ }
+
+ @Override
+ public Collection provideReferencedMembers(@NotNull PsiMember elementToSearch) {
+ final PsiClass containingClass = elementToSearch.getContainingClass();
+ if (containingClass != null) {
+ final Collection result = new ArrayList<>();
+
+ Arrays.stream(containingClass.getMethods())
+ .filter(LombokLightMethodBuilder.class::isInstance)
+ .map(LombokLightMethodBuilder.class::cast)
+ .filter(psiMethod -> psiMethod.getNavigationElement() == elementToSearch || psiMethod.hasRelatedMember(elementToSearch))
+ .forEach(result::add);
+
+ Arrays.stream(containingClass.getInnerClasses())
+ .map(PsiClass::getMethods)
+ .flatMap(Arrays::stream)
+ .filter(LombokLightMethodBuilder.class::isInstance)
+ .map(LombokLightMethodBuilder.class::cast)
+ .filter(psiMethod -> psiMethod.hasRelatedMember(elementToSearch))
+ .forEach(result::add);
+
+ return result;
+ }
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void appendReferencedMethods(@NotNull PsiMethod methodToFind, @NotNull JavaCallHierarchyData hierarchyData) {
+ if (methodToFind.isConstructor()) {
+ final PsiClass containingClass = methodToFind.getContainingClass();
+ if (null != containingClass) {
+ Arrays.stream(containingClass.getInnerClasses())
+ .map(PsiClass::getMethods)
+ .flatMap(Arrays::stream)
+ .filter(LombokLightMethodBuilder.class::isInstance)
+ .map(LombokLightMethodBuilder.class::cast)
+ .filter(methodBuilder -> methodBuilder.hasRelatedMember(methodToFind))
+ .forEach(methodBuilder -> {
+ CallHierarchyNodeDescriptor parentDescriptor = (CallHierarchyNodeDescriptor)hierarchyData.getNodeDescriptor();
+ final Map> nodeDescriptorMap = hierarchyData.getResultMap();
+ CallHierarchyNodeDescriptor d = (CallHierarchyNodeDescriptor)nodeDescriptorMap.get(methodBuilder);
+ if (d == null) {
+ d = new CallHierarchyNodeDescriptor(hierarchyData.getProject(), parentDescriptor, methodBuilder, false, true);
+ nodeDescriptorMap.put(methodBuilder, d);
+ }
+ });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/EqualsAndHashCodeProcessor.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/EqualsAndHashCodeProcessor.java
index f9998af7d2bc..8438c80e0a5c 100644
--- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/EqualsAndHashCodeProcessor.java
+++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/EqualsAndHashCodeProcessor.java
@@ -3,6 +3,7 @@ package de.plushnikov.intellij.plugin.processor.clazz;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTypesUtil;
+import com.intellij.util.containers.ContainerUtil;
import de.plushnikov.intellij.plugin.LombokClassNames;
import de.plushnikov.intellij.plugin.lombokconfig.ConfigKey;
import de.plushnikov.intellij.plugin.problem.ProblemSink;
@@ -194,19 +195,28 @@ public final class EqualsAndHashCodeProcessor extends AbstractClassProcessor {
LombokAddNullAnnotations.createRelevantNullableAnnotation(psiClass, parameter);
copyOnXAnnotationsForFirstParam(psiAnnotation, parameter);
}
-
+ methodBuilder.withRelatedMembers(m -> {
+ final Collection memberInfos = collectEqualsAndHashcodeMemberInfo(m);
+ return ContainerUtil.map(memberInfos, MemberInfo::getField);
+ });
methodBuilder.withBodyText(m -> {
- PsiClass containingClass = m.getContainingClass();
- PsiAnnotation anno = (PsiAnnotation)m.getNavigationElement();
- return createEqualsBlockString(containingClass, anno, hasCanEqualMethod,
- EqualsAndHashCodeToStringHandler.filterMembers(containingClass, anno, true,
- INCLUDE_ANNOTATION_METHOD, null,
- EQUALS_AND_HASHCODE_INCLUDE,
- EQUALS_AND_HASHCODE_EXCLUDE));
+ final PsiClass containingClass = m.getContainingClass();
+ final PsiAnnotation anno = (PsiAnnotation)m.getNavigationElement();
+ final Collection memberInfos = collectEqualsAndHashcodeMemberInfo(m);
+ return createEqualsBlockString(containingClass, anno, hasCanEqualMethod, memberInfos);
});
return methodBuilder;
}
+ private static @NotNull Collection collectEqualsAndHashcodeMemberInfo(LombokLightMethodBuilder m) {
+ PsiClass containingClass = m.getContainingClass();
+ PsiAnnotation anno = (PsiAnnotation)m.getNavigationElement();
+ return EqualsAndHashCodeToStringHandler.filterMembers(containingClass, anno, true,
+ INCLUDE_ANNOTATION_METHOD, null,
+ EQUALS_AND_HASHCODE_INCLUDE,
+ EQUALS_AND_HASHCODE_EXCLUDE);
+ }
+
private @NotNull PsiMethod createHashCodeMethod(@NotNull PsiClass psiClass,
@NotNull PsiAnnotation psiAnnotation) {
final PsiManager psiManager = psiClass.getManager();
@@ -216,14 +226,15 @@ public final class EqualsAndHashCodeProcessor extends AbstractClassProcessor {
.withMethodReturnType(PsiTypes.intType())
.withContainingClass(psiClass)
.withNavigationElement(psiAnnotation)
+ .withRelatedMembers(m -> {
+ final Collection memberInfos = collectEqualsAndHashcodeMemberInfo(m);
+ return ContainerUtil.map(memberInfos, MemberInfo::getField);
+ })
.withBodyText(m -> {
PsiClass containingClass = m.getContainingClass();
PsiAnnotation anno = (PsiAnnotation)m.getNavigationElement();
- return createHashcodeBlockString(containingClass, anno,
- EqualsAndHashCodeToStringHandler.filterMembers(containingClass, anno, true,
- INCLUDE_ANNOTATION_METHOD, null,
- EQUALS_AND_HASHCODE_INCLUDE,
- EQUALS_AND_HASHCODE_EXCLUDE));
+ final Collection memberInfos = collectEqualsAndHashcodeMemberInfo(m);
+ return createHashcodeBlockString(containingClass, anno, memberInfos);
});
}
diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/ToStringProcessor.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/ToStringProcessor.java
index 0c68c3e97dfc..01282df6dac3 100644
--- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/ToStringProcessor.java
+++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/ToStringProcessor.java
@@ -126,6 +126,10 @@ public final class ToStringProcessor extends AbstractClassProcessor {
LombokAddNullAnnotations.createRelevantNonNullAnnotation(psiClass, methodBuilder);
+ for (MemberInfo memberInfo : memberInfos) {
+ methodBuilder.withRelatedMember(memberInfo.getField());
+ }
+
return methodBuilder;
}
diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/constructor/AbstractConstructorClassProcessor.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/constructor/AbstractConstructorClassProcessor.java
index 7bfc5b1a9f79..b0659af857fd 100644
--- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/constructor/AbstractConstructorClassProcessor.java
+++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/constructor/AbstractConstructorClassProcessor.java
@@ -328,6 +328,10 @@ public abstract class AbstractConstructorClassProcessor extends AbstractClassPro
.withModifier(modifier)
.withWriteAccess();
+ for (PsiField param : params) {
+ constructorBuilder.withRelatedMember(param);
+ }
+
LombokCopyableAnnotations.copyOnXAnnotations(psiAnnotation, constructorBuilder.getModifierList(), "onConstructor");
if (useJavaDefaults) {
@@ -395,6 +399,10 @@ public abstract class AbstractConstructorClassProcessor extends AbstractClassPro
.withModifier(PsiModifier.STATIC)
.withWriteAccess();
+ for (PsiField param : params) {
+ methodBuilder.withRelatedMember(param);
+ }
+
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
if (psiClass.hasTypeParameters()) {
final PsiTypeParameter[] classTypeParameters = psiClass.getTypeParameters();
diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderHandler.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderHandler.java
index 225105990b23..29b505fc41ad 100644
--- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderHandler.java
+++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderHandler.java
@@ -23,10 +23,7 @@ import de.plushnikov.intellij.plugin.provider.LombokUserDataKeys;
import de.plushnikov.intellij.plugin.psi.LombokLightClassBuilder;
import de.plushnikov.intellij.plugin.psi.LombokLightMethodBuilder;
import de.plushnikov.intellij.plugin.thirdparty.LombokCopyableAnnotations;
-import de.plushnikov.intellij.plugin.util.LombokProcessorUtil;
-import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil;
-import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil;
-import de.plushnikov.intellij.plugin.util.PsiClassUtil;
+import de.plushnikov.intellij.plugin.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -766,6 +763,16 @@ public class BuilderHandler {
.withContainingClass(builderClass)
.withNavigationElement(parentClass)
.withModifier(getBuilderInnerAccessVisibility(psiAnnotation));
+
+ if (null == psiMethod) {
+ Stream.of(parentClass.getConstructors())
+ .filter(m -> sameParameters(m.getParameterList().getParameters(), builderInfos))
+ .findFirst().ifPresent(methodBuilder::withRelatedMember);
+ }
+ else if (psiMethod.isConstructor()) {
+ methodBuilder.withRelatedMember(psiMethod);
+ }
+
final String codeBlockText =
createBuildMethodCodeBlockText(psiMethod, builderClass, returnType, buildMethodPrepare, buildMethodParameters);
methodBuilder.withBodyText(codeBlockText);
diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightMethodBuilder.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightMethodBuilder.java
index 31ffe9bc07bd..7c39882b848a 100644
--- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightMethodBuilder.java
+++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightMethodBuilder.java
@@ -21,6 +21,9 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.util.Objects;
import java.util.function.Function;
@@ -38,6 +41,11 @@ public class LombokLightMethodBuilder extends LightMethodBuilder implements Synt
private boolean myReadWriteAccess = false;
+ private Function> myRelatedMembersFunction = builder -> {
+ return List.of();
+ };
+ private Collection myRelatedMembers;
+
public LombokLightMethodBuilder(@NotNull PsiManager manager, @NotNull String name) {
super(manager, JavaLanguage.INSTANCE, name,
new LombokLightParameterListBuilder(manager, JavaLanguage.INSTANCE),
@@ -48,6 +56,29 @@ public class LombokLightMethodBuilder extends LightMethodBuilder implements Synt
setBaseIcon(LombokIcons.Nodes.LombokMethod);
}
+ public LombokLightMethodBuilder withRelatedMembers(@NotNull Function> buildFunction) {
+ myRelatedMembersFunction = buildFunction;
+ myRelatedMembers = null;
+ return this;
+ }
+
+ public LombokLightMethodBuilder withRelatedMember(@Nullable PsiElement member) {
+ if(null != member) {
+ if (myRelatedMembers == null) {
+ myRelatedMembers = new ArrayList<>();
+ }
+ myRelatedMembers.add(member);
+ }
+ return this;
+ }
+
+ public boolean hasRelatedMember(@NotNull PsiMember member) {
+ if(myRelatedMembers == null) {
+ myRelatedMembers = myRelatedMembersFunction.apply(this);
+ }
+ return myRelatedMembers.contains(member);
+ }
+
public LombokLightMethodBuilder withNavigationElement(PsiElement navigationElement) {
setNavigationElement(navigationElement);
return this;
diff --git a/plugins/lombok/src/main/resources/META-INF/plugin.xml b/plugins/lombok/src/main/resources/META-INF/plugin.xml
index 022e21a659af..1e020483bd25 100644
--- a/plugins/lombok/src/main/resources/META-INF/plugin.xml
+++ b/plugins/lombok/src/main/resources/META-INF/plugin.xml
@@ -113,6 +113,8 @@
+
+
> nodeDescriptorComparator = JavaHierarchyUtil.getComparator(getProject());
+ String plainDumped = HierarchyViewTestFixture.dump(plainJavaHierarchy, null, nodeDescriptorComparator, 0);
+
+ String plainDumpedNormalized = plainDumped.replaceAll(plainJavaClassName, lombokClassName);
+ plainDumpedNormalized = plainDumpedNormalized.replaceAll(plainJavaCallerClassName, lombokCallerClassName);
+
+ final String equalsMethodCall = lombokClassName + ".equals(Object)";
+ if(StringUtil.getOccurrenceCount(plainDumpedNormalized, equalsMethodCall) > 1) {
+ plainDumpedNormalized = removeFirstLineWithSubstring(plainDumpedNormalized, equalsMethodCall);
+ }
+
+ HierarchyViewTestFixture.doHierarchyTest(lombokHierarchy, plainDumpedNormalized);
+ }
+
+ public static String removeFirstLineWithSubstring(String text, String substring) {
+ AtomicBoolean removed = new AtomicBoolean(false);
+
+ return Arrays.stream(text.split("\\R"))
+ .filter(line -> {
+ if (!removed.get() && line.contains(substring)) {
+ removed.set(true);
+ return false; // erstes Vorkommen raus
+ }
+ return true;
+ })
+ .collect(Collectors.joining(System.lineSeparator()));
+ }
+
+
+ @NotNull
+ private CallerMethodsTreeStructure getFieldCallerHierarchy(String className, String fieldName) {
+ PsiClass psiClass = JavaPsiFacade.getInstance(getProject())
+ .findClass(className, ProjectScope.getProjectScope(getProject()));
+ assertNotNull("Class '" + className + "' not found", psiClass);
+
+ PsiField field = psiClass.findFieldByName(fieldName, false);
+ assertNotNull("Field '" + fieldName + "' not found in " + className, field);
+
+ return new CallerMethodsTreeStructure(getProject(), field, HierarchyBrowserBaseEx.SCOPE_PROJECT);
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/BuilderLombok.java b/plugins/lombok/testData/hierarchy/BuilderLombok.java
new file mode 100644
index 000000000000..f900632ab54d
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/BuilderLombok.java
@@ -0,0 +1,9 @@
+import lombok.Builder;
+
+@Builder
+public class BuilderLombok {
+ private String title;
+ private String author;
+ private int pages;
+ private boolean published;
+}
diff --git a/plugins/lombok/testData/hierarchy/BuilderLombokCaller.java b/plugins/lombok/testData/hierarchy/BuilderLombokCaller.java
new file mode 100644
index 000000000000..7b82b9780e10
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/BuilderLombokCaller.java
@@ -0,0 +1,25 @@
+public class BuilderLombokCaller {
+
+ public void useBuilder() {
+ BuilderLombok book = BuilderLombok.builder()
+ .title("Clean Code")
+ .author("Robert C. Martin")
+ .pages(464)
+ .published(true)
+ .build();
+ }
+
+ public BuilderLombok createBook(String title, String author) {
+ return BuilderLombok.builder()
+ .title(title)
+ .author(author)
+ .pages(100)
+ .published(false)
+ .build();
+ }
+
+ public BuilderLombok.BuilderLombokBuilder startBuilding() {
+ return BuilderLombok.builder()
+ .title("New Book");
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/BuilderPlainJava.java b/plugins/lombok/testData/hierarchy/BuilderPlainJava.java
new file mode 100644
index 000000000000..5a17814b1866
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/BuilderPlainJava.java
@@ -0,0 +1,51 @@
+public class BuilderPlainJava {
+ private String title;
+ private String author;
+ private int pages;
+ private boolean published;
+
+ BuilderPlainJava(String title, String author, int pages, boolean published) {
+ this.title = title;
+ this.author = author;
+ this.pages = pages;
+ this.published = published;
+ }
+
+ public static BuilderPlainJavaBuilder builder() {
+ return new BuilderPlainJavaBuilder();
+ }
+
+ public static class BuilderPlainJavaBuilder {
+ private String title;
+ private String author;
+ private int pages;
+ private boolean published;
+
+ BuilderPlainJavaBuilder() {
+ }
+
+ public BuilderPlainJavaBuilder title(String title) {
+ this.title = title;
+ return this;
+ }
+
+ public BuilderPlainJavaBuilder author(String author) {
+ this.author = author;
+ return this;
+ }
+
+ public BuilderPlainJavaBuilder pages(int pages) {
+ this.pages = pages;
+ return this;
+ }
+
+ public BuilderPlainJavaBuilder published(boolean published) {
+ this.published = published;
+ return this;
+ }
+
+ public BuilderPlainJava build() {
+ return new BuilderPlainJava(title, author, pages, published);
+ }
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/BuilderPlainJavaCaller.java b/plugins/lombok/testData/hierarchy/BuilderPlainJavaCaller.java
new file mode 100644
index 000000000000..818ad466e75b
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/BuilderPlainJavaCaller.java
@@ -0,0 +1,25 @@
+public class BuilderPlainJavaCaller {
+
+ public void useBuilder() {
+ BuilderPlainJava book = BuilderPlainJava.builder()
+ .title("Clean Code")
+ .author("Robert C. Martin")
+ .pages(464)
+ .published(true)
+ .build();
+ }
+
+ public BuilderPlainJava createBook(String title, String author) {
+ return BuilderPlainJava.builder()
+ .title(title)
+ .author(author)
+ .pages(100)
+ .published(false)
+ .build();
+ }
+
+ public BuilderPlainJava.BuilderPlainJavaBuilder startBuilding() {
+ return BuilderPlainJava.builder()
+ .title("New Book");
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/DataLombok.java b/plugins/lombok/testData/hierarchy/DataLombok.java
new file mode 100644
index 000000000000..33a3f9987884
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/DataLombok.java
@@ -0,0 +1,8 @@
+import lombok.Data;
+
+@Data
+public class DataLombok {
+ private Long id;
+ private String name;
+ private boolean active;
+}
diff --git a/plugins/lombok/testData/hierarchy/DataLombokCaller.java b/plugins/lombok/testData/hierarchy/DataLombokCaller.java
new file mode 100644
index 000000000000..9b029619d8af
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/DataLombokCaller.java
@@ -0,0 +1,23 @@
+public class DataLombokCaller {
+
+ public void useData() {
+ DataLombok obj = new DataLombok();
+ obj.setId(1L);
+ obj.setName("Test");
+ obj.setActive(true);
+
+ Long id = obj.getId();
+ String name = obj.getName();
+ boolean active = obj.isActive();
+
+ System.out.println("ID: " + id + ", Name: " + name + ", Active: " + active);
+ }
+
+ public Long fetchId(DataLombok data) {
+ return data.getId();
+ }
+
+ public void updateId(DataLombok data, Long newId) {
+ data.setId(newId);
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/DataPlainJava.java b/plugins/lombok/testData/hierarchy/DataPlainJava.java
new file mode 100644
index 000000000000..71a3c344d48b
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/DataPlainJava.java
@@ -0,0 +1,53 @@
+import java.util.Objects;
+
+public class DataPlainJava {
+ private Long id;
+ private String name;
+ private boolean active;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setActive(boolean active) {
+ this.active = active;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DataPlainJava that = (DataPlainJava) o;
+ return active == that.active && Objects.equals(id, that.id) && Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name, active);
+ }
+
+ @Override
+ public String toString() {
+ return "DataPlainJava{" +
+ "id=" + id +
+ ", name='" + name + '\'' +
+ ", active=" + active +
+ '}';
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/DataPlainJavaCaller.java b/plugins/lombok/testData/hierarchy/DataPlainJavaCaller.java
new file mode 100644
index 000000000000..014a4812c762
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/DataPlainJavaCaller.java
@@ -0,0 +1,23 @@
+public class DataPlainJavaCaller {
+
+ public void useData() {
+ DataPlainJava obj = new DataPlainJava();
+ obj.setId(1L);
+ obj.setName("Test");
+ obj.setActive(true);
+
+ Long id = obj.getId();
+ String name = obj.getName();
+ boolean active = obj.isActive();
+
+ System.out.println("ID: " + id + ", Name: " + name + ", Active: " + active);
+ }
+
+ public Long fetchId(DataPlainJava data) {
+ return data.getId();
+ }
+
+ public void updateId(DataPlainJava data, Long newId) {
+ data.setId(newId);
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/GetterLombok.java b/plugins/lombok/testData/hierarchy/GetterLombok.java
new file mode 100644
index 000000000000..fad97ba7b953
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/GetterLombok.java
@@ -0,0 +1,12 @@
+import lombok.Getter;
+
+@Getter
+public class GetterLombok {
+ private String name;
+ private int age;
+
+ public GetterLombok(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/GetterLombokCaller.java b/plugins/lombok/testData/hierarchy/GetterLombokCaller.java
new file mode 100644
index 000000000000..2c44389899e5
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/GetterLombokCaller.java
@@ -0,0 +1,13 @@
+public class GetterLombokCaller {
+
+ public void useGetter() {
+ GetterLombok obj = new GetterLombok("Test", 25);
+ String name = obj.getName();
+ int age = obj.getAge();
+ System.out.println("Name: " + name + ", Age: " + age);
+ }
+
+ public String fetchName(GetterLombok lombok) {
+ return lombok.getName();
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/GetterPlainJava.java b/plugins/lombok/testData/hierarchy/GetterPlainJava.java
new file mode 100644
index 000000000000..d7aaab3c813a
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/GetterPlainJava.java
@@ -0,0 +1,17 @@
+public class GetterPlainJava {
+ private String name;
+ private int age;
+
+ public GetterPlainJava(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/GetterPlainJavaCaller.java b/plugins/lombok/testData/hierarchy/GetterPlainJavaCaller.java
new file mode 100644
index 000000000000..d4dd4372178d
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/GetterPlainJavaCaller.java
@@ -0,0 +1,13 @@
+public class GetterPlainJavaCaller {
+
+ public void useGetter() {
+ GetterPlainJava obj = new GetterPlainJava("Test", 25);
+ String name = obj.getName();
+ int age = obj.getAge();
+ System.out.println("Name: " + name + ", Age: " + age);
+ }
+
+ public String fetchName(GetterPlainJava plainJava) {
+ return plainJava.getName();
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/SetterLombok.java b/plugins/lombok/testData/hierarchy/SetterLombok.java
new file mode 100644
index 000000000000..c556fe611ff3
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/SetterLombok.java
@@ -0,0 +1,7 @@
+import lombok.Setter;
+
+@Setter
+public class SetterLombok {
+ private String value;
+ private int count;
+}
diff --git a/plugins/lombok/testData/hierarchy/SetterLombokCaller.java b/plugins/lombok/testData/hierarchy/SetterLombokCaller.java
new file mode 100644
index 000000000000..132c23c20837
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/SetterLombokCaller.java
@@ -0,0 +1,12 @@
+public class SetterLombokCaller {
+
+ public void useSetter() {
+ SetterLombok obj = new SetterLombok();
+ obj.setValue("Hello");
+ obj.setCount(42);
+ }
+
+ public void updateValue(SetterLombok lombok, String newValue) {
+ lombok.setValue(newValue);
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/SetterPlainJava.java b/plugins/lombok/testData/hierarchy/SetterPlainJava.java
new file mode 100644
index 000000000000..31d8b0168f07
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/SetterPlainJava.java
@@ -0,0 +1,12 @@
+public class SetterPlainJava {
+ private String value;
+ private int count;
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/SetterPlainJavaCaller.java b/plugins/lombok/testData/hierarchy/SetterPlainJavaCaller.java
new file mode 100644
index 000000000000..2b823de56743
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/SetterPlainJavaCaller.java
@@ -0,0 +1,12 @@
+public class SetterPlainJavaCaller {
+
+ public void useSetter() {
+ SetterPlainJava obj = new SetterPlainJava();
+ obj.setValue("Hello");
+ obj.setCount(42);
+ }
+
+ public void updateValue(SetterPlainJava plainJava, String newValue) {
+ plainJava.setValue(newValue);
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/ToStringLombok.java b/plugins/lombok/testData/hierarchy/ToStringLombok.java
new file mode 100644
index 000000000000..a3674a07d210
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/ToStringLombok.java
@@ -0,0 +1,14 @@
+import lombok.ToString;
+
+@ToString
+public class ToStringLombok {
+ private String description;
+ private int priority;
+ private boolean completed;
+
+ public ToStringLombok(String description, int priority, boolean completed) {
+ this.description = description;
+ this.priority = priority;
+ this.completed = completed;
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/ToStringLombokCaller.java b/plugins/lombok/testData/hierarchy/ToStringLombokCaller.java
new file mode 100644
index 000000000000..8339069393a0
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/ToStringLombokCaller.java
@@ -0,0 +1,16 @@
+public class ToStringLombokCaller {
+
+ public void useToString() {
+ ToStringLombok obj = new ToStringLombok("Task description", 1, false);
+ String result = obj.toString();
+ System.out.println(result);
+ }
+
+ public String getStringRepresentation(ToStringLombok lombok) {
+ return lombok.toString();
+ }
+
+ public void logObject(ToStringLombok lombok) {
+ System.out.println("Object: " + lombok.toString());
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/ToStringPlainJava.java b/plugins/lombok/testData/hierarchy/ToStringPlainJava.java
new file mode 100644
index 000000000000..e7ad903d7270
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/ToStringPlainJava.java
@@ -0,0 +1,20 @@
+public class ToStringPlainJava {
+ private String description;
+ private int priority;
+ private boolean completed;
+
+ public ToStringPlainJava(String description, int priority, boolean completed) {
+ this.description = description;
+ this.priority = priority;
+ this.completed = completed;
+ }
+
+ @Override
+ public String toString() {
+ return "ToStringPlainJava{" +
+ "description='" + description + '\'' +
+ ", priority=" + priority +
+ ", completed=" + completed +
+ '}';
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/ToStringPlainJavaCaller.java b/plugins/lombok/testData/hierarchy/ToStringPlainJavaCaller.java
new file mode 100644
index 000000000000..f5b03fbc1eb7
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/ToStringPlainJavaCaller.java
@@ -0,0 +1,16 @@
+public class ToStringPlainJavaCaller {
+
+ public void useToString() {
+ ToStringPlainJava obj = new ToStringPlainJava("Task description", 1, false);
+ String result = obj.toString();
+ System.out.println(result);
+ }
+
+ public String getStringRepresentation(ToStringPlainJava plainJava) {
+ return plainJava.toString();
+ }
+
+ public void logObject(ToStringPlainJava plainJava) {
+ System.out.println("Object: " + plainJava.toString());
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/ValueLombok.java b/plugins/lombok/testData/hierarchy/ValueLombok.java
new file mode 100644
index 000000000000..59f927d7b30d
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/ValueLombok.java
@@ -0,0 +1,8 @@
+import lombok.Value;
+
+@Value
+public class ValueLombok {
+ String code;
+ int version;
+ boolean enabled;
+}
diff --git a/plugins/lombok/testData/hierarchy/ValueLombokCaller.java b/plugins/lombok/testData/hierarchy/ValueLombokCaller.java
new file mode 100644
index 000000000000..dedfd0f36ac8
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/ValueLombokCaller.java
@@ -0,0 +1,20 @@
+public class ValueLombokCaller {
+
+ public void useValue() {
+ ValueLombok obj = new ValueLombok("ABC", 1, true);
+
+ String code = obj.getCode();
+ int version = obj.getVersion();
+ boolean enabled = obj.isEnabled();
+
+ System.out.println("Code: " + code + ", Version: " + version + ", Enabled: " + enabled);
+ }
+
+ public String fetchCode(ValueLombok value) {
+ return value.getCode();
+ }
+
+ public boolean checkEnabled(ValueLombok value) {
+ return value.isEnabled();
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/ValuePlainJava.java b/plugins/lombok/testData/hierarchy/ValuePlainJava.java
new file mode 100644
index 000000000000..73f100948bf4
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/ValuePlainJava.java
@@ -0,0 +1,47 @@
+import java.util.Objects;
+
+public final class ValuePlainJava {
+ private final String code;
+ private final int version;
+ private final boolean enabled;
+
+ public ValuePlainJava(String code, int version, boolean enabled) {
+ this.code = code;
+ this.version = version;
+ this.enabled = enabled;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ValuePlainJava that = (ValuePlainJava) o;
+ return version == that.version && enabled == that.enabled && Objects.equals(code, that.code);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(code, version, enabled);
+ }
+
+ @Override
+ public String toString() {
+ return "ValuePlainJava{" +
+ "code='" + code + '\'' +
+ ", version=" + version +
+ ", enabled=" + enabled +
+ '}';
+ }
+}
diff --git a/plugins/lombok/testData/hierarchy/ValuePlainJavaCaller.java b/plugins/lombok/testData/hierarchy/ValuePlainJavaCaller.java
new file mode 100644
index 000000000000..8d31ec164748
--- /dev/null
+++ b/plugins/lombok/testData/hierarchy/ValuePlainJavaCaller.java
@@ -0,0 +1,20 @@
+public class ValuePlainJavaCaller {
+
+ public void useValue() {
+ ValuePlainJava obj = new ValuePlainJava("ABC", 1, true);
+
+ String code = obj.getCode();
+ int version = obj.getVersion();
+ boolean enabled = obj.isEnabled();
+
+ System.out.println("Code: " + code + ", Version: " + version + ", Enabled: " + enabled);
+ }
+
+ public String fetchCode(ValuePlainJava value) {
+ return value.getCode();
+ }
+
+ public boolean checkEnabled(ValuePlainJava value) {
+ return value.isEnabled();
+ }
+}