|
From: <caw...@us...> - 2007-05-16 20:33:51
|
Revision: 2492
http://svn.sourceforge.net/rubyeclipse/?rev=2492&view=rev
Author: cawilliams
Date: 2007-05-16 13:33:50 -0700 (Wed, 16 May 2007)
Log Message:
-----------
fix one case where we could fall into infinite loop doing type inferrencing
Modified Paths:
--------------
trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DefaultTypeInferrer.java
trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/DataFlowTypeInferrerTest.java
trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTest.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTestCase.java
Modified: trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DefaultTypeInferrer.java
===================================================================
--- trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DefaultTypeInferrer.java 2007-05-16 18:44:05 UTC (rev 2491)
+++ trunk/org.rubypeople.rdt.core/src/org/rubypeople/rdt/internal/ti/DefaultTypeInferrer.java 2007-05-16 20:33:50 UTC (rev 2492)
@@ -1,9 +1,11 @@
package org.rubypeople.rdt.internal.ti;
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;
@@ -27,6 +29,7 @@
import org.rubypeople.rdt.internal.core.util.ASTUtil;
import org.rubypeople.rdt.internal.ti.data.LiteralNodeTypeNames;
import org.rubypeople.rdt.internal.ti.data.TypicalMethodReturnNames;
+import org.rubypeople.rdt.internal.ti.util.ClosestSpanningNodeLocator;
import org.rubypeople.rdt.internal.ti.util.FirstPrecursorNodeLocator;
import org.rubypeople.rdt.internal.ti.util.INodeAcceptor;
import org.rubypeople.rdt.internal.ti.util.OffsetNodeLocator;
@@ -36,6 +39,7 @@
private static final String CONSTRUCTOR_INVOKE_NAME = "new";
private RootNode rootNode;
+ private Set<Node> dontVisitNodes;
/**
* Infers type inside the source at given offset.
@@ -43,6 +47,7 @@
* @return List of ITypeGuess objects.
*/
public List<ITypeGuess> infer(String source, int offset) {
+ dontVisitNodes = new HashSet<Node>();
try {
RubyParser parser = new RubyParser();
rootNode = (RootNode) parser.parse(source);
@@ -154,13 +159,22 @@
// Or scopingNode. Still not sure whether IterNodes count or not...
// silly block-local-var ambiguity ;)
- // CHRIS - Changed to just grab all assignments to this instance variable, not just first assignment
+ // try and grab the assignment node if this reference is in an assignment, so we can "blacklist" it from being grabbed in next step where we grab all assignments to the instance variable
+ final Node assignmentNode = ClosestSpanningNodeLocator.Instance().findClosestSpanner(rootNode, instVarNode.getPosition().getStartOffset(), new INodeAcceptor() {
+
+ public boolean doesAccept(Node node) {
+ return node instanceof InstAsgnNode;
+ }
+
+ });
+ if (assignmentNode != null) dontVisitNodes.add(assignmentNode);
List<Node> assignments = new ArrayList<Node>();
assignments.addAll(ScopedNodeLocator.Instance().findNodesInScope(rootNode, new INodeAcceptor() {
public boolean doesAccept(Node node) {
- return (node instanceof InstAsgnNode) && (((InstAsgnNode)node).getName().equals(instVarNode.getName()));
+ return (node instanceof InstAsgnNode) && (((InstAsgnNode)node).getName().equals(instVarNode.getName())) && !dontVisitNodes.contains(node);
}
}));
+
for (Node assignNode : assignments) {
tryAsgnNode(assignNode, guesses);
}
Modified: trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/DataFlowTypeInferrerTest.java
===================================================================
--- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/DataFlowTypeInferrerTest.java 2007-05-16 18:44:05 UTC (rev 2491)
+++ trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/DataFlowTypeInferrerTest.java 2007-05-16 20:33:50 UTC (rev 2492)
@@ -1,49 +1,12 @@
package org.rubypeople.rdt.internal.ti;
-import java.util.List;
-import junit.framework.TestCase;
-
/**
* @author Jason
*
*/
-public class DataFlowTypeInferrerTest extends TestCase {
+public class DataFlowTypeInferrerTest extends TypeInferrerTestCase {
- private ITypeInferrer inferrer;
- public void setUp() {
- inferrer = createTypeInferrer();
- }
-
- /**
- * Shortcut for testing that a particular type is the only one inferred,
- * and is inferred with 100% confidence
- * @param guesses
- * @param type
- */
- private void assertInfersTypeWithoutDoubt(List<ITypeGuess> guesses, String type) {
- assertEquals(1, guesses.size());
- ITypeGuess guess = guesses.get(0);
- assertEquals(type, guess.getType());
- assertEquals(100, guess.getConfidence());
- }
-
- /**
- * Shortcut for testing that two types are inferred, each with 50% confidence
- * @param guesses
- * @param type
- * @param type2
- */
-
- private void assertInfersTypeFiftyFifty( List<ITypeGuess> guesses, String type1, String type2 ) {
- assertEquals(2, guesses.size());
- assertEquals( guesses.get(0).getType(), type1 );
- assertEquals( guesses.get(1).getType(), type2 );
- assertEquals( guesses.get(0).getConfidence(), 50 );
- assertEquals( guesses.get(1).getConfidence(), 50 );
- }
-
-
public void testFixnum() throws Exception {
assertInfersTypeWithoutDoubt(inferrer.infer("5", 0), "Fixnum");
}
Modified: trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTest.java
===================================================================
--- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTest.java 2007-05-16 18:44:05 UTC (rev 2491)
+++ trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTest.java 2007-05-16 20:33:50 UTC (rev 2492)
@@ -1,37 +1,16 @@
package org.rubypeople.rdt.internal.ti;
-import java.util.List;
-import junit.framework.TestCase;
-
/**
* @author Jason
*
*/
-/**
- * @author Jason
- *
- */
-public class TypeInferrerTest extends TestCase {
+public class TypeInferrerTest extends TypeInferrerTestCase {
- private ITypeInferrer inferrer;
- public void setUp() {
- inferrer = createTypeInferrer();
+ protected ITypeInferrer createTypeInferrer() {
+ return new DefaultTypeInferrer();
}
- /**
- * Shortcut for testing that a particular type is the only one inferred,
- * and is inferred with 100% confidence
- * @param guesses
- * @param type
- */
- private void assertInfersTypeWithoutDoubt(List<ITypeGuess> guesses, String type) {
- assertEquals(1, guesses.size());
- ITypeGuess guess = guesses.get(0);
- assertEquals(type, guess.getType());
- assertEquals(100, guess.getConfidence());
- }
-
public void testFixnum() throws Exception {
assertInfersTypeWithoutDoubt(inferrer.infer("5", 0), "Fixnum");
}
@@ -77,52 +56,9 @@
assertInfersTypeWithoutDoubt(inferrer.infer("x=Regexp.new;x", 13), "Regexp");
}
-
-
-
-
-
-//todo: at a later date, make sure this is handled:
-/*
- * def foo
- * x = 5
- * puts x
- * end
- *
- * def bar(x)
- * do_stuff_with(x)
- * end
- *
- * param to do_stuff_with should not be affected by the assignment to x in foo.
- */
-// public void testLocalVariableAssignmentWithSameNameAsInAnotherScope() throws Exception {
-// System.out.println("booga");
-// // Note that the N::x may be preceded by another operations that affect its type, such as
-// // x.to_s!. Or it may be a parameter. The search for a preceding LocalAsgnNode should
-// // respect scopes and not override these, say, with the assignment to local x in M.
-// String script = "module M;x=5;x;end;module N;x=6;x;end";
-//
-// // Test first scope
-// List<ITypeGuess> guesses = inferrer.infer(script, 13);
-// assertEquals(1, guesses.size());
-// ITypeGuess guess = guesses.get(0);
-// assertEquals("Fixnum", guess.getType());
-//
-// System.out.println("wooga");
-// // Test second scope
-// guesses = inferrer.infer(script, 32);
-// assertEquals(0, guesses.size());
-//// guess = guesses.get(0);
-//// assertEquals("String", guess.getType());
-// }
-
- /**
- * Override this method in subclasses so that we can test any
- * implementation of ITypeInferrer the same way.
- * @return an implementation of ITypeInferrer
- */
- protected ITypeInferrer createTypeInferrer() {
- return new DefaultTypeInferrer();
+ public void testInfiniteLoop() throws Exception {
+ inferrer.infer("@inst = 1;@inst = @inst.blah", 15);
+ assertTrue(true);
}
}
Added: trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTestCase.java
===================================================================
--- trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTestCase.java (rev 0)
+++ trunk/org.rubypeople.rdt.core.tests/src/org/rubypeople/rdt/internal/ti/TypeInferrerTestCase.java 2007-05-16 20:33:50 UTC (rev 2492)
@@ -0,0 +1,54 @@
+package org.rubypeople.rdt.internal.ti;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public abstract class TypeInferrerTestCase extends TestCase {
+
+ protected ITypeInferrer inferrer;
+
+ public TypeInferrerTestCase() {
+ super();
+ }
+
+ public void setUp() {
+ inferrer = createTypeInferrer();
+ }
+
+ /**
+ * Shortcut for testing that a particular type is the only one inferred,
+ * and is inferred with 100% confidence
+ * @param guesses
+ * @param type
+ */
+ protected void assertInfersTypeWithoutDoubt(List<ITypeGuess> guesses, String type) {
+ assertEquals(1, guesses.size());
+ ITypeGuess guess = guesses.get(0);
+ assertEquals(type, guess.getType());
+ assertEquals(100, guess.getConfidence());
+ }
+
+ /**
+ * Shortcut for testing that two types are inferred, each with 50% confidence
+ * @param guesses
+ * @param type
+ * @param type2
+ */
+
+ protected void assertInfersTypeFiftyFifty( List<ITypeGuess> guesses, String type1, String type2 ) {
+ assertEquals(2, guesses.size());
+ assertEquals( guesses.get(0).getType(), type1 );
+ assertEquals( guesses.get(1).getType(), type2 );
+ assertEquals( guesses.get(0).getConfidence(), 50 );
+ assertEquals( guesses.get(1).getConfidence(), 50 );
+ }
+
+ /**
+ * Override this method in subclasses so that we can test any
+ * implementation of ITypeInferrer the same way.
+ * @return an implementation of ITypeInferrer
+ */
+ protected abstract ITypeInferrer createTypeInferrer();
+
+}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|