aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Format/BreakableToken.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
commit6a0372513edbc473b538d2f724efac50405d6fef (patch)
tree8f7776b7310bebaf415ac5b69e46e9f928c37144 /lib/Format/BreakableToken.cpp
parent809500fc2c13c8173a16b052304d983864e4a1e1 (diff)
downloadsrc-6a0372513edbc473b538d2f724efac50405d6fef.tar.gz
src-6a0372513edbc473b538d2f724efac50405d6fef.zip
Vendor import of clang tags/RELEASE_33/final r183502 (effectively, 3.3vendor/clang/clang-release_33-r183502
Notes
Notes: svn path=/vendor/clang/dist/; revision=251609 svn path=/vendor/clang/clang-release_33-r183502/; revision=251610; tag=vendor/clang/clang-release_33-r183502
Diffstat (limited to 'lib/Format/BreakableToken.cpp')
-rw-r--r--lib/Format/BreakableToken.cpp179
1 files changed, 179 insertions, 0 deletions
diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp
new file mode 100644
index 000000000000..3e2e0ce7cf3d
--- /dev/null
+++ b/lib/Format/BreakableToken.cpp
@@ -0,0 +1,179 @@
+//===--- BreakableToken.cpp - 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 Contains implementation of BreakableToken class and classes derived
+/// from it.
+///
+//===----------------------------------------------------------------------===//
+
+#include "BreakableToken.h"
+#include "llvm/ADT/STLExtras.h"
+#include <algorithm>
+
+namespace clang {
+namespace format {
+
+BreakableToken::Split BreakableComment::getSplit(unsigned LineIndex,
+ unsigned TailOffset,
+ unsigned ColumnLimit) const {
+ StringRef Text = getLine(LineIndex).substr(TailOffset);
+ unsigned ContentStartColumn = getContentStartColumn(LineIndex, TailOffset);
+ if (ColumnLimit <= ContentStartColumn + 1)
+ return Split(StringRef::npos, 0);
+
+ unsigned MaxSplit = ColumnLimit - ContentStartColumn + 1;
+ StringRef::size_type SpaceOffset = Text.rfind(' ', MaxSplit);
+ if (SpaceOffset == StringRef::npos ||
+ Text.find_last_not_of(' ', SpaceOffset) == StringRef::npos) {
+ SpaceOffset = Text.find(' ', MaxSplit);
+ }
+ if (SpaceOffset != StringRef::npos && SpaceOffset != 0) {
+ StringRef BeforeCut = Text.substr(0, SpaceOffset).rtrim();
+ StringRef AfterCut = Text.substr(SpaceOffset).ltrim();
+ return BreakableToken::Split(BeforeCut.size(),
+ AfterCut.begin() - BeforeCut.end());
+ }
+ return BreakableToken::Split(StringRef::npos, 0);
+}
+
+void BreakableComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
+ Split Split, bool InPPDirective,
+ WhitespaceManager &Whitespaces) {
+ StringRef Text = getLine(LineIndex).substr(TailOffset);
+ StringRef AdditionalPrefix = Decoration;
+ if (Text.size() == Split.first + Split.second) {
+ // For all but the last line handle trailing space in trimLine.
+ if (LineIndex < Lines.size() - 1)
+ return;
+ // For the last line we need to break before "*/", but not to add "* ".
+ AdditionalPrefix = "";
+ }
+
+ unsigned WhitespaceStartColumn =
+ getContentStartColumn(LineIndex, TailOffset) + Split.first;
+ unsigned BreakOffset = Text.data() - TokenText.data() + Split.first;
+ unsigned CharsToRemove = Split.second;
+ Whitespaces.breakToken(Tok, BreakOffset, CharsToRemove, "", AdditionalPrefix,
+ InPPDirective, IndentAtLineBreak,
+ WhitespaceStartColumn);
+}
+
+BreakableBlockComment::BreakableBlockComment(const SourceManager &SourceMgr,
+ const AnnotatedToken &Token,
+ unsigned StartColumn)
+ : BreakableComment(SourceMgr, Token.FormatTok, StartColumn + 2) {
+ assert(TokenText.startswith("/*") && TokenText.endswith("*/"));
+
+ OriginalStartColumn =
+ SourceMgr.getSpellingColumnNumber(Tok.getStartOfNonWhitespace()) - 1;
+
+ TokenText.substr(2, TokenText.size() - 4).split(Lines, "\n");
+
+ bool NeedsStar = true;
+ CommonPrefixLength = UINT_MAX;
+ if (Lines.size() == 1) {
+ if (Token.Parent == 0) {
+ // Standalone block comments will be aligned and prefixed with *s.
+ CommonPrefixLength = OriginalStartColumn + 1;
+ } else {
+ // Trailing comments can start on arbitrary column, and available
+ // horizontal space can be too small to align consecutive lines with
+ // the first one. We could, probably, align them to current
+ // indentation level, but now we just wrap them without indentation
+ // and stars.
+ CommonPrefixLength = 0;
+ NeedsStar = false;
+ }
+ } else {
+ for (size_t i = 1; i < Lines.size(); ++i) {
+ size_t FirstNonWhitespace = Lines[i].find_first_not_of(" ");
+ if (FirstNonWhitespace != StringRef::npos) {
+ NeedsStar = NeedsStar && (Lines[i][FirstNonWhitespace] == '*');
+ CommonPrefixLength =
+ std::min<unsigned>(CommonPrefixLength, FirstNonWhitespace);
+ }
+ }
+ }
+ if (CommonPrefixLength == UINT_MAX)
+ CommonPrefixLength = 0;
+
+ Decoration = NeedsStar ? "* " : "";
+
+ IndentAtLineBreak =
+ std::max<int>(StartColumn - OriginalStartColumn + CommonPrefixLength, 0);
+}
+
+void BreakableBlockComment::alignLines(WhitespaceManager &Whitespaces) {
+ SourceLocation TokenLoc = Tok.getStartOfNonWhitespace();
+ int IndentDelta = (StartColumn - 2) - OriginalStartColumn;
+ if (IndentDelta > 0) {
+ std::string WhiteSpace(IndentDelta, ' ');
+ for (size_t i = 1; i < Lines.size(); ++i) {
+ Whitespaces.addReplacement(
+ TokenLoc.getLocWithOffset(Lines[i].data() - TokenText.data()), 0,
+ WhiteSpace);
+ }
+ } else if (IndentDelta < 0) {
+ std::string WhiteSpace(-IndentDelta, ' ');
+ // Check that the line is indented enough.
+ for (size_t i = 1; i < Lines.size(); ++i) {
+ if (!Lines[i].startswith(WhiteSpace))
+ return;
+ }
+ for (size_t i = 1; i < Lines.size(); ++i) {
+ Whitespaces.addReplacement(
+ TokenLoc.getLocWithOffset(Lines[i].data() - TokenText.data()),
+ -IndentDelta, "");
+ }
+ }
+
+ for (unsigned i = 1; i < Lines.size(); ++i)
+ Lines[i] = Lines[i].substr(CommonPrefixLength + Decoration.size());
+}
+
+void BreakableBlockComment::trimLine(unsigned LineIndex, unsigned TailOffset,
+ unsigned InPPDirective,
+ WhitespaceManager &Whitespaces) {
+ if (LineIndex == Lines.size() - 1)
+ return;
+ StringRef Text = Lines[LineIndex].substr(TailOffset);
+ if (!Text.endswith(" ") && !InPPDirective)
+ return;
+
+ StringRef TrimmedLine = Text.rtrim();
+ unsigned WhitespaceStartColumn =
+ getLineLengthAfterSplit(LineIndex, TailOffset);
+ unsigned BreakOffset = TrimmedLine.end() - TokenText.data();
+ unsigned CharsToRemove = Text.size() - TrimmedLine.size() + 1;
+ Whitespaces.breakToken(Tok, BreakOffset, CharsToRemove, "", "", InPPDirective,
+ 0, WhitespaceStartColumn);
+}
+
+BreakableLineComment::BreakableLineComment(const SourceManager &SourceMgr,
+ const AnnotatedToken &Token,
+ unsigned StartColumn)
+ : BreakableComment(SourceMgr, Token.FormatTok, StartColumn) {
+ assert(TokenText.startswith("//"));
+ Decoration = getLineCommentPrefix(TokenText);
+ Lines.push_back(TokenText.substr(Decoration.size()));
+ IndentAtLineBreak = StartColumn;
+ this->StartColumn += Decoration.size(); // Start column of the contents.
+}
+
+StringRef BreakableLineComment::getLineCommentPrefix(StringRef Comment) {
+ const char *KnownPrefixes[] = { "/// ", "///", "// ", "//" };
+ for (size_t i = 0; i < llvm::array_lengthof(KnownPrefixes); ++i)
+ if (Comment.startswith(KnownPrefixes[i]))
+ return KnownPrefixes[i];
+ return "";
+}
+
+} // namespace format
+} // namespace clang