From a976385b440d08ad9c894b2acae2cba8d224510e Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Fri, 20 Feb 2009 12:55:01 +0100
Subject: [PATCH] Code completion of doxygen tags.

---
 src/libs/cplusplus/TokenUnderCursor.cpp       |   3 +
 src/plugins/cppeditor/cppeditor.pro           |   6 +-
 src/plugins/cppeditor/cpphighlighter.cpp      |   6 +-
 src/plugins/cpptools/cppcodecompletion.cpp    |  72 ++++++---
 .../{cppeditor => cpptools}/cppdoxygen.cpp    | 143 ++++++++++++++++--
 .../{cppeditor => cpptools}/cppdoxygen.h      |  13 +-
 src/plugins/cpptools/cpptools.pro             |   6 +-
 src/plugins/cpptools/cpptools_global.h        |   4 +-
 8 files changed, 203 insertions(+), 50 deletions(-)
 rename src/plugins/{cppeditor => cpptools}/cppdoxygen.cpp (95%)
 rename src/plugins/{cppeditor => cpptools}/cppdoxygen.h (94%)

diff --git a/src/libs/cplusplus/TokenUnderCursor.cpp b/src/libs/cplusplus/TokenUnderCursor.cpp
index d103a0307f7..0caf3240766 100644
--- a/src/libs/cplusplus/TokenUnderCursor.cpp
+++ b/src/libs/cplusplus/TokenUnderCursor.cpp
@@ -49,6 +49,9 @@ TokenUnderCursor::~TokenUnderCursor()
 SimpleToken TokenUnderCursor::operator()(const QTextCursor &cursor) const
 {
     SimpleLexer tokenize;
+    tokenize.setObjCEnabled(true);
+    tokenize.setSkipComments(false);
+
     QTextBlock block = cursor.block();
     int column = cursor.columnNumber();
 
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index 3d4abf71679..5660b26b1e9 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -15,8 +15,7 @@ HEADERS += cppplugin.h \
     cppeditorconstants.h \
     cppeditorenums.h \
     cppeditor_global.h \
-    cppclasswizard.h \
-    cppdoxygen.h
+    cppclasswizard.h
 
 SOURCES += cppplugin.cpp \
     cppeditoractionhandler.cpp \
@@ -24,7 +23,6 @@ SOURCES += cppplugin.cpp \
     cpphighlighter.cpp \
     cpphoverhandler.cpp \
     cppfilewizard.cpp \
-    cppclasswizard.cpp \
-    cppdoxygen.cpp
+    cppclasswizard.cpp
 
 RESOURCES += cppeditor.qrc
diff --git a/src/plugins/cppeditor/cpphighlighter.cpp b/src/plugins/cppeditor/cpphighlighter.cpp
index 657967a3ce0..8c4919c738d 100644
--- a/src/plugins/cppeditor/cpphighlighter.cpp
+++ b/src/plugins/cppeditor/cpphighlighter.cpp
@@ -32,7 +32,7 @@
 ***************************************************************************/
 
 #include "cpphighlighter.h"
-#include "cppdoxygen.h"
+#include <cpptools/cppdoxygen.h>
 
 #include <Token.h>
 #include <cplusplus/SimpleLexer.h>
@@ -341,8 +341,8 @@ void CppHighlighter::highlightDoxygenComment(const QString &text, int position,
             while (it->isLetterOrNumber() || it->unicode() == '_')
                 ++it;
 
-            int k = classifyDoxygen(start, it - start);
-            if (k != T_DOXY_IDENTIFIER) {
+            int k = CppTools::classifyDoxygenTag(start, it - start);
+            if (k != CppTools::T_DOXY_IDENTIFIER) {
                 setFormat(initial, start - uc - initial, format);
                 setFormat(start - uc - 1, it - start + 1, kwFormat);
                 initial = it - uc;
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 2a1e13ae3f1..65802dd61b9 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -32,8 +32,8 @@
 ***************************************************************************/
 
 #include "cppcodecompletion.h"
-
 #include "cppmodelmanager.h"
+#include "cppdoxygen.h"
 
 #include <Control.h>
 #include <AST.h>
@@ -371,46 +371,54 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
     const QChar ch3 = pos >  1 ? editor->characterAt(pos - 3) : QChar();
 
     int start = pos;
+    int k = T_EOF_SYMBOL;
 
     if        (ch2 != QLatin1Char('.') && ch == QLatin1Char('.')) {
-        if (kind)
-            *kind = T_DOT;
+        k = T_DOT;
         --start;
     } else if (wantFunctionCall        && ch == QLatin1Char('(')) {
-        if (kind)
-            *kind = T_LPAREN;
+        k = T_LPAREN;
         --start;
     } else if (ch2 == QLatin1Char(':') && ch == QLatin1Char(':')) {
-        if (kind)
-            *kind = T_COLON_COLON;
+        k = T_COLON_COLON;
         start -= 2;
     } else if (ch2 == QLatin1Char('-') && ch == QLatin1Char('>')) {
-        if (kind)
-            *kind = T_ARROW;
+        k = T_ARROW;
         start -= 2;
     } else if (ch2 == QLatin1Char('.') && ch == QLatin1Char('*')) {
-        if (kind)
-            *kind = T_DOT_STAR;
+        k = T_DOT_STAR;
         start -= 2;
     } else if (ch3 == QLatin1Char('-') && ch2 == QLatin1Char('>') && ch == QLatin1Char('*')) {
-        if (kind)
-            *kind = T_ARROW_STAR;
+        k = T_ARROW_STAR;
         start -= 3;
+    } else if (ch == QLatin1Char('@') || ch == QLatin1Char('\\')) {
+        k = T_DOXY_COMMENT;
+        --start;
     }
 
-    if (start != pos) {
-        TextEditor::BaseTextEditor *edit = qobject_cast<TextEditor::BaseTextEditor *>(editor->widget());
-        QTextCursor tc(edit->textCursor());
-        tc.setPosition(pos);
-        static CPlusPlus::TokenUnderCursor tokenUnderCursor;
-        const SimpleToken tk = tokenUnderCursor(tc);
-        if (tk.isComment() || tk.isLiteral()) {
-            if (kind)
-                *kind = T_EOF_SYMBOL;
-            return pos;
-        }
+    if (start == pos)
+        return start;
+
+    TextEditor::BaseTextEditor *edit = qobject_cast<TextEditor::BaseTextEditor *>(editor->widget());
+    QTextCursor tc(edit->textCursor());
+    tc.setPosition(pos);
+
+    static CPlusPlus::TokenUnderCursor tokenUnderCursor;
+    const SimpleToken tk = tokenUnderCursor(tc);
+
+    if (k == T_DOXY_COMMENT && tk.isNot(T_DOXY_COMMENT)) {
+        k = T_EOF_SYMBOL;
+        start = pos;
     }
 
+    else if (tk.is(T_COMMENT) || tk.isLiteral()) {
+        k = T_EOF_SYMBOL;
+        start = pos;
+    }
+
+    if (kind)
+        *kind = k;
+
     return start;
 }
 
@@ -457,15 +465,31 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
     ExpressionUnderCursor expressionUnderCursor;
     QString expression;
 
+
+    if (m_completionOperator == T_DOXY_COMMENT) {
+        for (int i = 1; i < T_DOXY_LAST_TAG; ++i) {
+            TextEditor::CompletionItem item(this);
+            item.m_text.append(QString::fromLatin1(doxygenTagSpell(i)));
+            m_completions.append(item);
+        }
+
+        return m_startPosition;
+    }
+
+
     if (m_completionOperator) {
         QTextCursor tc(edit->document());
         tc.setPosition(endOfExpression);
+
         expression = expressionUnderCursor(tc);
+
         if (m_completionOperator == T_LPAREN) {
             if (expression.endsWith(QLatin1String("SIGNAL")))
                 m_completionOperator = T_SIGNAL;
+
             else if (expression.endsWith(QLatin1String("SLOT")))
                 m_completionOperator = T_SLOT;
+
             else if (editor->position() != endOfOperator) {
                 // We don't want a function completion when the cursor isn't at the opening brace
                 expression.clear();
diff --git a/src/plugins/cppeditor/cppdoxygen.cpp b/src/plugins/cpptools/cppdoxygen.cpp
similarity index 95%
rename from src/plugins/cppeditor/cppdoxygen.cpp
rename to src/plugins/cpptools/cppdoxygen.cpp
index 21ea204d832..5f003157145 100644
--- a/src/plugins/cppeditor/cppdoxygen.cpp
+++ b/src/plugins/cpptools/cppdoxygen.cpp
@@ -34,20 +34,138 @@
 #include <QString>
 #include "cppdoxygen.h"
 
-using namespace CppEditor::Internal;
+using namespace CppTools;
 
 /*
+  TODO:
+    ~
+    @
+    $
+    \
+    #
+    f[
+    f]
+    f$
+*/
 
-~
-@
-$
-\
-#
-f[
-f]
-f$
+static const char *doxy_token_spell[] = {
+    "identifier",
+
+    "arg",
+    "attention",
+    "author",
+    "callgraph",
+    "code",
+    "dot",
+    "else",
+    "endcode",
+    "endcond",
+    "enddot",
+    "endhtmlonly",
+    "endif",
+    "endlatexonly",
+    "endlink",
+    "endmanonly",
+    "endverbatim",
+    "endxmlonly",
+    "hideinitializer",
+    "htmlonly",
+    "interface",
+    "internal",
+    "invariant",
+    "latexonly",
+    "li",
+    "manonly",
+    "n",
+    "nosubgrouping",
+    "note",
+    "only",
+    "post",
+    "pre",
+    "remarks",
+    "return",
+    "returns",
+    "sa",
+    "see",
+    "showinitializer",
+    "since",
+    "test",
+    "todo",
+    "verbatim",
+    "warning",
+    "xmlonly",
+
+    "a",
+    "addtogroup",
+    "anchor",
+    "b",
+    "c",
+    "class",
+    "cond",
+    "copydoc",
+    "def",
+    "dontinclude",
+    "dotfile",
+    "e",
+    "elseif",
+    "em",
+    "enum",
+    "example",
+    "exception",
+    "exceptions",
+    "file",
+    "htmlinclude",
+    "if",
+    "ifnot",
+    "include",
+    "link",
+    "namespace",
+    "p",
+    "package",
+    "ref",
+    "relates",
+    "relatesalso",
+    "retval",
+    "throw",
+    "throws",
+    "verbinclude",
+    "version",
+    "xrefitem",
+
+    "param",
+
+    "image",
+
+    "defgroup",
+    "page",
+    "paragraph",
+    "section",
+    "struct",
+    "subsection",
+    "subsubsection",
+    "union",
+    "weakgroup",
+
+    "addindex",
+    "brief",
+    "bug",
+    "date",
+    "deprecated",
+    "fn",
+    "ingroup",
+    "line",
+    "mainpage",
+    "name",
+    "overload",
+    "par",
+    "short",
+    "skip",
+    "skipline",
+    "typedef",
+    "until",
+    "var"
+};
 
-*/
 static inline int classify1(const QChar *s) {
   if (s[0].unicode() == 'a') {
     return T_DOXY_A;
@@ -1490,7 +1608,10 @@ static inline int classify15(const QChar *s) {
   return T_DOXY_IDENTIFIER;
 }
 
-int CppEditor::Internal::classifyDoxygen(const QChar *s, int n) {
+const char *CppTools::doxygenTagSpell(int index)
+{ return doxy_token_spell[index]; }
+
+int CppTools::classifyDoxygenTag(const QChar *s, int n) {
   switch (n) {
     case 1: return classify1(s);
     case 2: return classify2(s);
diff --git a/src/plugins/cppeditor/cppdoxygen.h b/src/plugins/cpptools/cppdoxygen.h
similarity index 94%
rename from src/plugins/cppeditor/cppdoxygen.h
rename to src/plugins/cpptools/cppdoxygen.h
index 61c8e9da0cc..9c70420f519 100644
--- a/src/plugins/cppeditor/cppdoxygen.h
+++ b/src/plugins/cpptools/cppdoxygen.h
@@ -30,8 +30,10 @@
 ** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
 **
 ***************************************************************************/
-namespace CppEditor {
-namespace Internal {
+
+#include "cpptools_global.h"
+
+namespace CppTools {
 
 enum DoxygenReservedWord {
   T_DOXY_IDENTIFIER = 0,
@@ -150,11 +152,12 @@ enum DoxygenReservedWord {
   T_DOXY_UNTIL,
   T_DOXY_VAR,
 
-};
+  T_DOXY_LAST_TAG
 
-int classifyDoxygen(const QChar *s, int n);
+};
 
+CPPTOOLS_EXPORT int classifyDoxygenTag(const QChar *s, int n);
+CPPTOOLS_EXPORT const char *doxygenTagSpell(int index);
 
-} // namespace Internal
 } // namespace CppEditor::Internal
 
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index f8259c9031c..21298bef073 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -19,7 +19,8 @@ HEADERS += completionsettingspage.h \
     cpptoolsconstants.h \
     cpptoolseditorsupport.h \
     cpptoolsplugin.h \
-    searchsymbols.h
+    searchsymbols.h \
+    cppdoxygen.h
 
 SOURCES += completionsettingspage.cpp \
     cppclassesfilter.cpp \
@@ -29,6 +30,7 @@ SOURCES += completionsettingspage.cpp \
     cppquickopenfilter.cpp \
     cpptoolseditorsupport.cpp \
     cpptoolsplugin.cpp \
-    searchsymbols.cpp
+    searchsymbols.cpp \
+    cppdoxygen.cpp
 
 FORMS += completionsettingspage.ui
diff --git a/src/plugins/cpptools/cpptools_global.h b/src/plugins/cpptools/cpptools_global.h
index 1793c738769..0b71d7b0f7c 100644
--- a/src/plugins/cpptools/cpptools_global.h
+++ b/src/plugins/cpptools/cpptools_global.h
@@ -34,10 +34,12 @@
 #ifndef CPPTOOLS_GLOBAL_H
 #define CPPTOOLS_GLOBAL_H
 
+#include <QtGlobal>
+
 #if defined(CPPTOOLS_LIBRARY)
 #  define CPPTOOLS_EXPORT Q_DECL_EXPORT
 #else
 #  define CPPTOOLS_EXPORT Q_DECL_IMPORT
 #endif
-        
+
 #endif // CPPTOOLS_GLOBAL_H
-- 
GitLab