Skip to content

Commit da3292f

Browse files
gayanperrgrunber
authored andcommitted
Fix call hierarchy position resolution #2771
1 parent e49a751 commit da3292f

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyHandler.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public List<CallHierarchyItem> prepareCallHierarchy(CallHierarchyPrepareParams p
7575
int character = params.getPosition().getCharacter();
7676

7777
try {
78-
IMember candidate = getCallHierarchyElement(uri, line, character, monitor);
78+
IMember candidate = getCallHierarchyElement(uri, line, character, true, monitor);
7979
if (candidate == null) {
8080
return null;
8181
}
@@ -140,7 +140,7 @@ public List<CallHierarchyOutgoingCall> callHierarchyOutgoingCalls(CallHierarchyO
140140
return null;
141141
}
142142

143-
private IMember getCallHierarchyElement(String uri, int line, int character, IProgressMonitor monitor) throws JavaModelException {
143+
private IMember getCallHierarchyElement(String uri, int line, int character, boolean prepare, IProgressMonitor monitor) throws JavaModelException {
144144
Assert.isNotNull(uri, "uri");
145145

146146
ITypeRoot root = JDTUtils.resolveTypeRoot(uri);
@@ -162,7 +162,12 @@ private IMember getCallHierarchyElement(String uri, int line, int character, IPr
162162
int offset = JsonRpcHelpers.toOffset(root, line, character);
163163
List<IJavaElement> selectedElements = codeResolve(root, offset);
164164
Stream<IJavaElement> possibleElements = selectedElements.stream().filter(CallHierarchyCore::isPossibleInputElement);
165-
Optional<IJavaElement> firstElement = possibleElements.findFirst();
165+
Optional<IJavaElement> firstElement = possibleElements.findFirst().flatMap(element -> {
166+
if (!prepare && element instanceof IType) {
167+
return Optional.ofNullable(getEnclosingMember(root, offset)).map(IJavaElement.class::cast).filter(e -> !element.equals(e)).or(() -> Optional.of(element));
168+
}
169+
return Optional.of(element);
170+
});
166171
if (firstElement.isPresent() && firstElement.get() instanceof IMember member) {
167172
candidate = member;
168173
}
@@ -177,7 +182,7 @@ private IMember getCallHierarchyElement(String uri, int line, int character, IPr
177182

178183
private List<CallHierarchyIncomingCall> getIncomingCallItemsAt(String uri, int line, int character, IProgressMonitor monitor) throws JavaModelException {
179184
SubMonitor sub = SubMonitor.convert(monitor, 2);
180-
IMember candidate = getCallHierarchyElement(uri, line, character, sub.split(1));
185+
IMember candidate = getCallHierarchyElement(uri, line, character, false, sub.split(1));
181186
if (candidate == null) {
182187
return null;
183188
}
@@ -228,7 +233,7 @@ private Range getRange(IOpenable openable, CallLocation location) {
228233

229234
private List<CallHierarchyOutgoingCall> getOutgoingCallItemsAt(String uri, int line, int character, IProgressMonitor monitor) throws JavaModelException {
230235
SubMonitor sub = SubMonitor.convert(monitor, 2);
231-
IMember candidate = getCallHierarchyElement(uri, line, character, sub.split(1));
236+
IMember candidate = getCallHierarchyElement(uri, line, character, false, sub.split(1));
232237
if (candidate == null) {
233238
return null;
234239
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.sample;
2+
3+
public interface CallHierarchyGH2771 {
4+
Opt<String> name();
5+
6+
public static class Opt<T> {
7+
public static <T> Opt<T> of(T t) {
8+
return new Opt();
9+
}
10+
}
11+
}

org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/CallHierarchyHandlerTest.java

+29
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,35 @@ public void outgoing_jar() throws Exception {
193193
assertTrue(jarUri.contains("WordUtils.class"));
194194
}
195195

196+
@Test
197+
public void incomingCalls_OnInterfaceMethod() throws Exception {
198+
// Line 27 from `CallHierarchy`
199+
// public void <|>bar() {
200+
String uri = getUriFromSrcProject("org.sample.CallHierarchyGH2771");
201+
List<CallHierarchyItem> items = prepareCallHierarchy(uri, 3, 17);
202+
assertNotNull(items);
203+
assertEquals(1, items.size());
204+
assertItem(items.get(0), "name()" + JavaElementLabels.DECL_STRING + "Opt<String>", Method, "org.sample.CallHierarchyGH2771", false, 3);
205+
206+
List<CallHierarchyIncomingCall> calls = getIncomingCalls(items.get(0));
207+
assertNotNull(calls);
208+
assertEquals(0, calls.size());
209+
}
210+
211+
@Test
212+
public void incomingCalls_OnInterfaceMethodReturnType() throws Exception {
213+
// Line 27 from `CallHierarchy`
214+
// public void <|>bar() {
215+
String uri = getUriFromSrcProject("org.sample.CallHierarchyGH2771");
216+
List<CallHierarchyItem> items = prepareCallHierarchy(uri, 3, 6);
217+
assertNotNull(items);
218+
assertEquals(1, items.size());
219+
assertItem(items.get(0), "Opt<T>", Class, "org.sample.CallHierarchyGH2771", false, 5);
220+
221+
List<CallHierarchyIncomingCall> calls = getIncomingCalls(items.get(0));
222+
assertNotNull(calls);
223+
assertEquals(1, calls.size());
224+
}
196225
// @Test
197226
// public void outgoing_recursive() throws Exception {
198227
// // Line 60 from `CallHierarchy`

0 commit comments

Comments
 (0)