From 956bac297b5b888474889ca1f3acd81a873f3b46 Mon Sep 17 00:00:00 2001 From: Leandro Melo Date: Thu, 19 May 2011 18:02:09 +0200 Subject: [PATCH] C++ editor: Fix potential crash in completion There was still a problem in the previous change (that's why it was reverted) which should be fixed now. Task-number: QTCREATORBUG-4940 Change-Id: I8a0d993b9f313fc98494cf93fed1f87939a358b1 Reviewed-on: http://codereview.qt.nokia.com/27 Reviewed-by: Leandro T. C. Melo --- src/plugins/cpptools/cppcompletionassist.cpp | 68 ++++++++++++++++++---------- src/plugins/cpptools/cppcompletionassist.h | 1 - 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp index 4eac92047d..8ed37c8cd2 100644 --- a/src/plugins/cpptools/cppcompletionassist.cpp +++ b/src/plugins/cpptools/cppcompletionassist.cpp @@ -184,7 +184,9 @@ public: , m_sortable(false) , m_completionOperator(T_EOF_SYMBOL) , m_replaceDotForArrow(false) + , m_typeOfExpression(new TypeOfExpression) {} + virtual ~CppAssistProposalModel(); virtual bool isSortable() const { return m_sortable; } virtual IAssistProposalItem *proposalItem(int index) const; @@ -192,16 +194,23 @@ public: bool m_sortable; unsigned m_completionOperator; bool m_replaceDotForArrow; - Snapshot m_snapshot; + mutable TypeOfExpression *m_typeOfExpression; }; +CppAssistProposalModel::~CppAssistProposalModel() +{ + delete m_typeOfExpression; +} + // --------------------- // CppAssistProposalItem // --------------------- class CppAssistProposalItem : public TextEditor::BasicProposalItem { public: - CppAssistProposalItem() : m_isOverloaded(false) {} + CppAssistProposalItem() : + m_isOverloaded(false), m_typeOfExpression(0) {} + virtual ~CppAssistProposalItem(); virtual bool prematurelyApplies(const QChar &c) const; virtual void applyContextualContent(TextEditor::BaseTextEditor *editor, @@ -210,15 +219,21 @@ public: bool isOverloaded() const { return m_isOverloaded; } void markAsOverloaded() { m_isOverloaded = true; } void keepCompletionOperator(unsigned compOp) { m_completionOperator = compOp; } - void keepSnapshot(const Snapshot &snapshot) { m_snapshot = snapshot; } + void ownTypeOfExpression(TypeOfExpression *typeOfExp) { m_typeOfExpression = typeOfExp; } private: bool m_isOverloaded; unsigned m_completionOperator; mutable QChar m_typedChar; - Snapshot m_snapshot; + TypeOfExpression *m_typeOfExpression; }; +CppAssistProposalItem::~CppAssistProposalItem() +{ + if (m_typeOfExpression) + delete m_typeOfExpression; +} + } // Internal } // CppTools @@ -231,7 +246,8 @@ IAssistProposalItem *CppAssistProposalModel::proposalItem(int index) const if (!item->data().canConvert()) { CppAssistProposalItem *cppItem = static_cast(item); cppItem->keepCompletionOperator(m_completionOperator); - cppItem->keepSnapshot(m_snapshot); + cppItem->ownTypeOfExpression(m_typeOfExpression); + m_typeOfExpression = 0; } return item; } @@ -413,9 +429,10 @@ void CppAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor *e class CppFunctionHintModel : public TextEditor::IFunctionHintProposalModel { public: - CppFunctionHintModel(QList functionSymbols) + CppFunctionHintModel(QList functionSymbols, TypeOfExpression *typeOfExp) : m_functionSymbols(functionSymbols) , m_currentArg(-1) + , m_typeOfExpression(typeOfExp) {} virtual void reset() {} @@ -426,6 +443,7 @@ public: private: QList m_functionSymbols; mutable int m_currentArg; + TypeOfExpression *m_typeOfExpression; }; QString CppFunctionHintModel::text(int index) const @@ -675,8 +693,6 @@ IAssistProposal * CppCompletionAssistProcessor::perform(const IAssistInterface * if (interface->reason() != ExplicitlyInvoked && !accepts()) return 0; - m_model->m_snapshot = m_interface->snapshot(); - int index = startCompletionHelper(); if (index != -1) { if (m_hintProposal) @@ -804,7 +820,9 @@ IAssistProposal *CppCompletionAssistProcessor::createContentProposal() IAssistProposal *CppCompletionAssistProcessor::createHintProposal( QList functionSymbols) const { - IFunctionHintProposalModel *model = new CppFunctionHintModel(functionSymbols); + IFunctionHintProposalModel *model = + new CppFunctionHintModel(functionSymbols, m_model->m_typeOfExpression); + m_model->m_typeOfExpression = 0; IAssistProposal *proposal = new FunctionHintProposal(m_startPosition, model); return proposal; } @@ -1043,19 +1061,20 @@ bool CppCompletionAssistProcessor::tryObjCCompletion() const int startPos = tokens[start].begin() + tokens.startPosition(); const QString expr = m_interface->textAt(startPos, m_interface->position() - startPos); - Document::Ptr thisDocument = m_model->m_snapshot.document(m_interface->file()->fileName()); + Document::Ptr thisDocument = m_interface->snapshot().document(m_interface->file()->fileName()); if (! thisDocument) return false; - typeOfExpression.init(thisDocument, m_model->m_snapshot); + m_model->m_typeOfExpression->init(thisDocument, m_interface->snapshot()); + int line = 0, column = 0; Convenience::convertPosition(m_interface->document(), m_interface->position(), &line, &column); Scope *scope = thisDocument->scopeAt(line, column); if (!scope) return false; - const QList items = typeOfExpression(expr, scope); - LookupContext lookupContext(thisDocument, m_model->m_snapshot); + const QList items = (*m_model->m_typeOfExpression)(expr, scope); + LookupContext lookupContext(thisDocument, m_interface->snapshot()); foreach (const LookupItem &item, items) { FullySpecifiedType ty = item.type().simplified(); @@ -1246,18 +1265,18 @@ int CppCompletionAssistProcessor::startCompletionInternal(const QString fileName { QString expression = expr.trimmed(); - Document::Ptr thisDocument = m_model->m_snapshot.document(fileName); + Document::Ptr thisDocument = m_interface->snapshot().document(fileName); if (! thisDocument) return -1; - typeOfExpression.init(thisDocument, m_model->m_snapshot); + m_model->m_typeOfExpression->init(thisDocument, m_interface->snapshot()); Scope *scope = thisDocument->scopeAt(line, column); Q_ASSERT(scope != 0); if (expression.isEmpty()) { if (m_model->m_completionOperator == T_EOF_SYMBOL || m_model->m_completionOperator == T_COLON_COLON) { - (void) typeOfExpression(expression, scope); + (void) (*m_model->m_typeOfExpression)(expression, scope); globalCompletion(scope); if (m_completions.isEmpty()) return -1; @@ -1270,13 +1289,14 @@ int CppCompletionAssistProcessor::startCompletionInternal(const QString fileName } } - QList results = typeOfExpression(expression, scope, TypeOfExpression::Preprocess); + QList results = + (*m_model->m_typeOfExpression)(expression, scope, TypeOfExpression::Preprocess); if (results.isEmpty()) { if (m_model->m_completionOperator == T_SIGNAL || m_model->m_completionOperator == T_SLOT) { if (! (expression.isEmpty() || expression == QLatin1String("this"))) { expression = QLatin1String("this"); - results = typeOfExpression(expression, scope); + results = (*m_model->m_typeOfExpression)(expression, scope); } if (results.isEmpty()) @@ -1297,7 +1317,7 @@ int CppCompletionAssistProcessor::startCompletionInternal(const QString fileName // Resolve the type of this expression const QList results = - typeOfExpression(baseExpression, scope, + (*m_model->m_typeOfExpression)(baseExpression, scope, TypeOfExpression::Preprocess); // If it's a class, add completions for the constructors @@ -1355,7 +1375,7 @@ int CppCompletionAssistProcessor::startCompletionInternal(const QString fileName void CppCompletionAssistProcessor::globalCompletion(CPlusPlus::Scope *currentScope) { - const LookupContext &context = typeOfExpression.context(); + const LookupContext &context = m_model->m_typeOfExpression->context(); if (m_model->m_completionOperator == T_COLON_COLON) { completeNamespace(context.globalNamespace()); @@ -1422,7 +1442,7 @@ void CppCompletionAssistProcessor::globalCompletion(CPlusPlus::Scope *currentSco bool CppCompletionAssistProcessor::completeMember(const QList &baseResults) { - const LookupContext &context = typeOfExpression.context(); + const LookupContext &context = m_model->m_typeOfExpression->context(); if (baseResults.isEmpty()) return false; @@ -1444,7 +1464,7 @@ bool CppCompletionAssistProcessor::completeMember(const QList &results) { - const LookupContext &context = typeOfExpression.context(); + const LookupContext &context = m_model->m_typeOfExpression->context(); if (results.isEmpty()) return false; @@ -1574,7 +1594,7 @@ bool CppCompletionAssistProcessor::completeQtMethod(const QListm_typeOfExpression->context(); ConvertToCompletionItem toCompletionItem; Overview o; @@ -1727,7 +1747,7 @@ bool CppCompletionAssistProcessor::completeConstructorOrFunction(const QListm_typeOfExpression->context(); QList functions; foreach (const LookupItem &result, results) { diff --git a/src/plugins/cpptools/cppcompletionassist.h b/src/plugins/cpptools/cppcompletionassist.h index 080b5c3c84..073c4619c9 100644 --- a/src/plugins/cpptools/cppcompletionassist.h +++ b/src/plugins/cpptools/cppcompletionassist.h @@ -133,7 +133,6 @@ private: TextEditor::SnippetAssistCollector m_snippetCollector; const CppCompletionAssistProvider *m_provider; CPlusPlus::Icons m_icons; - CPlusPlus::TypeOfExpression typeOfExpression; QStringList preprocessorCompletions; QScopedPointer m_model; TextEditor::IAssistProposal *m_hintProposal; -- 2.11.0