|
From: <caw...@us...> - 2007-03-09 20:17:08
|
Revision: 2122
http://svn.sourceforge.net/rubyeclipse/?rev=2122&view=rev
Author: cawilliams
Date: 2007-03-09 12:17:06 -0800 (Fri, 09 Mar 2007)
Log Message:
-----------
do some more code completion tweaking
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
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptStructureBuilder.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-03-09 17:20:36 UTC (rev 2121)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionContext.java 2007-03-09 20:17:06 UTC (rev 2122)
@@ -60,11 +60,23 @@
this.correctedSource = source.toString();
}
- public boolean isMethodInvokation() {
+ /**
+ * This is when we have a receiver and a period in the prefix
+ * @return
+ */
+ public boolean isExplicitMethodInvokation() {
return isMethodInvokation;
}
/**
+ * This is when it could be a method call with an implicit self, or when it may just be a local
+ * @return
+ */
+ public boolean isMethodInvokationOrLocal() {
+ return !isExplicitMethodInvokation() && (emptyPrefix() || Character.isLowerCase(getPartialPrefix().charAt(0)));
+ }
+
+ /**
* The last portion of prefix is not null, not empty and starts with an uppercase letter
* @return
*/
@@ -125,7 +137,7 @@
}
public boolean isGlobal() {
- return !emptyPrefix() && !isMethodInvokation() && getPartialPrefix().startsWith("$");
+ return !emptyPrefix() && !isExplicitMethodInvokation() && getPartialPrefix().startsWith("$");
}
public boolean fullPrefixIsConstant() {
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-03-09 17:20:36 UTC (rev 2121)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/CompletionEngine.java 2007-03-09 20:17:06 UTC (rev 2122)
@@ -30,6 +30,7 @@
import org.rubypeople.rdt.core.CompletionProposal;
import org.rubypeople.rdt.core.CompletionRequestor;
import org.rubypeople.rdt.core.Flags;
+import org.rubypeople.rdt.core.IMember;
import org.rubypeople.rdt.core.IMethod;
import org.rubypeople.rdt.core.IOpenable;
import org.rubypeople.rdt.core.IRubyElement;
@@ -75,7 +76,7 @@
suggestTypeNames();
suggestConstantNames();
}
- if (fContext.isMethodInvokation()) {
+ if (fContext.isExplicitMethodInvokation()) {
ITypeInferrer inferrer = new DefaultTypeInferrer();
List<ITypeGuess> guesses = inferrer.infer(fContext.getCorrectedSource(), fContext.getOffset());
RubyElementRequestor requestor = new RubyElementRequestor(script);
@@ -92,7 +93,17 @@
} else {
// FIXME If we're invoked on the class declaration (it's super class) don't do this!
// FIXME Traverse the IRubyElement model, not nodes (and don't reparse)?
- getDocumentsRubyElementsInScope();
+ if (fContext.isMethodInvokationOrLocal()) {
+ // Grab all the methods in this type and it's super/module.
+ IMember element = (IMember) script.getElementAt(fContext.getOffset());
+ IType type = element.getDeclaringType();
+ List<CompletionProposal> list = sort(suggestMethods(100, type));
+ for (CompletionProposal proposal : list) {
+ fRequestor.accept(proposal);
+ }
+ }
+ // FIXME WHat about instance and class variables?
+// getDocumentsRubyElementsInScope();
}
if (fContext.isGlobal()) { // looks like a global
suggestGlobals();
@@ -159,8 +170,41 @@
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, type));
+ proposals.putAll(addSuperClassMethods(confidence, type));
+ return proposals;
+ }
+
+ private Map<String, CompletionProposal> addModuleMethods(int confidence, IType type) {
+ Map<String, CompletionProposal> proposals = new HashMap<String, CompletionProposal>();
+ if (type.isModule()) return proposals;
+ String[] modules = null;
+ try {
+ modules = type.getIncludedModuleNames();
+ } catch (RubyModelException e) {
+ // ignore
+ }
+ if (modules == null || modules.length == 0) return proposals;
+ RubyElementRequestor requestor = new RubyElementRequestor(type.getRubyScript());
+ for (int i = 0; i < modules.length; i++) {
+ IType[] moduleTypes = requestor.findType(modules[i]);
+ for (int j = 0; j < moduleTypes.length; j++) {
+ try {
+ IType moduleType = moduleTypes[j];
+ proposals.putAll(suggestMethods(confidence, moduleType));
+ } catch (RubyModelException e) {
+ // ignore
+ }
+ }
+ }
+ return proposals;
+ }
+
+ private Map<String, CompletionProposal> addSuperClassMethods(int confidence, IType type) throws RubyModelException {
+ Map<String, CompletionProposal> proposals = new HashMap<String, CompletionProposal>();
String superClass = type.getSuperclassName();
if (superClass == null) return proposals;
+ if (type.isModule() && superClass.equals("Module")) return proposals;
RubyElementRequestor requestor = new RubyElementRequestor(type.getRubyScript());
IType[] supers = requestor.findType(superClass);
for (int i = 0; i < supers.length; i++) {
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptStructureBuilder.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptStructureBuilder.java 2007-03-09 17:20:36 UTC (rev 2121)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptStructureBuilder.java 2007-03-09 20:17:06 UTC (rev 2122)
@@ -916,89 +916,94 @@
*/
public Instruction visitFCallNode(FCallNode iVisited) {
handleNode(iVisited);
- // FIXME Evaluate self and check to see if the method exists!
if (DEBUG)
System.out.println(iVisited.getName());
String functionName = iVisited.getName();
if (functionName.equals("require") || functionName.equals("load")) {
- ArrayNode node = (ArrayNode) iVisited.getArgsNode();
- String arg = getString(node);
- if (arg != null) {
- ImportContainer importContainer = (ImportContainer) script
- .getImportContainer();
- // create the import container and its info
- if (this.importContainerInfo == null) {
- this.importContainerInfo = new RubyElementInfo();
- scriptInfo.addChild(importContainer);
- this.newElements.put(importContainer,
- this.importContainerInfo);
- }
- RubyImport handle = new RubyImport(importContainer, arg);
-
- ImportDeclarationElementInfo info = new ImportDeclarationElementInfo();
- setKeywordRange(functionName, node.getPosition(), info, arg);
- info.name = arg; // no trailing * if onDemand
-
- this.importContainerInfo.addChild(handle);
- this.newElements.put(handle, info);
- }
+ addImport(iVisited, functionName);
}
// Collect included mixins
if ( functionName.equals("include") ) {
- List<String> mixins = new LinkedList<String>();
- Node argsNode = iVisited.getArgsNode();
- Iterator iter = null;
- if (argsNode instanceof SplatNode) {
- SplatNode splat = (SplatNode) argsNode;
- iter = splat.childNodes().iterator();
+ includeModule(iVisited);
+ }
+ visitNode(iVisited.getArgsNode());
+ visitNode(iVisited.getIterNode());
+ return null;
+ }
+
+ private void addImport(FCallNode iVisited, String functionName) {
+ ArrayNode node = (ArrayNode) iVisited.getArgsNode();
+ String arg = getString(node);
+ if (arg != null) {
+ ImportContainer importContainer = (ImportContainer) script
+ .getImportContainer();
+ // create the import container and its info
+ if (this.importContainerInfo == null) {
+ this.importContainerInfo = new RubyElementInfo();
+ scriptInfo.addChild(importContainer);
+ this.newElements.put(importContainer,
+ this.importContainerInfo);
}
- else if (argsNode instanceof ArrayNode) {
- ArrayNode arrayNode = (ArrayNode) iVisited.getArgsNode();
- iter = arrayNode.iterator();
+ RubyImport handle = new RubyImport(importContainer, arg);
+
+ ImportDeclarationElementInfo info = new ImportDeclarationElementInfo();
+ setKeywordRange(functionName, node.getPosition(), info, arg);
+ info.name = arg; // no trailing * if onDemand
+
+ this.importContainerInfo.addChild(handle);
+ this.newElements.put(handle, info);
+ }
+ }
+
+ private void includeModule(FCallNode iVisited) {
+ List<String> mixins = new LinkedList<String>();
+ Node argsNode = iVisited.getArgsNode();
+ Iterator iter = null;
+ if (argsNode instanceof SplatNode) {
+ SplatNode splat = (SplatNode) argsNode;
+ iter = splat.childNodes().iterator();
+ }
+ else if (argsNode instanceof ArrayNode) {
+ ArrayNode arrayNode = (ArrayNode) iVisited.getArgsNode();
+ iter = arrayNode.iterator();
+ }
+ for (; iter.hasNext();) {
+ Node mixinNameNode = (Node) iter.next();
+ if ( mixinNameNode instanceof StrNode ) {
+ mixins.add( ((StrNode)mixinNameNode).getValue().toString() );
}
- for (; iter.hasNext();) {
- Node mixinNameNode = (Node) iter.next();
- if ( mixinNameNode instanceof StrNode ) {
- mixins.add( ((StrNode)mixinNameNode).getValue().toString() );
+ if ( mixinNameNode instanceof DStrNode ) {
+ Node next = (Node)((DStrNode)mixinNameNode).iterator().next();
+ if ( next instanceof StrNode ) {
+ mixins.add( ((StrNode)next).getValue().toString() );
}
- if ( mixinNameNode instanceof DStrNode ) {
- Node next = (Node)((DStrNode)mixinNameNode).iterator().next();
- if ( next instanceof StrNode ) {
- mixins.add( ((StrNode)next).getValue().toString() );
- }
- }
- if (mixinNameNode instanceof ConstNode) {
- mixins.add( ((ConstNode)mixinNameNode).getName() );
- }
}
+ if (mixinNameNode instanceof ConstNode) {
+ mixins.add( ((ConstNode)mixinNameNode).getName() );
+ }
+ }
+
+ // Push mixins into parent type, if available
+ if ( infoStack.peek() instanceof RubyTypeElementInfo ) {
- // Push mixins into parent type, if available
- if ( infoStack.peek() instanceof RubyTypeElementInfo ) {
-
- // Get parent type
- RubyTypeElementInfo parentType = (RubyTypeElementInfo)infoStack.peek();
+ // Get parent type
+ RubyTypeElementInfo parentType = (RubyTypeElementInfo)infoStack.peek();
- // Get existing imported module names
- String[] importedModuleNames = parentType.getIncludedModuleNames();
- List<String> mergedModuleNames = new LinkedList<String>();
-
- // Merge newly found module name(s)
- if ( importedModuleNames != null ) {
- mergedModuleNames.addAll( (Arrays.asList( importedModuleNames )));
- }
- mergedModuleNames.addAll( mixins );
-
- // Apply included module names back to parent type info
- String[] newIncludedModuleNames = mergedModuleNames.toArray(new String[]{});
- parentType.setIncludedModuleNames( newIncludedModuleNames );
+ // Get existing imported module names
+ String[] importedModuleNames = parentType.getIncludedModuleNames();
+ List<String> mergedModuleNames = new LinkedList<String>();
+
+ // Merge newly found module name(s)
+ if ( importedModuleNames != null ) {
+ mergedModuleNames.addAll( (Arrays.asList( importedModuleNames )));
}
-
+ mergedModuleNames.addAll( mixins );
+ // Apply included module names back to parent type info
+ String[] newIncludedModuleNames = mergedModuleNames.toArray(new String[]{});
+ parentType.setIncludedModuleNames( newIncludedModuleNames );
}
- visitNode(iVisited.getArgsNode());
- visitNode(iVisited.getIterNode());
- return null;
}
/**
@@ -1344,8 +1349,6 @@
info.setHandle(module);
ISourcePosition pos = iVisited.getPosition();
setKeywordRange(MODULE_KEYWORD, pos, info, name);
- // TODO Set super module better! set Module if null, set nothing if name is Module.
- info.setSuperclassName(MODULE);
infoStack.push(info);
newElements.put(module, info);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|