Bug 161882 - [search] Call hierarchy does not find callers to implementations of interface methods
Summary: [search] Call hierarchy does not find callers to implementations of interface...
Status: RESOLVED WORKSFORME
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.3   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.3 M3   Edit
Assignee: Frederic Fusier CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-10-22 14:11 EDT by Koen van Dijken CLA
Modified: 2006-10-25 06:03 EDT (History)
0 users

See Also:


Attachments
workspace with testcase (640.15 KB, application/zip)
2006-10-24 07:10 EDT, Koen van Dijken CLA
no flags Details
second project (253.44 KB, application/zip)
2006-10-24 07:10 EDT, Koen van Dijken CLA
no flags Details
third project (97.71 KB, application/zip)
2006-10-24 07:11 EDT, Koen van Dijken CLA
no flags Details
fourth project (142.27 KB, application/zip)
2006-10-24 07:11 EDT, Koen van Dijken CLA
no flags Details
fifth project (338.06 KB, application/zip)
2006-10-24 07:12 EDT, Koen van Dijken CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Koen van Dijken CLA 2006-10-22 14:11:16 EDT
In a workspace with many projects (52) I often notice that the Call Hierachy does not find callers to implementations of methods defined in interfaces. This bug is easy to reproduce in this large workspace, but (until now) I have not been able to isolate it in a small workspace.

The search scope for the caller hierachy is 'workspace' and no filters are active.

At this very moment I have one case, spanning three projects. In one project I have this interface:

public interface ITransactionManager<T extends AbstractStore> {
   blabla
   String canCommit(Object context);
}

in a second project this implementation:

public class FocusTriggeredTransactionManager implements
		ITransactionManager<FeatureStore> {
   blabla
}

In a third projects I have this piece of code

Set<ITransactionManager<?>> transactionManagers = ITransactionManager.Registry.getTransactionManagers();
for (ITransactionManager<?> manager : transactionManagers) {
   Set contexts = manager.getContexts();
   for (Object context : contexts) {
      String msg = manager.canCommit(context);    // THIS LINE
      if (msg != null)
         msgs.add(msg);
   }
}

The call on 'THIS LINE' is not found when requested from the implementation class FocusTriggeredTransactionManager, but it is found when requested from the interface ITransactionManager.

I hope I can still isolate this bug into a manageable workspace...

Eclipse SDK
Version: 3.3.0
Build id: I20060922-0010
Comment 1 Frederic Fusier CLA 2006-10-23 13:40:57 EDT
Do you have any compilation errors in your code?
You don't find any references while using call hierarchy but can you find it/them while using search references instead?
Comment 2 Koen van Dijken CLA 2006-10-23 13:59:15 EDT
(In reply to comment #1)
> Do you have any compilation errors in your code?

No, there are no compilation errors in the source code.

> You don't find any references while using call hierarchy but can you find
> it/them while using search references instead?
> 

No, with search references (Shift-Ctrl-G) I get exactly the same results: On the method declaration in the interface I find the reference (caller), on the method implementation I do not get any references.
Comment 3 Frederic Fusier CLA 2006-10-24 05:23:51 EDT
Here's a simple test case based on comment 0 without any compiler error:

ITransactionManager.java:
  import java.util.Set;
  public interface ITransactionManager<T> {
    static class Registry {
      public static Set<ITransactionManager<?>> getTransactionManagers() {
        return null;
      }
    }
    String canCommit(Object context);
    Set<T> getContexts();
  }

FocusTriggeredTransactionManager.java:
  import java.util.Set;
  public class FocusTriggeredTransactionManager
               implements ITransactionManager<Object> {
    public String canCommit(Object context) {
      return null;
    }
    public Set<Object> getContexts() {
      return null;
    }
  }

Test.java:
  import java.util.Set;
  public class Test {
    void foo() {
      Set<ITransactionManager<?>> transactionManagers = 
        ITransactionManager.Registry.getTransactionManagers();
      for (ITransactionManager<?> manager : transactionManagers) {
        Set contexts = manager.getContexts();
        for (Object context : contexts) {
          manager.canCommit(context); // THIS LINE
        }
      }
    }
  }

I can find method references in Call Hierarchy view or using Search->References starting from interface method declaration or method implementation in class FocusTriggeredTransactionManager.

So, it seems that problem is located in your workspace.

To figure out what happens, can you follow these instructions:
1) delete all index files: shutdown your eclipse session, go to <wksp dir>/.metadata/.plugins/org.eclipse.jdt.core directory, delete all files, restart eclipse and redo the search (using Search->References)
2) If you still do not find any match after step 1), then create a new workspace, import your 5 projects in this brand new workspace and redo the search...

If you still have no matches after these 2 tries, then next step will be to trace what happens during the search...
Comment 4 Koen van Dijken CLA 2006-10-24 06:51:41 EDT
(In reply to comment #3)

> 
> So, it seems that problem is located in your workspace.
> 
> To figure out what happens, can you follow these instructions:
> 1) delete all index files: shutdown your eclipse session, go to <wksp
> dir>/.metadata/.plugins/org.eclipse.jdt.core directory, delete all files,
> restart eclipse and redo the search (using Search->References)

This does not make any difference.

> 2) If you still do not find any match after step 1), then create a new
> workspace, import your 5 projects in this brand new workspace and redo the
> search...
> 

Still no difference, no references found...

> If you still have no matches after these 2 tries, then next step will be to
> trace what happens during the search...
> 

I'll attach a 5 projects workspace in which the problem can be reproduced.
Comment 5 Koen van Dijken CLA 2006-10-24 07:10:02 EDT
Created attachment 52583 [details]
workspace with testcase

The projects in this workspace require the following:

Eclipse Modeling Framework (EMF) 
Version: 2.2.0.v200606271057
Build id: 200606271057

Eclipse Graphical Editing Framework
Version: 3.2.0.v20060626
Build id: 20060627-0816

Callers to FocusTriggeredTransactionManager.commit() (in project nl.juncus.spatial.geometrydata) cannot be found, callers to its declaration in ITransactionManager (in project nl.juncus.spatial.data) can be found. There is one caller, in nl.juncus.spatial.presentation.SpatialEditor.doSave(...).new WorkspaceModifyOperation() {...}.execute(IProgressMonitor).

I cannot get this single workspace into bugzilla because of its size. Instead I zipped each project separately and attach it separately.
Comment 6 Koen van Dijken CLA 2006-10-24 07:10:46 EDT
Created attachment 52584 [details]
second project
Comment 7 Koen van Dijken CLA 2006-10-24 07:11:23 EDT
Created attachment 52585 [details]
third project
Comment 8 Koen van Dijken CLA 2006-10-24 07:11:50 EDT
Created attachment 52586 [details]
fourth project
Comment 9 Koen van Dijken CLA 2006-10-24 07:12:19 EDT
Created attachment 52587 [details]
fifth project
Comment 10 Frederic Fusier CLA 2006-10-24 12:08:10 EDT
OK, thanks for the test case, I can now reproduce it...
Here's a small test case showing this issue: with comment 3 test case, just put each file in 3 different plugins projects.
For example:
P1 -> ITransactionManager.java
P2 -> FocusTriggeredTransactionManager.java
P3 -> Test.java

Of course, you need to export define plugins dependency to fix build errors:
P2 requires P1 and P3 also requires P1.

You need also to put ITransactionManager in a package (let say 'pack') and export this package.

Then, you'll find method reference in Test.java if you're searching from interface declaration but not from class implementation...
Comment 11 Frederic Fusier CLA 2006-10-24 12:11:55 EDT
Now, close as WORKSFORME as it is the expected behavior...
When you're searching for reference of method canCommit from FocusTriggeredTransactionManager, the reference in Test.java is not a possible match. To be one, then P3 should depends on P2. If you add this dependency, then you'll find the match
Comment 12 Koen van Dijken CLA 2006-10-24 17:19:34 EDT
(In reply to comment #11)
> Now, close as WORKSFORME as it is the expected behavior...
> When you're searching for reference of method canCommit from
> FocusTriggeredTransactionManager, the reference in Test.java is not a possible
> match. To be one, then P3 should depends on P2. If you add this dependency,
> then you'll find the match
> 

Well, I see it works the way you describe here, but I wouldn't call it expected behaviour (at least not for me :)). If I do not add the dependency of P3 depends on P2, a 'Quick Type Hierarchy' (Ctrl+T) also gives me the implementation in P2, no dependency in P2 is needed for that.

Why would you call it expected behaviour? What's the reasoning behind that?
Comment 13 Frederic Fusier CLA 2006-10-25 02:43:21 EDT
Sorry I wasn't clear enough. This is the expected behavior because in code:
          manager.canCommit(context); // THIS LINE
the reference to canCommit(Object) method _cannot_ be a reference to FocusTriggeredTransactionManager one. This is due to the fact that there's _no_ dependency between P3 and P2 and so, the object stored in manager will never be an instance of FocusTriggeredTransactionManager. If you set the dependency, then it becomes possible that the instance might be one of FocusTriggeredTransactionManager and so, the match is returned...

Hope this is more clear now
Comment 14 Koen van Dijken CLA 2006-10-25 03:11:54 EDT
Thank you Frederic,

I do understand the logic behind it now. Nevertheless it was quite confusing for me because the call in P3 to canCommit is done to the implementation in P2, and it works to great satisfaction. In our application software there is no hard 'coded' dependency between P3 and P2, and still code in P3 calls this code in P2. It does this bij using the extension point mechanism. In short: P3 asks eclipse for extension points implementing a particular interface and calls methods on it.

Would it be possible to extend the mechanism the call hierarchy/search references work in some way to tackle this kind of calls/references?

Comment 15 Frederic Fusier CLA 2006-10-25 04:13:31 EDT
(In reply to comment #14)
> Thank you Frederic,
> 
You're welcome

> I do understand the logic behind it now. Nevertheless it was quite confusing
> for me because the call in P3 to canCommit is done to the implementation in P2
> and it works to great satisfaction. In our application software there is no
> hard 'coded' dependency between P3 and P2, and still code in P3 calls this code
> in P2. It does this bij using the extension point mechanism. In short: P3 asks
> eclipse for extension points implementing a particular interface and calls
> methods on it.
> 
> Would it be possible to extend the mechanism the call hierarchy/search
> references work in some way to tackle this kind of calls/references?
> 
I'm afraid not... Extension point uses the interface to work properly and SearchEngine needs the same => it also works properly when you're searching from method declaration. If you definitely needs to find all possible callers to this method, then you need to start search from there.

If we do modify this behavior, then users would get tons of irrelevant matches (same as if he has searched for method with 'canCommit' selector using Java Search dialog) and that's what we want to avoid.
Comment 16 Koen van Dijken CLA 2006-10-25 06:03:45 EDT
(In reply to comment #15)
> 
> If we do modify this behavior, then users would get tons of irrelevant matches
> (same as if he has searched for method with 'canCommit' selector using Java
> Search dialog) and that's what we want to avoid.
> 

Is that so? Isn't there some kind of index of object declarations indexed by type? Then, find all objects of the particular interface (in any project) and check if the particular method is run on them would do the trick. No project dependencies required. (just my layman's thoughts).

I suppose the same happens for methods on adapters which are returned from the platforms adaptermanager.