So, one of the things the new RB is trying to achieve is a real namespace move refactoring. One of the reasons I'd really like people to start using the new browser is to tell me what I've missed here. I can only come up with so many move scenarios, either automated trhough SUnit, or ad-hoc to test this out. One litmus test though that I wanted to see, I recently passed.
Lets say you wanted to start over again with namespaces in VisualWorks? One of the things that would make that easier, is if nothing were in namespaces right now. Then you could evolve from there. If the RefactoringBrowser could just move EVERY single class back into the base Smalltalk namespace, you might be able to try something like that.
So I sat down and wrote a script to do just that. And then beat away at it until it worked. Here's the script:
"rename any potential conflicts"
all := Set new.
SystemUtils allClassesDo: [:each | all addAll: each].
byName := all groupedBy: #name.
(byName select: [:each | each size > 1])
do:
[:conflicts |
conflicts
do:
[:each |
each environment == Smalltalk
ifFalse:
[each fullName out.
(RenameObjectRefactoring
renameObjectNamed: each fullName
to: each environment name , '_' , each name) execute]]].
all := Set new. "now move everything not already in Smalltalk"
SystemUtils allClassesDo: [:each | all addAll: each].
all := all reject: [:each | each environment == Smalltalk].
all
do:
[:each |
(MoveObjectRefactoring
moveObjectNamed: each absoluteName
to: Smalltalk absoluteName) execute]
The first 2/3's are actualy there to do what we'd have to do if we didn't have namespaces: put prefixes on things. It finds all matching class names, where there are multiples, renames them to include their environment names. So UI.Text and XML.Text become UI_Text and XML_Text. I had a reasonably heavy image when I did this, about 4000 classes, and ran into 50-ish conflicting class names.
And then it goes through the bottom. It's not a cup of coffee process, more like a "go to lunch" process. But in the end, it worked. And... the image was still running and usable. And all of the namespaces were empty. Except for shares. There's some interesting trickery that keeps the bindings alive while a move is in progress. This is especially important for core objects such as Process.
The one caveat, is that it won't work on private classes. VisualWorks base has one such class, and I haven't chased it down. I'm still not sure how I even feel about private classes in this sense. The class isn't so much private, as its binding is private. I would love to hear of anyone else who can do this refactoring on an image with their code loaded, and perhaps even running, and if the thing will make it all the way through. The next stress test will to be create 10 arbitrary namespaces and move every class into a random namespace, and see if the system can stay on it's feet. Wish me luck.