From 4679f38a876bb66dbe38f22da231f7e14699b8e1 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <qtc-committer@nokia.com>
Date: Thu, 11 Dec 2008 11:27:07 +0100
Subject: [PATCH] Fixed code completion when using macros in the expression's
 code (e.g. in qApp->).

---
 src/libs/cplusplus/TypeOfExpression.cpp    | 40 ++++++++++++++++++++--
 src/libs/cplusplus/TypeOfExpression.h      | 19 +++++++++-
 src/plugins/cpptools/cppcodecompletion.cpp |  3 +-
 3 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp
index 487c9f8a469..53fa7e78396 100644
--- a/src/libs/cplusplus/TypeOfExpression.cpp
+++ b/src/libs/cplusplus/TypeOfExpression.cpp
@@ -37,6 +37,7 @@
 #include <TranslationUnit.h>
 #include <cplusplus/LookupContext.h>
 #include <cplusplus/ResolveExpression.h>
+#include <cplusplus/pp.h>
 
 using namespace CPlusPlus;
 
@@ -53,9 +54,13 @@ void TypeOfExpression::setDocuments(const QMap<QString, Document::Ptr> &document
 
 QList<TypeOfExpression::Result> TypeOfExpression::operator()(const QString &expression,
                                                              Document::Ptr document,
-                                                             Symbol *lastVisibleSymbol)
+                                                             Symbol *lastVisibleSymbol,
+                                                             PreprocessMode mode)
 {
-    Document::Ptr expressionDoc = documentForExpression(expression);
+    QString code = expression;
+    if (mode == Preprocess)
+        code = preprocessedExpression(expression, m_documents, document);
+    Document::Ptr expressionDoc = documentForExpression(code);
     m_ast = extractExpressionAST(expressionDoc);
 
     m_lookupContext = LookupContext(lastVisibleSymbol, expressionDoc,
@@ -97,3 +102,34 @@ Document::Ptr TypeOfExpression::documentForExpression(const QString &expression)
     doc->parse(Document::ParseExpression);
     return doc;
 }
+
+void TypeOfExpression::processEnvironment(QMap<QString, Document::Ptr> documents,
+                                          Document::Ptr doc, Environment *env,
+                                          QSet<QString> *processed) const
+{
+    if (processed->contains(doc->fileName()))
+        return;
+    processed->insert(doc->fileName());
+    foreach (const Document::Include &incl, doc->includes()) {
+        processEnvironment(documents,
+                           documents.value(incl.fileName()),
+                           env, processed);
+    }
+    foreach (const Macro &macro, doc->definedMacros())
+        env->bind(macro);
+}
+
+QString TypeOfExpression::preprocessedExpression(const QString &expression,
+                                                 QMap<QString, Document::Ptr> documents,
+                                                 Document::Ptr thisDocument) const
+{
+    Environment env;
+    QSet<QString> processed;
+    processEnvironment(documents, thisDocument,
+                       &env, &processed);
+    const QByteArray code = expression.toUtf8();
+    pp preproc(0, env);
+    QByteArray preprocessedCode;
+    preproc("<expression>", code, &preprocessedCode);
+    return QString::fromUtf8(preprocessedCode);
+}
diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h
index cd7a23441fd..e6a9a7f4b66 100644
--- a/src/libs/cplusplus/TypeOfExpression.h
+++ b/src/libs/cplusplus/TypeOfExpression.h
@@ -43,6 +43,9 @@
 
 namespace CPlusPlus {
 
+class Environment;
+class Macro;
+
 class CPLUSPLUS_EXPORT TypeOfExpression
 {
 public:
@@ -60,6 +63,11 @@ public:
      */
     void setDocuments(const QMap<QString, Document::Ptr> &documents);
 
+    enum PreprocessMode {
+        NoPreprocess,
+        Preprocess
+    };
+
     /**
      * Returns a list of possible fully specified types associated with the
      * given expression.
@@ -73,7 +81,8 @@ public:
      * @param lastVisibleSymbol The last visible symbol in the document.
      */
     QList<Result> operator()(const QString &expression, Document::Ptr document,
-                             Symbol *lastVisibleSymbol);
+                             Symbol *lastVisibleSymbol,
+                             PreprocessMode mode = NoPreprocess);
 
     /**
      * Returns the AST of the last evaluated expression.
@@ -91,6 +100,14 @@ private:
     ExpressionAST *extractExpressionAST(Document::Ptr doc) const;
     Document::Ptr documentForExpression(const QString &expression) const;
 
+    void processEnvironment(QMap<QString, CPlusPlus::Document::Ptr> documents,
+                            CPlusPlus::Document::Ptr doc, CPlusPlus::Environment *env,
+                            QSet<QString> *processed) const;
+
+    QString preprocessedExpression(const QString &expression,
+                                   QMap<QString, CPlusPlus::Document::Ptr> documents,
+                                   CPlusPlus::Document::Ptr thisDocument) const;
+
     QMap<QString, Document::Ptr> m_documents;
     ExpressionAST *m_ast;
     LookupContext m_lookupContext;
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 35206c2633b..4606bd948f3 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -439,7 +439,8 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
 
         typeOfExpression.setDocuments(m_manager->documents());
 
-        QList<TypeOfExpression::Result> resolvedTypes = typeOfExpression(expression, thisDocument, symbol);
+        QList<TypeOfExpression::Result> resolvedTypes = typeOfExpression(expression, thisDocument, symbol,
+                                                                         TypeOfExpression::Preprocess);
         LookupContext context = typeOfExpression.lookupContext();
 
         if (!typeOfExpression.expressionAST() && (! m_completionOperator ||
-- 
GitLab