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