From: Alexander Kornienko Date: Sun, 19 May 2013 00:53:30 +0000 (+0000) Subject: Clang-format: allow -style="{yaml/json}" on command line X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=885f87b4be987fd8912779419ec88e3c37481967;p=clang Clang-format: allow -style="{yaml/json}" on command line Summary: + improved handling of default style and predefined styles. Reviewers: djasper, klimek Reviewed By: klimek CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D813 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182205 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/ClangFormat.rst b/docs/ClangFormat.rst index a9687bc9e4..8df7d24c9b 100644 --- a/docs/ClangFormat.rst +++ b/docs/ClangFormat.rst @@ -20,8 +20,8 @@ to format C/C++/Obj-C code. If no arguments are specified, it formats the code from standard input and writes the result to the standard output. - If s are given, it reformats the files. If -i is specified - together with s, the files are edited in-place. Otherwise, the + If s are given, it reformats the files. If -i is specified + together with s, the files are edited in-place. Otherwise, the result is written to the standard output. USAGE: clang-format [options] [ ...] @@ -47,10 +47,13 @@ to format C/C++/Obj-C code. -output-replacements-xml - Output replacements as XML. -style= - Coding style, currently supports: LLVM, Google, Chromium, Mozilla. - Use '-style file' to load style configuration from + 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). + Use -style="{key: value, ...}" to set specific + parameters, e.g.: + -style="{BasedOnStyle: llvm, IndentWidth: 8}" General options: diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 021073b6c6..1bc1996d20 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -161,11 +161,13 @@ FormatStyle getChromiumStyle(); /// https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style. FormatStyle getMozillaStyle(); -/// \brief Returns a predefined style by name. +/// \brief Gets a predefined style by name. /// /// Currently supported names: LLVM, Google, Chromium, Mozilla. Names are /// compared case-insensitively. -FormatStyle getPredefinedStyle(StringRef Name); +/// +/// Returns true if the Style has been set. +bool getPredefinedStyle(StringRef Name, FormatStyle *Style); /// \brief Parse configuration from YAML-formatted text. llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style); diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 3dd0002abb..64a988df31 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -60,7 +60,9 @@ template <> struct MappingTraits { ArrayRef Styles(StylesArray); for (size_t i = 0, e = Styles.size(); i < e; ++i) { StringRef StyleName(Styles[i]); - if (Style == clang::format::getPredefinedStyle(StyleName)) { + clang::format::FormatStyle PredefinedStyle; + if (clang::format::getPredefinedStyle(StyleName, &PredefinedStyle) && + Style == PredefinedStyle) { IO.mapOptional("# BasedOnStyle", StyleName); break; } @@ -69,7 +71,10 @@ template <> struct MappingTraits { StringRef BasedOnStyle; IO.mapOptional("BasedOnStyle", BasedOnStyle); if (!BasedOnStyle.empty()) - Style = clang::format::getPredefinedStyle(BasedOnStyle); + if (!clang::format::getPredefinedStyle(BasedOnStyle, &Style)) { + IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle)); + return; + } } IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset); @@ -180,18 +185,19 @@ FormatStyle getMozillaStyle() { return MozillaStyle; } -FormatStyle getPredefinedStyle(StringRef Name) { +bool getPredefinedStyle(StringRef Name, FormatStyle *Style) { if (Name.equals_lower("llvm")) - return getLLVMStyle(); - if (Name.equals_lower("chromium")) - return getChromiumStyle(); - if (Name.equals_lower("mozilla")) - return getMozillaStyle(); - if (Name.equals_lower("google")) - return getGoogleStyle(); - - llvm::errs() << "Unknown style " << Name << ", using Google style.\n"; - return getGoogleStyle(); + *Style = getLLVMStyle(); + else if (Name.equals_lower("chromium")) + *Style = getChromiumStyle(); + else if (Name.equals_lower("mozilla")) + *Style = getMozillaStyle(); + else if (Name.equals_lower("google")) + *Style = getGoogleStyle(); + else + return false; + + return true; } llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style) { diff --git a/test/Format/style-on-command-line.cpp b/test/Format/style-on-command-line.cpp new file mode 100644 index 0000000000..679236f7a4 --- /dev/null +++ b/test/Format/style-on-command-line.cpp @@ -0,0 +1,23 @@ +// RUN: grep -Ev "// *[A-Z0-9]+:" %s > %t.cpp +// RUN: clang-format -style="{BasedOnStyle: Google, IndentWidth: 8}" %t.cpp | FileCheck -strict-whitespace -check-prefix=CHECK1 %s +// RUN: clang-format -style="{BasedOnStyle: LLVM, IndentWidth: 7}" %t.cpp | FileCheck -strict-whitespace -check-prefix=CHECK2 %s +// RUN: clang-format -style="{BasedOnStyle: invalid, IndentWidth: 7}" %t.cpp 2>&1 | FileCheck -strict-whitespace -check-prefix=CHECK3 %s +// RUN: clang-format -style="{lsjd}" %t.cpp 2>&1 | FileCheck -strict-whitespace -check-prefix=CHECK4 %s +// RUN: [ ! -e %T/.clang-format ] || rm %T/.clang-format +// RUN: clang-format -style=file %t.cpp 2>&1 | FileCheck -strict-whitespace -check-prefix=CHECK5 %s +// RUN: echo -e "BasedOnStyle: google\nIndentWidth: 5" > %T/.clang-format +// RUN: clang-format -style=file %t.cpp 2>&1 | FileCheck -strict-whitespace -check-prefix=CHECK6 %s +void f() { +// CHECK1: {{^ int\* i;$}} +// CHECK2: {{^ int \*i;$}} +// CHECK3: Unknown value for BasedOnStyle: invalid +// CHECK3: Error parsing -style: Invalid argument, using LLVM style +// CHECK3: {{^ int \*i;$}} +// CHECK4: Error parsing -style: Invalid argument, using LLVM style +// CHECK4: {{^ int \*i;$}} +// CHECK5: Can't find usable .clang-format, using LLVM style +// CHECK5: {{^ int \*i;$}} +// CHECK6: {{^ int\* i;$}} +int*i; +int j; +} diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp index f779348f0f..fccd6bf257 100644 --- a/tools/clang-format/ClangFormat.cpp +++ b/tools/clang-format/ClangFormat.cpp @@ -27,6 +27,9 @@ using namespace llvm; +// Default style to use when no style specified or specified style not found. +static const char *DefaultStyle = "LLVM"; + static cl::opt Help("h", cl::desc("Alias for -help"), cl::Hidden); // Mark all our options with this category, everything else (except for -version @@ -54,11 +57,14 @@ static cl::opt Style("style", cl::desc("Coding style, currently supports:\n" " LLVM, Google, Chromium, Mozilla.\n" - "Use '-style file' to load style configuration from\n" + "Use -style=file to load style configuration from\n" ".clang-format file located in one of the parent\n" "directories of the source file (or current\n" - "directory for stdin)."), - cl::init("LLVM"), cl::cat(ClangFormatCategory)); + "directory for stdin).\n" + "Use -style=\"{key: value, ...}\" to set specific\n" + "parameters, e.g.:\n" + " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""), + cl::init(DefaultStyle), cl::cat(ClangFormatCategory)); static cl::opt Inplace("i", cl::desc("Inplace edit s, if specified."), cl::cat(ClangFormatCategory)); @@ -88,8 +94,24 @@ static FileID createInMemoryFile(StringRef FileName, const MemoryBuffer *Source, } FormatStyle getStyle(StringRef StyleName, StringRef FileName) { - if (!StyleName.equals_lower("file")) - return getPredefinedStyle(StyleName); + FormatStyle Style; + getPredefinedStyle(DefaultStyle, &Style); + + if (StyleName.startswith("{")) { + // Parse YAML/JSON style from the command line. + if (error_code ec = parseConfiguration(StyleName, &Style)) { + llvm::errs() << "Error parsing -style: " << ec.message() + << ", using " << DefaultStyle << " style\n"; + } + return Style; + } + + if (!StyleName.equals_lower("file")) { + if (!getPredefinedStyle(StyleName, &Style)) + llvm::errs() << "Invalid value for -style, using " << DefaultStyle + << " style\n"; + return Style; + } SmallString<128> Path(FileName); llvm::sys::fs::make_absolute(Path); @@ -109,7 +131,6 @@ FormatStyle getStyle(StringRef StyleName, StringRef FileName) { llvm::errs() << ec.message() << "\n"; continue; } - FormatStyle Style; if (error_code ec = parseConfiguration(Text->getBuffer(), &Style)) { llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message() << "\n"; @@ -119,8 +140,9 @@ FormatStyle getStyle(StringRef StyleName, StringRef FileName) { return Style; } } - llvm::errs() << "Can't find usable .clang-format, using LLVM style\n"; - return getLLVMStyle(); + llvm::errs() << "Can't find usable .clang-format, using " << DefaultStyle + << " style\n"; + return Style; } // Returns true on error. diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index e143603f28..e0ef3d192d 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -4209,27 +4209,29 @@ bool allStylesEqual(ArrayRef Styles) { } TEST_F(FormatTest, GetsPredefinedStyleByName) { - FormatStyle LLVMStyles[] = { getLLVMStyle(), getPredefinedStyle("LLVM"), - getPredefinedStyle("llvm"), - getPredefinedStyle("lLvM") }; - EXPECT_TRUE(allStylesEqual(LLVMStyles)); + FormatStyle Styles[3]; - FormatStyle GoogleStyles[] = { getGoogleStyle(), getPredefinedStyle("Google"), - getPredefinedStyle("google"), - getPredefinedStyle("gOOgle") }; - EXPECT_TRUE(allStylesEqual(GoogleStyles)); + Styles[0] = getLLVMStyle(); + EXPECT_TRUE(getPredefinedStyle("LLVM", &Styles[1])); + EXPECT_TRUE(getPredefinedStyle("lLvM", &Styles[2])); + EXPECT_TRUE(allStylesEqual(Styles)); - FormatStyle ChromiumStyles[] = { getChromiumStyle(), - getPredefinedStyle("Chromium"), - getPredefinedStyle("chromium"), - getPredefinedStyle("chROmiUM") }; - EXPECT_TRUE(allStylesEqual(ChromiumStyles)); + Styles[0] = getGoogleStyle(); + EXPECT_TRUE(getPredefinedStyle("Google", &Styles[1])); + EXPECT_TRUE(getPredefinedStyle("gOOgle", &Styles[2])); + EXPECT_TRUE(allStylesEqual(Styles)); - FormatStyle MozillaStyles[] = { getMozillaStyle(), - getPredefinedStyle("Mozilla"), - getPredefinedStyle("mozilla"), - getPredefinedStyle("moZilla") }; - EXPECT_TRUE(allStylesEqual(MozillaStyles)); + Styles[0] = getChromiumStyle(); + EXPECT_TRUE(getPredefinedStyle("Chromium", &Styles[1])); + EXPECT_TRUE(getPredefinedStyle("cHRoMiUM", &Styles[2])); + EXPECT_TRUE(allStylesEqual(Styles)); + + Styles[0] = getMozillaStyle(); + EXPECT_TRUE(getPredefinedStyle("Mozilla", &Styles[1])); + EXPECT_TRUE(getPredefinedStyle("moZILla", &Styles[2])); + EXPECT_TRUE(allStylesEqual(Styles)); + + EXPECT_FALSE(getPredefinedStyle("qwerty", &Styles[0])); } TEST_F(FormatTest, ParsesConfiguration) { @@ -4242,7 +4244,7 @@ TEST_F(FormatTest, ParsesConfiguration) { #define CHECK_PARSE_BOOL(FIELD) \ Style.FIELD = false; \ EXPECT_EQ(0, parseConfiguration(#FIELD ": true", &Style).value()); \ - EXPECT_TRUE(Style.FIELD); \ + EXPECT_TRUE(Style.FIELD); \ EXPECT_EQ(0, parseConfiguration(#FIELD ": false", &Style).value()); \ EXPECT_FALSE(Style.FIELD);