Browse Source

Fixes #887

- Only use navigation nodes to find the node at point
- adds a test for cascades
Nicolas Petton 10 years ago
parent
commit
a66bb5f425
6 changed files with 45 additions and 29 deletions
  1. 6 3
      src/Compiler-AST.js
  2. 5 2
      src/Compiler-AST.st
  3. 20 9
      src/Compiler-Tests.js
  4. 8 3
      src/Compiler-Tests.st
  5. 4 8
      src/Helios-Workspace.js
  6. 2 4
      src/Helios-Workspace.st

+ 6 - 3
src/Compiler-AST.js

@@ -78,7 +78,10 @@ var $early={};
 try {
 children=_st(self._allNodes())._select_((function(each){
 return smalltalk.withContext(function($ctx2) {
+return _st(_st(each)._isNavigationNode())._and_((function(){
+return smalltalk.withContext(function($ctx3) {
 return _st(each)._inPosition_(aPoint);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)})}));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 _st(children)._ifEmpty_((function(){
 throw $early=[nil];
@@ -90,14 +93,14 @@ $ctx2.sendIdx["positionStart"]=1;
 $2=_st($3)._dist_(aPoint);
 $ctx2.sendIdx["dist:"]=1;
 return _st($2).__lt_eq(_st(_st(b)._positionStart())._dist_(aPoint));
-}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1,3)})})))._first();
+}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1,4)})})))._first();
 return $1;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
 }, function($ctx1) {$ctx1.fill(self,"atPosition:",{aPoint:aPoint,children:children},globals.Node)})},
 args: ["aPoint"],
-source: "atPosition: aPoint\x0a\x09\x22Answer the node in the receiver's tree at aPoint\x22\x0a\x09\x0a\x09| children |\x0a\x09\x0a\x09children := self allNodes select: [ :each | \x0a\x09\x09each inPosition: aPoint ].\x0a\x09\x0a\x09children ifEmpty: [ ^ nil ].\x0a\x09\x0a\x09^ (children asArray sort: [ :a :b | \x0a\x09\x09(a positionStart dist: aPoint) <= \x0a\x09\x09(b positionStart dist: aPoint) ]) first",
-messageSends: ["select:", "allNodes", "inPosition:", "ifEmpty:", "first", "sort:", "asArray", "<=", "dist:", "positionStart"],
+source: "atPosition: aPoint\x0a\x09\x22Answer the navigation node in the receiver's tree at aPoint \x0a\x09or nil if no navigation node was found.\x0a\x09\x0a\x09See `node >> isNaviationNode`\x22\x0a\x09\x0a\x09| children |\x0a\x09\x0a\x09children := self allNodes select: [ :each | \x0a\x09\x09each isNavigationNode and: [ each inPosition: aPoint ] ].\x0a\x09\x0a\x09children ifEmpty: [ ^ nil ].\x0a\x09\x0a\x09^ (children asArray sort: [ :a :b | \x0a\x09\x09(a positionStart dist: aPoint) <= \x0a\x09\x09(b positionStart dist: aPoint) ]) first",
+messageSends: ["select:", "allNodes", "and:", "isNavigationNode", "inPosition:", "ifEmpty:", "first", "sort:", "asArray", "<=", "dist:", "positionStart"],
 referencedClasses: []
 }),
 globals.Node);

+ 5 - 2
src/Compiler-AST.st

@@ -27,12 +27,15 @@ allNodes
 !
 
 atPosition: aPoint
-	"Answer the node in the receiver's tree at aPoint"
+	"Answer the navigation node in the receiver's tree at aPoint 
+	or nil if no navigation node was found.
+	
+	See `node >> isNaviationNode`"
 	
 	| children |
 	
 	children := self allNodes select: [ :each | 
-		each inPosition: aPoint ].
+		each isNavigationNode and: [ each inPosition: aPoint ] ].
 	
 	children ifEmpty: [ ^ nil ].
 	

+ 20 - 9
src/Compiler-Tests.js

@@ -272,29 +272,40 @@ globals.ASTPCNodeVisitorTest);
 smalltalk.addClass('ASTPositionTest', globals.ASTParsingTest, [], 'Compiler-Tests');
 smalltalk.addMethod(
 smalltalk.method({
-selector: "testAtPosition",
+selector: "testNodeAtPosition",
 protocol: 'tests',
 fn: function (){
 var self=this;
 var node;
 return smalltalk.withContext(function($ctx1) { 
-var $3,$4,$2,$1;
+var $3,$4,$2,$1,$7,$8,$6,$5;
 node=self._parse_("yourself\x0a\x09^ self");
 $ctx1.sendIdx["parse:"]=1;
 $3=node;
 $4=(2).__at((4));
 $ctx1.sendIdx["@"]=1;
-$2=_st($3)._atPosition_($4);
-$ctx1.sendIdx["atPosition:"]=1;
+$2=_st($3)._nodeAtPosition_($4);
+$ctx1.sendIdx["nodeAtPosition:"]=1;
 $1=_st($2)._source();
 self._assert_equals_($1,"self");
 $ctx1.sendIdx["assert:equals:"]=1;
 node=self._parse_("foo\x0a\x09true ifTrue: [ 1 ]");
-self._assert_equals_(_st(_st(node)._atPosition_((2).__at((7))))._selector(),"ifTrue:");
-return self}, function($ctx1) {$ctx1.fill(self,"testAtPosition",{node:node},globals.ASTPositionTest)})},
-args: [],
-source: "testAtPosition\x0a\x09| node |\x0a\x09\x0a\x09node := self parse: 'yourself\x0a\x09^ self'.\x0a\x09\x0a\x09self assert: (node atPosition: 2@4) source equals: 'self'.\x0a\x09\x0a\x09node := self parse: 'foo\x0a\x09true ifTrue: [ 1 ]'.\x0a\x09\x0a\x09self assert: (node atPosition: 2@7) selector equals: 'ifTrue:'",
-messageSends: ["parse:", "assert:equals:", "source", "atPosition:", "@", "selector"],
+$ctx1.sendIdx["parse:"]=2;
+$7=node;
+$8=(2).__at((7));
+$ctx1.sendIdx["@"]=2;
+$6=_st($7)._nodeAtPosition_($8);
+$ctx1.sendIdx["nodeAtPosition:"]=2;
+$5=_st($6)._selector();
+$ctx1.sendIdx["selector"]=1;
+self._assert_equals_($5,"ifTrue:");
+$ctx1.sendIdx["assert:equals:"]=2;
+node=self._parse_("foo\x0a\x09self foo; bar; baz");
+self._assert_equals_(_st(_st(node)._nodeAtPosition_((2).__at((8))))._selector(),"foo");
+return self}, function($ctx1) {$ctx1.fill(self,"testNodeAtPosition",{node:node},globals.ASTPositionTest)})},
+args: [],
+source: "testNodeAtPosition\x0a\x09| node |\x0a\x09\x0a\x09node := self parse: 'yourself\x0a\x09^ self'.\x0a\x09\x0a\x09self assert: (node nodeAtPosition: 2@4) source equals: 'self'.\x0a\x09\x0a\x09node := self parse: 'foo\x0a\x09true ifTrue: [ 1 ]'.\x0a\x09\x0a\x09self assert: (node nodeAtPosition: 2@7) selector equals: 'ifTrue:'.\x0a\x09\x0a\x09node := self parse: 'foo\x0a\x09self foo; bar; baz'.\x0a\x09\x0a\x09self assert: (node nodeAtPosition: 2@8) selector equals: 'foo'",
+messageSends: ["parse:", "assert:equals:", "source", "nodeAtPosition:", "@", "selector"],
 referencedClasses: []
 }),
 globals.ASTPositionTest);

+ 8 - 3
src/Compiler-Tests.st

@@ -108,18 +108,23 @@ ASTParsingTest subclass: #ASTPositionTest
 
 !ASTPositionTest methodsFor: 'tests'!
 
-testAtPosition
+testNodeAtPosition
 	| node |
 	
 	node := self parse: 'yourself
 	^ self'.
 	
-	self assert: (node atPosition: 2@4) source equals: 'self'.
+	self assert: (node nodeAtPosition: 2@4) source equals: 'self'.
 	
 	node := self parse: 'foo
 	true ifTrue: [ 1 ]'.
 	
-	self assert: (node atPosition: 2@7) selector equals: 'ifTrue:'
+	self assert: (node nodeAtPosition: 2@7) selector equals: 'ifTrue:'.
+	
+	node := self parse: 'foo
+	self foo; bar; baz'.
+	
+	self assert: (node nodeAtPosition: 2@8) selector equals: 'foo'
 ! !
 
 ASTParsingTest subclass: #CodeGeneratorTest

+ 4 - 8
src/Helios-Workspace.js

@@ -659,7 +659,7 @@ var ast,node;
 function $Smalltalk(){return globals.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 function $Error(){return globals.Error||(typeof Error=="undefined"?nil:Error)}
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
+var $1;
 var $early={};
 try {
 ast=_st((function(){
@@ -668,24 +668,20 @@ return _st($Smalltalk())._parse_(_st(self._editor())._getValue());
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._on_do_($Error(),(function(error){
 throw $early=[self];
 }));
-node=_st(ast)._atPosition_(aPosition);
-_st(console)._log_(node);
+node=_st(ast)._nodeAtPosition_(aPosition);
 $1=node;
 if(($receiver = $1) == nil || $receiver == null){
 return self;
 } else {
 $1;
 };
-$2=_st(node)._isNavigationNode();
-if(smalltalk.assert($2)){
 self._navigateTo_(_st(node)._navigationLink());
-};
 return self}
 catch(e) {if(e===$early)return e[0]; throw e}
 }, function($ctx1) {$ctx1.fill(self,"onCtrlClickAt:",{aPosition:aPosition,ast:ast,node:node},globals.HLCodeWidget)})},
 args: ["aPosition"],
-source: "onCtrlClickAt: aPosition\x0a\x09| ast node |\x0a\x09\x0a\x09ast := [ Smalltalk parse: self editor getValue ] \x0a\x09\x09on: Error \x0a\x09\x09do: [ :error | ^ self ].\x0a\x09\x0a\x09node := (ast atPosition: aPosition).\x0a\x09console log: node.\x0a\x09node ifNil: [ ^ self ].\x0a\x09\x0a\x09node isNavigationNode ifTrue: [ \x0a\x09\x09self navigateTo: node navigationLink ]",
-messageSends: ["on:do:", "parse:", "getValue", "editor", "atPosition:", "log:", "ifNil:", "ifTrue:", "isNavigationNode", "navigateTo:", "navigationLink"],
+source: "onCtrlClickAt: aPosition\x0a\x09| ast node |\x0a\x09\x0a\x09ast := [ Smalltalk parse: self editor getValue ] \x0a\x09\x09on: Error \x0a\x09\x09do: [ :error | ^ self ].\x0a\x09\x0a\x09node := (ast nodeAtPosition: aPosition).\x0a\x09node ifNil: [ ^ self ].\x0a\x09\x0a\x09self navigateTo: node navigationLink",
+messageSends: ["on:do:", "parse:", "getValue", "editor", "nodeAtPosition:", "ifNil:", "navigateTo:", "navigationLink"],
 referencedClasses: ["Smalltalk", "Error"]
 }),
 globals.HLCodeWidget);

+ 2 - 4
src/Helios-Workspace.st

@@ -273,12 +273,10 @@ onCtrlClickAt: aPosition
 		on: Error 
 		do: [ :error | ^ self ].
 	
-	node := (ast atPosition: aPosition).
-	console log: node.
+	node := (ast nodeAtPosition: aPosition).
 	node ifNil: [ ^ self ].
 	
-	node isNavigationNode ifTrue: [ 
-		self navigateTo: node navigationLink ]
+	self navigateTo: node navigationLink
 !
 
 onInspectIt