mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[lombok] IDEA-310810 IDEA-380110 Show Lombok-generated methods in 'Caller-Hierarchy' tool window, apply review suggestions
GitOrigin-RevId: d3cc45468756d840bec3f5e9c974efb391d9708c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
55dfc2580c
commit
d6698abecb
+16
-10
@@ -71,9 +71,9 @@ public final class CallerMethodsTreeStructure extends HierarchyTreeStructure {
|
||||
|
||||
PsiMember member = enclosingElement;
|
||||
PsiClass originalClass = member.getContainingClass();
|
||||
|
||||
|
||||
if (originalClass == null) return ArrayUtilRt.EMPTY_OBJECT_ARRAY;
|
||||
|
||||
|
||||
PsiClassType originalType = JavaPsiFacade.getElementFactory(myProject).createType(originalClass);
|
||||
Set<PsiMethod> methodsToFind = new HashSet<>();
|
||||
|
||||
@@ -83,7 +83,9 @@ public final class CallerMethodsTreeStructure extends HierarchyTreeStructure {
|
||||
|
||||
Map<PsiMember, NodeDescriptor<?>> methodToDescriptorMap = new HashMap<>();
|
||||
for (PsiMethod methodToFind : methodsToFind) {
|
||||
JavaCallHierarchyData data = new JavaCallHierarchyData(originalClass, methodToFind, originalType, method, methodsToFind, descriptor, methodToDescriptorMap, myProject);
|
||||
JavaCallHierarchyData data =
|
||||
new JavaCallHierarchyData(originalClass, methodToFind, originalType, method, methodsToFind, descriptor, methodToDescriptorMap,
|
||||
myProject);
|
||||
|
||||
MethodReferencesSearch.search(methodToFind, searchScope, true).forEach(reference -> {
|
||||
// references in javadoc really couldn't "call" anything
|
||||
@@ -118,15 +120,21 @@ public final class CallerMethodsTreeStructure extends HierarchyTreeStructure {
|
||||
return true;
|
||||
});
|
||||
|
||||
// add other method elements without references
|
||||
// add other methods with augmented references to methodToFind
|
||||
for (CallHierarchyElementProvider provider : CallHierarchyElementProvider.EP_NAME.getExtensionList()) {
|
||||
provider.appendReferencedMethods(methodToFind, data);
|
||||
final Collection<PsiMethod> referencedMethods = provider.provideReferencedMethods(methodToFind);
|
||||
referencedMethods.forEach(referencedMethod -> {
|
||||
final Map<PsiMember, NodeDescriptor<?>> nodeDescriptorMap = data.getResultMap();
|
||||
nodeDescriptorMap.computeIfAbsent(referencedMethod,
|
||||
psiMember -> new CallHierarchyNodeDescriptor(myProject, descriptor, psiMember,
|
||||
false, true));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayUtil.toObjectArray(methodToDescriptorMap.values());
|
||||
}
|
||||
|
||||
|
||||
assert enclosingElement instanceof PsiField || enclosingElement instanceof PsiRecordComponent
|
||||
: "Enclosing element should be a field, but was " + enclosingElement.getClass() + ", text: " + enclosingElement.getText();
|
||||
|
||||
@@ -134,12 +142,10 @@ public final class CallerMethodsTreeStructure extends HierarchyTreeStructure {
|
||||
.search(enclosingElement, searchScope).findAll().stream()
|
||||
.map(PsiReference::getElement);
|
||||
|
||||
// collect other field elements without references
|
||||
// collect other field elements without direct references
|
||||
Collection<@NotNull PsiElement> providedElements = new ArrayList<>();
|
||||
for (CallHierarchyElementProvider provider : CallHierarchyElementProvider.EP_NAME.getExtensionList()) {
|
||||
if(provider.canProvide(enclosingElement)) {
|
||||
providedElements.addAll(provider.provideReferencedMembers(enclosingElement));
|
||||
}
|
||||
providedElements.addAll(provider.provideReferencedMembers(enclosingElement));
|
||||
}
|
||||
|
||||
return Stream.concat(referencedElements, providedElements.stream())
|
||||
|
||||
@@ -5,18 +5,35 @@ 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;
|
||||
|
||||
/**
|
||||
* The CallHierarchyElementProvider ExtensionPoint is designed to augment the Call Hierarchy results (specifically the "Caller Hierarchy" view).
|
||||
* Its primary purpose is to allow plugins to provide "virtual" or "implicit" relationships between code elements that are not represented
|
||||
* by standard physical PsiReference objects in the source code.
|
||||
* This is particularly useful for frameworks that generate code or use bytecode manipulation (like Lombok),
|
||||
* where a method or field might be logically "called" or "used" by elements that the standard Java reference search cannot find.
|
||||
*/
|
||||
public interface CallHierarchyElementProvider {
|
||||
ExtensionPointName<CallHierarchyElementProvider> EP_NAME =
|
||||
ExtensionPointName.create("com.intellij.hierarchy.elementProvider");
|
||||
|
||||
boolean canProvide(@NotNull PsiMember element);
|
||||
/**
|
||||
* Collects augmented elements, which are not really present in code but virtually references to psiMember
|
||||
* @param psiMember some PsiMember to find referenced elements for
|
||||
* @return collection of virtually augmented elements references to psiMember
|
||||
*/
|
||||
@NotNull
|
||||
Collection<PsiElement> provideReferencedMembers(@NotNull PsiMember psiMember);
|
||||
|
||||
Collection<PsiElement> provideReferencedMembers(@NotNull PsiMember reference);
|
||||
|
||||
void appendReferencedMethods(@NotNull PsiMethod methodToFind, @NotNull JavaCallHierarchyData hierarchyData);
|
||||
/**
|
||||
* Collects augmented PsiMethods, which are not really present in code but virtually references to methodToFind
|
||||
* @param methodToFind some PsiMethod to find virtually referenced other PsiMethods for
|
||||
** @return collection of virtually augmented PsiMethods references to methodToFind
|
||||
*/
|
||||
@NotNull
|
||||
Collection<PsiMethod> provideReferencedMethods(@NotNull PsiMethod methodToFind);
|
||||
}
|
||||
|
||||
+28
-23
@@ -1,33 +1,39 @@
|
||||
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.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import de.plushnikov.intellij.plugin.psi.LombokLightMethodBuilder;
|
||||
import de.plushnikov.intellij.plugin.util.LombokLibraryUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LombokFieldHierarchyElementProvider implements CallHierarchyElementProvider {
|
||||
|
||||
@Override
|
||||
public boolean canProvide(@NotNull PsiMember element) {
|
||||
return element instanceof PsiField;
|
||||
}
|
||||
public @NotNull Collection<PsiElement> provideReferencedMembers(@NotNull PsiMember psiMember) {
|
||||
// only PsiFields are supported now
|
||||
if(!(psiMember instanceof PsiField)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PsiElement> provideReferencedMembers(@NotNull PsiMember elementToSearch) {
|
||||
final PsiClass containingClass = elementToSearch.getContainingClass();
|
||||
// skip early if no lombok in current module
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(psiMember);
|
||||
if (!LombokLibraryUtil.hasLombokClasses(module)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final PsiClass containingClass = psiMember.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
final Collection<PsiElement> result = new ArrayList<>();
|
||||
|
||||
Arrays.stream(containingClass.getMethods())
|
||||
.filter(LombokLightMethodBuilder.class::isInstance)
|
||||
.map(LombokLightMethodBuilder.class::cast)
|
||||
.filter(psiMethod -> psiMethod.getNavigationElement() == elementToSearch || psiMethod.hasRelatedMember(elementToSearch))
|
||||
.filter(psiMethod -> psiMethod.getNavigationElement() == psiMember || psiMethod.hasRelatedMember(psiMember))
|
||||
.forEach(result::add);
|
||||
|
||||
Arrays.stream(containingClass.getInnerClasses())
|
||||
@@ -35,7 +41,7 @@ public class LombokFieldHierarchyElementProvider implements CallHierarchyElement
|
||||
.flatMap(Arrays::stream)
|
||||
.filter(LombokLightMethodBuilder.class::isInstance)
|
||||
.map(LombokLightMethodBuilder.class::cast)
|
||||
.filter(psiMethod -> psiMethod.hasRelatedMember(elementToSearch))
|
||||
.filter(psiMethod -> psiMethod.hasRelatedMember(psiMember))
|
||||
.forEach(result::add);
|
||||
|
||||
return result;
|
||||
@@ -44,26 +50,25 @@ public class LombokFieldHierarchyElementProvider implements CallHierarchyElement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendReferencedMethods(@NotNull PsiMethod methodToFind, @NotNull JavaCallHierarchyData hierarchyData) {
|
||||
public @NotNull List<PsiMethod> provideReferencedMethods(@NotNull PsiMethod methodToFind) {
|
||||
// skip early if no lombok in current module
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(methodToFind);
|
||||
if (!LombokLibraryUtil.hasLombokClasses(module)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (methodToFind.isConstructor()) {
|
||||
final PsiClass containingClass = methodToFind.getContainingClass();
|
||||
if (null != containingClass) {
|
||||
Arrays.stream(containingClass.getInnerClasses())
|
||||
return 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<PsiMember, NodeDescriptor<?>> 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);
|
||||
}
|
||||
});
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user