diff options
| author | Krasimir Georgiev <krasimir@google.com> | 2018-07-30 08:45:45 +0000 | 
|---|---|---|
| committer | Krasimir Georgiev <krasimir@google.com> | 2018-07-30 08:45:45 +0000 | 
| commit | 6a5c95bd6643a78b5bc1df7397444138956ffbc0 (patch) | |
| tree | e7409e3697234de49f96f0acda6079bf858f8f40 /clang/lib | |
| parent | e5899447b40355ad0a79db6e04f8f1d5293d8fd1 (diff) | |
| download | bcm5719-llvm-6a5c95bd6643a78b5bc1df7397444138956ffbc0.tar.gz bcm5719-llvm-6a5c95bd6643a78b5bc1df7397444138956ffbc0.zip  | |
[clang-format] Indent after breaking Javadoc annotated line
Summary:
This patch makes clang-format indent the subsequent lines created by breaking a
long javadoc annotated line.
Reviewers: mprobst
Reviewed By: mprobst
Subscribers: acoomans, cfe-commits
Differential Revision: https://reviews.llvm.org/D49797
llvm-svn: 338232
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Format/BreakableToken.cpp | 54 | ||||
| -rw-r--r-- | clang/lib/Format/BreakableToken.h | 25 | ||||
| -rw-r--r-- | clang/lib/Format/ContinuationIndenter.cpp | 25 | ||||
| -rw-r--r-- | clang/lib/Format/Format.cpp | 7 | 
4 files changed, 96 insertions, 15 deletions
diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp index cc68f70100e..9974ed0a518 100644 --- a/clang/lib/Format/BreakableToken.cpp +++ b/clang/lib/Format/BreakableToken.cpp @@ -235,6 +235,7 @@ BreakableToken::Split BreakableStringLiteral::getSplit(  void BreakableStringLiteral::insertBreak(unsigned LineIndex,                                           unsigned TailOffset, Split Split, +                                         unsigned ContentIndent,                                           WhitespaceManager &Whitespaces) const {    Whitespaces.replaceWhitespaceInToken(        Tok, Prefix.size() + TailOffset + Split.first, Split.second, Postfix, @@ -510,8 +511,33 @@ unsigned BreakableBlockComment::getContentStartColumn(unsigned LineIndex,    return std::max(0, ContentColumn[LineIndex]);  } +const llvm::StringSet<> +    BreakableBlockComment::ContentIndentingJavadocAnnotations = { +        "@param", "@return",     "@returns", "@throws",  "@type", "@template", +        "@see",   "@deprecated", "@define",  "@exports", "@mods", +}; + +unsigned BreakableBlockComment::getContentIndent(unsigned LineIndex) const { +  if (Style.Language != FormatStyle::LK_Java && +      Style.Language != FormatStyle::LK_JavaScript) +    return 0; +  // The content at LineIndex 0 of a comment like: +  // /** line 0 */ +  // is "* line 0", so we need to skip over the decoration in that case. +  StringRef ContentWithNoDecoration = Content[LineIndex]; +  if (LineIndex == 0 && ContentWithNoDecoration.startswith("*")) { +    ContentWithNoDecoration = ContentWithNoDecoration.substr(1).ltrim(Blanks); +  } +  StringRef FirstWord = ContentWithNoDecoration.substr( +      0, ContentWithNoDecoration.find_first_of(Blanks)); +  if (ContentIndentingJavadocAnnotations.find(FirstWord) != +      ContentIndentingJavadocAnnotations.end()) +    return Style.ContinuationIndentWidth; +  return 0; +} +  void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset, -                                        Split Split, +                                        Split Split, unsigned ContentIndent,                                          WhitespaceManager &Whitespaces) const {    StringRef Text = Content[LineIndex].substr(TailOffset);    StringRef Prefix = Decoration; @@ -532,10 +558,14 @@ void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,        Text.data() - tokenAt(LineIndex).TokenText.data() + Split.first;    unsigned CharsToRemove = Split.second;    assert(LocalIndentAtLineBreak >= Prefix.size()); +  std::string PrefixWithTrailingIndent = Prefix; +  for (unsigned I = 0; I < ContentIndent; ++I) +    PrefixWithTrailingIndent += " ";    Whitespaces.replaceWhitespaceInToken( -      tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "", Prefix, -      InPPDirective, /*Newlines=*/1, -      /*Spaces=*/LocalIndentAtLineBreak - Prefix.size()); +      tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "", +      PrefixWithTrailingIndent, InPPDirective, /*Newlines=*/1, +      /*Spaces=*/LocalIndentAtLineBreak + ContentIndent - +          PrefixWithTrailingIndent.size());  }  BreakableToken::Split @@ -543,8 +573,17 @@ BreakableBlockComment::getReflowSplit(unsigned LineIndex,                                        llvm::Regex &CommentPragmasRegex) const {    if (!mayReflow(LineIndex, CommentPragmasRegex))      return Split(StringRef::npos, 0); - +   +  // If we're reflowing into a line with content indent, only reflow the next +  // line if its starting whitespace matches the content indent.    size_t Trimmed = Content[LineIndex].find_first_not_of(Blanks); +  if (LineIndex) { +    unsigned PreviousContentIndent = getContentIndent(LineIndex - 1); +    if (PreviousContentIndent && Trimmed != StringRef::npos && +        Trimmed != PreviousContentIndent) +      return Split(StringRef::npos, 0); +  } +    return Split(0, Trimmed != StringRef::npos ? Trimmed : 0);  } @@ -583,7 +622,8 @@ void BreakableBlockComment::adaptStartOfLine(        // break length are the same.        size_t BreakLength = Lines[0].substr(1).find_first_not_of(Blanks);        if (BreakLength != StringRef::npos) -        insertBreak(LineIndex, 0, Split(1, BreakLength), Whitespaces); +        insertBreak(LineIndex, 0, Split(1, BreakLength), /*ContentIndent=*/0, +                    Whitespaces);      }      return;    } @@ -754,7 +794,7 @@ unsigned BreakableLineCommentSection::getContentStartColumn(unsigned LineIndex,  void BreakableLineCommentSection::insertBreak(      unsigned LineIndex, unsigned TailOffset, Split Split, -    WhitespaceManager &Whitespaces) const { +    unsigned ContentIndent, WhitespaceManager &Whitespaces) const {    StringRef Text = Content[LineIndex].substr(TailOffset);    // Compute the offset of the split relative to the beginning of the token    // text. diff --git a/clang/lib/Format/BreakableToken.h b/clang/lib/Format/BreakableToken.h index 0fac8f08c02..a2a818f9114 100644 --- a/clang/lib/Format/BreakableToken.h +++ b/clang/lib/Format/BreakableToken.h @@ -21,6 +21,7 @@  #include "Encoding.h"  #include "TokenAnnotator.h"  #include "WhitespaceManager.h" +#include "llvm/ADT/StringSet.h"  #include "llvm/Support/Regex.h"  #include <utility> @@ -135,6 +136,19 @@ public:    virtual unsigned getContentStartColumn(unsigned LineIndex,                                           bool Break) const = 0; +  /// Returns additional content indent required for the second line after the +  /// content at line \p LineIndex is broken. +  /// +  /// For example, Javadoc @param annotations require and indent of 4 spaces and +  /// in this example getContentIndex(1) returns 4. +  /// /** +  ///  * @param loooooooooooooong line +  ///  *     continuation +  ///  */ +  virtual unsigned getContentIndent(unsigned LineIndex) const { +    return 0; +  } +    /// Returns a range (offset, length) at which to break the line at    /// \p LineIndex, if previously broken at \p TailOffset. If possible, do not    /// violate \p ColumnLimit, assuming the text starting at \p TailOffset in @@ -146,6 +160,7 @@ public:    /// Emits the previously retrieved \p Split via \p Whitespaces.    virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, +                           unsigned ContentIndent,                             WhitespaceManager &Whitespaces) const = 0;    /// Returns the number of columns needed to format @@ -210,7 +225,7 @@ public:                                        Split SplitAfterLastLine,                                        WhitespaceManager &Whitespaces) const {      insertBreak(getLineCount() - 1, TailOffset, SplitAfterLastLine, -                Whitespaces); +                /*ContentIndent=*/0, Whitespaces);    }    /// Updates the next token of \p State to the next token after this @@ -245,6 +260,7 @@ public:                   unsigned ContentStartColumn,                   llvm::Regex &CommentPragmasRegex) const override;    void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, +                   unsigned ContentIndent,                     WhitespaceManager &Whitespaces) const override;    void compressWhitespace(unsigned LineIndex, unsigned TailOffset, Split Split,                            WhitespaceManager &Whitespaces) const override {} @@ -354,7 +370,9 @@ public:    unsigned getRemainingLength(unsigned LineIndex, unsigned Offset,                                unsigned StartColumn) const override;    unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override; +  unsigned getContentIndent(unsigned LineIndex) const override;    void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, +                   unsigned ContentIndent,                     WhitespaceManager &Whitespaces) const override;    Split getReflowSplit(unsigned LineIndex,                         llvm::Regex &CommentPragmasRegex) const override; @@ -368,6 +386,10 @@ public:    bool mayReflow(unsigned LineIndex,                   llvm::Regex &CommentPragmasRegex) const override; +  // Contains Javadoc annotations that require additional indent when continued +  // on multiple lines. +  static const llvm::StringSet<> ContentIndentingJavadocAnnotations; +  private:    // Rearranges the whitespace between Lines[LineIndex-1] and Lines[LineIndex].    // @@ -423,6 +445,7 @@ public:                            unsigned StartColumn) const override;    unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override;    void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split, +                   unsigned ContentIndent,                     WhitespaceManager &Whitespaces) const override;    Split getReflowSplit(unsigned LineIndex,                         llvm::Regex &CommentPragmasRegex) const override; diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 90d2a999711..7ca588a675b 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -1809,6 +1809,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,    if (!DryRun)      Token->adaptStartOfLine(0, Whitespaces); +  unsigned ContentIndent = 0;    unsigned Penalty = 0;    LLVM_DEBUG(llvm::dbgs() << "Breaking protruding token at column "                            << StartColumn << ".\n"); @@ -1930,11 +1931,28 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,          }        }        LLVM_DEBUG(llvm::dbgs() << "    Breaking...\n"); -      ContentStartColumn = -          Token->getContentStartColumn(LineIndex, /*Break=*/true); +      // Update the ContentIndent only if the current line was not reflown with +      // the previous line, since in that case the previous line should still +      // determine the ContentIndent. Also never intent the last line. +      if (!Reflow) +        ContentIndent = Token->getContentIndent(LineIndex); +      LLVM_DEBUG(llvm::dbgs() +                 << "    ContentIndent: " << ContentIndent << "\n"); +      ContentStartColumn = ContentIndent + Token->getContentStartColumn( +                                               LineIndex, /*Break=*/true); +        unsigned NewRemainingTokenColumns = Token->getRemainingLength(            LineIndex, TailOffset + Split.first + Split.second,            ContentStartColumn); +      if (NewRemainingTokenColumns == 0) { +        // No content to indent. +        ContentIndent = 0; +        ContentStartColumn = +            Token->getContentStartColumn(LineIndex, /*Break=*/true); +        NewRemainingTokenColumns = Token->getRemainingLength( +            LineIndex, TailOffset + Split.first + Split.second, +            ContentStartColumn); +      }        // When breaking before a tab character, it may be moved by a few columns,        // but will still be expanded to the next tab stop, so we don't save any @@ -1948,7 +1966,8 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,        LLVM_DEBUG(llvm::dbgs() << "    Breaking at: " << TailOffset + Split.first                                << ", " << Split.second << "\n");        if (!DryRun) -        Token->insertBreak(LineIndex, TailOffset, Split, Whitespaces); +        Token->insertBreak(LineIndex, TailOffset, Split, ContentIndent, +                           Whitespaces);        Penalty += NewBreakPenalty;        TailOffset += Split.first + Split.second; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 59d34308c0a..ec96eaa98d0 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -808,10 +808,9 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {      GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;      GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;      GoogleStyle.BreakBeforeTernaryOperators = false; -    // taze:, triple slash directives (`/// <...`), @tag followed by { for a lot -    // of JSDoc tags, and @see, which is commonly followed by overlong URLs. -    GoogleStyle.CommentPragmas = -        "(taze:|^/[ \t]*<|(@[A-Za-z_0-9-]+[ \\t]*{)|@see)"; +    // taze:, triple slash directives (`/// <...`), @see, which is commonly +    // followed by overlong URLs. +    GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|@see)";      GoogleStyle.MaxEmptyLinesToKeep = 3;      GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;      GoogleStyle.SpacesInContainerLiterals = false;  | 

