|
From: <jas...@us...> - 2006-08-15 04:15:52
|
Revision: 1566 Author: jasonpmorrison Date: 2006-08-14 21:15:27 -0700 (Mon, 14 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1566&view=rev Log Message: ----------- * Added support code for code completion in UI module Modified Paths: -------------- branches/type_inferrence/trunk/org.rubypeople.rdt.core/META-INF/MANIFEST.MF branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/RubyElementRequestor.java branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyProject.java branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptStructureBuilder.java branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MassIndexUpdater.java branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DefaultOccurrencesFinder.java branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/AttributeLocator.java branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/FirstPrecursorNodeLocator.java Added Paths: ----------- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/ClosestSpanningNodeLocator.java branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/MethodDefinitionLocator.java Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.core/META-INF/MANIFEST.MF =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/META-INF/MANIFEST.MF 2006-08-15 04:14:18 UTC (rev 1565) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/META-INF/MANIFEST.MF 2006-08-15 04:15:27 UTC (rev 1566) @@ -18,7 +18,9 @@ org.rubypeople.rdt.internal.core.symbols, org.rubypeople.rdt.internal.core.util, org.rubypeople.rdt.internal.formatter, - org.rubypeople.rdt.internal.ti + org.rubypeople.rdt.internal.ti, + org.rubypeople.rdt.internal.ti.util, + org.rubypeople.rdt.internal.codeassist Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.resources, org.eclipse.team.core, Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/RubyElementRequestor.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/RubyElementRequestor.java 2006-08-15 04:14:18 UTC (rev 1565) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/codeassist/RubyElementRequestor.java 2006-08-15 04:15:27 UTC (rev 1566) @@ -4,6 +4,7 @@ import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourceAttributes; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; @@ -20,7 +21,8 @@ public RubyElementRequestor(IRubyProject[] projects) { this.projects = projects; // Get path of folder containing ruby core stubs - String dirName = RubyCore.getOSDirectory(RubyCore.getPlugin()) + String rootDirName = RubyCore.getOSDirectory(RubyCore.getPlugin()); + String dirName = rootDirName + "ruby/lib"; File rubyfolder = new File(dirName); @@ -36,6 +38,25 @@ } } + // Hide ruby_core resource folder + try { + ResourceAttributes ra = folder.getResourceAttributes(); + if ( ra != null ) { + + //TODO: Doesn't hide & make readonly for some reason? + ra.setHidden(true); + ra.setReadOnly(true); + + folder.setResourceAttributes(ra); + + // Mark ruby_core as derived to keep out of source control + folder.setDerived(true); + } + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } public IType findType(String typeName) { Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyProject.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyProject.java 2006-08-15 04:14:18 UTC (rev 1565) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyProject.java 2006-08-15 04:15:27 UTC (rev 1566) @@ -77,7 +77,6 @@ * Configure the project with Ruby nature. */ public void configure() throws CoreException { - // register Ruby builder addToBuildSpec(RubyCore.BUILDER_ID); } @@ -190,7 +189,11 @@ } public int hashCode() { - return this.project.hashCode(); + if ( this.project == null ) + { + return super.hashCode() * 10 + 1; + } + return this.project.hashCode() * 10 + 2; } public boolean exists() { @@ -430,6 +433,10 @@ * @see org.rubypeople.rdt.core.IRubyElement#getElementName() */ public String getElementName() { + if ( project == null ) + { + return super.getElementName(); + } return project.getName(); } Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptStructureBuilder.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptStructureBuilder.java 2006-08-15 04:14:18 UTC (rev 1565) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptStructureBuilder.java 2006-08-15 04:15:27 UTC (rev 1566) @@ -25,7 +25,10 @@ package org.rubypeople.rdt.internal.core; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -504,7 +507,11 @@ String superClass = getSuperClassName(iVisited.getSuperNode()); info.setSuperclassName(superClass); - info.setIncludedModuleNames(new String[] { "Kernel" }); + + // FIXME Types do not explicitly include Kernel; if this is solely for completions, then Kernel elements are gotten elsewhere. + // FIXME If this must include Kernel, then completions will have to handle this differently than current. (Otherwise dupes of Kernel elements will show up when bringing together Class & its Superclass completions?) +// info.setIncludedModuleNames(new String[] { "Kernel" }); + info.setIncludedModuleNames(new String[] {}); infoStack.push(info); newElements.put(handle, info); @@ -993,6 +1000,47 @@ this.newElements.put(handle, info); } } + + // Collect included mixins + if ( functionName.equals("include") ) { + List<String> mixins = new LinkedList<String>();; + ArrayNode arrayNode = (ArrayNode) iVisited.getArgsNode(); + for (Iterator iter = arrayNode.iterator(); iter.hasNext();) { + Node mixinNameNode = (Node) iter.next(); + if ( mixinNameNode instanceof StrNode ) { + mixins.add( ((StrNode)mixinNameNode).getValue() ); + } + if ( mixinNameNode instanceof DStrNode ) { + Node next = (Node)((DStrNode)mixinNameNode).iterator().next(); + if ( next instanceof StrNode ) { + mixins.add( ((StrNode)next).getValue() ); + } + } + } + + // Push mixins into parent type, if available + if ( infoStack.peek() instanceof RubyTypeElementInfo ) { + + // 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( (List<String>)(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()); return null; } Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MassIndexUpdater.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MassIndexUpdater.java 2006-08-15 04:14:18 UTC (rev 1565) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MassIndexUpdater.java 2006-08-15 04:15:27 UTC (rev 1566) @@ -19,6 +19,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.jruby.ast.Node; +import org.jruby.lexer.yacc.SyntaxException; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.internal.core.parser.RubyParser; @@ -61,6 +62,9 @@ updater.update(file, node, false); } catch (CoreException e) { RubyCore.log(e); + } catch (SyntaxException se) { + System.err.println("Explicit catch of SyntaxError in MassIndexUpdater (jpm)"); + RubyCore.log(se); } catch (Exception ex) { // e.g: the parser currently throws a ClassCastExcpetion when parsing xmldecl.rb RubyCore.log(ex); Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DefaultOccurrencesFinder.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DefaultOccurrencesFinder.java 2006-08-15 04:14:18 UTC (rev 1565) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DefaultOccurrencesFinder.java 2006-08-15 04:15:27 UTC (rev 1566) @@ -59,14 +59,19 @@ private String source; public String initialize(String source, int offset, int length) { + if ( source == null ) { return null; } + this.source = source; try { - this.root = (new RubyParser()).parse(source); + RubyParser rubyParser = new RubyParser(); + this.root = rubyParser.parse(source); + if ( this.root == null ) { return null; } } //TODO: Is there anything else the parsing could choke on that should be silently ignored with no markings? catch (SyntaxException se) { this.root = null; + return null; } this.orig = OffsetNodeLocator.Instance().getNodeAtOffset(root, offset); if ( orig == null ) { return null; } Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/AttributeLocator.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/AttributeLocator.java 2006-08-15 04:14:18 UTC (rev 1565) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/AttributeLocator.java 2006-08-15 04:15:27 UTC (rev 1566) @@ -40,7 +40,7 @@ * @return */ public List<String> findInstanceAttributesInScope(Node rootNode) { - if ( rootNode == null ) { return null; } + if ( rootNode == null ) { return new ArrayList<String>(); } attributes = new HashSet<String>(); Added: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/ClosestSpanningNodeLocator.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/ClosestSpanningNodeLocator.java (rev 0) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/ClosestSpanningNodeLocator.java 2006-08-15 04:15:27 UTC (rev 1566) @@ -0,0 +1,86 @@ +package org.rubypeople.rdt.internal.ti.util; + +import org.jruby.ast.Node; +import org.jruby.evaluator.Instruction; + +/** + * Visitor to find the first node that precedes a given offset that satisfies a given condition. + * @author Jason Morrison + */ +public class ClosestSpanningNodeLocator extends NodeLocator { + + //Singleton pattern + private ClosestSpanningNodeLocator() {} + private static ClosestSpanningNodeLocator staticInstance = new ClosestSpanningNodeLocator(); + public static ClosestSpanningNodeLocator Instance() + { + return staticInstance; + } + + /** Offset to start searching backwards from. */ + private int offset; + + /** INodeAcceptor that defines the desired node. */ + private INodeAcceptor acceptor; + + /** Running best match for closest precursor */ + private Node locatedNode; + + /** + * Finds the closest spanning node given offset that is accepted by the acceptor. + * @param rootNode Root Node that contains all nodes to search. + * @param offset Offset to search for + * @param acceptor INodeAcceptor defining the condition which the desired node fulfills. + * @return First precursor or null. + */ + public Node findClosestSpanner(Node rootNode, int offset, INodeAcceptor acceptor ) { + locatedNode = null; + this.offset = offset; + this.acceptor = acceptor; + + // Traverse to find closest precursor + rootNode.accept(this); + + // Return the match + return locatedNode; + } + + /** + * Searches via InOrderVisitor for the closest spanning node. + */ + public Instruction handleNode(Node iVisited) + { + boolean nodeSpansOffset = nodeSpansOffset( iVisited, offset ); + boolean nodeSpansMoreCloselyThanCurrent = ( locatedNode == null ) || + ( calculateSpanLength(iVisited) <= calculateSpanLength(locatedNode) ); + + if ( nodeSpansOffset && nodeSpansMoreCloselyThanCurrent && acceptor.doesAccept( iVisited ) ) { + locatedNode = iVisited; + } + + return super.handleNode(iVisited); + } + + /** + * Determine whether the node's position spans an offset + * @param node Node to check + * @param offset Offset to check + * @return Whether it spans the offset + */ + private boolean nodeSpansOffset(Node node, int offset) { + return + ( node.getPosition().getStartOffset() <= offset ) && + ( node.getPosition().getEndOffset() >= offset ); + } + + /** + * Gets the span length of the node (endOffset - startOffset) + * @param node Node to check + * @return Span length + */ + private int calculateSpanLength(Node node) { + if ( node == null ) { return 0; } + if ( node.getPosition() == null ) { return 0; } + return node.getPosition().getEndOffset() - node.getPosition().getStartOffset(); + } +} Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/FirstPrecursorNodeLocator.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/FirstPrecursorNodeLocator.java 2006-08-15 04:14:18 UTC (rev 1565) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/FirstPrecursorNodeLocator.java 2006-08-15 04:15:27 UTC (rev 1566) @@ -1,12 +1,7 @@ package org.rubypeople.rdt.internal.ti.util; -import org.jruby.ast.DefnNode; -import org.jruby.ast.DefsNode; -import org.jruby.ast.LocalAsgnNode; -import org.jruby.ast.LocalVarNode; import org.jruby.ast.Node; import org.jruby.evaluator.Instruction; -import org.rubypeople.rdt.internal.core.parser.InOrderVisitor; /** * Visitor to find the first node that precedes a given offset that satisfies a given condition. @@ -58,10 +53,12 @@ //todo: This will include nodes that envelop nodeStart, not only those starting strictly before it. // If this behavior is unwanted, remove the || (iVisited.getPosition().getStartOffset() <= offset) // in the conditional + if (( iVisited.getPosition().getEndOffset() <= offset) || (iVisited.getPosition().getStartOffset() <= offset )) { if ( acceptor.doesAccept( iVisited ) ) { + System.out.println("Recording accepted node: " + iVisited.getClass().getSimpleName() + "@" + iVisited.getPosition().getStartOffset() + ".." + iVisited.getPosition().getEndOffset() ); locatedNode = iVisited; } } Added: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/MethodDefinitionLocator.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/MethodDefinitionLocator.java (rev 0) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/MethodDefinitionLocator.java 2006-08-15 04:15:27 UTC (rev 1566) @@ -0,0 +1,67 @@ +package org.rubypeople.rdt.internal.ti.util; + + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.jruby.ast.ArgsNode; +import org.jruby.ast.ArgumentNode; +import org.jruby.ast.ArrayNode; +import org.jruby.ast.DefnNode; +import org.jruby.ast.DefsNode; +import org.jruby.ast.Node; +import org.jruby.evaluator.Instruction; + +/** + * Visitor to find all method definitions within a specific scope. + * @author Jason Morrison + */ +public class MethodDefinitionLocator extends NodeLocator { + + //Singleton pattern + private MethodDefinitionLocator() {} + private static MethodDefinitionLocator staticInstance = new MethodDefinitionLocator(); + public static MethodDefinitionLocator Instance() + { + return staticInstance; + } + + /** Running total of results; is a Set to ensure uniqueness */ + private Set<String> methods; + + /** + * Finds all method definitions within a given node + * @param rootNode + * @return + */ + public List<String> findMethodDefinitionsInScope(Node rootNode) { + if ( rootNode == null ) { return new ArrayList<String>(); } + + methods = new HashSet<String>(); + + // Traverse to find all matches + rootNode.accept(this); + + // Return the matches + return new ArrayList<String>(methods); + } + + /** + * Searches via InOrderVisitor for matches + */ + public Instruction handleNode(Node node ) { + if ( node instanceof DefnNode ) { + methods.add( ((DefnNode)node).getName() ); + } + + if ( node instanceof DefsNode ) { + methods.add( ((DefsNode)node).getName() ); + } + + return super.handleNode(node); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |