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: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
David Schulz
2023-08-02 13:56:28 +02:00
parent 8d554aba1a
commit 66d49e6a53
4 changed files with 35 additions and 5 deletions

View File

@@ -837,7 +837,7 @@ bool TextDocument::reload(QString *errorString, const FilePath &realFilePath)
auto documentLayout = auto documentLayout =
qobject_cast<TextDocumentLayout*>(d->m_document.documentLayout()); qobject_cast<TextDocumentLayout*>(d->m_document.documentLayout());
if (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) bool success = openImpl(errorString, filePath(), realFilePath, /*reload =*/true)
== OpenResult::Success; == OpenResult::Success;

View File

@@ -4,9 +4,14 @@
#include "textdocumentlayout.h" #include "textdocumentlayout.h"
#include "fontsettings.h" #include "fontsettings.h"
#include "textdocument.h" #include "textdocument.h"
#include "texteditorplugin.h"
#include "texteditorsettings.h" #include "texteditorsettings.h"
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/temporarydirectory.h>
#include <QDebug> #include <QDebug>
#include <QTest>
namespace TextEditor { namespace TextEditor {
@@ -667,11 +672,15 @@ TextMarks TextDocumentLayout::documentClosing()
return marks; return marks;
} }
void TextDocumentLayout::documentAboutToReload() void TextDocumentLayout::documentAboutToReload(TextDocument *baseTextDocument)
{ {
m_reloadMarks = documentClosing(); m_reloadMarks = documentClosing();
for (TextMark *mark : std::as_const(m_reloadMarks)) for (TextMark *mark : std::as_const(m_reloadMarks)) {
mark->setDeleteCallback([this, mark] { m_reloadMarks.removeOne(mark); }); mark->setDeleteCallback([this, mark, baseTextDocument] {
baseTextDocument->removeMarkFromMarksCache(mark);
m_reloadMarks.removeOne(mark);
});
}
} }
void TextDocumentLayout::documentReloaded(TextDocument *baseTextDocument) void TextDocumentLayout::documentReloaded(TextDocument *baseTextDocument)
@@ -860,4 +869,23 @@ TextSuggestion::TextSuggestion()
TextSuggestion::~TextSuggestion() = default; 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<TextDocumentLayout *>(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 } // namespace TextEditor

View File

@@ -246,7 +246,7 @@ public:
QRectF blockBoundingRect(const QTextBlock &block) const override; QRectF blockBoundingRect(const QTextBlock &block) const override;
TextMarks documentClosing(); TextMarks documentClosing();
void documentAboutToReload(); void documentAboutToReload(TextDocument *baseTextDocument);
void documentReloaded(TextDocument *baseextDocument); void documentReloaded(TextDocument *baseextDocument);
void updateMarksLineNumber(); void updateMarksLineNumber();
void updateMarksBlock(const QTextBlock &block); void updateMarksBlock(const QTextBlock &block);

View File

@@ -40,6 +40,8 @@ private slots:
void testFormatting_data(); void testFormatting_data();
void testFormatting(); void testFormatting();
void testDeletingMarkOnReload();
#endif #endif
}; };