Используемый метод переходит на следующую строку вместо перехода по параметрам

У меня возникли проблемы с настройкой моего файла в формате clang специально в этом случае. Это может быть фиктивный вопрос, но я пробовал несколько комбинаций, и мне не удалось настроить его.

Что у меня есть:

  bool res = MethodName(<ParameterList>);
  res      = res && AdtVec_Equal(<ParameterList>);
  res      = res && AdtVec_Equal(<ParameterList>);
  res      = res &&
        AdtVec_Equal(<ParameterList>); //same num of parameters, longer names

Что я хочу:

  bool res = MethodName(<ParameterList>);
  res      = res && AdtVec_Equal(<ParameterList>);
  res      = res && AdtVec_Equal(<ParameterList>);
  res      = res && AdtVec_Equal(<ParamA>, <ParamB>,
                                 <ParamC>);

Я предполагаю, что это происходит из-за значения columnLimit, но я не хочу устанавливать его дольше. Любые идеи?

Мой файл в формате .clang выглядит следующим образом:

BasedOnStyle: LLVM

AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignConsecutiveMacros: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
  BeforeElse: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Stroustrup
BreakBeforeTernaryOperators: false
BreakInheritanceList: AfterColon
ColumnLimit: 80
ContinuationIndentWidth: 8
IncludeBlocks: Regroup
IndentCaseLabels: true
IndentWidth: 2
KeepEmptyLinesAtTheStartOfBlocks: false
PenaltyReturnTypeOnItsOwnLine: 100
PointerAlignment: Left
ReflowComments: false
SortIncludes: true
SpacesBeforeTrailingComments: 2
Standard: Auto

Заранее спасибо.


person Sergio Sánchez    schedule 25.03.2020    source источник


Ответы (1)


Краткий ответ: я не вижу разумного способа избежать этого.

Точное поведение clang-format зависит от длины параметров и от того, является ли вызов функции сам по себе или частью выражения. Чтобы увидеть различия, я создал пример входного файла:

int f()
{
  bool res = MethodName(a, b, c, d);
  res      = res && AdtVec_Equal(a, b, c, d);
  res      = res && AdtVec_Equal(a, b, c, d);
  res      = res && AdtVec_Equal(aLooooooooong, bLooooooong, cLoooooooong, dLoooooong);
  res      = res && AdtVec_Equal(aLooooooooonger, bLooooooonger, cLoooooooonger, dLoooooonger);

  AdtVec_Equal(a, b, c, d);
  AdtVec_Equal(aLooooooooooooong, bLooooooooooong, cLoooooooooooong, dLoooooooooong);
}

Затем ваши настройки .clang-format производят следующее:

int f()
{
  bool res = MethodName(a, b, c, d);
  res      = res && AdtVec_Equal(a, b, c, d);
  res      = res && AdtVec_Equal(a1, b1, c1, d1);
  res      = res &&
        AdtVec_Equal(aLooooooooong, bLooooooong, cLoooooooong, dLoooooong);
  res = res && AdtVec_Equal(aLooooooooonger, bLooooooonger, cLoooooooonger,
                            dLoooooonger);

  AdtVec_Equal(a, b, c, d);
  AdtVec_Equal(aLooooooooooooong, bLooooooooooong, cLoooooooooooong,
               dLoooooooooong);
}

Обратите внимание, что если параметры действительно длинные, вы получаете параметры так, как вам нравится (AdtVec_Equal в той же строке, что и res, а параметры прерываются и выстраиваются в очередь под первым параметром). Но есть окно, в котором параметры достаточно длинные, чтобы все не помещалось в одну строку, но достаточно короткие, чтобы позволить вызову AdtVec_Equal уместиться на одной строке, и в этом окне clang-format действительно хочет поместить AdtVec_Equal вызов полностью на одной линии.

Возможные обходные пути:

  1. Возможно, вам это не понравится, но вы можете установить PenaltyExcessCharacter на что-то очень маленькое, например 10. Это приводит к этому результату:

    int f()
    {
      bool res = MethodName(a, b, c, d);
      res      = res && AdtVec_Equal(a, b, c, d);
      res      = res && AdtVec_Equal(a1, b1, c1, d1);
      res = res && AdtVec_Equal(aLooooooooong, bLooooooong, cLoooooooong, dLoooooong);
      res = res && AdtVec_Equal(aLooooooooonger, bLooooooonger, cLoooooooonger,
                                dLoooooonger);
    
      AdtVec_Equal(a, b, c, d);
      AdtVec_Equal(aLooooooooooooong, bLooooooooooong, cLoooooooooooong,
                   dLoooooooooong);
    }
    

    Это позволяет избежать вызова AdtVec_Equal в отдельной строке от res. Но для этого он неправильно выравнивает знак равенства, а также расширяет строку за пределы 80 символов. Это, вероятно, испортит и другие части вашего кода.

  2. Вы можете вручную отформатировать код так, как вам нравится, а затем окружить код // clang-format off и // clang-format on.


Я тестировал с использованием clang-format 6.0.0, а также тестировал 10.0.0 с помощью конфигуратора. . Таким образом, такое поведение существует некоторое время и, вероятно, не изменится, если кто-то не создаст новую опцию стиля и не отправит патч для ее реализации.

person Eric Backus    schedule 21.08.2020