DoWhatIMeanSupport.st
changeset 5071 976ed2a22e27
parent 5070 8277d17c3e50
child 5072 44266af72629
child 5074 1f0c4ef255d8
--- a/DoWhatIMeanSupport.st	Thu May 05 17:11:41 2016 +0200
+++ b/DoWhatIMeanSupport.st	Fri May 06 04:54:44 2016 +0200
@@ -1841,14 +1841,13 @@
 codeCompletionForMessage:node into:actionBlock
     "find good completions for a message selector in a message-send node"
     
-    |selector lcSelector srchClass implClass    
-     bestSelectors parentSelector newParentSelector bestSelectors2 bestWithParenthesis allBest best info numArgs
+    |selector lcSelector bestSelectors parentSelector newParentSelector bestSelectors2 bestWithParenthesis allBest numArgs
      newParts nSelParts oldLen newLen selectorParts
      findBest parentNode nodeReceiver "selectorsSentInCode" selectorsImplementedInClass
      editAction parentNodeClassIfKnown
      receiverNodeClassIfKnown 
-     offerParenthisationAroundNode parenthesisAroundIndex
-     parentNodeToParenthesize 
+     offerParenthisationAroundNode parenthesisAroundIndex parentNodeToParenthesize
+     offerValueInsertion valueToInsert valueToInsertIndex valueInfo
      classesFromAssignmentsToReceiver otherMessagesToReceiver
      canParenthesize|
  
@@ -1856,6 +1855,7 @@
     "/ Transcript show:'msg in '; show:methodOrNil; show:' / '; showCR:classOrNil.
  
     offerParenthisationAroundNode := nil.
+    offerValueInsertion := false.
  
     "/ node at:1
  
@@ -2239,7 +2239,30 @@
         ]
     ].
  
-    (allBest isEmptyOrNil and:[bestWithParenthesis isEmptyOrNil]) ifTrue:[ 
+    "/ another convenient hack; 
+    "/ if we have just typed in foo == 
+    "/ and the value of foo is a known literal,
+    "/ offer inserting this literal. This is great in a debugger...
+    ( #(#'==' #'=' #'~=' #'~~') includes:selector ) ifTrue:[
+        |val|
+
+        (val := self valueOfNode:nodeReceiver) notNil ifTrue:[
+            offerValueInsertion := true.
+            valueToInsert := val storeString.
+            nodeReceiver isVariable ifTrue:[
+                valueInfo := ' (current value of %1)' bindWith:nodeReceiver name.
+            ] ifFalse:[                
+                valueInfo := ' (current value of expression)'.
+            ].
+            valueInfo := valueInfo withColor:(Color grey).
+        ].    
+    ].    
+    
+    (allBest isEmptyOrNil 
+        and:[bestWithParenthesis isEmptyOrNil
+        and:[offerParenthisationAroundNode isNil
+        and:[offerValueInsertion not]]] 
+    ) ifTrue:[ 
         ^ self 
     ].
  
@@ -2353,6 +2376,10 @@
         allBest := allBest copyWith:( '(',selector,')' ).
         parenthesisAroundIndex := allBest size.
     ].
+    offerValueInsertion ifTrue:[
+        allBest := allBest copyWith:( '... ',(valueToInsert contractTo:30),valueInfo). 
+        valueToInsertIndex := allBest size.
+    ].
  
     editAction :=
         [:index |
@@ -2387,7 +2414,22 @@
                                 codeView insertString:')' atCharacterPosition:offerParenthisationAroundNode stop+2.
                                 codeView cursorToCharacterPosition:(offerParenthisationAroundNode stop+2); cursorRight.
                             ].
-                    ]
+                    ] ifFalse:[
+                        (offerValueInsertion and:[index = valueToInsertIndex]) ifTrue:[
+                            "/ for input like: 
+                            "/      foo == 
+                            "/ insert a value
+                            "/ i.e.:   foo == #someSymbol
+                            action :=
+                                [
+                                    codeView characterBeforeCursor isSeparator ifFalse:[
+                                        codeView insertStringAtCursor:' '.
+                                    ].    
+                                    codeView insertStringAtCursor:valueToInsert.
+                                    "/ codeView cursorRight.
+                                ].
+                        ]
+                    ].    
                 ].
  
                 action isNil ifTrue:[
@@ -3728,8 +3770,10 @@
                 (node isMethod or:[node isBlock or:[node isSequence]]) ifTrue:[
                     currentScopeNodes add:node.
                 ] ifFalse:[
-                    self debuggingCodeFor:#cg is:[
+                    true ifTrue: "self debuggingCodeFor:#cg is:"[
+                        node isMessage ifTrue:[
                         Transcript show:node; show:' '; show:node start; show:'->'; showCR:node stop.
+                        ].
                     ].
 
                     (node intersectsInterval:interval) ifTrue:[
@@ -4817,7 +4861,7 @@
      it is a good idea to know what the reveiver's value is.
      Sigh - returns nil both if unknown AND if a real nil is there."
 
-    |nodeSelector nodeReceiver isNonDestructive receiverValue method|
+    |nodeSelector nodeReceiver isNonDestructive receiverValue method impl|
 
     aNode isLiteral ifTrue:[
         ^ aNode value
@@ -4829,7 +4873,7 @@
     aNode isMessage ifTrue:[
         nodeSelector := aNode selector.
         nodeReceiver := aNode receiver.
-
+                
         "/ some hardwired knowlegde here
         classOrNil notNil ifTrue:[
             (nodeReceiver isSelf and:[nodeSelector = #'class']) ifTrue:[
@@ -4837,22 +4881,36 @@
             ].
         ].
 
-        isNonDestructive := false.
-
-        ( #( class theMetaclass theNonMetaclass ) includes:nodeSelector) ifTrue:[
-            isNonDestructive := true.
-        ] ifFalse:[
-            "/ follow non-destructive accessors
-            receiverValue := self valueOfNode:nodeReceiver.
-            receiverValue notNil ifTrue:[
+        receiverValue := self valueOfNode:nodeReceiver.
+        receiverValue notNil ifTrue:[
+            isNonDestructive := false.
+
+            "/ some are wellknown
+            nodeSelector == #size ifTrue:[
+                "/ mhm - be conservative; someone might have redefined #size
+                impl := receiverValue class whichClassIncludesSelector:nodeSelector.
+                "/ more hardwired stuff.
+                ((impl == Object) or:[(impl == String) or:[impl isSubclassOf:Collection]]) ifTrue:[
+                    isNonDestructive := true.
+                ].
+            ].
+        
+            ( #( basicSize
+                 class theMetaclass theNonMetaclass ) includes:nodeSelector) ifTrue:[
+                isNonDestructive := true.
+            ] ifFalse:[
+                "/ follow non-destructive accessors
                 method := receiverValue class lookupMethodFor:nodeSelector.
                 method notNil ifTrue:[
                     (ParseTreeSearcher methodIsJustReturningSomething:method) ifTrue:[
                         "/ we can savely call that method to get the current value
-                        ^ receiverValue perform: nodeSelector.
-                    ]
+                        isNonDestructive := true.
+                    ].
                 ].
             ].
+            isNonDestructive ifTrue:[
+                 ^ receiverValue perform: nodeSelector.
+            ].
         ].
     ].