better comment in CustomNamespace >> execute
fix replace on wrong code selection ( replace only if found match ) in CustomRefactoryBuilder
"{ Package: 'jn:refactoring_custom' }"
RBNamespace subclass:#CustomNamespace
instanceVariableNames:'changeManager formatter defaultValues defaultReplacements package
classModelClass methodModelClass sourceCodeGeneratorClass'
classVariableNames:''
poolDictionaries:''
category:'Interface-Refactoring-Custom'
!
!CustomNamespace methodsFor:'accessing'!
changeManager
^ changeManager
!
changeManager:something
changeManager := something.
!
classModelClass
"Returns class which represents Class in model in which we make changes (add class, rename class ...)."
^ classModelClass
"Modified (comment): / 09-10-2014 / 11:14:51 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
classModelClass: aClass
"see classModelClass"
classModelClass := aClass.
"Modified (comment): / 09-10-2014 / 11:15:18 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
formatter
^ formatter
"Created: / 28-08-2014 / 23:19:02 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
formatter: aFormatter
formatter := aFormatter
"Created: / 28-08-2014 / 23:19:26 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
methodModelClass
"Returns class which represents Method in model in which we make changes (add method, change method source ...)."
^ methodModelClass
"Modified (comment): / 09-10-2014 / 11:17:09 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
methodModelClass: aClass
"see methodModelClass"
methodModelClass := aClass.
"Modified (comment): / 09-10-2014 / 11:16:02 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
sourceCodeGenerator
"Returns initialized source code generator"
| sourceCodeGenerator |
sourceCodeGenerator := self sourceCodeGeneratorClass new.
sourceCodeGenerator formatter: formatter.
^ sourceCodeGenerator.
"Created: / 19-09-2014 / 20:56:22 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 09-10-2014 / 11:35:24 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
sourceCodeGeneratorClass
"Returns code generator class which supports search & replace in method source code and formatting"
^ sourceCodeGeneratorClass
"Modified (comment): / 09-10-2014 / 11:34:34 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
sourceCodeGeneratorClass: aClass
"see sourceCodeGeneratorClass"
sourceCodeGeneratorClass := aClass.
"Modified (comment): / 09-10-2014 / 11:34:56 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
! !
!CustomNamespace methodsFor:'code creation'!
createClass
"Much like createMethod, but for class"
| class |
class := self classModelClass new
model: self;
superclass: (self classNamed: #Object);
instanceVariableNames: #();
classVariableNames: #();
poolDictionaryNames: #();
yourself.
self fillDefaultValuesTo: class.
self storeDefaultClassWhenNoneStored: class.
^ class
"Created: / 09-04-2014 / 21:38:20 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 09-10-2014 / 11:18:17 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
createMethod
"
Creates, returns method representation
so code changes can be created withing this class as one undo change
"
| method |
method := self methodModelClass new
model: self;
sourceCodeGenerator: self sourceCodeGenerator;
yourself.
self fillDefaultValuesTo: method.
^ method
"Created: / 09-04-2014 / 23:54:03 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 09-10-2014 / 11:25:43 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
! !
!CustomNamespace methodsFor:'code creation - immediate'!
createClassImmediate: aClassName
"Creates class immediately and returns the real class"
^ self createClassImmediate: aClassName superClassName: 'Object'
"Created: / 27-07-2014 / 12:40:55 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
createClassImmediate: aClassName instanceVariableNames: instVarNames
"Creates class immediately and returns the real class"
^ self
createClassImmediate: aClassName
superClassName: 'Object'
instanceVariableNames: instVarNames
classVariableNames: ''
"Created: / 23-08-2014 / 22:25:08 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
createClassImmediate: aClassName superClassName: aSuperClassName
"Creates class immediately and returns the real class"
^ self
createClassImmediate: aClassName
superClassName: aSuperClassName
instanceVariableNames: ''
classVariableNames: ''
"Created: / 15-06-2014 / 15:59:21 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 23-08-2014 / 22:18:58 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
createClassImmediate: aClassName superClassName: aSuperClassName instanceVariableNames: instVarNames classVariableNames: classVarNames
"Creates class immediately and returns the real class"
changes addChange: (InteractiveAddClassChange definition:
aSuperClassName, ' subclass:#', aClassName, '
instanceVariableNames:''', instVarNames, '''
classVariableNames:''', classVarNames, '''
poolDictionaries:''''
category:''''
').
self execute.
^ Smalltalk classNamed: aClassName
"Created: / 23-08-2014 / 22:18:07 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 21-09-2014 / 22:39:33 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
createMethodImmediate: aClass protocol: aProtocol source: aSource
"Much like createClassImmediate:superClassName:, but for method"
^ self createMethodImmediate: aClass protocol: aProtocol source: aSource package: nil
"Created: / 15-06-2014 / 16:06:00 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 17-10-2014 / 09:58:17 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
createMethodImmediate: aClass protocol: aProtocol source: aSource package: aPackageId
"Much like createClassImmediate:superClassName:, but for method"
| selector change |
change := InteractiveAddMethodChange compile: aSource in: aClass classified: aProtocol.
(aPackageId notNil and: [ (change class canUnderstand: #package:) ]) ifTrue: [
change package: aPackageId
].
changes addChange: change.
self execute.
selector := (Parser parseMethodSpecification: aSource) selector.
^ aClass compiledMethodAt: selector
"Created: / 17-10-2014 / 09:53:45 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
createMethodImmediate: aClass source: aSource
"Much like createClassImmediate:superClassName:, but for method"
^ self createMethodImmediate: aClass protocol: 'protocol' source: aSource
"Created: / 23-08-2014 / 20:17:22 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
! !
!CustomNamespace methodsFor:'compiling'!
execute
"Performs code changes ( add method, add class, rename class... )
so they take in effect ( method is added, class is renamed, ... )
with respect to current change manager implementatin - see CustomChangeManager subclasses."
changeManager performChange: changes
"Created: / 27-04-2014 / 16:30:05 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 21-09-2014 / 22:34:58 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified (comment): / 19-10-2014 / 14:30:45 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
redoChanges
"redo all changes made by execute method"
changeManager redoChanges
"Created: / 27-04-2014 / 17:07:52 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 31-05-2014 / 19:47:02 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
! !
!CustomNamespace methodsFor:'default values'!
category:aString
self storeDefaultValue: #category: value: aString
"Created: / 29-04-2014 / 19:51:45 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
class:aClass
self storeDefaultValue: #classes: value: (Array with: aClass)
"Created: / 29-04-2014 / 19:55:50 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 31-08-2014 / 17:01:22 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
className:something
self storeDefaultValue: #className: value: something
"Created: / 29-04-2014 / 19:42:23 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
classVariableNames:something
self storeDefaultValue: #classVariableNames: value: something
"Created: / 29-04-2014 / 19:43:22 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
classes: aClassCollection
self storeDefaultValue: #classes: value: aClassCollection
"Created: / 29-04-2014 / 19:50:07 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
fillDefaultValuesTo: aCodeElement
"Initializes new code element (class, method) and fills default values from this model"
| builderClass |
builderClass := aCodeElement class.
defaultValues keysAndValuesDo: [ :selector :value |
((builderClass includesSelector: selector) or: [self isSharedAttribute: selector]) ifTrue: [
aCodeElement perform: selector with: value.
]
].
defaultReplacements keysAndValuesDo: [ :placeholder :code |
aCodeElement replace: placeholder with: code
].
"Created: / 29-04-2014 / 20:21:57 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 09-10-2014 / 10:47:07 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
forgetReplacements
defaultReplacements removeAll
"Created: / 29-04-2014 / 20:19:15 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
instanceVariableNames:something
self storeDefaultValue: #instanceVariableNames: value: something
"Created: / 29-04-2014 / 19:44:37 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
isDefaultValueStored: aSelector
^ defaultValues includesKey: aSelector
"Created: / 31-08-2014 / 16:43:52 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
isMeta:aBoolean
self storeDefaultValue: #isMeta: value: aBoolean
"Created: / 29-04-2014 / 19:47:47 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
package:aPackage
((self class) == CustomNamespace) ifTrue: [
self storeDefaultValue: #package: value: aPackage
] ifFalse: [
package := aPackage
]
"Created: / 30-08-2014 / 18:32:01 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 09-10-2014 / 09:18:16 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
poolDictionaryNames:something
self storeDefaultValue: #poolDictionaryNames: value: something
"Created: / 29-04-2014 / 19:48:37 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
protocol:aString
self storeDefaultValue: #protocol: value: aString
"Created: / 29-04-2014 / 20:01:08 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
replace: placeholder with: code
((self class) == CustomNamespace) ifTrue: [
defaultReplacements
at: placeholder
put: code
]
ifFalse: [
"replacements
at: placeholder
put: (self replacementFromCode: code)"
]
"Created: / 29-04-2014 / 20:02:45 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 09-10-2014 / 09:18:22 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
source:aString
self storeDefaultValue: #source: value: aString
"Created: / 29-04-2014 / 20:12:20 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
storeDefaultClassWhenNoneStored:aClass
"Save class as default class when none class is actually set as default class"
(self isDefaultValueStored: #classes:) ifFalse: [
self storeDefaultValue: #classes: value: (Array with: aClass)
]
"Created: / 31-08-2014 / 16:23:38 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
storeDefaultValue: aSelector value: aValue
((self class) == CustomNamespace) ifTrue: [
defaultValues
at: aSelector
put: aValue
]
ifFalse: [
self error: 'Selector ', aSelector, ' has to be overwritten by class: ', self className.
"
| superclass |
superclass := self class superclass.
superclass superclass isNil ifFalse: [
superclass := superclass superclass
].
(superclass canUnderstand: aSelector) ifTrue: [
self assert: (superclass == CustomSourceCodeBuilder) not.
self perform: aSelector with: aValue
]
"
]
"Created: / 28-04-2014 / 19:08:17 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 09-10-2014 / 09:34:39 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
!
superclassName:something
self storeDefaultValue: #superclassName: value: something
"Created: / 29-04-2014 / 19:49:02 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
! !
!CustomNamespace methodsFor:'initialization'!
initialize
"Invoked when a new instance is created."
super initialize.
changeManager := CustomLocalChangeManager new.
defaultValues := Dictionary new.
defaultReplacements := Dictionary new.
formatter := CustomRBLocalSourceCodeFormatter new.
classModelClass := RBClass.
methodModelClass := RBMethod.
sourceCodeGeneratorClass := CustomSourceCodeGenerator.
"Created: / 09-04-2014 / 23:44:04 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
"Modified: / 09-10-2014 / 11:30:42 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
! !
!CustomNamespace methodsFor:'private'!
isSharedAttribute: aSelector
"Tells if given selector is shared attribute setter for subclasses"
^ (aSelector = #package:)
"Created: / 30-08-2014 / 21:38:21 / Jakub Nesveda <nesvejak@fit.cvut.cz>"
! !
!CustomNamespace class methodsFor:'documentation'!
version_HG
^ '$Changeset: <not expanded> $'
! !