This tutorial belongs to Eclipse JDT Tutorial Series.
I will explore how we can compute fan in i.e. find all the methods that call a particular method (all callers of a method).
In Eclipse, one can right click on a method and choose “open call hierarchy” and eclipse shows all the methods that call the selected method and all the methods that are called from the selected method (callers and callees of the selected method).
We can programtically find callers and callees and I will explain how I have done it.
There are a couple of different ways that I know:
- Use the eclipse JDT internal classes : these are the same classes used by eclipse to show the callers and callees of a method
- Use the eclipse ast visitor
In this post, I will discuss how we can use the eclipse JDT internal classes to find callers and callees of a method.
Firstly, import the following classes (as you can see they are in an “internal” package!)
import org.eclipse.jdt.internal.corext.callhierarchy.CallHierarchy; import org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper; |
Write a methodgetCallersOf that takes the selected method as an input [IMethod]. This will be your API type method, you should call this method from your program for any method whose callers you wish to find.
The crucial part of the code is to first get the default CallHierarchy object, use this CallHierarchy object to get the caller-roots of the input IMethod, and for each method-wrapper object that is returned, invoke the getCalls method. getCalls in turn returns an array of MethodWrapper objects and these are the actual callers. From each MethodWrapper object, we can get a corresponding IMethod.
public HashSet<IMethod> getCallersOf(IMethod m) { CallHierarchy callHierarchy = CallHierarchy.getDefault(); IMember[] members = {m}; MethodWrapper[] methodWrappers = callHierarchy.getCallerRoots(members); HashSet<IMethod> callers = new HashSet<IMethod>(); for (MethodWrapper mw : methodWrappers) { MethodWrapper[] mw2 = mw.getCalls(new NullProgressMonitor()); HashSet<IMethod> temp = getIMethods(mw2); callers.addAll(temp); } return callers; } HashSet<IMethod> getIMethods(MethodWrapper[] methodWrappers) { HashSet<IMethod> c = new HashSet<IMethod>(); for (MethodWrapper m : methodWrappers) { IMethod im = getIMethodFromMethodWrapper(m); if (im != null) { c.add(im); } } return c; } IMethod getIMethodFromMethodWrapper(MethodWrapper m) { try { IMember im = m.getMember(); if (im.getElementType() == IJavaElement.METHOD) { return (IMethod)m.getMember(); } } catch (Exception e) { e.printStackTrace(); } return null; } |
Some heads up here -> https://stackoverflow.com/questions/21839197/run-java-code-error-workspace-is-closed?rq=1
But this is not enough, I believe.
https://uploads.disquscdn.com/images/0454ff7885cb0771470fcf4eae3ad819645c1f84473b43558fcbe46324db859d.png
But after doing all, one will ger ‘Workspace Closed’ error. Any pointer appreciated.
Exception in thread “main” java.lang.IllegalStateException: Workspace is closed.
at org.eclipse.core.resources.ResourcesPlugin.getWorkspace(ResourcesPlugin.java:412)
at util.FindAllMethodInWorkspace.processRootDirectory(FindAllMethodInWorkspace.java:32)
at util.FindAllMethodInWorkspace.main(FindAllMethodInWorkspace.java:20)
Why did you not mentioned where your dependencies come from???
I want to get the reference on code which is not in compiling stage
Can anyone suggest the way?
I want to get the reference on code which is not in compiling stage.
I have the same problem. You could solve?
thank you
can you post the second way :
Use the eclipse ast visitor
Thank you for your helpful article .
However , My project is written in J2SE 1.3 version and i cannot change the version because of hardware reasons.Do you have any idea or any technique for finding all callers of a method in java 1.3 version.Could you please to help me answer the following question?
I don’t know. Maybe you can post this question on stackoverflow.
hi,
i’m trying to analyse the JHotDraw project to calculate the fan in metric, but i’m getting a java.lang.nullPointerException @ this line MethodWrapper[] mw2 = mw.getCalls(new NullProgressMonitor());
org.eclipse.e4.core.di.InjectionException: java.lang.NullPointerException
at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:63)
at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:231)
at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:212)
at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:131)
at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.executeHandler(HandlerServiceImpl.java:171)
at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem.executeItem(HandledContributionItem.java:831)
at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem.handleWidgetSelection(HandledContributionItem.java:724)
at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem.access$7(HandledContributionItem.java:708)
at org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem$4.handleEvent(HandledContributionItem.java:647)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4169)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3758)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1053)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:942)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:86)
at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:588)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:543)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
at org.eclipse.equinox.launcher.Main.main(Main.java:1414)
Caused by: java.lang.NullPointerException
at org.eclipse.jdt.internal.core.search.matching.ClasspathSourceDirectory.directoryTable(ClasspathSourceDirectory.java:44)
at org.eclipse.jdt.internal.core.search.matching.ClasspathSourceDirectory.findClass(ClasspathSourceDirectory.java:84)
at org.eclipse.jdt.internal.core.search.matching.JavaSearchNameEnvironment.findClass(JavaSearchNameEnvironment.java:146)
at org.eclipse.jdt.internal.core.search.matching.JavaSearchNameEnvironment.findType(JavaSearchNameEnvironment.java:185)
at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.askForType(LookupEnvironment.java:145)
at org.eclipse.jdt.internal.compiler.lookup.PackageBinding.getTypeOrPackage(PackageBinding.java:197)
at org.eclipse.jdt.internal.compiler.lookup.Scope.getTypeOrPackage(Scope.java:2795)
at org.eclipse.jdt.internal.compiler.lookup.Scope.getType(Scope.java:2513)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.getType(MatchLocator.java:899)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.getMethodBinding0(MatchLocator.java:955)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.getMethodBinding(MatchLocator.java:907)
at org.eclipse.jdt.internal.core.search.matching.MethodLocator.matchMethod(MethodLocator.java:327)
at org.eclipse.jdt.internal.core.search.matching.MethodLocator.resolveLevel(MethodLocator.java:664)
at org.eclipse.jdt.internal.core.search.matching.ClassFileMatchLocator.locateMatches(ClassFileMatchLocator.java:209)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.process(MatchLocator.java:1697)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1141)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1182)
at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1299)
at org.eclipse.jdt.internal.core.search.JavaSearchParticipant.locateMatches(JavaSearchParticipant.java:95)
at org.eclipse.jdt.internal.core.search.BasicSearchEngine.findMatches(BasicSearchEngine.java:231)
at org.eclipse.jdt.internal.core.search.BasicSearchEngine.search(BasicSearchEngine.java:515)
at org.eclipse.jdt.core.search.SearchEngine.search(SearchEngine.java:584)
at org.eclipse.jdt.internal.corext.callhierarchy.CallerMethodWrapper.findChildren(CallerMethodWrapper.java:155)
at org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper.performSearch(MethodWrapper.java:301)
at org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper.doFindChildren(MethodWrapper.java:232)
at org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper.getCalls(MethodWrapper.java:84)
at projet.aspectm.plug.handler.ExtractHandler.getCallersOf(ExtractHandler.java:206)
at projet.aspectm.plug.handler.ExtractHandler.printIMethodDetails(ExtractHandler.java:174)
at projet.aspectm.plug.handler.ExtractHandler.printIMethods(ExtractHandler.java:121)
at projet.aspectm.plug.handler.ExtractHandler.printCompilationUnitDetails(ExtractHandler.java:137)
at projet.aspectm.plug.handler.ExtractHandler.printICompilationUnitInfo(ExtractHandler.java:112)
at projet.aspectm.plug.handler.ExtractHandler.printPackageInfos(ExtractHandler.java:99)
at projet.aspectm.plug.handler.ExtractHandler.execute(ExtractHandler.java:68)
at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:290)
at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:76)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:56)
… 34 more
I used reflection to get all classes and methods from a given java project
with the method : class.getDeclaredMethods();
I want to get the callers of each method in this list or if I can do the same thing with the API org.eclipse.jdt.core or if I can find an IMethod from the method name (string) to finally use the code you proposed
thank you very much for your reply ^_^
Can you post your code here?
how I can use this code if I have a list of methods (Method [] and not IMethod []) because this code generates me the following error: Exception in thread “main” java.lang.Error: Unresolved compilation problem:
The method getCallersOf(IMethod) in the type TestingCalls is not applicable for the arguments ()