diff options
author | Gedare Bloom <gedare@rtems.org> | 2024-07-24 20:47:11 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-24 19:47:11 -0700 |
commit | ccae7b461be339e717d02f99ac857cf0bc7d17fc (patch) | |
tree | 6f3cf4629836a7fd4814b33db06f7e49febb7e9f /clang/lib/Format/ContinuationIndenter.cpp | |
parent | 7e7a9069d4240d2ae619cb50eba09f948c537ce3 (diff) | |
download | llvm-ccae7b461be339e717d02f99ac857cf0bc7d17fc.zip llvm-ccae7b461be339e717d02f99ac857cf0bc7d17fc.tar.gz llvm-ccae7b461be339e717d02f99ac857cf0bc7d17fc.tar.bz2 |
[clang-format] Improve BlockIndent at ColumnLimit (#93140)
Fixes #55731
The reported formatting problems were related to ignoring deep nesting
of "simple" functions (causing #54808) and to allowing the trailing
annotation to become separated from the closing parens, which allowed a
break to occur between the closing parens and the trailing annotation.
The fix for the nesting of "simple" functions is to detect them more
carefully. "Simple" was defined in a comment as being a single
non-expression argument. I tried to stay as close to the original intent
of the implementation while fixing the various bad formatting reports.
In the process of fixing these bugs, some latent bugs were discovered
related to how JavaScript Template Strings are handled. Those are also
fixed here.
---------
Co-authored-by: Owen Pan <owenpiano@gmail.com>
Diffstat (limited to 'clang/lib/Format/ContinuationIndenter.cpp')
-rw-r--r-- | clang/lib/Format/ContinuationIndenter.cpp | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index b073604..df86a77 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -803,6 +803,37 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, tok::kw_switch); }; + auto IsFunctionCallParen = [](const FormatToken &Tok) { + return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [this](const FormatToken &Tok) { + if (!Style.isJavaScript()) + return false; + for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) { + if (Prev->is(TT_TemplateString) && Prev->opensScope()) + return true; + if (Prev->is(TT_TemplateString) && Prev->closesScope()) + break; + } + return false; + }; + // Identifies simple (no expression) one-argument function calls. + const auto IsSimpleFunction = [&](const FormatToken &Tok) { + if (!Tok.FakeLParens.empty() && Tok.FakeLParens.back() > prec::Unknown) + return false; + const auto *Previous = Tok.Previous; + if (!Previous || (!Previous->isOneOf(TT_FunctionDeclarationLParen, + TT_LambdaDefinitionLParen) && + !IsFunctionCallParen(*Previous))) { + return true; + } + if (IsOpeningBracket(Tok) || IsInTemplateString(Tok)) + return true; + const auto *Next = Tok.Next; + return !Next || Next->isMemberAccess() || + Next->is(TT_FunctionDeclarationLParen) || IsFunctionCallParen(*Next); + }; if ((Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak || Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) && IsOpeningBracket(Previous) && State.Column > getNewLineColumn(State) && @@ -813,10 +844,10 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, // caaaaaaaaaaaall( // caaaaaaaaaaaall( // caaaaaaaaaaaaaaaaaaaaaaall(aaaaaaaaaaaaaa, aaaaaaaaa)))); - Current.FakeLParens.size() > 0 && - Current.FakeLParens.back() > prec::Unknown) { + !IsSimpleFunction(Current)) { CurrentState.NoLineBreak = true; } + if (Previous.is(TT_TemplateString) && Previous.opensScope()) CurrentState.NoLineBreak = true; @@ -831,7 +862,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, Previous.isNot(TT_TableGenDAGArgOpenerToBreak) && !(Current.MacroParent && Previous.MacroParent) && (Current.isNot(TT_LineComment) || - Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen))) { + Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen)) && + !IsInTemplateString(Current)) { CurrentState.Indent = State.Column + Spaces; CurrentState.IsAligned = true; } |