#UI_ENHANCEMENT expecco_ALM_1_9_7
authorClaus Gittinger <cg@exept.de>
Sun, 17 Jan 2016 22:26:26 +0100
changeset 4934 9b2c18bd9e9c
parent 4933 9801e2eea4c7
child 4935 127cb7e78672
child 4936 486789a85cea
#UI_ENHANCEMENT class: DoWhatIMeanSupport comment/format in: #findNodeForInterval:in:allowErrors:mustBeMethod:mustBeExpression: changed: #codeCompletionForMessage:into: selectors already sent in the parsed method are a very good heuristic hint. Present them at top of the list.
DoWhatIMeanSupport.st
--- a/DoWhatIMeanSupport.st	Sun Jan 17 11:48:52 2016 +0100
+++ b/DoWhatIMeanSupport.st	Sun Jan 17 22:26:26 2016 +0100
@@ -2290,14 +2290,20 @@
     allBest := (bestSelectors3 ? #()) , allBest.
     allBest isEmptyOrNil ifTrue:[ ^ self ].
 
+    "/ the one's which are a prefix are moved towards the top of the list
+    allBest := split value:allBest value:[:sel | sel notNil and:[sel startsWith:selector]].
+
+    rememberedNodes notNil ifTrue:[
+        selectorsSentInCode := 
+            (rememberedNodes
+                select:[:node | node isMessage]
+                thenCollect:[:node | node selector]) asSet.
+        selectorsSentInCode remove:selector ifAbsent:[].
+    ].    
     selectorsSentInCode notNil ifTrue:[
         "/ the one's already sent in the code are moved to the top of the list.
         allBest := split value:allBest value:[:sel | selectorsSentInCode includes:sel].
     ].
-
-    "/ the one's which are a prefix are moved towards the top of the list
-    allBest := split value:allBest value:[:sel | sel notNil and:[sel startsWith:selector]].
-
 "/false ifTrue:[
 "/    srchClass notNil ifTrue:[
 "/        implClass := srchClass whichClassIncludesSelector:best.
@@ -3366,19 +3372,19 @@
 
     interval isEmpty ifTrue: [^ nil].
     languageOrNil notNil ifTrue:[
-	parserClass := languageOrNil parserClass.
+        parserClass := languageOrNil parserClass.
     ] ifFalse:[
-	classOrNil notNil ifTrue:[
-	    parserClass := classOrNil programmingLanguage parserClass.
-	]
+        classOrNil notNil ifTrue:[
+            parserClass := classOrNil programmingLanguage parserClass.
+        ]
     ].
     parserClass notNil ifTrue:[
-	"/ hack
-	parserClass == Parser ifTrue: [
-	    parserClass := RBParser.
-	].
+        "/ hack
+        parserClass == Parser ifTrue: [
+            parserClass := RBParser.
+        ].
     ] ifFalse:[
-	parserClass := RBParser.
+        parserClass := RBParser.
     ].
     parserClass isNil ifTrue: [^ nil].
 
@@ -3387,136 +3393,136 @@
 
     "/ LastSource := nil.
     source = LastSource ifTrue:[
-	tree := LastParseTree.
-	tokens := LastScanTokens.
+        tree := LastParseTree.
+        tokens := LastScanTokens.
     ] ifFalse:[
-	intersectingNodes := OrderedCollection new.
-	currentScopeNodes := IdentitySet new.
-
-	onErrorBlock :=
-	    [:str :err :nodesSoFar |
-		|nodes|
-
-		allowErrors ifTrue:[
-		    rememberedScopeNodes := currentScopeNodes.
-		    firstIntersectingNode notNil ifTrue:[
-			^ firstIntersectingNode
-		    ].
-		    nodesSoFar notNil ifTrue:[
-			nodes := nodesSoFar asOrderedCollection
-				    collect:[:nd | nd whichNodeIntersects:interval]
-				    thenSelect:[:nd | nd notNil ].
-			nodes size == 1 ifTrue:[
-			    ^ nodes first
-			].
-		    ]
-		].
-		nil
-	    ].
-
-	self debuggingCodeFor:#cg is:[
-	    Transcript show:'looking for: '; showCR:interval.
-	].
-
-	nodeGenerationHook :=
-	    [:node |
-		rememberedNodes add:node.
-
-		"/ would like to return here as soon as the node has been created by the parser;
-		"/ however, at that time, its parent(chain) is not yet created and so we might not know
-		"/ what the semantic interpretation (especially: scope of variable) will be.
-		"/ therefore, we parse all, and return the found node at the end.
-		(node isMethod or:[node isBlock or:[node isSequence]]) ifTrue:[
-		    currentScopeNodes add:node.
-		] ifFalse:[
-		    self debuggingCodeFor:#cg is:[
-			Transcript show:node; show:' '; show:node start; show:'->'; showCR:node stop.
-		    ].
-
-		    (node intersectsInterval:interval) ifTrue:[
-			self debuggingCodeFor:#cg is:[
-			    Transcript showCR:'yes'.
-			].
-			intersectingNodes add:node.
-			firstIntersectingNode isNil ifTrue:[
-			    firstIntersectingNode := lastIntersectingNode := smallestIntersectingNode := node
-			] ifFalse:[
-			    |lenNode lenSmallest|
-
-			    lenNode := (node stop - node start).
-			    lenSmallest := (smallestIntersectingNode stop - smallestIntersectingNode start).
-			    lenNode < lenSmallest ifTrue:[
-				smallestIntersectingNode := node.
-			    ].
-			    node start > lastIntersectingNode start ifTrue:[
-				lastIntersectingNode := node.
-			    ].
-			].
-		    ].
-		].
-	    ].
-
-	"/ one of the big problems when using the RBParser here is
-	"/ that it behaves badly when a syntax error is encountered;
-	"/ for example, a node's parent is usually set AFTER the children are
-	"/ completely parsed (for example, a blockNode gets the parent-method only
-	"/ after parsing). Thus, when an error is encountered, we cannot walk
-	"/ the parent chain, and therefore will not see the outer locals/args of
-	"/ an inner scope (allVariablesOnScope returns only a partial set).
-	"/ A walkaround is to remember Method/Block nodes as created in the above node generation.
-	"/ The disadvantage of it is that we do not have correct scope information, until the nodes
-	"/ parent gets set eventually, this we might consider locals from sibling blocks.
-	"/ See rememberedScopeNodes handling above.
-	"/ Those other nodes are only remembered for failed parses;
-	"/ if the parse is ok, rememberedScopeNodes will be nil.
-
-	mustBeExpression ifFalse:[
-	    tree := parserClass
-			parseMethod: source
-			setup:[:p |
-			    parser := p.
-			    p rememberNodes:true.
-			    p rememberTokens:true.
-			    p nodeGenerationCallback:nodeGenerationHook
-			]
-			onError: onErrorBlock.
-	    parser notNil ifTrue:[ tokens := parser rememberedTokens ].
-	].
-
-	mustBeMethod ifTrue:[
-	    "/ only cache parsed methods
-	    tree notNil ifTrue:[
-		LastSource := source.
-		LastParseTree := tree.
-		LastScanTokens := tokens.
-	    ].
-	] ifFalse:[
-	    (tree isNil or:[firstIntersectingNode isNil]) ifTrue:[
-		"/ try as an expression
-		tree := parserClass
-			    parseExpression: source
-			    setup:[:p |
-				parser := p.
-				p rememberNodes:true.
-				p rememberTokens:true.
-				p nodeGenerationCallback:nodeGenerationHook
-			    ]
-			    onError: onErrorBlock.
-		parser notNil ifTrue:[ tokens := parser rememberedTokens ].
-	    ].
-	].
-	lastIntersectingNode notNil ifTrue:[
-	    self debuggingCodeFor:#cg is:[
-		Transcript show:'last: '; showCR:lastIntersectingNode.
-	    ].
-	    ^ lastIntersectingNode
-	].
-	"/ firstIntersectingNode notNil ifTrue:[ ^ firstIntersectingNode ].
+        intersectingNodes := OrderedCollection new.
+        currentScopeNodes := IdentitySet new.
+
+        onErrorBlock :=
+            [:str :err :nodesSoFar |
+                |nodes|
+
+                allowErrors ifTrue:[
+                    rememberedScopeNodes := currentScopeNodes.
+                    firstIntersectingNode notNil ifTrue:[
+                        ^ firstIntersectingNode
+                    ].
+                    nodesSoFar notNil ifTrue:[
+                        nodes := nodesSoFar asOrderedCollection
+                                    collect:[:nd | nd whichNodeIntersects:interval]
+                                    thenSelect:[:nd | nd notNil ].
+                        nodes size == 1 ifTrue:[
+                            ^ nodes first
+                        ].
+                    ]
+                ].
+                nil
+            ].
+
+        self debuggingCodeFor:#cg is:[
+            Transcript show:'looking for: '; showCR:interval.
+        ].
+
+        nodeGenerationHook :=
+            [:node |
+                rememberedNodes add:node.
+
+                "/ would like to return here as soon as the node has been created by the parser;
+                "/ however, at that time, its parent(chain) is not yet created and so we might not know
+                "/ what the semantic interpretation (especially: scope of variable) will be.
+                "/ therefore, we parse all, and return the found node at the end.
+                (node isMethod or:[node isBlock or:[node isSequence]]) ifTrue:[
+                    currentScopeNodes add:node.
+                ] ifFalse:[
+                    self debuggingCodeFor:#cg is:[
+                        Transcript show:node; show:' '; show:node start; show:'->'; showCR:node stop.
+                    ].
+
+                    (node intersectsInterval:interval) ifTrue:[
+                        self debuggingCodeFor:#cg is:[
+                            Transcript showCR:'yes'.
+                        ].
+                        intersectingNodes add:node.
+                        firstIntersectingNode isNil ifTrue:[
+                            firstIntersectingNode := lastIntersectingNode := smallestIntersectingNode := node
+                        ] ifFalse:[
+                            |lenNode lenSmallest|
+
+                            lenNode := (node stop - node start).
+                            lenSmallest := (smallestIntersectingNode stop - smallestIntersectingNode start).
+                            lenNode < lenSmallest ifTrue:[
+                                smallestIntersectingNode := node.
+                            ].
+                            node start > lastIntersectingNode start ifTrue:[
+                                lastIntersectingNode := node.
+                            ].
+                        ].
+                    ].
+                ].
+            ].
+
+        "/ one of the big problems when using the RBParser here is
+        "/ that it behaves badly when a syntax error is encountered;
+        "/ for example, a node's parent is usually set AFTER the children are
+        "/ completely parsed (for example, a blockNode gets the parent-method only
+        "/ after parsing). Thus, when an error is encountered, we cannot walk
+        "/ the parent chain, and therefore will not see the outer locals/args of
+        "/ an inner scope (allVariablesOnScope returns only a partial set).
+        "/ A walkaround is to remember Method/Block nodes as created in the above node generation.
+        "/ The disadvantage of it is that we do not have correct scope information, until the node's
+        "/ parent gets set eventually, thus we might consider locals from sibling blocks.
+        "/ See rememberedScopeNodes handling above.
+        "/ Those other nodes are only remembered for failed parses;
+        "/ if the parse is ok, rememberedScopeNodes will be nil.
+
+        mustBeExpression ifFalse:[
+            tree := parserClass
+                        parseMethod: source
+                        setup:[:p |
+                            parser := p.
+                            p rememberNodes:true.
+                            p rememberTokens:true.
+                            p nodeGenerationCallback:nodeGenerationHook
+                        ]
+                        onError: onErrorBlock.
+            parser notNil ifTrue:[ tokens := parser rememberedTokens ].
+        ].
+
+        mustBeMethod ifTrue:[
+            "/ only cache parsed methods
+            tree notNil ifTrue:[
+                LastSource := source.
+                LastParseTree := tree.
+                LastScanTokens := tokens.
+            ].
+        ] ifFalse:[
+            (tree isNil or:[firstIntersectingNode isNil]) ifTrue:[
+                "/ try as an expression
+                tree := parserClass
+                            parseExpression: source
+                            setup:[:p |
+                                parser := p.
+                                p rememberNodes:true.
+                                p rememberTokens:true.
+                                p nodeGenerationCallback:nodeGenerationHook
+                            ]
+                            onError: onErrorBlock.
+                parser notNil ifTrue:[ tokens := parser rememberedTokens ].
+            ].
+        ].
+        lastIntersectingNode notNil ifTrue:[
+            self debuggingCodeFor:#cg is:[
+                Transcript show:'last: '; showCR:lastIntersectingNode.
+            ].
+            ^ lastIntersectingNode
+        ].
+        "/ firstIntersectingNode notNil ifTrue:[ ^ firstIntersectingNode ].
     ].
 
     bestNode := self findNodeForInterval:interval inParseTree:tree.
     self debuggingCodeFor:#cg is:[
-	Transcript show:'best: '; showCR:bestNode.
+        Transcript show:'best: '; showCR:bestNode.
     ].
     ^ bestNode