From 66d49e6a53a9c535a9eb277f2bcd50e0fc3f4cfc Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 2 Aug 2023 13:56:28 +0200 Subject: [PATCH] TextEditor: Fix crash on reloading the document as part of the reload operation we set the document to nullptr inside TextBlockUserData::documentClosing, but we do not remove the mark from the marks cache. So when a text mark gets deleted while a document is reloaded the mark does not get readded to the document, but it wont get removed from the marks cache inside the document either, so we have to manually make sure the mark is removed from the cache in this situation. Fixes: QTCREATORBUG-29432 Change-Id: I3ae4182c4d2bbd3426c1d7a60275d21ac20ea99a Reviewed-by: Reviewed-by: Jarek Kobus --- src/plugins/texteditor/textdocument.cpp | 2 +- src/plugins/texteditor/textdocumentlayout.cpp | 34 +++++++++++++++++-- src/plugins/texteditor/textdocumentlayout.h | 2 +- src/plugins/texteditor/texteditorplugin.h | 2 ++ 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index f8512e9a111..98a3eda4a1e 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -837,7 +837,7 @@ bool TextDocument::reload(QString *errorString, const FilePath &realFilePath) auto documentLayout = qobject_cast(d->m_document.documentLayout()); if (documentLayout) - documentLayout->documentAboutToReload(); // removes text marks non-permanently + documentLayout->documentAboutToReload(this); // removes text marks non-permanently bool success = openImpl(errorString, filePath(), realFilePath, /*reload =*/true) == OpenResult::Success; diff --git a/src/plugins/texteditor/textdocumentlayout.cpp b/src/plugins/texteditor/textdocumentlayout.cpp index 08c1e21117b..a1a04e44479 100644 --- a/src/plugins/texteditor/textdocumentlayout.cpp +++ b/src/plugins/texteditor/textdocumentlayout.cpp @@ -4,9 +4,14 @@ #include "textdocumentlayout.h" #include "fontsettings.h" #include "textdocument.h" +#include "texteditorplugin.h" #include "texteditorsettings.h" + #include +#include + #include +#include namespace TextEditor { @@ -667,11 +672,15 @@ TextMarks TextDocumentLayout::documentClosing() return marks; } -void TextDocumentLayout::documentAboutToReload() +void TextDocumentLayout::documentAboutToReload(TextDocument *baseTextDocument) { m_reloadMarks = documentClosing(); - for (TextMark *mark : std::as_const(m_reloadMarks)) - mark->setDeleteCallback([this, mark] { m_reloadMarks.removeOne(mark); }); + for (TextMark *mark : std::as_const(m_reloadMarks)) { + mark->setDeleteCallback([this, mark, baseTextDocument] { + baseTextDocument->removeMarkFromMarksCache(mark); + m_reloadMarks.removeOne(mark); + }); + } } void TextDocumentLayout::documentReloaded(TextDocument *baseTextDocument) @@ -860,4 +869,23 @@ TextSuggestion::TextSuggestion() TextSuggestion::~TextSuggestion() = default; +#ifdef WITH_TESTS + +void Internal::TextEditorPlugin::testDeletingMarkOnReload() +{ + auto doc = new TextDocument(); + doc->setFilePath(Utils::TemporaryDirectory::masterDirectoryFilePath() / "TestMarkDoc.txt"); + doc->setPlainText("asd"); + auto documentLayout = qobject_cast(doc->document()->documentLayout()); + QVERIFY(documentLayout); + auto mark = new TextMark(doc, 1, TextMarkCategory{"testMark","testMark"}); + QVERIFY(doc->marks().contains(mark)); + documentLayout->documentAboutToReload(doc); // removes text marks non-permanently + delete mark; + documentLayout->documentReloaded(doc); // re-adds text marks + QVERIFY(!doc->marks().contains(mark)); +} + +#endif + } // namespace TextEditor diff --git a/src/plugins/texteditor/textdocumentlayout.h b/src/plugins/texteditor/textdocumentlayout.h index 33387093da7..427500a8326 100644 --- a/src/plugins/texteditor/textdocumentlayout.h +++ b/src/plugins/texteditor/textdocumentlayout.h @@ -246,7 +246,7 @@ public: QRectF blockBoundingRect(const QTextBlock &block) const override; TextMarks documentClosing(); - void documentAboutToReload(); + void documentAboutToReload(TextDocument *baseTextDocument); void documentReloaded(TextDocument *baseextDocument); void updateMarksLineNumber(); void updateMarksBlock(const QTextBlock &block); diff --git a/src/plugins/texteditor/texteditorplugin.h b/src/plugins/texteditor/texteditorplugin.h index 3df46c0b578..f5725061950 100644 --- a/src/plugins/texteditor/texteditorplugin.h +++ b/src/plugins/texteditor/texteditorplugin.h @@ -40,6 +40,8 @@ private slots: void testFormatting_data(); void testFormatting(); + + void testDeletingMarkOnReload(); #endif };