Automatic deprecation refactoring

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

Automatic deprecation refactoring

Marcus Denker-4
Hi,


I have dusted off and improved the automatic refactoring of deprecations.

- when the refactoring engine is not present, it falls back to a standard deprecation
- It does not introduce any dependencies (can just be in the Kernel, the only cost is one method of 10 lines).
- It sets the author so it does not require initials
- It refactors ​*only*​ the sending (offending, deprecated) send site. So a second selector that is identical (which might be a different method and not deprecated) will not be affected.

The way to use it is this:

ifNotNilDo: aBlock
    self
        deprecated: 'Please use #ifNotNil: instead'
        transformWith: '`@receiver ifNotNilDo: `@statements' -> '`@receiver ifNotNil: `@statements'.
    ^ aBlock ifNotNil: aBlock


As we try to provide already Lint rules for deprecations (or at least should have..) the amount of additional work is not much.

This is the full implementation:

deprecated: anExplanationString transformWith: aRule
    | rewriteRule method context node |
    context := thisContext sender sender.
    (Smalltalk globals hasClassNamed: #RBParseTreeRewriter)
        ifFalse: [ ^self deprecated: anExplanationString ].
    method := context method.
    node := context sourceNodeExecuted.
    rewriteRule := (Smalltalk globals classNamed: #RBParseTreeRewriter) new replace: aRule key with: aRule value.
    (rewriteRule executeTree: node)
        ifFalse: [ ^ self ].
    node replaceWith: rewriteRule tree.
    Author
        useAuthor: 'AutoDeprecationRefactoring'
        during: [method methodClass compile: method ast formattedCode classified: method protocol]

https://pharo.fogbugz.com/f/cases/18507/

This is *with intention* the absolute “simplest thing that can possibly work”. There is no interactive tool to preview refactoring in interactive
mode, or some way to opt in or out.

The power of things like this comes from actually using them, not from being perfect...

        Marcus
Reply | Threaded
Open this post in threaded view
|

Re: Automatic deprecation refactoring

Guillermo Polito
Hi!

How is this packaged? I don't want to introduce a dependency to the
refactoring browser into the kernel...

Guille

-------- Original Message --------

> Hi,
>
>
> I have dusted off and improved the automatic refactoring of deprecations.
>
> - when the refactoring engine is not present, it falls back to a standard deprecation
> - It does not introduce any dependencies (can just be in the Kernel, the only cost is one method of 10 lines).
> - It sets the author so it does not require initials
> - It refactors ​*only*​ the sending (offending, deprecated) send site. So a second selector that is identical (which might be a different method and not deprecated) will not be affected.
>
> The way to use it is this:
>
> ifNotNilDo: aBlock
>      self
>          deprecated: 'Please use #ifNotNil: instead'
>          transformWith: '`@receiver ifNotNilDo: `@statements' -> '`@receiver ifNotNil: `@statements'.
>      ^ aBlock ifNotNil: aBlock
>
>
> As we try to provide already Lint rules for deprecations (or at least should have..) the amount of additional work is not much.
>
> This is the full implementation:
>
> deprecated: anExplanationString transformWith: aRule
>      | rewriteRule method context node |
>      context := thisContext sender sender.
>      (Smalltalk globals hasClassNamed: #RBParseTreeRewriter)
>          ifFalse: [ ^self deprecated: anExplanationString ].
>      method := context method.
>      node := context sourceNodeExecuted.
>      rewriteRule := (Smalltalk globals classNamed: #RBParseTreeRewriter) new replace: aRule key with: aRule value.
>      (rewriteRule executeTree: node)
>          ifFalse: [ ^ self ].
>      node replaceWith: rewriteRule tree.
>      Author
>          useAuthor: 'AutoDeprecationRefactoring'
>          during: [method methodClass compile: method ast formattedCode classified: method protocol]
>
> https://pharo.fogbugz.com/f/cases/18507/
>
> This is *with intention* the absolute “simplest thing that can possibly work”. There is no interactive tool to preview refactoring in interactive
> mode, or some way to opt in or out.
>
> The power of things like this comes from actually using them, not from being perfect...
>
> Marcus


Reply | Threaded
Open this post in threaded view
|

Re: Automatic deprecation refactoring

Marcus Denker-4

> On 17 Jun 2016, at 12:22, Guille Polito <[hidden email]> wrote:
>
> Hi!
>
> How is this packaged? I don't want to introduce a dependency to the refactoring browser into the kernel…
>
There is *NO* dependency.


> Guille
>
> -------- Original Message --------
>> Hi,
>>
>>
>> I have dusted off and improved the automatic refactoring of deprecations.
>>
>> - when the refactoring engine is not present, it falls back to a standard deprecation
>> - It does not introduce any dependencies (can just be in the Kernel, the only cost is one method of 10 lines).
>> - It sets the author so it does not require initials
>> - It refactors ​*only*​ the sending (offending, deprecated) send site. So a second selector that is identical (which might be a different method and not deprecated) will not be affected.
>>
>> The way to use it is this:
>>
>> ifNotNilDo: aBlock
>>     self
>>         deprecated: 'Please use #ifNotNil: instead'
>>         transformWith: '`@receiver ifNotNilDo: `@statements' -> '`@receiver ifNotNil: `@statements'.
>>     ^ aBlock ifNotNil: aBlock
>>
>>
>> As we try to provide already Lint rules for deprecations (or at least should have..) the amount of additional work is not much.
>>
>> This is the full implementation:
>>
>> deprecated: anExplanationString transformWith: aRule
>>     | rewriteRule method context node |
>>     context := thisContext sender sender.
>>     (Smalltalk globals hasClassNamed: #RBParseTreeRewriter)
>>         ifFalse: [ ^self deprecated: anExplanationString ].
>>     method := context method.
>>     node := context sourceNodeExecuted.
>>     rewriteRule := (Smalltalk globals classNamed: #RBParseTreeRewriter) new replace: aRule key with: aRule value.
>>     (rewriteRule executeTree: node)
>>         ifFalse: [ ^ self ].
>>     node replaceWith: rewriteRule tree.
>>     Author
>>         useAuthor: 'AutoDeprecationRefactoring'
>>         during: [method methodClass compile: method ast formattedCode classified: method protocol]
>>
>> https://pharo.fogbugz.com/f/cases/18507/
>>
>> This is *with intention* the absolute “simplest thing that can possibly work”. There is no interactive tool to preview refactoring in interactive
>> mode, or some way to opt in or out.
>>
>> The power of things like this comes from actually using them, not from being perfect...
>>
>> Marcus
>


Reply | Threaded
Open this post in threaded view
|

Re: Automatic deprecation refactoring

stepharo
In reply to this post by Guillermo Polito
it is using


     #Refactoring asClassIfPresent:

     I would prefer

     self class environment atIfPresent:

Because asClass is evil since it does not consider that we can have
different namespaces.

Stef

Le 17/6/16 à 12:22, Guille Polito a écrit :

> Hi!
>
> How is this packaged? I don't want to introduce a dependency to the
> refactoring browser into the kernel...
>
> Guille
>
> -------- Original Message --------
>> Hi,
>>
>>
>> I have dusted off and improved the automatic refactoring of
>> deprecations.
>>
>> - when the refactoring engine is not present, it falls back to a
>> standard deprecation
>> - It does not introduce any dependencies (can just be in the Kernel,
>> the only cost is one method of 10 lines).
>> - It sets the author so it does not require initials
>> - It refactors ​*only*​ the sending (offending, deprecated) send
>> site. So a second selector that is identical (which might be a
>> different method and not deprecated) will not be affected.
>>
>> The way to use it is this:
>>
>> ifNotNilDo: aBlock
>>      self
>>          deprecated: 'Please use #ifNotNil: instead'
>>          transformWith: '`@receiver ifNotNilDo: `@statements' ->
>> '`@receiver ifNotNil: `@statements'.
>>      ^ aBlock ifNotNil: aBlock
>>
>>
>> As we try to provide already Lint rules for deprecations (or at least
>> should have..) the amount of additional work is not much.
>>
>> This is the full implementation:
>>
>> deprecated: anExplanationString transformWith: aRule
>>      | rewriteRule method context node |
>>      context := thisContext sender sender.
>>      (Smalltalk globals hasClassNamed: #RBParseTreeRewriter)
>>          ifFalse: [ ^self deprecated: anExplanationString ].
>>      method := context method.
>>      node := context sourceNodeExecuted.
>>      rewriteRule := (Smalltalk globals classNamed:
>> #RBParseTreeRewriter) new replace: aRule key with: aRule value.
>>      (rewriteRule executeTree: node)
>>          ifFalse: [ ^ self ].
>>      node replaceWith: rewriteRule tree.
>>      Author
>>          useAuthor: 'AutoDeprecationRefactoring'
>>          during: [method methodClass compile: method ast
>> formattedCode classified: method protocol]
>>
>> https://pharo.fogbugz.com/f/cases/18507/
>>
>> This is *with intention* the absolute “simplest thing that can
>> possibly work”. There is no interactive tool to preview refactoring
>> in interactive
>> mode, or some way to opt in or out.
>>
>> The power of things like this comes from actually using them, not
>> from being perfect...
>>
>>     Marcus
>
>
>