From 1c078ec2a3685d4760aa38fe305dde1a3d40579b Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Mon, 31 May 2010 12:09:28 +0200
Subject: [PATCH] Ensure we keep the context around for as long as it is
 needed.

---
 src/libs/cplusplus/FindUsages.cpp             |  13 ++
 src/libs/cplusplus/FindUsages.h               |   1 +
 src/plugins/cppeditor/cppeditor.cpp           | 126 ++++++++++--------
 src/plugins/cppeditor/cppeditor.h             |   5 +-
 src/plugins/cpptools/cppfindreferences.cpp    |  27 ++--
 src/plugins/cpptools/cppfindreferences.h      |  10 +-
 src/plugins/cpptools/cppmodelmanager.cpp      |  14 +-
 src/plugins/cpptools/cppmodelmanager.h        |   8 +-
 .../cpptools/cppmodelmanagerinterface.h       |  11 +-
 9 files changed, 120 insertions(+), 95 deletions(-)

diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index ebecec6a12f..795de07f935 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -56,6 +56,19 @@ FindUsages::FindUsages(Document::Ptr doc, const Snapshot &snapshot)
     typeofExpression.init(_doc, _snapshot, _context.bindings());
 }
 
+FindUsages::FindUsages(const LookupContext &context)
+    : ASTVisitor(context.thisDocument()->translationUnit()),
+      _doc(context.thisDocument()),
+      _snapshot(context.snapshot()),
+      _context(context),
+      _source(_doc->source()),
+      _sem(_doc->translationUnit()),
+      _inSimpleDeclaration(0),
+      _inQProperty(false)
+{
+    typeofExpression.init(_doc, _snapshot, _context.bindings());
+}
+
 QList<Usage> FindUsages::usages() const
 { return _usages; }
 
diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h
index 12f7743db76..1bcaa66609b 100644
--- a/src/libs/cplusplus/FindUsages.h
+++ b/src/libs/cplusplus/FindUsages.h
@@ -60,6 +60,7 @@ class CPLUSPLUS_EXPORT FindUsages: protected ASTVisitor
 {
 public:
     FindUsages(Document::Ptr doc, const Snapshot &snapshot);
+    FindUsages(const LookupContext &context);
 
     void operator()(Symbol *symbol);
 
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 4c1c79d219a..30e5005ac09 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -565,6 +565,59 @@ protected:
     }
 };
 
+
+struct FindCanonicalSymbol
+{
+    CPPEditor *editor;
+    QString code;
+    TypeOfExpression typeOfExpression;
+    ExpressionUnderCursor expressionUnderCursor;
+    SemanticInfo info;
+
+    FindCanonicalSymbol(CPPEditor *editor, const SemanticInfo &info)
+        : editor(editor), info(info)
+    {
+        typeOfExpression.init(info.doc, info.snapshot);
+    }
+
+    const LookupContext &context() const
+    {
+        return typeOfExpression.context();
+    }
+
+    Symbol *operator()(const QTextCursor &cursor)
+    {
+        if (! info.doc)
+            return 0;
+
+        QTextCursor tc = cursor;
+        int line, col;
+        editor->convertPosition(tc.position(), &line, &col);
+        ++col; // 1-based line and 1-based column
+
+        QTextDocument *document = editor->document();
+
+        int pos = tc.position();
+        while (document->characterAt(pos).isLetterOrNumber() ||
+               document->characterAt(pos) == QLatin1Char('_'))
+            ++pos;
+        tc.setPosition(pos);
+
+        code = expressionUnderCursor(tc);
+        Scope *scope = info.doc->scopeAt(line, col);
+
+        const QList<LookupItem> results = typeOfExpression(code, scope, TypeOfExpression::Preprocess);
+        for (int i = results.size() - 1; i != -1; --i) { // ### TODO virtual methods and classes.
+            const LookupItem &r = results.at(i);
+
+            if (r.declaration())
+                return r.declaration();
+        }
+
+        return 0;
+    }
+};
+
 } // end of anonymous namespace
 
 CPPEditorEditable::CPPEditorEditable(CPPEditor *editor)
@@ -819,46 +872,7 @@ void CPPEditor::onDocumentUpdated(Document::Ptr doc)
     updateMethodBoxIndexNow();
 }
 
-CPlusPlus::Symbol *CPPEditor::findCanonicalSymbol(const QTextCursor &cursor,
-                                                  Document::Ptr doc,
-                                                  const Snapshot &snapshot) const
-{
-    if (! doc)
-        return 0;
-
-    QTextCursor tc = cursor;
-    int line, col;
-    convertPosition(tc.position(), &line, &col);
-    ++col; // 1-based line and 1-based column
-
-    int pos = tc.position();
-    while (document()->characterAt(pos).isLetterOrNumber() ||
-           document()->characterAt(pos) == QLatin1Char('_'))
-        ++pos;
-    tc.setPosition(pos);
-
-    ExpressionUnderCursor expressionUnderCursor;
-    const QString code = expressionUnderCursor(tc);
-    // qDebug() << "code:" << code;
-
-    TypeOfExpression typeOfExpression;
-    typeOfExpression.init(doc, snapshot);
-
-    Scope *scope = doc->scopeAt(line, col);
-
-    const QList<LookupItem> results = typeOfExpression(code, scope, TypeOfExpression::Preprocess);
-    for (int i = results.size() - 1; i != -1; --i) { // ### TODO virtual methods and classes.
-        const LookupItem &r = results.at(i);
-
-        if (r.declaration())
-            return r.declaration();
-    }
-
-    return 0;
-}
-
-const Macro *CPPEditor::findCanonicalMacro(const QTextCursor &cursor,
-                                                  Document::Ptr doc) const
+const Macro *CPPEditor::findCanonicalMacro(const QTextCursor &cursor, Document::Ptr doc) const
 {
     if (! doc)
         return 0;
@@ -877,9 +891,13 @@ const Macro *CPPEditor::findCanonicalMacro(const QTextCursor &cursor,
 
 void CPPEditor::findUsages()
 {
-    if (Symbol *canonicalSymbol = markSymbols()) {
-        m_modelManager->findUsages(m_lastSemanticInfo.doc, canonicalSymbol);
-    } else if (const Macro *macro = findCanonicalMacro(textCursor(), m_lastSemanticInfo.doc)) {
+    const SemanticInfo info = m_lastSemanticInfo;
+
+    FindCanonicalSymbol cs(this, info);
+    Symbol *canonicalSymbol = cs(textCursor());
+    if (canonicalSymbol) {
+        m_modelManager->findUsages(canonicalSymbol, cs.context());
+    } else if (const Macro *macro = findCanonicalMacro(textCursor(), info.doc)) {
         m_modelManager->findMacroUsages(*macro);
     }
 }
@@ -920,7 +938,10 @@ void CPPEditor::hideRenameNotification()
 
 void CPPEditor::renameUsagesNow()
 {
-    if (Symbol *canonicalSymbol = markSymbols()) {
+    const SemanticInfo info = m_lastSemanticInfo;
+
+    FindCanonicalSymbol cs(this, info);
+    if (Symbol *canonicalSymbol = cs(textCursor())) {
         if (canonicalSymbol->identifier() != 0) {
             if (showWarningMessage()) {
                 Core::EditorManager::instance()->showEditorInfoBar(QLatin1String("CppEditor.Rename"),
@@ -929,12 +950,12 @@ void CPPEditor::renameUsagesNow()
                                                                    this, SLOT(hideRenameNotification()));
             }
 
-            m_modelManager->renameUsages(m_lastSemanticInfo.doc, canonicalSymbol);
+            m_modelManager->renameUsages(canonicalSymbol, cs.context());
         }
     }
 }
 
-Symbol *CPPEditor::markSymbols()
+void CPPEditor::markSymbols(Symbol *canonicalSymbol, const SemanticInfo &info)
 {
     //updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource()));
 
@@ -942,13 +963,11 @@ Symbol *CPPEditor::markSymbols()
 
     QList<QTextEdit::ExtraSelection> selections;
 
-    const SemanticInfo info = m_lastSemanticInfo;
-
-    Symbol *canonicalSymbol = findCanonicalSymbol(textCursor(), info.doc, info.snapshot);
     if (canonicalSymbol) {
         TranslationUnit *unit = info.doc->translationUnit();
 
-        const QList<int> references = m_modelManager->references(canonicalSymbol, info.doc, info.snapshot);
+        LookupContext context(info.doc, info.snapshot); // ### remove me
+        const QList<int> references = m_modelManager->references(canonicalSymbol, context);
         foreach (int index, references) {
             unsigned line, column;
             unit->getTokenPosition(index, &line, &column);
@@ -970,7 +989,6 @@ Symbol *CPPEditor::markSymbols()
     }
 
     setExtraSelections(CodeSemanticsSelection, selections);
-    return canonicalSymbol;
 }
 
 void CPPEditor::renameSymbolUnderCursor()
@@ -1938,8 +1956,10 @@ void CPPEditor::updateSemanticInfo(const SemanticInfo &semanticInfo)
 
     if (! m_renameSelections.isEmpty())
         setExtraSelections(CodeSemanticsSelection, m_renameSelections); // ###
-    else
-        markSymbols();
+    else {
+        FindCanonicalSymbol cs(this, semanticInfo);
+        markSymbols(cs(textCursor()), semanticInfo);
+    }
 
     m_lastSemanticInfo.forced = false; // clear the forced flag
 }
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index c6e039ba007..3e94328cba9 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -227,9 +227,6 @@ protected:
 
     virtual bool isInComment(const QTextCursor &cursor) const;
 
-    CPlusPlus::Symbol *findCanonicalSymbol(const QTextCursor &cursor,
-                                           CPlusPlus::Document::Ptr doc,
-                                           const CPlusPlus::Snapshot &snapshot) const;
     const CPlusPlus::Macro *findCanonicalMacro(const QTextCursor &cursor,
                                                CPlusPlus::Document::Ptr doc) const;
 
@@ -253,7 +250,7 @@ private:
     bool showWarningMessage() const;
     void setShowWarningMessage(bool showWarningMessage);
 
-    CPlusPlus::Symbol *markSymbols();
+    void markSymbols(CPlusPlus::Symbol *canonicalSymbol, const SemanticInfo &info);
     bool sortedMethodOverview() const;
     CPlusPlus::Symbol *findDefinition(CPlusPlus::Symbol *symbol, const CPlusPlus::Snapshot &snapshot);
     virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp
index 1238581af19..857324f754c 100644
--- a/src/plugins/cpptools/cppfindreferences.cpp
+++ b/src/plugins/cpptools/cppfindreferences.cpp
@@ -167,13 +167,11 @@ CppFindReferences::~CppFindReferences()
 {
 }
 
-QList<int> CppFindReferences::references(Symbol *symbol,
-                                         Document::Ptr doc,
-                                         const Snapshot& snapshot) const
+QList<int> CppFindReferences::references(Symbol *symbol, const LookupContext &context) const
 {
     QList<int> references;
 
-    FindUsages findUsages(doc, snapshot);
+    FindUsages findUsages(context);
     findUsages(symbol);
     references = findUsages.references();
 
@@ -182,9 +180,8 @@ QList<int> CppFindReferences::references(Symbol *symbol,
 
 static void find_helper(QFutureInterface<Usage> &future,
                         const CppTools::CppModelManagerInterface::WorkingCopy workingCopy,
-                        Snapshot snapshot,
-                        Document::Ptr symbolDocument,
-                        DependencyTable dependencyTable,
+                        const LookupContext context,
+                        const DependencyTable dependencyTable,
                         Symbol *symbol)
 {
     QTime tm;
@@ -197,7 +194,7 @@ static void find_helper(QFutureInterface<Usage> &future,
     QStringList files(sourceFile);
 
     if (symbol->isClass() || symbol->isForwardClassDeclaration()) {
-        foreach (const Document::Ptr &doc, snapshot) {
+        foreach (const Document::Ptr &doc, context.snapshot()) {
             if (doc->fileName() == sourceFile)
                 continue;
 
@@ -214,7 +211,7 @@ static void find_helper(QFutureInterface<Usage> &future,
 
     future.setProgressRange(0, files.size());
 
-    ProcessFile process(workingCopy, snapshot, symbolDocument, symbol);
+    ProcessFile process(workingCopy, context.snapshot(), context.thisDocument(), symbol);
     UpdateUI reduce(&future);
 
     QtConcurrent::blockingMappedReduced<QList<Usage> > (files, process, reduce);
@@ -238,17 +235,17 @@ void CppFindReferences::updateDependencyTable()
     m_depsFuture = QtConcurrent::run(&dependencyTable, m_deps, _modelManager->snapshot());
 }
 
-void CppFindReferences::findUsages(Document::Ptr symbolDocument, Symbol *symbol)
+void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context)
 {
     Find::SearchResult *search = _resultWindow->startNewSearch(Find::SearchResultWindow::SearchOnly);
 
     connect(search, SIGNAL(activated(Find::SearchResultItem)),
             this, SLOT(openEditor(Find::SearchResultItem)));
 
-    findAll_helper(symbolDocument, symbol);
+    findAll_helper(symbol, context);
 }
 
-void CppFindReferences::renameUsages(Document::Ptr symbolDocument, Symbol *symbol)
+void CppFindReferences::renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context)
 {
     if (const Identifier *id = symbol->identifier()) {
         const QString textToReplace = QString::fromUtf8(id->chars(), id->size());
@@ -262,11 +259,11 @@ void CppFindReferences::renameUsages(Document::Ptr symbolDocument, Symbol *symbo
         connect(search, SIGNAL(replaceButtonClicked(QString,QList<Find::SearchResultItem>)),
                 SLOT(onReplaceButtonClicked(QString,QList<Find::SearchResultItem>)));
 
-        findAll_helper(symbolDocument, symbol);
+        findAll_helper(symbol, context);
     }
 }
 
-void CppFindReferences::findAll_helper(Document::Ptr symbolDocument, Symbol *symbol)
+void CppFindReferences::findAll_helper(Symbol *symbol, const LookupContext &context)
 {
     if (! (symbol && symbol->identifier()))
         return;
@@ -283,7 +280,7 @@ void CppFindReferences::findAll_helper(Document::Ptr symbolDocument, Symbol *sym
 
     QFuture<Usage> result;
 
-    result = QtConcurrent::run(&find_helper, workingCopy, snapshot, symbolDocument, m_deps, symbol);
+    result = QtConcurrent::run(&find_helper, workingCopy, context, m_deps, symbol);
     m_watcher.setFuture(result);
 
     Core::FutureProgress *progress = progressManager->addTask(result, tr("Searching"),
diff --git a/src/plugins/cpptools/cppfindreferences.h b/src/plugins/cpptools/cppfindreferences.h
index f37d2b6643d..f16bf53ffde 100644
--- a/src/plugins/cpptools/cppfindreferences.h
+++ b/src/plugins/cpptools/cppfindreferences.h
@@ -59,16 +59,14 @@ public:
     CppFindReferences(CppModelManagerInterface *modelManager);
     virtual ~CppFindReferences();
 
-    QList<int> references(CPlusPlus::Symbol *symbol,
-                          CPlusPlus::Document::Ptr doc,
-                          const CPlusPlus::Snapshot& snapshot) const;
+    QList<int> references(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context) const;
 
 Q_SIGNALS:
     void changed();
 
 public:
-    void findUsages(CPlusPlus::Document::Ptr symbolDocument,CPlusPlus::Symbol *symbol);
-    void renameUsages(CPlusPlus::Document::Ptr symbolDocument,CPlusPlus::Symbol *symbol);
+    void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
+    void renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
 
     void findMacroUses(const CPlusPlus::Macro &macro);
 
@@ -80,7 +78,7 @@ private Q_SLOTS:
     void updateDependencyTable();
 
 private:
-    void findAll_helper(CPlusPlus::Document::Ptr symbolDocument, CPlusPlus::Symbol *symbol);
+    void findAll_helper(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
 
 private:
     QPointer<CppModelManagerInterface> _modelManager;
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index ffa8e71b5bb..f6222bfc500 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -785,23 +785,21 @@ void CppModelManager::removeEditorSupport(AbstractEditorSupport *editorSupport)
     m_addtionalEditorSupport.remove(editorSupport);
 }
 
-QList<int> CppModelManager::references(CPlusPlus::Symbol *symbol,
-                                       CPlusPlus::Document::Ptr doc,
-                                       const CPlusPlus::Snapshot &snapshot)
+QList<int> CppModelManager::references(CPlusPlus::Symbol *symbol, const LookupContext &context)
 {
-    return m_findReferences->references(symbol, doc, snapshot);
+    return m_findReferences->references(symbol, context);
 }
 
-void CppModelManager::findUsages(CPlusPlus::Document::Ptr symbolDocument, CPlusPlus::Symbol *symbol)
+void CppModelManager::findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context)
 {
     if (symbol->identifier())
-        m_findReferences->findUsages(symbolDocument, symbol);
+        m_findReferences->findUsages(symbol, context);
 }
 
-void CppModelManager::renameUsages(CPlusPlus::Document::Ptr symbolDocument, CPlusPlus::Symbol *symbol)
+void CppModelManager::renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context)
 {
     if (symbol->identifier())
-        m_findReferences->renameUsages(symbolDocument, symbol);
+        m_findReferences->renameUsages(symbol, context);
 }
 
 void CppModelManager::findMacroUsages(const CPlusPlus::Macro &macro)
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index 1ba6d71efdb..0058e4edafc 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -116,12 +116,10 @@ public:
     virtual void addEditorSupport(AbstractEditorSupport *editorSupport);
     virtual void removeEditorSupport(AbstractEditorSupport *editorSupport);
 
-    virtual QList<int> references(CPlusPlus::Symbol *symbol,
-                                  CPlusPlus::Document::Ptr doc,
-                                  const CPlusPlus::Snapshot &snapshot);
+    virtual QList<int> references(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
 
-    virtual void findUsages(CPlusPlus::Document::Ptr symbolDocument, CPlusPlus::Symbol *symbol);
-    virtual void renameUsages(CPlusPlus::Document::Ptr symbolDocument, CPlusPlus::Symbol *symbol);
+    virtual void renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
+    virtual void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
 
     virtual void findMacroUsages(const CPlusPlus::Macro &macro);
 
diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.h b/src/plugins/cpptools/cppmodelmanagerinterface.h
index eb3b151432c..cc1177a27f7 100644
--- a/src/plugins/cpptools/cppmodelmanagerinterface.h
+++ b/src/plugins/cpptools/cppmodelmanagerinterface.h
@@ -38,6 +38,10 @@
 #include <QtCore/QStringList>
 #include <QtCore/QFuture>
 
+namespace CPlusPlus {
+    class LookupContext;
+}
+
 namespace ProjectExplorer {
     class Project;
 }
@@ -119,11 +123,10 @@ public:
     virtual void removeEditorSupport(AbstractEditorSupport *editorSupport) = 0;
 
     virtual QList<int> references(CPlusPlus::Symbol *symbol,
-                                  CPlusPlus::Document::Ptr doc,
-                                  const CPlusPlus::Snapshot &snapshot) = 0;
+                                  const CPlusPlus::LookupContext &context) = 0;
 
-    virtual void renameUsages(CPlusPlus::Document::Ptr symbolDocument, CPlusPlus::Symbol *symbol) = 0;
-    virtual void findUsages(CPlusPlus::Document::Ptr symbolDocument, CPlusPlus::Symbol *symbol) = 0;
+    virtual void renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context) = 0;
+    virtual void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context) = 0;
 
     virtual void findMacroUsages(const CPlusPlus::Macro &macro) = 0;
 
-- 
GitLab