|
From: <caw...@us...> - 2007-02-27 15:24:49
|
Revision: 2052
http://svn.sourceforge.net/rubyeclipse/?rev=2052&view=rev
Author: cawilliams
Date: 2007-02-27 07:24:41 -0800 (Tue, 27 Feb 2007)
Log Message:
-----------
when suggesting methods, don't suggest a method from a superclass if the subclass has overriden the method (and it's already in the list of suggestions). Also, sort method proposals by name.
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyScriptCompletion.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionProposalComparator.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-02-27 14:48:01 UTC (rev 2051)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java 2007-02-27 15:24:41 UTC (rev 2052)
@@ -2,9 +2,13 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IResource;
@@ -53,57 +57,66 @@
public class CompletionEngine {
private static final String CONSTRUCTOR_INVOKE_NAME = "new";
- private CompletionRequestor requestor;
- private CompletionContext context;
+ private CompletionRequestor fRequestor;
+ private CompletionContext fContext;
public CompletionEngine(CompletionRequestor requestor) {
- this.requestor = requestor;
+ this.fRequestor = requestor;
}
public void complete(IRubyScript script, int offset) throws RubyModelException {
- this.requestor.beginReporting();
- context = new CompletionContext(script, offset);
- if (context.emptyPrefix()) { // no prefix, so we could suggest anything
+ this.fRequestor.beginReporting();
+ fContext = new CompletionContext(script, offset);
+ if (fContext.emptyPrefix()) { // no prefix, so we could suggest anything
suggestTypeNames();
suggestConstantNames();
suggestGlobals();
getDocumentsRubyElementsInScope();
} else {
- if (context.isConstant()) { // type or constant
+ if (fContext.isConstant()) { // type or constant
suggestTypeNames();
suggestConstantNames();
}
- if (context.isMethodInvokation()) {
+ if (fContext.isMethodInvokation()) {
ITypeInferrer inferrer = new DefaultTypeInferrer();
- List<ITypeGuess> guesses = inferrer.infer(context.getCorrectedSource(), context.getOffset());
+ List<ITypeGuess> guesses = inferrer.infer(fContext.getCorrectedSource(), fContext.getOffset());
RubyElementRequestor requestor = new RubyElementRequestor(script);
for (ITypeGuess guess : guesses) {
String name = guess.getType();
IType[] types = requestor.findType(name); // FIXME When syntax is broken, grabbing type that is defined in same script like this just doesn't work!
for (int i = 0; i < types.length; i++) {
- suggestMethods(guess.getConfidence(), types[i]);
+ List<CompletionProposal> list = sort(suggestMethods(guess.getConfidence(), types[i]));
+ for (CompletionProposal proposal : list) {
+ fRequestor.accept(proposal);
+ }
}
}
} else {
// FIXME Traverse the IRubyElement model, not nodes (and don't reparse)?
getDocumentsRubyElementsInScope();
}
- if (context.isGlobal()) { // looks like a global
+ if (fContext.isGlobal()) { // looks like a global
suggestGlobals();
}
}
- this.requestor.endReporting();
- context = null;
+ this.fRequestor.endReporting();
+ fContext = null;
}
+
+ private List<CompletionProposal> sort(Map<String, CompletionProposal> proposals) {
+ List<CompletionProposal> list = new ArrayList<CompletionProposal>(proposals.values());
+ Collections.sort(list, new CompletionProposalComparator());
+ return list;
+ }
private void suggestGlobals() {
Set<String> globals = ExperimentalIndex.getGlobalNames();
// TODO Sort?
for (String name : globals) {
- if (!context.prefixStartsWith(name))
+ if (!fContext.prefixStartsWith(name))
continue;
- CompletionProposal proposal = createProposal(context.getReplaceStart(), CompletionProposal.FIELD_REF, name);
- requestor.accept(proposal);
+ CompletionProposal proposal = createProposal(fContext.getReplaceStart(), CompletionProposal.FIELD_REF, name);
+ fRequestor.accept(proposal);
}
}
@@ -111,11 +124,11 @@
Set<String> types = ExperimentalIndex.getTypeNames();
// TODO Sort?
for (String name : types) {
- if (!context.prefixStartsWith(name))
+ if (!fContext.prefixStartsWith(name))
continue;
- CompletionProposal proposal = createProposal(context.getReplaceStart(), CompletionProposal.TYPE_REF, name);
+ CompletionProposal proposal = createProposal(fContext.getReplaceStart(), CompletionProposal.TYPE_REF, name);
proposal.setType(name);
- requestor.accept(proposal);
+ fRequestor.accept(proposal);
}
}
@@ -129,33 +142,37 @@
Set<String> types = ExperimentalIndex.getConstantNames();
// TODO Sort?
for (String name : types) {
- if (!context.prefixStartsWith(name))
+ if (!fContext.prefixStartsWith(name))
continue;
- CompletionProposal proposal = createProposal(context.getReplaceStart(), CompletionProposal.FIELD_REF, name);
- requestor.accept(proposal);
+ CompletionProposal proposal = createProposal(fContext.getReplaceStart(), CompletionProposal.FIELD_REF, name);
+ fRequestor.accept(proposal);
}
}
- private void suggestMethods(int confidence, IType type) throws RubyModelException {
+ private Map<String, CompletionProposal> suggestMethods(int confidence, IType type) throws RubyModelException {
+ Map<String, CompletionProposal> proposals = new HashMap<String, CompletionProposal>();
if (type == null)
- return;
+ return proposals;
IMethod[] methods = type.getMethods();
for (int k = 0; k < methods.length; k++) {
- suggestMethod(methods[k], type.getElementName(), confidence);
- }
- // FIXME If a method name matches an existing suggestion (i.e. its overriden in the subclass), don't suggest it again!
+ 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!
+ }
+ }
String superClass = type.getSuperclassName();
- if (superClass == null) return;
+ if (superClass == null) return proposals;
RubyElementRequestor requestor = new RubyElementRequestor(type.getRubyScript());
IType[] supers = requestor.findType(superClass);
for (int i = 0; i < supers.length; i++) {
IType superType = supers[i];
- suggestMethods(confidence, superType);
+ proposals.putAll(suggestMethods(confidence, superType));
}
+ return proposals;
}
- private void suggestMethod(IMethod method, String typeName, int confidence) {
- int start = context.getReplaceStart();
+ private CompletionProposal suggestMethod(IMethod method, String typeName, int confidence) {
+ int start = fContext.getReplaceStart();
String name = method.getElementName();
int flags = Flags.AccDefault;
if (method.isSingleton()) {
@@ -167,10 +184,10 @@
} else {
// Don't show instance methods if the thing we're working on is a class' name!
// FIXME We do want to show if it is a constant, but not a class name
- if (context.fullPrefixIsConstant()) return;
+ if (fContext.fullPrefixIsConstant()) return null;
}
- if (!context.prefixStartsWith(name))
- return;
+ if (!fContext.prefixStartsWith(name))
+ return null;
try {
switch (method.getVisibility()) {
@@ -199,8 +216,7 @@
if (declaringType != null)
declaringName = declaringType.getElementName();
proposal.setDeclaringType(declaringName);
- requestor.accept(proposal);
-
+ return proposal;
}
/**
@@ -216,13 +232,13 @@
// 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 = (new RubyParser()).parse(context.getCorrectedSource());
+ Node rootNode = (new RubyParser()).parse(fContext.getCorrectedSource());
if (rootNode == null) {
return;
}
// Find the enclosing method to get locals and args
- Node enclosingMethodNode = ClosestSpanningNodeLocator.Instance().findClosestSpanner(rootNode, context.getOffset(), new INodeAcceptor() {
+ Node enclosingMethodNode = ClosestSpanningNodeLocator.Instance().findClosestSpanner(rootNode, fContext.getOffset(), new INodeAcceptor() {
public boolean doesAccept(Node node) {
return (node instanceof DefnNode || node instanceof DefsNode);
}
@@ -232,7 +248,7 @@
// Find the enclosing type (class or module) to get instance and
// classvars from
- Node enclosingTypeNode = ClosestSpanningNodeLocator.Instance().findClosestSpanner(rootNode, context.getOffset(), new INodeAcceptor() {
+ Node enclosingTypeNode = ClosestSpanningNodeLocator.Instance().findClosestSpanner(rootNode, fContext.getOffset(), new INodeAcceptor() {
public boolean doesAccept(Node node) {
return (node instanceof ClassNode || node instanceof ModuleNode);
}
@@ -260,15 +276,15 @@
List locals = Arrays.asList(scope.getVariables());
for (Iterator iter = locals.iterator(); iter.hasNext();) {
String local = (String) iter.next();
- if (!context.prefixStartsWith(local))
+ if (!fContext.prefixStartsWith(local))
continue;
matches.add(local);
}
}
for (String local : matches) { // Avoid duplicates
CompletionProposal proposal = new CompletionProposal(CompletionProposal.LOCAL_VARIABLE_REF, local, 100);
- proposal.setReplaceRange(context.getReplaceStart(), context.getReplaceStart() + local.length());
- requestor.accept(proposal);
+ proposal.setReplaceRange(fContext.getReplaceStart(), fContext.getReplaceStart() + local.length());
+ fRequestor.accept(proposal);
}
}
}
@@ -339,7 +355,7 @@
if (methodDefinition instanceof DefsNode) {
name = ((DefsNode) methodDefinition).getName();
}
- if (!context.prefixStartsWith(name))
+ if (!fContext.prefixStartsWith(name))
continue;
NodeMethod method = new NodeMethod((MethodDefNode)methodDefinition);
suggestMethod(method, typeName, 100);
@@ -371,7 +387,7 @@
// Get the unique names of instance and class variables
for (Node varNode : instanceAndClassVars) {
String name = ASTUtil.getNameReflectively(varNode);
- if (!context.prefixStartsWith(name))
+ if (!fContext.prefixStartsWith(name))
continue;
fields.add(name);
}
@@ -380,14 +396,14 @@
List<String> attrs = AttributeLocator.Instance().findInstanceAttributesInScope(typeNode);
for (Iterator iter = attrs.iterator(); iter.hasNext();) {
String attr = (String) iter.next();
- if (!context.prefixStartsWith(attr))
+ if (!fContext.prefixStartsWith(attr))
continue;
fields.add(attr);
}
for (String field : fields) {
CompletionProposal proposal = new CompletionProposal(CompletionProposal.FIELD_REF, field, 100);
- proposal.setReplaceRange(context.getReplaceStart(), context.getReplaceStart() + field.length());
- requestor.accept(proposal);
+ proposal.setReplaceRange(fContext.getReplaceStart(), fContext.getReplaceStart() + field.length());
+ fRequestor.accept(proposal);
}
}
@@ -422,7 +438,7 @@
System.out.println("Being asked for the type decl node for " + typeName);
// Find the named type
- RubyElementRequestor requestor = new RubyElementRequestor(context.getScript());
+ RubyElementRequestor requestor = new RubyElementRequestor(fContext.getScript());
IType[] types = requestor.findType(typeName);
IType type = types[0];
@@ -462,7 +478,7 @@
}
private List<String> getIncludedMixinNames(String typeName) {
- IType rubyType = new RubyType((RubyElement)context.getScript(), typeName);
+ IType rubyType = new RubyType((RubyElement)fContext.getScript(), typeName);
try {
String[] includedModuleNames = rubyType.getIncludedModuleNames();
Added: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionProposalComparator.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionProposalComparator.java (rev 0)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionProposalComparator.java 2007-02-27 15:24:41 UTC (rev 2052)
@@ -0,0 +1,13 @@
+package org.rubypeople.rdt.internal.codeassist;
+
+import java.util.Comparator;
+
+import org.rubypeople.rdt.core.CompletionProposal;
+
+public class CompletionProposalComparator implements Comparator<CompletionProposal> {
+
+ public int compare(CompletionProposal o1, CompletionProposal o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+
+}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java 2007-02-27 14:48:01 UTC (rev 2051)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java 2007-02-27 15:24:41 UTC (rev 2052)
@@ -24,7 +24,6 @@
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorPart;
import org.rubypeople.rdt.core.IRubyScript;
-import org.rubypeople.rdt.core.RubyCore;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.internal.corext.template.ruby.RubyContextType;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
@@ -111,6 +110,7 @@
cursorPosition = selection.getOffset() + selection.getLength();
List templates = determineTemplateProposals(viewer, documentOffset);
+ // FIXME Don't suggest templates or keywords if we are invoking a method?
ICompletionProposal[] templateArray = (ICompletionProposal[]) templates.toArray(new ICompletionProposal[templates
.size()]);
ICompletionProposal[] keyWordsAndTemplates = merge(templateArray, determineKeywordProposals(viewer,
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyScriptCompletion.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyScriptCompletion.java 2007-02-27 14:48:01 UTC (rev 2051)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyScriptCompletion.java 2007-02-27 15:24:41 UTC (rev 2052)
@@ -93,11 +93,11 @@
// TODO Handle potential method declarations
// acceptPotentialMethodDeclaration(proposal);
} else {
- IRubyCompletionProposal javaProposal= createRubyCompletionProposal(proposal);
- if (javaProposal != null) {
- fRubyProposals.add(javaProposal);
+ IRubyCompletionProposal rubyProposal= createRubyCompletionProposal(proposal);
+ if (rubyProposal != null) {
+ fRubyProposals.add(rubyProposal);
if (proposal.getKind() == CompletionProposal.KEYWORD)
- fKeywords.add(javaProposal);
+ fKeywords.add(rubyProposal);
}
}
} catch (IllegalArgumentException e) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|