/
RBReplaceMessageSendTransformation.class.st
174 lines (147 loc) · 4.81 KB
/
RBReplaceMessageSendTransformation.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
"
I'm a transformation replaces one message send by another one.
As such I cannot garantee anything about behavior preservation.
The new method's name can have a different number of arguments than the original method,
if it has more arguments a list of initializers will be needed for them.
All senders of this method are changed by the other.
### Example
```
(RBReplaceMessageSendTransformation
model: model
replaceMethod: #anInstVar:
in: RBBasicLintRuleTestData
to: #newResultClass:
permutation: (1 to: 1)
inAllClasses: true) execute
```
"
Class {
#name : #RBReplaceMessageSendTransformation,
#superclass : #RBChangeMethodNameRefactoring,
#instVars : [
'replaceInAllClasses',
'initializers'
],
#category : #'Refactoring-Core-Refactorings'
}
{ #category : #accessing }
RBReplaceMessageSendTransformation class >> kind [
^ 'Transformation'
]
{ #category : #'instance creation' }
RBReplaceMessageSendTransformation class >> model: aRBSmalltalk replaceMethod: aSelector in: aClass to: newSelector permutation: aMap [
^ self new
model: aRBSmalltalk;
replaceCallMethod: aSelector
in: aClass
to: newSelector
permutation: aMap;
yourself
]
{ #category : #'instance creation' }
RBReplaceMessageSendTransformation class >> model: aRBSmalltalk replaceMethod: aSelector in: aClass to: newSelector permutation: aMap inAllClasses: aBoolean [
^ self new
model: aRBSmalltalk;
replaceCallMethod: aSelector
in: aClass
to: newSelector
permutation: aMap
inAllClasses: aBoolean;
yourself
]
{ #category : #'instance creation' }
RBReplaceMessageSendTransformation class >> replaceCallMethod: aSelector in: aClass to: newSelector permutation: aMap [
^self new
replaceCallMethod: aSelector
in: aClass
to: newSelector
permutation: aMap
]
{ #category : #'instance creation' }
RBReplaceMessageSendTransformation class >> replaceCallMethod: aSelector in: aClass to: newSelector permutation: aMap inAllClasses: aBoolean [
^self new
replaceCallMethod: aSelector
in: aClass
to: newSelector
permutation: aMap
inAllClasses: aBoolean
]
{ #category : #accessing }
RBReplaceMessageSendTransformation >> initializers [
^ initializers ifNil: [ initializers := { } ]
]
{ #category : #accessing }
RBReplaceMessageSendTransformation >> initializers: anObject [
initializers := anObject
]
{ #category : #private }
RBReplaceMessageSendTransformation >> newSelectorString [
| stream keywords |
stream := WriteStream on: String new.
permutation ifEmpty: [ stream nextPutAll: newSelector ].
keywords := newSelector keywords.
permutation
doWithIndex:
[:each :index |
stream nextPutAll: (keywords at: index).
each < 0
ifTrue:
[stream
nextPut: $(;
nextPutAll: (initializers at: each abs);
nextPut: $)]
ifFalse:
[stream
nextPutAll: ' ``@arg';
nextPutAll: each printString].
stream nextPut: $ ].
^stream contents
]
{ #category : #transforming }
RBReplaceMessageSendTransformation >> parseTreeRewriter [
| rewriteRule oldString newString |
rewriteRule := self parseTreeRewriterClass new.
oldString := self buildSelectorString: oldSelector.
newString := self newSelectorString.
rewriteRule
replace: '``@object ' , oldString
with: '``@object ' , newString.
^ rewriteRule
]
{ #category : #preconditions }
RBReplaceMessageSendTransformation >> preconditions [
| conditions |
conditions := (RBCondition withBlock: [
oldSelector numArgs < newSelector numArgs ifTrue: [
oldSelector numArgs + self initializers size
= newSelector numArgs ifFalse: [
self refactoringFailure:
'You don''t have the necessary initializers to replace senders.' ] ].
true ])
& (RBCondition definesSelector: oldSelector in: class)
& (RBCondition definesSelector: newSelector in: class).
"This is unclear that the targeting method should already be defined."
^ conditions
]
{ #category : #initialization }
RBReplaceMessageSendTransformation >> replaceCallMethod: aSelector in: aClass to: newSel permutation: aMap [
oldSelector := aSelector asSymbol.
newSelector := newSel asSymbol.
class := self classObjectFor: aClass.
permutation := aMap.
]
{ #category : #initialization }
RBReplaceMessageSendTransformation >> replaceCallMethod: aSelector in: aClass to: newSel permutation: aMap inAllClasses: aBoolean [
self replaceCallMethod: aSelector in: aClass to: newSel permutation: aMap.
replaceInAllClasses := aBoolean.
]
{ #category : #accessing }
RBReplaceMessageSendTransformation >> replaceInAllClasses [
^ replaceInAllClasses ifNil: [ replaceInAllClasses := false ]
]
{ #category : #transforming }
RBReplaceMessageSendTransformation >> transform [
self replaceInAllClasses
ifTrue: [ self renameMessageSends ]
ifFalse: [ self renameMessageSendsIn: {class} ]
]