QML: Fix crash when opening context menu

The AssistInterface changed to unique_ptr, but the internals of how the
QmlJSEditor looked for quick fixes still wrapped it into a
QSharedPointer, which then deleted the assist interface in addition to
the unique_ptr.

Amends 0e4b0a26d3

Fixes: QTCREATORBUG-28742
Change-Id: If685dbb2c49b09d529d0dcb3677dc90b03a039f0
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Eike Ziller
2023-02-06 15:32:00 +01:00
committed by David Schulz
parent 8512aba9eb
commit 541aafecbb
7 changed files with 40 additions and 45 deletions

View File

@@ -58,24 +58,22 @@ public:
setDescription(Tr::tr("Move Component into Separate File")); setDescription(Tr::tr("Move Component into Separate File"));
} }
Operation(const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface, Operation(const Internal::QmlJSQuickFixAssistInterface *interface, UiObjectDefinition *objDef)
UiObjectDefinition *objDef) : QmlJSQuickFixOperation(interface, 0)
: QmlJSQuickFixOperation(interface, 0), , m_idName(idOfObject(objDef))
m_idName(idOfObject(objDef)), , m_firstSourceLocation(objDef->firstSourceLocation())
m_firstSourceLocation(objDef->firstSourceLocation()), , m_lastSourceLocation(objDef->lastSourceLocation())
m_lastSourceLocation(objDef->lastSourceLocation()), , m_initializer(objDef->initializer)
m_initializer(objDef->initializer)
{ {
init(); init();
} }
Operation(const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface, Operation(const Internal::QmlJSQuickFixAssistInterface *interface, UiObjectBinding *objDef)
UiObjectBinding *objDef) : QmlJSQuickFixOperation(interface, 0)
: QmlJSQuickFixOperation(interface, 0), , m_idName(idOfObject(objDef))
m_idName(idOfObject(objDef)), , m_firstSourceLocation(objDef->qualifiedTypeNameId->firstSourceLocation())
m_firstSourceLocation(objDef->qualifiedTypeNameId->firstSourceLocation()), , m_lastSourceLocation(objDef->lastSourceLocation())
m_lastSourceLocation(objDef->lastSourceLocation()), , m_initializer(objDef->initializer)
m_initializer(objDef->initializer)
{ {
init(); init();
} }
@@ -223,7 +221,7 @@ public:
} // end of anonymous namespace } // end of anonymous namespace
void matchComponentFromObjectDefQuickFix(const QmlJSQuickFixInterface &interface, QuickFixOperations &result) void matchComponentFromObjectDefQuickFix(const QmlJSQuickFixAssistInterface *interface, QuickFixOperations &result)
{ {
const int pos = interface->currentFile()->cursor().position(); const int pos = interface->currentFile()->cursor().position();
@@ -254,8 +252,7 @@ void performComponentFromObjectDef(const QString &fileName, QmlJS::AST::UiObject
QmlJS::ModelManagerInterface::instance()->snapshot()); QmlJS::ModelManagerInterface::instance()->snapshot());
QmlJSRefactoringFilePtr current = refactoring.file(Utils::FilePath::fromString(fileName)); QmlJSRefactoringFilePtr current = refactoring.file(Utils::FilePath::fromString(fileName));
QmlJSQuickFixInterface interface; Operation operation(nullptr, objDef);
Operation operation(interface, objDef);
operation.performChanges(current, refactoring); operation.performChanges(current, refactoring);
} }

View File

@@ -8,8 +8,8 @@
namespace QmlJSEditor { namespace QmlJSEditor {
QMLJSEDITOR_EXPORT void matchComponentFromObjectDefQuickFix QMLJSEDITOR_EXPORT void matchComponentFromObjectDefQuickFix(
(const QmlJSQuickFixInterface &interface, QuickFixOperations &result); const Internal::QmlJSQuickFixAssistInterface *interface, QuickFixOperations &result);
QMLJSEDITOR_EXPORT void performComponentFromObjectDef QMLJSEDITOR_EXPORT void performComponentFromObjectDef
(const QString &fileName, QmlJS::AST::UiObjectDefinition *objDef); (const QString &fileName, QmlJS::AST::UiObjectDefinition *objDef);

View File

@@ -2,8 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qmljsquickfix.h" #include "qmljsquickfix.h"
#include "qmljscomponentfromobjectdef.h"
#include "qmljseditor.h"
#include "qmljsquickfixassist.h" #include "qmljsquickfixassist.h"
#include <extensionsystem/iplugin.h> #include <extensionsystem/iplugin.h>
@@ -23,30 +21,29 @@ namespace QmlJSEditor {
using namespace Internal; using namespace Internal;
QmlJSQuickFixOperation::QmlJSQuickFixOperation(const QmlJSQuickFixInterface &interface, QmlJSQuickFixOperation::QmlJSQuickFixOperation(const QmlJSQuickFixAssistInterface *interface,
int priority) int priority)
: QuickFixOperation(priority) : QuickFixOperation(priority)
, m_interface(interface) , m_semanticInfo(interface->semanticInfo())
{ {
} }
void QmlJSQuickFixOperation::perform() void QmlJSQuickFixOperation::perform()
{ {
QmlJSRefactoringChanges refactoring(ModelManagerInterface::instance(), QmlJSRefactoringChanges refactoring(ModelManagerInterface::instance(), semanticInfo().snapshot);
m_interface->semanticInfo().snapshot);
QmlJSRefactoringFilePtr current = refactoring.file(fileName()); QmlJSRefactoringFilePtr current = refactoring.file(fileName());
performChanges(current, refactoring); performChanges(current, refactoring);
} }
const QmlJSQuickFixAssistInterface *QmlJSQuickFixOperation::assistInterface() const const QmlJSTools::SemanticInfo &QmlJSQuickFixOperation::semanticInfo() const
{ {
return m_interface.data(); return m_semanticInfo;
} }
Utils::FilePath QmlJSQuickFixOperation::fileName() const Utils::FilePath QmlJSQuickFixOperation::fileName() const
{ {
return m_interface->semanticInfo().document->fileName(); return semanticInfo().document->fileName();
} }
} // namespace QmlJSEditor } // namespace QmlJSEditor

View File

@@ -7,6 +7,7 @@
#include <qmljs/parser/qmljsastfwd_p.h> #include <qmljs/parser/qmljsastfwd_p.h>
#include <qmljs/qmljsdocument.h> #include <qmljs/qmljsdocument.h>
#include <qmljstools/qmljsrefactoringchanges.h> #include <qmljstools/qmljsrefactoringchanges.h>
#include <qmljstools/qmljssemanticinfo.h>
#include <QSharedPointer> #include <QSharedPointer>
@@ -14,7 +15,6 @@ namespace QmlJSEditor {
namespace Internal { class QmlJSQuickFixAssistInterface; } namespace Internal { class QmlJSQuickFixAssistInterface; }
using QmlJSQuickFixInterface = QSharedPointer<const Internal::QmlJSQuickFixAssistInterface>;
using TextEditor::QuickFixOperation; using TextEditor::QuickFixOperation;
using TextEditor::QuickFixOperations; using TextEditor::QuickFixOperations;
using TextEditor::QuickFixInterface; using TextEditor::QuickFixInterface;
@@ -31,7 +31,8 @@ public:
\param interface The interface on which the operation is performed. \param interface The interface on which the operation is performed.
\param priority The priority for this operation. \param priority The priority for this operation.
*/ */
explicit QmlJSQuickFixOperation(const QmlJSQuickFixInterface &interface, int priority = -1); explicit QmlJSQuickFixOperation(const Internal::QmlJSQuickFixAssistInterface *interface,
int priority = -1);
void perform() override; void perform() override;
@@ -41,13 +42,13 @@ protected:
virtual void performChanges(QmlJSTools::QmlJSRefactoringFilePtr currentFile, virtual void performChanges(QmlJSTools::QmlJSRefactoringFilePtr currentFile,
const QmlJSTools::QmlJSRefactoringChanges &refactoring) = 0; const QmlJSTools::QmlJSRefactoringChanges &refactoring) = 0;
const Internal::QmlJSQuickFixAssistInterface *assistInterface() const; const QmlJSTools::SemanticInfo &semanticInfo() const;
/// \returns The name of the file for for which this operation is invoked. /// \returns The name of the file for for which this operation is invoked.
Utils::FilePath fileName() const; Utils::FilePath fileName() const;
private: private:
QmlJSQuickFixInterface m_interface; const QmlJSTools::SemanticInfo m_semanticInfo;
}; };
TextEditor::QuickFixOperations findQmlJSQuickFixes(const TextEditor::AssistInterface *interface); TextEditor::QuickFixOperations findQmlJSQuickFixes(const TextEditor::AssistInterface *interface);

View File

@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qmljscomponentfromobjectdef.h" #include "qmljscomponentfromobjectdef.h"
#include "qmljseditor.h"
#include "qmljseditortr.h" #include "qmljseditortr.h"
#include "qmljsquickfix.h" #include "qmljsquickfix.h"
#include "qmljsquickfixassist.h" #include "qmljsquickfixassist.h"
@@ -42,8 +41,8 @@ class SplitInitializerOperation: public QmlJSQuickFixOperation
UiObjectInitializer *_objectInitializer; UiObjectInitializer *_objectInitializer;
public: public:
SplitInitializerOperation(const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface, SplitInitializerOperation(const Internal::QmlJSQuickFixAssistInterface *interface,
UiObjectInitializer *objectInitializer) UiObjectInitializer *objectInitializer)
: QmlJSQuickFixOperation(interface, 0) : QmlJSQuickFixOperation(interface, 0)
, _objectInitializer(objectInitializer) , _objectInitializer(objectInitializer)
{ {
@@ -77,7 +76,8 @@ public:
} }
}; };
void matchSplitInitializerQuickFix(const QmlJSQuickFixInterface &interface, QuickFixOperations &result) void matchSplitInitializerQuickFix(const Internal::QmlJSQuickFixAssistInterface *interface,
QuickFixOperations &result)
{ {
UiObjectInitializer *objectInitializer = nullptr; UiObjectInitializer *objectInitializer = nullptr;
@@ -108,7 +108,7 @@ class AnalysizeMessageSuppressionOperation: public QmlJSQuickFixOperation
Q_DECLARE_TR_FUNCTIONS(AddAnalysisMessageSuppressionComment) Q_DECLARE_TR_FUNCTIONS(AddAnalysisMessageSuppressionComment)
public: public:
AnalysizeMessageSuppressionOperation(const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface, AnalysizeMessageSuppressionOperation(const Internal::QmlJSQuickFixAssistInterface *interface,
const StaticAnalysis::Message &message) const StaticAnalysis::Message &message)
: QmlJSQuickFixOperation(interface, 0) : QmlJSQuickFixOperation(interface, 0)
, _message(message) , _message(message)
@@ -128,7 +128,8 @@ public:
} }
}; };
void matchAddAnalysisMessageSuppressionCommentQuickFix(const QmlJSQuickFixInterface &interface, QuickFixOperations &result) void matchAddAnalysisMessageSuppressionCommentQuickFix(
const Internal::QmlJSQuickFixAssistInterface *interface, QuickFixOperations &result)
{ {
const QList<StaticAnalysis::Message> &messages = interface->semanticInfo().staticAnalysisMessages; const QList<StaticAnalysis::Message> &messages = interface->semanticInfo().staticAnalysisMessages;
@@ -144,8 +145,7 @@ void matchAddAnalysisMessageSuppressionCommentQuickFix(const QmlJSQuickFixInterf
QuickFixOperations findQmlJSQuickFixes(const AssistInterface *interface) QuickFixOperations findQmlJSQuickFixes(const AssistInterface *interface)
{ {
QSharedPointer<const AssistInterface> assistInterface(interface); auto qmlJSInterface = static_cast<const QmlJSQuickFixAssistInterface *>(interface);
auto qmlJSInterface = assistInterface.staticCast<const QmlJSQuickFixAssistInterface>();
QuickFixOperations quickFixes; QuickFixOperations quickFixes;

View File

@@ -67,8 +67,7 @@ class Operation: public QmlJSQuickFixOperation
T *m_objDef; T *m_objDef;
public: public:
Operation(const QSharedPointer<const QmlJSQuickFixAssistInterface> &interface, Operation(const QmlJSQuickFixAssistInterface *interface, T *objDef)
T *objDef)
: QmlJSQuickFixOperation(interface, 0) : QmlJSQuickFixOperation(interface, 0)
, m_objDef(objDef) , m_objDef(objDef)
{ {
@@ -82,7 +81,7 @@ public:
QString tryName = base; QString tryName = base;
int extraNumber = 1; int extraNumber = 1;
const ObjectValue *found = nullptr; const ObjectValue *found = nullptr;
const ScopeChain &scope = assistInterface()->semanticInfo().scopeChain(); const ScopeChain &scope = semanticInfo().scopeChain();
forever { forever {
scope.lookup(tryName, &found); scope.lookup(tryName, &found);
if (!found || extraNumber > 1000) if (!found || extraNumber > 1000)
@@ -157,7 +156,7 @@ public:
} // end of anonymous namespace } // end of anonymous namespace
void matchWrapInLoaderQuickFix(const QmlJSQuickFixInterface &interface, QuickFixOperations &result) void matchWrapInLoaderQuickFix(const QmlJSQuickFixAssistInterface *interface, QuickFixOperations &result)
{ {
const int pos = interface->currentFile()->cursor().position(); const int pos = interface->currentFile()->cursor().position();

View File

@@ -7,6 +7,7 @@
namespace QmlJSEditor { namespace QmlJSEditor {
void matchWrapInLoaderQuickFix(const QmlJSQuickFixInterface &interface, QuickFixOperations &result); void matchWrapInLoaderQuickFix(const Internal::QmlJSQuickFixAssistInterface *interface,
QuickFixOperations &result);
} // namespace QmlJSEditor } // namespace QmlJSEditor