From: <caw...@us...> - 2007-06-29 16:05:45
|
Revision: 2701 http://svn.sourceforge.net/rubyeclipse/?rev=2701&view=rev Author: cawilliams Date: 2007-06-29 09:05:43 -0700 (Fri, 29 Jun 2007) Log Message: ----------- include some code to keep track of types visited when we're recursing through type hierarchies. If we've already visited the type, we skip out. This should help avoid StackOverflows. Modified Paths: -------------- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java 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-06-27 19:21:32 UTC (rev 2700) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java 2007-06-29 16:05:43 UTC (rev 2701) @@ -75,6 +75,7 @@ private CompletionRequestor fRequestor; private CompletionContext fContext; + private Set<IType> fVisitedTypes; public CompletionEngine(CompletionRequestor requestor) { this.fRequestor = requestor; @@ -152,7 +153,7 @@ } IType[] types = requestor.findType(name); for (int i = 0; i < types.length; i++) { - Map<String, CompletionProposal> map = suggestMethods(guess.getConfidence(), types[i], true); + Map<String, CompletionProposal> map = doSuggestMethods(guess.getConfidence(), types[i], true); list.addAll(map.values()); } } @@ -262,6 +263,22 @@ fRequestor.accept(proposal); } } + + /** + * Wrap beginning of recursion to suggest methods for a type. We keep track of types visited so that we can avoid inifnite loops. + * + * @param confidence + * @param type + * @param includeInstanceMethods + * @return + * @throws RubyModelException + */ + private Map<String, CompletionProposal> suggestMethods(int confidence, IType type, boolean includeInstanceMethods) throws RubyModelException { + if (fVisitedTypes == null) fVisitedTypes = new HashSet<IType>(); + Map<String, CompletionProposal> list = doSuggestMethods(100, type, true); + fVisitedTypes.clear(); + return list; + } private List<CompletionProposal> sort(Map<String, CompletionProposal> proposals) { List<CompletionProposal> list = new ArrayList<CompletionProposal>(proposals.values()); @@ -333,10 +350,12 @@ } } - private Map<String, CompletionProposal> suggestMethods(int confidence, IType type, boolean includeInstanceMethods) throws RubyModelException { + private Map<String, CompletionProposal> doSuggestMethods(int confidence, IType type, boolean includeInstanceMethods) throws RubyModelException { Map<String, CompletionProposal> proposals = new HashMap<String, CompletionProposal>(); if (type == null) return proposals; + if (fVisitedTypes.contains(type)) return proposals; + fVisitedTypes.add(type); IMethod[] methods = type.getMethods(); for (int k = 0; k < methods.length; k++) { if (!includeInstanceMethods && !methods[k].isSingleton()) { @@ -367,7 +386,7 @@ for (int j = 0; j < moduleTypes.length; j++) { try { IType moduleType = moduleTypes[j]; - proposals.putAll(suggestMethods(confidence, moduleType, true)); + proposals.putAll(doSuggestMethods(confidence, moduleType, true)); } catch (RubyModelException e) { // ignore } @@ -384,7 +403,7 @@ IType[] supers = requestor.findType(superClass); for (int i = 0; i < supers.length; i++) { IType superType = supers[i]; - proposals.putAll(suggestMethods(confidence, superType, includeInstanceMethods)); + proposals.putAll(doSuggestMethods(confidence, superType, includeInstanceMethods)); } return proposals; } Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java 2007-06-27 19:21:32 UTC (rev 2700) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/SelectionEngine.java 2007-06-29 16:05:43 UTC (rev 2701) @@ -59,8 +59,12 @@ import org.rubypeople.rdt.internal.ti.util.INodeAcceptor; import org.rubypeople.rdt.internal.ti.util.OffsetNodeLocator; +import com.sun.corba.se.impl.io.FVDCodeBaseImpl; + public class SelectionEngine { + private HashSet<IType> fVisitedTypes; + public IRubyElement[] select(IRubyScript script, int start, int end) throws RubyModelException { String source = script.getSource(); @@ -145,7 +149,9 @@ IType[] types = getReceiver(script, source, selected, root, start); for (int i = 0; i < types.length; i++) { IType type = types[i]; + if (fVisitedTypes == null) { fVisitedTypes = new HashSet<IType>(); } // keep track of types so we don't get into infinite loop Collection<IMethod> methods = suggestMethods(type); + fVisitedTypes.clear(); for (IMethod method : methods) { if (method.getElementName().equals(methodName)) possible.add(method); @@ -231,12 +237,14 @@ private Collection<IMethod> suggestMethods(IType type) throws RubyModelException { List<IMethod> proposals = new ArrayList<IMethod>(); if (type == null) return proposals; + if (fVisitedTypes.contains(type)) return proposals; + fVisitedTypes.add(type); IMethod[] methods = type.getMethods(); for (int k = 0; k < methods.length; k++) { proposals.add(methods[k]); } proposals.addAll(addModuleMethods(type)); // Decrement confidence by one as a hack to make sure as we move up the inheritance chain we suggest "closer" parents methods first - if (!type.isModule()) proposals.addAll(addSuperClassMethods(type)); + if (!type.isModule()) proposals.addAll(addSuperClassMethods(type)); return proposals; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |