--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CustomCodeGeneratorAbstract.st Sun Dec 08 21:42:38 2013 +0100
@@ -0,0 +1,719 @@
+"
+ COPYRIGHT (c) 2002 by eXept Software AG
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+"{ Package: 'jn:refactoring_custom' }"
+
+Object subclass:#CustomCodeGeneratorAbstract
+ instanceVariableNames:'compositeChangeCollector compositeChangeNesting userPreferences
+ generateComments confirmChanges targetClass'
+ classVariableNames:'GenerateCommentsForGetters GenerateCommentsForSetters
+ CopyrightTemplate'
+ poolDictionaries:''
+ category:'Interface-Refactoring-Custom'
+!
+
+!CustomCodeGeneratorAbstract class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 2002 by eXept Software AG
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+!
+
+documentation
+"
+ This utility class contains various code generation facilites;
+ these were extracted from the old and newBrowser.
+ There is probably more to come...
+
+ Note: being refactored into separate per-language generators
+
+ [author:]
+ Claus Gittiner
+"
+! !
+
+!CustomCodeGeneratorAbstract class methodsFor:'instance creation'!
+
+new
+ ^ self subclassResponsibility.
+
+ "Modified: / 23-08-2013 / 22:19:23 / user"
+! !
+
+!CustomCodeGeneratorAbstract class methodsFor:'compilation'!
+
+compile:theCode forClass:aClass inCategory:cat
+ "install some code for a class.
+ If refactory browser stuff is avaliable the refactory tools are used to support undo"
+
+ ^ self new compile:theCode forClass:aClass inCategory:cat
+! !
+
+!CustomCodeGeneratorAbstract class methodsFor:'interface specs'!
+
+initialMenuSpecForApplications
+ "return a menuSpec with typical stuff in it"
+
+ "This resource specification was automatically generated by the CustomCodeGeneratorAbstract."
+
+ "Do not manually edit this!! If it is corrupted,
+ the MenuEditor may not be able to read the specification."
+
+ "
+ MenuEditor new openOnClass:self andSelector:#initialMenuSpecForApplications
+ "
+
+ <resource: #menu>
+
+ ^ #(#Menu
+ #(
+ #(#MenuItem
+ #label: 'File'
+ #translateLabel: true
+ #submenu:
+ #(#Menu
+ #(
+ #(#MenuItem
+ #label: 'New'
+ #translateLabel: true
+ #value: #menuNew
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Open...'
+ #translateLabel: true
+ #value: #menuOpen
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Save'
+ #translateLabel: true
+ #value: #menuSave
+ )
+ #(#MenuItem
+ #label: 'Save As...'
+ #translateLabel: true
+ #value: #menuSaveAs
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Exit'
+ #translateLabel: true
+ #value: #closeRequest
+ )
+ ) nil
+ nil
+ )
+ )
+ #(#MenuItem
+ #label: 'Help'
+ #translateLabel: true
+ #startGroup: #right
+ #submenu:
+ #(#Menu
+ #(
+ #(#MenuItem
+ #label: 'Documentation'
+ #translateLabel: true
+ #value: #openDocumentation
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'About this Application...'
+ #translateLabel: true
+ #value: #openAboutThisApplication
+ )
+ ) nil
+ nil
+ )
+ )
+ ) nil
+ nil
+ )
+!
+
+initialPageMenuSpecForWebApplications
+ "return a menuSpec with typical stuff in it"
+
+ "This resource specification was automatically generated by the CustomCodeGeneratorAbstract."
+
+ "Do not manually edit this!! If it is corrupted,
+ the MenuEditor may not be able to read the specification."
+
+ "
+ MenuEditor new openOnClass:self andSelector:#initialPageMenuSpecForWebApplications
+ "
+
+ <resource: #menu>
+
+ ^ #(#Menu
+ #(
+ #(#MenuItem
+ #label: 'File'
+ #translateLabel: true
+ #submenu:
+ #(#Menu
+ #(
+ #(#MenuItem
+ #label: 'New'
+ #translateLabel: true
+ #value: #menuNew
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Open...'
+ #translateLabel: true
+ #value: #menuOpen
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Save'
+ #translateLabel: true
+ #value: #menuSave
+ )
+ #(#MenuItem
+ #label: 'Save As...'
+ #translateLabel: true
+ #value: #menuSaveAs
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Exit'
+ #translateLabel: true
+ #value: #closeRequest
+ )
+ ) nil
+ nil
+ )
+ )
+ #(#MenuItem
+ #label: 'Help'
+ #translateLabel: true
+ #startGroup: #right
+ #submenu:
+ #(#Menu
+ #(
+ #(#MenuItem
+ #label: 'Documentation'
+ #translateLabel: true
+ #value: #openDocumentation
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'About this Application...'
+ #translateLabel: true
+ #value: #openAboutThisApplication
+ )
+ ) nil
+ nil
+ )
+ )
+ ) nil
+ nil
+ )
+!
+
+initialPageSpecForWebApplications
+ "Do not manually edit this!! If it is corrupted,
+ the UIPainter may not be able to read the specification."
+
+ "
+ UIPainter new openOnClass:self andSelector:#initialPageSpecForWebApplications
+ "
+
+ <resource: #canvas>
+
+ ^ #(#FullSpec
+ #window:
+ #(#WindowSpec
+ #name: '%1'
+ #layout: #(#LayoutFrame 204 0 162 0 503 0 461 0)
+ #label: '%1'
+ #min: #(#Point 10 10)
+ #max: #(#Point 1024 768)
+ #bounds: #(#Rectangle 204 162 504 462)
+ #menu: #pageMenu
+ #usePreferredExtent: false
+ )
+ #component:
+ #(#SpecCollection
+ #collection: #()
+ )
+ )
+
+ "Modified: / 14-07-2011 / 16:44:20 / cg"
+!
+
+initialToolbarMenuSpec
+ "This resource specification was automatically generated
+ by the MenuEditor of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the MenuEditor may not be able to read the specification."
+
+
+ "
+ MenuEditor new openOnClass:CustomCodeGeneratorAbstract andSelector:#initialToolbarMenuSpec
+ (Menu new fromLiteralArrayEncoding:(CustomCodeGeneratorAbstract initialToolbarMenuSpec)) startUp
+ "
+
+ <resource: #menu>
+
+ ^
+ #(Menu
+ (
+ (MenuItem
+ label: 'Reload'
+ itemValue: menuReload
+ translateLabel: true
+ isButton: true
+ labelImage: (ResourceRetriever ToolbarIconLibrary reload24x24Icon)
+ )
+ )
+ nil
+ nil
+ )
+!
+
+initialWindowSpecForApplications
+ "This resource specification was automatically generated
+ by the UIPainter of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the UIPainter may not be able to read the specification."
+
+ "
+ UIPainter new openOnClass:CustomCodeGeneratorAbstract andSelector:#initialWindowSpecForApplications
+ "
+
+ <resource: #canvas>
+
+ ^
+ #(FullSpec
+ name: initialWindowSpecForApplications
+ window:
+ (WindowSpec
+ label: '%1'
+ name: '%1'
+ min: (Point 10 10)
+ bounds: (Rectangle 0 0 300 300)
+ menu: mainMenu
+ )
+ component:
+ (SpecCollection
+ collection: (
+ (LabelSpec
+ label: 'Hello World'
+ name: 'Label1'
+ layout: (LayoutFrame 0 0.0 60 0 0 1.0 219 0)
+ translateLabel: true
+ )
+ )
+
+ )
+ )
+
+ "Modified: / 07-05-2010 / 14:21:48 / cg"
+!
+
+initialWindowSpecForApplications2
+ "This resource specification was automatically generated
+ by the UIPainter of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the UIPainter may not be able to read the specification."
+
+ "
+ UIPainter new openOnClass:CustomCodeGeneratorAbstract andSelector:#initialWindowSpecForApplications2
+ "
+
+ <resource: #canvas>
+
+ ^
+ #(FullSpec
+ name: initialWindowSpecForApplications2
+ window:
+ (WindowSpec
+ label: '%1'
+ name: '%1'
+ min: (Point 10 10)
+ bounds: (Rectangle 0 0 300 300)
+ menu: mainMenu
+ )
+ component:
+ (SpecCollection
+ collection: (
+ (MenuPanelSpec
+ name: 'ToolBar1'
+ layout: (LayoutFrame 0 0.0 0 0 0 1.0 36 0)
+ menu: toolbarMenu
+ textDefault: true
+ )
+ (ViewSpec
+ name: 'Box1'
+ layout: (LayoutFrame 1 0 36 0 0 1 -26 1)
+ level: 1
+ component:
+ (SpecCollection
+ collection: (
+ (LabelSpec
+ label: 'Hello World'
+ name: 'Contents'
+ layout: (LayoutFrame 0 0 0 0 0 1 0 1)
+ translateLabel: true
+ )
+ )
+
+ )
+ )
+ (ViewSpec
+ name: 'Box2'
+ layout: (LayoutFrame 0 0 -26 1 0 1 0 1)
+ level: 1
+ component:
+ (SpecCollection
+ collection: (
+ (LabelSpec
+ label: 'InfoLabel'
+ name: 'Label2'
+ layout: (LayoutFrame 0 0 -26 1 -1 1 0 1)
+ level: -1
+ translateLabel: true
+ labelChannel: infoLabelHolder
+ adjust: left
+ )
+ )
+
+ )
+ )
+ )
+
+ )
+ )
+!
+
+initialWindowSpecForDialogs
+ "This resource specification was automatically generated
+ by the UIPainter of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the UIPainter may not be able to read the specification."
+
+ "
+ UIPainter new openOnClass:CustomCodeGeneratorAbstract andSelector:#initialWindowSpecForDialogs
+ "
+
+ <resource: #canvas>
+
+ ^
+ #(FullSpec
+ name: initialWindowSpecForDialogs
+ window:
+ (WindowSpec
+ label: '%1'
+ name: '%1'
+ min: (Point 10 10)
+ bounds: (Rectangle 0 0 300 300)
+ )
+ component:
+ (SpecCollection
+ collection: (
+ (HorizontalPanelViewSpec
+ name: 'buttonPanel'
+ layout: (LayoutFrame 0 0.0 -40 1 0 1.0 0 1.0)
+ horizontalLayout: spreadSpaceMax
+ verticalLayout: center
+ horizontalSpace: 3
+ verticalSpace: 3
+ reverseOrderIfOKAtLeft: true
+ component:
+ (SpecCollection
+ collection: (
+ (ActionButtonSpec
+ label: 'Cancel'
+ name: 'cancelButton'
+ translateLabel: true
+ tabable: true
+ model: cancel
+ extent: (Point 125 22)
+ )
+ (ActionButtonSpec
+ label: 'OK'
+ name: 'okButton'
+ translateLabel: true
+ tabable: true
+ model: accept
+ isDefault: true
+ extent: (Point 125 22)
+ )
+ )
+
+ )
+ )
+ )
+
+ )
+ )
+
+ "Modified: / 07-05-2010 / 14:21:55 / cg"
+! !
+
+!CustomCodeGeneratorAbstract class methodsFor:'private'!
+
+canUseRefactoringSupport
+ "check if refactory browser stuff is avaliable"
+
+ ^ RefactoryChangeManager notNil
+ and:[RefactoryChangeManager isLoaded
+ and:[UserPreferences current useRefactoringSupport]]
+!
+
+methodNameTemplateFor:aSelector
+ self subclassResponsibility
+! !
+
+!CustomCodeGeneratorAbstract class methodsFor:'utilities'!
+
+missingRequiredProtocolFor:aClass
+ "return the missing required protocol;
+ that is the set of selectors which send #subclassResponsibility in a superclass and
+ have no implementation in aClass or in any class between aClass and that superclass"
+
+ |requiredSelectors implementedSelectors|
+
+ requiredSelectors := IdentitySet new.
+ implementedSelectors := IdentitySet withAll:(aClass methodDictionary keys).
+
+ aClass allSuperclassesDo:[:eachSuperClass |
+ eachSuperClass methodDictionary keysAndValuesDo:[:eachSelector :eachMethod |
+ (eachMethod sends:#subclassResponsibility or:#subclassResponsibility:) ifTrue:[
+ (implementedSelectors includes:eachSelector) ifFalse:[
+ requiredSelectors add:eachSelector.
+ ]
+ ] ifFalse:[
+ (requiredSelectors includes:eachSelector) ifFalse:[
+ implementedSelectors add:eachSelector.
+ ].
+ ].
+ ]
+ ].
+ ^ requiredSelectors
+
+ "Modified: / 08-08-2011 / 18:44:58 / cg"
+! !
+
+!CustomCodeGeneratorAbstract methodsFor:'bulk changes'!
+
+addChange:aChange
+ compositeChangeCollector addChange:aChange
+!
+
+executeCollectedChangesNamed:name
+ "if both the compositeChangeCollector and I myself think, that it should be confirmed,
+ the let user do it - I am not sure, if the heuristics here is useful;
+ it might be better to let the generator decide (for example, if it does high-impact
+ changes, as opposed to simple ones)"
+
+ compositeChangeCollector notNil ifTrue:[
+ compositeChangeNesting := compositeChangeNesting - 1.
+ compositeChangeNesting == 0 ifTrue:[
+ compositeChangeCollector name:name.
+ compositeChangeCollector changesSize == 0 ifTrue:[
+ self information:'Nothing generated.'.
+ ] ifFalse:[
+ "JV@2012-04-04: Here used to be a code for confirming changes.
+ The has moved to RefactoryChangeManager so all refactorings
+ are also subject to confirmation (is enabled in UserPreferences)"
+ RefactoryChangeManager instance performChange: compositeChangeCollector
+ ].
+ compositeChangeCollector := nil.
+ ]
+ ]
+
+ "Modified (comment): / 04-08-2011 / 17:30:27 / cg"
+ "Modified (format): / 04-04-2012 / 16:35:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+startCollectChanges
+ (self canUseRefactoringSupport) ifTrue:[
+ compositeChangeCollector isNil ifTrue:[
+ compositeChangeCollector := CompositeRefactoryChange new.
+ compositeChangeNesting := 0.
+ ].
+ compositeChangeNesting := compositeChangeNesting + 1.
+ ]
+! !
+
+!CustomCodeGeneratorAbstract methodsFor:'code generation interface'!
+
+canGenerate: aClass
+ "tell whether code generation on given class is possible"
+
+ self subclassResponsibility.
+
+ "Created: / 23-08-2013 / 22:36:56 / user"
+!
+
+generate: aClass
+ "interface for code generation"
+
+ self subclassResponsibility.
+
+ "Created: / 23-08-2013 / 22:34:18 / user"
+! !
+
+!CustomCodeGeneratorAbstract methodsFor:'compilation'!
+
+compile:theCode forClass:aClass inCategory:cat
+ "install some code for a class.
+ If refactory browser stuff is avaliable the refactory tools are used to support undo"
+
+ self
+ compile:theCode forClass:aClass inCategory:cat
+ skipIfSame:true
+!
+
+compile:theCode forClass:aClass inCategory:cat skipIfSame:skipIfSame
+ "install some code for a class.
+ If refactory browser stuff is avaliable the refactory tools are used to support undo"
+
+ |change compiler selector oldMthd isSame|
+
+ isSame := false.
+ skipIfSame ifTrue:[
+ compiler := aClass compilerClass new.
+ compiler parseMethod:theCode in:aClass ignoreErrors:true ignoreWarnings:true.
+
+ selector := compiler selector.
+ selector notNil ifTrue:[
+ oldMthd := aClass compiledMethodAt:selector.
+ isSame := (oldMthd notNil and:[oldMthd source = theCode]).
+ isSame ifTrue:[^ self ].
+ ].
+ ].
+
+ self canUseRefactoringSupport ifFalse:[
+ "/ compile immediately
+ aClass compile:theCode classified:cat.
+ ^ self.
+ ].
+
+ change := InteractiveAddMethodChange compile:(theCode asString) in:aClass classified:cat.
+
+ "/ if collecting, add to changes (to be executed as one change at the end,
+ "/ in order to have only one change in the undo-list (instead of many)
+ compositeChangeCollector notNil ifTrue:[
+ compositeChangeCollector addChange:change
+ ] ifFalse:[
+ RefactoryChangeManager performChange:change.
+ ]
+
+ "Modified: / 21-08-2006 / 18:39:06 / cg"
+ "Modified (format): / 21-01-2012 / 10:40:59 / cg"
+! !
+
+!CustomCodeGeneratorAbstract methodsFor:'initialization'!
+
+confirmChanges
+ "if true, let user confirm complicated changes; if false, just do it"
+
+ ^ confirmChanges ? true
+
+ "Created: / 04-08-2011 / 17:31:45 / cg"
+!
+
+confirmChanges:aBoolean
+ "if true, let user confirm complicated changes; if false, just do it"
+
+ confirmChanges := aBoolean
+
+ "Created: / 04-08-2011 / 17:26:47 / cg"
+!
+
+initialize
+ userPreferences := UserPreferences current.
+ generateComments := userPreferences generateComments.
+! !
+
+!CustomCodeGeneratorAbstract methodsFor:'private'!
+
+canUseRefactoringSupport
+ "check if refactory browser stuff is avaliable"
+
+ ^ self class canUseRefactoringSupport
+!
+
+privCreateClassResponsibleProtocolFor:aClass
+ "create stubs for the required protocol.
+ aClass may be a a MetaClass or a non-MetaClass"
+
+ |requiredProtocol|
+
+ requiredProtocol := self class missingRequiredProtocolFor:aClass.
+ requiredProtocol do:[:eachSelector |
+ |code implClass|
+
+ implClass := aClass whichClassImplements:eachSelector.
+ implClass == Object ifFalse:[
+ code := self codeFor_shouldImplementFor:eachSelector inClass:aClass.
+
+ self
+ compile:code
+ forClass:aClass
+ inCategory:(implClass compiledMethodAt:eachSelector) category.
+ ]
+ ].
+! !
+
+!CustomCodeGeneratorAbstract class methodsFor:'documentation'!
+
+version
+ ^ '$Header: /cvs/stx/stx/libtool/CustomCodeGeneratorAbstract.st,v 1.100 2012-10-15 20:17:19 cg Exp $'
+!
+
+version_CVS
+ ^ '$Header: /cvs/stx/stx/libtool/CustomCodeGeneratorAbstract.st,v 1.100 2012-10-15 20:17:19 cg Exp $'
+!
+
+version_HG
+
+ ^ '$Changeset: <not expanded> $'
+!
+
+version_SVN
+ ^ '$Id: CustomCodeGeneratorAbstract.st 8074 2012-11-30 17:23:39Z vranyj1 $'
+! !
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/VisitorCodeGeneratorTests.st Sun Dec 08 21:42:38 2013 +0100
@@ -0,0 +1,40 @@
+"{ Package: 'jn:refactoring_custom' }"
+
+TestCase subclass:#VisitorCodeGeneratorTests
+ instanceVariableNames:''
+ classVariableNames:''
+ poolDictionaries:''
+ category:'Interface-Refactoring-Custom-Tests'
+!
+
+!VisitorCodeGeneratorTests methodsFor:'tests'!
+
+test_dummy
+
+ self assert: 'a' = 'a'.
+
+ "Created: / 25-08-2013 / 09:46:14 / user"
+!
+
+test_visitor_pattern_methods_generated
+ "check if methods for visitor pattern are correctly generated"
+
+ |codeGenerator aClass|
+
+ codeGenerator := VisitorCodeGenerator new.
+ aClass := DummyTests.
+
+ self assert: ((aClass includesSelector:#'visit:') not).
+
+ codeGenerator generate: aClass.
+
+ self assert: (aClass includesSelector:#'visit:').
+
+ aClass removeSelector:#'visit:'.
+
+ self assert: ((aClass includesSelector:#'visit:') not).
+
+ "Created: / 25-08-2013 / 09:44:35 / user"
+ "Modified: / 03-09-2013 / 21:52:14 / user"
+! !
+