benhamilton created this revision.
benhamilton added reviewers: djasper, jolesiak.
Herald added subscribers: cfe-commits, klimek.

Currently, indentation of Objective-C method names which are wrapped
onto the next line due to a long return type is controlled by the
style option `IndentWrappedFunctionNames`.

For the Google style, we'd like to indent Objective-C method names
when wrapped onto the next line, but *not* indent non-Objective-C
functions when wrapped onto the next line.

This diff adds a new style option, `IndentWrappedObjCMethodNames`,
with three options:

1. Auto: Keep current behavior (indent ObjC methods according to

`IndentWrappedFunctionNames`)

2. Always: Always indent wrapped ObjC methods

3. Never: Never indent wrapped ObjC methods

In a separate diff, I'll update the Google style to set
`IndentWrappedFunctionNames` to `Always`.

Test Plan: Tests updated. Ran tests with:

  % make -j12 FormatTests && ./tools/clang/unittests/Format/FormatTests


Repository:
  rC Clang

https://reviews.llvm.org/D45004

Files:
  include/clang/Format/Format.h
  lib/Format/ContinuationIndenter.cpp
  lib/Format/Format.cpp
  unittests/Format/FormatTestObjC.cpp

Index: unittests/Format/FormatTestObjC.cpp
===================================================================
--- unittests/Format/FormatTestObjC.cpp
+++ unittests/Format/FormatTestObjC.cpp
@@ -539,6 +539,36 @@
                "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
                " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
 
+  Style.IndentWrappedObjCMethodNames = FormatStyle::IWM_Always;
+  verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+               "    aaaaaaaaaaaaaaaaaaaaaaaaaaaa;\n");
+  verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+               "    aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+  verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+               "    aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+               "    aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+  verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+               "     aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+               "    aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+  verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+               "    aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+               "     aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+
+  Style.IndentWrappedObjCMethodNames = FormatStyle::IWM_Never;
+  verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+               "aaaaaaaaaaaaaaaaaaaaaaaaaaaa;\n");
+  verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+               "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+  verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+               "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+               "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+  verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+               " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+               "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+  verifyFormat("- (aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+               "aaaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a\n"
+               " aaaaaaaaaaaaaaaaaaaaaaaaaaa:(int)a;\n");
+
   // Continuation indent width should win over aligning colons if the function
   // name is long.
   Style = getGoogleStyle(FormatStyle::LK_ObjC);
Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -243,6 +243,16 @@
   }
 };
 
+template <>
+struct ScalarEnumerationTraits<FormatStyle::IndentWrappedMethodStyle> {
+  static void enumeration(IO &IO,
+                          FormatStyle::IndentWrappedMethodStyle &Value) {
+    IO.enumCase(Value, "Auto", FormatStyle::IWM_Auto);
+    IO.enumCase(Value, "Always", FormatStyle::IWM_Always);
+    IO.enumCase(Value, "Never", FormatStyle::IWM_Never);
+  }
+};
+
 template <> struct MappingTraits<FormatStyle> {
   static void mapping(IO &IO, FormatStyle &Style) {
     // When reading, read the language first, we need it for getPredefinedStyle.
@@ -378,6 +388,8 @@
     IO.mapOptional("IndentWidth", Style.IndentWidth);
     IO.mapOptional("IndentWrappedFunctionNames",
                    Style.IndentWrappedFunctionNames);
+    IO.mapOptional("IndentWrappedObjCMethodNames",
+                   Style.IndentWrappedObjCMethodNames);
     IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
     IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
     IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
@@ -645,6 +657,7 @@
   LLVMStyle.IndentCaseLabels = false;
   LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
   LLVMStyle.IndentWrappedFunctionNames = false;
+  LLVMStyle.IndentWrappedObjCMethodNames = FormatStyle::IWM_Auto;
   LLVMStyle.IndentWidth = 2;
   LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
   LLVMStyle.JavaScriptWrapImports = true;
Index: lib/Format/ContinuationIndenter.cpp
===================================================================
--- lib/Format/ContinuationIndenter.cpp
+++ lib/Format/ContinuationIndenter.cpp
@@ -26,6 +26,19 @@
 namespace clang {
 namespace format {
 
+// Returns true if a TT_SelectorName should be indented when wrapped,
+// false otherwise.
+static bool shouldIndentWrappedSelectorName(const FormatStyle &Style) {
+  // TT_SelectorName is used across multiple languages; we only want
+  // Style.IndentWrappedObjCMethodNames to apply to ObjC.
+  if (Style.Language == FormatStyle::LK_ObjC)
+    return Style.IndentWrappedObjCMethodNames == FormatStyle::IWM_Always ||
+           (Style.IndentWrappedObjCMethodNames == FormatStyle::IWM_Auto &&
+            Style.IndentWrappedFunctionNames);
+  else
+    return Style.IndentWrappedFunctionNames;
+}
+
 // Returns the length of everything up to the first possible line break after
 // the ), ], } or > matching \c Tok.
 static unsigned getLengthToMatchingParen(const FormatToken &Tok) {
@@ -698,7 +711,7 @@
         State.Stack.back().AlignColons = false;
       } else {
         State.Stack.back().ColonPos =
-            (Style.IndentWrappedFunctionNames
+            (shouldIndentWrappedSelectorName(Style)
                  ? std::max(State.Stack.back().Indent,
                             State.FirstIndent + Style.ContinuationIndentWidth)
                  : State.Stack.back().Indent) +
@@ -897,7 +910,7 @@
   if (NextNonComment->is(TT_SelectorName)) {
     if (!State.Stack.back().ObjCSelectorNameFound) {
       unsigned MinIndent =
-          (Style.IndentWrappedFunctionNames
+          (shouldIndentWrappedSelectorName(Style)
                ? std::max(State.Stack.back().Indent,
                           State.FirstIndent + Style.ContinuationIndentWidth)
                : State.Stack.back().Indent);
@@ -996,10 +1009,9 @@
         !Current.NextOperator ? 0 : State.Column;
   if (Current.is(TT_SelectorName)) {
     State.Stack.back().ObjCSelectorNameFound = true;
-    if (Style.IndentWrappedFunctionNames) {
+    if (shouldIndentWrappedSelectorName(Style))
       State.Stack.back().Indent =
           State.FirstIndent + Style.ContinuationIndentWidth;
-    }
   }
   if (Current.is(TT_CtorInitializerColon) &&
       Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon) {
Index: include/clang/Format/Format.h
===================================================================
--- include/clang/Format/Format.h
+++ include/clang/Format/Format.h
@@ -1151,6 +1151,30 @@
   /// \endcode
   bool IndentWrappedFunctionNames;
 
+  /// \brief The style of indenting long function or method names wrapped
+  /// onto the next line.
+  enum IndentWrappedMethodStyle {
+    /// Automatically determine indenting style.
+    IWM_Auto,
+    /// Always indent wrapped methods names.
+    IWM_Always,
+    /// Never indent wrapped method names.
+    IWM_Never,
+  };
+
+  /// \brief Controls whether Objective-C method definition or
+  /// declaration is indented after wrapping onto the next line.
+  /// \code
+  ///    Always (or Auto, if IndentWrappedFunctionNames is true):
+  ///    - (LoooooooooooooooooooooooooooooooooooooooongReturnType)
+  ///        loooooooooooooooooooooooooooooooongFunctionDeclaration;
+  ///
+  ///    Never (or Auto, if IndentWrappedFunctionNames is false):
+  ///    - (LoooooooooooooooooooooooooooooooooooooooongReturnType)
+  ///    LoooooooooooooooooooooooooooooooongFunctionDeclaration;
+  /// \endcode
+  IndentWrappedMethodStyle IndentWrappedObjCMethodNames;
+
   /// \brief Quotation styles for JavaScript strings. Does not affect template
   /// strings.
   enum JavaScriptQuoteStyle {
@@ -1741,6 +1765,7 @@
            IndentPPDirectives == R.IndentPPDirectives &&
            IndentWidth == R.IndentWidth && Language == R.Language &&
            IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
+           IndentWrappedObjCMethodNames == R.IndentWrappedObjCMethodNames &&
            JavaScriptQuotes == R.JavaScriptQuotes &&
            JavaScriptWrapImports == R.JavaScriptWrapImports &&
            KeepEmptyLinesAtTheStartOfBlocks ==
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to