Hello,
this patch tries to address the fact the 'type' syntax highlighting
format isn't used in any version of QtCreator i've tried but for Qt
specific stuff.
It demotes some keywords (most of 7.1 [dcl.dcl])  and identifiers
ending with '_t' as types.

Given this is my first tentative to contribute to this project, being
not quite sure about which set of features of C++ were allowed, i've
tried to restrain myself (ie i haven't added __m128 & co) yet i
couldn't resist removing some of the string matching spaghetti. Sorry.
If more aggressive preprocessor tricks are allowed, i'd like to
tighten it some more (but i feared even basic variadic macros would
already be too much).

This patch is against v1.2.1 mostly because i haven't found out how to
statically build Qt 4.7 and trunk.

PS: I've seen signs of semantic highlighting in v2.0, which i'm
interested in, but couldn't quite figure how/what it was supposed to
effect.
--- qtcreator-1.2.1.orig/src/plugins/cppeditor/cpphighlighter.cpp	2009-07-10 14:38:08.000000000 +0200
+++ qtcreator-1.2.1/src/plugins/cppeditor/cpphighlighter.cpp	2010-04-02 14:49:03.076338548 +0200
@@ -41,6 +41,80 @@
 using namespace TextEditor;
 using namespace CPlusPlus;
 
+namespace {
+    // makes a sparse table of strings binned by their length.
+    #define MATCH_TABLE_LATIN(postfix, args...) const char * const tbl_latin_##postfix[] = { args }
+    // makes an index for sparsely binned strings of idx_lo <= length <= idx_hi, -1 being emptyness.
+    // the first element is always empty.
+    #define MATCH_TABLE_SKIP(postfix, idx_lo, idx_hi, args...) \
+        enum { tbl_lo_##postfix = idx_lo, tbl_hi_##postfix = idx_hi }; \
+        const char tbl_skip_##postfix[] = { -1, args };
+    // a predicate for text being exactly matched within postfix set.
+    #define IS_MATCHED(postfix, text) is_matched( tbl_lo_##postfix,  tbl_hi_##postfix,  tbl_latin_##postfix,  tbl_skip_##postfix, text)
+
+    bool is_matched(unsigned idx_lo, unsigned idx_hi, const char * const tbl_latin[], const char * const tbl_skip, const QStringRef &text) {
+        const unsigned len = text.length(), start = (len - idx_lo) < (1 + idx_hi - idx_lo) ? 1 + len - idx_lo : 0;
+        const char first = text.at(0).toLatin1();
+        int i = tbl_skip[start];
+        if (i + 1)
+            while (const char * const p = tbl_latin[i++])
+                if (p[0] == first && text == QLatin1String(p))
+                    return true;
+        return false;
+    }
+
+    // preprocessor keywords.
+    MATCH_TABLE_LATIN(PPKeyword,
+        /* len: 2 */ "if", 0,
+        /* len: 4 */ "else", "elif", 0,
+        /* len: 5 */ "ifdef", "undef", "endif", "error",  0,
+        /* len: 6 */ "define", "ifndef", "pragma", "import", 0,
+        /* len: 7 */ "include", "warning",  0,
+        /* len:12 */ "include_next", 0 );
+    MATCH_TABLE_SKIP(PPKeyword, 2, 12,
+         /* len: 2 */ 0,
+         -1,
+         /* len: 4 */ 0+2,
+         /* len: 5 */ 0+2+3,
+         /* len: 6 */ 0+2+3+5,
+         /* len: 7 */ 0+2+3+5+5,
+         -1,-1,-1,-1,
+         /* len:12 */ 0+2+3+5+5+3 );
+
+    // Qt keywords.
+    MATCH_TABLE_LATIN(QtKeyword,
+        /* len: 4 */ "emit","SLOT",0,
+        /* len: 5 */ "slots",0,
+        /* len: 6 */ "SIGNAL",0,
+        /* len: 7 */ "signals","foreach","forever",0 );
+    MATCH_TABLE_SKIP(QtKeyword, 4,7,
+        /* len: 4 */ 0,
+        /* len: 5 */ 0+3,
+        /* len: 6 */ 0+3+2,
+        /* len: 7 */ 0+3+2+2 );
+
+    MATCH_TABLE_LATIN(DeclSpec,
+        /* len: 3 */ "int", 0,
+        /* len: 4 */ "void", "bool", "char", "long", "auto", 0,
+        /* len: 5 */ "const", "float", "short", 0,
+        /* len: 6 */ "signed", "static", "extern", "double", 0,
+        /* len: 7 */ "wchar_t", "static", "mutable", 0,
+        /* len: 8 */ "unsigned", "volatile", "register", 0 );
+    MATCH_TABLE_SKIP(DeclSpec, 3,8,
+         /* len: 3 */ 0,
+         /* len: 4 */ 0+2,
+         /* len: 5 */ 0+2+6,
+         /* len: 6 */ 0+2+6+4,
+         /* len: 7 */ 0+2+6+4+5,
+         /* len: 8 */ 0+2+6+4+5+4 );
+
+    // a predicate to refine/demote a keyword to a type for the purpose of highlighting.
+    // candidates are from 7.1 [dcl.dcl], with 7.1, 7.1.2, 7.1.5.3 ommited.
+    bool isDeclSpec(const QStringRef &text) {
+        return IS_MATCHED(DeclSpec, text);
+    }
+}
+
 CppHighlighter::CppHighlighter(QTextDocument *document) :
     QSyntaxHighlighter(document)
 {
@@ -157,8 +231,13 @@
                 initialState = 0;
             }
 
-        } else if (tk.isKeyword() || isQtKeyword(tk.text()))
-            setFormat(tk.position(), tk.length(), m_formats[CppKeywordFormat]);
+        } else if (tk.isKeyword() || isQtKeyword(tk.text())) {
+            CppFormats fmt = CppKeywordFormat;
+            // demote some keywords to type (qualifiers and so on).
+            if (tk.isKeyword() && isDeclSpec(tk.text()))
+                fmt = CppTypeFormat;
+            setFormat(tk.position(), tk.length(), m_formats[fmt]);
+        }
 
         else if (tk.isOperator())
             setFormat(tk.position(), tk.length(), m_formats[CppOperatorFormat]);
@@ -239,94 +318,12 @@
 
 bool CppHighlighter::isPPKeyword(const QStringRef &text) const
 {
-    switch (text.length())
-    {
-    case 2:
-        if (text.at(0) == 'i' && text.at(1) == 'f')
-            return true;
-        break;
-
-    case 4:
-        if (text.at(0) == 'e' && text == QLatin1String("elif"))
-            return true;
-        else if (text.at(0) == 'e' && text == QLatin1String("else"))
-            return true;
-        break;
-
-    case 5:
-        if (text.at(0) == 'i' && text == QLatin1String("ifdef"))
-            return true;
-        else if (text.at(0) == 'u' && text == QLatin1String("undef"))
-            return true;
-        else if (text.at(0) == 'e' && text == QLatin1String("endif"))
-            return true;
-        else if (text.at(0) == 'e' && text == QLatin1String("error"))
-            return true;
-        break;
-
-    case 6:
-        if (text.at(0) == 'i' && text == QLatin1String("ifndef"))
-            return true;
-        if (text.at(0) == 'i' && text == QLatin1String("import"))
-            return true;
-        else if (text.at(0) == 'd' && text == QLatin1String("define"))
-            return true;
-        else if (text.at(0) == 'p' && text == QLatin1String("pragma"))
-            return true;
-        break;
-
-    case 7:
-        if (text.at(0) == 'i' && text == QLatin1String("include"))
-            return true;
-        else if (text.at(0) == 'w' && text == QLatin1String("warning"))
-            return true;
-        break;
-
-    case 12:
-        if (text.at(0) == 'i' && text == QLatin1String("include_next"))
-            return true;
-        break;
-
-    default:
-        break;
-    }
-
-    return false;
+    return IS_MATCHED(PPKeyword, text);
 }
 
 bool CppHighlighter::isQtKeyword(const QStringRef &text) const
 {
-    switch (text.length()) {
-    case 4:
-        if (text.at(0) == 'e' && text == QLatin1String("emit"))
-            return true;
-        else if (text.at(0) == 'S' && text == QLatin1String("SLOT"))
-            return true;
-        break;
-
-    case 5:
-        if (text.at(0) == 's' && text == QLatin1String("slots"))
-            return true;
-        break;
-
-    case 6:
-        if (text.at(0) == 'S' && text == QLatin1String("SIGNAL"))
-            return true;
-        break;
-
-    case 7:
-        if (text.at(0) == 's' && text == QLatin1String("signals"))
-            return true;
-        else if (text.at(0) == 'f' && text == QLatin1String("foreach"))
-            return true;
-        else if (text.at(0) == 'f' && text == QLatin1String("forever"))
-            return true;
-        break;
-
-    default:
-        break;
-    }
-    return false;
+    return IS_MATCHED(QtKeyword, text);
 }
 
 void CppHighlighter::highlightWord(QStringRef word, int position, int length)
@@ -340,6 +337,11 @@
             || word.at(1) == QLatin1Char('t'))) {
         setFormat(position, length, m_formats[CppTypeFormat]);
     }
+    // highlight identifiers ending in '_t' as a type.
+    else if (word.length() > 2
+        && word.at(word.length() - 2) == QLatin1Char('_')
+        && word.at(word.length() - 1) == QLatin1Char('t'))
+        setFormat(position, length, m_formats[CppTypeFormat]);
 }
 
 void CppHighlighter::highlightDoxygenComment(const QString &text, int position, int)
_______________________________________________
Qt-creator mailing list
[email protected]
http://lists.trolltech.com/mailman/listinfo/qt-creator

Reply via email to