| 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;        outputI 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! !
 |