]> granicus.if.org Git - clang/commitdiff
Improvements to function type and ObjC block formatting.
authorDaniel Jasper <djasper@google.com>
Thu, 10 Jan 2013 13:08:12 +0000 (13:08 +0000)
committerDaniel Jasper <djasper@google.com>
Thu, 10 Jan 2013 13:08:12 +0000 (13:08 +0000)
Before: int (^myBlock) (int) = ^(int num) {}
        A<void ()>;
int (*b)(int);

After:  int (^myBlock)(int) = ^(int num) {}
        A<void()>;
int(*b)(int);

For function types and function pointer types, this patch only makes
the behavior consistent (for types that are keywords and other types).
For the latter function pointer type declarations, we'll probably
want to add a space after "int".

Also added LangOpts.Bool = 1, so we handle "A<bool()>" appropriately
Moved the LangOpts-settings to a public place for use by tests
and clang-format binary.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172065 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Format/Format.h
lib/Format/Format.cpp
test/Index/comment-c-decls.c
test/Index/format-comment-cdecls.c
unittests/Format/FormatTest.cpp

index 32bb53c8d4cd667853092bcac9a0ce6cbf389918..7713cf784a801043c1b18199a07c1205cf388f34 100644 (file)
@@ -78,6 +78,9 @@ tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
                                SourceManager &SourceMgr,
                                std::vector<CharSourceRange> Ranges);
 
+/// \brief Returns the \c LangOpts that the formatter expects you to set.
+LangOptions getFormattingLangOpts();
+
 } // end namespace format
 } // end namespace clang
 
index 00a4b779801045311cc80c066ff67195c7dd622a..c0ed6c5be19dd78f742805e0fe7c3555dfd2c4ad 100644 (file)
@@ -34,6 +34,7 @@ enum TokenType {
   TT_CtorInitializerColon,
   TT_DirectorySeparator,
   TT_LineComment,
+  TT_ObjCBlockLParen,
   TT_ObjCMethodSpecifier,
   TT_OverloadedOperator,
   TT_PointerOrReference,
@@ -627,6 +628,8 @@ public:
     }
 
     bool parseParens() {
+      if (CurrentToken != NULL && CurrentToken->is(tok::caret))
+        CurrentToken->Parent->Type = TT_ObjCBlockLParen;
       while (CurrentToken != NULL) {
         if (CurrentToken->is(tok::r_paren)) {
           next();
@@ -995,7 +998,8 @@ private:
     if (Left.is(tok::at) &&
         (Right.is(tok::identifier) || Right.is(tok::string_literal) ||
          Right.is(tok::char_constant) || Right.is(tok::numeric_constant) ||
-         Right.is(tok::l_paren) || Right.is(tok::l_brace)))
+         Right.is(tok::l_paren) || Right.is(tok::l_brace) ||
+         Right.is(tok::kw_true) || Right.is(tok::kw_false)))
       return false;
     if (Left.is(tok::less) || Right.is(tok::greater) || Right.is(tok::less))
       return false;
@@ -1024,8 +1028,7 @@ private:
     if (Right.is(tok::l_paren)) {
       return Left.is(tok::kw_if) || Left.is(tok::kw_for) ||
              Left.is(tok::kw_while) || Left.is(tok::kw_switch) ||
-             (Left.isNot(tok::identifier) && Left.isNot(tok::kw_sizeof) &&
-              Left.isNot(tok::kw_typeof) && Left.isNot(tok::kw_alignof));
+             Left.is(tok::kw_return) || Left.is(tok::kw_catch);
     }
     if (Left.is(tok::at) &&
         Right.FormatTok.Tok.getObjCKeywordID() != tok::objc_not_keyword)
@@ -1050,11 +1053,11 @@ private:
         return false;
     }
 
-    if (Tok.Type == TT_CtorInitializerColon)
+    if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
       return true;
     if (Tok.Type == TT_OverloadedOperator)
       return Tok.is(tok::identifier) || Tok.is(tok::kw_new) ||
-             Tok.is(tok::kw_delete);
+             Tok.is(tok::kw_delete) || Tok.is(tok::kw_bool);
     if (Tok.Parent->Type == TT_OverloadedOperator)
       return false;
     if (Tok.is(tok::colon))
@@ -1290,5 +1293,15 @@ tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
   return formatter.format();
 }
 
+LangOptions getFormattingLangOpts() {
+  LangOptions LangOpts;
+  LangOpts.CPlusPlus = 1;
+  LangOpts.CPlusPlus11 = 1;
+  LangOpts.Bool = 1;
+  LangOpts.ObjC1 = 1;
+  LangOpts.ObjC2 = 1;
+  return LangOpts;
+}
+
 } // namespace format
 } // namespace clang
index f6d3feec81c377f0ecbeb33aef2e3051b496ff83..261481a5ea631265a6826655e55ca87eed920682 100644 (file)
@@ -95,10 +95,10 @@ enum e {
  *\brief block declaration
 */
 int (^Block) (int i, int j);
-// CHECK: <Declaration>int (^Block) (int, int)</Declaration>
+// CHECK: <Declaration>int (^Block)(int, int)</Declaration>
 
 /**
  *\brief block declaration
 */
 int (^Block1) (int i, int j) = ^(int i, int j) { return i + j; };
-// CHECK: <Declaration>int (^Block1) (int, int) = ^(int i, int j) {\n}</Declaration>
+// CHECK: <Declaration>int (^Block1)(int, int) = ^(int i, int j) {\n}</Declaration>
index 31ec95b9212810db7873b719af377cf3c4580355..ff36dd7fd085d754211713352d1c98ade0bfceba 100644 (file)
@@ -90,10 +90,10 @@ enum e {
  *\brief block declaration
 */
 int (^Block) (int i, int j);
-// CHECK: <Declaration>int (^Block) (int, int)</Declaration>
+// CHECK: <Declaration>int (^Block)(int, int)</Declaration>
 
 /**
  *\brief block declaration
 */
 int (^Block1) (int i, int j) = ^(int i, int j) { return i + j; };
-// CHECK: <Declaration>int (^Block1) (int, int) = ^(int i, int j) {\n}</Declaration>
+// CHECK: <Declaration>int (^Block1)(int, int) = ^(int i, int j) {\n}</Declaration>
index 860661b432419d1c66c7cb8db403cdcfe0d1137d..39d8bb8f774aacd2bb947861cd5bb97357a8d0d2 100644 (file)
@@ -26,12 +26,8 @@ protected:
     std::vector<CharSourceRange> Ranges(
         1,
         CharSourceRange::getCharRange(Start, Start.getLocWithOffset(Length)));
-    LangOptions LangOpts;
-    LangOpts.CPlusPlus = 1;
-    LangOpts.CPlusPlus11 = 1;
-    LangOpts.ObjC1 = 1;
-    LangOpts.ObjC2 = 1;
-    Lexer Lex(ID, Context.Sources.getBuffer(ID), Context.Sources, LangOpts);
+    Lexer Lex(ID, Context.Sources.getBuffer(ID), Context.Sources,
+              getFormattingLangOpts());
     tooling::Replacements Replace = reformat(Style, Lex, Context.Sources,
                                              Ranges);
     EXPECT_TRUE(applyAllReplacements(Replace, Context.Rewrite));
@@ -1029,6 +1025,15 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
   verifyGoogleFormat("int a = b ? *c : *d;");
 }
 
+TEST_F(FormatTest, FormatsFunctionTypes) {
+  // FIXME: Determine the cases that need a space after the return type and fix.
+  verifyFormat("A<bool()> a;");
+  verifyFormat("A<SomeType()> a;");
+  verifyFormat("A<void(*)(int, std::string)> a;");
+
+  verifyFormat("int(*func)(void *);");
+}
+
 TEST_F(FormatTest, DoesNotBreakBeforePointerOrReference) {
   verifyFormat("int *someFunction(int LoooooooooooooooongParam1,\n"
                "                  int LoooooooooooooooongParam2) {\n}");
@@ -1177,8 +1182,8 @@ TEST_F(FormatTest, FormatForObjectiveCMethodDecls) {
 }
 
 TEST_F(FormatTest, FormatObjCBlocks) {
-  verifyFormat("int (^Block) (int, int);");
-  verifyFormat("int (^Block1) (int, int) = ^(int i, int j)");
+  verifyFormat("int (^Block)(int, int);");
+  verifyFormat("int (^Block1)(int, int) = ^(int i, int j)");
 }
 
 TEST_F(FormatTest, FormatObjCInterface) {