#UI_ENHANCEMENT by cg
class: DoWhatIMeanSupport
changed:
#codeCompletionForMessage:into:
#tryCodeCompletionWithSource:nodeInterval:at:mustBeExpression:into:
--- a/DoWhatIMeanSupport.st Thu May 12 18:07:46 2016 +0200
+++ b/DoWhatIMeanSupport.st Thu May 12 21:30:38 2016 +0200
@@ -1873,7 +1873,7 @@
offerParenthisationAroundNode parenthesisAroundIndex parentNodeToParenthesize
offerValueInsertion valueToInsert valueToInsertIndex valueInfo
classesFromAssignmentsToReceiver otherMessagesToReceiver
- canParenthesize|
+ canParenthesize classesOfReceiver|
"/ Transcript show:'node '; show:node; show:' ; '.
"/ Transcript show:'msg in '; show:methodOrNil; show:' / '; showCR:classOrNil.
@@ -1887,8 +1887,10 @@
[:node :selector |
|srchClasses bestSelectors bestPrefixes
allMessagesSentToVariable classesImplementingAllMessages|
-
- srchClasses := self classesOfNode:node.
+
+ srchClasses := node==nodeReceiver
+ ifTrue:[classesOfReceiver]
+ ifFalse:[self classesOfNode:node].
srchClasses isEmptyOrNil ifTrue:[
node isVariable ifTrue:[
@@ -1932,6 +1934,7 @@
bestSelectors addAll:bestForThisClass.
].
].
+ (bestSelectors includes:'h1')ifTrue:[self halt].
"/ remove the already typed-in selector itself, in case.
bestSelectors remove:selector ifAbsent:[].
bestSelectors := bestSelectors asOrderedCollection.
@@ -1942,6 +1945,10 @@
lcSelector := selector asLowercase.
parentNode := node parent.
nodeReceiver := node receiver.
+ nodeReceiver notNil ifTrue:[
+ classesOfReceiver := self classesOfNode:nodeReceiver.
+ ].
+( node isVariable and:[node name = 'self']) ifTrue:[self halt].
"/ if there is already space before the cursor, and the parent node is not a message,
"/ do not attempt to complete the current message.
@@ -2100,11 +2107,15 @@
] ifFalse:[
|kwSels|
- "/ if its a unary message AND the parent is a unary or binary node, try again, sending the partial message
+ "/ if its a unary message AND the parent is a unary or binary node,
+ "/ try again, sending the partial message
"/ as a keyword to the parent node.
- "/ this is the case when after "foo binOp bar if", which should include ifTrue: in the result.
- "/ transform from (the incorrectly parsed)
+ "/ this is the case when after "foo binOp bar if", or "foo unOp bar if"
+ "/ which should include ifTrue: in the suggestion result.
+
+ "/ suggestion will transform from (the incorrectly parsed)
"/ foo == (shift if)
+ "/
"/ nonKWsel-msg(parent)
"/ / \
"/ / \
@@ -2124,34 +2135,42 @@
"/ /
"/ arg
- kwSels := findBest value:parentNode value:selector.
- kwSels := kwSels select:[:sel | sel isKeyword].
+ "/ but only do this, if typing to the end of the parent message
+ "/ (i.e. after (foo == shift) <-
+ "/ or after foo bar baz <-
+ "/ not if typing into an existing message
+ "/ (i.e. into foo == shift <- more
+ "/ or into foo bar <- baz
+ codeView characterPositionOfCursor >= parentNode stop ifTrue:[
+ kwSels := findBest value:parentNode value:selector.
+ kwSels := kwSels select:[:sel | sel isKeyword].
+
+ kwSels := kwSels asOrderedCollection sort:[:a :b | a size < b size].
- kwSels := kwSels asOrderedCollection sort:[:a :b | a size < b size].
-
- bestSelectors := bestSelectors reject:[:sel | kwSels includes:sel].
+ bestSelectors := bestSelectors reject:[:sel | kwSels includes:sel].
- "/ these need to go to bestSelectors (see editAction)
- parentNodeClassIfKnown := self classOfNode:parentNode.
- (parentNodeClassIfKnown notNil and:[ parentNodeClassIfKnown includesBehavior: Boolean ]) ifTrue:[
- "/ this is so common, that it deserves a special case:
- "/ if we complete an if after some boolean message e.g '(a == b) if'
- "/ throw out the very unlikely ifNil, ifEmpty etc. messages (which are inherited by Object, but absolutely unrealistic)
- bestSelectors := self
- withoutSelectorsUnlikelyFor:parentNodeClassIfKnown
- from:bestSelectors
- forPartial:selector.
- kwSels := self
- withoutSelectorsUnlikelyFor:parentNodeClassIfKnown
- from:kwSels
- forPartial:selector.
-
- "/ put keyword selectors in front, because they are very likely
- bestSelectors := kwSels , bestSelectors.
- ] ifFalse:[
- "/ put them at the end
- bestSelectors := bestSelectors , kwSels.
- ].
+ "/ these need to go to bestSelectors (see editAction)
+ parentNodeClassIfKnown := self classOfNode:parentNode.
+ (parentNodeClassIfKnown notNil and:[ parentNodeClassIfKnown includesBehavior: Boolean ]) ifTrue:[
+ "/ this is so common, that it deserves a special case:
+ "/ if we complete an if after some boolean message e.g '(a == b) if'
+ "/ throw out the very unlikely ifNil, ifEmpty etc. messages (which are inherited by Object, but absolutely unrealistic)
+ bestSelectors := self
+ withoutSelectorsUnlikelyFor:parentNodeClassIfKnown
+ from:bestSelectors
+ forPartial:selector.
+ kwSels := self
+ withoutSelectorsUnlikelyFor:parentNodeClassIfKnown
+ from:kwSels
+ forPartial:selector.
+
+ "/ put keyword selectors in front, because they are very likely
+ bestSelectors := kwSels , bestSelectors.
+ ] ifFalse:[
+ "/ put them at the end
+ bestSelectors := bestSelectors , kwSels.
+ ].
+ ]
]
].
@@ -4308,6 +4327,7 @@
^ self.
].
].
+ (source startsWith:'sel') ifTrue:[self halt].
nodeParent := node parent.
(node isVariable