-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #95 from jecisc/77-Add-cleaner-extracting-returns-…
…for-conditionals-with-return-as-last-statement-in-the-two-branches 77-Add-cleaner-extracting-returns-for-conditionals-with-return-as-last-statement-in-the-two-branches
- Loading branch information
Showing
8 changed files
with
380 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
285 changes: 285 additions & 0 deletions
285
src/Chanel-Tests/ChanelExtractReturnFromAllBranchesCleanerTest.class.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,285 @@ | ||
" | ||
A ChanelExtractReturnFromAllBranchesCleanerTest is a test class for testing the behavior of ChanelExtractReturnFromAllBranchesCleaner | ||
" | ||
Class { | ||
#name : #ChanelExtractReturnFromAllBranchesCleanerTest, | ||
#superclass : #ChanelAbstractCleanerTest, | ||
#category : #'Chanel-Tests' | ||
} | ||
|
||
{ #category : #running } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> setUp [ | ||
super setUp. | ||
class := self createDefaultClass | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testDoesNotExtractReturnIfABranchIsASymbol [ | ||
| oldMethod | | ||
class | ||
compile: | ||
'method | ||
self toto ifNil: [ ^ 1 ] ifNotNil: #yourself'. | ||
|
||
oldMethod := class >> #method. | ||
|
||
self runCleaner. | ||
|
||
self | ||
assert: (class >> #method) sourceCode | ||
equals: | ||
'method | ||
self toto ifNil: [ ^ 1 ] ifNotNil: #yourself'. | ||
|
||
self assert: oldMethod identicalTo: class >> #method | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testDoesNotExtractReturnIfAlreadyOutside [ | ||
| oldMethod | | ||
class | ||
compile: | ||
'method | ||
^ self toto ifTrue: [ 1 ] ifFalse: [ 2 ]'. | ||
|
||
oldMethod := class >> #method. | ||
|
||
self runCleaner. | ||
|
||
self | ||
assert: (class >> #method) sourceCode | ||
equals: | ||
'method | ||
^ self toto ifTrue: [ 1 ] ifFalse: [ 2 ]'. | ||
|
||
self assert: oldMethod identicalTo: class >> #method | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testDoesNotExtractReturnIfInACascade [ | ||
| oldMethod | | ||
class compile: 'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ ^ 2 ]; bar'. | ||
|
||
oldMethod := class >> #method. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ ^ 2 ]; bar'. | ||
|
||
self assert: oldMethod identicalTo: class >> #method | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testDoesNotExtractReturnIfMessageIsNotTheLastStatement [ | ||
| oldMethod | | ||
class | ||
compile: | ||
'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ ^ 2 ]. | ||
self bar'. | ||
|
||
oldMethod := class >> #method. | ||
|
||
self runCleaner. | ||
|
||
self | ||
assert: (class >> #method) sourceCode | ||
equals: | ||
'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ ^ 2 ]. | ||
self bar'. | ||
|
||
self assert: oldMethod identicalTo: class >> #method | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testDoesNotExtractReturnIfOnBranchDoesNotHaveOne [ | ||
| oldMethod | | ||
class | ||
compile: | ||
'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ 2 ]'. | ||
|
||
oldMethod := class >> #method. | ||
|
||
self runCleaner. | ||
|
||
self | ||
assert: (class >> #method) sourceCode | ||
equals: | ||
'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ 2 ]'. | ||
|
||
self assert: oldMethod identicalTo: class >> #method | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testDoesNotExtractReturnIfReturnIsNotTheLastStatement [ | ||
| oldMethod | | ||
class | ||
compile: | ||
'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ self foo ifTrue: [ ^ 2 ] ]'. | ||
|
||
oldMethod := class >> #method. | ||
|
||
self runCleaner. | ||
|
||
self | ||
assert: (class >> #method) sourceCode | ||
equals: | ||
'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ self foo ifTrue: [ ^ 2 ] ]'. | ||
|
||
self assert: oldMethod identicalTo: class >> #method | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnDoesNotFailIfThereIsAlreadyAReturn [ | ||
class compile: 'method | ||
^self toto ifTrue: [ ^ 1 ] ifFalse: [ ^ 2 ]'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
^self toto ifTrue: [ 1 ] ifFalse: [ 2 ]' | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnFromIfEmptyIfNotEmpty [ | ||
class compile: 'method | ||
self toto ifEmpty: [ ^ 2 ] ifNotEmpty: [ ^ 1 ]'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
^self toto ifEmpty: [ 2 ] ifNotEmpty: [ 1 ]' | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnFromIfExistsIfAbsent [ | ||
class compile: 'method | ||
self toto ifExists: [ ^ 2 ] ifAbsent: [ ^ 1 ]'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
^self toto ifExists: [ 2 ] ifAbsent: [ 1 ]' | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnFromIfFalseIfTrue [ | ||
class compile: 'method | ||
self toto ifFalse: [ ^ 2 ] ifTrue: [ ^ 1 ]'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
^self toto ifFalse: [ 2 ] ifTrue: [ 1 ]' | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnFromIfNilIfNotNil [ | ||
class compile: 'method | ||
self toto ifNil: [ ^ 2 ] ifNotNil: [ ^ 1 ]'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
^self toto ifNil: [ 2 ] ifNotNil: [ 1 ]' | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnFromIfNotEmptyIfEmpty [ | ||
class compile: 'method | ||
self toto ifNotEmpty: [ ^ 2 ] ifEmpty: [ ^ 1 ]'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
^self toto ifNotEmpty: [ 2 ] ifEmpty: [ 1 ]' | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnFromIfNotNilIfNil [ | ||
class compile: 'method | ||
self toto ifNotNil: [ ^ 2 ] ifNil: [ ^ 1 ]'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
^self toto ifNotNil: [ 2 ] ifNil: [ 1 ]' | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnFromIfTrueIfFalse [ | ||
class compile: 'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ ^ 2 ]'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
^self toto ifTrue: [ 1 ] ifFalse: [ 2 ]' | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnFromIfTrueIfFalseWithOtherStatements [ | ||
class compile: 'method | ||
self toto ifTrue: [ self foo. ^ 1 ] ifFalse: [ ^ self bar ]'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
^self toto ifTrue: [ self foo. | ||
1 ] ifFalse: [ self bar ]' | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnIfTheLastStatementOfABlock [ | ||
class compile: 'method | ||
self foo ifTrue: [ self toto ifTrue: [ ^ 1 ] ifFalse: [ ^ 2 ] ]. | ||
self bar'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class >> #method) sourceCode equals: 'method | ||
self foo ifTrue: [ ^self toto ifTrue: [ 1 ] ifFalse: [ 2 ] ]. | ||
self bar' | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnInTrait [ | ||
| trait | | ||
trait := self createDefaultTrait. | ||
|
||
class setTraitComposition: trait. | ||
|
||
trait | ||
compile: | ||
'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ ^ 2 ]'. | ||
|
||
self runCleaner. | ||
|
||
self | ||
assert: (trait >> #method) sourceCode | ||
equals: | ||
'method | ||
^self toto ifTrue: [ 1 ] ifFalse: [ 2 ]'. | ||
|
||
self assert: (trait localSelectors includes: #method). | ||
self deny: (class localSelectors includes: #method) | ||
] | ||
|
||
{ #category : #tests } | ||
ChanelExtractReturnFromAllBranchesCleanerTest >> testExtractReturnOnClassSide [ | ||
class class compile: 'method | ||
self toto ifTrue: [ ^ 1 ] ifFalse: [ ^ 2 ]'. | ||
|
||
self runCleaner. | ||
|
||
self assert: (class class >> #method) sourceCode equals: 'method | ||
^self toto ifTrue: [ 1 ] ifFalse: [ 2 ]' | ||
] |
33 changes: 33 additions & 0 deletions
33
src/Chanel/ChanelExtractReturnFromAllBranchesCleaner.class.st
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
" | ||
Description | ||
-------------------- | ||
I am a cleaner trying to extract returns from conditions. | ||
" | ||
Class { | ||
#name : #ChanelExtractReturnFromAllBranchesCleaner, | ||
#superclass : #ChanelAbstractCleaner, | ||
#category : #Chanel | ||
} | ||
|
||
{ #category : #accessing } | ||
ChanelExtractReturnFromAllBranchesCleaner class >> priority [ | ||
^ 15000 | ||
] | ||
|
||
{ #category : #cleaning } | ||
ChanelExtractReturnFromAllBranchesCleaner >> clean [ | ||
(self configuration localMethods iterator | ||
| #ast collectIt | ||
| #allChildren flatCollectIt | ||
| #isMessage selectIt | ||
| #isCascaded rejectIt | ||
| [ :node | node parent isLast: node ] selectIt | ||
| #isConditionNecessarilyExecutingABranch selectIt | ||
| [ :node | node arguments allSatisfy: #isBlock ] selectIt | ||
| [ :node | node arguments allSatisfy: #hasBlockReturn ] selectIt | ||
| [ :node | node arguments do: #inlineLastReturn ] doIt | ||
| #wrapsInReturn doIt | ||
| #methodNode collectIt | ||
> Set) do: #install | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Extension { #name : #RBBlockNode } | ||
|
||
{ #category : #'*Chanel' } | ||
RBBlockNode >> inlineLastReturn [ | ||
self statements last inline | ||
] |
Oops, something went wrong.