Author: alexfh Date: Fri May 10 06:56:10 2013 New Revision: 181589 URL: http://llvm.org/viewvc/llvm-project?rev=181589&view=rev Log: Config file support for clang-format, part 2.
Summary: Adds actual config file reading to the clang-format utility. Configuration file name is .clang-format. It is looked up for each input file in its parent directories starting from immediate one. First found .clang-format file is used. When using standard input, .clang-format is searched starting from the current directory. Added -dump-config option to easily create configuration files. Reviewers: djasper, klimek Reviewed By: klimek CC: cfe-commits, jordan_rose, kimgr Differential Revision: http://llvm-reviews.chandlerc.com/D758 Modified: cfe/trunk/include/clang/Format/Format.h cfe/trunk/lib/Format/Format.cpp cfe/trunk/tools/clang-format/ClangFormat.cpp cfe/trunk/unittests/Format/FormatTest.cpp Modified: cfe/trunk/include/clang/Format/Format.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=181589&r1=181588&r2=181589&view=diff ============================================================================== --- cfe/trunk/include/clang/Format/Format.h (original) +++ cfe/trunk/include/clang/Format/Format.h Fri May 10 06:56:10 2013 @@ -93,6 +93,29 @@ struct FormatStyle { /// \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: Modified: cfe/trunk/lib/Format/Format.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=181589&r1=181588&r2=181589&view=diff ============================================================================== --- cfe/trunk/lib/Format/Format.cpp (original) +++ cfe/trunk/lib/Format/Format.cpp Fri May 10 06:56:10 2013 @@ -46,10 +46,19 @@ struct ScalarEnumerationTraits<clang::fo 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); } @@ -245,9 +254,9 @@ public: 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 { @@ -825,7 +834,7 @@ private: 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(); @@ -845,8 +854,8 @@ private: // 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; @@ -862,7 +871,7 @@ private: 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"; Modified: cfe/trunk/tools/clang-format/ClangFormat.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-format/ClangFormat.cpp?rev=181589&r1=181588&r2=181589&view=diff ============================================================================== --- cfe/trunk/tools/clang-format/ClangFormat.cpp (original) +++ cfe/trunk/tools/clang-format/ClangFormat.cpp Fri May 10 06:56:10 2013 @@ -20,6 +20,7 @@ #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" @@ -36,13 +37,20 @@ Lengths("length", cl::desc("Format a ran "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> ...]")); @@ -59,18 +67,38 @@ static FileID createInMemoryFile(StringR 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. @@ -118,7 +146,8 @@ static bool format(std::string FileName) } 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"; @@ -171,6 +200,13 @@ int main(int argc, const char **argv) { 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: Modified: cfe/trunk/unittests/Format/FormatTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=181589&r1=181588&r2=181589&view=diff ============================================================================== --- cfe/trunk/unittests/Format/FormatTest.cpp (original) +++ cfe/trunk/unittests/Format/FormatTest.cpp Fri May 10 06:56:10 2013 @@ -3933,28 +3933,6 @@ TEST_F(FormatTest, DoNotCreateUnreasonab "}"); } -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])) _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
