Finding RB parse tree rule for replacements
Recently I wanted to replace all method sends of oldMessage to newMessage in a specific method category in a class, then I wrote this little script I want to share with you: | className realClass replacer category | className := #MyClass. realClass := Smalltalk at: className. category := #accessing. replacer := RBParseTreeRewriter new replace: '`receiver oldMessage' with: '`receiver newMessage'; yourself. (realClass organization listAtCategoryNamed: category) collect: [:sel | | parseTree | parseTree := ( realClass >> sel) parseTree. (replacer executeTree: parseTree) ifTrue: [ realClass compile: replacer tree newSource " [1] " ] ] Now some questions: 1) In [1] "( RBClass existingNamed: className ) compileTree: replacer tree" would be more appropiate? I get a MNU when evaluated with latest AST/Refactoring. 2) The above script have some problems, if you want to get replaced 'this is a string' asString. to 'this is a string' asText it won't match. The same happens with: " self model asString " and other patterns. How to modify the rewriter to match oldMessage/newMessage at any point? i.e. [: tmp | anObject1 blabla1 blabla2 oldMessage blabla3 ] Thanks in advance, -- Hernán Morales Information Technology Manager, Institute of Veterinary Genetics. National Scientific and Technical Research Council (CONICET). La Plata (1900), Buenos Aires, Argentina. Telephone: +54 (0221) 421-1799. Internal: 422 Fax: 425-7980 or 421-1799.
1) In [1] "( RBClass existingNamed: className ) compileTree: replacer tree" would be more appropiate? I get a MNU when evaluated with latest AST/Refactoring.
What kind of MNU?
2) The above script have some problems, if you want to get replaced
'this is a string' asString.
to
'this is a string' asText
it won't match. The same happens with: " self model asString " and other patterns.
`#literal asString
i.e. [: tmp | anObject1 blabla1 blabla2 oldMessage blabla3 ] How to modify the rewriter to match oldMessage/newMessage at any point?
``@obj oldMessage Lukas -- Lukas Renggli www.lukas-renggli.ch
2011/1/12 Lukas Renggli <renggli@gmail.com>:
1) In [1] "( RBClass existingNamed: className ) compileTree: replacer tree" would be more appropiate? I get a MNU when evaluated with latest AST/Refactoring.
What kind of MNU?
Debug log attached
2) The above script have some problems, if you want to get replaced
'this is a string' asString.
to
'this is a string' asText
it won't match. The same happens with: " self model asString " and other patterns.
`#literal asString
i.e. [: tmp | anObject1 blabla1 blabla2 oldMessage blabla3 ] How to modify the rewriter to match oldMessage/newMessage at any point?
``@obj oldMessage
Lukas
Cool, thanks!
The stack-trace and your code snippet does not match. There are no references (and should be no references) to #compileTree: or RBClass in the code you pasted into the mail. The easiest is probably if you use the refactoring tools as integrated into OB. This does all automatically. Lukas On 12 January 2011 08:47, Hernán Morales Durand <hernan.morales@gmail.com> wrote:
2011/1/12 Lukas Renggli <renggli@gmail.com>:
1) In [1] "( RBClass existingNamed: className ) compileTree: replacer tree" would be more appropiate? I get a MNU when evaluated with latest AST/Refactoring.
What kind of MNU?
Debug log attached
2) The above script have some problems, if you want to get replaced
'this is a string' asString.
to
'this is a string' asText
it won't match. The same happens with: " self model asString " and other patterns.
`#literal asString
i.e. [: tmp | anObject1 blabla1 blabla2 oldMessage blabla3 ] How to modify the rewriter to match oldMessage/newMessage at any point?
``@obj oldMessage
Lukas
Cool, thanks!
-- Lukas Renggli www.lukas-renggli.ch
2011/1/12 Lukas Renggli <renggli@gmail.com>:
The stack-trace and your code snippet does not match. There are no references (and should be no references) to #compileTree: or RBClass in the code you pasted into the mail.
The thing was to replace the line marked with [1] as I've commented above. If you file in the attached dummy class and evaluate the following script should be reproduceable: | className realClass replacer category | className := #MyClass. realClass := Smalltalk at: className. category := #accessing. replacer := RBParseTreeRewriter new replace: '`receiver asString' with: '`receiver asText'; yourself. (realClass organization listAtCategoryNamed: category) collect: [:sel | | parseTree | parseTree := ( realClass >> sel) parseTree. (replacer executeTree: parseTree) ifTrue: [ ( RBClass existingNamed: className ) compileTree: replacer tree ] ]
The easiest is probably if you use the refactoring tools as integrated into OB. This does all automatically.
It should be too obvious but I didn't find how. May you comment how to perform the task in the script with OB? Thanks, Hernán
Lukas
On 12 January 2011 08:47, Hernán Morales Durand <hernan.morales@gmail.com> wrote:
2011/1/12 Lukas Renggli <renggli@gmail.com>:
1) In [1] "( RBClass existingNamed: className ) compileTree: replacer tree" would be more appropiate? I get a MNU when evaluated with latest AST/Refactoring.
What kind of MNU?
Debug log attached
2) The above script have some problems, if you want to get replaced
'this is a string' asString.
to
'this is a string' asText
it won't match. The same happens with: " self model asString " and other patterns.
`#literal asString
i.e. [: tmp | anObject1 blabla1 blabla2 oldMessage blabla3 ] How to modify the rewriter to match oldMessage/newMessage at any point?
``@obj oldMessage
Lukas
Cool, thanks!
-- Lukas Renggli www.lukas-renggli.ch
The stack-trace and your code snippet does not match. There are no references (and should be no references) to #compileTree: or RBClass in the code you pasted into the mail.
The thing was to replace the line marked with [1] as I've commented above.
I don't get it, the code you posted looks ok. RBClass is a class private to the framework, you should never need to instantiate it directly. And if you do, only through an instance of RBNamespace that provides a delta to the current system state. In your example you don't need to do that.
The easiest is probably if you use the refactoring tools as integrated into OB. This does all automatically.
It should be too obvious but I didn't find how. May you comment how to perform the task in the script with OB?
1. Select "MyClass" 2. Menu "Refactoring Scope" -> "Class" 3. Menu "Rewrite Code" and fill the template 4. Accept the rewrite expression 5. Review and accept the proposed changes This is also show here in a slightly older version of OB: http://www.lukas-renggli.ch/blog/ob-rb-3 Lukas -- Lukas Renggli www.lukas-renggli.ch
2011/1/12 Lukas Renggli <renggli@gmail.com>:
The stack-trace and your code snippet does not match. There are no references (and should be no references) to #compileTree: or RBClass in the code you pasted into the mail.
The thing was to replace the line marked with [1] as I've commented above.
I don't get it, the code you posted looks ok.
RBClass is a class private to the framework, you should never need to instantiate it directly. And if you do, only through an instance of RBNamespace that provides a delta to the current system state. In your example you don't need to do that.
That's exactly what I wanted to know :)
The easiest is probably if you use the refactoring tools as integrated into OB. This does all automatically.
It should be too obvious but I didn't find how. May you comment how to perform the task in the script with OB?
1. Select "MyClass" 2. Menu "Refactoring Scope" -> "Class" 3. Menu "Rewrite Code" and fill the template 4. Accept the rewrite expression 5. Review and accept the proposed changes
This is also show here in a slightly older version of OB: http://www.lukas-renggli.ch/blog/ob-rb-3
Thanks, just an *idea* you may like: It would be cool to select a method category, then a menu item for having a rewrite to be applied only to that category.
Lukas
-- Lukas Renggli www.lukas-renggli.ch
lukas it would be great if you could write some blog entries on RBWriter and that we turn that into a book chapter. We have powerful tools but only two guys knowing how to use them and this is a pity. Stef On Jan 12, 2011, at 7:08 AM, Lukas Renggli wrote:
1) In [1] "( RBClass existingNamed: className ) compileTree: replacer tree" would be more appropiate? I get a MNU when evaluated with latest AST/Refactoring.
What kind of MNU?
2) The above script have some problems, if you want to get replaced
'this is a string' asString.
to
'this is a string' asText
it won't match. The same happens with: " self model asString " and other patterns.
`#literal asString
i.e. [: tmp | anObject1 blabla1 blabla2 oldMessage blabla3 ] How to modify the rewriter to match oldMessage/newMessage at any point?
``@obj oldMessage
Lukas
-- Lukas Renggli www.lukas-renggli.ch
participants (3)
-
Hernán Morales Durand -
Lukas Renggli -
Stéphane Ducasse