|
From: <caw...@us...> - 2007-08-24 17:02:22
|
Revision: 3070
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=3070&view=rev
Author: cawilliams
Date: 2007-08-24 10:02:19 -0700 (Fri, 24 Aug 2007)
Log Message:
-----------
an initial cut at #4846 - Create a Call Hierarchy View
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/plugin.properties
trunk/org.rubypeople.rdt.ui/plugin.xml
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPluginImages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/actions/ActionMessages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/actions/SelectionConverter.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyOutlinePage.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/IContextMenuConstants.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/RubyUI.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/IRubyEditorActionDefinitionIds.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/RdtActionConstants.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/SelectionDispatchAction.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/ch_callees.gif
trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/ch_callers.gif
trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/ch_cancel.gif
trunk/org.rubypeople.rdt.ui/icons/full/elcl16/ch_callees.gif
trunk/org.rubypeople.rdt.ui/icons/full/elcl16/ch_callers.gif
trunk/org.rubypeople.rdt.ui/icons/full/elcl16/ch_cancel.gif
trunk/org.rubypeople.rdt.ui/icons/full/eview16/call_hierarchy.gif
trunk/org.rubypeople.rdt.ui/icons/full/ovr16/maxlevel_co.gif
trunk/org.rubypeople.rdt.ui/icons/full/ovr16/recursive_co.gif
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallHierarchyMessages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallHierarchyVisitor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallLocation.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallSearchResultCollector.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CalleeAnalyzerVisitor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CalleeMethodWrapper.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallerMethodWrapper.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodCall.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodReferencesSearchRequestor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodWrapper.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyFiltersActionGroup.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyImageDescriptor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyLabelDecorator.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyLabelProvider.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyMessages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyMessages.properties
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyTransferDropAdapter.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyUI.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyViewPart.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyViewer.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CancelSearchAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CopyCallHierarchyAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/DeferredMethodWrapper.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/FiltersDialog.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/FocusOnSelectionAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/HistoryAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/HistoryDropDownAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/HistoryListAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/ICallHierarchyViewPart.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/LocationLabelProvider.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/LocationViewer.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/MethodWrapperWorkbenchAdapter.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/OpenLocationAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/RefreshAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/SearchScopeAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/SearchScopeActionGroup.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/SearchScopeHierarchyAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/SearchScopeProjectAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/SearchScopeWorkingSetAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/SearchScopeWorkspaceAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/SearchUtil.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/SelectWorkingSetAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/ToggleCallModeAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/ToggleOrientationAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/TreeRoot.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/TreeTermination.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/dnd/RdtViewerDropAdapter.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/packageview/SelectionTransferDropAdapter.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/OpenCallHierarchyAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/OpenTypeHierarchyAction.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/OpenViewActionGroup.java
Added: trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/ch_callees.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/ch_callees.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/ch_callers.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/ch_callers.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/ch_cancel.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/dlcl16/ch_cancel.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/icons/full/elcl16/ch_callees.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/elcl16/ch_callees.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/icons/full/elcl16/ch_callers.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/elcl16/ch_callers.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/icons/full/elcl16/ch_cancel.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/elcl16/ch_cancel.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/icons/full/eview16/call_hierarchy.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/eview16/call_hierarchy.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/icons/full/ovr16/maxlevel_co.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/ovr16/maxlevel_co.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.ui/icons/full/ovr16/recursive_co.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.ui/icons/full/ovr16/recursive_co.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: trunk/org.rubypeople.rdt.ui/plugin.properties
===================================================================
--- trunk/org.rubypeople.rdt.ui/plugin.properties 2007-08-24 16:07:58 UTC (rev 3069)
+++ trunk/org.rubypeople.rdt.ui/plugin.properties 2007-08-24 17:02:19 UTC (rev 3070)
@@ -8,6 +8,8 @@
hyperlinkProvider=Hyperlink provider
+callHierarchyViewName=Call Hierarchy
+
# Browsing
Browsing.perspectiveName= Ruby Browsing
Browsing.viewCategoryName= Ruby Browsing
Modified: trunk/org.rubypeople.rdt.ui/plugin.xml
===================================================================
--- trunk/org.rubypeople.rdt.ui/plugin.xml 2007-08-24 16:07:58 UTC (rev 3069)
+++ trunk/org.rubypeople.rdt.ui/plugin.xml 2007-08-24 17:02:19 UTC (rev 3070)
@@ -398,6 +398,12 @@
class="org.rubypeople.rdt.internal.ui.typehierarchy.TypeHierarchyViewPart"
id="org.rubypeople.rdt.ui.TypeHierarchy">
</view>
+ <view
+ category="org.rubypeople.rdt.ui.ruby"
+ class="org.rubypeople.rdt.internal.ui.callhierarchy.CallHierarchyViewPart"
+ icon="$nl$/icons/full/eview16/call_hierarchy.gif"
+ id="org.rubypeople.rdt.callhierarchy.view"
+ name="%callHierarchyViewName"/>
</extension>
<extension point="org.eclipse.ui.editors">
<editor
@@ -499,6 +505,10 @@
commandId="org.rubypeople.rdt.ui.edit.text.ruby.open.type.hierarchy"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
<key
+ sequence="CTRL+ALT+H"
+ commandId="org.rubypeople.rdt.ui.edit.text.ruby.open.call.hierarchy"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
+ <key
sequence="M1+M2+T"
contextId="org.rubypeople.rdt.ui.rubyEditorScope"
commandId="org.rubypeople.rdt.ui.edit.text.ruby.open.type"
@@ -703,6 +713,11 @@
description="%ActionDefinition.openTypeHierarchy.description"
id="org.rubypeople.rdt.ui.edit.text.ruby.open.type.hierarchy"
name="%ActionDefinition.openTypeHierarchy.name"/>
+ <command
+ categoryId="org.eclipse.ui.category.navigate"
+ description="%ActionDefinition.openCallHierarchy.description"
+ id="org.rubypeople.rdt.ui.edit.text.ruby.open.call.hierarchy"
+ name="%ActionDefinition.openCallHierarchy.name"/>
</extension>
<extension
@@ -903,6 +918,13 @@
menubarPath="navigate/open.ext"
id="org.rubypeople.rdt.ui.actions.OpenTypeHierarchy">
</action>
+ <action
+ definitionId="org.rubypeople.rdt.ui.edit.text.ruby.open.call.hierarchy"
+ label="%OpenCallHierarchyAction.label"
+ retarget="true"
+ menubarPath="navigate/open.ext"
+ id="org.rubypeople.rdt.ui.actions.OpenCallHierarchy">
+ </action>
</actionSet>
</extension>
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallHierarchyMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallHierarchyMessages.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallHierarchyMessages.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.callhierarchy;
+
+import org.eclipse.osgi.util.NLS;
+
+public final class CallHierarchyMessages extends NLS {
+
+ private static final String BUNDLE_NAME= "org.rubypeople.rdt.internal.corext.callhierarchy.CallHierarchyMessages";//$NON-NLS-1$
+
+ private CallHierarchyMessages() {
+ // Do not instantiate
+ }
+
+ public static String CallerMethodWrapper_taskname;
+ public static String CalleeMethodWrapper_taskname;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, CallHierarchyMessages.class);
+ }
+}
\ No newline at end of file
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallHierarchyMessages.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallHierarchyVisitor.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallHierarchyVisitor.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallHierarchyVisitor.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Jesper Kamstrup Linnet (ec...@ka...) - initial API and implementation
+ * (report 36180: Callers/Callees view)
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.callhierarchy;
+
+public abstract class CallHierarchyVisitor {
+ public void preVisit(MethodWrapper methodWrapper) {
+ }
+
+ public void postVisit(MethodWrapper methodWrapper) {
+ }
+
+ public boolean visit(MethodWrapper methodWrapper) {
+ return true;
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallHierarchyVisitor.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallLocation.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallLocation.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallLocation.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Jesper Kamstrup Linnet (ec...@ka...) - initial API and implementation
+ * (report 36180: Callers/Callees view)
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.callhierarchy;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.rubypeople.rdt.core.IBuffer;
+import org.rubypeople.rdt.core.IMember;
+import org.rubypeople.rdt.core.IOpenable;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+
+public class CallLocation implements IAdaptable {
+ public static final int UNKNOWN_LINE_NUMBER= -1;
+ private IMember fMember;
+ private IMember fCalledMember;
+ private int fStart;
+ private int fEnd;
+
+ private String fCallText;
+ private int fLineNumber;
+
+ public CallLocation(IMember member, IMember calledMember, int start, int end, int lineNumber) {
+ this.fMember = member;
+ this.fCalledMember = calledMember;
+ this.fStart = start;
+ this.fEnd = end;
+ this.fLineNumber= lineNumber;
+ }
+
+ /**
+ * @return IMethod
+ */
+ public IMember getCalledMember() {
+ return fCalledMember;
+ }
+
+ /**
+ *
+ */
+ public int getEnd() {
+ return fEnd;
+ }
+
+ public IMember getMember() {
+ return fMember;
+ }
+
+ /**
+ *
+ */
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getLineNumber() {
+ initCallTextAndLineNumber();
+ return fLineNumber;
+ }
+
+ public String getCallText() {
+ initCallTextAndLineNumber();
+ return fCallText;
+ }
+
+ private void initCallTextAndLineNumber() {
+ if (fCallText != null)
+ return;
+
+ IBuffer buffer= getBufferForMember();
+ if (buffer == null || buffer.getLength() < fEnd) { //binary, without source attachment || buffer contents out of sync (bug 121900)
+ fCallText= ""; //$NON-NLS-1$
+ fLineNumber= UNKNOWN_LINE_NUMBER;
+ return;
+ }
+
+ fCallText= buffer.getText(fStart, (fEnd - fStart));
+
+ if (fLineNumber == UNKNOWN_LINE_NUMBER) {
+ Document document= new Document(buffer.getContents());
+ try {
+ fLineNumber= document.getLineOfOffset(fStart) + 1;
+ } catch (BadLocationException e) {
+ RubyPlugin.log(e);
+ }
+ }
+ }
+
+ /**
+ * Returns the IBuffer for the IMember represented by this CallLocation.
+ *
+ * @return IBuffer for the IMember or null if the member doesn't have a buffer (for
+ * example if it is a binary file without source attachment).
+ */
+ private IBuffer getBufferForMember() {
+ IBuffer buffer = null;
+ try {
+ IOpenable openable = fMember.getOpenable();
+ if (openable != null && fMember.exists()) {
+ buffer = openable.getBuffer();
+ }
+ } catch (RubyModelException e) {
+ RubyPlugin.log(e);
+ }
+ return buffer;
+ }
+
+ public String toString() {
+ return getCallText();
+ }
+
+ public Object getAdapter(Class adapter) {
+ if (IRubyElement.class.isAssignableFrom(adapter)) {
+ return getMember();
+ }
+
+ return null;
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallLocation.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallSearchResultCollector.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallSearchResultCollector.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallSearchResultCollector.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Jesper Kamstrup Linnet (ec...@ka...) - initial API and implementation
+ * (report 36180: Callers/Callees view)
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.callhierarchy;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.rubypeople.rdt.core.IMember;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.IType;
+
+class CallSearchResultCollector {
+ private Map fCalledMembers;
+
+ public CallSearchResultCollector() {
+ this.fCalledMembers = createCalledMethodsData();
+ }
+
+ public Map getCallers() {
+ return fCalledMembers;
+ }
+
+ protected void addMember(IMember member, IMember calledMember, int start, int end) {
+ addMember(member, calledMember, start, end, CallLocation.UNKNOWN_LINE_NUMBER);
+ }
+
+ protected void addMember(IMember member, IMember calledMember, int start, int end, int lineNumber) {
+ if ((member != null) && (calledMember != null)) {
+ if (!isIgnored(calledMember)) {
+ MethodCall methodCall = (MethodCall) fCalledMembers.get(calledMember.getHandleIdentifier());
+
+ if (methodCall == null) {
+ methodCall = new MethodCall(calledMember);
+ fCalledMembers.put(calledMember.getHandleIdentifier(), methodCall);
+ }
+
+ methodCall.addCallLocation(new CallLocation(member, calledMember, start,
+ end, lineNumber));
+ }
+ }
+ }
+
+ protected Map createCalledMethodsData() {
+ return new HashMap();
+ }
+
+ /**
+ * Method isIgnored.
+ * @param enclosingElement
+ * @return boolean
+ */
+ private boolean isIgnored(IMember enclosingElement) {
+ IType type = getTypeOfElement(enclosingElement);
+ String fullyQualifiedName = "Object";
+ if (type != null) {
+ fullyQualifiedName = type.getFullyQualifiedName();
+ }
+
+ return CallHierarchy.getDefault().isIgnored(fullyQualifiedName);
+ }
+
+ private IType getTypeOfElement(IMember element) {
+ if (element.getElementType() == IRubyElement.TYPE) {
+ return (IType) element;
+ }
+
+ return element.getDeclaringType();
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallSearchResultCollector.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CalleeAnalyzerVisitor.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CalleeAnalyzerVisitor.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CalleeAnalyzerVisitor.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,119 @@
+package org.rubypeople.rdt.internal.corext.callhierarchy;
+
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.jruby.ast.CallNode;
+import org.jruby.ast.FCallNode;
+import org.jruby.ast.Node;
+import org.jruby.ast.VCallNode;
+import org.jruby.evaluator.Instruction;
+import org.jruby.lexer.yacc.IDESourcePosition;
+import org.jruby.lexer.yacc.ISourcePosition;
+import org.rubypeople.rdt.core.IMember;
+import org.rubypeople.rdt.core.IMethod;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.ISourceRange;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.internal.core.parser.InOrderVisitor;
+import org.rubypeople.rdt.internal.core.util.ASTUtil;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+
+class CalleeAnalyzerVisitor extends InOrderVisitor {
+
+ private IMethod fMethod;
+ private CallSearchResultCollector fSearchResults;
+ private IProgressMonitor fProgressMonitor;
+ private int fMethodStartPosition;
+ private int fMethodEndPosition;
+ private Node fCompilationUnit;
+
+ public CalleeAnalyzerVisitor(IMethod method, Node cu, IProgressMonitor progressMonitor) {
+ fSearchResults = new CallSearchResultCollector();
+ this.fMethod = method;
+ this.fCompilationUnit= cu;
+ this.fProgressMonitor = progressMonitor;
+
+ try {
+ ISourceRange sourceRange = method.getSourceRange();
+ this.fMethodStartPosition = sourceRange.getOffset();
+ this.fMethodEndPosition = fMethodStartPosition + sourceRange.getLength();
+ } catch (RubyModelException jme) {
+ RubyPlugin.log(jme);
+ }
+ }
+
+ private void addMethodCall(ISourcePosition pos) {
+ int offset = pos.getStartOffset();
+ int endOffset = pos.getEndOffset();
+ int length = endOffset - offset;
+ try {
+ IRubyElement[] elements = fMethod.getRubyScript().codeSelect(offset, length);
+ if (elements == null) return; // FIXME Only take first, what do we do?
+ for (int i = 0; i < elements.length; i++) {
+ if (elements[i] instanceof IMember) {
+ IMember member = (IMember) elements[i];
+ fSearchResults.addMember(fMethod, member, offset, endOffset, pos.getStartLine());
+ }
+ }
+ } catch (RubyModelException e) {
+ RubyPlugin.log(e);
+ }
+ }
+
+ /**
+ * Method getCallees.
+ *
+ * @return CallerElement
+ */
+ public Map getCallees() {
+ return fSearchResults.getCallers();
+ }
+
+ // FIXME When visiting types, check to see if we even need to traverse into the type...
+
+ @Override
+ public Instruction visitVCallNode(VCallNode iVisited) {
+ if (isNodeWithinMethod(iVisited)) {
+ addMethodCall(iVisited.getPosition());
+ }
+ return super.visitVCallNode(iVisited);
+ }
+
+ @Override
+ public Instruction visitFCallNode(FCallNode iVisited) {
+ if (isNodeWithinMethod(iVisited)) {
+ addMethodCall(iVisited.getPosition());// FIXME Only look up the hierarchy for the resolution
+ }
+ return super.visitFCallNode(iVisited);
+ }
+
+ @Override
+ public Instruction visitCallNode(CallNode iVisited) {
+ if (isNodeWithinMethod(iVisited)) {
+ if (iVisited.getName().equals("[]"))return super.visitCallNode(iVisited);
+ String receiver = ASTUtil.stringRepresentation(iVisited.getReceiverNode());
+ ISourcePosition original = iVisited.getPosition();
+ int start = original.getStartOffset() + receiver.length() + 1;
+ ISourcePosition pos = new IDESourcePosition(original.getFile(), original.getStartLine(), original.getEndLine(), start, original.getEndOffset());
+ addMethodCall(pos);
+ }
+ return super.visitCallNode(iVisited);
+ }
+
+ private boolean isNodeWithinMethod(Node node) {
+ int nodeStartPosition = node.getPosition().getStartOffset();
+ int nodeEndPosition = node.getPosition().getEndOffset();
+
+ if (nodeStartPosition < fMethodStartPosition) {
+ return false;
+ }
+
+ if (nodeEndPosition > fMethodEndPosition) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CalleeAnalyzerVisitor.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CalleeMethodWrapper.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CalleeMethodWrapper.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CalleeMethodWrapper.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Jesper Kamstrup Linnet (ec...@ka...) - initial API and implementation
+ * (report 36180: Callers/Callees view)
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.callhierarchy;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.jruby.ast.Node;
+import org.rubypeople.rdt.core.IMethod;
+import org.rubypeople.rdt.core.IRubyElement;
+
+class CalleeMethodWrapper extends MethodWrapper {
+ private Comparator fMethodWrapperComparator = new MethodWrapperComparator();
+
+ private static class MethodWrapperComparator implements Comparator {
+ /* (non-Rubydoc)
+ * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+ */
+ public int compare(Object o1, Object o2) {
+ MethodWrapper m1 = (MethodWrapper) o1;
+ MethodWrapper m2 = (MethodWrapper) o2;
+
+ CallLocation callLocation1 = m1.getMethodCall().getFirstCallLocation();
+ CallLocation callLocation2 = m2.getMethodCall().getFirstCallLocation();
+
+ if ((callLocation1 != null) && (callLocation2 != null)) {
+ if (callLocation1.getStart() == callLocation2.getStart()) {
+ return callLocation1.getEnd() - callLocation2.getEnd();
+ }
+
+ return callLocation1.getStart() - callLocation2.getStart();
+ }
+
+ return 0;
+ }
+ }
+
+ /**
+ * Constructor for CalleeMethodWrapper.
+ */
+ public CalleeMethodWrapper(MethodWrapper parent, MethodCall methodCall) {
+ super(parent, methodCall);
+ }
+
+ /* Returns the calls sorted after the call location
+ * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#getCalls()
+ */
+ public MethodWrapper[] getCalls(IProgressMonitor progressMonitor) {
+ MethodWrapper[] result = super.getCalls(progressMonitor);
+ Arrays.sort(result, fMethodWrapperComparator);
+
+ return result;
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#getTaskName()
+ */
+ protected String getTaskName() {
+ return CallHierarchyMessages.CalleeMethodWrapper_taskname;
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#createMethodWrapper(org.eclipse.jdt.internal.corext.callhierarchy.MethodCall)
+ */
+ protected MethodWrapper createMethodWrapper(MethodCall methodCall) {
+ return new CalleeMethodWrapper(this, methodCall);
+ }
+
+ /**
+ * Find callees called from the current method.
+ * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#findChildren(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected Map findChildren(IProgressMonitor progressMonitor) {
+ if (getMember().exists() && getMember().getElementType() == IRubyElement.METHOD) {
+ Node cu= CallHierarchy.getRubyScriptNode(getMember(), true);
+ if (progressMonitor != null) {
+ progressMonitor.worked(5);
+ }
+
+ if (cu != null) {
+ CalleeAnalyzerVisitor visitor = new CalleeAnalyzerVisitor((IMethod) getMember(),
+ cu, progressMonitor);
+
+ cu.accept(visitor);
+ return visitor.getCallees();
+ }
+ }
+ return new HashMap(0);
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CalleeMethodWrapper.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallerMethodWrapper.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallerMethodWrapper.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallerMethodWrapper.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Jesper Kamstrup Linnet (ec...@ka...) - initial API and implementation
+ * (report 36180: Callers/Callees view)
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.callhierarchy;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.rubypeople.rdt.core.IMember;
+import org.rubypeople.rdt.core.IMethod;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.core.search.IRubySearchConstants;
+import org.rubypeople.rdt.core.search.IRubySearchScope;
+import org.rubypeople.rdt.core.search.SearchEngine;
+import org.rubypeople.rdt.core.search.SearchParticipant;
+import org.rubypeople.rdt.core.search.SearchPattern;
+import org.rubypeople.rdt.internal.corext.util.SearchUtils;
+import org.rubypeople.rdt.internal.ui.RubyPlugin;
+
+class CallerMethodWrapper extends MethodWrapper {
+ public CallerMethodWrapper(MethodWrapper parent, MethodCall methodCall) {
+ super(parent, methodCall);
+ }
+
+ protected IRubySearchScope getSearchScope() {
+ return CallHierarchy.getDefault().getSearchScope();
+ }
+
+ protected String getTaskName() {
+ return CallHierarchyMessages.CallerMethodWrapper_taskname;
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#createMethodWrapper(org.eclipse.jdt.internal.corext.callhierarchy.MethodCall)
+ */
+ protected MethodWrapper createMethodWrapper(MethodCall methodCall) {
+ return new CallerMethodWrapper(this, methodCall);
+ }
+
+ /**
+ * @return The result of the search for children
+ * @see org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper#findChildren(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected Map findChildren(IProgressMonitor progressMonitor) {
+ try {
+ MethodReferencesSearchRequestor searchRequestor= new MethodReferencesSearchRequestor();
+ SearchEngine searchEngine= new SearchEngine();
+
+ IProgressMonitor monitor= new SubProgressMonitor(progressMonitor, 95, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL);
+ IRubySearchScope defaultSearchScope= getSearchScope();
+ boolean isWorkspaceScope= SearchEngine.createWorkspaceScope().equals(defaultSearchScope);
+
+ for (Iterator iter= getMembers().iterator(); iter.hasNext();) {
+ checkCanceled(progressMonitor);
+
+ IMember member= (IMember) iter.next();
+ SearchPattern pattern= SearchPattern.createPattern(member, IRubySearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
+ IRubySearchScope searchScope= isWorkspaceScope ? getAccurateSearchScope(defaultSearchScope, member) : defaultSearchScope;
+ searchEngine.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, searchScope, searchRequestor,
+ monitor);
+ }
+ return searchRequestor.getCallers();
+
+ } catch (CoreException e) {
+ RubyPlugin.log(e);
+ return new HashMap(0);
+ }
+ }
+
+ private IRubySearchScope getAccurateSearchScope(IRubySearchScope defaultSearchScope, IMember member) throws RubyModelException {
+ if (!(member.isType(IRubyElement.METHOD) && (((IMethod)member).isPrivate())))
+ return defaultSearchScope;
+
+ if (member.getRubyScript() != null) {
+ return SearchEngine.createRubySearchScope(new IRubyElement[] { member.getRubyScript() });
+ } else {
+ return defaultSearchScope;
+ }
+ }
+
+ /**
+ * Returns a collection of IMember instances representing what to search for
+ */
+ private Collection getMembers() {
+ Collection result = new ArrayList();
+
+ result.add(getMember());
+
+ return result;
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/CallerMethodWrapper.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodCall.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodCall.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodCall.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Jesper Kamstrup Linnet (ec...@ka...) - initial API and implementation
+ * (report 36180: Callers/Callees view)
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.callhierarchy;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.rubypeople.rdt.core.IMember;
+
+public class MethodCall {
+ private IMember fMember;
+ private List fCallLocations;
+
+ /**
+ * @param enclosingElement
+ */
+ public MethodCall(IMember enclosingElement) {
+ this.fMember = enclosingElement;
+ }
+
+ /**
+ *
+ */
+ public Collection getCallLocations() {
+ return fCallLocations;
+ }
+
+ public CallLocation getFirstCallLocation() {
+ if ((fCallLocations != null) && !fCallLocations.isEmpty()) {
+ return (CallLocation) fCallLocations.get(0);
+ } else {
+ return null;
+ }
+ }
+
+ public boolean hasCallLocations() {
+ return fCallLocations != null && fCallLocations.size() > 0;
+ }
+
+ /**
+ * @return Object
+ */
+ public Object getKey() {
+ return getMember().getHandleIdentifier();
+ }
+
+ /**
+ *
+ */
+ public IMember getMember() {
+ return fMember;
+ }
+
+ /**
+ * @param location
+ */
+ public void addCallLocation(CallLocation location) {
+ if (fCallLocations == null) {
+ fCallLocations = new ArrayList();
+ }
+
+ fCallLocations.add(location);
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodCall.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodReferencesSearchRequestor.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodReferencesSearchRequestor.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodReferencesSearchRequestor.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Jesper Kamstrup Linnet (ec...@ka...) - initial API and implementation
+ * (report 36180: Callers/Callees view)
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.callhierarchy;
+
+import java.util.Map;
+
+import org.rubypeople.rdt.core.IMember;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.search.SearchMatch;
+import org.rubypeople.rdt.core.search.SearchRequestor;
+
+class MethodReferencesSearchRequestor extends SearchRequestor {
+ private CallSearchResultCollector fSearchResults;
+ private boolean fRequireExactMatch = true;
+
+ MethodReferencesSearchRequestor() {
+ fSearchResults = new CallSearchResultCollector();
+ }
+
+ public Map getCallers() {
+ return fSearchResults.getCallers();
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.jdt.core.search.SearchRequestor#acceptSearchMatch(org.eclipse.jdt.core.search.SearchMatch)
+ */
+ public void acceptSearchMatch(SearchMatch match) {
+ if (fRequireExactMatch && (match.getAccuracy() != SearchMatch.A_ACCURATE)) {
+ return;
+ }
+
+ if (match.isInsideDocComment()) {
+ return;
+ }
+
+ if (match.getElement() != null && match.getElement() instanceof IMember) {
+ IMember member= (IMember) match.getElement();
+ switch (member.getElementType()) {
+ case IRubyElement.METHOD:
+ case IRubyElement.TYPE:
+ case IRubyElement.FIELD:
+ fSearchResults.addMember(member, member, match.getOffset(), match.getOffset()+match.getLength());
+ break;
+ }
+ }
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodReferencesSearchRequestor.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodWrapper.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodWrapper.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodWrapper.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,318 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Jesper Kamstrup Linnet (ec...@ka...) - initial API and implementation
+ * (report 36180: Callers/Callees view)
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.corext.callhierarchy;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+import org.rubypeople.rdt.core.IMember;
+import org.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.internal.ui.callhierarchy.MethodWrapperWorkbenchAdapter;
+
+/**
+ * This class represents the general parts of a method call (either to or from a
+ * method).
+ *
+ */
+public abstract class MethodWrapper extends PlatformObject {
+ private Map fElements = null;
+
+ /*
+ * A cache of previously found methods. This cache should be searched
+ * before adding a "new" method object reference to the list of elements.
+ * This way previously found methods won't be searched again.
+ */
+ private Map fMethodCache;
+ private MethodCall fMethodCall;
+ private MethodWrapper fParent;
+ private int fLevel;
+
+ /**
+ * Constructor CallerElement.
+ */
+ public MethodWrapper(MethodWrapper parent, MethodCall methodCall) {
+ Assert.isNotNull(methodCall);
+
+ if (parent == null) {
+ setMethodCache(new HashMap());
+ fLevel = 1;
+ } else {
+ setMethodCache(parent.getMethodCache());
+ fLevel = parent.getLevel() + 1;
+ }
+
+ this.fMethodCall = methodCall;
+ this.fParent = parent;
+ }
+
+ public Object getAdapter(Class adapter) {
+ if (adapter == IRubyElement.class) {
+ return getMember();
+ } else if (adapter == IWorkbenchAdapter.class){
+ return new MethodWrapperWorkbenchAdapter(this);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @return the child caller elements of this element
+ */
+ public MethodWrapper[] getCalls(IProgressMonitor progressMonitor) {
+ if (fElements == null) {
+ doFindChildren(progressMonitor);
+ }
+
+ MethodWrapper[] result = new MethodWrapper[fElements.size()];
+ int i = 0;
+
+ for (Iterator iter = fElements.keySet().iterator(); iter.hasNext();) {
+ MethodCall methodCall = getMethodCallFromMap(fElements, iter.next());
+ result[i++] = createMethodWrapper(methodCall);
+ }
+
+ return result;
+ }
+
+ public int getLevel() {
+ return fLevel;
+ }
+
+ public IMember getMember() {
+ return getMethodCall().getMember();
+ }
+
+ public MethodCall getMethodCall() {
+ return fMethodCall;
+ }
+
+ public String getName() {
+ if (getMethodCall() != null) {
+ return getMethodCall().getMember().getElementName();
+ } else {
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ public MethodWrapper getParent() {
+ return fParent;
+ }
+
+ public boolean equals(Object oth) {
+ if (this == oth) {
+ return true;
+ }
+
+ if (oth == null) {
+ return false;
+ }
+
+ if (oth instanceof MethodWrapperWorkbenchAdapter) {
+ //Note: A MethodWrapper is equal to a referring MethodWrapperWorkbenchAdapter and vice versa (bug 101677).
+ oth= ((MethodWrapperWorkbenchAdapter) oth).getMethodWrapper();
+ }
+
+ if (oth.getClass() != getClass()) {
+ return false;
+ }
+
+ MethodWrapper other = (MethodWrapper) oth;
+
+ if (this.fParent == null) {
+ if (other.fParent != null) {
+ return false;
+ }
+ } else {
+ if (!this.fParent.equals(other.fParent)) {
+ return false;
+ }
+ }
+
+ if (this.getMethodCall() == null) {
+ if (other.getMethodCall() != null) {
+ return false;
+ }
+ } else {
+ if (!this.getMethodCall().equals(other.getMethodCall())) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public int hashCode() {
+ final int PRIME = 1000003;
+ int result = 0;
+
+ if (fParent != null) {
+ result = (PRIME * result) + fParent.hashCode();
+ }
+
+ if (getMethodCall() != null) {
+ result = (PRIME * result) + getMethodCall().getMember().hashCode();
+ }
+
+ return result;
+ }
+
+ private void setMethodCache(Map methodCache) {
+ fMethodCache = methodCache;
+ }
+
+ protected abstract String getTaskName();
+
+ private void addCallToCache(MethodCall methodCall) {
+ Map cachedCalls = lookupMethod(this.getMethodCall());
+ cachedCalls.put(methodCall.getKey(), methodCall);
+ }
+
+ protected abstract MethodWrapper createMethodWrapper(MethodCall methodCall);
+
+ private void doFindChildren(IProgressMonitor progressMonitor) {
+ Map existingResults = lookupMethod(getMethodCall());
+
+ if (existingResults != null) {
+ fElements = new HashMap();
+ fElements.putAll(existingResults);
+ } else {
+ initCalls();
+
+ if (progressMonitor != null) {
+ progressMonitor.beginTask(getTaskName(), 100);
+ }
+
+ try {
+ performSearch(progressMonitor);
+ } finally {
+ if (progressMonitor != null) {
+ progressMonitor.done();
+ }
+ }
+
+ // ModalContext.run(getRunnableWithProgress(), true, getProgressMonitor(),
+ // Display.getCurrent());
+ }
+ }
+
+ /**
+ * Determines if the method represents a recursion call (i.e. whether the
+ * method call is already in the cache.)
+ *
+ * @return True if the call is part of a recursion
+ */
+ public boolean isRecursive() {
+ MethodWrapper current = getParent();
+
+ while (current != null) {
+ if (getMember().getHandleIdentifier().equals(current.getMember()
+ .getHandleIdentifier())) {
+ return true;
+ }
+
+ current = current.getParent();
+ }
+
+ return false;
+ }
+
+ /**
+ * This method finds the children of the current IMethod (either callers or
+ * callees, depending on the concrete subclass.
+ * @return The result of the search for children
+ */
+ protected abstract Map findChildren(IProgressMonitor progressMonitor);
+
+ private Map getMethodCache() {
+ return fMethodCache;
+ }
+
+ private void initCalls() {
+ this.fElements = new HashMap();
+
+ initCacheForMethod();
+ }
+
+ /**
+ * Looks up a previously created search result in the "global" cache.
+ * @return the List of previously found search results
+ */
+ private Map lookupMethod(MethodCall methodCall) {
+ return (Map) getMethodCache().get(methodCall.getKey());
+ }
+
+ private void performSearch(IProgressMonitor progressMonitor) {
+ fElements = findChildren(progressMonitor);
+
+ for (Iterator iter = fElements.keySet().iterator(); iter.hasNext();) {
+ checkCanceled(progressMonitor);
+
+ MethodCall methodCall = getMethodCallFromMap(fElements, iter.next());
+ addCallToCache(methodCall);
+ }
+ }
+
+ private MethodCall getMethodCallFromMap(Map elements, Object key) {
+ return (MethodCall) elements.get(key);
+ }
+
+ private void initCacheForMethod() {
+ Map cachedCalls = new HashMap();
+ getMethodCache().put(this.getMethodCall().getKey(), cachedCalls);
+ }
+
+ /**
+ * Checks with the progress monitor to see whether the creation of the type hierarchy
+ * should be canceled. Should be regularly called
+ * so that the user can cancel.
+ *
+ * @exception OperationCanceledException if cancelling the operation has been requested
+ * @see IProgressMonitor#isCanceled
+ */
+ protected void checkCanceled(IProgressMonitor progressMonitor) {
+ if (progressMonitor != null && progressMonitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ }
+
+ /**
+ * Allows a visitor to traverse the call hierarchy. The visiting is stopped when
+ * a recursive node is reached.
+ *
+ * @param visitor
+ */
+ public void accept(CallHierarchyVisitor visitor, IProgressMonitor progressMonitor) {
+ if (getParent() != null && getParent().isRecursive()) {
+ return;
+ }
+ checkCanceled(progressMonitor);
+
+ visitor.preVisit(this);
+ if (visitor.visit(this)) {
+ MethodWrapper[] methodWrappers= getCalls(progressMonitor);
+ for (int i= 0; i < methodWrappers.length; i++) {
+ methodWrappers[i].accept(visitor, progressMonitor);
+ }
+ }
+ visitor.postVisit(this);
+
+ if (progressMonitor != null) {
+ progressMonitor.worked(1);
+ }
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/callhierarchy/MethodWrapper.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPluginImages.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPluginImages.java 2007-08-24 16:07:58 UTC (rev 3069)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyPluginImages.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -193,6 +193,10 @@
public static final ImageDescriptor DESC_ELCL_VIEW_MENU= createManaged(T_ELCL, "view_menu.gif", IMG_ELCL_VIEW_MENU); //$NON-NLS-1$
public static final ImageDescriptor DESC_DLCL_VIEW_MENU= createManaged(T_DLCL, "view_menu.gif", IMG_DLCL_VIEW_MENU); //$NON-NLS-1$
+
+ // Call Hierarchy
+ public static final ImageDescriptor DESC_OVR_RECURSIVE= createUnManaged(T_OVR, "recursive_co.gif"); //$NON-NLS-1$
+ public static final ImageDescriptor DESC_OVR_MAX_LEVEL= createUnManaged(T_OVR, "maxlevel_co.gif"); //$NON-NLS-1$
public static final ImageDescriptor DESC_MISC_PUBLIC= createManagedFromKey(T_OBJ, IMG_MISC_PUBLIC);
public static final ImageDescriptor DESC_MISC_PROTECTED= createManagedFromKey(T_OBJ, IMG_MISC_PROTECTED);
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/actions/ActionMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/actions/ActionMessages.java 2007-08-24 16:07:58 UTC (rev 3069)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/actions/ActionMessages.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -68,6 +68,19 @@
public static String OpenTypeInHierarchyAction_tooltip;
public static String OpenTypeInHierarchyAction_dialogTitle;
public static String OpenTypeInHierarchyAction_dialogMessage;
+
+ public static String SelectionConverter_codeResolve_failed;
+
+ public static String OpenTypeHierarchyAction_label;
+ public static String OpenTypeHierarchyAction_tooltip;
+ public static String OpenTypeHierarchyAction_description;
+ public static String OpenTypeHierarchyAction_messages_no_ruby_element;
+ public static String OpenTypeHierarchyAction_messages_title;
+ public static String OpenTypeHierarchyAction_dialog_title;
+ public static String OpenTypeHierarchyAction_messages_no_ruby_resources;
+ public static String OpenTypeHierarchyAction_messages_unknown_import_decl;
+ public static String OpenTypeHierarchyAction_messages_no_types;
+ public static String OpenTypeHierarchyAction_messages_no_valid_ruby_element;
static {
NLS.initializeMessages(BUNDLE_NAME, ActionMessages.class);
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/actions/SelectionConverter.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/actions/SelectionConverter.java 2007-08-24 16:07:58 UTC (rev 3069)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/actions/SelectionConverter.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -175,4 +175,14 @@
return runnable.result;
}
+ public static IRubyElement[] codeResolveOrInputForked(RubyEditor editor) throws InvocationTargetException, InterruptedException {
+ IRubyElement input= getInput(editor);
+ ITextSelection selection= (ITextSelection)editor.getSelectionProvider().getSelection();
+ IRubyElement[] result= performForkedCodeResolve(input, selection);
+ if (result.length == 0) {
+ result= new IRubyElement[] {input};
+ }
+ return result;
+ }
+
}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java 2007-08-24 17:02:19 UTC (rev 3070)
@@ -0,0 +1,204 @@
+/*...
[truncated message content] |