Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions src/Refactoring-Core/RBCondition.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -56,25 +56,6 @@ RBCondition class >> checkInstanceVariableName: aName in: aClass [
^ OCScanner isVariable: string
]

{ #category : 'instance creation' }
RBCondition class >> checkNotMultipleTemporaryDefinitionsOf: aString in: aClass [

| condition |
condition := self new.
condition
block: [
| methods |
methods := self multipleMethodsDefiningTemporary: aString in: aClass ignore: [ :class :selector | false ].
methods size > 1
ifTrue: [
condition errorMacro:
'More than one method defines temporary variable ' , aString , ': ' , (methods collect: [ :m | m selector ]) asString.
false ]
ifFalse: [ true ] ]
errorString: aClass printString , ' <1?:does not >define<1?s:> temporary variable ' , aString.
^ condition
]

{ #category : 'instance creation' }
RBCondition class >> definesClassVariable: aString in: aClass [
^self new
Expand Down Expand Up @@ -374,25 +355,6 @@ RBCondition class >> methodDefiningTemporary: aString in: aClass ignore: aBlock
^ nil
]

{ #category : 'utilities' }
RBCondition class >> multipleMethodsDefiningTemporary: aString in: aClass ignore: aBlock [

| searcher methods method |
searcher := OCParseTreeSearcher new.
methods := Set new.
method := nil.

searcher matches: aString do: [ :aNode :answer | methods add: method ].
aClass withAllSubclasses do: [ :class |
class selectors do: [ :each |
(aBlock value: class value: each) ifFalse: [
| parseTree |
method := class methodFor: each.
parseTree := class parseTreeForSelector: each.
parseTree ifNotNil: [ searcher executeTree: parseTree ] ] ] ].
^ methods
]

{ #category : 'instance creation' }
RBCondition class >> referencesClassVariable: aString in: aClass [

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,17 +114,9 @@ RBTemporaryToInstanceVariableRefactoring >> applicabilityPreconditions [
RBTemporaryToInstanceVariableRefactoring >> breakingChangePreconditions [

^ {
(RBCondition withBlock: [
(class allSubclasses anySatisfy: [ :cls | cls definesInstanceVariable: temporaryVariableName asString ]) ifTrue: [
self refactoringWarning:
('One or more subclasses of <1p> already defines an<n>instance variable with the same name. Proceed anyway?'
expandMacrosWith: class name) ].
true ]).
(RBCondition checkNotMultipleTemporaryDefinitionsOf: temporaryVariableName in: class).
(ReVariablesNotReadBeforeWrittenCondition new
subtree: parseTree;
variables: temporaryVariableName;
checkForTemporaryVariables: true) }
self preconditionNoSubclassDefinesVar.
self preconditionNoMultipleTempOccurences.
self preconditionNoReadBeforeWritten }
]

{ #category : 'initialization' }
Expand All @@ -143,6 +135,31 @@ RBTemporaryToInstanceVariableRefactoring >> isTemporaryVariableNameValid [
self refactoringError: temporaryVariableName , ' is a block parameter' ]
]

{ #category : 'preconditions' }
RBTemporaryToInstanceVariableRefactoring >> preconditionNoMultipleTempOccurences [

^ ReMultipleMethodsDontReferToTempVarsCondition name: temporaryVariableName class: class selector: selector
]

{ #category : 'preconditions' }
RBTemporaryToInstanceVariableRefactoring >> preconditionNoReadBeforeWritten [

^ ReVariablesNotReadBeforeWrittenCondition new
subtree: parseTree;
variables: temporaryVariableName;
checkForTemporaryVariables: true
]

{ #category : 'preconditions' }
RBTemporaryToInstanceVariableRefactoring >> preconditionNoSubclassDefinesVar [

^ RBCondition
withBlock: [ (class allSubclasses anySatisfy: [ :cls | cls definesInstanceVariable: temporaryVariableName asString ]) not ]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a second PR we should remove this pop up!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a second PR we should remove this pop up!

Yes, I suggested Alexis to leave it like this for the moment.
After merging this PR refactoring the method will be way easier

errorString:
('One or more subclasses of <1p> already defines an<n>instance variable with the same name. Proceed anyway?'
expandMacrosWith: class name)
]

{ #category : 'preconditions' }
RBTemporaryToInstanceVariableRefactoring >> preconditions [

Expand All @@ -159,10 +176,6 @@ RBTemporaryToInstanceVariableRefactoring >> prepareForExecution [
RBTemporaryToInstanceVariableRefactoring >> privateTransform [

self removeTemporaryOfClass: class.
class allSubclasses do: [ :cls |
(cls definesInstanceVariable: temporaryVariableName)
ifTrue: [ cls removeInstanceVariable: temporaryVariableName ]
ifFalse: [ self removeTemporaryOfClass: cls ] ].
class addInstanceVariable: temporaryVariableName
]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
Class {
#name : 'ReMultipleMethodsDontReferToTempVarsCondition',
#superclass : 'ReVariableNameCondition',
#instVars : [
'class',
'selector'
],
#category : 'Refactoring-Core-Conditions',
#package : 'Refactoring-Core',
#tag : 'Conditions'
}

{ #category : 'instance creation' }
ReMultipleMethodsDontReferToTempVarsCondition class >> name: aString class: aClass selector: aSelector [

^ (self name: aString)
class: aClass;
selector: aSelector yourself
]

{ #category : 'checking' }
ReMultipleMethodsDontReferToTempVarsCondition >> check [

^ self violators isEmpty
]

{ #category : 'setter' }
ReMultipleMethodsDontReferToTempVarsCondition >> class: aRBClass [

class := aRBClass.

]

{ #category : 'utilities' }
ReMultipleMethodsDontReferToTempVarsCondition >> multipleMethodsDefiningTemporary: aString in: aClass ignore: aBlock [

| searcher methods method |
searcher := OCParseTreeSearcher new.
methods := Set new.
method := nil.

searcher matches: aString do: [ :aNode :answer | methods add: method ].
aClass withAllSubclasses do: [ :cls |
cls selectors do: [ :each |
(aBlock value: cls value: each) ifFalse: [
| parseTree |
method := cls methodFor: each.
parseTree := cls parseTreeForSelector: each.
parseTree ifNotNil: [ searcher executeTree: parseTree ] ] ] ].
^ methods
]

{ #category : 'accessing' }
ReMultipleMethodsDontReferToTempVarsCondition >> selector: aSelector [

selector := aSelector
]

{ #category : 'displaying' }
ReMultipleMethodsDontReferToTempVarsCondition >> violationMessageOn: aStream [

self violators ifEmpty: [ ^ self ].
^ aStream
nextPutAll: 'More than one method defines temporary variable ';
nextPutAll: name;
nextPutAll: ': ';
nextPutAll: (self violators collect: [ :m | m selector ]) asArray asString
]

{ #category : 'checking' }
ReMultipleMethodsDontReferToTempVarsCondition >> violators [

| methods |
methods := self multipleMethodsDefiningTemporary: name in: class ignore: [ :cls :selectors | false ].
^ methods reject: [ :m | m selector = selector ]
]
3 changes: 2 additions & 1 deletion src/Refactoring-Core/ReRefactoring.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ ReRefactoring >> canReferenceVariable: aString in: aClass [
{ #category : 'scripting api - conditions' }
ReRefactoring >> checkBreakingChangePreconditions [
"Check a preconditions and raise an error on violations. This method is part of the scripting API since it raises an error."

| failedPreconditions |
failedPreconditions := self failedBreakingChangePreconditions.
failedPreconditions ifEmpty: [ ^ self ].

RBRefactoringWarning signalFor: failedPreconditions
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ ReVariablesNotReadBeforeWrittenCondition >> variables: aCollection [
{ #category : 'displaying' }
ReVariablesNotReadBeforeWrittenCondition >> violationMessageOn: aStream [

self check ifTrue: [ ^ self ].
aStream
nextPutAll: 'Cannot extract selected code because variables: ';
nextPutAll: variables asString;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Class {
#name : 'ReClassToConvertTemporaryToInstanceVariable',
#superclass : 'Object',
#instVars : [
'instVar'
],
#category : 'Refactoring-DataForTesting-ForConvertingVariables',
#package : 'Refactoring-DataForTesting',
#tag : 'ForConvertingVariables'
}

{ #category : 'action' }
ReClassToConvertTemporaryToInstanceVariable >> doAction1 [

| temp |
temp := 35.

^ temp
]

{ #category : 'action' }
ReClassToConvertTemporaryToInstanceVariable >> doAction2 [

| instVar |
instVar := 3.
^ instVar
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
Class {
#name : 'ReConvertTemporaryToInstanceVariableDriverTest',
#superclass : 'ReDriverTest',
#instVars : [
'testingEnvironment'
],
#category : 'Refactoring-UI-Tests-Driver',
#package : 'Refactoring-UI-Tests',
#tag : 'Driver'
}

{ #category : 'getter' }
ReConvertTemporaryToInstanceVariableDriverTest >> classToConvertTemporaryToInstanceVariable [

^ ReClassToConvertTemporaryToInstanceVariable
]

{ #category : 'running' }
ReConvertTemporaryToInstanceVariableDriverTest >> setUp [

super setUp.
testingEnvironment := RBClassEnvironment classes: self classToConvertTemporaryToInstanceVariable withAllSubclasses
]

{ #category : 'tests' }
ReConvertTemporaryToInstanceVariableDriverTest >> testConvertTempFailure [

| driver |
driver := ReConvertTemporaryToInstanceVariableDriver new.
self setUpDriver: driver.
driver class: self classToConvertTemporaryToInstanceVariable selector: #doAction2 variable: 'instVar'.

driver runRefactoring.

self assert: driver refactoring changes changes size equals: 0
]

{ #category : 'tests' }
ReConvertTemporaryToInstanceVariableDriverTest >> testConvertTempSuccessfully [

| driver |
driver := ReConvertTemporaryToInstanceVariableDriver new.
self setUpDriver: driver.
driver class: self classToConvertTemporaryToInstanceVariable selector: #doAction1 variable: 'temp'.

driver runRefactoring.

self assert: driver refactoring changes changes size equals: 3.

]
2 changes: 1 addition & 1 deletion src/Refactoring-UI/ReBrowseMethodChoice.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ ReBrowseMethodChoice >> action [
{ #category : 'accessing' }
ReBrowseMethodChoice >> description [

^ 'Browse the method(s)'
^ 'Browse the method'
]
19 changes: 19 additions & 0 deletions src/Refactoring-UI/ReBrowseMethodsChoice.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Class {
#name : 'ReBrowseMethodsChoice',
#superclass : 'ReMethodChoice',
#category : 'Refactoring-UI-Choices',
#package : 'Refactoring-UI',
#tag : 'Choices'
}

{ #category : 'accessing' }
ReBrowseMethodsChoice >> action [

driver browseMethods
]

{ #category : 'accessing' }
ReBrowseMethodsChoice >> description [

^ 'Browse the methods'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description is almost the same as ReBrowseMethodChoice.
Maybe we could use an IV to set it from the driver and make it more specific?

]
Loading