forked from qt-creator/qt-creator
QmlDesigner: fix crash at RewriterView::amendQmlText()
RewriterView does not own m_textModifier, so it needs to be checked.
Especially if it is called by a timer like in the amendQmlText() case.
With m_textToModelMerger, its a different story because its
an owned unique_ptr. So no need to check it.
Change-Id: If19b58cc94ec5e8ddd68a8c12acba0f880cbdc6b
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
(cherry picked from commit 6bcf4c9dc7
)
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -196,7 +196,7 @@ private: //variables
|
||||
void handleProjectUpdate();
|
||||
bool inErrorState() const { return !m_rewritingErrorMessage.isEmpty(); }
|
||||
|
||||
TextModifier *m_textModifier = nullptr;
|
||||
QPointer<TextModifier> m_textModifier;
|
||||
int transactionLevel = 0;
|
||||
bool m_modificationGroupActive = false;
|
||||
bool m_checkSemanticErrors = true;
|
||||
|
@@ -88,6 +88,7 @@ Internal::TextToModelMerger *RewriterView::textToModelMerger() const
|
||||
|
||||
void RewriterView::modelAttached(Model *model)
|
||||
{
|
||||
QTC_ASSERT(m_textModifier, return);
|
||||
m_modelAttachPending = false;
|
||||
|
||||
AbstractView::modelAttached(model);
|
||||
@@ -431,7 +432,7 @@ void RewriterView::deactivateTextMofifierChangeSignals()
|
||||
|
||||
void RewriterView::auxiliaryDataChanged(const ModelNode &, AuxiliaryDataKeyView key, const QVariant &)
|
||||
{
|
||||
if (m_restoringAuxData)
|
||||
if (m_restoringAuxData || !m_textModifier)
|
||||
return;
|
||||
|
||||
if (key.type == AuxiliaryDataType::Document)
|
||||
@@ -488,9 +489,9 @@ void RewriterView::amendQmlText()
|
||||
|
||||
if (!model()->rewriterView())
|
||||
return;
|
||||
QTC_ASSERT(m_textModifier, return);
|
||||
|
||||
emitCustomNotification(StartRewriterAmend);
|
||||
|
||||
const QString newQmlText = m_textModifier->text();
|
||||
|
||||
ModelAmender differenceHandler(m_textToModelMerger.data());
|
||||
@@ -754,6 +755,7 @@ void RewriterView::enterErrorState(const QString &errorMessage)
|
||||
|
||||
void RewriterView::resetToLastCorrectQml()
|
||||
{
|
||||
QTC_ASSERT(m_textModifier, return);
|
||||
m_textModifier->textDocument()->undo();
|
||||
m_textModifier->textDocument()->clearUndoRedoStacks(QTextDocument::RedoStack);
|
||||
ModelAmender differenceHandler(m_textToModelMerger.data());
|
||||
@@ -766,6 +768,7 @@ void RewriterView::resetToLastCorrectQml()
|
||||
|
||||
QMap<ModelNode, QString> RewriterView::extractText(const QList<ModelNode> &nodes) const
|
||||
{
|
||||
QTC_ASSERT(m_textModifier, return {});
|
||||
QmlDesigner::ASTObjectTextExtractor extract(m_textModifier->text());
|
||||
QMap<ModelNode, QString> result;
|
||||
|
||||
@@ -792,6 +795,7 @@ int RewriterView::nodeOffset(const ModelNode &node) const
|
||||
*/
|
||||
int RewriterView::nodeLength(const ModelNode &node) const
|
||||
{
|
||||
QTC_ASSERT(m_textModifier, return -1);
|
||||
ObjectLengthCalculator objectLengthCalculator;
|
||||
unsigned length;
|
||||
if (objectLengthCalculator(m_textModifier->text(), nodeOffset(node), length))
|
||||
@@ -802,12 +806,14 @@ int RewriterView::nodeLength(const ModelNode &node) const
|
||||
|
||||
int RewriterView::firstDefinitionInsideOffset(const ModelNode &node) const
|
||||
{
|
||||
QTC_ASSERT(m_textModifier, return -1);
|
||||
FirstDefinitionFinder firstDefinitionFinder(m_textModifier->text());
|
||||
return firstDefinitionFinder(nodeOffset(node));
|
||||
}
|
||||
|
||||
int RewriterView::firstDefinitionInsideLength(const ModelNode &node) const
|
||||
{
|
||||
QTC_ASSERT(m_textModifier, return -1);
|
||||
FirstDefinitionFinder firstDefinitionFinder(m_textModifier->text());
|
||||
const int offset = firstDefinitionFinder(nodeOffset(node));
|
||||
|
||||
@@ -831,6 +837,7 @@ static bool isInNodeDefinition(int nodeTextOffset, int nodeTextLength, int curso
|
||||
|
||||
ModelNode RewriterView::nodeAtTextCursorPositionHelper(const ModelNode &root, int cursorPosition) const
|
||||
{
|
||||
QTC_ASSERT(m_textModifier, return {});
|
||||
using myPair = std::pair<ModelNode,int>;
|
||||
std::vector<myPair> data;
|
||||
|
||||
@@ -1080,36 +1087,35 @@ void RewriterView::qmlTextChanged()
|
||||
{
|
||||
if (inErrorState())
|
||||
return;
|
||||
QTC_ASSERT(m_textModifier, return);
|
||||
|
||||
if (m_textToModelMerger && m_textModifier) {
|
||||
const QString newQmlText = m_textModifier->text();
|
||||
const QString newQmlText = m_textModifier->text();
|
||||
|
||||
#if 0
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "old:" << lastCorrectQmlSource;
|
||||
qDebug() << "new:" << newQmlText;
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "old:" << lastCorrectQmlSource;
|
||||
qDebug() << "new:" << newQmlText;
|
||||
#endif
|
||||
|
||||
switch (m_differenceHandling) {
|
||||
case Validate: {
|
||||
ModelValidator differenceHandler(m_textToModelMerger.data());
|
||||
if (m_textToModelMerger->load(newQmlText, differenceHandler))
|
||||
m_lastCorrectQmlSource = newQmlText;
|
||||
break;
|
||||
}
|
||||
switch (m_differenceHandling) {
|
||||
case Validate: {
|
||||
ModelValidator differenceHandler(m_textToModelMerger.data());
|
||||
if (m_textToModelMerger->load(newQmlText, differenceHandler))
|
||||
m_lastCorrectQmlSource = newQmlText;
|
||||
break;
|
||||
}
|
||||
|
||||
case Amend: {
|
||||
if (m_instantQmlTextUpdate || externalDependencies().instantQmlTextUpdate()) {
|
||||
amendQmlText();
|
||||
} else {
|
||||
if (externalDependencies().viewManagerUsesRewriterView(this)) {
|
||||
externalDependencies().viewManagerDiableWidgets();
|
||||
m_amendTimer.start();
|
||||
}
|
||||
case Amend: {
|
||||
if (m_instantQmlTextUpdate || externalDependencies().instantQmlTextUpdate()) {
|
||||
amendQmlText();
|
||||
} else {
|
||||
if (externalDependencies().viewManagerUsesRewriterView(this)) {
|
||||
externalDependencies().viewManagerDiableWidgets();
|
||||
m_amendTimer.start();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user