From c5ce20c5f74d3ee6d665b3aedd9822a5ff204bc4 Mon Sep 17 00:00:00 2001
From: Christian Kamm <christian.d.kamm@nokia.com>
Date: Thu, 19 May 2011 13:19:08 +0200
Subject: [PATCH] C++ indenter: Treat extern "C" like namespace.

Change-Id: Ib0553d35fbd83aada2b8809aa008b1f75ca77c32
Done-with: Erik Verbruggen
Reviewed-on: http://codereview.qt.nokia.com/14
Reviewed-by: Erik Verbruggen <erik.verbruggen@nokia.com>
---
 src/plugins/cpptools/cppcodeformatter.cpp     | 23 +++++++++++++++++++
 src/plugins/cpptools/cppcodeformatter.h       |  3 +++
 .../codeformatter/tst_codeformatter.cpp       | 17 ++++++++++++++
 3 files changed, 43 insertions(+)

diff --git a/src/plugins/cpptools/cppcodeformatter.cpp b/src/plugins/cpptools/cppcodeformatter.cpp
index 33aa6aedefd..fecee6d0436 100644
--- a/src/plugins/cpptools/cppcodeformatter.cpp
+++ b/src/plugins/cpptools/cppcodeformatter.cpp
@@ -107,6 +107,20 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
             case T_RBRACE:      leave(); continue; // always nested in namespace_start
             } break;
 
+        case extern_start:
+            switch (kind) {
+            case T_STRING_LITERAL: break; // continue looking for the lbrace
+            case T_LBRACE:      enter(extern_open); break;
+            default:            leave(); continue;
+            } break;
+
+        case extern_open:
+            if (tryDeclaration())
+                break;
+            switch (kind) {
+            case T_RBRACE:      leave(); leave(); break; // always nested in extern_start
+            } break;
+
         case class_start:
             switch (kind) {
             case T_SEMICOLON:   leave(); break;
@@ -680,6 +694,7 @@ bool CodeFormatter::tryExpression(bool alsoExpression)
                     || type == substatement_open
                     || type == defun_open
                     || type == namespace_open
+                    || type == extern_open
                     || type == class_open
                     || type == brace_list_open) {
                 break;
@@ -759,6 +774,10 @@ bool CodeFormatter::tryDeclaration()
         enter(namespace_start);
         return true;
 
+    case T_EXTERN:
+        enter(extern_start);
+        return true;
+
     case T_STRUCT:
     case T_UNION:
     case T_CLASS:
@@ -1067,6 +1086,7 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
         *paddingDepth = 0;
 
     switch (newState) {
+    case extern_start:
     case namespace_start:
         if (firstToken) {
             *savedIndentDepth = tokenPosition;
@@ -1364,6 +1384,7 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
             const int type = state(i).type;
             if (type == class_open
                     || type == namespace_open
+                    || type == extern_open
                     || type == enum_open
                     || type == defun_open) {
                 *indentDepth = state(i).savedIndentDepth;
@@ -1468,6 +1489,8 @@ bool QtStyleCodeFormatter::shouldClearPaddingOnEnter(int state)
     case enum_open:
     case namespace_start:
     case namespace_open:
+    case extern_start:
+    case extern_open:
     case template_start:
     case if_statement:
     case else_clause:
diff --git a/src/plugins/cpptools/cppcodeformatter.h b/src/plugins/cpptools/cppcodeformatter.h
index 28f5dd62f8b..2a21d2ffc01 100644
--- a/src/plugins/cpptools/cppcodeformatter.h
+++ b/src/plugins/cpptools/cppcodeformatter.h
@@ -134,6 +134,9 @@ public: // must be public to make Q_GADGET introspection work
         namespace_start, // after the namespace token, before the opening brace.
         namespace_open, // Brace that opens a C++ namespace block.
 
+        extern_start, // after the extern token, before the opening brace.
+        extern_open, // Brace that opens a C++ extern block.
+
         declaration_start, // shifted a token which could start a declaration.
         operator_declaration, // after 'operator' in declaration_start
 
diff --git a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
index d0c3ee811a0..ade32d8c2e9 100644
--- a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
+++ b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
@@ -92,6 +92,7 @@ private Q_SLOTS:
     void indentToNextToken();
     void labels();
     void functionsWithExtraSpecifier();
+    void externSpec();
 };
 
 struct Line {
@@ -1192,6 +1193,22 @@ void tst_CodeFormatter::functionsWithExtraSpecifier()
     checkIndent(data);
 }
 
+void tst_CodeFormatter::externSpec()
+{
+    QList<Line> data;
+    data << Line("extern void foo() {}")
+         << Line("extern \"C\" {")
+         << Line("void foo() {}")
+         << Line("int a;")
+         << Line("class C {")
+         << Line("    int a;")
+         << Line("}")
+         << Line("}")
+         << Line("int a;")
+         ;
+    checkIndent(data);
+}
+
 QTEST_APPLESS_MAIN(tst_CodeFormatter)
 #include "tst_codeformatter.moc"
 
-- 
GitLab