/
RBSelectorEnvironment.class.st
356 lines (318 loc) · 10.7 KB
/
RBSelectorEnvironment.class.st
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
"
I am a RBBrowserEnvironment for a set of selectors.
Usually I am constructed as a result of a query on another environment:
env referencesTo:#aselector -> a RBSelectorEnvironments.
"
Class {
#name : #RBSelectorEnvironment,
#superclass : #RBBrowserEnvironmentWrapper,
#instVars : [
'classSelectors',
'metaClassSelectors'
],
#category : #'Refactoring-Environment'
}
{ #category : #'instance creation' }
RBSelectorEnvironment class >> implementorsMatching: aString [
^ self
implementorsMatching: aString
in: self default
]
{ #category : #'instance creation' }
RBSelectorEnvironment class >> implementorsMatching: aString in: anEnvironment [
| classDict metaDict |
classDict := IdentityDictionary new.
metaDict := IdentityDictionary new.
anEnvironment classesDo: [ :class |
| selectors |
selectors := IdentitySet new.
anEnvironment selectorsForClass: class
do: [ :each | (aString match: each) ifTrue: [ selectors add: each ] ].
selectors isEmpty ifFalse: [
class isMeta
ifTrue: [ metaDict at: class soleInstance name put: selectors ]
ifFalse: [ classDict at: class name put: selectors ] ] ].
^ (self onEnvironment: anEnvironment)
classSelectors: classDict metaClassSelectors: metaDict;
label: 'Implementors of ' , aString;
yourself
]
{ #category : #'instance creation' }
RBSelectorEnvironment class >> implementorsOf: aSelector [
^ self
implementorsOf: aSelector
in: self default
]
{ #category : #'instance creation' }
RBSelectorEnvironment class >> implementorsOf: aSelector in: anEnvironment [
| classDict metaDict selectors |
classDict := IdentityDictionary new.
metaDict := IdentityDictionary new.
selectors := IdentitySet with: aSelector.
anEnvironment classesDo: [ :class |
((class includesLocalSelector: aSelector) and: [ anEnvironment includesSelector: aSelector in: class ])
ifTrue: [
class isMeta
ifTrue: [ metaDict at: class soleInstance name put: selectors copy ]
ifFalse: [ classDict at: class name put: selectors copy ] ] ].
^ (self onEnvironment: anEnvironment)
classSelectors: classDict metaClassSelectors: metaDict;
label: 'Implementors of ' , aSelector;
yourself
]
{ #category : #'instance creation' }
RBSelectorEnvironment class >> matches: aString [
^ self
matches: aString
in: self default
]
{ #category : #'instance creation' }
RBSelectorEnvironment class >> matches: aString in: anEnvironment [
| newEnvironment |
newEnvironment := (self onEnvironment: anEnvironment)
label: 'Matching: ' , aString;
searchStrings: (Array with: aString);
yourself.
anEnvironment classesAndSelectorsDo: [ :class :selector |
| method |
method := class compiledMethodAt: selector.
method allLiterals do: [ :literal |
literal isString ifTrue: [
(aString match: literal)
ifTrue: [ newEnvironment addClass: class selector: selector ] ] ] ].
^ newEnvironment
]
{ #category : #'instance creation' }
RBSelectorEnvironment class >> onMethods: selectorCollection forClass: aClass [
^ self
onMethods: selectorCollection
forClass: aClass
in: self default
]
{ #category : #'instance creation' }
RBSelectorEnvironment class >> onMethods: selectorCollection forClass: aClass in: anEnvironment [
| environemnt |
environemnt := self onEnvironment: anEnvironment.
selectorCollection do: [ :each | environemnt addClass: aClass selector: each ].
^ environemnt
]
{ #category : #'instance creation' }
RBSelectorEnvironment class >> referencesTo: aLiteral [
^ self
referencesTo: aLiteral
in: self default
]
{ #category : #'instance creation' }
RBSelectorEnvironment class >> referencesTo: aLiteral in: anEnvironment [
| classDict literalPrintString |
literalPrintString := aLiteral isVariableBinding
ifTrue: [ aLiteral key asString ]
ifFalse: [
aLiteral isString
ifTrue: [ aLiteral ]
ifFalse: [ aLiteral printString ] ].
classDict := IdentityDictionary new.
anEnvironment classesDo: [ :class |
| selectors |
selectors := (class thoroughWhichSelectorsReferTo: aLiteral)
select: [ :selector | anEnvironment includesSelector: selector in: class ].
selectors isEmpty
ifFalse: [ classDict at: class put: selectors asIdentitySet ] ].
^ (self onEnvironment: anEnvironment)
on: classDict;
label: 'References to: ' , literalPrintString;
searchStrings: (Array with: literalPrintString);
yourself
]
{ #category : #adding }
RBSelectorEnvironment >> addClass: aClass [
aClass isMeta
ifTrue: [ metaClassSelectors at: aClass soleInstance name put: aClass selectors asIdentitySet ]
ifFalse: [ classSelectors at: aClass name put: aClass selectors asIdentitySet ]
]
{ #category : #adding }
RBSelectorEnvironment >> addClass: aClass selector: aSymbol [
(aClass isMeta
ifTrue: [ metaClassSelectors at: aClass soleInstance name ifAbsentPut: [ IdentitySet new ] ]
ifFalse: [ classSelectors at: aClass name ifAbsentPut: [ IdentitySet new ] ])
add: aSymbol
]
{ #category : #adding }
RBSelectorEnvironment >> addMethod: aMethod [
"this is a method to improve addition of methods, as class and selector data can be retrieved from a single compiled method"
self addClass: aMethod methodClass selector: aMethod selector
]
{ #category : #accessing }
RBSelectorEnvironment >> asSelectorEnvironment [
^ self
]
{ #category : #'accessing-classes' }
RBSelectorEnvironment >> classNames [
^ IdentitySet new
addAll: classSelectors keys;
addAll: metaClassSelectors keys;
yourself
]
{ #category : #'initialize-release' }
RBSelectorEnvironment >> classSelectors: classSelectorDictionary metaClassSelectors: metaClassSelectorDictionary [
classSelectors := classSelectorDictionary.
metaClassSelectors := metaClassSelectorDictionary
]
{ #category : #initialization }
RBSelectorEnvironment >> classes: classArray metaClasses: metaArray [
"Used to recreate an environment from its storeString"
classSelectors := IdentityDictionary new.
metaClassSelectors := IdentityDictionary new.
classArray
do: [ :each | classSelectors at: each first put: each last asIdentitySet ].
metaArray
do: [ :each | metaClassSelectors at: each first put: each last asIdentitySet ]
]
{ #category : #'accessing-classes' }
RBSelectorEnvironment >> classesDo: aBlock [
classSelectors keysDo: [ :each |
| class |
class := self systemDictionary at: each ifAbsent: [ nil ].
(class notNil and: [ environment includesClass: class ])
ifTrue: [ aBlock value: class ] ].
metaClassSelectors keysDo: [ :each |
| class |
class := self systemDictionary at: each ifAbsent: [ nil ].
(class notNil and: [ environment includesClass: class class ])
ifTrue: [ aBlock value: class class ] ]
]
{ #category : #private }
RBSelectorEnvironment >> defaultLabel [
^'some methods'
]
{ #category : #testing }
RBSelectorEnvironment >> includesCategory: aCategory [
^(super includesCategory: aCategory) and:
[(self classNamesFor: aCategory) anySatisfy:
[:className |
(classSelectors includesKey: className)
or: [metaClassSelectors includesKey: className]]]
]
{ #category : #testing }
RBSelectorEnvironment >> includesClass: aClass [
^(self privateSelectorsForClass: aClass) isEmpty not
and: [super includesClass: aClass]
]
{ #category : #testing }
RBSelectorEnvironment >> includesProtocol: aProtocol in: aClass [
^(super includesProtocol: aProtocol in: aClass)
and: [(environment selectorsFor: aProtocol in: aClass)
anySatisfy: [:aSelector | self privateIncludesSelector: aSelector inClass: aClass]]
]
{ #category : #testing }
RBSelectorEnvironment >> includesSelector: aSelector in: aClass [
^(environment includesSelector: aSelector in: aClass)
and: [self privateIncludesSelector: aSelector inClass: aClass]
]
{ #category : #initialization }
RBSelectorEnvironment >> initialize [
super initialize.
classSelectors := IdentityDictionary new.
metaClassSelectors := IdentityDictionary new
]
{ #category : #testing }
RBSelectorEnvironment >> isEmpty [
^classSelectors isEmpty and: [metaClassSelectors isEmpty]
]
{ #category : #testing }
RBSelectorEnvironment >> isSelectorEnvironment [
^ true
]
{ #category : #initialization }
RBSelectorEnvironment >> on: aDictionary [
aDictionary keysAndValuesDo: [ :class :selectors |
class isMeta
ifTrue: [ metaClassSelectors at: class soleInstance name put: selectors asIdentitySet ]
ifFalse: [ classSelectors at: class name put: selectors asIdentitySet ] ]
]
{ #category : #accessing }
RBSelectorEnvironment >> packages [
"Check that packages have really class and selector included."
| pSet |
pSet := Set new.
self classes
do: [ :each |
each packages
do: [ :p |
self
selectorsForClass: each
do: [ :s |
(p includesSelector: s ofClass: each)
ifTrue: [ pSet add: p ] ] ] ].
^ pSet
]
{ #category : #copying }
RBSelectorEnvironment >> postCopy [
| newDict |
super postCopy.
newDict := classSelectors copy.
newDict keysAndValuesDo: [:key :value | newDict at: key put: value copy].
classSelectors := newDict.
newDict := metaClassSelectors copy.
newDict keysAndValuesDo: [:key :value | newDict at: key put: value copy].
metaClassSelectors := newDict
]
{ #category : #private }
RBSelectorEnvironment >> privateIncludesSelector: aSelector inClass: aClass [
^(self privateSelectorsForClass: aClass) includes: aSelector
]
{ #category : #private }
RBSelectorEnvironment >> privateSelectorsForClass: aClass [
^aClass isMeta
ifTrue: [metaClassSelectors at: aClass soleInstance name ifAbsent: [#()]]
ifFalse: [classSelectors at: aClass name ifAbsent: [#()]]
]
{ #category : #removing }
RBSelectorEnvironment >> removeClass: aClass [
aClass isMeta
ifTrue: [metaClassSelectors removeKey: aClass soleInstance name ifAbsent: []]
ifFalse: [classSelectors removeKey: aClass name ifAbsent: []]
]
{ #category : #removing }
RBSelectorEnvironment >> removeClass: aClass selector: aSelector [
(aClass isMeta
ifTrue: [metaClassSelectors at: aClass soleInstance name ifAbsent: [^self]]
ifFalse: [classSelectors at: aClass name ifAbsent: [^self]])
remove: aSelector
ifAbsent: []
]
{ #category : #accessing }
RBSelectorEnvironment >> selectorsForClass: aClass do: aBlock [
^(self privateSelectorsForClass: aClass)
do: [:each | (aClass includesSelector: each) ifTrue: [aBlock value: each]]
]
{ #category : #printing }
RBSelectorEnvironment >> storeOn: aStream [
| classBlock |
aStream
nextPutAll: '((';
nextPutAll: self class name;
nextPutAll: ' onEnvironment: '.
environment storeOn: aStream.
aStream
nextPut: $);
nextPutAll: ' classes: #('.
classBlock :=
[:key :value |
aStream
nextPutAll: '#(';
nextPutAll: key;
nextPutAll: ' #('.
value do:
[:each |
aStream
nextPutAll: each;
nextPut: $ ].
aStream
nextPutAll: '))';
cr].
classSelectors keysAndValuesDo: classBlock.
aStream nextPutAll: ') metaClasses: #('.
metaClassSelectors keysAndValuesDo: classBlock.
aStream nextPutAll: '))'
]