<div dir="ltr">unittests/Format/FormatTest.cpp is pretty large by now. Should js-specific tests maybe go into a new file?<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Nov 30, 2013 at 12:19 AM, Alexander Kornienko <span dir="ltr"><<a href="mailto:alexfh@google.com" target="_blank">alexfh@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: alexfh<br>
Date: Fri Nov 29 09:19:43 2013<br>
New Revision: 195961<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=195961&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=195961&view=rev</a><br>
Log:<br>
Added LanguageStandard::LS_JavaScript to gate all JS-specific parsing.<br>
<br>
Summary:<br>
Use LS_JavaScript for files ending with ".js". Added support for ">>>="<br>
operator.<br>
<br>
Reviewers: djasper, klimek<br>
<br>
Reviewed By: djasper<br>
<br>
CC: cfe-commits, klimek<br>
<br>
Differential Revision: <a href="http://llvm-reviews.chandlerc.com/D2242" target="_blank">http://llvm-reviews.chandlerc.com/D2242</a><br>
<br>
Added:<br>
cfe/trunk/test/Format/language-detection.cpp<br>
Modified:<br>
cfe/trunk/include/clang/Format/Format.h<br>
cfe/trunk/lib/Format/Format.cpp<br>
cfe/trunk/unittests/Format/FormatTest.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Format/Format.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=195961&r1=195960&r2=195961&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=195961&r1=195960&r2=195961&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Format/Format.h (original)<br>
+++ cfe/trunk/include/clang/Format/Format.h Fri Nov 29 09:19:43 2013<br>
@@ -30,6 +30,21 @@ namespace format {<br>
/// \brief The \c FormatStyle is used to configure the formatting to follow<br>
/// specific guidelines.<br>
struct FormatStyle {<br>
+ /// \brief Supported languages. When stored in a configuration file, specifies<br>
+ /// the language, that the configuration targets. When passed to the<br>
+ /// reformat() function, enables syntax features specific to the language.<br>
+ enum LanguageKind {<br>
+ /// Do not use.<br>
+ LK_None,<br>
+ /// Should be used for C, C++, ObjectiveC, ObjectiveC++.<br>
+ LK_Cpp,<br>
+ /// Should be used for JavaScript.<br>
+ LK_JavaScript<br>
+ };<br>
+<br>
+ /// \brief Language, this format style is targeted at.<br>
+ LanguageKind Language;<br>
+<br>
/// \brief The column limit.<br>
///<br>
/// A column limit of \c 0 means that there is no column limit. In this case,<br>
@@ -283,7 +298,7 @@ struct FormatStyle {<br>
IndentCaseLabels == R.IndentCaseLabels &&<br>
IndentFunctionDeclarationAfterType ==<br>
R.IndentFunctionDeclarationAfterType &&<br>
- IndentWidth == R.IndentWidth &&<br>
+ IndentWidth == R.IndentWidth && Language == R.Language &&<br>
MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&<br>
NamespaceIndentation == R.NamespaceIndentation &&<br>
ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList &&<br>
<br>
Modified: cfe/trunk/lib/Format/Format.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=195961&r1=195960&r2=195961&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=195961&r1=195960&r2=195961&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Format/Format.cpp (original)<br>
+++ cfe/trunk/lib/Format/Format.cpp Fri Nov 29 09:19:43 2013<br>
@@ -34,6 +34,15 @@<br>
namespace llvm {<br>
namespace yaml {<br>
template <><br>
+struct ScalarEnumerationTraits<clang::format::FormatStyle::LanguageKind> {<br>
+ static void enumeration(IO &IO,<br>
+ clang::format::FormatStyle::LanguageKind &Value) {<br>
+ IO.enumCase(Value, "Cpp", clang::format::FormatStyle::LK_Cpp);<br>
+ IO.enumCase(Value, "JavaScript", clang::format::FormatStyle::LK_JavaScript);<br>
+ }<br>
+};<br>
+<br>
+template <><br>
struct ScalarEnumerationTraits<clang::format::FormatStyle::LanguageStandard> {<br>
static void enumeration(IO &IO,<br>
clang::format::FormatStyle::LanguageStandard &Value) {<br>
@@ -99,13 +108,17 @@ template <> struct MappingTraits<clang::<br>
} else {<br>
StringRef BasedOnStyle;<br>
IO.mapOptional("BasedOnStyle", BasedOnStyle);<br>
- if (!BasedOnStyle.empty())<br>
+ if (!BasedOnStyle.empty()) {<br>
+ clang::format::FormatStyle::LanguageKind Language = Style.Language;<br>
if (!clang::format::getPredefinedStyle(BasedOnStyle, &Style)) {<br>
IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));<br>
return;<br>
}<br>
+ Style.Language = Language;<br>
+ }<br>
}<br>
<br>
+ IO.mapOptional("Language", Style.Language);<br>
IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);<br>
IO.mapOptional("ConstructorInitializerIndentWidth",<br>
Style.ConstructorInitializerIndentWidth);<br>
@@ -173,6 +186,36 @@ template <> struct MappingTraits<clang::<br>
IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);<br>
}<br>
};<br>
+<br>
+// Allows to read vector<FormatStyle> while keeping default values.<br>
+// Elements will be written or read starting from the 1st element.<br>
+// When writing, the 0th element is ignored.<br>
+// When reading, keys that are not present in the serialized form will be<br>
+// copied from the 0th element of the vector. If the first element had no<br>
+// Language specified, it will be treated as the default one for the following<br>
+// elements.<br>
+template <><br>
+struct DocumentListTraits<std::vector<clang::format::FormatStyle> > {<br>
+ static size_t size(IO &io, std::vector<clang::format::FormatStyle> &Seq) {<br>
+ return Seq.size() - 1;<br>
+ }<br>
+ static clang::format::FormatStyle &<br>
+ element(IO &io, std::vector<clang::format::FormatStyle> &Seq, size_t Index) {<br>
+ if (Index + 2 > Seq.size()) {<br>
+ assert(Index + 2 == Seq.size() + 1);<br>
+ clang::format::FormatStyle Template;<br>
+ if (Seq.size() > 1 &&<br>
+ Seq[1].Language == clang::format::FormatStyle::LK_None) {<br>
+ Template = Seq[1];<br>
+ } else {<br>
+ Template = Seq[0];<br>
+ Template.Language = clang::format::FormatStyle::LK_None;<br>
+ }<br>
+ Seq.resize(Index + 2, Template);<br>
+ }<br>
+ return Seq[Index + 1];<br>
+ }<br>
+};<br>
}<br>
}<br>
<br>
@@ -188,6 +231,7 @@ void setDefaultPenalties(FormatStyle &St<br>
<br>
FormatStyle getLLVMStyle() {<br>
FormatStyle LLVMStyle;<br>
+ LLVMStyle.Language = FormatStyle::LK_Cpp;<br>
LLVMStyle.AccessModifierOffset = -2;<br>
LLVMStyle.AlignEscapedNewlinesLeft = false;<br>
LLVMStyle.AlignTrailingComments = true;<br>
@@ -236,6 +280,7 @@ FormatStyle getLLVMStyle() {<br>
<br>
FormatStyle getGoogleStyle() {<br>
FormatStyle GoogleStyle;<br>
+ GoogleStyle.Language = FormatStyle::LK_Cpp;<br>
GoogleStyle.AccessModifierOffset = -1;<br>
GoogleStyle.AlignEscapedNewlinesLeft = true;<br>
GoogleStyle.AlignTrailingComments = true;<br>
@@ -337,11 +382,42 @@ bool getPredefinedStyle(StringRef Name,<br>
}<br>
<br>
llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {<br>
+ assert(Style);<br>
+ assert(Style->Language != FormatStyle::LK_None);<br>
if (Text.trim().empty())<br>
return llvm::make_error_code(llvm::errc::invalid_argument);<br>
+<br>
+ std::vector<FormatStyle> Styles;<br>
+ // DocumentListTraits<vector<FormatStyle>> uses 0th element as the default one<br>
+ // for the fields, keys for which are missing from the configuration.<br>
+ Styles.push_back(*Style);<br>
llvm::yaml::Input Input(Text);<br>
- Input >> *Style;<br>
- return Input.error();<br>
+ Input >> Styles;<br>
+ if (Input.error())<br>
+ return Input.error();<br>
+<br>
+ for (unsigned i = 1; i < Styles.size(); ++i) {<br>
+ // Ensures that only the first configuration can skip the Language option.<br>
+ if (Styles[i].Language == FormatStyle::LK_None && i != 1)<br>
+ return llvm::make_error_code(llvm::errc::invalid_argument);<br>
+ // Ensure that each language is configured at most once.<br>
+ for (unsigned j = 1; j < i; ++j) {<br>
+ if (Styles[i].Language == Styles[j].Language)<br>
+ return llvm::make_error_code(llvm::errc::invalid_argument);<br>
+ }<br>
+ }<br>
+ // Look for a suitable configuration starting from the end, so we can<br>
+ // find the configuration for the specific language first, and the default<br>
+ // configuration (which can only be at slot 1) after it.<br>
+ for (unsigned i = Styles.size() - 1; i > 0; --i) {<br>
+ if (Styles[i].Language == Styles[0].Language ||<br>
+ Styles[i].Language == FormatStyle::LK_None) {<br>
+ *Style = Styles[i];<br>
+ Style->Language = Styles[0].Language;<br>
+ return llvm::make_error_code(llvm::errc::success);<br>
+ }<br>
+ }<br>
+ return llvm::make_error_code(llvm::errc::not_supported);<br>
}<br>
<br>
std::string configurationAsText(const FormatStyle &Style) {<br>
@@ -986,24 +1062,44 @@ public:<br>
<br>
private:<br>
void tryMergePreviousTokens() {<br>
- tryMerge_TMacro() || tryMergeJavaScriptIdentityOperators();<br>
+ if (tryMerge_TMacro())<br>
+ return;<br>
+<br>
+ if (Style.Language == FormatStyle::LK_JavaScript) {<br>
+ static tok::TokenKind JSIdentity[] = { tok::equalequal, tok::equal };<br>
+ static tok::TokenKind JSNotIdentity[] = { tok::exclaimequal, tok::equal };<br>
+ static tok::TokenKind JSShiftEqual[] = { tok::greater, tok::greater,<br>
+ tok::greaterequal };<br>
+ // FIXME: We probably need to change token type to mimic operator with the<br>
+ // correct priority.<br>
+ if (tryMergeTokens(JSIdentity))<br>
+ return;<br>
+ if (tryMergeTokens(JSNotIdentity))<br>
+ return;<br>
+ if (tryMergeTokens(JSShiftEqual))<br>
+ return;<br>
+ }<br>
}<br>
<br>
- bool tryMergeJavaScriptIdentityOperators() {<br>
- if (Tokens.size() < 2)<br>
- return false;<br>
- FormatToken &First = *Tokens[Tokens.size() - 2];<br>
- if (!First.isOneOf(tok::exclaimequal, tok::equalequal))<br>
+ bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds) {<br>
+ if (Tokens.size() < Kinds.size())<br>
return false;<br>
- FormatToken &Second = *Tokens.back();<br>
- if (!Second.is(tok::equal))<br>
- return false;<br>
- if (Second.WhitespaceRange.getBegin() != Second.WhitespaceRange.getEnd())<br>
+<br>
+ SmallVectorImpl<FormatToken *>::const_iterator First =<br>
+ Tokens.end() - Kinds.size();<br>
+ if (!First[0]->is(Kinds[0]))<br>
return false;<br>
- First.TokenText =<br>
- StringRef(First.TokenText.data(), First.TokenText.size() + 1);<br>
- First.ColumnWidth += 1;<br>
- Tokens.pop_back();<br>
+ unsigned AddLength = 0;<br>
+ for (unsigned i = 1; i < Kinds.size(); ++i) {<br>
+ if (!First[i]->is(Kinds[i]) || First[i]->WhitespaceRange.getBegin() !=<br>
+ First[i]->WhitespaceRange.getEnd())<br>
+ return false;<br>
+ AddLength += First[i]->TokenText.size();<br>
+ }<br>
+ Tokens.resize(Tokens.size() - Kinds.size() + 1);<br>
+ First[0]->TokenText = StringRef(First[0]->TokenText.data(),<br>
+ First[0]->TokenText.size() + AddLength);<br>
+ First[0]->ColumnWidth += AddLength;<br>
return true;<br>
}<br>
<br>
@@ -1201,6 +1297,17 @@ private:<br>
}<br>
};<br>
<br>
+static StringRef getLanguageName(FormatStyle::LanguageKind Language) {<br>
+ switch (Language) {<br>
+ case FormatStyle::LK_Cpp:<br>
+ return "C++";<br>
+ case FormatStyle::LK_JavaScript:<br>
+ return "JavaScript";<br>
+ default:<br>
+ return "Unknown";<br>
+ }<br>
+}<br>
+<br>
class Formatter : public UnwrappedLineConsumer {<br>
public:<br>
Formatter(const FormatStyle &Style, Lexer &Lex, SourceManager &SourceMgr,<br>
@@ -1213,6 +1320,8 @@ public:<br>
<< (Encoding == encoding::Encoding_UTF8 ? "UTF8"<br>
: "unknown")<br>
<< "\n");<br>
+ DEBUG(llvm::dbgs() << "Language: " << getLanguageName(Style.Language)<br>
+ << "\n");<br>
}<br>
<br>
tooling::Replacements format() {<br>
@@ -1538,11 +1647,26 @@ const char *StyleOptionHelpDescription =<br>
"parameters, e.g.:\n"<br>
" -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";<br>
<br>
+static void fillLanguageByFileName(StringRef FileName, FormatStyle *Style) {<br>
+ if (FileName.endswith_lower(".c") || FileName.endswith_lower(".h") ||<br>
+ FileName.endswith_lower(".cpp") || FileName.endswith_lower(".hpp") ||<br>
+ FileName.endswith_lower(".cc") || FileName.endswith_lower(".hh") ||<br>
+ FileName.endswith_lower(".cxx") || FileName.endswith_lower(".hxx") ||<br>
+ FileName.endswith_lower(".m") || FileName.endswith_lower(".mm")) {<br>
+ Style->Language = FormatStyle::LK_Cpp;<br>
+ }<br>
+ if (FileName.endswith_lower(".js")) {<br>
+ Style->Language = FormatStyle::LK_JavaScript;<br>
+ }<br>
+}<br>
+<br>
FormatStyle getStyle(StringRef StyleName, StringRef FileName) {<br>
+ // FIXME: Configure fallback style from outside (add a command line option).<br>
// Fallback style in case the rest of this function can't determine a style.<br>
StringRef FallbackStyle = "LLVM";<br>
FormatStyle Style;<br>
getPredefinedStyle(FallbackStyle, &Style);<br>
+ fillLanguageByFileName(FileName, &Style);<br>
<br>
if (StyleName.startswith("{")) {<br>
// Parse YAML/JSON style from the command line.<br>
@@ -1557,9 +1681,11 @@ FormatStyle getStyle(StringRef StyleName<br>
if (!getPredefinedStyle(StyleName, &Style))<br>
llvm::errs() << "Invalid value for -style, using " << FallbackStyle<br>
<< " style\n";<br>
+ fillLanguageByFileName(FileName, &Style);<br>
return Style;<br>
}<br>
<br>
+ SmallString<128> UnsuitableConfigFiles;<br>
SmallString<128> Path(FileName);<br>
llvm::sys::fs::make_absolute(Path);<br>
for (StringRef Directory = Path; !Directory.empty();<br>
@@ -1591,8 +1717,14 @@ FormatStyle getStyle(StringRef StyleName<br>
continue;<br>
}<br>
if (llvm::error_code ec = parseConfiguration(Text->getBuffer(), &Style)) {<br>
- llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message()<br>
- << "\n";<br>
+ if (ec == llvm::errc::not_supported) {<br>
+ if (!UnsuitableConfigFiles.empty())<br>
+ UnsuitableConfigFiles.append(", ");<br>
+ UnsuitableConfigFiles.append(ConfigFile);<br>
+ } else {<br>
+ llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message()<br>
+ << "\n";<br>
+ }<br>
continue;<br>
}<br>
DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n");<br>
@@ -1601,6 +1733,11 @@ FormatStyle getStyle(StringRef StyleName<br>
}<br>
llvm::errs() << "Can't find usable .clang-format, using " << FallbackStyle<br>
<< " style\n";<br>
+ if (!UnsuitableConfigFiles.empty()) {<br>
+ llvm::errs() << "Configuration file(s) do(es) not support "<br>
+ << getLanguageName(Style.Language) << ": "<br>
+ << UnsuitableConfigFiles << "\n";<br>
+ }<br>
return Style;<br>
}<br>
<br>
<br>
Added: cfe/trunk/test/Format/language-detection.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Format/language-detection.cpp?rev=195961&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Format/language-detection.cpp?rev=195961&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/Format/language-detection.cpp (added)<br>
+++ cfe/trunk/test/Format/language-detection.cpp Fri Nov 29 09:19:43 2013<br>
@@ -0,0 +1,7 @@<br>
+// RUN: grep -Ev "// *[A-Z0-9_]+:" %s > %t.js<br>
+// RUN: grep -Ev "// *[A-Z0-9_]+:" %s > %t.cpp<br>
+// RUN: clang-format -style=llvm %t.js | FileCheck -strict-whitespace -check-prefix=CHECK1 %s<br>
+// RUN: clang-format -style=llvm %t.cpp | FileCheck -strict-whitespace -check-prefix=CHECK2 %s<br>
+// CHECK1: {{^a >>>= b;$}}<br>
+// CHECK2: {{^a >> >= b;$}}<br>
+a >>>= b;<br>
<br>
Modified: cfe/trunk/unittests/Format/FormatTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=195961&r1=195960&r2=195961&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=195961&r1=195960&r2=195961&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)<br>
+++ cfe/trunk/unittests/Format/FormatTest.cpp Fri Nov 29 09:19:43 2013<br>
@@ -6939,8 +6939,6 @@ TEST_F(FormatTest, GetsPredefinedStyleBy<br>
EXPECT_FALSE(getPredefinedStyle("qwerty", &Styles[0]));<br>
}<br>
<br>
-TEST_F(FormatTest, ParsesConfiguration) {<br>
- FormatStyle Style = {};<br>
#define CHECK_PARSE(TEXT, FIELD, VALUE) \<br>
EXPECT_NE(VALUE, Style.FIELD); \<br>
EXPECT_EQ(0, parseConfiguration(TEXT, &Style).value()); \<br>
@@ -6953,6 +6951,9 @@ TEST_F(FormatTest, ParsesConfiguration)<br>
EXPECT_EQ(0, parseConfiguration(#FIELD ": false", &Style).value()); \<br>
EXPECT_FALSE(Style.FIELD);<br>
<br>
+TEST_F(FormatTest, ParsesConfiguration) {<br>
+ FormatStyle Style = {};<br>
+ Style.Language = FormatStyle::LK_Cpp;<br>
CHECK_PARSE_BOOL(AlignEscapedNewlinesLeft);<br>
CHECK_PARSE_BOOL(AlignTrailingComments);<br>
CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine);<br>
@@ -7027,15 +7028,117 @@ TEST_F(FormatTest, ParsesConfiguration)<br>
FormatStyle::NI_Inner);<br>
CHECK_PARSE("NamespaceIndentation: All", NamespaceIndentation,<br>
FormatStyle::NI_All);<br>
+}<br>
+<br>
+TEST_F(FormatTest, ParsesConfigurationWithLanguages) {<br>
+ FormatStyle Style = {};<br>
+ Style.Language = FormatStyle::LK_Cpp;<br>
+ CHECK_PARSE("Language: Cpp\n"<br>
+ "IndentWidth: 12",<br>
+ IndentWidth, 12u);<br>
+ EXPECT_EQ(llvm::errc::not_supported,<br>
+ parseConfiguration("Language: JavaScript\n"<br>
+ "IndentWidth: 34",<br>
+ &Style));<br>
+ EXPECT_EQ(12u, Style.IndentWidth);<br>
+ CHECK_PARSE("IndentWidth: 56", IndentWidth, 56u);<br>
+ EXPECT_EQ(FormatStyle::LK_Cpp, Style.Language);<br>
+<br>
+ Style.Language = FormatStyle::LK_JavaScript;<br>
+ CHECK_PARSE("Language: JavaScript\n"<br>
+ "IndentWidth: 12",<br>
+ IndentWidth, 12u);<br>
+ CHECK_PARSE("IndentWidth: 23", IndentWidth, 23u);<br>
+ EXPECT_EQ(llvm::errc::not_supported, parseConfiguration("Language: Cpp\n"<br>
+ "IndentWidth: 34",<br>
+ &Style));<br>
+ EXPECT_EQ(23u, Style.IndentWidth);<br>
+ CHECK_PARSE("IndentWidth: 56", IndentWidth, 56u);<br>
+ EXPECT_EQ(FormatStyle::LK_JavaScript, Style.Language);<br>
+<br>
+ CHECK_PARSE("BasedOnStyle: LLVM\n"<br>
+ "IndentWidth: 67",<br>
+ IndentWidth, 67u);<br>
+<br>
+ CHECK_PARSE("---\n"<br>
+ "Language: JavaScript\n"<br>
+ "IndentWidth: 12\n"<br>
+ "---\n"<br>
+ "Language: Cpp\n"<br>
+ "IndentWidth: 34\n"<br>
+ "...\n",<br>
+ IndentWidth, 12u);<br>
+<br>
+ Style.Language = FormatStyle::LK_Cpp;<br>
+ CHECK_PARSE("---\n"<br>
+ "Language: JavaScript\n"<br>
+ "IndentWidth: 12\n"<br>
+ "---\n"<br>
+ "Language: Cpp\n"<br>
+ "IndentWidth: 34\n"<br>
+ "...\n",<br>
+ IndentWidth, 34u);<br>
+ CHECK_PARSE("---\n"<br>
+ "IndentWidth: 78\n"<br>
+ "---\n"<br>
+ "Language: JavaScript\n"<br>
+ "IndentWidth: 56\n"<br>
+ "...\n",<br>
+ IndentWidth, 78u);<br>
+<br>
+ Style.ColumnLimit = 123;<br>
+ Style.IndentWidth = 234;<br>
+ Style.BreakBeforeBraces = FormatStyle::BS_Linux;<br>
+ Style.TabWidth = 345;<br>
+ EXPECT_EQ(llvm::errc::success,<br>
+ parseConfiguration("---\n"<br>
+ "IndentWidth: 456\n"<br>
+ "BreakBeforeBraces: Allman\n"<br>
+ "---\n"<br>
+ "Language: JavaScript\n"<br>
+ "IndentWidth: 111\n"<br>
+ "TabWidth: 111\n"<br>
+ "---\n"<br>
+ "Language: Cpp\n"<br>
+ "BreakBeforeBraces: Stroustrup\n"<br>
+ "TabWidth: 789\n"<br>
+ "...\n",<br>
+ &Style));<br>
+ EXPECT_EQ(123u, Style.ColumnLimit);<br>
+ EXPECT_EQ(456u, Style.IndentWidth);<br>
+ EXPECT_EQ(FormatStyle::BS_Stroustrup, Style.BreakBeforeBraces);<br>
+ EXPECT_EQ(789u, Style.TabWidth);<br>
+<br>
+<br>
+ EXPECT_EQ(llvm::errc::invalid_argument,<br>
+ parseConfiguration("---\n"<br>
+ "Language: JavaScript\n"<br>
+ "IndentWidth: 56\n"<br>
+ "---\n"<br>
+ "IndentWidth: 78\n"<br>
+ "...\n",<br>
+ &Style));<br>
+ EXPECT_EQ(llvm::errc::invalid_argument,<br>
+ parseConfiguration("---\n"<br>
+ "Language: JavaScript\n"<br>
+ "IndentWidth: 56\n"<br>
+ "---\n"<br>
+ "Language: JavaScript\n"<br>
+ "IndentWidth: 78\n"<br>
+ "...\n",<br>
+ &Style));<br>
+<br>
+ EXPECT_EQ(FormatStyle::LK_Cpp, Style.Language);<br>
+}<br>
<br>
#undef CHECK_PARSE<br>
#undef CHECK_PARSE_BOOL<br>
-}<br>
<br>
TEST_F(FormatTest, ConfigurationRoundTripTest) {<br>
FormatStyle Style = getLLVMStyle();<br>
std::string YAML = configurationAsText(Style);<br>
FormatStyle ParsedStyle = {};<br>
+ ParsedStyle.Language = FormatStyle::LK_Cpp;<br>
EXPECT_EQ(0, parseConfiguration(YAML, &ParsedStyle).value());<br>
EXPECT_EQ(Style, ParsedStyle);<br>
}<br>
@@ -7457,18 +7560,36 @@ TEST_F(FormatTest, SpacesInAngles) {<br>
}<br>
<br>
TEST_F(FormatTest, UnderstandsJavaScript) {<br>
- verifyFormat("a == = b;");<br>
- verifyFormat("a != = b;");<br>
-<br>
- verifyFormat("a === b;");<br>
- verifyFormat("aaaaaaa ===\n b;", getLLVMStyleWithColumns(10));<br>
- verifyFormat("a !== b;");<br>
- verifyFormat("aaaaaaa !==\n b;", getLLVMStyleWithColumns(10));<br>
+ FormatStyle JS = getLLVMStyle();<br>
+ FormatStyle JS10Columns = getLLVMStyleWithColumns(10);<br>
+ FormatStyle JS20Columns = getLLVMStyleWithColumns(20);<br>
+ JS.Language = JS10Columns.Language = JS20Columns.Language =<br>
+ FormatStyle::LK_JavaScript;<br>
+<br>
+ verifyFormat("a == = b;", JS);<br>
+ verifyFormat("a != = b;", JS);<br>
+<br>
+ verifyFormat("a === b;", JS);<br>
+ verifyFormat("aaaaaaa ===\n b;", JS10Columns);<br>
+ verifyFormat("a !== b;", JS);<br>
+ verifyFormat("aaaaaaa !==\n b;", JS10Columns);<br>
verifyFormat("if (a + b + c +\n"<br>
" d !==\n"<br>
" e + f + g)\n"<br>
" q();",<br>
- getLLVMStyleWithColumns(20));<br>
+ JS20Columns);<br>
+<br>
+ verifyFormat("a >> >= b;", JS);<br>
+<br>
+ verifyFormat("a >>> b;", JS);<br>
+ verifyFormat("aaaaaaa >>>\n b;", JS10Columns);<br>
+ verifyFormat("a >>>= b;", JS);<br>
+ verifyFormat("aaaaaaa >>>=\n b;", JS10Columns);<br>
+ verifyFormat("if (a + b + c +\n"<br>
+ " d >>>\n"<br>
+ " e + f + g)\n"<br>
+ " q();",<br>
+ JS20Columns);<br>
}<br>
<br>
} // end namespace tooling<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>