--- 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