|
From: <caw...@us...> - 2007-07-06 19:28:42
|
Revision: 2720
http://svn.sourceforge.net/rubyeclipse/?rev=2720&view=rev
Author: cawilliams
Date: 2007-07-06 12:28:39 -0700 (Fri, 06 Jul 2007)
Log Message:
-----------
more groundwork for the quick Outline and Type Hierarchy
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IMethod.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyMethod.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/RubyModelUtil.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/IRubyEditorActionDefinitionIds.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/MethodOverrideTester.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/TextMessages.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IMethod.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IMethod.java 2007-07-06 16:09:16 UTC (rev 2719)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/core/IMethod.java 2007-07-06 19:28:39 UTC (rev 2720)
@@ -43,4 +43,6 @@
public boolean isSingleton();
+ public int getNumberOfParameters() throws RubyModelException;
+
}
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java 2007-07-06 16:09:16 UTC (rev 2719)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java 2007-07-06 19:28:39 UTC (rev 2720)
@@ -736,6 +736,10 @@
public String[] getParameterNames() throws RubyModelException {
return ASTUtil.getArgs(node.getArgsNode(), node.getScope());
}
+
+ public int getNumberOfParameters() throws RubyModelException {
+ return getParameterNames().length;
+ }
public int getVisibility() throws RubyModelException {
return IMethod.PUBLIC;
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyMethod.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyMethod.java 2007-07-06 16:09:16 UTC (rev 2719)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyMethod.java 2007-07-06 19:28:39 UTC (rev 2720)
@@ -110,6 +110,10 @@
public String[] getParameterNames() throws RubyModelException {
return parameterNames;
}
+
+ public int getNumberOfParameters() throws RubyModelException {
+ return getParameterNames().length;
+ }
public boolean isSingleton() {
try {
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/MethodOverrideTester.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/MethodOverrideTester.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/MethodOverrideTester.java 2007-07-06 19:28:39 UTC (rev 2720)
@@ -0,0 +1,225 @@
+/*******************************************************************************
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.rubypeople.rdt.internal.corext.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.rubypeople.rdt.core.IMethod;
+import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.core.ITypeHierarchy;
+import org.rubypeople.rdt.core.RubyModelException;
+
+
+public class MethodOverrideTester {
+ private static class Substitutions {
+
+ public static final Substitutions EMPTY_SUBST= new Substitutions();
+
+ private HashMap fMap;
+
+ public Substitutions() {
+ fMap= null;
+ }
+
+ public void addSubstitution(String typeVariable, String substitution, String erasure) {
+ if (fMap == null) {
+ fMap= new HashMap(3);
+ }
+ fMap.put(typeVariable, new String[] { substitution, erasure });
+ }
+
+ private String[] getSubstArray(String typeVariable) {
+ if (fMap != null) {
+ return (String[]) fMap.get(typeVariable);
+ }
+ return null;
+ }
+
+ public String getSubstitution(String typeVariable) {
+ String[] subst= getSubstArray(typeVariable);
+ if (subst != null) {
+ return subst[0];
+ }
+ return null;
+ }
+
+ public String getErasure(String typeVariable) {
+ String[] subst= getSubstArray(typeVariable);
+ if (subst != null) {
+ return subst[1];
+ }
+ return null;
+ }
+ }
+
+ private final IType fFocusType;
+ private final ITypeHierarchy fHierarchy;
+
+ private Map /* <IMethod, Substitutions> */ fMethodSubstitutions;
+ private Map /* <IType, Substitutions> */ fTypeVariableSubstitutions;
+
+ public MethodOverrideTester(IType focusType, ITypeHierarchy hierarchy) {
+ fFocusType= focusType;
+ fHierarchy= hierarchy;
+ fTypeVariableSubstitutions= null;
+ fMethodSubstitutions= null;
+ }
+
+ public IType getFocusType() {
+ return fFocusType;
+ }
+
+ public ITypeHierarchy getTypeHierarchy() {
+ return fHierarchy;
+ }
+
+ /**
+ * Finds the method that declares the given method. A declaring method is the 'original' method declaration that does
+ * not override nor implement a method. <code>null</code> is returned it the given method does not override
+ * a method. When searching, super class are examined before implemented interfaces.
+ * @param testVisibility If true the result is tested on visibility. Null is returned if the method is not visible.
+ * @throws RubyModelException
+ */
+ public IMethod findDeclaringMethod(IMethod overriding, boolean testVisibility) throws RubyModelException {
+ IMethod result= null;
+ IMethod overridden= findOverriddenMethod(overriding, testVisibility);
+ while (overridden != null) {
+ result= overridden;
+ overridden= findOverriddenMethod(result, testVisibility);
+ }
+ return result;
+ }
+
+ /**
+ * Finds the method that is overridden by the given method.
+ * First the super class is examined and then the implemented interfaces.
+ * @param testVisibility If true the result is tested on visibility. Null is returned if the method is not visible.
+ * @throws RubyModelException
+ */
+ public IMethod findOverriddenMethod(IMethod overriding, boolean testVisibility) throws RubyModelException {
+ if (overriding.getVisibility() == IMethod.PRIVATE || overriding.isSingleton() || overriding.isConstructor()) {
+ return null;
+ }
+
+ IType type= overriding.getDeclaringType();
+ IType superClass= fHierarchy.getSuperclass(type);
+ if (superClass != null) {
+ IMethod res= findOverriddenMethodInHierarchy(superClass, overriding);
+ if (res != null && res.getVisibility() != IMethod.PRIVATE) {
+ if (!testVisibility || RubyModelUtil.isVisibleInHierarchy(res, type.getSourceFolder())) {
+ return res;
+ }
+ }
+ }
+ if (!overriding.isConstructor()) {
+ IType[] interfaces= fHierarchy.getSuperInterfaces(type);
+ for (int i= 0; i < interfaces.length; i++) {
+ IMethod res= findOverriddenMethodInHierarchy(interfaces[i], overriding);
+ if (res != null) {
+ return res; // methods from interfaces are always public and therefore visible
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Finds the directly overridden method in a type and its super types. First the super class is examined and then the implemented interfaces.
+ * With generics it is possible that 2 methods in the same type are overidden at the same time. In that case, the first overridden method found is returned.
+ * @param type The type to find methods in
+ * @param overriding The overriding method
+ * @return The first overridden method or <code>null</code> if no method is overridden
+ * @throws RubyModelException
+ */
+ public IMethod findOverriddenMethodInHierarchy(IType type, IMethod overriding) throws RubyModelException {
+ IMethod method= findOverriddenMethodInType(type, overriding);
+ if (method != null) {
+ return method;
+ }
+ IType superClass= fHierarchy.getSuperclass(type);
+ if (superClass != null) {
+ IMethod res= findOverriddenMethodInHierarchy(superClass, overriding);
+ if (res != null) {
+ return res;
+ }
+ }
+ if (!overriding.isConstructor()) {
+ IType[] superInterfaces= fHierarchy.getSuperInterfaces(type);
+ for (int i= 0; i < superInterfaces.length; i++) {
+ IMethod res= findOverriddenMethodInHierarchy(superInterfaces[i], overriding);
+ if (res != null) {
+ return res;
+ }
+ }
+ }
+ return method;
+ }
+
+ /**
+ * Finds an overridden method in a type. WWith generics it is possible that 2 methods in the same type are overidden at the same time.
+ * In that case the first overridden method found is returned.
+ * @param overriddenType The type to find methods in
+ * @param overriding The overriding method
+ * @return The first overridden method or <code>null</code> if no method is overridden
+ * @throws RubyModelException
+ */
+ public IMethod findOverriddenMethodInType(IType overriddenType, IMethod overriding) throws RubyModelException {
+ IMethod[] overriddenMethods= overriddenType.getMethods();
+ for (int i= 0; i < overriddenMethods.length; i++) {
+ if (isSubsignature(overriding, overriddenMethods[i])) {
+ return overriddenMethods[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Finds an overriding method in a type.
+ * @param overridingType The type to find methods in
+ * @param overridden The overridden method
+ * @return The overriding method or <code>null</code> if no method is overriding.
+ * @throws RubyModelException
+ */
+ public IMethod findOverridingMethodInType(IType overridingType, IMethod overridden) throws RubyModelException {
+ IMethod[] overridingMethods= overridingType.getMethods();
+ for (int i= 0; i < overridingMethods.length; i++) {
+ if (isSubsignature(overridingMethods[i], overridden)) {
+ return overridingMethods[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Tests if a method is a subsignature of another method.
+ * @param overriding overriding method (m1)
+ * @param overridden overridden method (m2)
+ * @return <code>true</code> iff the method <code>m1</code> is a subsignature of the method <code>m2</code>.
+ * This is one of the requirements for m1 to override m2.
+ * Accessibility and return types are not taken into account.
+ * Note that subsignature is <em>not</em> symmetric!
+ * @throws RubyModelException
+ */
+ public boolean isSubsignature(IMethod overriding, IMethod overridden) throws RubyModelException {
+ if (!overridden.getElementName().equals(overriding.getElementName())) {
+ return false;
+ }
+ int nParameters= overridden.getNumberOfParameters();
+ if (nParameters != overriding.getNumberOfParameters()) {
+ return false;
+ }
+
+ return nParameters == 0;
+ }
+
+}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/RubyModelUtil.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/RubyModelUtil.java 2007-07-06 16:09:16 UTC (rev 2719)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/corext/util/RubyModelUtil.java 2007-07-06 19:28:39 UTC (rev 2720)
@@ -5,10 +5,15 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
+import org.rubypeople.rdt.core.Flags;
+import org.rubypeople.rdt.core.IMember;
+import org.rubypeople.rdt.core.IMethod;
import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.IRubyScript;
+import org.rubypeople.rdt.core.ISourceFolder;
import org.rubypeople.rdt.core.ISourceFolderRoot;
import org.rubypeople.rdt.core.IType;
+import org.rubypeople.rdt.core.ITypeHierarchy;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.internal.core.util.CharOperation;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
@@ -171,4 +176,46 @@
}
return false;
}
+
+ public static boolean isSuperType(ITypeHierarchy hierarchy, IType possibleSuperType, IType type) {
+ // filed bug 112635 to add this method to ITypeHierarchy
+ IType superClass= hierarchy.getSuperclass(type);
+ if (superClass != null && (possibleSuperType.equals(superClass) || isSuperType(hierarchy, possibleSuperType, superClass))) {
+ return true;
+ }
+ if (Flags.isModule(hierarchy.getCachedFlags(possibleSuperType))) {
+ IType[] superInterfaces= hierarchy.getSuperInterfaces(type);
+ for (int i= 0; i < superInterfaces.length; i++) {
+ IType curr= superInterfaces[i];
+ if (possibleSuperType.equals(curr) || isSuperType(hierarchy, possibleSuperType, curr)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ /**
+ * Evaluates if a member in the focus' element hierarchy is visible from
+ * elements in a package.
+ * @param member The member to test the visibility for
+ * @param pack The package of the focus element focus
+ */
+ public static boolean isVisibleInHierarchy(IMember member, ISourceFolder pack) throws RubyModelException {
+ if (member.isType(IRubyElement.GLOBAL))
+ return true;
+ if (!member.isType(IRubyElement.METHOD))
+ return false;
+
+ IMethod method = (IMethod) member;
+
+ IType declaringType= member.getDeclaringType();
+ if (method.getVisibility() == IMethod.PUBLIC || method.getVisibility() == IMethod.PROTECTED || (declaringType != null && declaringType.isModule())) {
+ return true;
+ } else if (method.getVisibility() == IMethod.PRIVATE) {
+ return false;
+ }
+
+ ISourceFolder otherpack= (ISourceFolder) member.getAncestor(IRubyElement.SOURCE_FOLDER);
+ return (pack != null && pack.equals(otherpack));
+ }
}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.java 2007-07-06 16:09:16 UTC (rev 2719)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/RubyUIMessages.java 2007-07-06 19:28:39 UTC (rev 2720)
@@ -87,6 +87,8 @@
public static String OpenTypeAction_tooltip;
public static String OpenTypeAction_errorTitle;
public static String OpenTypeAction_errorMessage;
+ public static String RubyOutlineControl_statusFieldText_hideInheritedMembers;
+ public static String RubyOutlineControl_statusFieldText_showInheritedMembers;
private RubyUIMessages() {
}
Added: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/TextMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/TextMessages.java (rev 0)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/TextMessages.java 2007-07-06 19:28:39 UTC (rev 2720)
@@ -0,0 +1,22 @@
+package org.rubypeople.rdt.internal.ui.text;
+
+import org.eclipse.osgi.util.NLS;
+
+public class TextMessages extends NLS {
+
+ private static final String BUNDLE_NAME = TextMessages.class.getName();
+
+ public static String RubyOutlineInformationControl_GoIntoTopLevelType_label;
+ public static String RubyOutlineInformationControl_GoIntoTopLevelType_tooltip;
+ public static String RubyOutlineInformationControl_GoIntoTopLevelType_description;
+ public static String RubyOutlineInformationControl_LexicalSortingAction_label;
+ public static String RubyOutlineInformationControl_LexicalSortingAction_tooltip;
+ public static String RubyOutlineInformationControl_LexicalSortingAction_description;
+ public static String RubyOutlineInformationControl_SortByDefiningTypeAction_label;
+ public static String RubyOutlineInformationControl_SortByDefiningTypeAction_description;
+ public static String RubyOutlineInformationControl_SortByDefiningTypeAction_tooltip;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, TextMessages.class);
+ }
+}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/IRubyEditorActionDefinitionIds.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/IRubyEditorActionDefinitionIds.java 2007-07-06 16:09:16 UTC (rev 2719)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/actions/IRubyEditorActionDefinitionIds.java 2007-07-06 19:28:39 UTC (rev 2720)
@@ -149,5 +149,20 @@
*/
public static final String SEARCH_DECLARATIONS_IN_WORKING_SET= "org.rubypeople.rdt.ui.edit.text.ruby.search.declarations.in.working.set"; //$NON-NLS-1$
+ /**
+ * Action definition ID of the navigate -> Show Outline action
+ * (value <code>"org.rubypeople.rdt.ui.edit.text.ruby.show.outline"</code>).
+ *
+ * @since 1.0
+ */
+ public static final String SHOW_OUTLINE= "org.rubypeople.rdt.ui.edit.text.ruby.show.outline"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the Navigate -> Open Structure action
+ * (value <code>"org.rubypeople.rdt.ui.navigate.ruby.open.structure"</code>).
+ *
+ * @since 1.0
+ */
+ public static final String OPEN_STRUCTURE= "org.rubypeople.rdt.ui.navigate.ruby.open.structure"; //$NON-NLS-1$
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|