class: DoWhatIMeanSupport
authorClaus Gittinger <cg@exept.de>
Sun, 15 Sep 2013 12:43:18 +0200
changeset 4386 d5b6d7c0b6ee
parent 4385 d3381caeb327
child 4387 306eac46bcb1
class: DoWhatIMeanSupport comment/format in: #isKey:nextTo: #keyboard #tryCodeCompletionWithSource:nodeInterval:into: changed: #codeCompletionForClass:context:codeView: #codeCompletionForMessage:into: #codeCompletionForMethodSpec:
DoWhatIMeanSupport.st
--- a/DoWhatIMeanSupport.st	Thu Sep 12 16:01:17 2013 +0200
+++ b/DoWhatIMeanSupport.st	Sun Sep 15 12:43:18 2013 +0200
@@ -1019,7 +1019,7 @@
 isKey:k1 nextTo:k2
     "return true, if k1 and k2 are adjacent keys on the keyboard.
      This is used to specially priorize plausible typing errors of adjacent keys.
-     CAVEAT: hard coded us- and german keyboards here."
+     CAVEAT: hard coded us-, german and french keyboards here; data should come from somewhere else."
 
     ^ self isKey:k1 nextTo:k2 onKeyboard:(self keyboard)
 
@@ -1054,8 +1054,9 @@
 !
 
 keyboard
-    "the keyboard layout (useful to figure out which keys are nearby a key,
-     to find possible typing errors)"
+    "the keyboard layout 
+     (useful to figure out which keys are nearby a key, to find possible typing errors)
+     CAVEAT: hard coded us-, german and french keyboards here; data should come from somewhere else."
 
     |lang|
 
@@ -1065,7 +1066,8 @@
                '1234567890-'
                '*qwertzuiop'
                '**asdfghjkl:'
-               '***yxcvbnm' ).
+               '***yxcvbnm' 
+        ).
     ].
 
     lang == #fr ifTrue:[
@@ -1073,14 +1075,16 @@
                '1234567890'
                '*azertyuiop'
                '**qsdfghjklm'
-               '***wxcvbn,' ).
+               '***wxcvbn,' 
+        ).
     ].
 
     ^ #( 
            '1234567890-'
            '*qwertyuiop'
            '**asdfghjkl:'
-           '***zxcvbnm' ).
+           '***zxcvbnm' 
+    ).
 
     "
      self keyboard 
@@ -1164,7 +1168,7 @@
                 forceNewMessageSend := true.
             ].
         ] ifFalse:[
-            (node isUnary) ifTrue:[
+            (node isMessage and:[node isUnary]) ifTrue:[
                 "/ expanding <rcvr> foo |<- cursor here (i.e. a space after foo)
                 "/
                 forceNewMessageSend := true.
@@ -1652,7 +1656,7 @@
      bestSelectors selector2 bestSelectors2 allBest best info numArgs
      newParts nSelParts oldLen newLen selectorParts 
      findBest parentNode selectorsSentInCode split editAction parentNodeClassIfKnown 
-     otherMessagesToReceiver possibleClasses receiverNodeClassIfKnown|
+     otherMessagesToReceiver assignmentsToReceiver possibleClasses receiverNodeClassIfKnown|
 
     "/ Transcript show:'msg in '; show:methodOrNil; show:' / '; showCR:classOrNil.
 
@@ -1689,17 +1693,37 @@
 
     bestSelectors := findBest value:node receiver value:selector.  
 
-    "/ if the receiver is a variable, we can look for other messages being sent to that variable in the current method
+    "/ if the receiver is a variable, 
+    "/ we can look for other messages being sent to that variable in the current method.
+    "/ also, if there is an assignment like class new to it...
     (tree notNil and:[ node receiver isVariable ])
     ifTrue:[
-        otherMessagesToReceiver := tree allMessageNodes 
-                                    select:[:eachMessageNode | 
-                                        node receiver = eachMessageNode receiver
-                                        and:[ selector ~= eachMessageNode selector]]
-                                    thenCollect:[:eachNode | eachNode selector].
-        possibleClasses := Smalltalk allClassesForWhich:[:cls |
-                            otherMessagesToReceiver conform:[:eachSelectorSent | cls canUnderstand:eachSelectorSent]].
-        possibleClasses := possibleClasses select:[:cls | cls isLoaded].
+        assignmentsToReceiver := tree allAssignmentNodes 
+                                    collect:[:eachAssignmentNode |
+                                                |cls|
+
+                                                (node receiver = eachAssignmentNode variable
+                                                    and:[ (cls := self classOfNode:eachAssignmentNode value) notNil ]
+                                                ) ifTrue:[
+                                                    cls
+                                                ] ifFalse:[
+                                                    nil
+                                                ]
+                                            ]
+                                    thenSelect:[:classOrNil | classOrNil notNil].
+        assignmentsToReceiver notEmptyOrNil ifTrue:[
+            possibleClasses := assignmentsToReceiver
+        ] ifFalse:[
+            otherMessagesToReceiver := tree allMessageNodes 
+                                        select:[:eachMessageNode | 
+                                                    node receiver = eachMessageNode receiver
+                                                    and:[ selector ~= eachMessageNode selector]]
+                                        thenCollect:[:eachNode | eachNode selector].
+            otherMessagesToReceiver := otherMessagesToReceiver asSet.
+            possibleClasses := Smalltalk allClassesForWhich:[:cls |
+                                otherMessagesToReceiver conform:[:eachSelectorSent | cls includesSelector: "canUnderstand:" eachSelectorSent]].
+            possibleClasses := possibleClasses select:[:cls | cls isLoaded].
+        ].
         (possibleClasses notEmpty and:[possibleClasses size < 10]) ifTrue:[
             bestSelectors := Set new.
             possibleClasses do:[:eachClass |
@@ -1907,20 +1931,20 @@
 
     editAction := 
         [:index |
-            |best|
-
-            best := allBest at:index.
-
-            best ~= selector ifTrue:[
-                numArgs := best numArgs.
-                (bestSelectors2 notEmptyOrNil and:[bestSelectors2 includes:best]) ifTrue:[
+            |chosen|
+
+            chosen := allBest at:index.
+
+            chosen ~= selector ifTrue:[
+                numArgs := chosen numArgs.
+                (bestSelectors2 notEmptyOrNil and:[bestSelectors2 includes:chosen]) ifTrue:[
                     selectorParts := parentNode selectorParts , node selectorParts.
                 ] ifFalse:[
                     selectorParts := node selectorParts.
                 ].
                 nSelParts := selectorParts size.
 
-                newParts := best asCollectionOfSubstringsSeparatedBy:$:.
+                newParts := chosen asCollectionOfSubstringsSeparatedBy:$:.
                 newParts := newParts select:[:part | part size > 0].
 
                 codeView
@@ -1928,7 +1952,7 @@
                         |newCursorPosition stop checkForArgumentTemplates|
 
                         checkForArgumentTemplates := false.
-                        (selector isUnarySelector and:[best isKeywordSelector]) ifTrue:[ checkForArgumentTemplates := true ].
+                        (selector isUnarySelector and:[chosen isKeywordSelector]) ifTrue:[ checkForArgumentTemplates := true ].
                         numArgs > nSelParts ifTrue:[
                             "/ new selector has more arguments; append them
                             stop := selectorParts last stop.
@@ -1938,7 +1962,7 @@
                                 |newPart|
 
                                 newPart := newParts at:idx.
-                                (best endsWith:$:) ifTrue:[
+                                (chosen endsWith:$:) ifTrue:[
                                     newPart := newPart , ':'
                                 ].
 
@@ -1962,7 +1986,7 @@
                             start := oldPartialToken start.
                             stop := oldPartialToken stop.
 
-                            (best endsWith:$:) ifTrue:[
+                            (chosen endsWith:$:) ifTrue:[
                                 (codeView characterAtCharacterPosition:stop+1) == $: ifFalse:[
                                     newPart := newPart , ':'
                                 ]
@@ -2000,7 +2024,7 @@
                             (
                                 #(
                                     'ifTrue:' 'ifFalse:' 'ifTrue:ifFalse:' 'ifFalse:ifTrue:' 'and:' 'or:'
-                                ) includes:best
+                                ) includes:chosen
                             ) ifTrue:[
                                 codeView insertStringAtCursor:('[]',extra).
                                 codeView cursorLeft:1+extra size. 
@@ -2008,7 +2032,7 @@
                             (
                                 #(
                                     'collect:' 'select:' 'reject:' 'do:'
-                                ) includes:best
+                                ) includes:chosen
                             ) ifTrue:[
                                 codeView insertStringAtCursor:('[:each | ]',extra).
                                 codeView cursorLeft:1+extra size. 
@@ -2037,7 +2061,9 @@
             |chosen|
 
             chosen := self askUserForCompletion:whatIsIt for:codeView at:node start from:suggestions.
-            action value:(suggestions indexOf:chosen)
+            chosen notNil ifTrue:[
+                action value:(suggestions indexOf:chosen)
+            ].
         ].
 
 "/    |crsrPos
@@ -3997,10 +4023,10 @@
 !DoWhatIMeanSupport class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg2/DoWhatIMeanSupport.st,v 1.154 2013-09-12 14:01:17 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg2/DoWhatIMeanSupport.st,v 1.155 2013-09-15 10:43:18 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libwidg2/DoWhatIMeanSupport.st,v 1.154 2013-09-12 14:01:17 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg2/DoWhatIMeanSupport.st,v 1.155 2013-09-15 10:43:18 cg Exp $'
 ! !