llvm-project/clang/lib/Format/UnwrappedLineFormatter.h
Manuel Klimek 3d3ea84a4f Refactor clang-format's formatter.
Summary:
a) Pull out a class LevelIndentTracker whose responsibility is to keep track
   of the indent of levels across multiple annotated lines.
b) Put all responsibility for merging lines into the LineJoiner; make the
   LineJoiner iterate over the lines so we never operate on a line that might
   be merged later; this makes the interface safer to use.
c) Move formatting of the end-of-file whitespace into formatFirstToken.

Fix bugs that became obvious after the refactoring:
1. We would not format lines with offsets correctly inside nested blocks if
   only the outer expression was affected:
   int x = s({ // clang-format only this line
     class X {
       public:
    // ^ this starts at the non-modified indnent level; previously we would
    //   not fix this, now we correctly outdent it.
       void f();
     };
   });
2. We would incorrectly align comments across lines that do not have comments
   for lines with nested blocks:
   int expression; // with comment
   int x = s({
     int y; // comment
     int z; // we would incorrectly align this comment with the comment on
            // 'expression'
   });

llvm-svn: 237104
2015-05-12 09:23:57 +00:00

73 lines
2.7 KiB
C++

//===--- UnwrappedLineFormatter.h - Format C++ code -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Implements a combinartorial exploration of all the different
/// linebreaks unwrapped lines can be formatted in.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEFORMATTER_H
#define LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEFORMATTER_H
#include "ContinuationIndenter.h"
#include "clang/Format/Format.h"
#include <map>
#include <queue>
#include <string>
namespace clang {
namespace format {
class ContinuationIndenter;
class WhitespaceManager;
class UnwrappedLineFormatter {
public:
UnwrappedLineFormatter(ContinuationIndenter *Indenter,
WhitespaceManager *Whitespaces,
const FormatStyle &Style,
const AdditionalKeywords &Keywords,
bool *IncompleteFormat)
: Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
Keywords(Keywords), IncompleteFormat(IncompleteFormat) {}
/// \brief Format the current block and return the penalty.
unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines,
bool DryRun = false, int AdditionalIndent = 0,
bool FixBadIndentation = false);
private:
/// \brief Add a new line and the required indent before the first Token
/// of the \c UnwrappedLine if there was no structural parsing error.
void formatFirstToken(FormatToken &RootToken,
const AnnotatedLine *PreviousLine, unsigned IndentLevel,
unsigned Indent, bool InPPDirective);
/// \brief Returns the column limit for a line, taking into account whether we
/// need an escaped newline due to a continued preprocessor directive.
unsigned getColumnLimit(bool InPPDirective, const AnnotatedLine *NextLine) const;
// Cache to store the penalty of formatting a vector of AnnotatedLines
// starting from a specific additional offset. Improves performance if there
// are many nested blocks.
std::map<std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned>,
unsigned> PenaltyCache;
ContinuationIndenter *Indenter;
WhitespaceManager *Whitespaces;
const FormatStyle &Style;
const AdditionalKeywords &Keywords;
bool *IncompleteFormat;
};
} // end namespace format
} // end namespace clang
#endif // LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEFORMATTER_H