<b>=============== Summary ===============</b><br>
<br>
Change Set: browseMethodReference<br>
Date: 28 November 2022<br>
Author: Christoph Thiede<br>
<br>
Adds support for method references in editors's 'Browse it' and 'iMplmentors' shortcuts. Method references can have different formats such as String findMethodReference or String>>#findMethodReference. Includes tests and proper support for message traces.<br>
<br>
Performance: <1.1 ms per run if you select an entire line, which should be fine. :-)<br>
<br>
Also makes sure that no debuggers opens up when you browse the iMplementors of an incomplete literal such as a single quote.<br>
<br>
<b>=============== Diff ===============</b><br>
<br>
<b>MessageTrace>>browseMethod:requestor: {actions} · ct 11/28/2022 18:00</b><br>
<font color="#FF0000">+ browseMethod: aMethodReference requestor: requestor<br>
+ "Overwritten to modify the trace if the request origins from a model-menu command such as the message-list menu (shortcut)."<br>
+ <br>
+ (Preferences traceMessages and: [ self hasUnacceptedEdits not ])<br>
+ ifTrue: [ self<br>
+ addChildMessages: (OrderedCollection with: aMethodReference)<br>
+ autoSelectString: '' ]<br>
+ ifFalse: [ super browseAllImplementorsOf: aMethodReference requestor: requestor ].</font><br>
<br>
<b>Model>>browseMethod: {*Tools-MessageSets} · ct 11/28/2022 18:58</b><br>
<font color="#FF0000">+ browseMethod: aMethodReference<br>
+ "A tool's widget/view (i.e., 'requestor') requested to browse aMethodReference. By default, dispatch back to the reference."<br>
+ <br>
+ ^ aMethodReference browse</font><br>
<br>
<b>Model>>browseMethod:requestor: {*Tools-MessageSets} · ct 11/28/2022 18:58</b><br>
<font color="#FF0000">+ browseMethod: aMethodReference requestor: requestor<br>
+ "A tool's widget/view (i.e., 'requestor') requested to browse aMethodReference. By default, dispatch back to the reference."<br>
+ <br>
+ ^ self browseMethod: aMethodReference</font><br>
<br>
<b>ParagraphEditor>>selectedLiteral {menu messages} · ct 11/28/2022 18:18 (changed)</b><br>
selectedLiteral<br>
"Try to make a Smalltalk literal out of the current text selection."<br>
<br>
<s><font color="#0000FF">- ^ self selection string findLiteral<br>
</font></s><font color="#FF0000">+ ^ [self selection string findLiteral] ifError: ["e.g., incomplete string"]</font><br>
<br>
<b>String>>findMethodReference {converting} · ct 11/28/2022 19:03</b><br>
<font color="#FF0000">+ findMethodReference<br>
+ "Find and parse a method reference within the receiver. Answer a MethodReference or nil if none is found. Heuristic."<br>
+ <br>
+ | str substrings |<br>
+ str := self copyReplaceAll: '>>' with: ' >> '.<br>
+ str := str copyWithRegex: '(?=(?<![^\p{L}\:\s])[^\p{L}#\:\s]|(?<=[^\p{L}#\:\s])[\p{L}#\:\s])' matchesReplacedWith: ' '. "beginning or end of token"<br>
+ substrings := str substrings.<br>
+ substrings size - 1 to: 1 by: -1 do: [:classIndex | | classStr |<br>
+ classStr := substrings at: classIndex.<br>
+ (self environment classNamed: classStr) ifNotNil: [:class |<br>
+ (classIndex + 1 + ((substrings at: classIndex + 1) = '>>') asBit clampHigh: substrings size) to: classIndex + 1 by: -1 do: [:selIndex |<br>
+ | ref selStr |<br>
+ selStr := substrings at: selIndex.<br>
+ (selStr size > 1 and: [selStr first = $#]) ifTrue: [selStr := selStr allButFirst].<br>
+ (Symbol lookup: selStr) ifNotNil: [:sel |<br>
+ ref := MethodReference<br>
+ class: class<br>
+ selector: sel.<br>
+ ref isValid ifTrue: [^ ref]]]]].<br>
+ ^ nil</font><br>
<br>
<b>StringTest>>testFindMethodReference {tests - finding} · ct 11/28/2022 18:11</b><br>
<font color="#FF0000">+ testFindMethodReference<br>
+ <br>
+ {<br>
+ Number >> #negated. 'Number negated'.<br>
+ Number >> #negated. 'Number>>negated'.<br>
+ Number >> #negated. 'Number>>#negated'.<br>
+ Number >> #negated. 'Number >> #negated'.<br>
+ <br>
+ Number >> #negated. 'Number >> #negated.'.<br>
+ Number >> #negated. '"Number >> #negated"'.<br>
+ Number >> #negated. 'For more information, see Number>>#negated or run the tests.'.<br>
+ <br>
+ nil. 'Number absentSelector'.<br>
+ nil. ''.<br>
+ <br>
+ Morph >> #drawOn:. 'Morph drawOn:'.<br>
+ nil. 'Morph drawOn'. "Do not add colons."<br>
+ <br>
+ Number >> #+. 'Number +'.<br>
+ Number >> #+. 'Number>>+'.<br>
+ Number >> #+. 'Number>>#+'.<br>
+ Number >> #+. 'Number+'.<br>
+ <br>
+ Behavior >> #>>. 'Behavior >>'.<br>
+ Behavior >> #>>. 'Behavior>>'.<br>
+ Behavior >> #>>. 'Behavior>> >>'.<br>
+ } pairsDo: [:method :string |<br>
+ self<br>
+ assert: (method ifNotNil: [method asCodeReference])<br>
+ equals: string findMethodReference].</font><br>
<br>
<b>TextEditor>>browseIt {menu messages} · ct 11/28/2022 17:53 (changed)</b><br>
browseIt<br>
"Launch a browser for the current selection, if appropriate."<br>
<br>
<font color="#FF0000">+ self selectedMethodReference ifNotNil:<br>
+ [:methodReference | ^self model browseMethod: methodReference requestor: morph].<br>
</font> Preferences alternativeBrowseIt ifTrue: [^ self browseClassFromIt].<br>
<br>
self lineSelectAndEmptyCheck: [^ morph flash].<br>
<br>
"First, try to show all accesses to instance or class variables."<br>
self selectedInstanceVariable ifNotNil:<br>
[:nameToClass | self systemNavigation<br>
browseAllAccessesTo: nameToClass key<br>
from: nameToClass value].<br>
self selectedClassVariable ifNotNil:<br>
[:binding | self model browseAllCallsOn: binding].<br>
<br>
"Then, either browse the class (from a binding) or all implementors of a selector."<br>
self selectedBinding ifNotNil:<br>
[:binding | ^ self systemNavigation browseClass: binding].<br>
self selectedSelector ifNotNil:<br>
[:selector | ^ self model browseAllImplementorsOf: selector requestor: morph].<br>
<br>
morph flash<br>
<br>
<b>TextEditor>>implementorsOfIt {menu messages} · ct 11/28/2022 17:05 (changed)</b><br>
implementorsOfIt<br>
"Open an implementors browser on the selected selector"<br>
<br>
self lineSelectAndEmptyCheck: [^ self].<br>
<font color="#FF0000">+ self selectedMethodReference ifNotNil:<br>
+ [:methodReference | ^self model browseMethod: methodReference requestor: morph].<br>
</font> self selectedSelector ifNotNil:<br>
[:aSelector| ^self model browseAllImplementorsOf: aSelector requestor: morph].<br>
self selectedLiteral ifNotNil:<br>
[:aLiteral| ^self model browseAllImplementorsOf: aLiteral requestor: morph].<br>
morph flash.<br>
<br>
<b>TextEditor>>selectedLiteral {menu messages} · ct 11/28/2022 18:18 (changed)</b><br>
selectedLiteral<br>
"Try to make a Smalltalk literal out of the current text selection."<br>
<br>
<s><font color="#0000FF">- ^ self selection string findLiteral<br>
</font></s><font color="#FF0000">+ ^ [self selection string findLiteral] ifError: ["e.g., incomplete string"]</font><br>
<br>
<b>TextEditor>>selectedMethodReference {menu messages} · ct 11/28/2022 17:06</b><br>
<font color="#FF0000">+ selectedMethodReference<br>
+ "Try to make a method reference out of the current text selection."<br>
+ <br>
+ ^ self selection string findMethodReference</font><br>
<br>
<font color="#808080">---<br>
</font><font color="#808080"><i>Sent from </i></font><font color="#808080"><i><a href="https://github.com/hpi-swa-lab/squeak-inbox-talk"><u><font color="#808080">Squeak Inbox Talk</font></u></a></i></font><br>
["browseMethodReference.1.cs"]