From 919eadaaca99f6f0ea51ba348d53049129d20538 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Thu, 8 Apr 2010 11:23:15 +0200
Subject: [PATCH] Recognize user defined types.

---
 src/plugins/cppeditor/cppeditor.cpp |  125 +++++++++++++++++++++++++++++++++++
 src/plugins/cppeditor/cppeditor.h   |    2 +
 2 files changed, 127 insertions(+), 0 deletions(-)

diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 438da76..9c254fb 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -188,6 +188,110 @@ private:
     }
 };
 
+class MarkTypes
+{
+    TranslationUnit *_unit;
+    QSet<QByteArray> _types;
+    QList<SemanticInfo::Use> _locations;
+
+public:
+    MarkTypes(TranslationUnit *unit, const QSet<QByteArray> &types)
+        : _unit(unit), _types(types) {}
+
+    QList<SemanticInfo::Use> operator()() {
+        for (unsigned index = 0, end = _unit->tokenCount(); index != end; ++index) {
+            const Token &tk = _unit->tokenAt(index);
+            if (tk.generated())
+                continue;
+            else if (tk.isNot(T_IDENTIFIER))
+                continue;
+            const QByteArray id = QByteArray::fromRawData(tk.identifier->chars(), tk.identifier->size());
+            if (! _types.contains(id))
+                continue;
+            unsigned line = 0, column = 0;
+            _unit->getTokenPosition(index, &line, &column);
+            SemanticInfo::Use use;
+            use.line = line;
+            use.column = column;
+            use.length = tk.length();
+            _locations.append(use);
+        }
+        return _locations;
+    }
+};
+
+class FindTypes: protected SymbolVisitor
+{
+    Document::Ptr _doc;
+    Snapshot _snapshot;
+    QSet<QByteArray> _types;
+
+public:
+    FindTypes(Document::Ptr doc, const Snapshot &snapshot)
+        : _doc(doc), _snapshot(snapshot) {}
+
+    QList<SemanticInfo::Use> operator()() {
+        QSet<QString> processed;
+        process(_doc, &processed);
+        MarkTypes markTypes(_doc->translationUnit(), _types);
+        return markTypes();
+    }
+
+    void process(Document::Ptr doc, QSet<QString> *processed) {
+        if (! doc)
+            return;
+        else if (processed->contains(doc->fileName()))
+            return;
+
+        processed->insert(doc->fileName());
+
+        foreach (const Document::Include &i, doc->includes())
+            process(_snapshot.document(i.fileName()), processed);
+
+        accept(doc->globalNamespace());
+    }
+
+protected:
+    using SymbolVisitor::visit;
+
+    virtual bool visit(UsingNamespaceDirective *ns) {
+        if (const Identifier *id = ns->identifier())
+            _types.insert(QByteArray::fromRawData(id->chars(), id->size()));
+
+        return true;
+    }
+
+    virtual bool visit(Namespace *ns) {
+        if (const Identifier *id = ns->identifier())
+            _types.insert(QByteArray::fromRawData(id->chars(), id->size()));
+
+        return true;
+    }
+
+    virtual bool visit(Class *klass) {
+        if (const Identifier *id = klass->identifier())
+            _types.insert(QByteArray::fromRawData(id->chars(), id->size()));
+
+        return true;
+    }
+
+    virtual bool visit(ForwardClassDeclaration *fwd) {
+        if (const Identifier *id = fwd->identifier())
+            _types.insert(QByteArray::fromRawData(id->chars(), id->size()));
+
+        return true;
+    }
+
+    virtual bool visit(Declaration *decl) {
+        if (decl->isTypedef()) {
+            if (const Identifier *id = decl->identifier())
+                _types.insert(QByteArray::fromRawData(id->chars(), id->size()));
+        }
+
+        return true;
+    }
+};
+
 class FindLocalUses: protected ASTVisitor
 {
     Scope *_functionScope;
@@ -1943,6 +2047,8 @@ void CPPEditor::setFontSettings(const TextEditor::FontSettings &fs)
     highlighter->setFormats(formats.constBegin(), formats.constEnd());
     highlighter->rehighlight();
 
+    m_typesFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_TYPE));
+
     m_occurrencesFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_OCCURRENCES));
     m_occurrencesUnusedFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_OCCURRENCES_UNUSED));
     m_occurrencesUnusedFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
@@ -2041,6 +2147,19 @@ void CPPEditor::updateSemanticInfo(const SemanticInfo &semanticInfo)
             highlightUses(uses, semanticInfo, &m_renameSelections);
     }
 
+    foreach (const SemanticInfo::Use &use, semanticInfo.types) {
+        const int anchor = document()->findBlockByNumber(use.line - 1).position() + use.column - 1;
+        const int position = anchor + use.length;
+
+        QTextEdit::ExtraSelection sel;
+
+        sel.cursor = QTextCursor(document());
+        sel.cursor.setPosition(anchor);
+        sel.cursor.setPosition(position, QTextCursor::KeepAnchor);
+        sel.format = m_typesFormat;
+        unusedSelections.append(sel);
+    }
+
     setExtraSelections(UnusedSymbolSelection, unusedSelections);
     setExtraSelections(CodeSemanticsSelection, m_renameSelections);
 }
@@ -2134,11 +2253,13 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
 
     Snapshot snapshot;
     Document::Ptr doc;
+    QList<SemanticInfo::Use> types;
 
     if (! source.force && revision == source.revision) {
         m_mutex.lock();
         snapshot = m_lastSemanticInfo.snapshot;
         doc = m_lastSemanticInfo.doc;
+        types = m_lastSemanticInfo.types;
         m_mutex.unlock();
     }
 
@@ -2148,6 +2269,9 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
         snapshot = source.snapshot;
         doc = source.snapshot.documentFromSource(preprocessedCode, source.fileName);
         doc->check();
+
+        FindTypes findTypes(doc, snapshot);
+        types = findTypes();
     }
 
     TranslationUnit *translationUnit = doc->translationUnit();
@@ -2164,6 +2288,7 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
     semanticInfo.snapshot = snapshot;
     semanticInfo.doc = doc;
     semanticInfo.localUses = useTable.localUses;
+    semanticInfo.types = types;
     semanticInfo.hasQ = useTable.hasQ;
     semanticInfo.hasD = useTable.hasD;
 
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 8ab0ab0..9db4225 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -88,6 +88,7 @@ public:
     CPlusPlus::Snapshot snapshot;
     CPlusPlus::Document::Ptr doc;
     LocalUseMap localUses;
+    QList<Use> types;
 };
 
 class SemanticHighlighter: public QThread
@@ -294,6 +295,7 @@ private:
     QAction *m_sortAction;
     QTimer *m_updateMethodBoxTimer;
     QTimer *m_updateUsesTimer;
+    QTextCharFormat m_typesFormat;
     QTextCharFormat m_occurrencesFormat;
     QTextCharFormat m_occurrencesUnusedFormat;
     QTextCharFormat m_occurrenceRenameFormat;
-- 
1.7.0.4.360.g11766c

