From 10129e2dfc582915d999e24deed34f7303a6f02e Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 23 Jun 2020 12:12:19 +0200 Subject: sw doc model xml dump: improve undo-redo coverage: - show the undo manager's node array - show SwUndoDelete - show SwUndoSaveContent - show SwHistory - show SwHistoryHint - show SwHistoryTextFlyCnt - show SwUndoFlyBase - show SwHistorySetFormat - show SwUndoInserts When an action + undo pair goes wrong, it's easier to see the state of the undo stack after the action this way, then decide if the undo stack is already bad, or the problem is with the undo implementation. Change-Id: Ic509a233dce3c47db9697982eb7ea423f4706129 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96930 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- sw/inc/undobj.hxx | 7 ++++- sw/source/core/inc/UndoDelete.hxx | 2 ++ sw/source/core/inc/UndoManager.hxx | 1 + sw/source/core/inc/rolbck.hxx | 6 ++++ sw/source/core/layout/atrfrm.cxx | 7 ++++- sw/source/core/undo/docundo.cxx | 14 ++++++++++ sw/source/core/undo/rolbck.cxx | 56 ++++++++++++++++++++++++++++++++++++++ sw/source/core/undo/undel.cxx | 12 ++++++++ sw/source/core/undo/undobj.cxx | 15 ++++++++++ sw/source/core/undo/undobj1.cxx | 24 ++++++++++++++++ sw/source/core/undo/unins.cxx | 3 -- sw/source/core/undo/untblk.cxx | 35 ++++++++++++++++++++++++ 12 files changed, 177 insertions(+), 5 deletions(-) (limited to 'sw') diff --git a/sw/inc/undobj.hxx b/sw/inc/undobj.hxx index bd6748d656a0..60d219bc0109 100644 --- a/sw/inc/undobj.hxx +++ b/sw/inc/undobj.hxx @@ -42,6 +42,7 @@ class SwRedlineData; class SwRedlineSaveDatas; enum class RedlineFlags; enum class RndStdIds; +typedef struct _xmlTextWriter* xmlTextWriterPtr; namespace sw { class UndoRedoContext; @@ -191,7 +192,8 @@ protected: public: SwUndoSaveContent(); - ~SwUndoSaveContent() COVERITY_NOEXCEPT_FALSE; + virtual ~SwUndoSaveContent() COVERITY_NOEXCEPT_FALSE; + virtual void dumpAsXml(xmlTextWriterPtr pWriter) const; }; // Save a complete section in nodes-array. @@ -274,6 +276,8 @@ public: static bool IsCreateUndoForNewFly(SwFormatAnchor const& rAnchor, sal_uLong const nStartNode, sal_uLong const nEndNode); std::vector * GetFlysAnchoredAt() { return m_pFrameFormats.get(); } + + void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; class SwUndoInsDoc final : public SwUndoInserts @@ -307,6 +311,7 @@ protected: public: virtual ~SwUndoFlyBase() override; + void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; diff --git a/sw/source/core/inc/UndoDelete.hxx b/sw/source/core/inc/UndoDelete.hxx index ce38a4d99e03..6e38201f3443 100644 --- a/sw/source/core/inc/UndoDelete.hxx +++ b/sw/source/core/inc/UndoDelete.hxx @@ -27,6 +27,7 @@ class SwRedlineSaveDatas; class SwTextNode; +typedef struct _xmlTextWriter* xmlTextWriterPtr; namespace sfx2 { class MetadatableUndo; @@ -101,6 +102,7 @@ public: bool IsDelFullPara() const { return m_bDelFullPara; } void DisableMakeFrames() { m_bDisableMakeFrames = true; }; + void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; #endif // INCLUDED_SW_SOURCE_CORE_INC_UNDODELETE_HXX diff --git a/sw/source/core/inc/UndoManager.hxx b/sw/source/core/inc/UndoManager.hxx index fda9c734a7e6..4113d54d8f52 100644 --- a/sw/source/core/inc/UndoManager.hxx +++ b/sw/source/core/inc/UndoManager.hxx @@ -86,6 +86,7 @@ public: bool bTryMerg = false) override; virtual bool Undo() override; virtual bool Redo() override; + void dumpAsXml(xmlTextWriterPtr pWriter) const; SwUndo * RemoveLastUndo(); SwUndo * GetLastUndo(); diff --git a/sw/source/core/inc/rolbck.hxx b/sw/source/core/inc/rolbck.hxx index 1882a68d1d0e..96a8eb58b7d9 100644 --- a/sw/source/core/inc/rolbck.hxx +++ b/sw/source/core/inc/rolbck.hxx @@ -54,6 +54,7 @@ class SwFormatChain; class SwNode; class SwCharFormat; enum class SwFieldIds : sal_uInt16; +typedef struct _xmlTextWriter* xmlTextWriterPtr; enum HISTORY_HINT { HSTRY_SETFMTHNT, @@ -85,6 +86,7 @@ public: virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet ) = 0; HISTORY_HINT Which() const { return m_eWhichId; } virtual OUString GetDescription() const; + virtual void dumpAsXml(xmlTextWriterPtr pWriter) const; }; class SwHistorySetFormat : public SwHistoryHint @@ -98,6 +100,7 @@ public: virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet ) override; virtual OUString GetDescription() const override; + void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; class SwHistoryResetFormat : public SwHistoryHint @@ -234,6 +237,7 @@ public: virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet ) override; SwUndoDelLayFormat* GetUDelLFormat() { return m_pUndo.get(); } + void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; class SwHistoryBookmark : public SwHistoryHint @@ -400,6 +404,8 @@ public: const bool bCopyFields ); void CopyFormatAttr( const SfxItemSet& rSet, sal_uLong nNodeIdx ); + + void dumpAsXml(xmlTextWriterPtr pWriter) const; }; class SwRegHistory : public SwClient diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx index ae9311d2231d..976b38ce997e 100644 --- a/sw/source/core/layout/atrfrm.cxx +++ b/sw/source/core/layout/atrfrm.cxx @@ -577,7 +577,12 @@ void SwFormatContent::dumpAsXml(xmlTextWriterPtr pWriter) const { xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatContent")); xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); - xmlTextWriterWriteAttribute(pWriter, BAD_CAST("startNode"), BAD_CAST(OString::number(m_pStartNode->GetNode().GetIndex()).getStr())); + if (m_pStartNode) + { + xmlTextWriterWriteAttribute( + pWriter, BAD_CAST("startNode"), + BAD_CAST(OString::number(m_pStartNode->GetNode().GetIndex()).getStr())); + } xmlTextWriterEndElement(pWriter); } diff --git a/sw/source/core/undo/docundo.cxx b/sw/source/core/undo/docundo.cxx index 61629e087bc7..ce416250f2b6 100644 --- a/sw/source/core/undo/docundo.cxx +++ b/sw/source/core/undo/docundo.cxx @@ -19,6 +19,8 @@ #include +#include + #include #include #include @@ -651,6 +653,18 @@ bool UndoManager::Redo() } } +void UndoManager::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("swUndoManager")); + SdrUndoManager::dumpAsXml(pWriter); + + xmlTextWriterStartElement(pWriter, BAD_CAST("m_xUndoNodes")); + m_xUndoNodes->dumpAsXml(pWriter); + xmlTextWriterEndElement(pWriter); + + xmlTextWriterEndElement(pWriter); +} + void UndoManager::EmptyActionsChanged() { if (m_pDocShell) diff --git a/sw/source/core/undo/rolbck.cxx b/sw/source/core/undo/rolbck.cxx index 2de4c627109e..8806f4f690c3 100644 --- a/sw/source/core/undo/rolbck.cxx +++ b/sw/source/core/undo/rolbck.cxx @@ -18,6 +18,9 @@ */ #include + +#include + #include #include #include @@ -61,6 +64,16 @@ OUString SwHistoryHint::GetDescription() const return OUString(); } +void SwHistoryHint::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwHistoryHint")); + xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("symbol"), BAD_CAST(typeid(*this).name())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_eWhichId"), + BAD_CAST(OString::number(m_eWhichId).getStr())); + xmlTextWriterEndElement(pWriter); +} + SwHistorySetFormat::SwHistorySetFormat( const SfxPoolItem* pFormatHt, sal_uLong nNd ) : SwHistoryHint( HSTRY_SETFMTHNT ) , m_pAttr( pFormatHt->Clone() ) @@ -133,6 +146,21 @@ OUString SwHistorySetFormat::GetDescription() const return aResult; } +void SwHistorySetFormat::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwHistorySetFormat")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nNodeIndex"), + BAD_CAST(OString::number(m_nNodeIndex).getStr())); + SwHistoryHint::dumpAsXml(pWriter); + + if (m_pAttr) + { + m_pAttr->dumpAsXml(pWriter); + } + + xmlTextWriterEndElement(pWriter); +} + void SwHistorySetFormat::SetInDoc( SwDoc* pDoc, bool bTmpSet ) { SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ]; @@ -553,6 +581,19 @@ void SwHistoryTextFlyCnt::SetInDoc( SwDoc* pDoc, bool ) m_pUndo->UndoImpl(context); } +void SwHistoryTextFlyCnt::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwHistoryTextFlyCnt")); + SwHistoryHint::dumpAsXml(pWriter); + + if (m_pUndo) + { + m_pUndo->dumpAsXml(pWriter); + } + + xmlTextWriterEndElement(pWriter); +} + SwHistoryBookmark::SwHistoryBookmark( const ::sw::mark::IMark& rBkmk, bool bSavePos, @@ -1241,6 +1282,21 @@ void SwHistory::CopyFormatAttr( } } +void SwHistory::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwHistory")); + xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); + + xmlTextWriterStartElement(pWriter, BAD_CAST("m_SwpHstry")); + for (const auto& pHistory : m_SwpHstry) + { + pHistory->dumpAsXml(pWriter); + } + xmlTextWriterEndElement(pWriter); + + xmlTextWriterEndElement(pWriter); +} + void SwHistory::CopyAttr( SwpHints const * pHts, const sal_uLong nNodeIdx, diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx index d225d1eb2868..cc001373cc37 100644 --- a/sw/source/core/undo/undel.cxx +++ b/sw/source/core/undo/undel.cxx @@ -18,6 +18,9 @@ */ #include + +#include + #include #include #include @@ -1313,4 +1316,13 @@ void SwUndoDelete::SetTableName(const OUString & rName) m_sTableName = rName; } +void SwUndoDelete::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwUndoDelete")); + xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); + SwUndo::dumpAsXml(pWriter); + SwUndoSaveContent::dumpAsXml(pWriter); + xmlTextWriterEndElement(pWriter); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx index aca9012898c9..b2609a228813 100644 --- a/sw/source/core/undo/undobj.cxx +++ b/sw/source/core/undo/undobj.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include #include @@ -702,6 +704,19 @@ SwUndoSaveContent::~SwUndoSaveContent() COVERITY_NOEXCEPT_FALSE { } +void SwUndoSaveContent::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwUndoSaveContent")); + xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); + + if (m_pHistory) + { + m_pHistory->dumpAsXml(pWriter); + } + + xmlTextWriterEndElement(pWriter); +} + // This is needed when deleting content. For REDO all contents will be moved // into the UndoNodesArray. These methods always create a new node to insert // content. As a result, the attributes will not be expanded. diff --git a/sw/source/core/undo/undobj1.cxx b/sw/source/core/undo/undobj1.cxx index 51ba206af391..b9757d267850 100644 --- a/sw/source/core/undo/undobj1.cxx +++ b/sw/source/core/undo/undobj1.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include #include @@ -60,6 +62,28 @@ SwUndoFlyBase::~SwUndoFlyBase() } } +void SwUndoFlyBase::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwUndoFlyBase")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nNodePagePos"), + BAD_CAST(OString::number(m_nNodePagePos).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nContentPos"), + BAD_CAST(OString::number(m_nContentPos).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nRndId"), + BAD_CAST(OString::number(static_cast(m_nRndId)).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_bDelFormat"), + BAD_CAST(OString::boolean(m_bDelFormat).getStr())); + + SwUndo::dumpAsXml(pWriter); + + if (m_pFrameFormat) + { + m_pFrameFormat->dumpAsXml(pWriter); + } + + xmlTextWriterEndElement(pWriter); +} + void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrame) { SwDoc *const pDoc = & rContext.GetDoc(); diff --git a/sw/source/core/undo/unins.cxx b/sw/source/core/undo/unins.cxx index 6e08fb5027e5..dc5303c16808 100644 --- a/sw/source/core/undo/unins.cxx +++ b/sw/source/core/undo/unins.cxx @@ -490,9 +490,6 @@ class SwUndoReplace::Impl public: Impl(SwPaM const& rPam, OUString const& rIns, bool const bRegExp); - virtual ~Impl() - { - } void UndoImpl( ::sw::UndoRedoContext & ); void RedoImpl( ::sw::UndoRedoContext & ); diff --git a/sw/source/core/undo/untblk.cxx b/sw/source/core/undo/untblk.cxx index 2a4b489d1e29..6df02f3f805d 100644 --- a/sw/source/core/undo/untblk.cxx +++ b/sw/source/core/undo/untblk.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include #include @@ -178,6 +180,39 @@ bool SwUndoInserts::IsCreateUndoForNewFly(SwFormatAnchor const& rAnchor, || nEndNode == pAnchorPos->nNode.GetIndex()); } +void SwUndoInserts::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwUndoInserts")); + xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); + xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", + BAD_CAST(typeid(*this).name())); + + SwUndo::dumpAsXml(pWriter); + SwUndoSaveContent::dumpAsXml(pWriter); + + if (m_pFrameFormats) + { + xmlTextWriterStartElement(pWriter, BAD_CAST("m_pFrameFormats")); + for (const auto& pFormat : *m_pFrameFormats) + { + pFormat->dumpAsXml(pWriter); + } + xmlTextWriterEndElement(pWriter); + } + + if (!m_FlyUndos.empty()) + { + xmlTextWriterStartElement(pWriter, BAD_CAST("m_FlyUndos")); + for (const auto& pFly : m_FlyUndos) + { + pFly->dumpAsXml(pWriter); + } + xmlTextWriterEndElement(pWriter); + } + + xmlTextWriterEndElement(pWriter); +} + SwUndoInserts::~SwUndoInserts() { if (m_pUndoNodeIndex) // delete also the section from UndoNodes array -- cgit v1.2.3