| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 | 
							- Smalltalk current createPackage: 'Helios-Helpers'!
 
- Object subclass: #HLGenerationOutput
 
- 	instanceVariableNames: 'sourceCodes protocol targetClass'
 
- 	package: 'Helios-Helpers'!
 
- !HLGenerationOutput commentStamp!
 
- I am a simple data object used to store the result of a generation process!
 
- !HLGenerationOutput methodsFor: 'accessing'!
 
- protocol
 
- 	^ protocol
 
- !
 
- protocol: aString
 
- 	protocol := aString
 
- !
 
- sourceCodes
 
- 	^ sourceCodes
 
- !
 
- sourceCodes: aCollection
 
- 	sourceCodes := aCollection
 
- !
 
- targetClass
 
- 	^ targetClass
 
- !
 
- targetClass: aClass
 
- 	targetClass := aClass
 
- ! !
 
- !HLGenerationOutput methodsFor: 'initialization'!
 
- initialize
 
- 	super initialize.
 
- 	
 
- 	sourceCodes := OrderedCollection new
 
- ! !
 
- !HLGenerationOutput methodsFor: 'protocol'!
 
- addSourceCode: aString
 
- 	sourceCodes add: aString
 
- !
 
- compile
 
- 	sourceCodes do: [ :methodSourceCode |
 
- 		(targetClass includesSelector: methodSourceCode selector)
 
- 			ifFalse: [ 
 
- 				targetClass 
 
- 					compile: methodSourceCode sourceCode
 
- 					protocol: protocol ] ]
 
- ! !
 
- HLGenerationOutput subclass: #HLGenerationOutputWithIndex
 
- 	instanceVariableNames: 'index'
 
- 	package: 'Helios-Helpers'!
 
- !HLGenerationOutputWithIndex commentStamp!
 
- I am a simple data object used to store the result of a generation process.
 
- In addition of my super class, I have an index where to put the cursor at the end of the process for the first method created (aka. the first in `sourceCodes`)!
 
- !HLGenerationOutputWithIndex methodsFor: 'accessing'!
 
- index
 
- 	^ index
 
- !
 
- index: anIndex
 
- 	index := anIndex
 
- ! !
 
- Object subclass: #HLGenerator
 
- 	instanceVariableNames: 'output'
 
- 	package: 'Helios-Helpers'!
 
- !HLGenerator commentStamp!
 
- I am the abstract super class of the generators.
 
- My main method is `generate` which produce an `output` object!
 
- !HLGenerator methodsFor: 'accessing'!
 
- class: aClass
 
- 	output targetClass: aClass
 
- !
 
- output
 
- 	^ output
 
- ! !
 
- !HLGenerator methodsFor: 'initialization'!
 
- initialize
 
- 	super initialize.
 
- 	
 
- 	output := HLGenerationOutput new
 
- ! !
 
- !HLGenerator methodsFor: 'protocol'!
 
- generate
 
- 	output targetClass ifNil: [ self error: 'class should not be nil'].
 
- ! !
 
- HLGenerator subclass: #HLAccessorsGenerator
 
- 	instanceVariableNames: ''
 
- 	package: 'Helios-Helpers'!
 
- !HLAccessorsGenerator commentStamp!
 
- I am a generator used to compile the getters/setters of a class!
 
- !HLAccessorsGenerator methodsFor: 'double-dispatch'!
 
- accessorProtocolForObject
 
- 	output protocol: 'accessing'
 
- !
 
- accessorsSourceCodesForObject
 
- 	| sources |
 
- 	
 
- 	sources := OrderedCollection new.
 
- 	output targetClass instanceVariableNames sorted do: [ :each | 
 
- 		sources 
 
- 			add: (self getterFor: each);
 
- 			add: (self setterFor: each) ].
 
- 	output sourceCodes: sources
 
- ! !
 
- !HLAccessorsGenerator methodsFor: 'private'!
 
- getterFor: anInstanceVariable
 
- 	^ HLMethodSourceCode new
 
- 		selector:anInstanceVariable;
 
- 		sourceCode: (String streamContents: [ :stream |
 
- 		stream << anInstanceVariable.
 
- 		stream cr tab.
 
- 		stream << '^ ' << anInstanceVariable ])
 
- !
 
- setterFor: anInstanceVariable
 
- 	^ HLMethodSourceCode new
 
- 		selector: anInstanceVariable, ':';
 
- 		sourceCode: (String streamContents: [ :stream |
 
- 		stream << anInstanceVariable << ': anObject'.
 
- 		stream cr tab.
 
- 		stream << anInstanceVariable << ' := anObject' ])
 
- ! !
 
- !HLAccessorsGenerator methodsFor: 'protocol'!
 
- generate
 
- 	super generate.
 
- 	
 
- 	output targetClass 
 
- 		accessorsSourceCodesWith: self;
 
- 		accessorProtocolWith: self
 
- ! !
 
- HLGenerator subclass: #HLInitializeGenerator
 
- 	instanceVariableNames: ''
 
- 	package: 'Helios-Helpers'!
 
- !HLInitializeGenerator commentStamp!
 
- I am used to double-dispatch the `initialize` method(s) generation.
 
- Usage:
 
-     ^ HLInitializeGenerator new
 
-         class: aClass;
 
-         generate;
 
-         output
 
- I am a disposable object!
 
- !HLInitializeGenerator methodsFor: 'double-dispatch'!
 
- initializeForObject
 
- 	output addSourceCode: self initializeCodeForObject
 
- !
 
- initializeIndexForObject
 
- 	output index: self computeIndexForObject
 
- !
 
- initializeProtocolForObject
 
- 	output protocol: self retrieveProtocolForObject
 
- ! !
 
- !HLInitializeGenerator methodsFor: 'initialization'!
 
- initialize
 
- 	super initialize.
 
- 	
 
- 	output := HLGenerationOutputWithIndex new
 
- ! !
 
- !HLInitializeGenerator methodsFor: 'private'!
 
- computeIndexForObject
 
- 	| instVars headerSize firstInstVarSize |
 
- 	
 
- 	"32 is the size of the `initiliaze super initialize` part"
 
- 	headerSize := 32.
 
- 	instVars := output targetClass instanceVariableNames.
 
- 	firstInstVarSize := instVars sorted
 
- 		ifEmpty: [ 0 ]
 
- 		ifNotEmpty:[ instVars first size + 4 ].
 
- 	^ headerSize + firstInstVarSize
 
- !
 
- generateInitializeCodeForObject	
 
- 	^ String streamContents: [ :str || instVars size |
 
- 		instVars := output targetClass instanceVariableNames sorted.
 
- 		size := instVars size.
 
- 		str << 'initialize'.
 
- 		str cr tab << 'super initialize.';cr.
 
- 		str cr tab.
 
- 		instVars withIndexDo: [ :name :index |
 
- 			index ~= 1 ifTrue: [ str cr tab ].
 
- 			str << name << ' := nil'.
 
- 			index ~= size ifTrue: [ str << '.' ] ] ].
 
- !
 
- initializeCodeForObject	
 
- 	^ HLMethodSourceCode new
 
- 		selector: 'initialize';
 
- 		sourceCode: self generateInitializeCodeForObject;
 
- 		yourself
 
- !
 
- retrieveProtocolForObject
 
- 	^ 'initialization'
 
- ! !
 
- !HLInitializeGenerator methodsFor: 'protocol'!
 
- generate
 
- 	super generate.
 
- 	
 
- 	output targetClass 
 
- 		initializeSourceCodesWith: self;
 
- 		initializeIndexWith: self;
 
- 		initializeProtocolWith: self
 
- ! !
 
- Object subclass: #HLMethodSourceCode
 
- 	instanceVariableNames: 'selector sourceCode'
 
- 	package: 'Helios-Helpers'!
 
- !HLMethodSourceCode commentStamp!
 
- I am a simple data object keeping track of the information about a method that will be compiled at the end of the generation process!
 
- !HLMethodSourceCode methodsFor: 'accessing'!
 
- selector
 
- 	^ selector
 
- !
 
- selector: aSelector
 
- 	selector := aSelector
 
- !
 
- sourceCode
 
- 	^ sourceCode
 
- !
 
- sourceCode: aString
 
- 	sourceCode := aString
 
- ! !
 
 
  |