|
From: <caw...@us...> - 2007-07-09 13:54:29
|
Revision: 2729
http://svn.sourceforge.net/rubyeclipse/?rev=2729&view=rev
Author: cawilliams
Date: 2007-07-09 06:54:27 -0700 (Mon, 09 Jul 2007)
Log Message:
-----------
fix #4959 - Ctrl+Space inside a class definition autocompletes not only class methods but instance methods
Only show class methods, and don't show private class methods from types up the hierarchy
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionContext.java
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionContext.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionContext.java 2007-07-09 12:47:18 UTC (rev 2728)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionContext.java 2007-07-09 13:54:27 UTC (rev 2729)
@@ -1,7 +1,14 @@
package org.rubypeople.rdt.internal.codeassist;
+import org.jruby.ast.ClassNode;
+import org.jruby.ast.MethodDefNode;
+import org.jruby.ast.ModuleNode;
+import org.jruby.ast.Node;
import org.rubypeople.rdt.core.IRubyScript;
import org.rubypeople.rdt.core.RubyModelException;
+import org.rubypeople.rdt.internal.core.RubyScript;
+import org.rubypeople.rdt.internal.ti.util.ClosestSpanningNodeLocator;
+import org.rubypeople.rdt.internal.ti.util.INodeAcceptor;
public class CompletionContext {
@@ -184,4 +191,23 @@
return Character.isUpperCase(getFullPrefix().charAt(0));
}
+ /**
+ * Returns whether we're inside a type definition and not inside a method definition (used to determine if we should only show class level methods)
+ * @return
+ */
+ public boolean inTypeDefinition() {
+ Node spanner = ClosestSpanningNodeLocator.Instance().findClosestSpanner(getRootNode(), getOffset(), new INodeAcceptor() {
+
+ public boolean doesAccept(Node node) {
+ return node instanceof MethodDefNode || node instanceof ClassNode || node instanceof ModuleNode;
+ }
+
+ });
+ return spanner instanceof ClassNode || spanner instanceof ModuleNode;
+ }
+
+ Node getRootNode() {
+ return ((RubyScript) getScript()).lastGoodAST;
+ }
+
}
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-09 12:47:18 UTC (rev 2728)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java 2007-07-09 13:54:27 UTC (rev 2729)
@@ -52,7 +52,6 @@
import org.rubypeople.rdt.core.search.SearchParticipant;
import org.rubypeople.rdt.core.search.SearchPattern;
import org.rubypeople.rdt.internal.core.RubyElement;
-import org.rubypeople.rdt.internal.core.RubyScript;
import org.rubypeople.rdt.internal.core.RubyType;
import org.rubypeople.rdt.internal.core.parser.RubyParser;
import org.rubypeople.rdt.internal.core.search.BasicSearchEngine;
@@ -76,10 +75,14 @@
private CompletionRequestor fRequestor;
private CompletionContext fContext;
private Set<IType> fVisitedTypes;
+ /**
+ * temporary place to hold the original type we're completing for. Used to determine if we should be showing private methods.
+ */
+ private IType fOriginalType;
public CompletionEngine(CompletionRequestor requestor) {
this.fRequestor = requestor;
- }
+ }
public void complete(IRubyScript script, int offset) throws RubyModelException {
this.fRequestor.beginReporting();
@@ -258,7 +261,7 @@
type = element.getDeclaringType();
}
if (type == null) return;
- List<CompletionProposal> list = sort(suggestMethods(100, type, true));
+ List<CompletionProposal> list = sort(suggestMethods(100, type, !fContext.inTypeDefinition()));
for (CompletionProposal proposal : list) {
fRequestor.accept(proposal);
}
@@ -275,8 +278,10 @@
*/
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);
+ fOriginalType = type;
+ Map<String, CompletionProposal> list = doSuggestMethods(100, type, includeInstanceMethods);
fVisitedTypes.clear();
+ fOriginalType = null;
return list;
}
@@ -357,17 +362,18 @@
if (fVisitedTypes.contains(type)) return proposals;
fVisitedTypes.add(type);
IMethod[] methods = type.getMethods();
- if (methods == null) return proposals;
- for (int k = 0; k < methods.length; k++) {
- if (methods[k] == null) continue;
- if (!includeInstanceMethods && !methods[k].isSingleton()) {
- continue;
- }
- CompletionProposal proposal = suggestMethod(methods[k], type.getElementName(), confidence);
- if (proposal != null && !proposals.containsKey(proposal.getName())) {
- proposals.put(proposal.getName(), proposal); // If a method name matches an existing suggestion (i.e. its overriden in the subclass), don't suggest it again!
- }
- }
+ if (methods != null) {
+ for (int k = 0; k < methods.length; k++) {
+ if (methods[k] == null) continue;
+ if (!includeInstanceMethods && !methods[k].isSingleton()) {
+ continue;
+ }
+ CompletionProposal proposal = suggestMethod(methods[k], type.getElementName(), confidence);
+ if (proposal != null && !proposals.containsKey(proposal.getName())) {
+ proposals.put(proposal.getName(), proposal); // If a method name matches an existing suggestion (i.e. its overriden in the subclass), don't suggest it again!
+ }
+ }
+ }
proposals.putAll(addModuleMethods(confidence - 1, 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.putAll(addSuperClassMethods(confidence - 1, type, includeInstanceMethods));
return proposals;
@@ -435,6 +441,7 @@
switch (method.getVisibility()) {
case IMethod.PRIVATE:
flags |= Flags.AccPrivate;
+ if (!fOriginalType.getElementName().equals(typeName)) return null; // FIXME We should do a comparison of types, not names
if (fContext.hasReceiver()) return null; // can't invoke a private method on a receiver
break;
case IMethod.PUBLIC:
@@ -475,7 +482,7 @@
// FIXME Try to stop all the multiple re-parsing of the source! Can
// we parse once and pass the root node around?
// Parse
- Node rootNode = ((RubyScript) fContext.getScript()).lastGoodAST;
+ Node rootNode = fContext.getRootNode();
if (rootNode == null) {
return;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|