Finding RB parse tree rule for replacements

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Finding RB parse tree rule for replacements

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

Reply | Threaded
Open this post in threaded view
|

Re: Finding RB parse tree rule for replacements

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

Reply | Threaded
Open this post in threaded view
|

Re: Finding RB parse tree rule for replacements

hernanmd
2011/1/12 Lukas Renggli <[hidden email]>:
>> 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!

RBClassMNU.log (43K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Finding RB parse tree rule for replacements

Lukas Renggli
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
<[hidden email]> wrote:

> 2011/1/12 Lukas Renggli <[hidden email]>:
>>> 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

Reply | Threaded
Open this post in threaded view
|

Re: Finding RB parse tree rule for replacements

hernanmd
2011/1/12 Lukas Renggli <[hidden email]>:
> 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
> <[hidden email]> wrote:
>> 2011/1/12 Lukas Renggli <[hidden email]>:
>>>> 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
>
>

MyCategory.st (528 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Finding RB parse tree rule for replacements

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

Reply | Threaded
Open this post in threaded view
|

Re: Finding RB parse tree rule for replacements

hernanmd
2011/1/12 Lukas Renggli <[hidden email]>:

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

Reply | Threaded
Open this post in threaded view
|

Re: Finding RB parse tree rule for replacements

Lukas Renggli
> 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.

Refactoring Scope -> Selection

Lukas

--
Lukas Renggli
www.lukas-renggli.ch

Reply | Threaded
Open this post in threaded view
|

Re: Finding RB parse tree rule for replacements

Stéphane Ducasse
In reply to this post by Lukas Renggli
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
>