|  | @@ -0,0 +1,318 @@
 | 
	
		
			
				|  |  | +Smalltalk current createPackage: 'Helios-References'!
 | 
	
		
			
				|  |  | +HLWidget subclass: #HLReferences
 | 
	
		
			
				|  |  | +	instanceVariableNames: 'model sendersListWidget implementorsListWidget classReferencesListWidget regexpListWidget sourceCodeWidget'
 | 
	
		
			
				|  |  | +	package: 'Helios-References'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferences methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +classReferencesListWidget
 | 
	
		
			
				|  |  | +	^ classReferencesListWidget ifNil: [
 | 
	
		
			
				|  |  | +      	classReferencesListWidget := HLClassReferencesListWidget on: self model.
 | 
	
		
			
				|  |  | +		classReferencesListWidget next: self regexpListWidget ]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +implementorsListWidget
 | 
	
		
			
				|  |  | +	^ implementorsListWidget ifNil: [
 | 
	
		
			
				|  |  | +      	implementorsListWidget := HLImplementorsListWidget on: self model.
 | 
	
		
			
				|  |  | +		implementorsListWidget next: self classReferencesListWidget ]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +model
 | 
	
		
			
				|  |  | +	^ model ifNil: [
 | 
	
		
			
				|  |  | +		model := (HLReferencesModel new
 | 
	
		
			
				|  |  | +			environment: self manager environment;
 | 
	
		
			
				|  |  | +			yourself) ]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +model: aModel
 | 
	
		
			
				|  |  | +	model := aModel
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +regexpListWidget
 | 
	
		
			
				|  |  | +	^ regexpListWidget ifNil: [
 | 
	
		
			
				|  |  | +      	regexpListWidget := HLRegexpListWidget on: self model.
 | 
	
		
			
				|  |  | +		regexpListWidget next: self sourceCodeWidget ]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +sendersListWidget
 | 
	
		
			
				|  |  | +	^ sendersListWidget ifNil: [
 | 
	
		
			
				|  |  | +      	sendersListWidget := HLSendersListWidget on: self model.
 | 
	
		
			
				|  |  | +		sendersListWidget next: self implementorsListWidget ]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +sourceCodeWidget
 | 
	
		
			
				|  |  | +	^ sourceCodeWidget ifNil: [
 | 
	
		
			
				|  |  | +      	sourceCodeWidget := HLSourceCodeWidget on: self model ]
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferences methodsFor: 'actions'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +open
 | 
	
		
			
				|  |  | +	HLManager current addTab: (HLTab on: self labelled: self class tabLabel)
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +search: aString
 | 
	
		
			
				|  |  | +	self model search: aString
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferences methodsFor: 'rendering'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +renderContentOn: html
 | 
	
		
			
				|  |  | +	html with: (HLContainer with: (HLHorizontalSplitter 
 | 
	
		
			
				|  |  | +    	with: (HLVerticalSplitter
 | 
	
		
			
				|  |  | +        	with: (HLVerticalSplitter
 | 
	
		
			
				|  |  | +            	with: self sendersListWidget
 | 
	
		
			
				|  |  | +                with: self implementorsListWidget)
 | 
	
		
			
				|  |  | +            with: (HLVerticalSplitter
 | 
	
		
			
				|  |  | +            	with: self classReferencesListWidget
 | 
	
		
			
				|  |  | +                with: self regexpListWidget)) 
 | 
	
		
			
				|  |  | +        with: self sourceCodeWidget)).
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	self sendersListWidget focus
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferences class methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +tabLabel
 | 
	
		
			
				|  |  | +	^ 'References'
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +tabPriority
 | 
	
		
			
				|  |  | +	^ 100
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferences class methodsFor: 'testing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +canBeOpenAsTab
 | 
	
		
			
				|  |  | +	^ false
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +HLNavigationListWidget subclass: #HLReferencesListWidget
 | 
	
		
			
				|  |  | +	instanceVariableNames: 'model'
 | 
	
		
			
				|  |  | +	package: 'Helios-References'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferencesListWidget methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +label
 | 
	
		
			
				|  |  | +	^ 'List'
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +model
 | 
	
		
			
				|  |  | +	^ model
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +model: aModel
 | 
	
		
			
				|  |  | +	model := aModel.
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	self observeModel
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferencesListWidget methodsFor: 'actions'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +observeModel
 | 
	
		
			
				|  |  | +	self model announcer
 | 
	
		
			
				|  |  | +		on: HLSearchReferences
 | 
	
		
			
				|  |  | +		do: [ :ann | self onSearchReferences: ann searchString ]
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferencesListWidget methodsFor: 'reactions'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +onSearchReferences: aString
 | 
	
		
			
				|  |  | +	self subclassResponsibility
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferencesListWidget methodsFor: 'rendering'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +renderContentOn: html
 | 
	
		
			
				|  |  | +	self renderHeadOn: html.	
 | 
	
		
			
				|  |  | +	super renderContentOn: html
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +renderHeadOn: html
 | 
	
		
			
				|  |  | +	html div 
 | 
	
		
			
				|  |  | +		class: 'list-label';
 | 
	
		
			
				|  |  | +		with: [
 | 
	
		
			
				|  |  | +			html with: self label ]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +renderItemLabel: aMethod on: html
 | 
	
		
			
				|  |  | +	html with: aMethod methodClass name, ' >> #', aMethod selector
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferencesListWidget class methodsFor: 'instance creation'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +on: aModel
 | 
	
		
			
				|  |  | +	^ self new 
 | 
	
		
			
				|  |  | +		model: aModel; 
 | 
	
		
			
				|  |  | +		yourself
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +HLReferencesListWidget subclass: #HLClassReferencesListWidget
 | 
	
		
			
				|  |  | +	instanceVariableNames: ''
 | 
	
		
			
				|  |  | +	package: 'Helios-References'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLClassReferencesListWidget methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +label
 | 
	
		
			
				|  |  | +	^ 'Class references'
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLClassReferencesListWidget methodsFor: 'reactions'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +onSearchReferences: aString
 | 
	
		
			
				|  |  | +	self selectItem: nil.
 | 
	
		
			
				|  |  | +	self items: (self model classReferencesOf: aString).
 | 
	
		
			
				|  |  | +	self refresh
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +HLReferencesListWidget subclass: #HLImplementorsListWidget
 | 
	
		
			
				|  |  | +	instanceVariableNames: ''
 | 
	
		
			
				|  |  | +	package: 'Helios-References'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLImplementorsListWidget methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +label
 | 
	
		
			
				|  |  | +	^ 'Implementors'
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLImplementorsListWidget methodsFor: 'reactions'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +onSearchReferences: aString
 | 
	
		
			
				|  |  | +	self selectItem: nil.
 | 
	
		
			
				|  |  | +	self items: (self model implementorsOf: aString).
 | 
	
		
			
				|  |  | +	self refresh
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +HLReferencesListWidget subclass: #HLRegexpListWidget
 | 
	
		
			
				|  |  | +	instanceVariableNames: ''
 | 
	
		
			
				|  |  | +	package: 'Helios-References'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLRegexpListWidget methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +label
 | 
	
		
			
				|  |  | +	^ 'Source search'
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLRegexpListWidget methodsFor: 'reactions'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +onSearchReferences: aString
 | 
	
		
			
				|  |  | +	self selectItem: nil.
 | 
	
		
			
				|  |  | +	self items: (self model regexpReferencesOf: aString).
 | 
	
		
			
				|  |  | +	self refresh
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +HLReferencesListWidget subclass: #HLSendersListWidget
 | 
	
		
			
				|  |  | +	instanceVariableNames: ''
 | 
	
		
			
				|  |  | +	package: 'Helios-References'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLSendersListWidget methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +label
 | 
	
		
			
				|  |  | +	^ 'Senders'
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLSendersListWidget methodsFor: 'reactions'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +onSearchReferences: aString
 | 
	
		
			
				|  |  | +	self selectItem: nil.
 | 
	
		
			
				|  |  | +	self items: (self model sendersOf: aString).
 | 
	
		
			
				|  |  | +	self refresh
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +HLModel subclass: #HLReferencesModel
 | 
	
		
			
				|  |  | +	instanceVariableNames: 'methodsCache classesAndMetaclassesCache'
 | 
	
		
			
				|  |  | +	package: 'Helios-References'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferencesModel methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +allMethods
 | 
	
		
			
				|  |  | +	^ self methodsCache
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +allSelectors
 | 
	
		
			
				|  |  | +	^ (self allMethods 
 | 
	
		
			
				|  |  | +		collect: [ :each | each selector ])
 | 
	
		
			
				|  |  | +		asSet
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +classReferencesOf: aString
 | 
	
		
			
				|  |  | +	"Answer all methods referencing the class named aString"
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	| references |
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	references := OrderedCollection new.
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	self classesAndMetaclasses do: [ :each |
 | 
	
		
			
				|  |  | +		each methodDictionary values do: [ :method |
 | 
	
		
			
				|  |  | +			(method referencedClasses includes: aString) ifTrue: [
 | 
	
		
			
				|  |  | +				references add: method ] ] ].
 | 
	
		
			
				|  |  | +				
 | 
	
		
			
				|  |  | +	^ references
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +classesAndMetaclasses
 | 
	
		
			
				|  |  | +	^ self classesAndMetaclassesCache
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +implementorsOf: aString
 | 
	
		
			
				|  |  | +	^ self allMethods select: [ :each |
 | 
	
		
			
				|  |  | +		each selector = aString ]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +regexpReferencesOf: aString
 | 
	
		
			
				|  |  | +	^ self allMethods select: [ :each |
 | 
	
		
			
				|  |  | +		each source match: aString ]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +sendersOf: aString
 | 
	
		
			
				|  |  | +	^ self allMethods select: [ :each |
 | 
	
		
			
				|  |  | +		each messageSends includes: aString ]
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferencesModel methodsFor: 'actions'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +search: aString
 | 
	
		
			
				|  |  | +	self updateCaches.
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	self announcer announce: (HLSearchReferences new
 | 
	
		
			
				|  |  | +		searchString: aString;
 | 
	
		
			
				|  |  | +		yourself)
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!HLReferencesModel methodsFor: 'cache'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +classesAndMetaclassesCache
 | 
	
		
			
				|  |  | +	classesAndMetaclassesCache ifNil: [ self updateClassesAndMetaclassesCache ].
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	^ classesAndMetaclassesCache
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +methodsCache
 | 
	
		
			
				|  |  | +	methodsCache ifNil: [ self updateMethodsCache ].
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	^ methodsCache
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +updateCaches
 | 
	
		
			
				|  |  | +	self 
 | 
	
		
			
				|  |  | +		updateClassesAndMetaclassesCache;
 | 
	
		
			
				|  |  | +		updateMethodsCache
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +updateClassesAndMetaclassesCache
 | 
	
		
			
				|  |  | +	classesAndMetaclassesCache := self environment classes 
 | 
	
		
			
				|  |  | +		inject: OrderedCollection new 
 | 
	
		
			
				|  |  | +		into: [ :acc :each |
 | 
	
		
			
				|  |  | +			acc 
 | 
	
		
			
				|  |  | +				add: each; 
 | 
	
		
			
				|  |  | +				add: each class;
 | 
	
		
			
				|  |  | +				yourself ]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +updateMethodsCache
 | 
	
		
			
				|  |  | +	methodsCache := self classesAndMetaclasses
 | 
	
		
			
				|  |  | +		inject: OrderedCollection new
 | 
	
		
			
				|  |  | +		into: [ :acc :each |
 | 
	
		
			
				|  |  | +			acc, each methods ]
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 |