test
authorJakub Nesveda <jakubnesveda@seznam.cz>
Sun, 08 Dec 2013 21:42:38 +0100
changeset 502 4f90bc3ddf5b
parent 500 8c2b58d6b2d5 (current diff)
parent 501 871eb6e02f78 (diff)
child 503 343e97659160
test
CustomDummyTests.st
CustomVisitorCodeGenerator.st
Make.proto
Make.spec
abbrev.stc
bc.mak
jn_refactoring_custom.st
libInit.cc
refactoring_custom.rc
--- /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"
+! !
+