From ea266cad53e3d49771fa38103913d3ec7a166694 Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Mon, 10 Jun 2013 20:45:12 +0000
Subject: Vendor import of clang tags/RELEASE_33/final r183502 (effectively,
 3.3 release):
 http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_33/final@183502

---
 lib/Format/BreakableToken.h | 240 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 240 insertions(+)
 create mode 100644 lib/Format/BreakableToken.h

(limited to 'lib/Format/BreakableToken.h')

diff --git a/lib/Format/BreakableToken.h b/lib/Format/BreakableToken.h
new file mode 100644
index 0000000..c130318
--- /dev/null
+++ b/lib/Format/BreakableToken.h
@@ -0,0 +1,240 @@
+//===--- BreakableToken.h - Format C++ code -------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Declares BreakableToken, BreakableStringLiteral, and
+/// BreakableBlockComment classes, that contain token type-specific logic to
+/// break long lines in tokens.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FORMAT_BREAKABLETOKEN_H
+#define LLVM_CLANG_FORMAT_BREAKABLETOKEN_H
+
+#include "TokenAnnotator.h"
+#include "WhitespaceManager.h"
+#include <utility>
+
+namespace clang {
+namespace format {
+
+class BreakableToken {
+public:
+  BreakableToken(const SourceManager &SourceMgr, const FormatToken &Tok,
+                 unsigned StartColumn)
+      : Tok(Tok), StartColumn(StartColumn),
+        TokenText(SourceMgr.getCharacterData(Tok.getStartOfNonWhitespace()),
+                  Tok.TokenLength) {}
+  virtual ~BreakableToken() {}
+  virtual unsigned getLineCount() const = 0;
+  virtual unsigned getLineSize(unsigned Index) const = 0;
+  virtual unsigned getLineLengthAfterSplit(unsigned LineIndex,
+                                           unsigned TailOffset) const = 0;
+
+  // Contains starting character index and length of split.
+  typedef std::pair<StringRef::size_type, unsigned> Split;
+  virtual Split getSplit(unsigned LineIndex, unsigned TailOffset,
+                         unsigned ColumnLimit) const = 0;
+  virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+                           bool InPPDirective,
+                           WhitespaceManager &Whitespaces) = 0;
+  virtual void trimLine(unsigned LineIndex, unsigned TailOffset,
+                        unsigned InPPDirective,
+                        WhitespaceManager &Whitespaces) {}
+protected:
+  const FormatToken &Tok;
+  unsigned StartColumn;
+  StringRef TokenText;
+};
+
+class BreakableStringLiteral : public BreakableToken {
+public:
+  BreakableStringLiteral(const SourceManager &SourceMgr, const FormatToken &Tok,
+                         unsigned StartColumn)
+      : BreakableToken(SourceMgr, Tok, StartColumn) {
+    assert(TokenText.startswith("\"") && TokenText.endswith("\""));
+  }
+
+  virtual unsigned getLineCount() const { return 1; }
+
+  virtual unsigned getLineSize(unsigned Index) const {
+    return Tok.TokenLength - 2; // Should be in sync with getLine
+  }
+
+  virtual unsigned getLineLengthAfterSplit(unsigned LineIndex,
+                                           unsigned TailOffset) const {
+    return getDecorationLength() + getLine().size() - TailOffset;
+  }
+
+  virtual Split getSplit(unsigned LineIndex, unsigned TailOffset,
+                         unsigned ColumnLimit) const {
+    StringRef Text = getLine().substr(TailOffset);
+    if (ColumnLimit <= getDecorationLength())
+      return Split(StringRef::npos, 0);
+    unsigned MaxSplit = ColumnLimit - getDecorationLength();
+    assert(MaxSplit < Text.size());
+    StringRef::size_type SpaceOffset = Text.rfind(' ', MaxSplit);
+    if (SpaceOffset != StringRef::npos && SpaceOffset != 0)
+      return Split(SpaceOffset + 1, 0);
+    StringRef::size_type SlashOffset = Text.rfind('/', MaxSplit);
+    if (SlashOffset != StringRef::npos && SlashOffset != 0)
+      return Split(SlashOffset + 1, 0);
+    StringRef::size_type SplitPoint = getStartOfCharacter(Text, MaxSplit);
+    if (SplitPoint != StringRef::npos && SplitPoint > 1)
+      // Do not split at 0.
+      return Split(SplitPoint, 0);
+    return Split(StringRef::npos, 0);
+  }
+
+  virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+                           bool InPPDirective, WhitespaceManager &Whitespaces) {
+    unsigned WhitespaceStartColumn = StartColumn + Split.first + 2;
+    Whitespaces.breakToken(Tok, 1 + TailOffset + Split.first, Split.second,
+                           "\"", "\"", InPPDirective, StartColumn,
+                           WhitespaceStartColumn);
+  }
+
+private:
+  StringRef getLine() const {
+    // Get string without quotes.
+    // FIXME: Handle string prefixes.
+    return TokenText.substr(1, TokenText.size() - 2);
+  }
+
+  unsigned getDecorationLength() const { return StartColumn + 2; }
+
+  static StringRef::size_type getStartOfCharacter(StringRef Text,
+                                                  StringRef::size_type Offset) {
+    StringRef::size_type NextEscape = Text.find('\\');
+    while (NextEscape != StringRef::npos && NextEscape < Offset) {
+      StringRef::size_type SequenceLength =
+          getEscapeSequenceLength(Text.substr(NextEscape));
+      if (Offset < NextEscape + SequenceLength)
+        return NextEscape;
+      NextEscape = Text.find('\\', NextEscape + SequenceLength);
+    }
+    return Offset;
+  }
+
+  static unsigned getEscapeSequenceLength(StringRef Text) {
+    assert(Text[0] == '\\');
+    if (Text.size() < 2)
+      return 1;
+
+    switch (Text[1]) {
+    case 'u':
+      return 6;
+    case 'U':
+      return 10;
+    case 'x':
+      return getHexLength(Text);
+    default:
+      if (Text[1] >= '0' && Text[1] <= '7')
+        return getOctalLength(Text);
+      return 2;
+    }
+  }
+
+  static unsigned getHexLength(StringRef Text) {
+    unsigned I = 2; // Point after '\x'.
+    while (I < Text.size() && ((Text[I] >= '0' && Text[I] <= '9') ||
+                               (Text[I] >= 'a' && Text[I] <= 'f') ||
+                               (Text[I] >= 'A' && Text[I] <= 'F'))) {
+      ++I;
+    }
+    return I;
+  }
+
+  static unsigned getOctalLength(StringRef Text) {
+    unsigned I = 1;
+    while (I < Text.size() && I < 4 && (Text[I] >= '0' && Text[I] <= '7')) {
+      ++I;
+    }
+    return I;
+  }
+
+};
+
+class BreakableComment : public BreakableToken {
+public:
+  virtual unsigned getLineSize(unsigned Index) const {
+    return getLine(Index).size();
+  }
+
+  virtual unsigned getLineCount() const { return Lines.size(); }
+
+  virtual unsigned getLineLengthAfterSplit(unsigned LineIndex,
+                                           unsigned TailOffset) const {
+    return getContentStartColumn(LineIndex, TailOffset) +
+           getLine(LineIndex).size() - TailOffset;
+  }
+
+  virtual Split getSplit(unsigned LineIndex, unsigned TailOffset,
+                         unsigned ColumnLimit) const;
+  virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+                           bool InPPDirective, WhitespaceManager &Whitespaces);
+
+protected:
+  BreakableComment(const SourceManager &SourceMgr, const FormatToken &Tok,
+                   unsigned StartColumn)
+      : BreakableToken(SourceMgr, Tok, StartColumn) {}
+
+  // Get comment lines without /* */, common prefix and trailing whitespace.
+  // Last line is not trimmed, as it is terminated by */, so its trailing
+  // whitespace is not really trailing.
+  StringRef getLine(unsigned Index) const {
+    return Index < Lines.size() - 1 ? Lines[Index].rtrim() : Lines[Index];
+  }
+
+  unsigned getContentStartColumn(unsigned LineIndex,
+                                 unsigned TailOffset) const {
+    return (TailOffset == 0 && LineIndex == 0)
+               ? StartColumn
+               : IndentAtLineBreak + Decoration.size();
+  }
+
+  unsigned IndentAtLineBreak;
+  StringRef Decoration;
+  SmallVector<StringRef, 16> Lines;
+};
+
+class BreakableBlockComment : public BreakableComment {
+public:
+  BreakableBlockComment(const SourceManager &SourceMgr,
+                        const AnnotatedToken &Token, unsigned StartColumn);
+
+  void alignLines(WhitespaceManager &Whitespaces);
+
+  virtual unsigned getLineLengthAfterSplit(unsigned LineIndex,
+                                           unsigned TailOffset) const {
+    return BreakableComment::getLineLengthAfterSplit(LineIndex, TailOffset) +
+           (LineIndex + 1 < Lines.size() ? 0 : 2);
+  }
+
+  virtual void trimLine(unsigned LineIndex, unsigned TailOffset,
+                        unsigned InPPDirective, WhitespaceManager &Whitespaces);
+
+private:
+  unsigned OriginalStartColumn;
+  unsigned CommonPrefixLength;
+};
+
+class BreakableLineComment : public BreakableComment {
+public:
+  BreakableLineComment(const SourceManager &SourceMgr,
+                       const AnnotatedToken &Token, unsigned StartColumn);
+
+private:
+  static StringRef getLineCommentPrefix(StringRef Comment);
+};
+
+} // namespace format
+} // namespace clang
+
+#endif // LLVM_CLANG_FORMAT_BREAKABLETOKEN_H
-- 
cgit v1.1