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