You can subscribe to this list here.
| 2005 |
Jan
|
Feb
|
Mar
(41) |
Apr
(9) |
May
|
Jun
|
Jul
(39) |
Aug
(38) |
Sep
(135) |
Oct
(220) |
Nov
(75) |
Dec
(74) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2006 |
Jan
(44) |
Feb
(160) |
Mar
(49) |
Apr
(69) |
May
(40) |
Jun
(52) |
Jul
(47) |
Aug
(51) |
Sep
(19) |
Oct
(22) |
Nov
(36) |
Dec
(76) |
| 2007 |
Jan
(154) |
Feb
(165) |
Mar
(186) |
Apr
(143) |
May
(175) |
Jun
(133) |
Jul
(203) |
Aug
(177) |
Sep
(136) |
Oct
|
Nov
|
Dec
|
|
From: <jas...@us...> - 2006-08-21 08:31:35
|
Revision: 1577 Author: jasonpmorrison Date: 2006-08-21 01:31:18 -0700 (Mon, 21 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1577&view=rev Log Message: ----------- * Added test to old type inferrer a while ago Modified Paths: -------------- branches/type_inferrence/trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTest.java Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTest.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTest.java 2006-08-21 08:30:19 UTC (rev 1576) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTest.java 2006-08-21 08:31:18 UTC (rev 1577) @@ -63,6 +63,12 @@ assertInfersTypeWithoutDoubt(inferrer.infer(script, 10), "Fixnum"); // "y" } + public void testLocalVariableAssignmentToLocalVariableTwice() throws Exception { + String script = "x=5;y=x;z=y;z;y;x"; + assertInfersTypeWithoutDoubt(inferrer.infer(script, 12), "Fixnum"); // "z" + assertInfersTypeWithoutDoubt(inferrer.infer(script, 14), "Fixnum"); // "y" + assertInfersTypeWithoutDoubt(inferrer.infer(script, 16), "Fixnum"); // "x" + } public void testLocalVariableAssignmentToWellKnownMethodCall() throws Exception { assertInfersTypeWithoutDoubt(inferrer.infer("x=5.to_s;x", 9), "String"); } @@ -70,6 +76,9 @@ public void testLocalVariableAssignmentToClassInstantiation() throws Exception { assertInfersTypeWithoutDoubt(inferrer.infer("x=Regexp.new;x", 13), "Regexp"); } + + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <jas...@us...> - 2006-08-21 08:31:00
|
Revision: 1576 Author: jasonpmorrison Date: 2006-08-21 01:30:19 -0700 (Mon, 21 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1576&view=rev Log Message: ----------- * First rough cut of DataFlowTypeInferrer! Modified 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 Added Paths: ----------- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DataFlowTypeInferrer.java branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/TypeInferenceHelper.java branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/MethodInvocationLocator.java Added: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DataFlowTypeInferrer.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DataFlowTypeInferrer.java (rev 0) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DataFlowTypeInferrer.java 2006-08-21 08:30:19 UTC (rev 1576) @@ -0,0 +1,578 @@ +package org.rubypeople.rdt.internal.ti; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.jruby.ast.ArgsNode; +import org.jruby.ast.CallNode; +import org.jruby.ast.ClassNode; +import org.jruby.ast.ClassVarAsgnNode; +import org.jruby.ast.ClassVarDeclNode; +import org.jruby.ast.ClassVarNode; +import org.jruby.ast.Colon2Node; +import org.jruby.ast.ConstNode; +import org.jruby.ast.DAsgnNode; +import org.jruby.ast.DVarNode; +import org.jruby.ast.DefnNode; +import org.jruby.ast.DefsNode; +import org.jruby.ast.FCallNode; +import org.jruby.ast.GlobalAsgnNode; +import org.jruby.ast.GlobalVarNode; +import org.jruby.ast.InstAsgnNode; +import org.jruby.ast.InstVarNode; +import org.jruby.ast.ListNode; +import org.jruby.ast.LocalAsgnNode; +import org.jruby.ast.LocalVarNode; +import org.jruby.ast.ModuleNode; +import org.jruby.ast.Node; +import org.jruby.ast.ReturnNode; +import org.jruby.ast.SelfNode; +import org.jruby.ast.VCallNode; +import org.rubypeople.rdt.internal.core.parser.RubyParser; +import org.rubypeople.rdt.internal.ti.data.ConstNodeTypeNames; +import org.rubypeople.rdt.internal.ti.util.ClosestSpanningNodeLocator; +import org.rubypeople.rdt.internal.ti.util.INodeAcceptor; +import org.rubypeople.rdt.internal.ti.util.MethodDefinitionLocator; +import org.rubypeople.rdt.internal.ti.util.MethodInvocationLocator; +import org.rubypeople.rdt.internal.ti.util.OffsetNodeLocator; +import org.rubypeople.rdt.internal.ti.util.ScopedNodeLocator; + +public class DataFlowTypeInferrer extends Object implements ITypeInferrer { + private void sysout(String string) { + // false to suppress debug + if ( true ) { + System.out.println(string); + } + } + + private void prettyPrint(Node node) { + sysout( "----------------------------------------\n" + + "Node: " + node.getClass().getSimpleName() + "\n" + + "Source:\n[" + node.getPosition().getStartOffset() + ".." + node.getPosition().getEndOffset() + "]\n" + + source.substring( node.getPosition().getStartOffset(), node.getPosition().getEndOffset() + 1 ) + "\n" + + "----------------------------------------" ); + } + + TypeInferenceHelper helper; + private String source; + private Node rootNode; + + // To detect cycles in dataflow graph + private List<Node> inferNodeStack; + + + public List<ITypeGuess> infer(String source, int offset) { + List<ITypeGuess> guesses = new LinkedList<ITypeGuess>(); + + this.helper = TypeInferenceHelper.Instance(); + this.source = source; + this.rootNode = (new RubyParser()).parse(source); + this.inferNodeStack = new LinkedList<Node>(); + + Node node = OffsetNodeLocator.Instance().getNodeAtOffset(rootNode, offset); + + if ( node == null ) { return null; } + + guesses = inferNodeType(node); + + guesses = redistributeGuessConfidences(guesses); + + return guesses; + } + + /** + * Redistribute the confidence percentages. I.e. if guesses contains three guesses, each at 100%, they will now each be 33%. + * @param guesses Guesses to redistribute + * @return Guesses with confidences redistributes + */ + private List<ITypeGuess> redistributeGuessConfidences( List<ITypeGuess> guesses ) { + int sum = 0; + for ( ITypeGuess guess : guesses ) { + sum += guess.getConfidence(); + } + + List<ITypeGuess> newGuesses = new ArrayList<ITypeGuess>(guesses.size()); + for ( ITypeGuess guess : guesses ) { + ITypeGuess newGuess = new BasicTypeGuess( guess.getType(), (int)(((double)guess.getConfidence()) / ((double)sum) * 100.0 ) ); + newGuesses.add( newGuess ); + } + + return newGuesses; + } + + // Infer the type of specified node + private List<ITypeGuess> inferNodeType(Node node) { + + sysout("Inferring node: " + node.getClass().getSimpleName()); + List<ITypeGuess> guesses = new ArrayList<ITypeGuess>(1); + + // Detect cycles in data flow graph + if ( inferNodeStack.indexOf( node ) != -1 ) { + sysout("Data flow graph cycle detected:"); + prettyPrint(node); + return guesses; + } + + // Push node onto stack + inferNodeStack.add( 0, node ); + + if ( isSelfReferenceNode( node ) ) { + guesses.add( getSelfReferenceNodeType( node ) ); + } + + if ( isAssignmentNode( node ) ) { + guesses.addAll( inferNodeType( getAssignmentNodeValueNode( node ) ) ); + } + + if ( isTypeDefinitionNode( node ) ) { + guesses.add( getTypeDefinitionNodeType( node ) ); + } + + if ( isConstantNode( node ) ) { + guesses.add( getConstantNodeType( node ) ); + } + + if ( node instanceof LocalVarNode ) { + guesses.addAll( getLocalVarReferenceNodeTypes( (LocalVarNode)node ) ); + } + + if ( node instanceof DVarNode ) { + guesses.addAll( getDVarReferenceNodeTypes( (DVarNode)node ) ); + } + + if ( node instanceof InstVarNode ) { + guesses.addAll( getInstanceVarReferenceNodeTypes( (InstVarNode)node ) ); + } + + if ( node instanceof ClassVarNode ) { + guesses.addAll( getClassVarReferenceNodeTypes( (ClassVarNode)node ) ); + } + + if ( node instanceof GlobalVarNode ) { + guesses.addAll( getGlobalVarReferenceNodeTypes( (GlobalVarNode)node ) ); + } + + if ( isCallNode( node ) ) { + guesses.addAll( getCallNodeTypes( node ) ); + } + + +// PSEUDOCODE: +// if ( element is_a(instvar or global)) { +//ALREADY USING THIS: +// types = sum(typeOfEach(getThingsAssignedInto(element, :within => element.lexicalScope))); +// return types if any found; +//CAN STILL FALLBACK TO: +// //otherwise +// usages = list of places where element is passed as a param; +// sameTypedElements = list of elements passed into the same method-param-location element is; +// types = sum(typeOfEach(sameTypedElements)); +// return types if any found; +//CAN STILL FALLBACK TO: +// //otherwise +// methods = list of methods invoked against element; +// types = sum(typesRespondingToAllOfThese); +// return types; +// } +// if ( element is_a(method invocation)) { +//ALREADY USING THIS: +// klass = typeOf(receiver); +// +// // nice special case: check for accessors/mutators +// // hook for "magic" combinations; (class << ActiveRecord::Base).find(*) => ArrayOf[klass], etc. +// +// defNode = findDefinition(receiver,method_name); +// return findReturnedTypesInDefNode(); +// } + + + // Pop node from stack + inferNodeStack.remove(0); + + return guesses; + + } + + private boolean isConstantNode(Node node) { + return ( node instanceof ConstNode ) || ( null != ConstNodeTypeNames.get(node.getClass().getSimpleName() ) ); + } + + // Look up from ConstNodeTypeNames + private ITypeGuess getConstantNodeType(Node node) { + if ( node instanceof ConstNode ) { + return new BasicTypeGuess( ((ConstNode)node).getName(), 100 ); + } else { + return new BasicTypeGuess( ConstNodeTypeNames.get(node.getClass().getSimpleName()), 100 ); + } + } + + private boolean isTypeDefinitionNode(Node node) { + return ( node instanceof ClassNode ) || ( node instanceof ModuleNode ); + } + + private ITypeGuess getTypeDefinitionNodeType(Node node) { + String typeNodeName = helper.getTypeNodeName( node ); + if ( typeNodeName != null ) { + return new BasicTypeGuess( typeNodeName, 100 ); + } + return null; + } + + private boolean isSelfReferenceNode(Node node) { + return ( node instanceof SelfNode); + } + + private ITypeGuess getSelfReferenceNodeType( Node node ) { + Node enclosingTypeNode = findEnclosingTypeNode( node ); + return getTypeDefinitionNodeType( enclosingTypeNode ); + } + + private List<Node> findAllSendersOfMethod( String typeName, String methodName ) { + return MethodInvocationLocator.Instance().findMethodInvocations( rootNode, source, typeName, methodName, new DataFlowTypeInferrer() ); + } + + private List<Node> findAllMethodDefinitions( String typeName, String methodName ) { + return MethodDefinitionLocator.Instance().findMethodDefinitions( rootNode, source, typeName, methodName ); + } + + private List<Node> findRetvalExprs( Node methodNode ) { + + + //TODO: Does this handle implicit returns?? + + List<Node> returnNodes = ScopedNodeLocator.Instance().findNodesInScope(methodNode, new INodeAcceptor() { + public boolean doesAccept(Node node) { + return ( node instanceof ReturnNode ); + } + }); + + List<Node> retvalExprs = new ArrayList<Node>(returnNodes.size()); + for ( Node returnNode : returnNodes ) { + retvalExprs.add( ((ReturnNode)returnNode).getValueNode() ); + } + + sysout("Found " + retvalExprs.size() + " + retval exprs in method " + helper.getMethodDefinitionNodeName( methodNode )); + + return retvalExprs; + } + + private Node findEnclosingMethodNode(Node node) { + Node enclosingScopeNode = ClosestSpanningNodeLocator.Instance().findClosestSpanner(rootNode, node.getPosition().getStartOffset(), new INodeAcceptor() { + public boolean doesAccept(Node node) { + return ( node instanceof DefnNode ) || + ( node instanceof DefsNode ); + } + }); + + if ( enclosingScopeNode == null ) { + enclosingScopeNode = rootNode; + } + + return enclosingScopeNode; + } + + private Node findEnclosingTypeNode(Node node) { + Node enclosingTypeNode = ClosestSpanningNodeLocator.Instance().findClosestSpanner(rootNode, node.getPosition().getStartOffset(), new INodeAcceptor() { + public boolean doesAccept(Node node) { + return ( node instanceof ClassNode ) || ( node instanceof ModuleNode ); + } + }); + + // TODO: Handle reference inside metaclass block: + // class << foo; [[INFER]] ..... + + if ( enclosingTypeNode == null ) { + enclosingTypeNode = rootNode; + } + + return enclosingTypeNode; + } + + private List<ITypeGuess> getLocalVarReferenceNodeTypes(LocalVarNode node) { + List<ITypeGuess> possibleTypes = new ArrayList<ITypeGuess>(1); + + + // Get enclosing scope + Node enclosingScopeNode = findEnclosingMethodNode( node ); + if ( enclosingScopeNode == rootNode ) { + sysout("localvarnode outside a method!"); + enclosingScopeNode = findEnclosingTypeNode( node ); + } + + //TODO: ScopedNodeLocator doesn't ensure that returned asgns are prior to the ref... relevant to algo? + // Are there prior assigns into this ref within the scope? + final String localVarName = helper.getVarName(source, node); + + List<Node> localAssignsIntoNode = ScopedNodeLocator.Instance().findNodesInScope(enclosingScopeNode, new INodeAcceptor() { + public boolean doesAccept(Node acceptNode) { + if ( acceptNode instanceof LocalAsgnNode ) { + return ( ((LocalAsgnNode)acceptNode).getName().equals( localVarName ) ); + } + return false; + } + }); + + // If so, return the sum of the RHSes' type inferences + if ( ( localAssignsIntoNode != null ) && ( localAssignsIntoNode.size() > 0 ) ) { + for ( Node asgnNode : localAssignsIntoNode ) { + possibleTypes.addAll( inferNodeType( ((LocalAsgnNode)asgnNode).getValueNode() ) ); + } + return possibleTypes; + } + + + // No prior assigns; if is an arg, find send-exprs into that arg, return sum of their inferences + if ( helper.isArgumentInMethod( localVarName, enclosingScopeNode ) ) { + + // Rename for clarity + Node enclosingMethodNode = enclosingScopeNode; + + sysout("Is arg in method"); + // Get enclosing type name + Node enclosingTypeNode = findEnclosingTypeNode(node); + String enclosingTypeName = "Kernel"; + if ( enclosingTypeNode != rootNode ) { + enclosingTypeName = helper.getTypeNodeName( enclosingTypeNode ); + } + + // Get enclosing method name + String enclosingMethodName = helper.getMethodDefinitionNodeName( enclosingMethodNode ); + + sysout("Inferring type of argument " + localVarName + " in method " + enclosingMethodName ); + + // Find index of param + ListNode argsListNode = helper.getArgsListNode( enclosingMethodNode ); + int paramIndex = helper.getArgIndex( argsListNode, localVarName ); + + // Find all send-exprs to the enclosing method + List<Node> sendExprs = findAllSendersOfMethod( enclosingTypeName, enclosingMethodName ); + sysout( "Found " + sendExprs.size() + " senders: " ); + + + // Find all arg-exprs in the send-exprs that flow into the local var + List<Node> argExprs = new ArrayList<Node>(sendExprs.size()); + for ( Node sendExpr : sendExprs ) { + prettyPrint(sendExpr); + argExprs.add( helper.findNthArgExprInSendExpr( paramIndex, sendExpr ) ); + } + + sysout("Inflowing argexprs:" + argExprs.size()); + // Sum the inferred type of each arg-exprs that flows into the local var + for ( Node argExpr : argExprs ) { + prettyPrint(argExpr); + possibleTypes.addAll( inferNodeType(argExpr) ); + } + + return possibleTypes; + } + + sysout("bottom"); + + // No prior assigns and is not an arg; return empty set of guesses. + return possibleTypes; + + } + + private List<ITypeGuess> getDVarReferenceNodeTypes(DVarNode node) { + List<ITypeGuess> possibleTypes = new ArrayList<ITypeGuess>(1); + + Node enclosingScopeNode = findEnclosingMethodNode( node ); + if ( enclosingScopeNode == rootNode ) { + enclosingScopeNode = findEnclosingTypeNode( node ); + } + + // Find assignments into this variable + final String varName = node.getName(); + List<Node> dynAsgnNodes = ScopedNodeLocator.Instance().findNodesInScope(enclosingScopeNode, new INodeAcceptor() { + public boolean doesAccept(Node acceptNode) { + if ( acceptNode instanceof DAsgnNode ) { + return ( ((DAsgnNode)acceptNode).getName().equals( varName ) ); + } + return false; + } + }); + + // Sum the inferred type of assignment RHSes + if ( dynAsgnNodes != null ) { + for ( Node dynAsgnNode : dynAsgnNodes ) { + possibleTypes.addAll( inferNodeType( ((DAsgnNode)dynAsgnNode).getValueNode() ) ); + } + } + + return possibleTypes; + } + + private List<ITypeGuess> getInstanceVarReferenceNodeTypes(InstVarNode node) { + List<ITypeGuess> possibleTypes = new ArrayList<ITypeGuess>(1); + + Node enclosingTypeNode = findEnclosingTypeNode( node ); + + // Find assignments into this variable + final String instanceVarName = helper.getVarName(source, node); + List<Node> instAsgnNodes = ScopedNodeLocator.Instance().findNodesInScope(enclosingTypeNode, new INodeAcceptor() { + public boolean doesAccept(Node acceptNode) { + if ( acceptNode instanceof InstAsgnNode ) { + return ( ((InstAsgnNode)acceptNode).getName().equals( instanceVarName ) ); + } + return false; + } + }); + + //TODO: also collect calls to [parentype].instvarname= + + // Sum the inferred type of assignment RHSes + if ( instAsgnNodes != null ) { + for ( Node instAsgnNode : instAsgnNodes ) { + possibleTypes.addAll( inferNodeType( ((InstAsgnNode)instAsgnNode).getValueNode() ) ); + } + } + + return possibleTypes; + } + + private List<ITypeGuess> getClassVarReferenceNodeTypes(ClassVarNode node) { + List<ITypeGuess> possibleTypes = new ArrayList<ITypeGuess>(1); + + Node enclosingTypeNode = findEnclosingTypeNode( node ); + + // Find assignments into this variable + final String classVarName = helper.getVarName(source, node); + prettyPrint(enclosingTypeNode); + List<Node> classAsgnNodes = ScopedNodeLocator.Instance().findNodesInScope(enclosingTypeNode, new INodeAcceptor() { + public boolean doesAccept(Node acceptNode) { + if ( acceptNode instanceof ClassVarAsgnNode ) { + return ( ((ClassVarAsgnNode)acceptNode).getName().equals( classVarName ) ); + } else if ( acceptNode instanceof ClassVarDeclNode ) { + return ( ((ClassVarDeclNode)acceptNode).getName().equals( classVarName ) ); + } + return false; + } + }); + + //TODO: class Klass;@@x=5;@@x=6;@@x;end # @@x=5 is parsed as a ClassDeclNode, and so is @@x=6. Do ClassAsgnNodes ever pop up??? + + + //TODO: also collect calls to [parentypeklass].classvarname= + + // Sum the inferred type of assignment RHSes + if ( classAsgnNodes != null ) { + sysout("asgns not null: " + classAsgnNodes.size()); + for ( Node classAsgnNode : classAsgnNodes ) { + if ( classAsgnNode instanceof ClassVarAsgnNode ) { + possibleTypes.addAll( inferNodeType( ((ClassVarAsgnNode)classAsgnNode).getValueNode() ) ); + } + if ( classAsgnNode instanceof ClassVarDeclNode ) { + possibleTypes.addAll( inferNodeType( ((ClassVarDeclNode)classAsgnNode).getValueNode() ) ); + } + } + } + + return possibleTypes; + } + + private List<ITypeGuess> getGlobalVarReferenceNodeTypes(GlobalVarNode node) { + List<ITypeGuess> possibleTypes = new ArrayList<ITypeGuess>(1); + + // Find assignments into this variable + final String globalVarName = helper.getVarName(source, node); + List<Node> globalAsgnNodes = ScopedNodeLocator.Instance().findNodesInScope(rootNode, new INodeAcceptor() { + public boolean doesAccept(Node acceptNode) { + if ( acceptNode instanceof GlobalAsgnNode ) { + return ( ((GlobalAsgnNode)acceptNode).getName().equals( globalVarName ) ); + } + return false; + } + }); + + // Sum the inferred type of assignment RHSes + for ( Node globalAsgnNode : globalAsgnNodes ) { + possibleTypes.addAll( inferNodeType( ((GlobalAsgnNode)globalAsgnNode).getValueNode() ) ); + } + + return possibleTypes; + } + + + private boolean isAssignmentNode( Node node ) { + return ( node instanceof LocalAsgnNode ) || ( node instanceof InstAsgnNode ) || ( node instanceof GlobalAsgnNode ); + } + + private Node getAssignmentNodeValueNode( Node node ) { + if ( node instanceof InstAsgnNode ) { return ((InstAsgnNode)node).getValueNode(); } + if ( node instanceof LocalAsgnNode ) { return ((LocalAsgnNode)node).getValueNode(); } + if ( node instanceof GlobalAsgnNode ) { return ((GlobalAsgnNode)node).getValueNode(); } + return null; + } + + private boolean isCallNode( Node node ) { + return ( node instanceof CallNode ) || ( node instanceof FCallNode ) || ( node instanceof VCallNode ); + } + + private List<ITypeGuess> getCallNodeTypes( Node node ) { + String methodName = helper.getCallNodeMethodName( node ); + + // Handle class instantiations separately + if ( methodName.equals("new") ) { + return getInstantiationCallNodeTypes( node ); + } + + List<ITypeGuess> possibleTypes = new LinkedList<ITypeGuess>(); + String receiverTypeName = null; + + if ( node instanceof CallNode ) { + List<ITypeGuess> receiverTypeInferences = inferNodeType( ((CallNode)node).getReceiverNode() ); + //TODO Handle all types instead of the first + if ( receiverTypeInferences.size() > 0 ) { + receiverTypeName = receiverTypeInferences.get(0).getType(); + } + + } + if ( node instanceof FCallNode ) { + receiverTypeName = helper.getTypeNodeName(findEnclosingTypeNode( node )); + } + if ( node instanceof VCallNode ) { + + //TODO WTF why doesn't VCallNode support getReceiverNode + receiverTypeName="Kernel"; + } + + //TODO: Find method defnnode, sum types of its retval-exprs + List<Node> defnNodes = findAllMethodDefinitions(receiverTypeName, methodName); + + sysout(" " + defnNodes.size() + " defnnodes found"); + // For each send-expr, collect all retval-exprs + List<Node> retvalExprs = new LinkedList<Node>(); + for ( Node defnNode : defnNodes ) { + retvalExprs.addAll( findRetvalExprs( defnNode ) ); + } + + // Sum possible types for all retval-exprs + for ( Node retvalExpr : retvalExprs ) { + possibleTypes.addAll( inferNodeType( retvalExpr ) ); + } + + return possibleTypes; + } + + private List<ITypeGuess> getInstantiationCallNodeTypes( Node node ) { + List<ITypeGuess> possibleTypes = new ArrayList<ITypeGuess>(1); + + if ( node instanceof CallNode ) { + Node receiverNode = ((CallNode)node).getReceiverNode(); + return inferNodeType( receiverNode ); + } + if ( node instanceof FCallNode ) { + Node enclosingTypeNode = findEnclosingTypeNode(node); + possibleTypes.add( getTypeDefinitionNodeType( enclosingTypeNode ) ); + } + if ( node instanceof VCallNode ) { + System.err.println("//TODO: Why doesn't VCallNode support getReceiverNode() ???"); + //TODO: Why doesn't VCallNode support getReceiverNode() ??? +// Node receiverNode = ((VCallNode)node).getReceiverNode(); +// return inferNodeType( receiverNode ); + } + + return possibleTypes; + } +} Added: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/TypeInferenceHelper.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/TypeInferenceHelper.java (rev 0) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/TypeInferenceHelper.java 2006-08-21 08:30:19 UTC (rev 1576) @@ -0,0 +1,120 @@ +package org.rubypeople.rdt.internal.ti; + +import java.util.Iterator; + +import org.jruby.ast.ArgsNode; +import org.jruby.ast.ArgumentNode; +import org.jruby.ast.ArrayNode; +import org.jruby.ast.CallNode; +import org.jruby.ast.ClassNode; +import org.jruby.ast.ClassVarNode; +import org.jruby.ast.Colon2Node; +import org.jruby.ast.DefnNode; +import org.jruby.ast.DefsNode; +import org.jruby.ast.FCallNode; +import org.jruby.ast.GlobalVarNode; +import org.jruby.ast.InstVarNode; +import org.jruby.ast.ListNode; +import org.jruby.ast.LocalVarNode; +import org.jruby.ast.ModuleNode; +import org.jruby.ast.Node; +import org.jruby.ast.VCallNode; +import org.jruby.lexer.yacc.ISourcePosition; +import org.rubypeople.rdt.internal.ti.util.ScopedNodeLocator; + +public class TypeInferenceHelper { + + //Singleton pattern + private TypeInferenceHelper() {} + private static TypeInferenceHelper staticInstance = new TypeInferenceHelper(); + public static TypeInferenceHelper Instance() { + return staticInstance; + } + + /** + * Extracts the name of a variable from a VarNode + * @param source Source that contains the node + * @param node LocalVarNode, InstVarNode, or GlobalVarNode referring to a variable. + * @return Name of the variable. + */ + public String getVarName(String source, Node node) + { + ISourcePosition pos = null; + if ( node instanceof InstVarNode ) pos = ((InstVarNode)node).getPosition(); + if ( node instanceof ClassVarNode ) pos = ((ClassVarNode)node).getPosition(); + if ( node instanceof LocalVarNode ) pos = ((LocalVarNode)node).getPosition(); + if ( node instanceof GlobalVarNode ) pos = ((GlobalVarNode)node).getPosition(); + if ( pos != null ) + { + return source.substring(pos.getStartOffset(), pos.getEndOffset()+1); + } + return null; + } + + + public int getArgIndex(ListNode listNode, String argName) + { + int argNumber = 0; + for ( Iterator iter = listNode.iterator(); iter.hasNext();) { + if (((ArgumentNode)iter.next()).getName().equals(argName)) { return argNumber; } + argNumber++; + } + return -1; + } + + public String getTypeNodeName( Node node ) { + if ( node instanceof ClassNode ) { return ((Colon2Node)((ClassNode)node).getCPath()).getName(); } + if ( node instanceof ModuleNode ) { return ((Colon2Node)((ModuleNode)node).getCPath()).getName(); } + return null; + } + + public String getMethodDefinitionNodeName(Node methodNode) { + if ( methodNode instanceof DefnNode ) return ((DefnNode)methodNode).getName(); + if ( methodNode instanceof DefsNode ) return ((DefsNode)methodNode).getName(); + return null; + } + + public boolean isArgumentInMethod( String varName, Node enclosingScopeNode ) { + ListNode listNode = getArgsListNode( enclosingScopeNode ); + + // If the args node cannot be located, varName is probably not an arg ;) + if ( listNode == null ) { + return false; + } + + // See if the method contains the variable by name + return ( getArgIndex( listNode, varName ) >= 0 ); + } + + public ListNode getArgsListNode( Node node ) { + if ( node instanceof DefnNode ) { return ((ArgsNode)( ((DefnNode)node).getArgsNode() )).getArgs(); } + if ( node instanceof DefsNode ) { return ((ArgsNode)( ((DefsNode)node).getArgsNode() )).getArgs(); } + if ( node instanceof CallNode ) { return ((ArgsNode)( ((CallNode)node).getArgsNode() )).getArgs(); } + + //TODO: Is ArrayNode the proper cast? + if ( node instanceof FCallNode ) { return (ArrayNode)( ((FCallNode)node).getArgsNode() ); } + // VCallNode is a node w/o args + + return null; + } + + + public String getCallNodeMethodName( Node node ) { + if ( node instanceof CallNode ) { return ((CallNode)node).getName(); } + if ( node instanceof FCallNode ) { return ((FCallNode)node).getName(); } + if ( node instanceof VCallNode ) { return ((VCallNode)node).getMethodName(); } + return null; + } + + public Node findNthArgExprInSendExpr( int n, Node sendExprNode ) { + ListNode listNode = getArgsListNode( sendExprNode ); + if ( listNode == null ) { + return null; + } + + + return listNode.get(n); + } + + +} Modified: 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 2006-08-20 22:06:09 UTC (rev 1575) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/ClosestSpanningNodeLocator.java 2006-08-21 08:30:19 UTC (rev 1576) @@ -4,7 +4,7 @@ import org.jruby.evaluator.Instruction; /** - * Visitor to find the first node that precedes a given offset that satisfies a given condition. + * Visitor to find the closest node that spans a given offset that satisfies a given condition. * @author Jason Morrison */ public class ClosestSpanningNodeLocator extends NodeLocator { @@ -17,13 +17,13 @@ return staticInstance; } - /** Offset to start searching backwards from. */ + /** Offset to span. */ private int offset; /** INodeAcceptor that defines the desired node. */ private INodeAcceptor acceptor; - /** Running best match for closest precursor */ + /** Running best match for closest spanner */ private Node locatedNode; /** Modified: 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 2006-08-20 22:06:09 UTC (rev 1575) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/MethodDefinitionLocator.java 2006-08-21 08:30:19 UTC (rev 1576) @@ -11,10 +11,17 @@ import org.jruby.ast.ArgsNode; import org.jruby.ast.ArgumentNode; import org.jruby.ast.ArrayNode; +import org.jruby.ast.CallNode; +import org.jruby.ast.ClassNode; import org.jruby.ast.DefnNode; import org.jruby.ast.DefsNode; +import org.jruby.ast.FCallNode; +import org.jruby.ast.ModuleNode; import org.jruby.ast.Node; import org.jruby.evaluator.Instruction; +import org.rubypeople.rdt.internal.ti.ITypeGuess; +import org.rubypeople.rdt.internal.ti.ITypeInferrer; +import org.rubypeople.rdt.internal.ti.TypeInferenceHelper; /** * Visitor to find all method definitions within a specific scope. @@ -30,38 +37,88 @@ return staticInstance; } - /** Running total of results; is a Set to ensure uniqueness */ - private Set<String> methods; + /** Inference helper */ + private TypeInferenceHelper helper = TypeInferenceHelper.Instance(); + /** Type of receiver to look for */ + private String typeName; + + /** Name of method to search for invocations of */ + private String methodName; + + /** Stack of names of types (Class/Module) enclosing the visitor cursor as we traverse */ + private List<String> typeNameStack; + + /** Running total of results */ + private List<Node> locatedNodes; + + /** Source to search within */ + private String source; + /** - * Finds all method definitions within a given node - * @param rootNode + * Finds all method definition node within rootNode whose enclosing type is of type typeName and method is named methodName + * @param rootNode Node to search within + * @param source Source to search within + * @param typeName Name of type of method-send-expr receiver + * @param methodName Name of method to find * @return */ - public List<String> findMethodDefinitionsInScope(Node rootNode) { - if ( rootNode == null ) { return new ArrayList<String>(); } + public List<Node> findMethodDefinitions( Node rootNode, String source, String typeName, String methodName ) { + if ( rootNode == null ) { return null; } - methods = new HashSet<String>(); + this.locatedNodes = new LinkedList<Node>(); + this.typeNameStack = new LinkedList<String>(); + this.typeName = typeName; + this.methodName = methodName; + typeNameStack.add("Kernel"); + // Traverse to find all matches rootNode.accept(this); // Return the matches - return new ArrayList<String>(methods); + return locatedNodes; } - /** - * Searches via InOrderVisitor for matches - */ - public Instruction handleNode(Node node ) { - if ( node instanceof DefnNode ) { - methods.add( ((DefnNode)node).getName() ); + + public Instruction handleNode(Node iVisited) { + if ( ( iVisited instanceof DefnNode ) || ( iVisited instanceof DefsNode ) ) { + if ( peekType().equals(typeName)) { + String methodName = helper.getMethodDefinitionNodeName( iVisited ); + if ( methodName.equals(methodName) ) { + locatedNodes.add(iVisited); + } + } } - if ( node instanceof DefsNode ) { - methods.add( ((DefsNode)node).getName() ); - } - - return super.handleNode(node); + return super.handleNode(iVisited); } + + public Instruction visitClassNode(ClassNode iVisited) { + pushType( helper.getTypeNodeName( iVisited ) ); + super.visitClassNode( iVisited ); + popType(); + + return null; + } + + public Instruction visitModuleNode(ModuleNode iVisited) { + pushType( helper.getTypeNodeName( iVisited ) ); + super.visitModuleNode( iVisited ); + popType(); + + return null; + } + + private void pushType( String typeName ) { + typeNameStack.add( 0, typeName ); + } + + private void popType() { + typeNameStack.remove(0); + } + + private String peekType() { + return typeNameStack.get(0); + } } Added: branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/MethodInvocationLocator.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/MethodInvocationLocator.java (rev 0) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/MethodInvocationLocator.java 2006-08-21 08:30:19 UTC (rev 1576) @@ -0,0 +1,152 @@ +package org.rubypeople.rdt.internal.ti.util; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import javax.xml.transform.Source; + +import org.jruby.ast.ArgsNode; +import org.jruby.ast.ArgumentNode; +import org.jruby.ast.CallNode; +import org.jruby.ast.ClassNode; +import org.jruby.ast.Colon2Node; +import org.jruby.ast.FCallNode; +import org.jruby.ast.ModuleNode; +import org.jruby.ast.Node; +import org.jruby.ast.VCallNode; +import org.jruby.evaluator.Instruction; +import org.rubypeople.rdt.internal.ti.ITypeGuess; +import org.rubypeople.rdt.internal.ti.ITypeInferrer; +import org.rubypeople.rdt.internal.ti.TypeInferenceHelper; + +/** + * Visitor to find all method invocations for the specified type and method names + * @author Jason Morrison + */ +public class MethodInvocationLocator extends NodeLocator { + + //Singleton pattern + private MethodInvocationLocator() {} + private static MethodInvocationLocator staticInstance = new MethodInvocationLocator(); + public static MethodInvocationLocator Instance() + { + return staticInstance; + } + + /** Inference helper */ + private TypeInferenceHelper helper = TypeInferenceHelper.Instance(); + + /** Type of receiver to look for */ + private String typeName; + + /** Name of method to search for invocations of */ + private String methodName; + + /** Stack of names of types (Class/Module) enclosing the visitor cursor as we traverse */ + private List<String> typeNameStack; + + /** Running total of results */ + private List<Node> locatedNodes; + + /** Type inferrer to use when resolving receiver-types */ + private ITypeInferrer inferrer; + + /** Source to search within */ + private String source; + + /** + * Finds all method invocation node within rootNode whose receiver is of type typeName and method is named methodName + * @param rootNode Node to search within + * @param source Source to search within + * @param typeName Name of type of method-send-expr receiver + * @param methodName Name of method to find + * @param inferrer Inferrer to use for resolving receiver-types + * @return + */ + public List<Node> findMethodInvocations( Node rootNode, String source, String typeName, String methodName, ITypeInferrer inferrer ) { + if ( rootNode == null ) { return null; } + + this.locatedNodes = new LinkedList<Node>(); + this.typeNameStack = new LinkedList<String>(); + this.typeName = typeName; + this.methodName = methodName; + this.inferrer = inferrer; + + typeNameStack.add("Kernel"); + + // Traverse to find all matches + rootNode.accept(this); + + // Return the matches + return locatedNodes; + } + + + public Instruction handleNode(Node iVisited) { + + // Check for invocations on self + if ( iVisited instanceof FCallNode ) { + if ( ((FCallNode)iVisited).getName().equals(methodName)) { + if ( peekType().equals(typeName)) { + locatedNodes.add(iVisited); + } + } + } + + // Look for CallNodes where receiver matches typeName and methodName matches method invoked + if ( iVisited instanceof CallNode ) { + if ( helper.getCallNodeMethodName(iVisited).equals(methodName)) { + // TI the receiver + Node receiverNode = ((CallNode)iVisited).getReceiverNode(); + List<ITypeGuess> receiverTypeInferences = inferrer.infer( source, receiverNode.getPosition().getStartOffset()); + + // If the receiver matches desired typeName, add a match! + for ( ITypeGuess inference : receiverTypeInferences ) { + if ( inference.getType().equals( typeName ) ) { + locatedNodes.add( iVisited ); + break; + } + } + } + } + +// if ( iVisited instanceof VCallNode ) { + //TODO: VCallNode does not have getReceiverNode(). + // We don't particularly care for the purpose of finding send-exprs that flow params into args of method-defns, since VCallNodes + // don't send w/ args. But, to make this visitor general-purpose, it would have to support VCallNodes. Consider just renaming the +// } + + return super.handleNode(iVisited); + } + + public Instruction visitClassNode(ClassNode iVisited) { + pushType( helper.getTypeNodeName( iVisited ) ); + super.visitClassNode( iVisited ); + popType(); + + return null; + } + + public Instruction visitModuleNode(ModuleNode iVisited) { + pushType( helper.getTypeNodeName( iVisited ) ); + super.visitModuleNode( iVisited ); + popType(); + + return null; + } + + private void pushType( String typeName ) { + typeNameStack.add( 0, typeName ); + } + + private void popType() { + typeNameStack.remove(0); + } + + private String peekType() { + return typeNameStack.get(0); + } + + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <mir...@us...> - 2006-08-20 22:06:34
|
Revision: 1575 Author: mirkostocker Date: 2006-08-20 15:06:09 -0700 (Sun, 20 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1575&view=rev Log Message: ----------- A small change to fix ticket #115 (cannot doubleclick-select if the word starts at the first character of the file). Modified Paths: -------------- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyWordFinder.java Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyWordFinder.java =================================================================== --- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyWordFinder.java 2006-08-20 04:05:53 UTC (rev 1574) +++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/RubyWordFinder.java 2006-08-20 22:06:09 UTC (rev 1575) @@ -50,9 +50,10 @@ end = pos; } catch (BadLocationException x) { + return null; } - if (start > -1 && end > -1) { + if (start >= -1 && end > -1) { if (start == offset && end == offset) return new Region(offset, 0); else if (start == offset) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <caw...@us...> - 2006-08-20 04:06:01
|
Revision: 1574 Author: cawilliams Date: 2006-08-19 21:05:53 -0700 (Sat, 19 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1574&view=rev Log Message: ----------- fix call to String.contains() (which is JDK 1.5) Modified Paths: -------------- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java 2006-08-19 23:56:24 UTC (rev 1573) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java 2006-08-20 04:05:53 UTC (rev 1574) @@ -55,7 +55,7 @@ } String source = NodeUtil.getSource(contents, iVisited); - if (iVisited.getThenBody() == null && !source.contains("unless")) { + if (iVisited.getThenBody() == null && source.indexOf("unless") == -1) { IProblem problem = createProblem( RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited.getPosition(), "Empty Conditional Body"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <caw...@us...> - 2006-08-19 23:56:30
|
Revision: 1573 Author: cawilliams Date: 2006-08-19 16:56:24 -0700 (Sat, 19 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1573&view=rev Log Message: ----------- Modified Paths: -------------- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/TC_RubyLintVisitor.java Modified: trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/TC_RubyLintVisitor.java =================================================================== --- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/TC_RubyLintVisitor.java 2006-08-19 23:56:16 UTC (rev 1572) +++ trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/TC_RubyLintVisitor.java 2006-08-19 23:56:24 UTC (rev 1573) @@ -37,14 +37,26 @@ } } - public void testBlah() throws Exception { - String contents = "@var = 3 unless @blah"; + private MockProblemRequestor problemRequestor; + + public void testUnlessModififerDoesntCreateEmptyConditionalWarning() throws Exception { + runLint("@var = 3 unless @blah"); + assertEquals(0, problemRequestor.problems.size()); + } + + + public void testUnlessConditionalDoesntCreateEmptyConditionalWarning() throws Exception { + runLint("unless @blah\n @var = 3\nend"); + System.out.println(problemRequestor.problems.get(0)); + assertEquals(0, problemRequestor.problems.size()); + } + + private void runLint(String contents) { RubyParser parser = new RubyParser(); Node rootNode = parser.parse(new ShamFile("fake/path.rb"), new StringReader(contents)); - MockProblemRequestor problemRequestor = new MockProblemRequestor(); + problemRequestor = new MockProblemRequestor(); RubyLintVisitor visitor = new RubyLintVisitor(contents, problemRequestor); rootNode.accept(visitor); - assertEquals(1, problemRequestor.problems.size()); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <caw...@us...> - 2006-08-19 23:56:23
|
Revision: 1572 Author: cawilliams Date: 2006-08-19 16:56:16 -0700 (Sat, 19 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1572&view=rev Log Message: ----------- Modified Paths: -------------- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyCodeAnalyzer.java trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/DefaultProblem.java trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyCodeAnalyzer.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyCodeAnalyzer.java 2006-08-19 23:28:28 UTC (rev 1571) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyCodeAnalyzer.java 2006-08-19 23:56:16 UTC (rev 1572) @@ -16,6 +16,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.io.StringReader; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; @@ -48,7 +49,7 @@ String contents = readContents(reader); markerManager.removeProblemsAndTasksFor(file); try { - Node rootNode = parser.parse(file, reader); + Node rootNode = parser.parse(file, new StringReader(contents)); RubyLintVisitor visitor = new RubyLintVisitor(contents, new ProblemRequestorMarkerManager(file, markerManager)); rootNode.accept(visitor); indexUpdater.update(file, rootNode, true); Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/DefaultProblem.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/DefaultProblem.java 2006-08-19 23:28:28 UTC (rev 1571) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/DefaultProblem.java 2006-08-19 23:56:16 UTC (rev 1572) @@ -45,4 +45,8 @@ public int getSourceStart() { return position.getStartOffset(); } + + public String toString() { + return position.toString() + " => " + message; + } } Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java 2006-08-19 23:28:28 UTC (rev 1571) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java 2006-08-19 23:56:16 UTC (rev 1572) @@ -1,77 +1,44 @@ package org.rubypeople.rdt.internal.core.parser; -import java.io.Reader; - import java.util.HashSet; - import java.util.Set; - import org.jruby.ast.BlockNode; - import org.jruby.ast.CallNode; - import org.jruby.ast.ConstDeclNode; - import org.jruby.ast.DefnNode; - import org.jruby.ast.DefsNode; - import org.jruby.ast.FCallNode; - import org.jruby.ast.FalseNode; - import org.jruby.ast.IfNode; - import org.jruby.ast.IterNode; - import org.jruby.ast.NilNode; - import org.jruby.ast.Node; - import org.jruby.ast.ScopeNode; - import org.jruby.ast.TrueNode; - import org.jruby.ast.WhenNode; - import org.jruby.evaluator.Instruction; - import org.jruby.lexer.yacc.ISourcePosition; - import org.rubypeople.rdt.core.IProblemRequestor; - import org.rubypeople.rdt.core.RubyCore; - import org.rubypeople.rdt.core.parser.IProblem; public class RubyLintVisitor extends InOrderVisitor { private IProblemRequestor problemRequestor; - private Set assignedConstants; - private Set methodsCalled; - private String contents; public RubyLintVisitor(String contents, IProblemRequestor problemRequestor) { - this.problemRequestor = problemRequestor; - assignedConstants = new HashSet(); - methodsCalled = new HashSet(); - this.contents = contents; - } public Instruction visitFCallNode(FCallNode iVisited) { - methodsCalled.add(iVisited.getName()); - return super.visitFCallNode(iVisited); - } public Instruction visitCallNode(CallNode iVisited) { @@ -99,143 +66,76 @@ } public Instruction visitWhenNode(WhenNode iVisited) { - if (iVisited.getBodyNode() == null) { - - IProblem problem = createProblem( - - RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited - - .getPosition(), "Empty When Body"); - + IProblem problem = createProblem(RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited.getPosition(), "Empty When Body"); if (problem != null) problemRequestor.acceptProblem(problem); - } - return super.visitWhenNode(iVisited); - } public Instruction visitBlockNode(BlockNode iVisited) { - return super.visitBlockNode(iVisited); - } public Instruction visitIterNode(IterNode iVisited) { - if (iVisited.getBodyNode() == null) { + IProblem problem = createProblem(RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited.getPosition(), "Empty Block"); - IProblem problem = createProblem( - - RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited - - .getPosition(), "Empty Block"); - if (problem != null) problemRequestor.acceptProblem(problem); - } - return super.visitIterNode(iVisited); - } public Instruction visitDefnNode(DefnNode iVisited) { - // TODO Analyze method visibility. Create warning for uncalled private - // methods - ScopeNode scope = iVisited.getBodyNode(); - if (scope.getBodyNode() == null) { - - IProblem problem = createProblem( - - RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited - - .getPosition(), "Empty Method Definition"); - + IProblem problem = createProblem(RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited.getPosition(), "Empty Method Definition"); if (problem != null) problemRequestor.acceptProblem(problem); - } - return super.visitDefnNode(iVisited); - } public Instruction visitDefsNode(DefsNode iVisited) { - ScopeNode scope = iVisited.getBodyNode(); - if (scope.getBodyNode() == null) { + IProblem problem = createProblem(RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited.getPosition(), "Empty Method Definition"); - IProblem problem = createProblem( - - RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited - - .getPosition(), "Empty Method Definition"); - if (problem != null) problemRequestor.acceptProblem(problem); - } - return super.visitDefsNode(iVisited); - } protected Instruction handleNode(Node visited) { - // System.out.println(visited.toString() + ", position -> " - // + visited.getPosition()); - return super.handleNode(visited); - } public Instruction visitConstDeclNode(ConstDeclNode iVisited) { - String name = iVisited.getName(); if (assignedConstants.contains(name)) { - - problemRequestor.acceptProblem(new Warning(iVisited.getPosition(), - - "Reassignment of a constant")); - + problemRequestor.acceptProblem(new Warning(iVisited.getPosition(), "Reassignment of a constant")); } else - assignedConstants.add(name); - return super.visitConstDeclNode(iVisited); - } - private IProblem createProblem(String compilerOption, - - ISourcePosition position, String message) { - + private IProblem createProblem(String compilerOption, ISourcePosition position, String message) { String value = RubyCore.getOption(compilerOption); - if (value == null) - return new Error(position, message); - if (value.equals(RubyCore.WARNING)) - return new Warning(position, message); - if (value.equals(RubyCore.ERROR)) - return new Error(position, message); - return null; - } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <caw...@us...> - 2006-08-19 23:28:37
|
Revision: 1571 Author: cawilliams Date: 2006-08-19 16:28:28 -0700 (Sat, 19 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1571&view=rev Log Message: ----------- Modified Paths: -------------- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/ShamMarkerManager.java Added Paths: ----------- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/TC_RubyLintVisitor.java Modified: trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/ShamMarkerManager.java =================================================================== --- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/ShamMarkerManager.java 2006-08-19 23:28:22 UTC (rev 1570) +++ trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/ShamMarkerManager.java 2006-08-19 23:28:28 UTC (rev 1571) @@ -11,8 +11,10 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; +import org.jruby.lexer.yacc.ISourcePosition; import org.jruby.lexer.yacc.SyntaxException; import org.rubypeople.eclipse.shams.resources.ShamFile; +import org.rubypeople.rdt.internal.core.parser.RdtPosition; import org.rubypeople.rdt.internal.core.util.ListUtil; public class ShamMarkerManager implements IMarkerManager { @@ -85,5 +87,12 @@ endOffsetArg = endOffset; } + public void createError(IFile file, String message, int startLine, int startOffset, int endOffset) { + fileArg = file; + ISourcePosition position = new RdtPosition(startLine, startOffset, endOffset); + SyntaxException e = new SyntaxException(position, message); + syntaxExceptionArg = e; + } + } \ No newline at end of file Added: trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/TC_RubyLintVisitor.java =================================================================== --- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/TC_RubyLintVisitor.java (rev 0) +++ trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/core/builder/TC_RubyLintVisitor.java 2006-08-19 23:28:28 UTC (rev 1571) @@ -0,0 +1,50 @@ +package org.rubypeople.rdt.internal.core.builder; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.jruby.ast.Node; +import org.rubypeople.eclipse.shams.resources.ShamFile; +import org.rubypeople.rdt.core.IProblemRequestor; +import org.rubypeople.rdt.core.parser.IProblem; +import org.rubypeople.rdt.internal.core.parser.RubyLintVisitor; +import org.rubypeople.rdt.internal.core.parser.RubyParser; + +public class TC_RubyLintVisitor extends TestCase { + + class MockProblemRequestor implements IProblemRequestor { + List problems; + + public MockProblemRequestor() { + problems = new ArrayList(); + } + + public void acceptProblem(IProblem problem) { + problems.add(problem); + } + + public void beginReporting() { + } + + public void endReporting() { + } + + public boolean isActive() { + return false; + } + } + + public void testBlah() throws Exception { + String contents = "@var = 3 unless @blah"; + RubyParser parser = new RubyParser(); + Node rootNode = parser.parse(new ShamFile("fake/path.rb"), new StringReader(contents)); + MockProblemRequestor problemRequestor = new MockProblemRequestor(); + RubyLintVisitor visitor = new RubyLintVisitor(contents, + problemRequestor); + rootNode.accept(visitor); + assertEquals(1, problemRequestor.problems.size()); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <caw...@us...> - 2006-08-19 23:28:28
|
Revision: 1570 Author: cawilliams Date: 2006-08-19 16:28:22 -0700 (Sat, 19 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1570&view=rev Log Message: ----------- Modified Paths: -------------- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java 2006-08-15 11:40:54 UTC (rev 1569) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java 2006-08-19 23:28:22 UTC (rev 1570) @@ -1,15 +1,11 @@ package org.rubypeople.rdt.internal.core.parser; - - import java.io.Reader; import java.util.HashSet; import java.util.Set; - - import org.jruby.ast.BlockNode; import org.jruby.ast.CallNode; @@ -48,12 +44,8 @@ import org.rubypeople.rdt.core.parser.IProblem; - - public class RubyLintVisitor extends InOrderVisitor { - - private IProblemRequestor problemRequestor; private Set assignedConstants; @@ -62,8 +54,6 @@ private String contents; - - public RubyLintVisitor(String contents, IProblemRequestor problemRequestor) { this.problemRequestor = problemRequestor; @@ -76,8 +66,6 @@ } - - public Instruction visitFCallNode(FCallNode iVisited) { methodsCalled.add(iVisited.getName()); @@ -86,69 +74,42 @@ } - - public Instruction visitCallNode(CallNode iVisited) { - methodsCalled.add(iVisited.getName()); - return super.visitCallNode(iVisited); - } - - public Instruction visitIfNode(IfNode iVisited) { - Node condition = iVisited.getCondition(); - if (condition instanceof TrueNode) { - - problemRequestor.acceptProblem(new Warning(iVisited.getPosition(), - - "Condition is always true")); - - } else if ((condition instanceof FalseNode) - - || (condition instanceof NilNode)) { - - problemRequestor.acceptProblem(new Warning(iVisited.getPosition(), - - "Condition is always false")); - + problemRequestor.acceptProblem(new Warning(iVisited.getPosition(), "Condition is always true")); + } else if ((condition instanceof FalseNode) || (condition instanceof NilNode)) { + problemRequestor.acceptProblem(new Warning(iVisited.getPosition(), "Condition is always false")); } String source = NodeUtil.getSource(contents, iVisited); - if (iVisited.getThenBody() == null && !source.contains("unless")) { - IProblem problem = createProblem( + RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited.getPosition(), "Empty Conditional Body"); - RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited - - .getPosition(), "Empty Conditional Body"); - - if (problem != null) problemRequestor.acceptProblem(problem); - + if (problem != null) + problemRequestor.acceptProblem(problem); } - return super.visitIfNode(iVisited); - } - - public Instruction visitWhenNode(WhenNode iVisited) { if (iVisited.getBodyNode() == null) { IProblem problem = createProblem( - RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited + RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited - .getPosition(), "Empty When Body"); + .getPosition(), "Empty When Body"); - if (problem != null) problemRequestor.acceptProblem(problem); + if (problem != null) + problemRequestor.acceptProblem(problem); } @@ -156,27 +117,24 @@ } - - public Instruction visitBlockNode(BlockNode iVisited) { return super.visitBlockNode(iVisited); } - - public Instruction visitIterNode(IterNode iVisited) { if (iVisited.getBodyNode() == null) { IProblem problem = createProblem( - RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited + RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited - .getPosition(), "Empty Block"); + .getPosition(), "Empty Block"); - if (problem != null) problemRequestor.acceptProblem(problem); + if (problem != null) + problemRequestor.acceptProblem(problem); } @@ -184,8 +142,6 @@ } - - public Instruction visitDefnNode(DefnNode iVisited) { // TODO Analyze method visibility. Create warning for uncalled private @@ -198,11 +154,12 @@ IProblem problem = createProblem( - RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited + RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited - .getPosition(), "Empty Method Definition"); + .getPosition(), "Empty Method Definition"); - if (problem != null) problemRequestor.acceptProblem(problem); + if (problem != null) + problemRequestor.acceptProblem(problem); } @@ -210,8 +167,6 @@ } - - public Instruction visitDefsNode(DefsNode iVisited) { ScopeNode scope = iVisited.getBodyNode(); @@ -220,11 +175,12 @@ IProblem problem = createProblem( - RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited + RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited - .getPosition(), "Empty Method Definition"); + .getPosition(), "Empty Method Definition"); - if (problem != null) problemRequestor.acceptProblem(problem); + if (problem != null) + problemRequestor.acceptProblem(problem); } @@ -232,20 +188,16 @@ } - - protected Instruction handleNode(Node visited) { -// System.out.println(visited.toString() + ", position -> " + // System.out.println(visited.toString() + ", position -> " -// + visited.getPosition()); + // + visited.getPosition()); return super.handleNode(visited); } - - public Instruction visitConstDeclNode(ConstDeclNode iVisited) { String name = iVisited.getName(); @@ -254,7 +206,7 @@ problemRequestor.acceptProblem(new Warning(iVisited.getPosition(), - "Reassignment of a constant")); + "Reassignment of a constant")); } else @@ -264,11 +216,9 @@ } - - private IProblem createProblem(String compilerOption, - ISourcePosition position, String message) { + ISourcePosition position, String message) { String value = RubyCore.getOption(compilerOption); @@ -288,7 +238,4 @@ } - - } - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <caw...@us...> - 2006-08-15 11:41:02
|
Revision: 1569 Author: cawilliams Date: 2006-08-15 04:40:54 -0700 (Tue, 15 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1569&view=rev Log Message: ----------- Fix problems which were only getting marked as "Syntax Error" Made task for handling duplicate markers or lint visitor (builder creates a marker and so does reconciler) Added way to grab source code for a node Modified LintVistor to check source before marking some of the warnings Modified Paths: -------------- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptProblemFinder.java trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/IMarkerManager.java trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MarkerManager.java trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyCodeAnalyzer.java trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java Added Paths: ----------- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/NodeUtil.java Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptProblemFinder.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptProblemFinder.java 2006-08-15 04:21:04 UTC (rev 1568) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/RubyScriptProblemFinder.java 2006-08-15 11:40:54 UTC (rev 1569) @@ -3,6 +3,7 @@ */ package org.rubypeople.rdt.internal.core; +import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.Iterator; @@ -34,7 +35,8 @@ String contents = new String(charContents); try { Node node = parser.parse((IFile) script.getUnderlyingResource(), new StringReader(contents)); - RubyLintVisitor visitor = new RubyLintVisitor(problemRequestor); + // FIXME We're double marking problems here. We create markers for them when we build, and then create temporary annotations when we reconcile. We need to "toss" out any duplicates generated here. + RubyLintVisitor visitor = new RubyLintVisitor(contents, problemRequestor); node.accept(visitor); } catch (SyntaxException e) { problemRequestor.acceptProblem(new Error(e.getPosition(), "Syntax Error")); Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/IMarkerManager.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/IMarkerManager.java 2006-08-15 04:21:04 UTC (rev 1568) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/IMarkerManager.java 2006-08-15 11:40:54 UTC (rev 1569) @@ -21,6 +21,7 @@ public interface IMarkerManager { public void removeProblemsAndTasksFor(IResource resource); public void createSyntaxError(IFile file, SyntaxException e); + public void createError(IFile file, String message, int startLine, int startOffset, int endOffset); public void createTasks(IFile file, List tasks) throws CoreException; public void addWarning(IFile file, String message); public void addWarning(IFile file, String message, int startLine, int startOffset, int endOffset); Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MarkerManager.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MarkerManager.java 2006-08-15 04:21:04 UTC (rev 1568) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/MarkerManager.java 2006-08-15 11:40:54 UTC (rev 1569) @@ -21,6 +21,7 @@ import org.rubypeople.rdt.internal.core.parser.MarkerUtility; import org.rubypeople.rdt.internal.core.parser.RdtPosition; import org.rubypeople.rdt.internal.core.parser.Warning; +import org.rubypeople.rdt.internal.core.parser.Error; class MarkerManager implements IMarkerManager { @@ -51,4 +52,9 @@ MarkerUtility.createProblemMarker(file, new Warning(new RdtPosition(startLine, startOffset, endOffset), message)); } + public void createError(IFile file, String message, int startLine, int startOffset, int endOffset) { + MarkerUtility.createProblemMarker(file, new Error(new RdtPosition(startLine, startOffset, endOffset), message)); + + } + } Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyCodeAnalyzer.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyCodeAnalyzer.java 2006-08-15 04:21:04 UTC (rev 1568) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/builder/RubyCodeAnalyzer.java 2006-08-15 11:40:54 UTC (rev 1569) @@ -12,6 +12,8 @@ package org.rubypeople.rdt.internal.core.builder; +import java.io.BufferedReader; +import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; @@ -41,10 +43,13 @@ public void compileFile(IFile file) throws CoreException { Reader reader = new InputStreamReader(file.getContents()); + // XXX Make sure readContents isn't dropping end of line characters + // XXX Use a StringReader for the parser since we've already read it all in once before? + String contents = readContents(reader); markerManager.removeProblemsAndTasksFor(file); try { Node rootNode = parser.parse(file, reader); - RubyLintVisitor visitor = new RubyLintVisitor(new ProblemRequestorMarkerManager(file, markerManager)); + RubyLintVisitor visitor = new RubyLintVisitor(contents, new ProblemRequestorMarkerManager(file, markerManager)); rootNode.accept(visitor); indexUpdater.update(file, rootNode, true); } catch (SyntaxException e) { @@ -54,4 +59,21 @@ } } + private String readContents(Reader reader) { + try { + BufferedReader buff = new BufferedReader(reader); + StringBuffer str = new StringBuffer(); + String line; + while((line = buff.readLine()) != null) { + str.append(line); + str.append("\n"); + } + return str.toString(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return ""; + } + } + } \ No newline at end of file Added: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/NodeUtil.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/NodeUtil.java (rev 0) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/NodeUtil.java 2006-08-15 11:40:54 UTC (rev 1569) @@ -0,0 +1,14 @@ +package org.rubypeople.rdt.internal.core.parser; + +import org.jruby.ast.Node; +import org.jruby.lexer.yacc.ISourcePosition; + +public class NodeUtil { + + private NodeUtil() {} + + public static String getSource(String contents, Node node) { + ISourcePosition pos = node.getPosition(); + return contents.substring(pos.getStartOffset(), pos.getEndOffset()); + } +} Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java =================================================================== --- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java 2006-08-15 04:21:04 UTC (rev 1568) +++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/core/parser/RubyLintVisitor.java 2006-08-15 11:40:54 UTC (rev 1569) @@ -1,143 +1,294 @@ package org.rubypeople.rdt.internal.core.parser; + + +import java.io.Reader; + import java.util.HashSet; + import java.util.Set; + + import org.jruby.ast.BlockNode; + import org.jruby.ast.CallNode; + import org.jruby.ast.ConstDeclNode; + import org.jruby.ast.DefnNode; + import org.jruby.ast.DefsNode; + import org.jruby.ast.FCallNode; + import org.jruby.ast.FalseNode; + import org.jruby.ast.IfNode; + import org.jruby.ast.IterNode; + import org.jruby.ast.NilNode; + import org.jruby.ast.Node; + import org.jruby.ast.ScopeNode; + import org.jruby.ast.TrueNode; + import org.jruby.ast.WhenNode; + import org.jruby.evaluator.Instruction; + import org.jruby.lexer.yacc.ISourcePosition; + import org.rubypeople.rdt.core.IProblemRequestor; + import org.rubypeople.rdt.core.RubyCore; + import org.rubypeople.rdt.core.parser.IProblem; + + public class RubyLintVisitor extends InOrderVisitor { + + private IProblemRequestor problemRequestor; + private Set assignedConstants; + private Set methodsCalled; - public RubyLintVisitor(IProblemRequestor problemRequestor) { + private String contents; + + + + public RubyLintVisitor(String contents, IProblemRequestor problemRequestor) { + this.problemRequestor = problemRequestor; + assignedConstants = new HashSet(); + methodsCalled = new HashSet(); + + this.contents = contents; + } + + public Instruction visitFCallNode(FCallNode iVisited) { + methodsCalled.add(iVisited.getName()); + return super.visitFCallNode(iVisited); + } + + public Instruction visitCallNode(CallNode iVisited) { + methodsCalled.add(iVisited.getName()); + return super.visitCallNode(iVisited); + } + + public Instruction visitIfNode(IfNode iVisited) { + Node condition = iVisited.getCondition(); + if (condition instanceof TrueNode) { + problemRequestor.acceptProblem(new Warning(iVisited.getPosition(), + "Condition is always true")); + } else if ((condition instanceof FalseNode) + || (condition instanceof NilNode)) { + problemRequestor.acceptProblem(new Warning(iVisited.getPosition(), + "Condition is always false")); + } - if (iVisited.getThenBody() == null) { + String source = NodeUtil.getSource(contents, iVisited); + + if (iVisited.getThenBody() == null && !source.contains("unless")) { + IProblem problem = createProblem( + RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited + .getPosition(), "Empty Conditional Body"); + if (problem != null) problemRequestor.acceptProblem(problem); + } + return super.visitIfNode(iVisited); + } + + public Instruction visitWhenNode(WhenNode iVisited) { + if (iVisited.getBodyNode() == null) { + IProblem problem = createProblem( + RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited + .getPosition(), "Empty When Body"); + if (problem != null) problemRequestor.acceptProblem(problem); + } + return super.visitWhenNode(iVisited); + } + + public Instruction visitBlockNode(BlockNode iVisited) { return super.visitBlockNode(iVisited); + } + + public Instruction visitIterNode(IterNode iVisited) { + if (iVisited.getBodyNode() == null) { + IProblem problem = createProblem( + RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited + .getPosition(), "Empty Block"); + if (problem != null) problemRequestor.acceptProblem(problem); + } + return super.visitIterNode(iVisited); + } + + public Instruction visitDefnNode(DefnNode iVisited) { + // TODO Analyze method visibility. Create warning for uncalled private + // methods + ScopeNode scope = iVisited.getBodyNode(); + if (scope.getBodyNode() == null) { + IProblem problem = createProblem( + RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited + .getPosition(), "Empty Method Definition"); + if (problem != null) problemRequestor.acceptProblem(problem); + } + return super.visitDefnNode(iVisited); + } + + public Instruction visitDefsNode(DefsNode iVisited) { + ScopeNode scope = iVisited.getBodyNode(); + if (scope.getBodyNode() == null) { + IProblem problem = createProblem( + RubyCore.COMPILER_PB_EMPTY_STATEMENT, iVisited + .getPosition(), "Empty Method Definition"); + if (problem != null) problemRequestor.acceptProblem(problem); + } + return super.visitDefsNode(iVisited); + } + + protected Instruction handleNode(Node visited) { + // System.out.println(visited.toString() + ", position -> " + // + visited.getPosition()); + return super.handleNode(visited); + } + + public Instruction visitConstDeclNode(ConstDeclNode iVisited) { + String name = iVisited.getName(); + if (assignedConstants.contains(name)) { + problemRequestor.acceptProblem(new Warning(iVisited.getPosition(), + "Reassignment of a constant")); + } else + assignedConstants.add(name); + return super.visitConstDeclNode(iVisited); + } + + private IProblem createProblem(String compilerOption, + ISourcePosition position, String message) { + String value = RubyCore.getOption(compilerOption); - if ((value == null) || value.equals(RubyCore.WARNING)) + + if (value == null) + + return new Error(position, message); + + if (value.equals(RubyCore.WARNING)) + return new Warning(position, message); + if (value.equals(RubyCore.ERROR)) + return new Error(position, message); + return null; + } + + } + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
Revision: 1568 Author: jasonpmorrison Date: 2006-08-14 21:21:04 -0700 (Mon, 14 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1568&view=rev Log Message: ----------- * Updated RubyCompletionProcessor to add element completion for method locals/args, instance variables, class variables, globals, method definitions, class and module definitions available to the current scope and those included through mixins and inheritance. Items not covered include "class << self" insertions and modules included inside method calls (such as acts_as_*) Modified Paths: -------------- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java 2006-08-15 04:18:13 UTC (rev 1567) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java 2006-08-15 04:21:04 UTC (rev 1568) @@ -28,34 +28,39 @@ import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IEditorPart; -import org.jruby.ast.ArgsNode; -import org.jruby.ast.ArgumentNode; -import org.jruby.ast.CallNode; import org.jruby.ast.ClassNode; import org.jruby.ast.ClassVarAsgnNode; import org.jruby.ast.ClassVarDeclNode; import org.jruby.ast.ClassVarNode; +import org.jruby.ast.Colon2Node; +import org.jruby.ast.ConstNode; import org.jruby.ast.DefnNode; import org.jruby.ast.DefsNode; -import org.jruby.ast.FCallNode; import org.jruby.ast.InstAsgnNode; import org.jruby.ast.InstVarNode; import org.jruby.ast.ModuleNode; import org.jruby.ast.Node; import org.jruby.ast.ScopeNode; -import org.jruby.ast.VCallNode; import org.jruby.lexer.yacc.SyntaxException; -import org.rubypeople.rdt.core.CompletionRequestor; +import org.jruby.parser.RubyParserPool; import org.rubypeople.rdt.core.IParent; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IRubyScript; +import org.rubypeople.rdt.core.ISourceReference; +import org.rubypeople.rdt.core.IType; import org.rubypeople.rdt.core.RubyModelException; +import org.rubypeople.rdt.internal.codeassist.RubyElementRequestor; +import org.rubypeople.rdt.internal.core.RubyElement; +import org.rubypeople.rdt.internal.core.RubyScript; +import org.rubypeople.rdt.internal.core.RubyScriptStructureBuilder; +import org.rubypeople.rdt.internal.core.RubyType; import org.rubypeople.rdt.internal.core.parser.RubyParser; import org.rubypeople.rdt.internal.corext.template.ruby.RubyContextType; import org.rubypeople.rdt.internal.ti.util.AttributeLocator; -import org.rubypeople.rdt.internal.ti.util.FirstPrecursorNodeLocator; +import org.rubypeople.rdt.internal.ti.util.ClosestSpanningNodeLocator; import org.rubypeople.rdt.internal.ti.util.INodeAcceptor; +import org.rubypeople.rdt.internal.ti.util.MethodDefinitionLocator; import org.rubypeople.rdt.internal.ti.util.ScopedNodeLocator; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.RubyPluginImages; @@ -380,45 +385,91 @@ /** * Gets all the distinct elements in the current RubyScript - * @param documentOffset + * @param offset * * @return a List of the names of all the elements in the current RubyScript */ - private Collection getDocumentsRubyElementsInScope(int documentOffset) { + private Collection getDocumentsRubyElementsInScope(int offset) { IRubyScript script = fManager.getWorkingCopy(fEditor.getEditorInput()); - // FIXME Get only the elements in the current scope! + - Collection elements = getElementsInScope(script, documentOffset); +// Collection elements = getElementsInScope(script, offset); -// Collection elements = getElements(script); -// System.out.println(" :: " + elements.size() ); - - IRubyProject project = script.getRubyProject(); - // Add all the classes and modules in the project - elements.addAll(addClassesAndModulesInProject(project)); -// System.out.println(" :: " + elements.size() ); - - - // Add all the classes and modules in referenced projects - for (Iterator iter = project.getReferencedProjects().iterator(); iter - .hasNext();) { - elements.addAll(addClassesAndModulesInProject(((IRubyProject) iter - .next()))); + String source = ""; + Collection elements = new ArrayList(); + try { + // Get the script's source. If possible, get the most recent contents. + if ( script instanceof RubyScript ) { + source = new String(((RubyScript)script).getContents()); + } else { + source = script.getSource(); + } + + // Get all references projects + List<IRubyProject> projects = new ArrayList<IRubyProject>(); + projects.add(script.getRubyProject()); + projects.addAll(script.getRubyProject().getReferencedProjects()); + + // Parse + Node rootNode = (new RubyParser()).parse(source); + if ( rootNode == null ) { return elements; } + + // Find the enclosing method to get locals and args + Node enclosingMethodNode = ClosestSpanningNodeLocator.Instance().findClosestSpanner(rootNode, offset, new INodeAcceptor() { + public boolean doesAccept(Node node) { + return ( node instanceof DefnNode || node instanceof DefsNode ); + } + }); + + // Add local vars and arguments + if ( enclosingMethodNode != null ) { + ScopeNode scopeNode = null; + if ( enclosingMethodNode instanceof DefnNode ) { scopeNode = (ScopeNode)((DefnNode)enclosingMethodNode).getBodyNode(); } + if ( enclosingMethodNode instanceof DefsNode ) { scopeNode = (ScopeNode)((DefsNode)enclosingMethodNode).getBodyNode(); } + if ( scopeNode != null && scopeNode.getLocalNames().length > 0 ) { + elements.addAll( Arrays.asList (scopeNode.getLocalNames()) ); + } + } + + // Find the enclosing type (class or module) to get instance and classvars from + Node enclosingTypeNode = ClosestSpanningNodeLocator.Instance().findClosestSpanner(rootNode, offset, new INodeAcceptor() { + public boolean doesAccept(Node node) { + return ( node instanceof ClassNode || node instanceof ModuleNode ); + } + }); + + // Add members from enclosing type + if ( enclosingTypeNode != null ) { + elements.addAll( getMembersAvailableInsideType( enclosingTypeNode, script ) ); + } + + // Add all globals, classes, and modules + for (Iterator iter = projects.iterator(); iter.hasNext();) { + IRubyProject nextProject = (IRubyProject)(iter.next()); + + System.out.println("*** Adding globals/classes/modules available in project: " + nextProject.getElementName() ); + + elements.addAll(getElementsOfType( nextProject, new int[] { IRubyElement.GLOBAL })); + elements.addAll(addClassesAndModulesInProject( nextProject )); + } + + + // always add Kernel methods + elements.addAll(addKernelMethods()); + + + } catch ( RubyModelException rme ) { + System.out.println("RubyModelException in RubyCompletionProcessor::getElementsInScope()"); + rme.printStackTrace(); + // Return empty 'elements' + } catch ( SyntaxException se ) { + System.out.println("SyntaxError in RubyCompletionProcessor::getElementsInScope()"); + se.printStackTrace(); + // Return empty 'elements' } - System.out.println(" :: " + elements.size() ); + - - // TODO Add all the methods defined in included modules for the class - // TODO Add all the methods defined in superclasses for the class/module - // always add Kernel methods - elements.addAll(addKernelMethods()); - System.out.println(" :: " + elements.size() ); - - for ( Object element : elements ) - { -// System.out.println(" -- Element: " + (String)element); - } return elements; } @@ -461,100 +512,190 @@ IRubyElement.INSTANCE_VAR }); } + /** - * Gets the names of elements available in the specified scope. This includes: - * - Method arguments - * - Method locals - * - Enclosing class/module instance variables - * - Enclosing class/module class variables - * - Globals - * - * @param script Script to collect available elements from - * @param offset Offset in script to determine the access scope (for args/locals/instvars/classvars) + * Gets the memebrs available inside a type node (ModuleNode, ClassNode): + * - Instance variables + * - Class variables + * - Methods + * + * @param typeNode * @return */ - public Collection getElementsInScope(IRubyScript script, int offset) { - String source = ""; - Collection elements = new ArrayList(); - try { - // Get the script's source, and parse it. - source = script.getSource(); - Node rootNode = (new RubyParser()).parse(source); - if ( rootNode == null ) { return elements; } + private List<String> getMembersAvailableInsideType(Node typeNode, IRubyScript script) throws RubyModelException { + List<String> elements = new LinkedList<String>(); + if ( typeNode == null ) { return elements; } + + // Get type name + String typeName = null; + if ( typeNode instanceof ClassNode ) { typeName = ((Colon2Node)((ClassNode)typeNode).getCPath()).getName(); } + if ( typeNode instanceof ModuleNode ) { typeName = ((Colon2Node)((ModuleNode)typeNode).getCPath()).getName(); } + if ( typeName == null ) { return elements; } + + // XXX rubyType may not be in script, but rather be defined in another script +// IType rubyType = new RubyType( (RubyElement)script, typeName ); + //Better method: + // Find the named type +// IType rubyType = findTypeFromAllProjects(typeName, script); - // Find the enclosing method to get locals and args - Node enclosingMethodNode = FirstPrecursorNodeLocator.Instance().findFirstPrecursor(rootNode, offset, new INodeAcceptor() { - public boolean doesAccept(Node node) { - return ( node instanceof DefnNode || node instanceof DefsNode ); - }}); - - // Add locally available arguments -// ArgsNode argsNode = null; -// if ( enclosingMethodNode instanceof DefnNode ) { argsNode = (ArgsNode)((DefnNode)enclosingMethodNode).getArgsNode(); } -// if ( enclosingMethodNode instanceof DefsNode ) { argsNode = (ArgsNode)((DefsNode)enclosingMethodNode).getArgsNode(); } -// if ( argsNode != null ) { -// for (Iterator iter = argsNode.getArgs().iterator(); iter.hasNext();) { -// elements.add( ((ArgumentNode)iter.next()).getName() ); +// System.out.println(" -- Located RubyType info."); +// System.out.println(" -- Superclass: " + rubyType.getSuperclassName() ); + +// if ( rubyType != null ) { +// String[] includedModuleNames = rubyType.getIncludedModuleNames(); +// if ( includedModuleNames != null ) { +// for ( String moduleName : rubyType.getIncludedModuleNames() ) { +// System.out.println(" -- Includes module: " + moduleName); // } // } - +// } + + + + // Get superclass and add its public members + List<Node> superclassNodes = getSuperclassNodes( typeNode, script ); + + for ( Node superclassNode : superclassNodes ) { + elements.addAll( getMembersAvailableInsideType( superclassNode, script ) ); + } + + // Get public members of mixins + List<String> mixinNames = getIncludedMixinNames( typeName, script ); + for ( String mixinName : mixinNames ) { + List<Node> mixinDeclarations = getTypeDeclarationNodes( mixinName, script ); + for ( Node mixinDeclaration : mixinDeclarations ) { + elements.addAll( getMembersAvailableInsideType( mixinDeclaration, script ) ); + } + } + + // Get instance and class variables available in the enclosing type + List<Node> instanceAndClassVars = ScopedNodeLocator.Instance().findNodesInScope(typeNode, new INodeAcceptor() { + public boolean doesAccept(Node node) { + return ( node instanceof InstVarNode || + node instanceof InstAsgnNode || + node instanceof ClassVarNode || + node instanceof ClassVarDeclNode || + node instanceof ClassVarAsgnNode ); + } + }); + + if ( instanceAndClassVars != null ) { + // Get the unique names of instance and class variables + Set instanceAndClassVarNames = new HashSet(instanceAndClassVars.size()); + for ( Node varNode : instanceAndClassVars ) { + String name = getNameReflectively(varNode); + if ( name != null ) { + instanceAndClassVarNames.add(name); + } + } + + // Add instance and class variables to matched elements + elements.addAll( instanceAndClassVarNames ); + } + + // Get method names defined by DefnNodes and DefsNodes + elements.addAll( MethodDefinitionLocator.Instance().findMethodDefinitionsInScope(typeNode) ); + + // Get instance and class vars defined by [c]attr_* calls + elements.addAll( AttributeLocator.Instance().findInstanceAttributesInScope(typeNode) ); + + return elements; + } - // Add local vars - arguments are included - ScopeNode scopeNode = null; - if ( enclosingMethodNode instanceof DefnNode ) { scopeNode = (ScopeNode)((DefnNode)enclosingMethodNode).getBodyNode(); } - if ( enclosingMethodNode instanceof DefsNode ) { scopeNode = (ScopeNode)((DefsNode)enclosingMethodNode).getBodyNode(); } - if ( scopeNode != null && scopeNode.getLocalNames().length > 0 ) { - elements.addAll( Arrays.asList (scopeNode.getLocalNames()) ); + /** + * Finds all nodes that declare a type that is a superclass of the specified node. Example: + * + * """ + * class Klass;def meth_1;1;end;end + * class Klass;def meth_2;2;end;end + * + * class SubKlass < Klass;end + * """ + * + * Issuing getSuperClassNodes() on the ClassNode declaring SubKlass would return two ClassNodes; + * one for each definition of Klass. + * + * @param typeNode Node to find superclass nodes of + * @return List of ClassNode or ModuleNode + */ + private List<Node> getSuperclassNodes( Node typeNode, IRubyScript script ) { + if ( typeNode instanceof ClassNode ) { + Node superNode = ((ClassNode)typeNode).getSuperNode(); + if ( superNode instanceof ConstNode ) { + String superclassName = ((ConstNode)superNode).getName(); + return getTypeDeclarationNodes( superclassName, script ); } + } + + return new ArrayList<Node>(); + } + + private IType findTypeFromAllProjects(String typeName, IRubyScript rootScript) { + // Grab the project and all referred projects + List<IRubyProject> projects = new LinkedList<IRubyProject>(); + projects.add(rootScript.getRubyProject()); + projects.addAll(rootScript.getRubyProject().getReferencedProjects()); + List<IRubyProject> refProjects = rootScript.getRubyProject().getReferencedProjects(); - // Find the enclosing type (class or module) to get instance and classvars from - Node enclosingTypeNode = FirstPrecursorNodeLocator.Instance().findFirstPrecursor(rootNode, offset, new INodeAcceptor() { - public boolean doesAccept(Node node) { - return ( node instanceof ClassNode || node instanceof ModuleNode ); - }}); + // Find the named type + RubyElementRequestor completer = new RubyElementRequestor(projects.toArray(new IRubyProject[]{})); + return completer.findType(typeName); + } + + /** Lookup type declaration nodes */ + private List<Node> getTypeDeclarationNodes( String typeName, IRubyScript script ) { + System.out.println("Being asked for the type decl node for " + typeName ); + + // Find the named type + IType type = findTypeFromAllProjects(typeName, script); + + try { + if ( type instanceof RubyType ) { - // Get instance and class variables available in the enclosing type - List<Node> instanceAndClassVars = ScopedNodeLocator.Instance().findNodesInScope(enclosingTypeNode, new INodeAcceptor() { - public boolean doesAccept(Node node) { - return ( node instanceof InstVarNode || - node instanceof InstAsgnNode || - node instanceof ClassVarNode || - node instanceof ClassVarDeclNode || - node instanceof ClassVarAsgnNode ); - }}); - - if ( instanceAndClassVars != null ) { - // Get the unique names of instance and class variables - Set instanceAndClassVarNames = new HashSet(instanceAndClassVars.size()); - for ( Node varNode : instanceAndClassVars ) { - String name = getNameReflectively(varNode); - if ( name != null ) { - instanceAndClassVarNames.add(name); + // FIXME This feels a little hacky and backwards - RubyType.getSource() and then parse... consider reworking the clients to this method to accept RubyTypes or something similar? + // Find source and parse + RubyType rubyType = (RubyType)type; + String source = rubyType.getSource(); + + // FIXME Why does the parser balk on \r chars? + source = source.replace('\r', ' '); + Node rootNode = (new RubyParser()).parse( source ); + + // Bail if the parse fails + if ( rootNode == null ) { return new ArrayList(); } + + // Return any type declaration nodes in included source + return ScopedNodeLocator.Instance().findNodesInScope(rootNode, new INodeAcceptor() { + public boolean doesAccept(Node node) { + return ( node instanceof ClassNode ) || + ( node instanceof ModuleNode ); } - } - - // Add instnace and class variables to matched elements - elements.addAll( instanceAndClassVarNames ); + }); } - // Get instance and class vars defined by [c]attr_* calls - List<String> attributes = AttributeLocator.Instance().findInstanceAttributesInScope(enclosingTypeNode); - elements.addAll( attributes ); - - - // Add all the globals: like magic compared to the others, hey? - elements.addAll( getElementsOfType( script, new int[] { IRubyElement.GLOBAL })); - } catch ( RubyModelException rme ) { - // Return empty 'elements' - } catch ( SyntaxException se ) { - // Return empty 'elements' + rme.printStackTrace(); } - - return elements; + + return new ArrayList<Node>(0); } + private List<String> getIncludedMixinNames( String typeName, IRubyScript script ) { + IType rubyType = new RubyType( (RubyElement)script, typeName ); + + try { + String[] includedModuleNames = rubyType.getIncludedModuleNames(); + if ( includedModuleNames != null ) { + return Arrays.asList(rubyType.getIncludedModuleNames()); + } else { + return new ArrayList<String>(0); + } + } catch (RubyModelException e) { + return new ArrayList<String>(0); + } + } + /** * Gets the name of a node by reflectively invoking "getName()" on it; * helper method just to cut many "instanceof/cast" pairs. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
Revision: 1567 Author: jasonpmorrison Date: 2006-08-14 21:18:13 -0700 (Mon, 14 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1567&view=rev Log Message: ----------- * Catch a stray null in RubyAbstractEditor Modified Paths: -------------- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java 2006-08-15 04:15:27 UTC (rev 1566) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java 2006-08-15 04:18:13 UTC (rev 1567) @@ -1483,7 +1483,7 @@ fOccurrencesFinderJobCanceler= null; } - if (fPostSelectionListener != null) { + if ((fPostSelectionListener != null) && ( getSourceViewer() != null ) && ( getSourceViewer().getSelectionProvider() != null ) ) { IPostSelectionProvider postSelectionProvider = (IPostSelectionProvider)getSourceViewer().getSelectionProvider(); postSelectionProvider.removePostSelectionChangedListener(fPostSelectionListener); fPostSelectionListener = null; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
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. |
|
From: <jas...@us...> - 2006-08-15 04:14:23
|
Revision: 1565 Author: jasonpmorrison Date: 2006-08-14 21:14:18 -0700 (Mon, 14 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1565&view=rev Log Message: ----------- * Eclipse-LazyStart: false is necessary in org.jruby (why?) Modified Paths: -------------- branches/type_inferrence/trunk/org.jruby/META-INF/MANIFEST.MF Modified: branches/type_inferrence/trunk/org.jruby/META-INF/MANIFEST.MF =================================================================== --- branches/type_inferrence/trunk/org.jruby/META-INF/MANIFEST.MF 2006-08-13 19:12:24 UTC (rev 1564) +++ branches/type_inferrence/trunk/org.jruby/META-INF/MANIFEST.MF 2006-08-15 04:14:18 UTC (rev 1565) @@ -6,7 +6,7 @@ Bundle-Activator: org.jruby.Activator Bundle-Localization: plugin Require-Bundle: org.eclipse.core.runtime -Eclipse-LazyStart: true +Eclipse-LazyStart: false Bundle-ClassPath: lib/jruby.jar, . Export-Package: org.ablaf.ast, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <mba...@us...> - 2006-08-13 19:12:33
|
Revision: 1564 Author: mbarchfe Date: 2006-08-13 12:12:24 -0700 (Sun, 13 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1564&view=rev Log Message: ----------- designker patch: removed cheatsheet extension point from plugin.xml, updated WebServices.xml Removed Paths: ------------- trunk/org.rubypeople.rdt.debug.ui/cheatsheets/WebServices.xml Deleted: trunk/org.rubypeople.rdt.debug.ui/cheatsheets/WebServices.xml =================================================================== --- trunk/org.rubypeople.rdt.debug.ui/cheatsheets/WebServices.xml 2006-08-13 18:54:53 UTC (rev 1563) +++ trunk/org.rubypeople.rdt.debug.ui/cheatsheets/WebServices.xml 2006-08-13 19:12:24 UTC (rev 1564) @@ -1,192 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<cheatsheet title="Using RDT"> - <intro href="/org.eclipse.platform.doc.user/reference/ref-cheatsheets.htm"> - <description> This cheat sheet is an introduction to the Ruby Development Tools - (RDT) and uses a real world scenario to show how the RDT can be leveraged in your - work with ruby. As a prerequiste you need to get and install soap4r 1.5.5: extract - soap4r-1_5_5.tar.gz and run install.rb. Although soap4r is included since - ruby 1.8.1, you will need it because of the wsdl2ruby.rb file, which is not part of - ruby 1.8.1 or later. Extract so To start working on this cheat sheet, click the - "Click to Begin" button below. </description> - </intro> - <item href="/org.rubypeople.rdt.doc.user/html/ch02.html#importantSettings" - title="Interpreter setup"> - <description> Make sure you have registered at least one ruby interpreter with RDT. - Click on the help button if you don't know how to do that. </description> - </item> - <item title="Switch to Ruby Perspective"> - <!-- Fix missing class - <action pluginId="org.rubypeople.rdt.debug.ui" - class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenRubyPerspectiveAction"/> ---> - <description> Use the "Click to Perform" button to open the ruby - perspective. This can also be done manually by choosing "Window->Open - Perspective->Other..." from the main menu and selecting - "Ruby" from the dialog which opens. </description> - </item> - <item title="Create Ruby project on soap4r"> - <action pluginId="org.rubypeople.rdt" param1="soap4r" - class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenNewRubyProjectWizardAction"/> - <description> In order to run wsdl2ruby.rb from the soap4r package, you create a ruby - project called soap4r on top of the soap4r installation directory at first. - After clicking the "Click to Perform" button below, the "New - Ruby Project" wizard will open. The project name "soap4r" is - already entered. Disable the "Use Default" checkbox in the project - content area and use the browse button to select the directory to which you have - unzipped the soap4r tar ball. </description> - </item> - <item title="Create MyWebservice project"> - <action pluginId="org.rubypeople.rdt" param1="MyWebservice" - class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenNewRubyProjectWizardAction"/> - <description> In this step you create a new project within your workspace, which will - be used to hold the wsdl file and the generated code from this file. The project is - called - "MyWebservice" The "Click to Perform" button opens the - "New Ruby Project" wizard again. This time you can leave the - "Use Default" checkbox enabled. This will create the project as a - subdirectory into your workspace location. </description> - </item> - <item title="Add wsdl file to MyWebservice"> - <action pluginId="org.rubypeople.rdt" param1="MyWebservice" - class="org.rubypeople.rdt.internal.cheatsheets.webservice.CreateWsdlFileAction"/> - <description> Add a new file called sample.wsdl to the MyWebservice project. In the - dialog which "Click to Perform" brings up you only have to enter the - file name - "sample.wsdl". The MyWebservice project is already selected as the - container of this new resource. </description> - </item> - <item title="Add content to sample.wsdl"> - <action pluginId="org.rubypeople.rdt" - param1="/cheatsheets/Sample.wsdl" param2="/MyWebservice/sample.wsdl" - class="org.rubypeople.rdt.internal.cheatsheets.webservice.CopyContentAction"/> - <description> In the last step you have created the file "sample.wsdl". - But why is it not there? It is, but is filtered out: In the Ruby Resources views menu - deselect - "Show Ruby Files only" (this can be found by clicking the down arrow in - the Ruby Resources view MenuBar, in the menu of options). The "Click to - Perform" buttons copies sample content to the wsdl file. The content is - copied from the Sample.wsdl file which ships with RDT. </description> - </item> - <item title="Run wsdl2ruby.rb" - href="/org.rubypeople.rdt.doc.user/html/ch03s10.html"> - <description> Open the soap4r project. Open the bin directory and right-click the - "wsdl2ruby.rb" file to open the context menu. Choose - "Run->Run Ruby Application". Check the console for the output of the - process. There you find the required command line options. </description> - </item> - <item title="Modify the run configuration for server generation"> - <action pluginId="org.rubypeople.rdt" - class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenRunConfigurationAction"/> - <description> "Click to Perform" opens the run configuration dialog, - which is also available as Run As->Run... from the main menu. The running of - wsdl2ruby.rb in the last step has created a run-configuration named - "wsdl2ruby.rb". Rename it to - "wsdl-gen-server" Now open the Arguments tab and add "--wsdl - sample.wsdl --type server" to the program arguments. Then you change the - working directory to the directory of the MyWebservice project. Therefore you - must know where your workspace resides on the local disk: If you have forgotten - which workspace you are using or where it resides, you can choose - "File->Switch Workspace". </description> - </item> - <item title="Check generated server files"> - <description> The execution of the last step should have generated three files. - Because they have been created on the file system from the outside, you must - execute - "Refresh" from the context menu of the MyWebservice project. Then - you should see the new files: webServiceExample.rb, - webServiceExampleServant.rb and webServiceExampleService.rb. If they are - not there or are empty, check the console for error messages. If there is a stack - trace in the console, you can double-click to open the specified file locations. - </description> - </item> - <item title="Create Run-Configuration for client generation"> - <action pluginId="org.rubypeople.rdt" - class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenRunConfigurationAction"/> - <description> "Click to Perform" opens the run configuration dialog - again. Perform "Duplicate" from the context menu of the - wsdl-gen-server run configuration. A duplicate "wsdl-gen-server - (1)" will be generated. Rename it to "wsdl-gen-client", - change the argument "--type server" to - "--type client" and click "Run". </description> - </item> - <item title="Check generated client files"> - <description> Click "Refresh" on the MyWebservice project to display - the two newly generated files: webServiceExampleDriver.rb and - webServiceExampleServiceClient.rb. </description> - </item> - <item href="/org.rubypeople.rdt.doc.user/html/ch03s12.html#DebugKnownLimitations" - title="Check ruby version"> - <description> Please note there are limitations in the ruby versions which are - suitable for debugging. On Linux there is a restriction to ruby 1.6, on windows - ruby 1.8.2 works fine but 1.8.1 does not. See Help->Help Contents for more - details. If your version of ruby does not meet these requirements, use - "Run->Run Ruby Application" instead of - "Debug->Debug Ruby Application" in the next step for starting the - server. </description> - </item> - <item title="Debug server"> - <description> Open the editor for webServiceExampleServant.rb (by - double-clicking it in the "Ruby Resources" view) and set a - breakpoint in the line which raises the NotImplementedError. A breakpoint can - be set and removed either by double-clicking on the vertical bar at the left side - of the editor or by using the context menu on that bar. Start the debugger with - "Debug->Debug Ruby Application" from the context menu of - webServiceExampleService.rb. </description> - </item> - <item title="Modify the client"> - <description> If you look at the client code in webServiceExampleServiceClient.rb - you will notice that the user variable is set to nil. Assign a new user object - instead, e.b. with User.new('myID', 'myName'). Save the editor with the icon - from the toolbar or ctrl+s.</description> - </item> - <item title="Run the client"> - <action pluginId="org.rubypeople.rdt" - class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenRunConfigurationAction"/> - <description> Use the "Click to perform" button or select - "Run->Run..." from the main menu to open the run configuration - dialog. Select "Ruby Application" and click "New". - Rename the newly created run configuration to "run-client". Select - webServiceExampleServiceClient.rb as the file to be run with the - "Browse" button. Go the Arguments Tab and add - "http://localhost:10080/" as program argument. Click Run. - </description> - </item> - <item href="/org.rubypeople.rdt.doc.user/html/ch03s12.html#startDebugSession" - title="Breakpoint hit"> - <description> After a while the clients request will trigger the breakpoint in the - server process. If you haven't debugged before, you will be asked whether to - switch to the debug perspective or not. You should confirm the switch. In the - debug perspective you can see where the server process halted and examine the - program state. E.g. in the Variables view you can see the attribute values of - the user object. </description> - </item> - <item title="Edit the server code"> - <description>If you have a look at - the wsdl file, you'll discover that the addUser method expects an integer as return - value. Therefore you can replace the raise command with "return 0" and - save the new code. When you save the code the ruby interpreter, which runs the - server, also reloads the code. Now resume the server with the resume button, - "Run->Resume" or F8.</description> - </item> - <item href="/org.rubypeople.rdt.doc.user/html/ch03s12.html#codeReload" - title="Check the output of the client"> - <description> In the Debug view you can see that the client has terminated. In order to - see its output, select the terminated process. After that the Console shows the - output of the client, which is a stack trace showing the NotImplementedError: - although the interpreter has reloaded the new content of - webServiceExampleServant.rb it finished the stack with the old code. - Therefore we must run the client again.</description> - </item> - <item title="Run the client again"> - <description> Now run the client again with "Run->Run - History->run-client", wait for the breakpoint and resume again. The - console displays 0, the result of the addUser method, instead of the stack trace. - </description> - </item> - <item title="End"> - <description> This tutorial has given you a short overview of RDT. Please mind that - RDT is an an open source project and needs the feedback and contributions - from the users. Please visit http://www.rubypeople.org/ if you want to help to - further improve RDT.</description> - </item> -</cheatsheet> \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <mba...@us...> - 2006-08-13 18:55:06
|
Revision: 1563 Author: mbarchfe Date: 2006-08-13 11:54:53 -0700 (Sun, 13 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1563&view=rev Log Message: ----------- designker patch: removed cheatsheet extension point from plugin.xml, updated WebServices.xml Modified Paths: -------------- trunk/org.rubypeople.rdt.debug.ui/plugin.xml Removed Paths: ------------- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/cheatsheets/webservice/ Modified: trunk/org.rubypeople.rdt.debug.ui/plugin.xml =================================================================== --- trunk/org.rubypeople.rdt.debug.ui/plugin.xml 2006-08-13 18:53:45 UTC (rev 1562) +++ trunk/org.rubypeople.rdt.debug.ui/plugin.xml 2006-08-13 18:54:53 UTC (rev 1563) @@ -266,17 +266,6 @@ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/> </extension> - <extension point="org.eclipse.ui.cheatsheets.cheatSheetContent"> - <category name="Ruby" id="org.rubypeople.rdt.cheatsheet.category"> - </category> - <cheatsheet name="%cheatsheet.webservices.name" - category="org.rubypeople.rdt.cheatsheet.category" - contentFile="$nl$/cheatsheets/WebServices.xml" - id="org.rubypeople.rdt.cheatsheets.webservices"> - <description>%cheatsheet.webservices.desc</description> - </cheatsheet> - </extension> - <extension point="org.rubypeople.rdt.ui.editorPopupExtender"> <rubyEditorPopupMenuExtension class="org.rubypeople.rdt.internal.debug.ui.RubyEditorPopupMenuExtension"> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <mba...@us...> - 2006-08-13 18:53:51
|
Revision: 1562 Author: mbarchfe Date: 2006-08-13 11:53:45 -0700 (Sun, 13 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1562&view=rev Log Message: ----------- designker patch: removed cheatsheet extension point from plugin.xml, updated WebServices.xml Removed Paths: ------------- trunk/org.rubypeople.rdt.debug.ui/cheatsheets/Sample.wsdl Deleted: trunk/org.rubypeople.rdt.debug.ui/cheatsheets/Sample.wsdl =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <mba...@us...> - 2006-08-13 18:52:52
|
Revision: 1561 Author: mbarchfe Date: 2006-08-13 11:52:46 -0700 (Sun, 13 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1561&view=rev Log Message: ----------- designker patch: removed cheatsheet extension point from plugin.xml, updated WebServices.xml Modified Paths: -------------- trunk/org.rubypeople.rdt/cheatsheets/WebServices.xml Modified: trunk/org.rubypeople.rdt/cheatsheets/WebServices.xml =================================================================== --- trunk/org.rubypeople.rdt/cheatsheets/WebServices.xml 2006-08-09 13:23:55 UTC (rev 1560) +++ trunk/org.rubypeople.rdt/cheatsheets/WebServices.xml 2006-08-13 18:52:46 UTC (rev 1561) @@ -15,10 +15,9 @@ Click on the help button if you don't know how to do that. </description> </item> <item title="Switch to Ruby Perspective"> - <!-- Fix missing class - <action pluginId="org.rubypeople.rdt.debug.ui" - class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenRubyPerspectiveAction"/> ---> + <command + serialization="org.eclipse.ui.perspectives.showPerspective(org.eclipse.ui.perspectives.showPerspective.perspectiveId=org.rubypeople.rdt.ui.PerspectiveRuby)"> + </command> <description> Use the "Click to Perform" button to open the ruby perspective. This can also be done manually by choosing "Window->Open Perspective->Other..." from the main menu and selecting This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <jas...@us...> - 2006-08-09 13:24:02
|
Revision: 1560 Author: jasonpmorrison Date: 2006-08-09 06:23:55 -0700 (Wed, 09 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1560&view=rev Log Message: ----------- Working on completion for elements available in scope (args/locals/instvars/classvars/globals) Added Paths: ----------- branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/AttributeLocator.java Added: 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 (rev 0) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/util/AttributeLocator.java 2006-08-09 13:23:55 UTC (rev 1560) @@ -0,0 +1,124 @@ +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.FCallNode; +import org.jruby.ast.Node; +import org.jruby.ast.StrNode; +import org.jruby.ast.SymbolNode; +import org.jruby.evaluator.Instruction; + +/** + * Visitor to find all instance and class attribute declarations (attr_*, cattr_*) within a specific scope. + * @author Jason Morrison + */ +public class AttributeLocator extends NodeLocator { + + //Singleton pattern + private AttributeLocator() {} + private static AttributeLocator staticInstance = new AttributeLocator(); + public static AttributeLocator Instance() + { + return staticInstance; + } + + /** Running total of results; is a Set to ensure uniqueness */ + private Set<String> attributes; + + /** + * Finds all instance attributes within a given node by looking for attr_* calls + * @param rootNode + * @return + */ + public List<String> findInstanceAttributesInScope(Node rootNode) { + if ( rootNode == null ) { return null; } + + attributes = new HashSet<String>(); + +// Traverse to find all matches + rootNode.accept(this); + + // Return the matches + return new ArrayList<String>(attributes); + } + + /** + * Searches via InOrderVisitor for matches + */ + public Instruction handleNode(Node node ) { + // Look for FCallNodes to attr_* + if ( node instanceof FCallNode ) { + FCallNode fCallNode = (FCallNode)node; + + // Set up the prefix for instance (@) or class (@@) attributes + String attrPrefix = null; + if ( isInstanceAttributeDeclaration(fCallNode.getName()) ) { + attrPrefix = "@"; + } + if ( isClassAttributeDeclaration(fCallNode.getName()) ) { + attrPrefix = "@@"; + } + if ( attrPrefix != null) { + // Look for an array of symbols or strings - these are the instance variables being declared + Node argsNode = fCallNode.getArgsNode(); + if ( argsNode instanceof ArrayNode ) { + ArrayNode arrayNode = (ArrayNode)argsNode; + for (Iterator iter = arrayNode.iterator(); iter.hasNext();) { + Node argNode = (Node) iter.next(); + + // The nodes are found - record them! + if ( argNode instanceof SymbolNode ) { + attributes.add(attrPrefix + ((SymbolNode)argNode).getName() ); + } + if ( argNode instanceof StrNode ) { + attributes.add(attrPrefix + ((StrNode)argNode).getValue() ); + } + System.out.println(argNode.getClass().getName()); + + } + } + } + } + + return super.handleNode(node); + } + + /** + * Returns whether the specified method name is an instance attribute declaration + * (i.e. attr_* :foo, 'bar', "baz") + * @param methodName Method name to test + * @return + */ + private boolean isInstanceAttributeDeclaration(String methodName) { + return ( + methodName.equals("attr") || + methodName.equals("attr_reader") || + methodName.equals("attr_writer") || + methodName.equals("attr_accessor") ); + } + /** + * Returns whether the specified method name is a class attribute declaration + * (i.e. cattr_* :foo, 'bar', "baz") + * Non-standard, but conventional enough to be helpful, I believe. + * @param methodName Method name to test + * @return + */ + private boolean isClassAttributeDeclaration(String methodName) { + return ( + methodName.equals("cattr") || + methodName.equals("cattr_reader") || + methodName.equals("cattr_writer") || + methodName.equals("cattr_accessor") ); + } + + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
Revision: 1559 Author: jasonpmorrison Date: 2006-08-09 06:23:44 -0700 (Wed, 09 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1559&view=rev Log Message: ----------- Working on completion for elements available in scope (args/locals/instvars/classvars/globals) Modified Paths: -------------- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java 2006-08-09 02:40:35 UTC (rev 1558) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java 2006-08-09 13:23:44 UTC (rev 1559) @@ -30,17 +30,20 @@ import org.eclipse.ui.IEditorPart; import org.jruby.ast.ArgsNode; import org.jruby.ast.ArgumentNode; +import org.jruby.ast.CallNode; import org.jruby.ast.ClassNode; import org.jruby.ast.ClassVarAsgnNode; import org.jruby.ast.ClassVarDeclNode; import org.jruby.ast.ClassVarNode; import org.jruby.ast.DefnNode; import org.jruby.ast.DefsNode; +import org.jruby.ast.FCallNode; import org.jruby.ast.InstAsgnNode; import org.jruby.ast.InstVarNode; import org.jruby.ast.ModuleNode; import org.jruby.ast.Node; import org.jruby.ast.ScopeNode; +import org.jruby.ast.VCallNode; import org.jruby.lexer.yacc.SyntaxException; import org.rubypeople.rdt.core.CompletionRequestor; import org.rubypeople.rdt.core.IParent; @@ -50,6 +53,7 @@ import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.core.parser.RubyParser; import org.rubypeople.rdt.internal.corext.template.ruby.RubyContextType; +import org.rubypeople.rdt.internal.ti.util.AttributeLocator; import org.rubypeople.rdt.internal.ti.util.FirstPrecursorNodeLocator; import org.rubypeople.rdt.internal.ti.util.INodeAcceptor; import org.rubypeople.rdt.internal.ti.util.ScopedNodeLocator; @@ -534,6 +538,11 @@ elements.addAll( instanceAndClassVarNames ); } + // Get instance and class vars defined by [c]attr_* calls + List<String> attributes = AttributeLocator.Instance().findInstanceAttributesInScope(enclosingTypeNode); + elements.addAll( attributes ); + + // Add all the globals: like magic compared to the others, hey? elements.addAll( getElementsOfType( script, new int[] { IRubyElement.GLOBAL })); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
Revision: 1558 Author: jasonpmorrison Date: 2006-08-08 19:40:35 -0700 (Tue, 08 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1558&view=rev Log Message: ----------- Working on completion for elements available in scope (args/locals/instvars/classvars/globals) Modified Paths: -------------- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java Modified: branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java =================================================================== --- branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java 2006-08-08 23:59:21 UTC (rev 1557) +++ branches/type_inferrence/trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/text/ruby/RubyCompletionProcessor.java 2006-08-09 02:40:35 UTC (rev 1558) @@ -1,12 +1,16 @@ package org.rubypeople.rdt.internal.ui.text.ruby; +import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; +import java.util.Set; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; @@ -24,13 +28,31 @@ import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IEditorPart; +import org.jruby.ast.ArgsNode; +import org.jruby.ast.ArgumentNode; +import org.jruby.ast.ClassNode; +import org.jruby.ast.ClassVarAsgnNode; +import org.jruby.ast.ClassVarDeclNode; +import org.jruby.ast.ClassVarNode; +import org.jruby.ast.DefnNode; +import org.jruby.ast.DefsNode; +import org.jruby.ast.InstAsgnNode; +import org.jruby.ast.InstVarNode; +import org.jruby.ast.ModuleNode; +import org.jruby.ast.Node; +import org.jruby.ast.ScopeNode; +import org.jruby.lexer.yacc.SyntaxException; import org.rubypeople.rdt.core.CompletionRequestor; import org.rubypeople.rdt.core.IParent; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.RubyModelException; +import org.rubypeople.rdt.internal.core.parser.RubyParser; import org.rubypeople.rdt.internal.corext.template.ruby.RubyContextType; +import org.rubypeople.rdt.internal.ti.util.FirstPrecursorNodeLocator; +import org.rubypeople.rdt.internal.ti.util.INodeAcceptor; +import org.rubypeople.rdt.internal.ti.util.ScopedNodeLocator; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.RubyPluginImages; import org.rubypeople.rdt.internal.ui.text.template.contentassist.RubyTemplateAccess; @@ -181,7 +203,7 @@ */ private ICompletionProposal[] determineRubyElementProposals( ITextViewer viewer, int documentOffset) { - Collection completionProposals = getDocumentsRubyElements(documentOffset); + Collection completionProposals = getDocumentsRubyElementsInScope(documentOffset); String prefix = getCurrentPrefix(viewer.getDocument().get(), documentOffset); // following the JDT convention, if there's no text already entered, @@ -358,25 +380,41 @@ * * @return a List of the names of all the elements in the current RubyScript */ - private Collection getDocumentsRubyElements(int documentOffset) { + private Collection getDocumentsRubyElementsInScope(int documentOffset) { IRubyScript script = fManager.getWorkingCopy(fEditor.getEditorInput()); // FIXME Get only the elements in the current scope! - Collection elements = getElements(script); + Collection elements = getElementsInScope(script, documentOffset); + +// Collection elements = getElements(script); +// System.out.println(" :: " + elements.size() ); + IRubyProject project = script.getRubyProject(); // Add all the classes and modules in the project elements.addAll(addClassesAndModulesInProject(project)); +// System.out.println(" :: " + elements.size() ); + + // Add all the classes and modules in referenced projects for (Iterator iter = project.getReferencedProjects().iterator(); iter .hasNext();) { elements.addAll(addClassesAndModulesInProject(((IRubyProject) iter .next()))); } + System.out.println(" :: " + elements.size() ); + + // TODO Add all the methods defined in included modules for the class // TODO Add all the methods defined in superclasses for the class/module // always add Kernel methods elements.addAll(addKernelMethods()); + System.out.println(" :: " + elements.size() ); + + for ( Object element : elements ) + { +// System.out.println(" -- Element: " + (String)element); + } return elements; } @@ -418,7 +456,114 @@ IRubyElement.CONSTANT, IRubyElement.CLASS_VAR, IRubyElement.INSTANCE_VAR }); } + + /** + * Gets the names of elements available in the specified scope. This includes: + * - Method arguments + * - Method locals + * - Enclosing class/module instance variables + * - Enclosing class/module class variables + * - Globals + * + * @param script Script to collect available elements from + * @param offset Offset in script to determine the access scope (for args/locals/instvars/classvars) + * @return + */ + public Collection getElementsInScope(IRubyScript script, int offset) { + String source = ""; + Collection elements = new ArrayList(); + try { + // Get the script's source, and parse it. + source = script.getSource(); + Node rootNode = (new RubyParser()).parse(source); + if ( rootNode == null ) { return elements; } + // Find the enclosing method to get locals and args + Node enclosingMethodNode = FirstPrecursorNodeLocator.Instance().findFirstPrecursor(rootNode, offset, new INodeAcceptor() { + public boolean doesAccept(Node node) { + return ( node instanceof DefnNode || node instanceof DefsNode ); + }}); + + // Add locally available arguments +// ArgsNode argsNode = null; +// if ( enclosingMethodNode instanceof DefnNode ) { argsNode = (ArgsNode)((DefnNode)enclosingMethodNode).getArgsNode(); } +// if ( enclosingMethodNode instanceof DefsNode ) { argsNode = (ArgsNode)((DefsNode)enclosingMethodNode).getArgsNode(); } +// if ( argsNode != null ) { +// for (Iterator iter = argsNode.getArgs().iterator(); iter.hasNext();) { +// elements.add( ((ArgumentNode)iter.next()).getName() ); +// } +// } + + + // Add local vars - arguments are included + ScopeNode scopeNode = null; + if ( enclosingMethodNode instanceof DefnNode ) { scopeNode = (ScopeNode)((DefnNode)enclosingMethodNode).getBodyNode(); } + if ( enclosingMethodNode instanceof DefsNode ) { scopeNode = (ScopeNode)((DefsNode)enclosingMethodNode).getBodyNode(); } + if ( scopeNode != null && scopeNode.getLocalNames().length > 0 ) { + elements.addAll( Arrays.asList (scopeNode.getLocalNames()) ); + } + + + // Find the enclosing type (class or module) to get instance and classvars from + Node enclosingTypeNode = FirstPrecursorNodeLocator.Instance().findFirstPrecursor(rootNode, offset, new INodeAcceptor() { + public boolean doesAccept(Node node) { + return ( node instanceof ClassNode || node instanceof ModuleNode ); + }}); + + // Get instance and class variables available in the enclosing type + List<Node> instanceAndClassVars = ScopedNodeLocator.Instance().findNodesInScope(enclosingTypeNode, new INodeAcceptor() { + public boolean doesAccept(Node node) { + return ( node instanceof InstVarNode || + node instanceof InstAsgnNode || + node instanceof ClassVarNode || + node instanceof ClassVarDeclNode || + node instanceof ClassVarAsgnNode ); + }}); + + if ( instanceAndClassVars != null ) { + // Get the unique names of instance and class variables + Set instanceAndClassVarNames = new HashSet(instanceAndClassVars.size()); + for ( Node varNode : instanceAndClassVars ) { + String name = getNameReflectively(varNode); + if ( name != null ) { + instanceAndClassVarNames.add(name); + } + } + + // Add instnace and class variables to matched elements + elements.addAll( instanceAndClassVarNames ); + } + + // Add all the globals: like magic compared to the others, hey? + elements.addAll( getElementsOfType( script, new int[] { IRubyElement.GLOBAL })); + + } catch ( RubyModelException rme ) { + // Return empty 'elements' + } catch ( SyntaxException se ) { + // Return empty 'elements' + } + + return elements; + } + + /** + * Gets the name of a node by reflectively invoking "getName()" on it; + * helper method just to cut many "instanceof/cast" pairs. + * @param node + * @return name or null + */ + // TODO Copy/pasted from DefaultOccurrencesFinder, refactor these two methods to a common location. + private String getNameReflectively( Node node ) { + try { + Method getNameMethod = node.getClass().getMethod("getName", new Class[]{}); + Object name = getNameMethod.invoke( node, new Object[0] ); + return (String)name; + } catch (Exception e) { + return null; + } + } + + private ICompletionProposal[] determineKeywordProposals(ITextViewer viewer, int documentOffset) { initKeywordProposals(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <caw...@us...> - 2006-08-08 23:59:26
|
Revision: 1557 Author: cawilliams Date: 2006-08-08 16:59:21 -0700 (Tue, 08 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1557&view=rev Log Message: ----------- move all tab conversion stuff down into RubyEditor (doesn't apply to External editor), fixes ticket #144 Modified Paths: -------------- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java =================================================================== --- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java 2006-08-08 23:45:26 UTC (rev 1556) +++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyAbstractEditor.java 2006-08-08 23:59:21 UTC (rev 1557) @@ -39,7 +39,6 @@ import org.eclipse.ui.editors.text.TextEditor; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import org.eclipse.ui.texteditor.ChainedPreferenceStore; -import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; import org.eclipse.ui.views.contentoutline.ContentOutline; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; @@ -54,11 +53,8 @@ import org.rubypeople.rdt.core.ISourceReference; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.RubyModelException; -import org.rubypeople.rdt.core.formatter.DefaultCodeFormatterConstants; -import org.rubypeople.rdt.internal.corext.util.CodeFormatterUtil; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.rubyeditor.RubyEditor.ITextConverter; -import org.rubypeople.rdt.internal.ui.rubyeditor.RubyEditor.TabConverter; import org.rubypeople.rdt.internal.ui.text.ContentAssistPreference; import org.rubypeople.rdt.internal.ui.text.IRubyPartitions; import org.rubypeople.rdt.internal.ui.text.PreferencesAdapter; @@ -80,18 +76,13 @@ /** The selection changed listener */ protected AbstractSelectionChangedListener fOutlineSelectionChangedListener = new OutlineSelectionChangedListener(); private RubyOutlinePage fOutlinePage; - /** The editor's tab converter */ - private TabConverter fTabConverter; /** Preference key for matching brackets */ protected final static String MATCHING_BRACKETS= PreferenceConstants.EDITOR_MATCHING_BRACKETS; /** Preference key for matching brackets color */ protected final static String MATCHING_BRACKETS_COLOR= PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR; - /** Preference key for code formatter tab size */ - private final static String CODE_FORMATTER_TAB_SIZE= DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE; - /** Preference key for inserting spaces rather than tabs */ - private final static String SPACES_FOR_TABS= DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR; + protected final static char[] BRACKETS= { '{', '}', '(', ')', '[', ']' }; /** The editor's bracket matcher */ @@ -219,7 +210,6 @@ */ protected void doSetInput(IEditorInput input) throws CoreException { super.doSetInput(input); - configureTabConverter(); setOutlinePageInput(fOutlinePage, input); } @@ -250,21 +240,7 @@ return; ((RubySourceViewerConfiguration)getSourceViewerConfiguration()).handlePropertyChangeEvent(event); - - if (SPACES_FOR_TABS.equals(property)) { - if (isTabConversionEnabled()) - startTabConversion(); - else - stopTabConversion(); - return; - } - - if (CODE_FORMATTER_TAB_SIZE.equals(property)) { - sourceViewer.updateIndentationPrefixes(); - if (fTabConverter != null) - fTabConverter.setNumberOfSpacesPerTab(getTabSize()); - } - + IContentAssistant c= sourceViewer.getContentAssistant(); if (c instanceof ContentAssistant) ContentAssistPreference.changeConfiguration((ContentAssistant) c, getPreferenceStore(), event); @@ -289,34 +265,8 @@ } } - private int getTabSize() { - IRubyElement element= getInputRubyElement(); - IRubyProject project= element == null ? null : element.getRubyProject(); - return CodeFormatterUtil.getTabWidth(project); - } - private void startTabConversion() { - if (fTabConverter == null) { - fTabConverter= new TabConverter(); - configureTabConverter(); - fTabConverter.setNumberOfSpacesPerTab(getTabSize()); - AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer(); - asv.addTextConverter(fTabConverter); - // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270 - asv.updateIndentationPrefixes(); - } - } - private void configureTabConverter() { - if (fTabConverter != null) { - IDocumentProvider provider= getDocumentProvider(); - if (provider instanceof IRubyScriptDocumentProvider) { - IRubyScriptDocumentProvider cup= (IRubyScriptDocumentProvider) provider; - fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput())); - } - } - } - /** * Returns the Ruby element wrapped by this editors input. * @@ -330,34 +280,6 @@ return RubyUI.getEditorInputRubyElement(getEditorInput()); } - private void stopTabConversion() { - if (fTabConverter != null) { - AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer(); - asv.removeTextConverter(fTabConverter); - // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270 - asv.updateIndentationPrefixes(); - fTabConverter= null; - } - } - - public void createPartControl(Composite parent) { - super.createPartControl(parent); - - if (isTabConversionEnabled()) - startTabConversion(); - } - - private boolean isTabConversionEnabled() { - IRubyElement element= getInputRubyElement(); - IRubyProject project= element == null ? null : element.getRubyProject(); - String option; - if (project == null) - option= RubyCore.getOption(SPACES_FOR_TABS); - else - option= project.getOption(SPACES_FOR_TABS, true); - return RubyCore.SPACE.equals(option); - } - protected void handleOutlinePageSelection(SelectionChangedEvent event) { StructuredSelection selection = (StructuredSelection) event.getSelection(); Iterator iter = ((IStructuredSelection) selection).iterator(); Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java =================================================================== --- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java 2006-08-08 23:45:26 UTC (rev 1556) +++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java 2006-08-08 23:59:21 UTC (rev 1557) @@ -77,6 +77,7 @@ import org.eclipse.ui.help.WorkbenchHelp; import org.eclipse.ui.texteditor.AnnotationPreference; import org.eclipse.ui.texteditor.ContentAssistAction; +import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.IEditorStatusLine; import org.eclipse.ui.texteditor.ITextEditorActionConstants; import org.eclipse.ui.texteditor.MarkerAnnotation; @@ -84,8 +85,12 @@ import org.eclipse.ui.texteditor.link.EditorLinkedModeUI; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.rubypeople.rdt.core.IRubyElement; +import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IRubyScript; +import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.RubyModelException; +import org.rubypeople.rdt.core.formatter.DefaultCodeFormatterConstants; +import org.rubypeople.rdt.internal.corext.util.CodeFormatterUtil; import org.rubypeople.rdt.internal.corext.util.RubyModelUtil; import org.rubypeople.rdt.internal.ui.IRubyHelpContextIds; import org.rubypeople.rdt.internal.ui.RubyPlugin; @@ -107,6 +112,9 @@ protected RubyActionGroup actionGroup; private ProjectionSupport fProjectionSupport; + + /** The editor's tab converter */ + private TabConverter fTabConverter; /** Preference key for automatically closing strings */ private final static String CLOSE_STRINGS= PreferenceConstants.EDITOR_CLOSE_STRINGS; @@ -114,7 +122,11 @@ private final static String CLOSE_BRACKETS= PreferenceConstants.EDITOR_CLOSE_BRACKETS; /** Preference key for automatically closing braces */ private final static String CLOSE_BRACES= PreferenceConstants.EDITOR_CLOSE_BRACES; - + /** Preference key for code formatter tab size */ + private final static String CODE_FORMATTER_TAB_SIZE= DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE; + /** Preference key for inserting spaces rather than tabs */ + private final static String SPACES_FOR_TABS= DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR; + /** * Mutex for the reconciler. See * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898 for a description of @@ -279,6 +291,9 @@ if (isFoldingEnabled()) projectionViewer.doOperation(ProjectionViewer.TOGGLE); + if (isTabConversionEnabled()) + startTabConversion(); + ISourceViewer sourceViewer = getSourceViewer(); if (sourceViewer instanceof ITextViewerExtension) { IPreferenceStore preferenceStore= getPreferenceStore(); @@ -661,7 +676,7 @@ */ protected void doSetInput(IEditorInput input) throws CoreException { super.doSetInput(input); - + configureTabConverter(); if (fProjectionModelUpdater != null) fProjectionModelUpdater.initialize(); } @@ -721,10 +736,24 @@ fBracketInserter.setCloseStringsEnabled(getPreferenceStore().getBoolean(property)); return; } - - ISourceViewer sourceViewer= getSourceViewer(); + + AdaptedSourceViewer sourceViewer= (AdaptedSourceViewer) getSourceViewer(); if (sourceViewer == null) return; + + if (SPACES_FOR_TABS.equals(property)) { + if (isTabConversionEnabled()) + startTabConversion(); + else + stopTabConversion(); + return; + } + + if (CODE_FORMATTER_TAB_SIZE.equals(property)) { + sourceViewer.updateIndentationPrefixes(); + if (fTabConverter != null) + fTabConverter.setNumberOfSpacesPerTab(getTabSize()); + } if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) { if (sourceViewer instanceof ProjectionViewer) { @@ -1558,4 +1587,54 @@ public FoldingActionGroup getFoldingActionGroup() { return fFoldingGroup; } + + private int getTabSize() { + IRubyElement element= getInputRubyElement(); + IRubyProject project= element == null ? null : element.getRubyProject(); + return CodeFormatterUtil.getTabWidth(project); + } + + private void startTabConversion() { + if (fTabConverter == null) { + fTabConverter= new TabConverter(); + configureTabConverter(); + fTabConverter.setNumberOfSpacesPerTab(getTabSize()); + AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer(); + asv.addTextConverter(fTabConverter); + // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270 + asv.updateIndentationPrefixes(); + } + } + + private void configureTabConverter() { + if (fTabConverter != null) { + IDocumentProvider provider= getDocumentProvider(); + if (provider instanceof IRubyScriptDocumentProvider) { + IRubyScriptDocumentProvider cup= (IRubyScriptDocumentProvider) provider; + fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput())); + } + } + } + + + private void stopTabConversion() { + if (fTabConverter != null) { + AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer(); + asv.removeTextConverter(fTabConverter); + // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270 + asv.updateIndentationPrefixes(); + fTabConverter= null; + } + } + + private boolean isTabConversionEnabled() { + IRubyElement element= getInputRubyElement(); + IRubyProject project= element == null ? null : element.getRubyProject(); + String option; + if (project == null) + option= RubyCore.getOption(SPACES_FOR_TABS); + else + option= project.getOption(SPACES_FOR_TABS, true); + return RubyCore.SPACE.equals(option); + } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <caw...@us...> - 2006-08-08 23:45:30
|
Revision: 1556 Author: cawilliams Date: 2006-08-08 16:45:26 -0700 (Tue, 08 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1556&view=rev Log Message: ----------- add then to list of keywords Modified Paths: -------------- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/rubyeditor/RubyEditorPreferences.properties Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/rubyeditor/RubyEditorPreferences.properties =================================================================== --- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/rubyeditor/RubyEditorPreferences.properties 2006-08-08 07:03:10 UTC (rev 1555) +++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/rubyeditor/RubyEditorPreferences.properties 2006-08-08 23:45:26 UTC (rev 1556) @@ -1 +1 @@ -keywords=BEGIN,END,alias,begin,do,end,yield,if,unless,elsif,else,while,unless,for,in,super,retry,redo,break,case,when,throw,and,or,not,raise,rescue,ensure,new,each,def,class,module,return,false,true,nil \ No newline at end of file +keywords=BEGIN,END,alias,begin,do,end,yield,if,unless,elsif,else,while,unless,for,in,super,retry,redo,break,case,when,throw,and,or,not,raise,rescue,ensure,new,each,def,class,module,return,false,true,nil,then \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <mba...@us...> - 2006-08-08 07:03:16
|
Revision: 1555 Author: mbarchfe Date: 2006-08-08 00:03:10 -0700 (Tue, 08 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1555&view=rev Log Message: ----------- designker patch: Restored Welcome page, moved cheatsheet actions from rdt.debug.ui to rdt Added Paths: ----------- trunk/org.rubypeople.rdt/intro/css/rdtOverview.css trunk/org.rubypeople.rdt/intro/css/rdtTutorials.css Added: trunk/org.rubypeople.rdt/intro/css/rdtOverview.css =================================================================== --- trunk/org.rubypeople.rdt/intro/css/rdtOverview.css (rev 0) +++ trunk/org.rubypeople.rdt/intro/css/rdtOverview.css 2006-08-08 07:03:10 UTC (rev 1555) @@ -0,0 +1,2 @@ +a#ruby img { background-image : url(graphics/rdt_overview.gif); } +a#ruby:hover img { background-image : url(graphics/rdt_overviewhov.gif); } \ No newline at end of file Added: trunk/org.rubypeople.rdt/intro/css/rdtTutorials.css =================================================================== --- trunk/org.rubypeople.rdt/intro/css/rdtTutorials.css (rev 0) +++ trunk/org.rubypeople.rdt/intro/css/rdtTutorials.css 2006-08-08 07:03:10 UTC (rev 1555) @@ -0,0 +1,2 @@ +a#ruby-introduction img { background-image : url(graphics/rdt_tutorial.gif); } +a#ruby-introduction:hover img { background-image : url(graphics/rdt_tutorialhov.gif); } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <mba...@us...> - 2006-08-08 07:02:31
|
Revision: 1554 Author: mbarchfe Date: 2006-08-08 00:02:25 -0700 (Tue, 08 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1554&view=rev Log Message: ----------- designker patch: Restored Welcome page, moved cheatsheet actions from rdt.debug.ui to rdt Removed Paths: ------------- trunk/org.rubypeople.rdt/intro/css/rdtOverview.css trunk/org.rubypeople.rdt/intro/css/rdtTutorials.css Deleted: trunk/org.rubypeople.rdt/intro/css/rdtOverview.css =================================================================== (Binary files differ) Deleted: trunk/org.rubypeople.rdt/intro/css/rdtTutorials.css =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <mba...@us...> - 2006-08-08 07:00:31
|
Revision: 1553 Author: mbarchfe Date: 2006-08-08 00:00:22 -0700 (Tue, 08 Aug 2006) ViewCVS: http://svn.sourceforge.net/rubyeclipse/?rev=1553&view=rev Log Message: ----------- designker patch: Restored Welcome page, moved cheatsheet actions from rdt.debug.ui to rdt Added Paths: ----------- trunk/org.rubypeople.rdt/cheatsheets/ trunk/org.rubypeople.rdt/cheatsheets/Sample.wsdl trunk/org.rubypeople.rdt/cheatsheets/WebServices.xml Added: trunk/org.rubypeople.rdt/cheatsheets/Sample.wsdl =================================================================== --- trunk/org.rubypeople.rdt/cheatsheets/Sample.wsdl (rev 0) +++ trunk/org.rubypeople.rdt/cheatsheets/Sample.wsdl 2006-08-08 07:00:22 UTC (rev 1553) @@ -0,0 +1,64 @@ +<?xml version="1.0"?> + +<definitions name="webServiceExample" + targetNamespace="http://www.rubypeople.org/xmlns/webServiceExample" + xmlns:tns="http://www.rubypeople.org/xmlns/webServiceExample" + xmlns="http://schemas.xmlsoap.org/wsdl/" + xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" + xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" + xmlns:apachesoap="http://xml.apache.org/xml-soap"> + + <types> + <schema + xmlns="http://www.w3.org/2001/XMLSchema" + targetNamespace="http://www.rubypeople.org/xmlns/webServiceExample"> + + <complexType name="User"> + <all> + <element name="id" type="xsd:int"/> + <element name="name" type="string"/> + </all> + </complexType> + + + </schema> + </types> + + <message name="msg_user_request"> + <part name="user" type="tns:User"/> + </message> + + <message name="msg_user_response"> + <part name="return" type="xsd:int"/> + </message> + + <portType name="webServiceExamplePortType"> + <operation name="addUser"> + <input message="tns:msg_user_request"/> + <output message="tns:msg_user_response"/> + </operation> + </portType> + + <binding name="webServiceExampleServicePortBinding" type="tns:webServiceExamplePortType"> + <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> + + <operation name="addUser"> + <soap:operation soapAction=""/> + <input> + <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://www.rubypeople.org/xmlns/webServiceExample/"/> + </input> + <output> + <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://www.rubypeople.org/xmlns/webServiceExample/"/> + </output> + </operation> + </binding> + + <service name="webServiceExampleService"> + <port name="webServiceExamplePort" binding="tns:webServiceExampleServicePortBinding"> + <soap:address location="http://localhost/webServiceExampleService"/> + </port> + </service> + +</definitions> \ No newline at end of file Added: trunk/org.rubypeople.rdt/cheatsheets/WebServices.xml =================================================================== --- trunk/org.rubypeople.rdt/cheatsheets/WebServices.xml (rev 0) +++ trunk/org.rubypeople.rdt/cheatsheets/WebServices.xml 2006-08-08 07:00:22 UTC (rev 1553) @@ -0,0 +1,192 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<cheatsheet title="Using RDT"> + <intro href="/org.eclipse.platform.doc.user/reference/ref-cheatsheets.htm"> + <description> This cheat sheet is an introduction to the Ruby Development Tools + (RDT) and uses a real world scenario to show how the RDT can be leveraged in your + work with ruby. As a prerequiste you need to get and install soap4r 1.5.5: extract + soap4r-1_5_5.tar.gz and run install.rb. Although soap4r is included since + ruby 1.8.1, you will need it because of the wsdl2ruby.rb file, which is not part of + ruby 1.8.1 or later. Extract so To start working on this cheat sheet, click the + "Click to Begin" button below. </description> + </intro> + <item href="/org.rubypeople.rdt.doc.user/html/ch02.html#importantSettings" + title="Interpreter setup"> + <description> Make sure you have registered at least one ruby interpreter with RDT. + Click on the help button if you don't know how to do that. </description> + </item> + <item title="Switch to Ruby Perspective"> + <!-- Fix missing class + <action pluginId="org.rubypeople.rdt.debug.ui" + class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenRubyPerspectiveAction"/> +--> + <description> Use the "Click to Perform" button to open the ruby + perspective. This can also be done manually by choosing "Window->Open + Perspective->Other..." from the main menu and selecting + "Ruby" from the dialog which opens. </description> + </item> + <item title="Create Ruby project on soap4r"> + <action pluginId="org.rubypeople.rdt" param1="soap4r" + class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenNewRubyProjectWizardAction"/> + <description> In order to run wsdl2ruby.rb from the soap4r package, you create a ruby + project called soap4r on top of the soap4r installation directory at first. + After clicking the "Click to Perform" button below, the "New + Ruby Project" wizard will open. The project name "soap4r" is + already entered. Disable the "Use Default" checkbox in the project + content area and use the browse button to select the directory to which you have + unzipped the soap4r tar ball. </description> + </item> + <item title="Create MyWebservice project"> + <action pluginId="org.rubypeople.rdt" param1="MyWebservice" + class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenNewRubyProjectWizardAction"/> + <description> In this step you create a new project within your workspace, which will + be used to hold the wsdl file and the generated code from this file. The project is + called + "MyWebservice" The "Click to Perform" button opens the + "New Ruby Project" wizard again. This time you can leave the + "Use Default" checkbox enabled. This will create the project as a + subdirectory into your workspace location. </description> + </item> + <item title="Add wsdl file to MyWebservice"> + <action pluginId="org.rubypeople.rdt" param1="MyWebservice" + class="org.rubypeople.rdt.internal.cheatsheets.webservice.CreateWsdlFileAction"/> + <description> Add a new file called sample.wsdl to the MyWebservice project. In the + dialog which "Click to Perform" brings up you only have to enter the + file name + "sample.wsdl". The MyWebservice project is already selected as the + container of this new resource. </description> + </item> + <item title="Add content to sample.wsdl"> + <action pluginId="org.rubypeople.rdt" + param1="/cheatsheets/Sample.wsdl" param2="/MyWebservice/sample.wsdl" + class="org.rubypeople.rdt.internal.cheatsheets.webservice.CopyContentAction"/> + <description> In the last step you have created the file "sample.wsdl". + But why is it not there? It is, but is filtered out: In the Ruby Resources views menu + deselect + "Show Ruby Files only" (this can be found by clicking the down arrow in + the Ruby Resources view MenuBar, in the menu of options). The "Click to + Perform" buttons copies sample content to the wsdl file. The content is + copied from the Sample.wsdl file which ships with RDT. </description> + </item> + <item title="Run wsdl2ruby.rb" + href="/org.rubypeople.rdt.doc.user/html/ch03s10.html"> + <description> Open the soap4r project. Open the bin directory and right-click the + "wsdl2ruby.rb" file to open the context menu. Choose + "Run->Run Ruby Application". Check the console for the output of the + process. There you find the required command line options. </description> + </item> + <item title="Modify the run configuration for server generation"> + <action pluginId="org.rubypeople.rdt" + class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenRunConfigurationAction"/> + <description> "Click to Perform" opens the run configuration dialog, + which is also available as Run As->Run... from the main menu. The running of + wsdl2ruby.rb in the last step has created a run-configuration named + "wsdl2ruby.rb". Rename it to + "wsdl-gen-server" Now open the Arguments tab and add "--wsdl + sample.wsdl --type server" to the program arguments. Then you change the + working directory to the directory of the MyWebservice project. Therefore you + must know where your workspace resides on the local disk: If you have forgotten + which workspace you are using or where it resides, you can choose + "File->Switch Workspace". </description> + </item> + <item title="Check generated server files"> + <description> The execution of the last step should have generated three files. + Because they have been created on the file system from the outside, you must + execute + "Refresh" from the context menu of the MyWebservice project. Then + you should see the new files: webServiceExample.rb, + webServiceExampleServant.rb and webServiceExampleService.rb. If they are + not there or are empty, check the console for error messages. If there is a stack + trace in the console, you can double-click to open the specified file locations. + </description> + </item> + <item title="Create Run-Configuration for client generation"> + <action pluginId="org.rubypeople.rdt" + class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenRunConfigurationAction"/> + <description> "Click to Perform" opens the run configuration dialog + again. Perform "Duplicate" from the context menu of the + wsdl-gen-server run configuration. A duplicate "wsdl-gen-server + (1)" will be generated. Rename it to "wsdl-gen-client", + change the argument "--type server" to + "--type client" and click "Run". </description> + </item> + <item title="Check generated client files"> + <description> Click "Refresh" on the MyWebservice project to display + the two newly generated files: webServiceExampleDriver.rb and + webServiceExampleServiceClient.rb. </description> + </item> + <item href="/org.rubypeople.rdt.doc.user/html/ch03s12.html#DebugKnownLimitations" + title="Check ruby version"> + <description> Please note there are limitations in the ruby versions which are + suitable for debugging. On Linux there is a restriction to ruby 1.6, on windows + ruby 1.8.2 works fine but 1.8.1 does not. See Help->Help Contents for more + details. If your version of ruby does not meet these requirements, use + "Run->Run Ruby Application" instead of + "Debug->Debug Ruby Application" in the next step for starting the + server. </description> + </item> + <item title="Debug server"> + <description> Open the editor for webServiceExampleServant.rb (by + double-clicking it in the "Ruby Resources" view) and set a + breakpoint in the line which raises the NotImplementedError. A breakpoint can + be set and removed either by double-clicking on the vertical bar at the left side + of the editor or by using the context menu on that bar. Start the debugger with + "Debug->Debug Ruby Application" from the context menu of + webServiceExampleService.rb. </description> + </item> + <item title="Modify the client"> + <description> If you look at the client code in webServiceExampleServiceClient.rb + you will notice that the user variable is set to nil. Assign a new user object + instead, e.b. with User.new('myID', 'myName'). Save the editor with the icon + from the toolbar or ctrl+s.</description> + </item> + <item title="Run the client"> + <action pluginId="org.rubypeople.rdt" + class="org.rubypeople.rdt.internal.cheatsheets.webservice.OpenRunConfigurationAction"/> + <description> Use the "Click to perform" button or select + "Run->Run..." from the main menu to open the run configuration + dialog. Select "Ruby Application" and click "New". + Rename the newly created run configuration to "run-client". Select + webServiceExampleServiceClient.rb as the file to be run with the + "Browse" button. Go the Arguments Tab and add + "http://localhost:10080/" as program argument. Click Run. + </description> + </item> + <item href="/org.rubypeople.rdt.doc.user/html/ch03s12.html#startDebugSession" + title="Breakpoint hit"> + <description> After a while the clients request will trigger the breakpoint in the + server process. If you haven't debugged before, you will be asked whether to + switch to the debug perspective or not. You should confirm the switch. In the + debug perspective you can see where the server process halted and examine the + program state. E.g. in the Variables view you can see the attribute values of + the user object. </description> + </item> + <item title="Edit the server code"> + <description>If you have a look at + the wsdl file, you'll discover that the addUser method expects an integer as return + value. Therefore you can replace the raise command with "return 0" and + save the new code. When you save the code the ruby interpreter, which runs the + server, also reloads the code. Now resume the server with the resume button, + "Run->Resume" or F8.</description> + </item> + <item href="/org.rubypeople.rdt.doc.user/html/ch03s12.html#codeReload" + title="Check the output of the client"> + <description> In the Debug view you can see that the client has terminated. In order to + see its output, select the terminated process. After that the Console shows the + output of the client, which is a stack trace showing the NotImplementedError: + although the interpreter has reloaded the new content of + webServiceExampleServant.rb it finished the stack with the old code. + Therefore we must run the client again.</description> + </item> + <item title="Run the client again"> + <description> Now run the client again with "Run->Run + History->run-client", wait for the breakpoint and resume again. The + console displays 0, the result of the addUser method, instead of the stack trace. + </description> + </item> + <item title="End"> + <description> This tutorial has given you a short overview of RDT. Please mind that + RDT is an an open source project and needs the feedback and contributions + from the users. Please visit http://www.rubypeople.org/ if you want to help to + further improve RDT.</description> + </item> +</cheatsheet> \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |