<body><div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000;text-align: left" dir="ltr">
                                        Yes! Thanks. :-)<div><br></div><div>Best,</div><div>Marcel</div><div class="mb_sig"></div><blockquote class='history_container' type='cite' style='border-left-style:solid;border-width:1px; margin-top:20px; margin-left:0px;padding-left:10px;'>
                        <p style='color: #AAAAAA; margin-top: 10px;'>Am 29.11.2021 11:53:46 schrieb commits@source.squeak.org <commits@source.squeak.org>:</p><div style='font-family:Arial,Helvetica,sans-serif'>Patrick Rein uploaded a new version of Tools to project The Trunk:<br>http://source.squeak.org/trunk/Tools-pre.1077.mcz<br><br>==================== Summary ====================<br><br>Name: Tools-pre.1077<br>Author: pre<br>Time: 29 November 2021, 11:53:31.567297 am<br>UUID: d1d2b6a9-1db1-1947-b4b6-5a57fd00945d<br>Ancestors: Tools-mt.1076<br><br>Slightly improves the documentation of the dependency browser and refactors the dependency computation by splitting it up into single methods describing the individual steps.<br><br>=============== Diff against Tools-mt.1076 ===============<br><br>Item was changed:<br>  CodeHolder subclass: #DependencyBrowser<br>   instanceVariableNames: 'packageList packageDeps packageDepsList classDeps classDepsList classList messageList packageListIndex packageDepsIndex classDepsIndex classListIndex messageListIndex autoSelectString windowTitle'<br>          classVariableNames: ''<br>        poolDictionaries: ''<br>          category: 'Tools-Browser'!<br>  <br>+ !DependencyBrowser commentStamp: 'pre 11/29/2021 11:48' prior: 0!<br>- !DependencyBrowser commentStamp: 'fbs 5/6/2011 11:29' prior: 0!<br>  A simple dependency browser showing five panes:<br>  [1]: Packages: The list of available packages in the system.<br>+ [2]: Package Dependencies: The packages the currently selected package depends on.<br>+ [3]: Class Dependencies: The classes the currently selected package [1] depends on (filtered by the selected required package [2]).<br>+ [4]: Class List: The classes in the currently selected package [1] containing the references to the class dependencies [3].<br>+ [5]: Messages: The messages in the currently selected package [1] and class [4] that contain the references to the class dependencies [3].<br>+ <br>+ # Implementation<br>+ The dependencies are pre-computed whenever the selected package changes [1], see #computePackageAndClassDependencies.!<br>- [2]: Package Dependencies: The dependent packages of the currently selected package.<br>- [3]: Class Dependencies: The classes causing the dependencies.<br>- [4]: Class List: The classes introducing the dependencies.<br>- [5]: Messages: The messages introducing the dependencies.!<br><br>Item was changed:<br>  ----- Method: DependencyBrowser class>>openInvertedOn: (in category 'opening') -----<br>  openInvertedOn: requiredPackageNames<br>        "DependencyBrowser openInvertedOn: #(Monticello)"<br>   <br>      | model |<br>     model := self new.      <br>      ^ ToolBuilder open: (<br>                 model<br>                         packageList: (model packageList select: [:packageName |<br>+                              model computePackageAndClassDependencies: packageName.<br>-                               model computePackageDependencies: packageName.<br>                                model packageDeps includesAnyOf: requiredPackageNames]);<br>                      windowTitle: ('Dependency Browser (inverted on {1})' format: {requiredPackageNames});<br>                         yourself)<br>  !<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>classDeps (in category 'class dependencies') -----<br>- ----- Method: DependencyBrowser>>classDeps (in category 'class deps') -----<br>  classDeps<br>    "Class dependencies for the currently selected package"<br>     packageDeps ifNil: [^ #()].<br>   ^ (packageDeps at: self packageDepsSelection ifAbsent:[#()]) sort.<br>  !<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>classDepsIndex (in category 'class dependencies') -----<br>- ----- Method: DependencyBrowser>>classDepsIndex (in category 'class deps') -----<br>  classDepsIndex<br>    "Class dependency selection"<br>        ^classDepsIndex ifNil:[0]!<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>classDepsIndex: (in category 'class dependencies') -----<br>- ----- Method: DependencyBrowser>>classDepsIndex: (in category 'class deps') -----<br>  classDepsIndex: idx<br>          "Class dependency selection"<br>        classDepsIndex := idx.<br>        self changed: #classDepsIndex.<br>        classList := nil.<br>     self changed: #classList.<br>     self classListIndex: (idx = 0 ifTrue: [0] ifFalse: [1]).!<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>classDepsKey:from: (in category 'class dependencies') -----<br>- ----- Method: DependencyBrowser>>classDepsKey:from: (in category 'class deps') -----<br>  classDepsKey: aCharacter from: aPluggableListMorphPlus <br>         aCharacter = $N ifTrue: [^ self referencesToIt: (self classDeps at: self classDepsIndex)].!<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>classDepsList (in category 'class dependencies') -----<br>- ----- Method: DependencyBrowser>>classDepsList (in category 'class deps') -----<br>  classDepsList<br>   "Class dependencies for the currently selected package"<br>  <br>         | checkDef checkExt |<br>         checkDef := [:mref | mref selector = #Definition].<br>    checkExt := [:mref | mref category notNil and: [mref category first = $*]].<br>   <br>      ^ classDepsList ifNil: [        <br>              classDepsList := self classDeps.<br>              classDepsList := classDepsList collect: [:className |<br>                         String streamContents: [:label |<br>                              label nextPutAll: className.<br>                                  (self depsForClassNamed: className allSatisfy: checkDef)<br>                                      ifTrue: [label nextPutAll: ' (defs only)']<br>                                    ifFalse: [(self depsForClassNamed: className allSatisfy: checkExt)<br>                                            ifTrue: [label nextPutAll: ' *exts only']<br>                                             ifFalse: [<br>                                                    (self depsForClassNamed: className anySatisfy: checkDef)<br>                                                              ifTrue: [label nextPutAll: ' ()'].<br>                                                    (self depsForClassNamed: className anySatisfy: checkExt)<br>                                                              ifTrue: [label nextPutAll: ' *']]]]]]!<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>classDepsMenu: (in category 'class dependencies') -----<br>- ----- Method: DependencyBrowser>>classDepsMenu: (in category 'class deps') -----<br>  classDepsMenu: aMenu<br>       ^aMenu!<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>classDepsSelection (in category 'class dependencies') -----<br>- ----- Method: DependencyBrowser>>classDepsSelection (in category 'class deps') -----<br>  classDepsSelection<br>        "Class dependency selection"<br>        ^(self classDepsIndex between: 1 and: self classDeps size)<br>            ifTrue:[self classDeps at: self classDepsIndex].!<br><br>Item was added:<br>+ ----- Method: DependencyBrowser>>computeClassDependenciesFor: (in category 'private - dependencies') -----<br>+ computeClassDependenciesFor: packageInfo<br>+         <br>+     packageInfo classes do: [:pkgClass |<br>+                 "Add the superclass and SharedPools as dependencies."<br>+              (classDeps at: (pkgClass superclass ifNil: [ProtoObject]) name<br>+                       ifAbsentPut: [OrderedCollection new]) add: <br>+                          (MethodReference class: pkgClass selector: #Definition).<br>+             pkgClass sharedPools do: [:sharedPool |<br>+                      sharedPool isBehavior ifTrue: [<br>+                              (classDeps at: sharedPool name<br>+                                       ifAbsentPut: [OrderedCollection new]) add: <br>+                                          (MethodReference class: pkgClass selector: #Definition)]]].<br>+ <br>+      packageInfo coreMethods do: [:mref |<br>+                 mref compiledMethod allLiteralsDo: [:lit |<br>+                   (lit isVariableBinding and: [lit value isBehavior]) ifTrue: [<br>+                                (classDeps at: lit value name ifAbsentPut: [OrderedCollection new])<br>+                                  add: mref]]].<br>+ <br>+    packageInfo extensionMethods do: [:mref |<br>+            (classDeps at: mref actualClass name ifAbsentPut: [OrderedCollection new])<br>+                   add: mref].<br>+ !<br><br>Item was added:<br>+ ----- Method: DependencyBrowser>>computePackageAndClassDependencies: (in category 'private - dependencies') -----<br>+ computePackageAndClassDependencies: pkgName<br>+        "Compute the dependencies for the given package"<br>+   | packageInfo |<br>+      classDeps := Dictionary new.<br>+         packageDeps := Dictionary new.<br>+       pkgName ifNil: [^ self].<br>+     packageInfo := PackageOrganizer default <br>+             packageNamed: pkgName <br>+               ifAbsent:["unloaded" ^ self]. <br>+             <br>+     self <br>+                computeClassDependenciesFor: packageInfo;<br>+            computePackageDependencies.<br>+ <br>+      (packageDeps removeKey: pkgName ifAbsent: [#()]) do: [:each |<br>+                classDeps removeKey: each ifAbsent: []].!<br><br>Item was added:<br>+ ----- Method: DependencyBrowser>>computePackageDependencies (in category 'private - dependencies') -----<br>+ computePackageDependencies<br>+         <br>+     classDeps keys do:[:className| | aClass pkg |<br>+                aClass := Smalltalk classNamed: className.<br>+           pkg := aClass ifNil: [nil] ifNotNil: [PackageOrganizer default packageOfClass: aClass ifNone:[nil]].<br>+                 pkg <br>+                         ifNil:[<br>+                              Transcript cr; show: 'WARNING: No package for ', className.<br>+                          (classDeps removeKey: className) do:[:each| Transcript crtab; show: each]]<br>+                   ifNotNil:[<br>+                           (packageDeps at: pkg name ifAbsentPut:[OrderedCollection new]) add: className]].!<br><br>Item was removed:<br>- ----- Method: DependencyBrowser>>computePackageDependencies: (in category 'package deps') -----<br>- computePackageDependencies: pkgName<br>-       "Compute the dependencies for the given package"<br>-   | pi |<br>-       classDeps := Dictionary new.<br>-         packageDeps := Dictionary new.<br>-       pkgName ifNil:[^self].<br>-       pi := PackageOrganizer default packageNamed: pkgName ifAbsent:[^self]. "unloaded"<br>-  pi classes do:[:pkgClass |<br>-           (classDeps at: (pkgClass superclass ifNil:[ProtoObject]) name<br>-                        ifAbsentPut:[OrderedCollection new]) add: <br>-                           (MethodReference class: pkgClass selector: #Definition).<br>-             pkgClass sharedPools do: [:sharedPool |<br>-                      sharedPool isBehavior ifTrue: [<br>-                              (classDeps at: sharedPool name<br>-                                       ifAbsentPut:[OrderedCollection new]) add: <br>-                                           (MethodReference class: pkgClass selector: #Definition)]]].<br>- <br>-      pi coreMethods do:[:mref| <br>-           mref compiledMethod allLiteralsDo:[:lit |<br>-                    (lit isVariableBinding and: [lit value isBehavior]) ifTrue:[<br>-                                 (classDeps at: lit value name ifAbsentPut:[OrderedCollection new])<br>-                                   add: mref]]].<br>- <br>-    pi extensionMethods do:[:mref|<br>-               (classDeps at: mref actualClass name ifAbsentPut: [OrderedCollection new])<br>-                   add: mref].<br>- <br>-      classDeps keys do:[:className| | aClass pkg |<br>-                aClass := Smalltalk classNamed: className.<br>-           pkg := aClass ifNil: [nil] ifNotNil: [PackageOrganizer default packageOfClass: aClass ifNone:[nil]].<br>-                 pkg ifNil:[<br>-                  Transcript cr; show: 'WARNING: No package for ', className.<br>-                  (classDeps removeKey: className) do:[:each| Transcript crtab; show: each].<br>-           ] ifNotNil:[<br>-                         (packageDeps at: pkg name ifAbsentPut:[OrderedCollection new]) add: className.<br>-               ].<br>-   ].<br>- <br>-       (packageDeps removeKey: pkgName ifAbsent:[#()]) do:[:each|<br>-           classDeps removeKey: each ifAbsent:[].<br>-       ].!<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>packageDeps (in category 'package dependencies') -----<br>- ----- Method: DependencyBrowser>>packageDeps (in category 'package deps') -----<br>  packageDeps<br>     "Package dependencies for the currently selected package"<br>   packageDeps ifNil:[<br>           packageDeps := Dictionary new.<br>                Cursor wait showWhile:[<br>+                      self computePackageAndClassDependencies: self packageListSelection.<br>-                  self computePackageDependencies: self packageListSelection.<br>           ].<br>    ].<br>    ^packageDeps keys sort!<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>packageDepsIndex (in category 'package dependencies') -----<br>- ----- Method: DependencyBrowser>>packageDepsIndex (in category 'package deps') -----<br>  packageDepsIndex<br>          "Current package dependencies selection"<br>    ^packageDepsIndex ifNil:[0]!<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>packageDepsIndex: (in category 'package dependencies') -----<br>- ----- Method: DependencyBrowser>>packageDepsIndex: (in category 'package deps') -----<br>  packageDepsIndex: aNumber<br>          "Current package dependencies selection"<br>    packageDepsIndex := aNumber.<br>          self changed: #packageDepsIndex.<br>      <br>      classDepsList := nil.<br>         self changed: #classDepsList.<br>         self classDepsIndex: (aNumber = 0 ifTrue: [0] ifFalse: [1]).<br>  !<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>packageDepsList (in category 'package dependencies') -----<br>- ----- Method: DependencyBrowser>>packageDepsList (in category 'package deps') -----<br>  packageDepsList<br>   "Package dependencies for the currently selected package"<br>   <br>      | checkDef checkExt |<br>         checkDef := [:mref | mref selector = #Definition].<br>    checkExt := [:mref | mref category notNil and: [mref category first = $*]].<br>   <br>      ^ packageDepsList ifNil: [<br>            packageDepsList := self packageDeps.<br>                  packageDepsList := packageDepsList collect: [:packageName |<br>                   String streamContents: [:label |<br>                              label nextPutAll: packageName.<br>                                (self depsForPackageNamed: packageName allSatisfy: checkDef)<br>                                          ifTrue: [label nextPutAll: ' (defs only)']<br>                                    ifFalse: [(self depsForPackageNamed: packageName allSatisfy: checkExt)<br>                                                ifTrue: [label nextPutAll: ' *exts only']<br>                                             ifFalse: [<br>                                                    (self depsForPackageNamed: packageName anySatisfy: checkDef)<br>                                                                  ifTrue: [label nextPutAll: ' ()'].<br>                                                    (self depsForPackageNamed: packageName anySatisfy: checkExt)<br>                                                                  ifTrue: [label nextPutAll: ' *']]]]]]!<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>packageDepsMenu: (in category 'package dependencies') -----<br>- ----- Method: DependencyBrowser>>packageDepsMenu: (in category 'package deps') -----<br>  packageDepsMenu: aMenu<br>     ^aMenu!<br><br>Item was changed:<br>+ ----- Method: DependencyBrowser>>packageDepsSelection (in category 'package dependencies') -----<br>- ----- Method: DependencyBrowser>>packageDepsSelection (in category 'package deps') -----<br>  packageDepsSelection<br>      "Current package dependencies selection"<br>    ^(self packageDepsIndex between: 1 and: self packageDeps size)<br>                ifTrue:[self packageDeps at: self packageDepsIndex]!<br><br>Item was changed:<br>  ----- Method: DependencyBrowser>>selectedMessage (in category 'contents') -----<br>  selectedMessage<br>         "Source code for currently selected message"<br>        | className methodName mref |<br>         className := self classListSelection.<br>         methodName := self messageListSelection.<br>      mref := (classDeps at: self classDepsSelection ifAbsent:[#()])<br>                detect:[:mr| mr actualClass name = className <br>                                                 and:[mr methodSymbol = methodName]]<br>           ifNone:[nil].<br>+        mref ifNil:[^ self class comment].<br>+   mref methodSymbol == #Definition ifTrue:[^ mref actualClass definition].<br>-     mref ifNil:[^self class comment].<br>-    mref methodSymbol == #Definition ifTrue:[^mref actualClass definition].<br>       ^mref sourceCode!<br><br><br></div></blockquote>
                                        </div></body>