/// \brief If \c true, aligns escaped newlines as far left as possible.
/// Otherwise puts them into the right-most column.
bool AlignEscapedNewlinesLeft;
+
+ bool operator==(const FormatStyle &R) const {
+ return AccessModifierOffset == R.AccessModifierOffset &&
+ AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft &&
+ AllowAllParametersOfDeclarationOnNextLine ==
+ R.AllowAllParametersOfDeclarationOnNextLine &&
+ AllowShortIfStatementsOnASingleLine ==
+ R.AllowShortIfStatementsOnASingleLine &&
+ BinPackParameters == R.BinPackParameters &&
+ ColumnLimit == R.ColumnLimit &&
+ ConstructorInitializerAllOnOneLineOrOnePerLine ==
+ R.ConstructorInitializerAllOnOneLineOrOnePerLine &&
+ DerivePointerBinding == R.DerivePointerBinding &&
+ IndentCaseLabels == R.IndentCaseLabels &&
+ MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
+ ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList &&
+ PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
+ PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
+ PointerBindsToType == R.PointerBindsToType &&
+ SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
+ Standard == R.Standard;
+ }
+
};
/// \brief Returns a format style complying with the LLVM coding standards:
template <> struct MappingTraits<clang::format::FormatStyle> {
static void mapping(llvm::yaml::IO &IO, clang::format::FormatStyle &Style) {
- if (!IO.outputting()) {
+ if (IO.outputting()) {
+ StringRef StylesArray[] = { "LLVM", "Google", "Chromium", "Mozilla" };
+ ArrayRef<StringRef> Styles(StylesArray);
+ for (size_t i = 0, e = Styles.size(); i < e; ++i) {
+ StringRef StyleName(Styles[i]);
+ if (Style == clang::format::getPredefinedStyle(StyleName)) {
+ IO.mapOptional("# BasedOnStyle", StyleName);
+ break;
+ }
+ }
+ } else {
StringRef BasedOnStyle;
IO.mapOptional("BasedOnStyle", BasedOnStyle);
-
if (!BasedOnStyle.empty())
Style = clang::format::getPredefinedStyle(BasedOnStyle);
}
private:
void DebugTokenState(const AnnotatedToken &AnnotatedTok) {
const Token &Tok = AnnotatedTok.FormatTok.Tok;
- llvm::errs() << StringRef(SourceMgr.getCharacterData(Tok.getLocation()),
+ llvm::dbgs() << StringRef(SourceMgr.getCharacterData(Tok.getLocation()),
Tok.getLength());
- llvm::errs();
+ llvm::dbgs();
}
struct ParenState {
unsigned Penalty = Queue.top().first.first;
StateNode *Node = Queue.top().second;
if (Node->State.NextToken == NULL) {
- DEBUG(llvm::errs() << "\n---\nPenalty for line: " << Penalty << "\n");
+ DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
break;
}
Queue.pop();
// Reconstruct the solution.
reconstructPath(InitialState, Queue.top().second);
- DEBUG(llvm::errs() << "Total number of analyzed states: " << Count << "\n");
- DEBUG(llvm::errs() << "---\n");
+ DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");
+ DEBUG(llvm::dbgs() << "---\n");
// Return the column after the last token of the solution.
return Queue.top().second->State.Column;
reconstructPath(State, Current->Previous);
DEBUG({
if (Current->NewLine) {
- llvm::errs()
+ llvm::dbgs()
<< "Penalty for splitting before "
<< Current->Previous->State.NextToken->FormatTok.Tok.getName()
<< ": " << Current->Previous->State.NextToken->SplitPenalty << "\n";
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Signals.h"
"Can only be used with one input file."));
static cl::opt<std::string> Style(
"style",
- cl::desc("Coding style, currently supports: LLVM, Google, Chromium, Mozilla."),
+ cl::desc(
+ "Coding style, currently supports: LLVM, Google, Chromium, Mozilla. "
+ "Use '-style file' to load style configuration from .clang-format file "
+ "located in one of the parent directories of the source file (or "
+ "current directory for stdin)."),
cl::init("LLVM"));
static cl::opt<bool> Inplace("i",
cl::desc("Inplace edit <file>s, if specified."));
static cl::opt<bool> OutputXML(
"output-replacements-xml", cl::desc("Output replacements as XML."));
+static cl::opt<bool>
+ DumpConfig("dump-config",
+ cl::desc("Dump configuration options to stdout and exit. Can be used with -style option."));
static cl::list<std::string> FileNames(cl::Positional,
cl::desc("[<file> ...]"));
return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
}
-static FormatStyle getStyle() {
- FormatStyle TheStyle = getGoogleStyle();
- if (Style == "LLVM")
- TheStyle = getLLVMStyle();
- else if (Style == "Chromium")
- TheStyle = getChromiumStyle();
- else if (Style == "Mozilla")
- TheStyle = getMozillaStyle();
- else if (Style != "Google")
- llvm::errs() << "Unknown style " << Style << ", using Google style.\n";
-
- return TheStyle;
+FormatStyle getStyle(StringRef StyleName, StringRef FileName) {
+ if (!StyleName.equals_lower("file"))
+ return getPredefinedStyle(StyleName);
+
+ SmallString<128> Path(FileName);
+ llvm::sys::fs::make_absolute(Path);
+ for (StringRef Directory = llvm::sys::path::parent_path(Path);
+ !Directory.empty();
+ Directory = llvm::sys::path::parent_path(Directory)) {
+ SmallString<128> ConfigFile(Directory);
+ llvm::sys::path::append(ConfigFile, ".clang-format");
+ DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
+ bool IsFile = false;
+ llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);
+ if (IsFile) {
+ OwningPtr<MemoryBuffer> Text;
+ if (error_code ec = MemoryBuffer::getFile(ConfigFile, Text)) {
+ llvm::errs() << ec.message() << "\n";
+ continue;
+ }
+ FormatStyle Style;
+ if (error_code ec = parseConfiguration(Text->getBuffer(), &Style)) {
+ llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message()
+ << "\n";
+ continue;
+ }
+ DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n");
+ return Style;
+ }
+ }
+ llvm::errs() << "Can't find usable .clang-format, using LLVM style\n";
+ return getLLVMStyle();
}
// Returns true on error.
}
Ranges.push_back(CharSourceRange::getCharRange(Start, End));
}
- tooling::Replacements Replaces = reformat(getStyle(), Lex, Sources, Ranges);
+ tooling::Replacements Replaces =
+ reformat(getStyle(Style, FileName), Lex, Sources, Ranges);
if (OutputXML) {
llvm::outs()
<< "<?xml version='1.0'?>\n<replacements xml:space='preserve'>\n";
if (Help)
cl::PrintHelpMessage();
+ if (DumpConfig) {
+ std::string Config = clang::format::configurationAsText(
+ clang::format::getStyle(Style, FileNames.empty() ? "-" : FileNames[0]));
+ llvm::outs() << Config << "\n";
+ return 0;
+ }
+
bool Error = false;
switch (FileNames.size()) {
case 0:
"}");
}
-bool operator==(const FormatStyle &L, const FormatStyle &R) {
- return L.AccessModifierOffset == R.AccessModifierOffset &&
- L.AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft &&
- L.AllowAllParametersOfDeclarationOnNextLine ==
- R.AllowAllParametersOfDeclarationOnNextLine &&
- L.AllowShortIfStatementsOnASingleLine ==
- R.AllowShortIfStatementsOnASingleLine &&
- L.BinPackParameters == R.BinPackParameters &&
- L.ColumnLimit == R.ColumnLimit &&
- L.ConstructorInitializerAllOnOneLineOrOnePerLine ==
- R.ConstructorInitializerAllOnOneLineOrOnePerLine &&
- L.DerivePointerBinding == R.DerivePointerBinding &&
- L.IndentCaseLabels == R.IndentCaseLabels &&
- L.MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
- L.ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList &&
- L.PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
- L.PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
- L.PointerBindsToType == R.PointerBindsToType &&
- L.SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
- L.Standard == R.Standard;
-}
-
bool allStylesEqual(ArrayRef<FormatStyle> Styles) {
for (size_t i = 1; i < Styles.size(); ++i)
if (!(Styles[0] == Styles[i]))