- About the Undo System
- How to Refer Other Snappers
- Minimizing the Test Case
- Tracing
- Tracing Flags
- UndoChain.debug()
- Chain of Reference
- Check the Consistency of All Snappers in Space
About the Undo System
To be able to debug an undo crash, you must first know a little about how undo works.
Undo stores information about snappers, like insert, remove and modify operations. The modify operations in particular store deep copies of the snappers as they were before the change took place. When the user performs undo, the current active snappers on the drawing are replaced by the stored copies.
How to Refer Other Snappers
If they do, you should normally not have any undo problems. (At least not that is caused by snappers. Problems caused be Animations or Dialogs that modifies snappers and also records undo operations is another thing.) But if one of your snappers, let's say a Table, has a field that refers to an attached Chair (not using a Connector), you are at risk. When undo is replacing the snappers (perhaps both the Table and the Chair), your Table will still be referring to the old Chair, not the one that has replaced it.
updateReplaced()
method:/** * Update replaced snappers - undo event. * * Makes it possible for a snapper with internal references to other snappers to * remap those references after an undo restore action has been performed. * * Use the 'oldToNew' map for translation. */ public void updateReplaced(Snapper->Snapper oldToNew, Snapper{} visited) {
Minimizing the Test Case
Let's say you have a crash that occurs when you modify some snappers and then press undo. Save the drawing just prior to the last change you do before the crash (using SaveTest). Then load it, perform the change and hit undo. If you still get the crash, you are on your way.
Then try to minimize the scene itself by removing as many snappers as possible while still being able to repeat the error. Minimizing the scene and the steps to reproduce the crash will help a lot when you are tracing to figure out what's wrong.
Tracing
Snappers can have a few different states when it comes to their "aliveness" in relation to undo.
- Active - normal state, the snapper is alive and (normally) visible and belongs to a Space
- Suspended - the snapper belongs to a Space but is only alive in the UndoChain
- Dead - the snapper does not belong to any Space
We also have:
- Alive - the opposite of dead (so both active and suspended snappers are considered alive)
- Doomed - this means that the snapper is about to be removed (transient state)
Tracing Flags
In base/cm/core/undoChain.cm you can find a variety of flags that are intended to help debug the undo system. Here are a few flags:
- dbg_traceStepsSimple - traces steps as they are added to the system.
- dbs_traceStepsNesting - traces steps as they are added and includes any nested steps.
- dbg_traceOpNesting - traces the recording of individual operations as they are added to the UndoStack.
UndoChain.debug()
The undo chain has a built-in method that developers find helpful from time to time. This code can be called at any time for the mainWorld's undoChain by using the following code:
mainWorld.undoChain.debug();
This code is also found in base/cm/core/undoChain.cm, which means if you "run" this file you can see the undo traces there.
The output of this function looks something like this:
With the "current position" being the place between "Undoable" actions and "Redoable" actions.
Chain of Reference
It might be the case that your Table is referring to a Chair, but you don't know how, because there might be many super-classes above Table and the chair can also be referred to by subobjects at any level.
Try turning on "undoDebugMode" in cm/core/undo/undoChain.cm. This might give you an early catch of the error. What you are looking for is probably the info printed out before cant happen in UndoModifyOp. If all is well, you might get a direct chain of reference from the traceReferences call just before the exception. If not, try working with the different versions of traceReferences that are available in cm/runtime/util/traceReferences.cm
.
This is an example output from traceReferences, from a lamp to it's (properly) connected lamp shade:
TestLamp((id=3, orig)) TestLamp.shadeAttach TestLamp.shadeAttach._connection TestLampShade.lampSnap.snapper + TestLampShade((id=4, orig))
Check the Consistency of All Snappers in Space
dbg_seriouslySeriousCheckConsistency
on a space to get a good printout of how the snappers in it are connected to each other.To run it on the main space in the active drawing, use the following code:
cm.core.session.mainSpace.dbg_seriouslySeriousCheckConsistency();
Comments
0 comments
Please sign in to leave a comment.