DoWhatIMeanSupport.st
changeset 5064 6a358957f3fd
parent 5058 925bc542ebd1
child 5068 31a72703269d
child 5070 8277d17c3e50
--- a/DoWhatIMeanSupport.st	Wed May 04 19:28:32 2016 +0200
+++ b/DoWhatIMeanSupport.st	Wed May 04 23:02:35 2016 +0200
@@ -1626,44 +1626,192 @@
 
 !DoWhatIMeanSupport methodsFor:'code completion-helpers'!
 
-addClassesOfExpression:expr inClass:aClass to:setOfTypes
-    |cls exprSelector val|
+addClassesOfExpression:expr inClass:classOrNil to:setOfTypes
+    |cls exprSelector exprVal varName instVarClass valClass
+     msgSelector msgReceiver msgArg1
+     receiverClasses receiverClass 
+     arg1Classes mthd|
     
     expr isLiteral ifTrue:[
-        val := expr evaluate.
-        cls := val class.         
-        (val isArray or:[ val isByteArray or:[ val isString ]]) ifTrue:[
-            val isImmutable ifTrue:[
+        exprVal := expr value.
+        cls := exprVal class.         
+        (exprVal isArray or:[ exprVal isByteArray or:[ exprVal isString ]]) ifTrue:[
+            exprVal isImmutable ifTrue:[
                 setOfTypes add:cls mutableClass.
                 ^ self.    
             ]
         ].
-        setOfTypes add:cls.
+        setOfTypes add:cls. 
         ^ self.    
     ].
     
+    expr isBlock ifTrue:[
+        setOfTypes add:Block. 
+        ^ self.
+    ].
+    (exprVal := self valueOfNode:expr) notNil ifTrue:[
+        "/ knowing the value is always great!!
+        setOfTypes add:exprVal class.
+        ^ self.
+    ].
+
+    expr isVariable ifTrue:[
+        varName := expr name.
+        varName = 'self' ifTrue:[
+            setOfTypes add:(classOrNil ? UndefinedObject).
+            ^ self
+        ].
+        varName = 'super' ifTrue:[
+            classOrNil isNil 
+                ifTrue:[setOfTypes add:Object]
+                ifFalse:[setOfTypes add:classOrNil superclass].
+            ^ self.    
+        ].
+        varName = 'thisContext' ifTrue:[
+            setOfTypes add:Context.
+            ^ self
+        ].
+
+        classOrNil notNil ifTrue:[
+            instVarClass := classOrNil whichClassDefinesInstVar:varName.
+            instVarClass notNil ifTrue:[
+                setOfTypes addAll:(self classesOfInstVarNamed:varName inClass:instVarClass).
+            ].    
+        ].
+        ^ self
+    ].
+
     expr isMessage ifTrue:[
-        exprSelector := expr selector. 
-        ( #(+ - * /) includes:exprSelector ) ifTrue:[
-            setOfTypes add:Number.
-            ^ self.
+        msgSelector := expr selector.
+
+        "/ heuristic: quickly assume boolean for some:
+        (
+            #( 
+                isNil notNil isEmpty isEmptyOrNil notEmpty notEmptyOrNil
+                > >= < <= = == ~ ~=
+                knownAsSymbol
+                isMeta 
+                includes: contains:
+                not and: or:
+                exists atEnd positive negative odd even
+            ) includes:msgSelector
+        ) ifTrue:[
+            setOfTypes add:True. "/ use True, because boolean does not include the full protocol
+            ^ self    
+        ].
+
+        msgReceiver := expr receiver.
+
+        "/ some hardwired knowlegde here
+        receiverClasses := self classesOfNode:msgReceiver.
+        receiverClass := receiverClasses size == 1 ifTrue:[receiverClasses anElement] ifFalse:[nil].
+
+        receiverClass notNil ifTrue:[
+            ( #(copy shallowCopy) includes:exprSelector ) ifTrue:[
+                setOfTypes addAll:receiverClasses.
+                ^ self.
+            ].
+
+            msgSelector == #theNonMetaclass ifTrue:[  
+                setOfTypes add:receiverClass theNonMetaclass class.
+                ^ self            
+            ].
+            msgSelector == #theMetaclass ifTrue:[  
+                setOfTypes add:receiverClass theMetaclass class.
+                ^ self
+            ].
+            msgSelector == #class ifTrue:[
+                setOfTypes add:receiverClass class.
+                ^ self.
+            ].
+
+            receiverClass isBehavior ifTrue:[
+                mthd := receiverClass lookupMethodFor:msgSelector.
+                receiverClass isMeta ifTrue:[
+                    ( #( #'new' #'basicNew' #'new:' #'basicNew:' #'with:' #'with:with:') includes: msgSelector ) ifTrue:[
+                        setOfTypes add:receiverClass theNonMetaclass.
+                        ^ self.
+                    ].
+                    "/ if that method sends one of new/basicNew/new:/basicNew:, assume it returns an instance of itself
+                    mthd notNil ifTrue:[
+                        ( mthd sendsAny:#( #'new' #'basicNew' #'new:' #'basicNew:' )) ifTrue:[
+                            setOfTypes add:receiverClass theNonMetaclass.
+                            ^ self
+                        ].
+                    ].
+                ] ifFalse:[
+                    mthd notNil ifTrue:[
+                        (ParseTreeSearcher methodIsSetterMethod:mthd) ifTrue:[
+                            setOfTypes add:receiverClass.
+                            ^ self
+                        ]
+                    ]
+                ]
+            ].
+        ].
+
+        ((msgSelector startsWith:'as')
+        and:[ (valClass := Smalltalk classNamed:(msgSelector copyFrom:3)) notNil ]
+        ) ifTrue:[
+            setOfTypes add:valClass.
+            ^ self
         ].    
-        ( #(// size) includes:exprSelector ) ifTrue:[
-            setOfTypes add:Integer.
+
+        ((msgSelector startsWith:'is')
+        and:[ (valClass := Smalltalk classNamed:(msgSelector copyFrom:3)) notNil ]
+        ) ifTrue:[
+            setOfTypes add:True. "/ Boolean - not boolean; it does not contain the full protocol (would not find ifTrue:)
             ^ self.
         ].    
-        ( #(copy shallowCopy) includes:exprSelector ) ifTrue:[
-            "/ self addClassesOfExpression:expression receiver inClass:aClass to:setOfTypes
-            ^ self.
+
+        #(
+            size                    SmallInteger
+            hash                    SmallInteger
+            identityHash            SmallInteger
+            class                   Class
+            theMetaclass            Metaclass
+            theNonMetaclass         Class
+            fork                    Process
+            newProcess              Process
+        ) pairWiseDo:[:sel :clsName |
+            msgSelector == sel ifTrue:[ 
+                setOfTypes add:(Smalltalk at:clsName).
+                ^ self.
+            ].
+        ].
+
+        ( #( bitAnd: bitOr: bitShift: rightShift: >> << highBit lowBit ) includes:msgSelector) ifTrue:[
+            "/ assume integer
+
+            setOfTypes add:Integer.
+            ^ self
         ].
-        ( #(new new: basicNew basicNew:) includes:exprSelector ) ifTrue:[
-            expr receiver isGlobal ifTrue:[
-                setOfTypes add:expr receiver evaluate.
+        ( #( + - * // \\ ) includes:msgSelector) ifTrue:[
+            "/ assume numeric
+
+            setOfTypes add:Number.
+            ^ self
+        ].
+        msgSelector == #/ ifTrue:[
+            ((receiverClasses ? #()) contains:[:cls | cls includesBehavior:Number]) ifTrue:[
+                setOfTypes add:Number.
                 ^ self.
+            ].
+            msgArg1 := expr arg1.
+            arg1Classes := ((self classesOfNode:msgArg1) ? #()).
+            (arg1Classes contains:[:cls | cls includesBehavior:Number]) ifTrue:[
+                setOfTypes add:Number.
+                ^ self
             ].    
-        ].   
-self breakPoint:#cg.
-    ].
+        ].    
+        ( #( construct: / ) includes:msgSelector) ifTrue:[
+            ((receiverClasses ? #()) contains:[:cls | cls includesBehavior:Filename]) ifTrue:[
+                setOfTypes add:Filename.
+                ^ self
+            ].
+        ].    
+    ].
+    ^ nil
 !
 
 askUserForCompletion:what for:codeView at:position from:allTheBest
@@ -1867,162 +2015,11 @@
      When showing possible completions for a message,
      it is a good idea to know what the kind receiver is."
 
-    | nm nodeVal receiverClass 
-      msgSelector msgReceiver msgArg1
-      receiverClasses arg1Classes
-      mthd instVarClass valClass|
-
-    aNode isBlock ifTrue:[
-        ^ { Block }
-    ].
-    (nodeVal := self valueOfNode:aNode) notNil ifTrue:[
-        "/ knowing the value is always great!!
-        ^ { nodeVal class }
-    ].
-
-    aNode isVariable ifTrue:[
-        nm := aNode name.
-        nm = 'self' ifTrue:[
-            classOrNil isNil ifTrue:[^ { UndefinedObject } ].
-            ^ { classOrNil }
-        ].
-        nm = 'super' ifTrue:[
-            classOrNil isNil ifTrue:[^ Object].
-            ^ { classOrNil superclass }
-        ].
-        nm = 'thisContext' ifTrue:[
-            ^ { Context }
-        ].
-
-        classOrNil notNil ifTrue:[
-            instVarClass := classOrNil whichClassDefinesInstVar:nm.
-            instVarClass notNil ifTrue:[
-                ^ self classesOfInstVarNamed:nm inClass:instVarClass.
-            ].    
-"/            (classOrNil allInstVarNames includes:nm) ifTrue:[
-"/                "/ could look at existing instances here...
-"/                self breakPoint:#cg.
-"/            ].
-        ].
-        ^ nil
-    ].
-
-    aNode isMessage ifTrue:[
-        msgSelector := aNode selector.
-
-        "/ heuristic: quickly assume boolean for some:
-        (
-            #( 
-                isNil notNil isEmpty isEmptyOrNil notEmpty notEmptyOrNil
-                > >= < <= = == ~ ~=
-                knownAsSymbol
-                isMeta            
-            ) includes:msgSelector
-        ) ifTrue:[
-            ^ { True } "/ use True, because boolean does not include the full protocol
-        ].
-
-        msgReceiver := aNode receiver.
-
-        "/ some hardwired knowlegde here
-        receiverClasses := self classesOfNode:msgReceiver.
-        receiverClass := receiverClasses size == 1 ifTrue:[receiverClasses anElement] ifFalse:[nil].
-        
-        receiverClass notNil ifTrue:[
-            msgSelector == #theNonMetaclass ifTrue:[  
-                ^ { receiverClass theNonMetaclass class }
-            ].
-            msgSelector == #theMetaclass ifTrue:[  
-                ^ { receiverClass theMetaclass class }
-            ].
-            msgSelector == #class ifTrue:[
-                ^ { receiverClass class }
-            ].
-
-            receiverClass isBehavior ifTrue:[
-                mthd := receiverClass lookupMethodFor:msgSelector.
-                receiverClass isMeta ifTrue:[
-                    ( #( #'new' #'basicNew' #'new:' #'basicNew:' #'with:' #'with:with:') includes: msgSelector ) ifTrue:[
-                        ^ { receiverClass theNonMetaclass }
-                    ].
-                    "/ if that method sends one of new/basicNew/new:/basicNew:, assume it returns an instance of itself
-                    mthd notNil ifTrue:[
-                        ( mthd sendsAny:#( #'new' #'basicNew' #'new:' #'basicNew:' )) ifTrue:[
-                            ^ { receiverClass theNonMetaclass }
-                        ].
-                    ].
-                ] ifFalse:[
-                    mthd notNil ifTrue:[
-                        (ParseTreeSearcher methodIsSetterMethod:mthd) ifTrue:[
-                            ^ { receiverClass }.
-                        ]
-                    ]
-                ]
-            ].
-        ].
-
-        ((msgSelector startsWith:'as')
-        and:[ (valClass := Smalltalk classNamed:(msgSelector copyFrom:3)) notNil ]
-        ) ifTrue:[
-            ^ { valClass }
-        ].    
-        ((msgSelector startsWith:'is')
-        and:[ (valClass := Smalltalk classNamed:(msgSelector copyFrom:3)) notNil ]
-        ) ifTrue:[
-            ^ { True } "/ Boolean - not boolean; it does not contain the full protocol (would not find ifTrue:)
-        ].    
-
-        #(
-            size                    SmallInteger
-            hash                    SmallInteger
-            identityHash            SmallInteger
-            class                   Class
-            theMetaclass            Metaclass
-            theNonMetaclass         Class
-        ) pairWiseDo:[:sel :clsName |
-            msgSelector == sel ifTrue:[ 
-                ^ { Smalltalk at:clsName } 
-            ].
-        ].
-
-        "/ some wellknown boolean returners (need better type inference here)
-        (#(  
-            includes: contains:
-            not and: or:
-            exists atEnd
-        ) includes:msgSelector ) ifTrue:[
-            ^ { True } "/ Boolean - not boolean; it does not contain the full protocol (would not find ifTrue:)
-        ].
-
-        ( #( bitAnd: bitOr: bitShift: rightShift: >> << highBit lowBit ) includes:msgSelector) ifTrue:[
-            "/ assume integer
-
-            ^ { Integer }
-        ].
-        ( #( + - * // \\ ) includes:msgSelector) ifTrue:[
-            "/ assume numeric
-            
-            ^ { Number }
-        ].
-        msgSelector == #/ ifTrue:[
-            ((receiverClasses ? #()) contains:[:cls | cls includesBehavior:Number]) ifTrue:[
-                ^ { Number }
-            ].
-            msgArg1 := aNode arg1.
-            arg1Classes := ((self classesOfNode:msgArg1) ? #()).
-            (arg1Classes contains:[:cls | cls includesBehavior:Number]) ifTrue:[
-                ^ { Number }
-            ].    
-        ].    
-        ( #( construct: / ) includes:msgSelector) ifTrue:[
-            ((receiverClasses ? #()) contains:[:cls | cls includesBehavior:Filename]) ifTrue:[
-                ^ { Filename }
-            ].
-        ].    
-    ].
-    ^ nil
-
-    "Modified: / 01-05-2016 / 12:33:20 / cg"
+    | setOfTypes|
+
+    setOfTypes := Set new.
+    self addClassesOfExpression:aNode inClass:classOrNil to:setOfTypes.
+    ^ setOfTypes
 !
 
 codeCompletionForLiteralSymbol:nodeOrNil element:tokenOrNil considerAll:considerAll into:actionBlock