r332968 - clang-format: [JS] do not wrap before any `is`.

2018-05-22 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue May 22 03:39:07 2018
New Revision: 332968

URL: http://llvm.org/viewvc/llvm-project?rev=332968&view=rev
Log:
clang-format: [JS] do not wrap before any `is`.

Summary:
`is` type annotations can occur at any nesting level. For example:

function x() {
  return function y(): a is B { ... };
}

Breaking before the `is` above breaks TypeScript parsing the code. This
change prevents the wrap.

Reviewers: krasimir

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D47193

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=332968&r1=332967&r2=332968&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue May 22 03:39:07 2018
@@ -2958,7 +2958,7 @@ bool TokenAnnotator::canBreakBefore(cons
   return false;
 if (Left.is(TT_JsTypeColon))
   return true;
-if (Right.NestingLevel == 0 && Right.is(Keywords.kw_is))
+if (Right.is(Keywords.kw_is))
   return false;
 if (Left.is(Keywords.kw_in))
   return Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None;

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=332968&r1=332967&r2=332968&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue May 22 03:39:07 2018
@@ -1164,7 +1164,15 @@ TEST_F(FormatTestJS, WrapRespectsAutomat
   verifyFormat("await theReckoning;", getGoogleJSStyleWithColumns(10));
   verifyFormat("some['a']['b']", getGoogleJSStyleWithColumns(10));
   verifyFormat("x = (a['a']\n"
-   "  ['b']);", getGoogleJSStyleWithColumns(10));
+   "  ['b']);",
+   getGoogleJSStyleWithColumns(10));
+  verifyFormat("function f() {\n"
+   "  return foo.bar(\n"
+   "  (param): param is {\n"
+   "a: SomeType\n"
+   "  }&ABC => 1)\n"
+   "}",
+   getGoogleJSStyleWithColumns(25));
 }
 
 TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r338706 - clang-format: fix a crash in comment wraps.

2018-08-02 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Thu Aug  2 04:52:08 2018
New Revision: 338706

URL: http://llvm.org/viewvc/llvm-project?rev=338706&view=rev
Log:
clang-format: fix a crash in comment wraps.

Summary:
Previously, clang-format would crash if it tried to wrap an overlong
single line comment, because two parts of the code inserted a break in
the same location.

/** heregoesalongcommentwithnospace */

This wasn't previously noticed as it could only trigger for an overlong
single line comment that did have no breaking opportunities except for a
whitespace at the very beginning.

This also introduces a check for JavaScript to not ever wrap a comment
before an opening curly brace:

/** @mods {donotbreakbeforethecurly} */

This is because some machinery parsing these tags sometimes supports
breaks before a possible `{`, but in some other cases does not.
Previously clang-format was careful never to wrap a line with certain
tags on it. The better solution is to specifically disable wrapping
before the problematic token: this allows wrapping and aligning comments
but still avoids the problem.

Reviewers: krasimir

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D50177

Modified:
cfe/trunk/lib/Format/BreakableToken.cpp
cfe/trunk/unittests/Format/FormatTestComments.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/BreakableToken.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/BreakableToken.cpp?rev=338706&r1=338705&r2=338706&view=diff
==
--- cfe/trunk/lib/Format/BreakableToken.cpp (original)
+++ cfe/trunk/lib/Format/BreakableToken.cpp Thu Aug  2 04:52:08 2018
@@ -67,10 +67,11 @@ static BreakableToken::Split getCommentS
  unsigned ContentStartColumn,
  unsigned ColumnLimit,
  unsigned TabWidth,
- encoding::Encoding Encoding) {
-  LLVM_DEBUG(llvm::dbgs() << "Comment split: \"" << Text << ", " << ColumnLimit
-  << "\", Content start: " << ContentStartColumn
-  << "\n");
+ encoding::Encoding Encoding,
+ const FormatStyle &Style) {
+  LLVM_DEBUG(llvm::dbgs() << "Comment split: \"" << Text
+  << "\", Column limit: " << ColumnLimit
+  << ", Content start: " << ContentStartColumn << 
"\n");
   if (ColumnLimit <= ContentStartColumn + 1)
 return BreakableToken::Split(StringRef::npos, 0);
 
@@ -95,6 +96,13 @@ static BreakableToken::Split getCommentS
   if (SpaceOffset != StringRef::npos &&
   kNumberedListRegexp->match(Text.substr(SpaceOffset).ltrim(Blanks)))
 SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
+  // In JavaScript, some @tags can be followed by {, and machinery that parses
+  // these comments will fail to understand the comment if followed by a line
+  // break. So avoid ever breaking before a {.
+  if (Style.Language == FormatStyle::LK_JavaScript &&
+  SpaceOffset != StringRef::npos && SpaceOffset + 1 < Text.size() &&
+  Text[SpaceOffset + 1] == '{')
+SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
 
   if (SpaceOffset == StringRef::npos ||
   // Don't break at leading whitespace.
@@ -109,6 +117,12 @@ static BreakableToken::Split getCommentS
 Blanks, std::max(MaxSplitBytes, FirstNonWhitespace));
   }
   if (SpaceOffset != StringRef::npos && SpaceOffset != 0) {
+// adaptStartOfLine will break after lines starting with /** if the comment
+// is broken anywhere. Avoid emitting this break twice here.
+// Example: in /** longtextcomesherethatbreaks */ (with ColumnLimit 20) 
will
+// insert a break after /**, so this code must not insert the same break.
+if (SpaceOffset == 1 && Text[SpaceOffset - 1] == '*')
+  return BreakableToken::Split(StringRef::npos, 0);
 StringRef BeforeCut = Text.substr(0, SpaceOffset).rtrim(Blanks);
 StringRef AfterCut = Text.substr(SpaceOffset).ltrim(Blanks);
 return BreakableToken::Split(BeforeCut.size(),
@@ -260,7 +274,7 @@ BreakableComment::getSplit(unsigned Line
 return Split(StringRef::npos, 0);
   return getCommentSplit(Content[LineIndex].substr(TailOffset),
  ContentStartColumn, ColumnLimit, Style.TabWidth,
- Encoding);
+ Encoding, Style);
 }
 
 void BreakableComment::compressWhitespace(
@@ -620,6 +634,8 @@ void BreakableBlockComment::adaptStartOf
 if (DelimitersOnNewline) {
   // Since we're breaking at index 1 below, the break position and the
   // break length are the same.
+  // Note: this works because getCommentSplit is careful never to split at
+  // the beginning of a line.
   size_t BreakL

r338837 - clang-format: [JS] don't break comments before any '{'

2018-08-03 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Aug  3 02:34:41 2018
New Revision: 338837

URL: http://llvm.org/viewvc/llvm-project?rev=338837&view=rev
Log:
clang-format: [JS] don't break comments before any '{'

Summary:
Previously, clang-format would avoid breaking before the first `{`
found, but then happily break before subsequent '{'s on the line. This
change fixes that by looking for the first location that has no opening
curly, if any.

Reviewers: krasimir

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D50230

Modified:
cfe/trunk/lib/Format/BreakableToken.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/BreakableToken.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/BreakableToken.cpp?rev=338837&r1=338836&r2=338837&view=diff
==
--- cfe/trunk/lib/Format/BreakableToken.cpp (original)
+++ cfe/trunk/lib/Format/BreakableToken.cpp Fri Aug  3 02:34:41 2018
@@ -90,19 +90,19 @@ static BreakableToken::Split getCommentS
 
   StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes);
 
-  // Do not split before a number followed by a dot: this would be interpreted
-  // as a numbered list, which would prevent re-flowing in subsequent passes.
   static auto *const kNumberedListRegexp = new llvm::Regex("^[1-9][0-9]?\\.");
-  if (SpaceOffset != StringRef::npos &&
-  kNumberedListRegexp->match(Text.substr(SpaceOffset).ltrim(Blanks)))
-SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
-  // In JavaScript, some @tags can be followed by {, and machinery that parses
-  // these comments will fail to understand the comment if followed by a line
-  // break. So avoid ever breaking before a {.
-  if (Style.Language == FormatStyle::LK_JavaScript &&
-  SpaceOffset != StringRef::npos && SpaceOffset + 1 < Text.size() &&
-  Text[SpaceOffset + 1] == '{')
-SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
+  while (SpaceOffset != StringRef::npos) {
+// Do not split before a number followed by a dot: this would be 
interpreted
+// as a numbered list, which would prevent re-flowing in subsequent passes.
+if (kNumberedListRegexp->match(Text.substr(SpaceOffset).ltrim(Blanks)))
+  SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
+// In JavaScript, some @tags can be followed by {, and machinery that 
parses
+// these comments will fail to understand the comment if followed by a line
+// break. So avoid ever breaking before a {.
+else if (Style.Language == FormatStyle::LK_JavaScript &&
+ SpaceOffset + 1 < Text.size() && Text[SpaceOffset + 1] == '{')
+  SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
+  }
 
   if (SpaceOffset == StringRef::npos ||
   // Don't break at leading whitespace.

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=338837&r1=338836&r2=338837&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Fri Aug  3 02:34:41 2018
@@ -2067,6 +2067,14 @@ TEST_F(FormatTestJS, JSDocAnnotations) {
" * @param {canWrap onSpace}\n"
" */",
getGoogleJSStyleWithColumns(20));
+  // make sure clang-format doesn't break before *any* '{'
+  verifyFormat("/**\n"
+   " * @lala {lala {lalala\n"
+   " */\n",
+   "/**\n"
+   " * @lala {lala {lalala\n"
+   " */\n",
+   getGoogleJSStyleWithColumns(20));
   verifyFormat("/**\n"
" * @see http://very/very/long/url/is/long\n";
" */",


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: r338837 - clang-format: [JS] don't break comments before any '{'

2018-08-03 Thread Martin Probst via cfe-commits
Sorry about that, yes, that was me. Thanks for reverting!

Tim Northover  schrieb am Fr., 3. Aug. 2018 um
14:19 Uhr:

> On Fri, 3 Aug 2018 at 11:47, Tim Northover 
> wrote:
> > On Fri, 3 Aug 2018 at 10:34, Martin Probst via cfe-commits
> >  wrote:
> > > clang-format: [JS] don't break comments before any '{'
> >
> > This looks like it's triggered a bunch of infinite loops in Clang's
> > unittests.
>
> I've just taken a look at the normal lab.llvm.org bots and it looks
> like *everything* is broken so I've reverted it for now.
>
> Cheers.
>
> Tim.
>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r338890 - clang-format: [JS] don't break comments before any '{'

2018-08-03 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Aug  3 06:58:33 2018
New Revision: 338890

URL: http://llvm.org/viewvc/llvm-project?rev=338890&view=rev
Log:
clang-format: [JS] don't break comments before any '{'

Summary:
Previously, clang-format would avoid breaking before the first `{`
found, but then happily break before subsequent '{'s on the line. This
change fixes that by looking for the first location that has no opening
curly, if any.

This fixes the original commit by correcting the loop condition.

This reverts commit 66dc646e09b795b943668179c33d09da71a3b6bc.

Reviewers: krasimir

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D50249

Modified:
cfe/trunk/lib/Format/BreakableToken.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/BreakableToken.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/BreakableToken.cpp?rev=338890&r1=338889&r2=338890&view=diff
==
--- cfe/trunk/lib/Format/BreakableToken.cpp (original)
+++ cfe/trunk/lib/Format/BreakableToken.cpp Fri Aug  3 06:58:33 2018
@@ -90,19 +90,21 @@ static BreakableToken::Split getCommentS
 
   StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes);
 
-  // Do not split before a number followed by a dot: this would be interpreted
-  // as a numbered list, which would prevent re-flowing in subsequent passes.
   static auto *const kNumberedListRegexp = new llvm::Regex("^[1-9][0-9]?\\.");
-  if (SpaceOffset != StringRef::npos &&
-  kNumberedListRegexp->match(Text.substr(SpaceOffset).ltrim(Blanks)))
-SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
-  // In JavaScript, some @tags can be followed by {, and machinery that parses
-  // these comments will fail to understand the comment if followed by a line
-  // break. So avoid ever breaking before a {.
-  if (Style.Language == FormatStyle::LK_JavaScript &&
-  SpaceOffset != StringRef::npos && SpaceOffset + 1 < Text.size() &&
-  Text[SpaceOffset + 1] == '{')
-SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
+  while (SpaceOffset != StringRef::npos) {
+// Do not split before a number followed by a dot: this would be 
interpreted
+// as a numbered list, which would prevent re-flowing in subsequent passes.
+if (kNumberedListRegexp->match(Text.substr(SpaceOffset).ltrim(Blanks)))
+  SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
+// In JavaScript, some @tags can be followed by {, and machinery that 
parses
+// these comments will fail to understand the comment if followed by a line
+// break. So avoid ever breaking before a {.
+else if (Style.Language == FormatStyle::LK_JavaScript &&
+ SpaceOffset + 1 < Text.size() && Text[SpaceOffset + 1] == '{')
+  SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
+else
+  break;
+  }
 
   if (SpaceOffset == StringRef::npos ||
   // Don't break at leading whitespace.

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=338890&r1=338889&r2=338890&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Fri Aug  3 06:58:33 2018
@@ -2067,6 +2067,14 @@ TEST_F(FormatTestJS, JSDocAnnotations) {
" * @param {canWrap onSpace}\n"
" */",
getGoogleJSStyleWithColumns(20));
+  // make sure clang-format doesn't break before *any* '{'
+  verifyFormat("/**\n"
+   " * @lala {lala {lalala\n"
+   " */\n",
+   "/**\n"
+   " * @lala {lala {lalala\n"
+   " */\n",
+   getGoogleJSStyleWithColumns(20));
   verifyFormat("/**\n"
" * @see http://very/very/long/url/is/long\n";
" */",


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r325489 - clang-format: [JS] fix `of` detection.

2018-02-19 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Feb 19 04:32:13 2018
New Revision: 325489

URL: http://llvm.org/viewvc/llvm-project?rev=325489&view=rev
Log:
clang-format: [JS] fix `of` detection.

Summary:
`of` is only a keyword when after an identifier, but not when after
an actual keyword.

Before:
return of (a, b, c);
After:
return of(a, b, c);

Reviewers: djasper

Subscribers: cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D43440

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=325489&r1=325488&r2=325489&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon Feb 19 04:32:13 2018
@@ -2496,7 +2496,7 @@ bool TokenAnnotator::spaceRequiredBefore
  // (e.g. as "const x of y" in a for loop), or after a destructuring
  // operation (const [x, y] of z, const {a, b} of c).
  (Left.is(Keywords.kw_of) && Left.Previous &&
-  (Left.Previous->Tok.getIdentifierInfo() ||
+  (Left.Previous->Tok.is(tok::identifier) ||
Left.Previous->isOneOf(tok::r_square, tok::r_brace &&
 (!Left.Previous || !Left.Previous->is(tok::period)))
   return true;

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=325489&r1=325488&r2=325489&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon Feb 19 04:32:13 2018
@@ -294,6 +294,7 @@ TEST_F(FormatTestJS, ReservedWords) {
   verifyFormat("x.for = 1;");
   verifyFormat("x.of();");
   verifyFormat("of(null);");
+  verifyFormat("return of(null);");
   verifyFormat("import {of} from 'x';");
   verifyFormat("x.in();");
   verifyFormat("x.let();");


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r304135 - clang-format: [JS] fix indenting bound functions.

2017-05-29 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon May 29 02:50:52 2017
New Revision: 304135

URL: http://llvm.org/viewvc/llvm-project?rev=304135&view=rev
Log:
clang-format: [JS] fix indenting bound functions.

Summary:
The previous fix to force build style wrapping if the previous token is a 
closing parenthesis broke a peculiar pattern where users parenthesize the 
function declaration in a bind call:
fn((function() { ... }).bind(this));

This restores the previous behaviour by reverting that change, but narrowing 
the special case for unindenting closing parentheses to those followed by 
semicolons and opening braces, i.e. immediate calls and function declarations.

Reviewers: djasper

Subscribers: cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D33640

Modified:
cfe/trunk/lib/Format/ContinuationIndenter.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=304135&r1=304134&r2=304135&view=diff
==
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Mon May 29 02:50:52 2017
@@ -215,7 +215,7 @@ bool ContinuationIndenter::mustBreak(con
   // ...
   //   }.bind(...));
   // FIXME: We should find a more generic solution to this problem.
-  !(State.Column <= NewLineColumn && Previous.isNot(tok::r_paren) &&
+  !(State.Column <= NewLineColumn &&
 Style.Language == FormatStyle::LK_JavaScript))
 return true;
 
@@ -689,7 +689,18 @@ unsigned ContinuationIndenter::getNewLin
   return State.Stack[State.Stack.size() - 2].LastSpace;
 return State.FirstIndent;
   }
-  if (Current.is(tok::r_paren) && State.Stack.size() > 1)
+  // Indent a closing parenthesis at the previous level if followed by a semi 
or
+  // opening brace. This allows indentations such as:
+  // foo(
+  //   a,
+  // );
+  // function foo(
+  //   a,
+  // ) {
+  //   code(); //
+  // }
+  if (Current.is(tok::r_paren) && State.Stack.size() > 1 &&
+  (!Current.Next || Current.Next->isOneOf(tok::semi, tok::l_brace)))
 return State.Stack[State.Stack.size() - 2].LastSpace;
   if (NextNonComment->is(TT_TemplateString) && NextNonComment->closesScope())
 return State.Stack[State.Stack.size() - 2].LastSpace;

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=304135&r1=304134&r2=304135&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon May 29 02:50:52 2017
@@ -717,6 +717,11 @@ TEST_F(FormatTestJS, FunctionLiterals) {
"  bar();\n"
"}.bind(this));");
 
+  verifyFormat("SomeFunction((function() {\n"
+   "   foo();\n"
+   "   bar();\n"
+   " }).bind(this));");
+
   // FIXME: This is bad, we should be wrapping before "function() {".
   verifyFormat("someFunction(function() {\n"
"  doSomething();  // break\n"


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r304141 - clang-format: [JS] do not clean up duplicated commas.

2017-05-29 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon May 29 03:41:11 2017
New Revision: 304141

URL: http://llvm.org/viewvc/llvm-project?rev=304141&view=rev
Log:
clang-format: [JS] do not clean up duplicated commas.

Summary:
In JavaScript, duplicated commas have semantic meaning.
x = [a,,b];

The statement above creates an array with three entries, the middle being 
undefined. Because clang-format should not change semantics, disable this 
cleanup in JS.

Reviewers: djasper

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D33641

Modified:
cfe/trunk/lib/Format/Format.cpp
cfe/trunk/unittests/Format/CleanupTest.cpp

Modified: cfe/trunk/lib/Format/Format.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=304141&r1=304140&r2=304141&view=diff
==
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Mon May 29 03:41:11 2017
@@ -1910,6 +1910,9 @@ tooling::Replacements reformat(const For
 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
   ArrayRef Ranges,
   StringRef FileName) {
+  // cleanups only apply to C++ (they mostly concern ctor commas etc.)
+  if (Style.Language != FormatStyle::LK_Cpp)
+return tooling::Replacements();
   std::unique_ptr Env =
   Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
   Cleaner Clean(*Env, Style);

Modified: cfe/trunk/unittests/Format/CleanupTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/CleanupTest.cpp?rev=304141&r1=304140&r2=304141&view=diff
==
--- cfe/trunk/unittests/Format/CleanupTest.cpp (original)
+++ cfe/trunk/unittests/Format/CleanupTest.cpp Mon May 29 03:41:11 2017
@@ -36,11 +36,12 @@ protected:
 
   // Returns code after cleanup around \p Offsets.
   std::string cleanupAroundOffsets(llvm::ArrayRef Offsets,
-   llvm::StringRef Code) {
+   llvm::StringRef Code,
+   const FormatStyle &Style = getLLVMStyle()) {
 std::vector Ranges;
 for (auto Offset : Offsets)
   Ranges.push_back(tooling::Range(Offset, 0));
-return cleanup(Code, Ranges);
+return cleanup(Code, Ranges, Style);
   }
 };
 
@@ -171,6 +172,14 @@ TEST_F(CleanupTest, ListRedundantComma)
   EXPECT_EQ(Expected, cleanupAroundOffsets({17, 22}, Code));
 }
 
+TEST_F(CleanupTest, NoCleanupsForJavaScript) {
+  std::string Code = "function f() { var x = [a, b, , c]; }";
+  std::string Expected = "function f() { var x = [a, b, , c]; }";
+  const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript);
+
+  EXPECT_EQ(Expected, cleanupAroundOffsets({30}, Code, Style));
+}
+
 TEST_F(CleanupTest, TrailingCommaInParens) {
   std::string Code = "int main() { f(,1,,2,3,f(1,2,),4,,);}";
   std::string Expected = "int main() { f(1,2,3,f(1,2),4);}";


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r304290 - clang-format: [JS] improve calculateBraceType heuristic

2017-05-31 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Wed May 31 04:29:40 2017
New Revision: 304290

URL: http://llvm.org/viewvc/llvm-project?rev=304290&view=rev
Log:
clang-format: [JS] improve calculateBraceType heuristic

Summary:

calculateBraceTypes decides for braced init for empty brace pairs ({}).
In context of a function declaration, this incorrectly classifies empty
function or method bodies as braced inits, leading to missing wraps:

class C {
  foo() {}[bar]() {}
}

Where code should have wrapped after "}", before "[". This change adds
another piece of contextual information in that braces following closing
parentheses must always be the opening braces of function blocks. This
fixes brace detection for methods immediately followed by brackets
(computed property declarations), but also curlies.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D33714

Modified:
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=304290&r1=304289&r2=304290&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Wed May 31 04:29:40 2017
@@ -360,16 +360,21 @@ void UnwrappedLineParser::calculateBrace
 
 switch (Tok->Tok.getKind()) {
 case tok::l_brace:
-  if (Style.Language == FormatStyle::LK_JavaScript && PrevTok &&
-  PrevTok->is(tok::colon))
-// A colon indicates this code is in a type, or a braced list following
-// a label in an object literal ({a: {b: 1}}).
-// The code below could be confused by semicolons between the 
individual
-// members in a type member list, which would normally trigger 
BK_Block.
-// In both cases, this must be parsed as an inline braced init.
-Tok->BlockKind = BK_BracedInit;
-  else
+  if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) {
+if (PrevTok->is(tok::colon))
+  // A colon indicates this code is in a type, or a braced list
+  // following a label in an object literal ({a: {b: 1}}). The code
+  // below could be confused by semicolons between the individual
+  // members in a type member list, which would normally trigger
+  // BK_Block. In both cases, this must be parsed as an inline braced
+  // init.
+  Tok->BlockKind = BK_BracedInit;
+else if (PrevTok->is(tok::r_paren))
+  // `) { }` can only occur in function or method declarations in JS.
+  Tok->BlockKind = BK_Block;
+  } else {
 Tok->BlockKind = BK_Unknown;
+  }
   LBraceStack.push_back(Tok);
   break;
 case tok::r_brace:
@@ -391,6 +396,8 @@ void UnwrappedLineParser::calculateBrace
   // BlockKind later if we parse a braced list (where all blocks
   // inside are by default braced lists), or when we explicitly detect
   // blocks (for example while parsing lambdas).
+  // FIXME: Some of these do not apply to JS, e.g. "} {" can never be a
+  // braced list in JS.
   ProbablyBracedList =
   (Style.Language == FormatStyle::LK_JavaScript &&
NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=304290&r1=304289&r2=304290&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Wed May 31 04:29:40 2017
@@ -474,9 +474,8 @@ TEST_F(FormatTestJS, FormatsFreestanding
"(function f() {\n"
"  var x = 1;\n"
"}());\n");
-  // Known issue: this should wrap after {}, but calculateBraceTypes
-  // misclassifies the first braces as a BK_BracedInit.
-  verifyFormat("function aFunction(){} {\n"
+  verifyFormat("function aFunction() {}\n"
+   "{\n"
"  let x = 1;\n"
"  console.log(x);\n"
"}\n");
@@ -1233,6 +1232,10 @@ TEST_F(FormatTestJS, ClassDeclarations)
   verifyFormat("class C {\n  x: string = 12;\n}");
   verifyFormat("class C {\n  x(): string => 12;\n}");
   verifyFormat("class C {\n  ['x' + 2]: string = 12;\n}");
+  verifyFormat("class C {\n"
+   "  foo() {}\n"
+   "  [bar]() {}\n"
+   "}\n");
   verifyFormat("class C {\n  private x: string = 12;\n}");
   verifyFormat("class C {\n  private static x: string = 12;\n}");
   verifyFormat("class C {\n  static x(): string {\nreturn 'asd';\n  }\n}");


___
cfe-commits mailing list
cfe-commits@lists.l

r304791 - clang-format: [JS] Correctly Indent Nested JavaScript Literals.

2017-06-06 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Jun  6 07:38:29 2017
New Revision: 304791

URL: http://llvm.org/viewvc/llvm-project?rev=304791&view=rev
Log:
clang-format: [JS] Correctly Indent Nested JavaScript Literals.

Nested literals are sometimes only indented by 2 spaces, instead of
respecting the IndentWidth option.
There are existing unit tests (FormatTestJS.ArrayLiterals) that only
pass because the style used to test them uses an IndentWidth of 2.
This change removes the magic 2 and always uses the IndentWidth.
I've added 6 tests. The first 4 of these tests fail before this change,
while the last 2 already pass, but were added just to make sure it the
change works with all types of braces.

Patch originally by Jared Neil, thanks!

Differential Revision: https://reviews.llvm.org/D33857

Modified:
cfe/trunk/lib/Format/ContinuationIndenter.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=304791&r1=304790&r2=304791&view=diff
==
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Tue Jun  6 07:38:29 2017
@@ -1036,8 +1036,8 @@ void ContinuationIndenter::moveStatePast
 State.Stack.back().NestedBlockIndent);
   if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)) {
 if (Current.opensBlockOrBlockTypeList(Style)) {
-  NewIndent = State.Stack.back().NestedBlockIndent + Style.IndentWidth;
-  NewIndent = std::min(State.Column + 2, NewIndent);
+  NewIndent = Style.IndentWidth +
+  std::min(State.Column, State.Stack.back().NestedBlockIndent);
 } else {
   NewIndent = State.Stack.back().LastSpace + Style.ContinuationIndentWidth;
 }

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=304791&r1=304790&r2=304791&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Jun  6 07:38:29 2017
@@ -1869,5 +1869,44 @@ TEST_F(FormatTestJS, Exponentiation) {
   verifyFormat("squared **= 2;");
 }
 
+TEST_F(FormatTestJS, NestedLiterals) {
+  FormatStyle FourSpaces = getGoogleJSStyleWithColumns(15);
+  FourSpaces.IndentWidth = 4;
+  verifyFormat("var l = [\n"
+   "[\n"
+   "1,\n"
+   "],\n"
+   "];", FourSpaces);
+  verifyFormat("var l = [\n"
+   "{\n"
+   "1: 1,\n"
+   "},\n"
+   "];", FourSpaces);
+  verifyFormat("someFunction(\n"
+   "p1,\n"
+   "[\n"
+   "1,\n"
+   "],\n"
+   ");", FourSpaces);
+  verifyFormat("someFunction(\n"
+   "p1,\n"
+   "{\n"
+   "1: 1,\n"
+   "},\n"
+   ");", FourSpaces);
+  verifyFormat("var o = {\n"
+   "1: 1,\n"
+   "2: {\n"
+   "3: 3,\n"
+   "},\n"
+   "};", FourSpaces);
+  verifyFormat("var o = {\n"
+   "1: 1,\n"
+   "2: [\n"
+   "3,\n"
+   "],\n"
+   "};", FourSpaces);
+}
+
 } // end namespace tooling
 } // end namespace clang


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r304904 - clang-format: [JS] recognize exported type definitions.

2017-06-07 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Wed Jun  7 07:53:22 2017
New Revision: 304904

URL: http://llvm.org/viewvc/llvm-project?rev=304904&view=rev
Log:
clang-format: [JS] recognize exported type definitions.

Summary: Support "export type T = {...};", in addition to just "type T = 
{...};".

Reviewers: klimek

Differential Revision: https://reviews.llvm.org/D33980

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=304904&r1=304903&r2=304904&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Wed Jun  7 07:53:22 2017
@@ -135,8 +135,11 @@ private:
 if (Left->is(TT_OverloadedOperatorLParen)) {
   Contexts.back().IsExpression = false;
 } else if (Style.Language == FormatStyle::LK_JavaScript &&
-   Line.startsWith(Keywords.kw_type, tok::identifier)) {
+   (Line.startsWith(Keywords.kw_type, tok::identifier) ||
+Line.startsWith(tok::kw_export, Keywords.kw_type,
+tok::identifier))) {
   // type X = (...);
+  // export type X = (...);
   Contexts.back().IsExpression = false;
 } else if (Left->Previous &&
 (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
@@ -979,9 +982,12 @@ private:
   void modifyContext(const FormatToken &Current) {
 if (Current.getPrecedence() == prec::Assignment &&
 !Line.First->isOneOf(tok::kw_template, tok::kw_using, tok::kw_return) 
&&
-// Type aliases use `type X = ...;` in TypeScript.
+// Type aliases use `type X = ...;` in TypeScript and can be exported
+// using `export type ...`.
 !(Style.Language == FormatStyle::LK_JavaScript &&
-  Line.startsWith(Keywords.kw_type, tok::identifier)) &&
+  (Line.startsWith(Keywords.kw_type, tok::identifier) ||
+   Line.startsWith(tok::kw_export, Keywords.kw_type,
+   tok::identifier))) &&
 (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
   Contexts.back().IsExpression = true;
   if (!Line.startsWith(TT_UnaryOperator)) {

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=304904&r1=304903&r2=304904&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Wed Jun  7 07:53:22 2017
@@ -1226,6 +1226,12 @@ TEST_F(FormatTestJS, UnionIntersectionTy
   verifyFormat("let x: Bar|Baz;");
   verifyFormat("let x: Bar|Baz;");
   verifyFormat("let x: (Foo|Bar)[];");
+  verifyFormat("type X = {\n"
+   "  a: Foo|Bar;\n"
+   "};");
+  verifyFormat("export type X = {\n"
+   "  a: Foo|Bar;\n"
+   "};");
 }
 
 TEST_F(FormatTestJS, ClassDeclarations) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r334415 - clang-format: [JS] strict prop init annotation.

2018-06-11 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Jun 11 09:20:13 2018
New Revision: 334415

URL: http://llvm.org/viewvc/llvm-project?rev=334415&view=rev
Log:
clang-format: [JS] strict prop init annotation.

Summary:
TypeScript uses the `!` token for strict property initialization
assertions, as in:

class X {
  strictPropAsserted!: string;
}

Previously, clang-format would wrap between the `!` and the `:` for
overly long lines. This patch fixes that by generally preventing the
wrap in that location.

Reviewers: krasimir

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D48030

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=334415&r1=334414&r2=334415&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon Jun 11 09:20:13 2018
@@ -2981,7 +2981,7 @@ bool TokenAnnotator::mustBreakBefore(con
   // We deal with this case later by detecting an entry
   // following a closing paren of this submessage.
 }
-
+
 // If this is an entry immediately following a submessage, it will be
 // preceded by a closing paren of that submessage, like in:
 // left---.  .---right
@@ -3027,6 +3027,9 @@ bool TokenAnnotator::canBreakBefore(cons
   return false;
 if (Left.is(TT_JsTypeColon))
   return true;
+// Don't wrap between ":" and "!" of a strict prop init ("field!: type;").
+if (Left.is(tok::exclaim) && Right.is(tok::colon))
+  return false;
 if (Right.is(Keywords.kw_is))
   return false;
 if (Left.is(Keywords.kw_in))

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=334415&r1=334414&r2=334415&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon Jun 11 09:20:13 2018
@@ -1540,6 +1540,15 @@ TEST_F(FormatTestJS, ClassDeclarations)
"}");
 }
 
+TEST_F(FormatTestJS, StrictPropInitWrap) {
+  const FormatStyle &Style = getGoogleJSStyleWithColumns(22);
+  verifyFormat("class X {\n"
+   "  strictPropInitField!:\n"
+   "  string;\n"
+   "}",
+   Style);
+}
+
 TEST_F(FormatTestJS, InterfaceDeclarations) {
   verifyFormat("interface I {\n"
"  x: string;\n"


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r356447 - [clang-format] [JS] Don't break between template string and tag

2019-03-19 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Mar 19 04:15:52 2019
New Revision: 356447

URL: http://llvm.org/viewvc/llvm-project?rev=356447&view=rev
Log:
[clang-format] [JS] Don't break between template string and tag

Before:
const x = veryLongIdentifier
`hello`;
After:
const x =
veryLongIdentifier`hello`;

While it's allowed to have the template string and tag identifier
separated by a line break, currently the clang-format output is not
stable when a break is forced. Additionally, disallowing a line break
makes it clear that the identifier is actually a tag for a template
string.

Patch originally by mitchellwills (thanks!).

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=356447&r1=356446&r2=356447&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Mar 19 04:15:52 2019
@@ -3171,6 +3171,11 @@ bool TokenAnnotator::canBreakBefore(cons
   return false; // must not break in "module foo { ...}"
 if (Right.is(TT_TemplateString) && Right.closesScope())
   return false;
+// Don't split tagged template literal so there is a break between the tag
+// identifier and template string.
+if (Left.is(tok::identifier) && Right.is(TT_TemplateString)) {
+  return false;
+}
 if (Left.is(TT_TemplateString) && Left.opensScope())
   return true;
   }

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=356447&r1=356446&r2=356447&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Mar 19 04:15:52 2019
@@ -1962,6 +1962,12 @@ TEST_F(FormatTestJS, NestedTemplateStrin
 TEST_F(FormatTestJS, TaggedTemplateStrings) {
   verifyFormat("var x = html``;");
   verifyFormat("yield `hello`;");
+  verifyFormat("var f = {\n"
+   "  param: longTagName`This is a ${\n"
+   "'really'} long line`\n"
+   "};",
+   "var f = {param: longTagName`This is a ${'really'} long 
line`};",
+   getGoogleJSStyleWithColumns(40));
 }
 
 TEST_F(FormatTestJS, CastSyntax) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r356449 - [clang-format] [JS] handle private members.

2019-03-19 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Mar 19 05:28:41 2019
New Revision: 356449

URL: http://llvm.org/viewvc/llvm-project?rev=356449&view=rev
Log:
[clang-format] [JS] handle private members.

Addresses PR40999 https://bugs.llvm.org/show_bug.cgi?id=40999

Private fields and methods in JavaScript would get incorrectly indented
(it sees them as preprocessor directives and hence left aligns them)

In this revision `#identifier` tokens `tok::hash->tok::identifier` are
merged into a single new token `tok::identifier` with the `#` contained
inside the TokenText.

Before:

```
class Example {
  pub = 1;

  static pub2 = "foo";
  static #priv2 = "bar";

  method() { this.#priv = 5; }

  static staticMethod() {
switch (this.#priv) {
case '1':
  break;
}
  }

  this.#privateMethod(); // infinite loop
}

static #staticPrivateMethod() {}
}
```

After this fix the code will be correctly indented

```
class Example {
  pub = 1;
  #priv = 2;

  static pub2 = "foo";
  static #priv2 = "bar";

  method() { this.#priv = 5; }

  static staticMethod() {
switch (this.#priv) {
case '1':
  #priv = 3;
  break;
}
  }

  #privateMethod() {
this.#privateMethod(); // infinite loop
  }

  static #staticPrivateMethod() {}
}
```

NOTE: There might be some JavaScript code out there which uses the C
processor to preprocess .js files
http://www.nongnu.org/espresso/js-cpp.html. It's not clear how this
revision or even private fields and methods would interact.

Patch originally by MyDeveloperDays (thanks!).

Modified:
cfe/trunk/lib/Format/FormatToken.h
cfe/trunk/lib/Format/FormatTokenLexer.cpp
cfe/trunk/lib/Format/FormatTokenLexer.h
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/FormatToken.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=356449&r1=356448&r2=356449&view=diff
==
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Tue Mar 19 05:28:41 2019
@@ -60,6 +60,7 @@ namespace format {
   TYPE(JsExponentiationEqual)  
\
   TYPE(JsFatArrow) 
\
   TYPE(JsNonNullAssertion) 
\
+  TYPE(JsPrivateIdentifier)
\
   TYPE(JsTypeColon)
\
   TYPE(JsTypeOperator) 
\
   TYPE(JsTypeOptionalQuestion) 
\

Modified: cfe/trunk/lib/Format/FormatTokenLexer.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatTokenLexer.cpp?rev=356449&r1=356448&r2=356449&view=diff
==
--- cfe/trunk/lib/Format/FormatTokenLexer.cpp (original)
+++ cfe/trunk/lib/Format/FormatTokenLexer.cpp Tue Mar 19 05:28:41 2019
@@ -95,6 +95,8 @@ void FormatTokenLexer::tryMergePreviousT
   Tokens.back()->Tok.setKind(tok::starequal);
   return;
 }
+if (tryMergeJSPrivateIdentifier())
+  return;
   }
 
   if (Style.Language == FormatStyle::LK_Java) {
@@ -120,6 +122,25 @@ bool FormatTokenLexer::tryMergeNSStringL
   Tokens.erase(Tokens.end() - 1);
   return true;
 }
+
+bool FormatTokenLexer::tryMergeJSPrivateIdentifier() {
+  // Merges #idenfier into a single identifier with the text #identifier
+  // but the token tok::identifier.
+  if (Tokens.size() < 2)
+return false;
+  auto &Hash = *(Tokens.end() - 2);
+  auto &Identifier = *(Tokens.end() - 1);
+  if (!Hash->is(tok::hash) || !Identifier->is(tok::identifier))
+return false;
+  Hash->Tok.setKind(tok::identifier);
+  Hash->TokenText =
+  StringRef(Hash->TokenText.begin(),
+Identifier->TokenText.end() - Hash->TokenText.begin());
+  Hash->ColumnWidth += Identifier->ColumnWidth;
+  Hash->Type = TT_JsPrivateIdentifier;
+  Tokens.erase(Tokens.end() - 1);
+  return true;
+}
 
 bool FormatTokenLexer::tryMergeLessLess() {
   // Merge X,less,less,Y into X,lessless,Y unless X or Y is less.

Modified: cfe/trunk/lib/Format/FormatTokenLexer.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatTokenLexer.h?rev=356449&r1=356448&r2=356449&view=diff
==
--- cfe/trunk/lib/Format/FormatTokenLexer.h (original)
+++ cfe/trunk/lib/Format/FormatTokenLexer.h Tue Mar 19 05:28:41 2019
@@ -48,6 +48,7 @@ private:
 
   bool tryMergeLessLess();
   bool tryMergeNSStringLiteral();
+  bool tryMergeJSPrivateIdentifier();
 
   bool tryMergeTokens(ArrayRef Kinds, TokenType NewType);
 

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=356449&r1=356448&r2=356449&view=diff
=

r343080 - clang-format: [JS] space after parameter naming.

2018-09-26 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Wed Sep 26 01:28:33 2018
New Revision: 343080

URL: http://llvm.org/viewvc/llvm-project?rev=343080&view=rev
Log:
clang-format: [JS] space after parameter naming.

Summary:
Previously:
foo(/*bar=*/baz);

Now:
foo(/*bar=*/ baz);

The run-in parameter naming comment is not intended in JS.

Reviewers: mboehme

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D52535

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=343080&r1=343079&r2=343080&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Wed Sep 26 01:28:33 2018
@@ -2517,7 +2517,9 @@ bool TokenAnnotator::spaceRequiredBetwee
Right.MatchingParen->BlockKind != BK_Block))
 return !Style.Cpp11BracedListStyle;
   if (Left.is(TT_BlockComment))
-return !Left.TokenText.endswith("=*/");
+// No whitespace in x(/*foo=*/1), except for JavaScript.
+return Style.Language == FormatStyle::LK_JavaScript ||
+   !Left.TokenText.endswith("=*/");
   if (Right.is(tok::l_paren)) {
 if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) ||
 (Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=343080&r1=343079&r2=343080&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Wed Sep 26 01:28:33 2018
@@ -2304,5 +2304,9 @@ TEST_F(FormatTestJS, AddsLastLinePenalty
  "};"));
 }
 
+TEST_F(FormatTestJS, ParameterNamingComment) {
+  verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
+}
+
 } // end namespace tooling
 } // end namespace clang


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r343179 - clang-format: [JS] conditional types.

2018-09-26 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Wed Sep 26 23:48:13 2018
New Revision: 343179

URL: http://llvm.org/viewvc/llvm-project?rev=343179&view=rev
Log:
clang-format: [JS] conditional types.

Summary:
This change adds some rudimentary support for conditional types.
Specifically it avoids breaking before `extends` and `infer` keywords,
which are subject to Automatic Semicolon Insertion, so breaking before
them creates incorrect syntax.

The actual formatting of the type expression is odd, but there is as of
yet no clear idea on how to format these.

See 
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types.

Reviewers: krasimir

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D52536

Modified:
cfe/trunk/lib/Format/FormatToken.h
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/FormatToken.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=343179&r1=343178&r2=343179&view=diff
==
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Wed Sep 26 23:48:13 2018
@@ -680,6 +680,7 @@ struct AdditionalKeywords {
 kw_function = &IdentTable.get("function");
 kw_get = &IdentTable.get("get");
 kw_import = &IdentTable.get("import");
+kw_infer = &IdentTable.get("infer");
 kw_is = &IdentTable.get("is");
 kw_let = &IdentTable.get("let");
 kw_module = &IdentTable.get("module");
@@ -751,6 +752,7 @@ struct AdditionalKeywords {
   IdentifierInfo *kw_function;
   IdentifierInfo *kw_get;
   IdentifierInfo *kw_import;
+  IdentifierInfo *kw_infer;
   IdentifierInfo *kw_is;
   IdentifierInfo *kw_let;
   IdentifierInfo *kw_module;

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=343179&r1=343178&r2=343179&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Wed Sep 26 23:48:13 2018
@@ -3088,6 +3088,12 @@ bool TokenAnnotator::canBreakBefore(cons
   return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;
 if (Right.is(Keywords.kw_as))
   return false; // must not break before as in 'x as type' casts
+if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_infer)) {
+  // extends and infer can appear as keywords in conditional types:
+  //   
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types
+  // do not break before them, as the expressions are subject to ASI.
+  return false;
+}
 if (Left.is(Keywords.kw_as))
   return true;
 if (Left.is(TT_JsNonNullAssertion))

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=343179&r1=343178&r2=343179&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Wed Sep 26 23:48:13 2018
@@ -2308,5 +2308,14 @@ TEST_F(FormatTestJS, ParameterNamingComm
   verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
 }
 
+TEST_F(FormatTestJS, ConditionalTypes) {
+  // Formatting below is not necessarily intentional, this just ensures that
+  // clang-format does not break the code.
+  verifyFormat( // wrap
+  "type UnionToIntersection =\n"
+  "(U extends any ? (k: U) => void :\n"
+  " never) extends((k: infer I) => void) ? I : 
never;");
+}
+
 } // end namespace tooling
 } // end namespace clang


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r311988 - clang-format: [JS] simplify template string wrapping.

2017-08-29 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Aug 29 01:30:07 2017
New Revision: 311988

URL: http://llvm.org/viewvc/llvm-project?rev=311988&view=rev
Log:
clang-format: [JS] simplify template string wrapping.

Summary:
Previously, clang-format would try to wrap template string substitutions
by indenting relative to the openening `${`. This helped with
indenting structured strings, such as strings containing HTML, as the
substitutions would be aligned according to the structure of the string.

However it turns out that the overwhelming majority of template string +
substitution usages are for substitutions into non-structured strings,
e.g. URLs or just plain messages. For these situations, clang-format
would often produce very ugly indents, in particular for strings
containing no line breaks:

return `${file}(${
row
  },${
  col
}): `;

This change makes clang-format indent template string substitutions as
if they were string concatenation operations. It wraps +4 on overlong
lines and keeps all operands on the same line:

return `${file}(${
row},${col}): `;

While this breaks some lexical continuity between the `${` and `row}`
here, the overall effects are still a huge improvement, and users can
still manually break the string using `+` if desired.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D37142

Modified:
cfe/trunk/lib/Format/ContinuationIndenter.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=311988&r1=311987&r2=311988&view=diff
==
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Tue Aug 29 01:30:07 2017
@@ -661,9 +661,7 @@ unsigned ContinuationIndenter::addTokenO
   // before the corresponding } or ].
   if (PreviousNonComment &&
   (PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
-   opensProtoMessageField(*PreviousNonComment, Style) ||
-   (PreviousNonComment->is(TT_TemplateString) &&
-PreviousNonComment->opensScope(
+   opensProtoMessageField(*PreviousNonComment, Style)))
 State.Stack.back().BreakBeforeClosingBrace = true;
 
   if (State.Stack.back().AvoidBinPacking) {
@@ -925,11 +923,6 @@ unsigned ContinuationIndenter::moveState
 
   moveStatePastFakeLParens(State, Newline);
   moveStatePastScopeCloser(State);
-  if (Current.is(TT_TemplateString) && Current.opensScope())
-State.Stack.back().LastSpace =
-(Current.IsMultiline ? Current.LastLineColumnWidth
- : State.Column + Current.ColumnWidth) -
-strlen("${");
   bool CanBreakProtrudingToken = !State.Stack.back().NoLineBreak &&
  !State.Stack.back().NoLineBreakInOperand;
   moveStatePastScopeOpener(State, Newline);
@@ -1101,18 +1094,6 @@ void ContinuationIndenter::moveStatePast
   LastSpace = std::max(LastSpace, State.Stack.back().Indent);
 }
 
-// JavaScript template strings are special as we always want to indent
-// nested expressions relative to the ${}. Otherwise, this can create quite
-// a mess.
-if (Current.is(TT_TemplateString)) {
-  unsigned Column = Current.IsMultiline
-? Current.LastLineColumnWidth
-: State.Column + Current.ColumnWidth;
-  NewIndent = Column;
-  LastSpace = Column;
-  NestedBlockIndent = Column;
-}
-
 bool EndsInComma =
 Current.MatchingParen &&
 Current.MatchingParen->getPreviousNonComment() &&

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=311988&r1=311987&r2=311988&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Aug 29 01:30:07 2017
@@ -1793,32 +1793,28 @@ TEST_F(FormatTestJS, TemplateStrings) {
   verifyFormat("var x = someFunction(`${})`)  //\n"
".oon();");
   verifyFormat("var x = someFunction(`${}${\n"
-   "   a(  //\n"
-   "   a)\n"
-   " })`);");
+   "a(  //\n"
+   "a)})`);");
 }
 
 TEST_F(FormatTestJS, TemplateStringMultiLineExpression) {
   verifyFormat("var f = `aa: ${\

r312918 - clang-format: [JS] wrap and indent `goog.setTestOnly` calls.

2017-09-11 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Sep 11 08:22:52 2017
New Revision: 312918

URL: http://llvm.org/viewvc/llvm-project?rev=312918&view=rev
Log:
clang-format: [JS] wrap and indent `goog.setTestOnly` calls.

Summary:
While `goog.setTestOnly` usually appears in the imports section of a file, it is
not actually an import, and also usually doesn't take long parameters (nor
namespaces as a parameter, it's a description/message that should be wrapped).

This fixes a regression where a `goog.setTestOnly` call nested in a function was
not wrapped.

Reviewers: djasper

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D37685

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=312918&r1=312917&r2=312918&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon Sep 11 08:22:52 2017
@@ -960,7 +960,6 @@ private:
Tok.Next->Next && (Tok.Next->Next->TokenText == "module" ||
   Tok.Next->Next->TokenText == "provide" ||
   Tok.Next->Next->TokenText == "require" ||
-  Tok.Next->Next->TokenText == "setTestOnly" ||
   Tok.Next->Next->TokenText == "forwardDeclare") &&
Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren);
   }

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=312918&r1=312917&r2=312918&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon Sep 11 08:22:52 2017
@@ -558,8 +558,6 @@ TEST_F(FormatTestJS, GoogModules) {
getGoogleJSStyleWithColumns(40));
   verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
getGoogleJSStyleWithColumns(40));
-  verifyFormat("goog.setTestOnly('this.is.really.absurdly.long');",
-   getGoogleJSStyleWithColumns(40));
   verifyFormat("goog.forwardDeclare('this.is.really.absurdly.long');",
getGoogleJSStyleWithColumns(40));
 
@@ -567,6 +565,12 @@ TEST_F(FormatTestJS, GoogModules) {
   verifyFormat(
   "var MyLongClassName =\n"
   "
goog.module.get('my.long.module.name.followedBy.MyLongClassName');");
+  verifyFormat("function a() {\n"
+   "  goog.setTestOnly();\n"
+   "}\n",
+   "function a() {\n"
+   "goog.setTestOnly();\n"
+   "}\n");
 }
 
 TEST_F(FormatTestJS, FormatsNamespaces) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r350516 - clang-format: [JS] support goog.requireType.

2019-01-07 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Jan  7 05:12:50 2019
New Revision: 350516

URL: http://llvm.org/viewvc/llvm-project?rev=350516&view=rev
Log:
clang-format: [JS] support goog.requireType.

Summary:
It's a new primitive for importing symbols, and should be treated like
the (previously handled) `goog.require` and `goog.forwardDeclare`.

Reviewers: krasimir

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D56385

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=350516&r1=350515&r2=350516&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon Jan  7 05:12:50 2019
@@ -1123,6 +1123,7 @@ private:
(Tok.Next->Next->TokenText == "module" ||
 Tok.Next->Next->TokenText == "provide" ||
 Tok.Next->Next->TokenText == "require" ||
+Tok.Next->Next->TokenText == "requireType" ||
 Tok.Next->Next->TokenText == "forwardDeclare") &&
Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren);
   }

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=350516&r1=350515&r2=350516&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon Jan  7 05:12:50 2019
@@ -600,6 +600,8 @@ TEST_F(FormatTestJS, GoogModules) {
getGoogleJSStyleWithColumns(40));
   verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
getGoogleJSStyleWithColumns(40));
+  verifyFormat("const X = goog.requireType('this.is.really.absurdly.long');",
+   getGoogleJSStyleWithColumns(40));
   verifyFormat("goog.forwardDeclare('this.is.really.absurdly.long');",
getGoogleJSStyleWithColumns(40));
 


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 146d685 - clang-format: [JS] detect C++ keywords.

2020-04-03 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2020-04-03T14:23:56+02:00
New Revision: 146d685cd657399a4698015f16cc5910cc828728

URL: 
https://github.com/llvm/llvm-project/commit/146d685cd657399a4698015f16cc5910cc828728
DIFF: 
https://github.com/llvm/llvm-project/commit/146d685cd657399a4698015f16cc5910cc828728.diff

LOG: clang-format: [JS] detect C++ keywords.

Summary:
C++ defines a number of keywords that are regular identifiers in
JavaScript, e.g. `concept`:

const concept = 1; // legit JS

This change expands the existing `IsJavaScriptIdentifier(Tok)` function
to return false for C++ keywords that aren't keywords in JS.

Reviewers: krasimir

Subscribers: jfb, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D77311

Added: 


Modified: 
clang/lib/Format/FormatToken.h
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 10a5f0e96f96..48ec7602c21c 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -910,9 +910,64 @@ struct AdditionalKeywords {
   /// Returns \c true if \p Tok is a true JavaScript identifier, returns
   /// \c false if it is a keyword or a pseudo keyword.
   bool IsJavaScriptIdentifier(const FormatToken &Tok) const {
-return Tok.is(tok::identifier) &&
-   JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==
-   JsExtraKeywords.end();
+// Based on the list of JavaScript & TypeScript keywords here:
+// 
https://github.com/microsoft/TypeScript/blob/master/src/compiler/scanner.ts#L74
+switch (Tok.Tok.getKind()) {
+case tok::kw_break:
+case tok::kw_case:
+case tok::kw_catch:
+case tok::kw_class:
+case tok::kw_continue:
+case tok::kw_const:
+case tok::kw_default:
+case tok::kw_delete:
+case tok::kw_do:
+case tok::kw_else:
+case tok::kw_enum:
+case tok::kw_export:
+case tok::kw_false:
+case tok::kw_for:
+case tok::kw_if:
+case tok::kw_import:
+case tok::kw_module:
+case tok::kw_new:
+case tok::kw_private:
+case tok::kw_protected:
+case tok::kw_public:
+case tok::kw_return:
+case tok::kw_static:
+case tok::kw_switch:
+case tok::kw_this:
+case tok::kw_throw:
+case tok::kw_true:
+case tok::kw_try:
+case tok::kw_typeof:
+case tok::kw_void:
+case tok::kw_while:
+  // These are JS keywords that are lexed by LLVM/clang as keywords.
+  return false;
+case tok::identifier:
+  // For identifiers, make sure they are true identifiers, excluding the
+  // JavaScript pseudo-keywords (not lexed by LLVM/clang as keywords).
+  return JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==
+ JsExtraKeywords.end();
+default:
+  // Other keywords are handled in the switch below, to avoid problems due
+  // to duplicate case labels when using the #include trick.
+  break;
+}
+
+switch (Tok.Tok.getKind()) {
+  // Handle C++ keywords not included above: these are all JS identifiers.
+#define KEYWORD(X, Y) case tok::kw_##X:
+#include "clang/Basic/TokenKinds.def"
+  // #undef KEYWORD is not needed -- it's #undef-ed at the end of
+  // TokenKinds.def
+  return true;
+default:
+  // All other tokens (punctuation etc) are not JS identifiers.
+  return false;
+}
   }
 
   /// Returns \c true if \p Tok is a C# keyword, returns

diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index a3cd4f42f8f8..029741c3dce7 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1522,9 +1522,9 @@ class AnnotatingParser {
 if (Style.Language == FormatStyle::LK_JavaScript) {
   if (Current.is(tok::exclaim)) {
 if (Current.Previous &&
-(Current.Previous->isOneOf(tok::identifier, tok::kw_namespace,
-   tok::r_paren, tok::r_square,
-   tok::r_brace) ||
+(Keywords.IsJavaScriptIdentifier(*Current.Previous) ||
+ Current.Previous->isOneOf(tok::kw_namespace, tok::r_paren,
+   tok::r_square, tok::r_brace) ||
  Current.Previous->Tok.isLiteral())) {
   Current.Type = TT_JsNonNullAssertion;
   return;
@@ -3070,10 +3070,8 @@ bool TokenAnnotator::spaceRequiredBefore(const 
AnnotatedLine &Line,
 (Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
   return false;
 // In tagged template literals ("html`bar baz`"), there is no space between
-// the tag identifier and the template string. getIdentifierInfo makes sure
-// that the identifier is not a pseudo keyword like `yield`, either.
-if (Left.is(tok::identifier) && Keywords.IsJavaScriptIdentifier(Lef

[clang] 9220150 - clang-format: [JS] handle pseudo-keywords.

2020-04-06 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2020-04-06T17:13:04+02:00
New Revision: 92201505cdecd8ba5795f5e33821c49dc57f0816

URL: 
https://github.com/llvm/llvm-project/commit/92201505cdecd8ba5795f5e33821c49dc57f0816
DIFF: 
https://github.com/llvm/llvm-project/commit/92201505cdecd8ba5795f5e33821c49dc57f0816.diff

LOG: clang-format: [JS] handle pseudo-keywords.

Summary:
The previous change in https://reviews.llvm.org/D77311 attempted to
detect more C++ keywords. However it also precisely detected all
JavaScript keywords. That's generally correct, but many JavaScripy
keywords, e.g. `get`, are so-called pseudo-keywords. They can be used in
positions where a keyword would never be legal, e.g. in a dotted
expression:

x.type;  // type is a pseudo-keyword, but can be used here.
x.get;   // same for get etc.

This change introduces an additional parameter to
`IsJavaScriptIdentifier`, allowing clients to toggle whether they want
to allow `IdentifierName` tokens, i.e. pseudo-keywords.

Reviewers: krasimir

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D77548

Added: 


Modified: 
clang/lib/Format/FormatToken.h
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 48ec7602c21c..c67cf192ab1f 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -909,7 +909,11 @@ struct AdditionalKeywords {
 
   /// Returns \c true if \p Tok is a true JavaScript identifier, returns
   /// \c false if it is a keyword or a pseudo keyword.
-  bool IsJavaScriptIdentifier(const FormatToken &Tok) const {
+  /// If \c AcceptIdentifierName is true, returns true not only for keywords,
+  // but also for IdentifierName tokens (aka pseudo-keywords), such as
+  // ``yield``.
+  bool IsJavaScriptIdentifier(const FormatToken &Tok,
+  bool AcceptIdentifierName = true) const {
 // Based on the list of JavaScript & TypeScript keywords here:
 // 
https://github.com/microsoft/TypeScript/blob/master/src/compiler/scanner.ts#L74
 switch (Tok.Tok.getKind()) {
@@ -946,11 +950,14 @@ struct AdditionalKeywords {
 case tok::kw_while:
   // These are JS keywords that are lexed by LLVM/clang as keywords.
   return false;
-case tok::identifier:
+case tok::identifier: {
   // For identifiers, make sure they are true identifiers, excluding the
   // JavaScript pseudo-keywords (not lexed by LLVM/clang as keywords).
-  return JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==
- JsExtraKeywords.end();
+  bool IsPseudoKeyword =
+  JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) !=
+  JsExtraKeywords.end();
+  return AcceptIdentifierName || !IsPseudoKeyword;
+}
 default:
   // Other keywords are handled in the switch below, to avoid problems due
   // to duplicate case labels when using the #include trick.

diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 029741c3dce7..8204623645a4 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1522,9 +1522,11 @@ class AnnotatingParser {
 if (Style.Language == FormatStyle::LK_JavaScript) {
   if (Current.is(tok::exclaim)) {
 if (Current.Previous &&
-(Keywords.IsJavaScriptIdentifier(*Current.Previous) ||
- Current.Previous->isOneOf(tok::kw_namespace, tok::r_paren,
-   tok::r_square, tok::r_brace) ||
+(Keywords.IsJavaScriptIdentifier(
+ *Current.Previous, /* AcceptIdentifierName= */ true) ||
+ Current.Previous->isOneOf(
+ tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace,
+ Keywords.kw_type, Keywords.kw_get, Keywords.kw_set) ||
  Current.Previous->Tok.isLiteral())) {
   Current.Type = TT_JsNonNullAssertion;
   return;
@@ -3071,7 +3073,9 @@ bool TokenAnnotator::spaceRequiredBefore(const 
AnnotatedLine &Line,
   return false;
 // In tagged template literals ("html`bar baz`"), there is no space between
 // the tag identifier and the template string.
-if (Keywords.IsJavaScriptIdentifier(Left) && Right.is(TT_TemplateString))
+if (Keywords.IsJavaScriptIdentifier(Left,
+/* AcceptIdentifierName= */ false) &&
+Right.is(TT_TemplateString))
   return false;
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))

diff  --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index 3fd795c526b1..eadea35f051a 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -2412,6 +2412,11 @

[PATCH] D24708: clang-format: [JS] Fix line breaks before comments when sorting imports.

2016-09-18 Thread Martin Probst via cfe-commits
mprobst created this revision.
mprobst added a reviewer: djasper.
mprobst added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

Previously, clang-format would always insert an additional line break after the
import block if the main body started with a comment, due to loosing track of
the first non-import line.

https://reviews.llvm.org/D24708

Files:
  lib/Format/SortJavaScriptImports.cpp
  unittests/Format/SortImportsTestJS.cpp

Index: unittests/Format/SortImportsTestJS.cpp
===
--- unittests/Format/SortImportsTestJS.cpp
+++ unittests/Format/SortImportsTestJS.cpp
@@ -121,6 +121,16 @@
  "import {sym} from 'b';  // from //foo:bar\n"
  "// A very important import follows.\n"
  "import {sym} from 'a';  /* more comments */\n");
+  verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n",
+ "import {sym} from 'b';\n"
+ "import {sym} from 'a';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n");
 }
 
 TEST_F(SortImportsTestJS, SortStar) {
Index: lib/Format/SortJavaScriptImports.cpp
===
--- lib/Format/SortJavaScriptImports.cpp
+++ lib/Format/SortJavaScriptImports.cpp
@@ -293,14 +293,19 @@
 // of the import that immediately follows them by using the previously
 // set Start.
 Start = Line->First->Tok.getLocation();
-  if (!Current)
-continue; // Only comments on this line.
+  if (!Current) {
+// Only comments on this line. Could be the first non-import line.
+FirstNonImportLine = Line;
+continue;
+  }
   JsModuleReference Reference;
   Reference.Range.setBegin(Start);
   if (!parseModuleReference(Keywords, Reference)) {
-FirstNonImportLine = Line;
+if (!FirstNonImportLine)
+  FirstNonImportLine = Line; // if no comment before.
 break;
   }
+  FirstNonImportLine = nullptr;
   AnyImportAffected = AnyImportAffected || Line->Affected;
   Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
   DEBUG({


Index: unittests/Format/SortImportsTestJS.cpp
===
--- unittests/Format/SortImportsTestJS.cpp
+++ unittests/Format/SortImportsTestJS.cpp
@@ -121,6 +121,16 @@
  "import {sym} from 'b';  // from //foo:bar\n"
  "// A very important import follows.\n"
  "import {sym} from 'a';  /* more comments */\n");
+  verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n",
+ "import {sym} from 'b';\n"
+ "import {sym} from 'a';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n");
 }
 
 TEST_F(SortImportsTestJS, SortStar) {
Index: lib/Format/SortJavaScriptImports.cpp
===
--- lib/Format/SortJavaScriptImports.cpp
+++ lib/Format/SortJavaScriptImports.cpp
@@ -293,14 +293,19 @@
 // of the import that immediately follows them by using the previously
 // set Start.
 Start = Line->First->Tok.getLocation();
-  if (!Current)
-continue; // Only comments on this line.
+  if (!Current) {
+// Only comments on this line. Could be the first non-import line.
+FirstNonImportLine = Line;
+continue;
+  }
   JsModuleReference Reference;
   Reference.Range.setBegin(Start);
   if (!parseModuleReference(Keywords, Reference)) {
-FirstNonImportLine = Line;
+if (!FirstNonImportLine)
+  FirstNonImportLine = Line; // if no comment before.
 break;
   }
+  FirstNonImportLine = nullptr;
   AnyImportAffected = AnyImportAffected || Line->Affected;
   Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
   DEBUG({
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r281856 - clang-format: [JS] ASI insertion after boolean literals.

2016-09-18 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Sun Sep 18 12:21:52 2016
New Revision: 281856

URL: http://llvm.org/viewvc/llvm-project?rev=281856&view=rev
Log:
clang-format: [JS] ASI insertion after boolean literals.

Summary:
Before when a semicolon was missing after a boolean literal:
a = true
return 1;

clang-format would parse this as one line and format as:
a = true return 1;

It turns out that C++ does not consider `true` and `false` to be literals, we
have to check for that explicitly.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D24574

Modified:
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=281856&r1=281855&r2=281856&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Sun Sep 18 12:21:52 2016
@@ -681,7 +681,9 @@ static bool mustBeJSIdent(const Addition
 
 static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,
  const FormatToken *FormatTok) {
-  return FormatTok->Tok.isLiteral() || mustBeJSIdent(Keywords, FormatTok);
+  return FormatTok->Tok.isLiteral() ||
+ FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||
+ mustBeJSIdent(Keywords, FormatTok);
 }
 
 // isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=281856&r1=281855&r2=281856&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Sun Sep 18 12:21:52 2016
@@ -774,6 +774,18 @@ TEST_F(FormatTestJS, AutomaticSemicolonI
   "String");
   verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n"
   "  bar) {}");
+  verifyFormat("a = true\n"
+   "return 1",
+   "a = true\n"
+   "  return   1");
+  verifyFormat("a = 's'\n"
+   "return 1",
+   "a = 's'\n"
+   "  return   1");
+  verifyFormat("a = null\n"
+   "return 1",
+   "a = null\n"
+   "  return   1");
 }
 
 TEST_F(FormatTestJS, ClosureStyleCasts) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24574: clang-format: [JS] ASI insertion after boolean literals.

2016-09-18 Thread Martin Probst via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL281856: clang-format: [JS] ASI insertion after boolean 
literals. (authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D24574?vs=71385&id=71755#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D24574

Files:
  cfe/trunk/lib/Format/UnwrappedLineParser.cpp
  cfe/trunk/unittests/Format/FormatTestJS.cpp

Index: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
===
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp
@@ -681,7 +681,9 @@
 
 static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,
  const FormatToken *FormatTok) {
-  return FormatTok->Tok.isLiteral() || mustBeJSIdent(Keywords, FormatTok);
+  return FormatTok->Tok.isLiteral() ||
+ FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||
+ mustBeJSIdent(Keywords, FormatTok);
 }
 
 // isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -774,6 +774,18 @@
   "String");
   verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n"
   "  bar) {}");
+  verifyFormat("a = true\n"
+   "return 1",
+   "a = true\n"
+   "  return   1");
+  verifyFormat("a = 's'\n"
+   "return 1",
+   "a = 's'\n"
+   "  return   1");
+  verifyFormat("a = null\n"
+   "return 1",
+   "a = null\n"
+   "  return   1");
 }
 
 TEST_F(FormatTestJS, ClosureStyleCasts) {


Index: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
===
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp
@@ -681,7 +681,9 @@
 
 static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,
  const FormatToken *FormatTok) {
-  return FormatTok->Tok.isLiteral() || mustBeJSIdent(Keywords, FormatTok);
+  return FormatTok->Tok.isLiteral() ||
+ FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||
+ mustBeJSIdent(Keywords, FormatTok);
 }
 
 // isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -774,6 +774,18 @@
   "String");
   verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n"
   "  bar) {}");
+  verifyFormat("a = true\n"
+   "return 1",
+   "a = true\n"
+   "  return   1");
+  verifyFormat("a = 's'\n"
+   "return 1",
+   "a = 's'\n"
+   "  return   1");
+  verifyFormat("a = null\n"
+   "return 1",
+   "a = null\n"
+   "  return   1");
 }
 
 TEST_F(FormatTestJS, ClosureStyleCasts) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r281857 - clang-format: [JS] Do not wrap taze annotation comments.

2016-09-18 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Sun Sep 18 12:33:51 2016
New Revision: 281857

URL: http://llvm.org/viewvc/llvm-project?rev=281857&view=rev
Log:
clang-format: [JS] Do not wrap taze annotation comments.

Summary:
`// taze: ... from ...` comments are used help tools where a
specific global symbol comes from.

Before:
// taze: many, different, symbols from
// 'some_long_location_here'

After:
// taze: many, different, symbols from 'some_long_location_here'

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D24477

Modified:
cfe/trunk/lib/Format/Format.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/Format.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=281857&r1=281856&r2=281857&view=diff
==
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Sun Sep 18 12:33:51 2016
@@ -613,7 +613,7 @@ FormatStyle getGoogleStyle(FormatStyle::
 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
 GoogleStyle.BreakBeforeTernaryOperators = false;
-GoogleStyle.CommentPragmas = "@(export|requirecss|return|see|visibility) ";
+GoogleStyle.CommentPragmas = 
"(taze:|@(export|requirecss|return|see|visibility)) ";
 GoogleStyle.MaxEmptyLinesToKeep = 3;
 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
 GoogleStyle.SpacesInContainerLiterals = false;

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=281857&r1=281856&r2=281857&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Sun Sep 18 12:33:51 2016
@@ -1444,5 +1444,11 @@ TEST_F(FormatTestJS, Conditional) {
"}");
 }
 
+TEST_F(FormatTestJS, ImportComments) {
+  verifyFormat("import {x} from 'x';  // from some location",
+   getGoogleJSStyleWithColumns(25));
+  verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10));
+}
+
 } // end namespace tooling
 } // end namespace clang


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24477: clang-format: [JS] Do not wrap taze: IWYU comments

2016-09-18 Thread Martin Probst via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL281857: clang-format: [JS] Do not wrap taze annotation 
comments. (authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D24477?vs=71189&id=71756#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D24477

Files:
  cfe/trunk/lib/Format/Format.cpp
  cfe/trunk/unittests/Format/FormatTestJS.cpp

Index: cfe/trunk/lib/Format/Format.cpp
===
--- cfe/trunk/lib/Format/Format.cpp
+++ cfe/trunk/lib/Format/Format.cpp
@@ -613,7 +613,7 @@
 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
 GoogleStyle.BreakBeforeTernaryOperators = false;
-GoogleStyle.CommentPragmas = "@(export|requirecss|return|see|visibility) ";
+GoogleStyle.CommentPragmas = 
"(taze:|@(export|requirecss|return|see|visibility)) ";
 GoogleStyle.MaxEmptyLinesToKeep = 3;
 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
 GoogleStyle.SpacesInContainerLiterals = false;
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -1444,5 +1444,11 @@
"}");
 }
 
+TEST_F(FormatTestJS, ImportComments) {
+  verifyFormat("import {x} from 'x';  // from some location",
+   getGoogleJSStyleWithColumns(25));
+  verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10));
+}
+
 } // end namespace tooling
 } // end namespace clang


Index: cfe/trunk/lib/Format/Format.cpp
===
--- cfe/trunk/lib/Format/Format.cpp
+++ cfe/trunk/lib/Format/Format.cpp
@@ -613,7 +613,7 @@
 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
 GoogleStyle.BreakBeforeTernaryOperators = false;
-GoogleStyle.CommentPragmas = "@(export|requirecss|return|see|visibility) ";
+GoogleStyle.CommentPragmas = "(taze:|@(export|requirecss|return|see|visibility)) ";
 GoogleStyle.MaxEmptyLinesToKeep = 3;
 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
 GoogleStyle.SpacesInContainerLiterals = false;
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -1444,5 +1444,11 @@
"}");
 }
 
+TEST_F(FormatTestJS, ImportComments) {
+  verifyFormat("import {x} from 'x';  // from some location",
+   getGoogleJSStyleWithColumns(25));
+  verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10));
+}
+
 } // end namespace tooling
 } // end namespace clang
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r281888 - clang-format: [JS] Fix line breaks before comments when sorting imports.

2016-09-19 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Sep 19 02:02:34 2016
New Revision: 281888

URL: http://llvm.org/viewvc/llvm-project?rev=281888&view=rev
Log:
clang-format: [JS] Fix line breaks before comments when sorting imports.

Summary:
Previously, clang-format would always insert an additional line break after the
import block if the main body started with a comment, due to loosing track of
the first non-import line.

Reviewers: djasper

Subscribers: cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D24708

Modified:
cfe/trunk/lib/Format/SortJavaScriptImports.cpp
cfe/trunk/unittests/Format/SortImportsTestJS.cpp

Modified: cfe/trunk/lib/Format/SortJavaScriptImports.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/SortJavaScriptImports.cpp?rev=281888&r1=281887&r2=281888&view=diff
==
--- cfe/trunk/lib/Format/SortJavaScriptImports.cpp (original)
+++ cfe/trunk/lib/Format/SortJavaScriptImports.cpp Mon Sep 19 02:02:34 2016
@@ -293,14 +293,19 @@ private:
 // of the import that immediately follows them by using the previously
 // set Start.
 Start = Line->First->Tok.getLocation();
-  if (!Current)
-continue; // Only comments on this line.
+  if (!Current) {
+// Only comments on this line. Could be the first non-import line.
+FirstNonImportLine = Line;
+continue;
+  }
   JsModuleReference Reference;
   Reference.Range.setBegin(Start);
   if (!parseModuleReference(Keywords, Reference)) {
-FirstNonImportLine = Line;
+if (!FirstNonImportLine)
+  FirstNonImportLine = Line; // if no comment before.
 break;
   }
+  FirstNonImportLine = nullptr;
   AnyImportAffected = AnyImportAffected || Line->Affected;
   Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
   DEBUG({

Modified: cfe/trunk/unittests/Format/SortImportsTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/SortImportsTestJS.cpp?rev=281888&r1=281887&r2=281888&view=diff
==
--- cfe/trunk/unittests/Format/SortImportsTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/SortImportsTestJS.cpp Mon Sep 19 02:02:34 2016
@@ -121,6 +121,16 @@ TEST_F(SortImportsTestJS, Comments) {
  "import {sym} from 'b';  // from //foo:bar\n"
  "// A very important import follows.\n"
  "import {sym} from 'a';  /* more comments */\n");
+  verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n",
+ "import {sym} from 'b';\n"
+ "import {sym} from 'a';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n");
 }
 
 TEST_F(SortImportsTestJS, SortStar) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24708: clang-format: [JS] Fix line breaks before comments when sorting imports.

2016-09-19 Thread Martin Probst via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL281888: clang-format: [JS] Fix line breaks before comments 
when sorting imports. (authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D24708?vs=71754&id=71772#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D24708

Files:
  cfe/trunk/lib/Format/SortJavaScriptImports.cpp
  cfe/trunk/unittests/Format/SortImportsTestJS.cpp

Index: cfe/trunk/lib/Format/SortJavaScriptImports.cpp
===
--- cfe/trunk/lib/Format/SortJavaScriptImports.cpp
+++ cfe/trunk/lib/Format/SortJavaScriptImports.cpp
@@ -293,14 +293,19 @@
 // of the import that immediately follows them by using the previously
 // set Start.
 Start = Line->First->Tok.getLocation();
-  if (!Current)
-continue; // Only comments on this line.
+  if (!Current) {
+// Only comments on this line. Could be the first non-import line.
+FirstNonImportLine = Line;
+continue;
+  }
   JsModuleReference Reference;
   Reference.Range.setBegin(Start);
   if (!parseModuleReference(Keywords, Reference)) {
-FirstNonImportLine = Line;
+if (!FirstNonImportLine)
+  FirstNonImportLine = Line; // if no comment before.
 break;
   }
+  FirstNonImportLine = nullptr;
   AnyImportAffected = AnyImportAffected || Line->Affected;
   Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
   DEBUG({
Index: cfe/trunk/unittests/Format/SortImportsTestJS.cpp
===
--- cfe/trunk/unittests/Format/SortImportsTestJS.cpp
+++ cfe/trunk/unittests/Format/SortImportsTestJS.cpp
@@ -121,6 +121,16 @@
  "import {sym} from 'b';  // from //foo:bar\n"
  "// A very important import follows.\n"
  "import {sym} from 'a';  /* more comments */\n");
+  verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n",
+ "import {sym} from 'b';\n"
+ "import {sym} from 'a';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n");
 }
 
 TEST_F(SortImportsTestJS, SortStar) {


Index: cfe/trunk/lib/Format/SortJavaScriptImports.cpp
===
--- cfe/trunk/lib/Format/SortJavaScriptImports.cpp
+++ cfe/trunk/lib/Format/SortJavaScriptImports.cpp
@@ -293,14 +293,19 @@
 // of the import that immediately follows them by using the previously
 // set Start.
 Start = Line->First->Tok.getLocation();
-  if (!Current)
-continue; // Only comments on this line.
+  if (!Current) {
+// Only comments on this line. Could be the first non-import line.
+FirstNonImportLine = Line;
+continue;
+  }
   JsModuleReference Reference;
   Reference.Range.setBegin(Start);
   if (!parseModuleReference(Keywords, Reference)) {
-FirstNonImportLine = Line;
+if (!FirstNonImportLine)
+  FirstNonImportLine = Line; // if no comment before.
 break;
   }
+  FirstNonImportLine = nullptr;
   AnyImportAffected = AnyImportAffected || Line->Affected;
   Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
   DEBUG({
Index: cfe/trunk/unittests/Format/SortImportsTestJS.cpp
===
--- cfe/trunk/unittests/Format/SortImportsTestJS.cpp
+++ cfe/trunk/unittests/Format/SortImportsTestJS.cpp
@@ -121,6 +121,16 @@
  "import {sym} from 'b';  // from //foo:bar\n"
  "// A very important import follows.\n"
  "import {sym} from 'a';  /* more comments */\n");
+  verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n",
+ "import {sym} from 'b';\n"
+ "import {sym} from 'a';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n");
 }
 
 TEST_F(SortImportsTestJS, SortStar) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D24767: clang-format: [JS] do not wrapp @returns tags.

2016-09-20 Thread Martin Probst via cfe-commits
mprobst created this revision.
mprobst added a reviewer: djasper.
mprobst added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

@returns is incorrect code, the standard is @return. However wrapping it can 
still confuse users.

https://reviews.llvm.org/D24767

Files:
  lib/Format/Format.cpp

Index: lib/Format/Format.cpp
===
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -613,7 +613,8 @@
 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
 GoogleStyle.BreakBeforeTernaryOperators = false;
-GoogleStyle.CommentPragmas = 
"(taze:|@(export|requirecss|return|see|visibility)) ";
+GoogleStyle.CommentPragmas =
+"(taze:|@(export|requirecss|return|returns|see|visibility)) ";
 GoogleStyle.MaxEmptyLinesToKeep = 3;
 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
 GoogleStyle.SpacesInContainerLiterals = false;


Index: lib/Format/Format.cpp
===
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -613,7 +613,8 @@
 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
 GoogleStyle.BreakBeforeTernaryOperators = false;
-GoogleStyle.CommentPragmas = "(taze:|@(export|requirecss|return|see|visibility)) ";
+GoogleStyle.CommentPragmas =
+"(taze:|@(export|requirecss|return|returns|see|visibility)) ";
 GoogleStyle.MaxEmptyLinesToKeep = 3;
 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
 GoogleStyle.SpacesInContainerLiterals = false;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r282056 - clang-format: [JS] do not wrapp @returns tags.

2016-09-21 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Wed Sep 21 01:56:38 2016
New Revision: 282056

URL: http://llvm.org/viewvc/llvm-project?rev=282056&view=rev
Log:
clang-format: [JS] do not wrapp @returns tags.

Summary: @returns is incorrect code, the standard is @return. However wrapping 
it can still confuse users.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D24767

Modified:
cfe/trunk/lib/Format/Format.cpp

Modified: cfe/trunk/lib/Format/Format.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=282056&r1=282055&r2=282056&view=diff
==
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Wed Sep 21 01:56:38 2016
@@ -613,7 +613,8 @@ FormatStyle getGoogleStyle(FormatStyle::
 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
 GoogleStyle.BreakBeforeTernaryOperators = false;
-GoogleStyle.CommentPragmas = 
"(taze:|@(export|requirecss|return|see|visibility)) ";
+GoogleStyle.CommentPragmas =
+"(taze:|@(export|requirecss|return|returns|see|visibility)) ";
 GoogleStyle.MaxEmptyLinesToKeep = 3;
 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
 GoogleStyle.SpacesInContainerLiterals = false;


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24767: clang-format: [JS] do not wrapp @returns tags.

2016-09-21 Thread Martin Probst via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL282056: clang-format: [JS] do not wrapp @returns tags. 
(authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D24767?vs=71938&id=72010#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D24767

Files:
  cfe/trunk/lib/Format/Format.cpp

Index: cfe/trunk/lib/Format/Format.cpp
===
--- cfe/trunk/lib/Format/Format.cpp
+++ cfe/trunk/lib/Format/Format.cpp
@@ -613,7 +613,8 @@
 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
 GoogleStyle.BreakBeforeTernaryOperators = false;
-GoogleStyle.CommentPragmas = 
"(taze:|@(export|requirecss|return|see|visibility)) ";
+GoogleStyle.CommentPragmas =
+"(taze:|@(export|requirecss|return|returns|see|visibility)) ";
 GoogleStyle.MaxEmptyLinesToKeep = 3;
 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
 GoogleStyle.SpacesInContainerLiterals = false;


Index: cfe/trunk/lib/Format/Format.cpp
===
--- cfe/trunk/lib/Format/Format.cpp
+++ cfe/trunk/lib/Format/Format.cpp
@@ -613,7 +613,8 @@
 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
 GoogleStyle.BreakBeforeTernaryOperators = false;
-GoogleStyle.CommentPragmas = "(taze:|@(export|requirecss|return|see|visibility)) ";
+GoogleStyle.CommentPragmas =
+"(taze:|@(export|requirecss|return|returns|see|visibility)) ";
 GoogleStyle.MaxEmptyLinesToKeep = 3;
 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
 GoogleStyle.SpacesInContainerLiterals = false;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D24804: clang-format: [JS] reserved words in method names.

2016-09-21 Thread Martin Probst via cfe-commits
mprobst created this revision.
mprobst added a reviewer: djasper.
mprobst added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

Before:
class X {
  delete () {
...
  }
}

After:
class X {
  delete() {
...
  }
}

https://reviews.llvm.org/D24804

Files:
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTestJS.cpp

Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -147,6 +147,18 @@
   verifyFormat("x = interface instanceof y;");
 }
 
+TEST_F(FormatTestJS, ReservedWordsMethods) {
+  verifyFormat(
+  "class X {\n"
+  "  delete() {\n"
+  "x();\n"
+  "  }\n"
+  "  interface() {\n"
+  "x();\n"
+  "  }\n"
+  "}\n");
+}
+
 TEST_F(FormatTestJS, CppKeywords) {
   // Make sure we don't mess stuff up because of C++ keywords.
   verifyFormat("return operator && (aa);");
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -2158,6 +2158,10 @@
 tok::r_square, tok::r_brace) ||
Left.Tok.isLiteral()))
   return false;
+// JS methods can use some keywords as names (e.g. `delete()`).
+if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
+Left.Tok.getIdentifierInfo())
+  return false;
 if (Left.is(tok::exclaim) && Right.is(Keywords.kw_as))
   return true; // "x! as string"
   } else if (Style.Language == FormatStyle::LK_Java) {


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -147,6 +147,18 @@
   verifyFormat("x = interface instanceof y;");
 }
 
+TEST_F(FormatTestJS, ReservedWordsMethods) {
+  verifyFormat(
+  "class X {\n"
+  "  delete() {\n"
+  "x();\n"
+  "  }\n"
+  "  interface() {\n"
+  "x();\n"
+  "  }\n"
+  "}\n");
+}
+
 TEST_F(FormatTestJS, CppKeywords) {
   // Make sure we don't mess stuff up because of C++ keywords.
   verifyFormat("return operator && (aa);");
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -2158,6 +2158,10 @@
 tok::r_square, tok::r_brace) ||
Left.Tok.isLiteral()))
   return false;
+// JS methods can use some keywords as names (e.g. `delete()`).
+if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
+Left.Tok.getIdentifierInfo())
+  return false;
 if (Left.is(tok::exclaim) && Right.is(Keywords.kw_as))
   return true; // "x! as string"
   } else if (Style.Language == FormatStyle::LK_Java) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24804: clang-format: [JS] reserved words in method names.

2016-09-21 Thread Martin Probst via cfe-commits
mprobst updated this revision to Diff 72061.
mprobst added a comment.

- move up to support let in methods.


https://reviews.llvm.org/D24804

Files:
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTestJS.cpp

Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -147,6 +147,21 @@
   verifyFormat("x = interface instanceof y;");
 }
 
+TEST_F(FormatTestJS, ReservedWordsMethods) {
+  verifyFormat(
+  "class X {\n"
+  "  delete() {\n"
+  "x();\n"
+  "  }\n"
+  "  interface() {\n"
+  "x();\n"
+  "  }\n"
+  "  let() {\n"
+  "x();\n"
+  "  }\n"
+  "}\n");
+}
+
 TEST_F(FormatTestJS, CppKeywords) {
   // Make sure we don't mess stuff up because of C++ keywords.
   verifyFormat("return operator && (aa);");
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -2125,6 +2125,10 @@
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
   return false;
+// JS methods can use some keywords as names (e.g. `delete()`).
+if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
+Left.Tok.getIdentifierInfo())
+  return false;
 if (Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -147,6 +147,21 @@
   verifyFormat("x = interface instanceof y;");
 }
 
+TEST_F(FormatTestJS, ReservedWordsMethods) {
+  verifyFormat(
+  "class X {\n"
+  "  delete() {\n"
+  "x();\n"
+  "  }\n"
+  "  interface() {\n"
+  "x();\n"
+  "  }\n"
+  "  let() {\n"
+  "x();\n"
+  "  }\n"
+  "}\n");
+}
+
 TEST_F(FormatTestJS, CppKeywords) {
   // Make sure we don't mess stuff up because of C++ keywords.
   verifyFormat("return operator && (aa);");
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -2125,6 +2125,10 @@
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
   return false;
+// JS methods can use some keywords as names (e.g. `delete()`).
+if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
+Left.Tok.getIdentifierInfo())
+  return false;
 if (Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24804: clang-format: [JS] reserved words in method names.

2016-09-22 Thread Martin Probst via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL282138: clang-format: [JS] reserved words in method names. 
(authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D24804?vs=72061&id=72140#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D24804

Files:
  cfe/trunk/lib/Format/TokenAnnotator.cpp
  cfe/trunk/unittests/Format/FormatTestJS.cpp

Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -147,6 +147,21 @@
   verifyFormat("x = interface instanceof y;");
 }
 
+TEST_F(FormatTestJS, ReservedWordsMethods) {
+  verifyFormat(
+  "class X {\n"
+  "  delete() {\n"
+  "x();\n"
+  "  }\n"
+  "  interface() {\n"
+  "x();\n"
+  "  }\n"
+  "  let() {\n"
+  "x();\n"
+  "  }\n"
+  "}\n");
+}
+
 TEST_F(FormatTestJS, CppKeywords) {
   // Make sure we don't mess stuff up because of C++ keywords.
   verifyFormat("return operator && (aa);");
Index: cfe/trunk/lib/Format/TokenAnnotator.cpp
===
--- cfe/trunk/lib/Format/TokenAnnotator.cpp
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp
@@ -2125,6 +2125,10 @@
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
   return false;
+// JS methods can use some keywords as names (e.g. `delete()`).
+if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
+Left.Tok.getIdentifierInfo())
+  return false;
 if (Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))


Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -147,6 +147,21 @@
   verifyFormat("x = interface instanceof y;");
 }
 
+TEST_F(FormatTestJS, ReservedWordsMethods) {
+  verifyFormat(
+  "class X {\n"
+  "  delete() {\n"
+  "x();\n"
+  "  }\n"
+  "  interface() {\n"
+  "x();\n"
+  "  }\n"
+  "  let() {\n"
+  "x();\n"
+  "  }\n"
+  "}\n");
+}
+
 TEST_F(FormatTestJS, CppKeywords) {
   // Make sure we don't mess stuff up because of C++ keywords.
   verifyFormat("return operator && (aa);");
Index: cfe/trunk/lib/Format/TokenAnnotator.cpp
===
--- cfe/trunk/lib/Format/TokenAnnotator.cpp
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp
@@ -2125,6 +2125,10 @@
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
   return false;
+// JS methods can use some keywords as names (e.g. `delete()`).
+if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
+Left.Tok.getIdentifierInfo())
+  return false;
 if (Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r282138 - clang-format: [JS] reserved words in method names.

2016-09-22 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Thu Sep 22 02:18:00 2016
New Revision: 282138

URL: http://llvm.org/viewvc/llvm-project?rev=282138&view=rev
Log:
clang-format: [JS] reserved words in method names.

Summary:
Before:
class X {
  delete () {
...
  }
}

After:
class X {
  delete() {
...
  }
}

Reviewers: djasper

Subscribers: cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D24804

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=282138&r1=282137&r2=282138&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Thu Sep 22 02:18:00 2016
@@ -2125,6 +2125,10 @@ bool TokenAnnotator::spaceRequiredBefore
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
   return false;
+// JS methods can use some keywords as names (e.g. `delete()`).
+if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
+Left.Tok.getIdentifierInfo())
+  return false;
 if (Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=282138&r1=282137&r2=282138&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Thu Sep 22 02:18:00 2016
@@ -147,6 +147,21 @@ TEST_F(FormatTestJS, ReservedWords) {
   verifyFormat("x = interface instanceof y;");
 }
 
+TEST_F(FormatTestJS, ReservedWordsMethods) {
+  verifyFormat(
+  "class X {\n"
+  "  delete() {\n"
+  "x();\n"
+  "  }\n"
+  "  interface() {\n"
+  "x();\n"
+  "  }\n"
+  "  let() {\n"
+  "x();\n"
+  "  }\n"
+  "}\n");
+}
+
 TEST_F(FormatTestJS, CppKeywords) {
   // Make sure we don't mess stuff up because of C++ keywords.
   verifyFormat("return operator && (aa);");


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D25439: Fixed column shift when formatting line containing bit shift operators

2016-10-10 Thread Martin Probst via cfe-commits
mprobst added a comment.

Looks good to me, but Daniel is a better owner for this code.


https://reviews.llvm.org/D25439



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D25675: clang-format: [JS] Fix template string ASI.

2016-10-17 Thread Martin Probst via cfe-commits
mprobst created this revision.
mprobst added a reviewer: djasper.
mprobst added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

Previously, automatic semicolon insertion would add an unwrapped line
when a template string contained a line break.

  var x = `foo${
  bar}`;

Would be formatted with `bar...` on a separate line and no indent.


https://reviews.llvm.org/D25675

Files:
  lib/Format/UnwrappedLineParser.cpp
  unittests/Format/FormatTestJS.cpp


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1276,6 +1276,12 @@
   verifyFormat("var x = ` \\${foo}`;\n");
 }
 
+TEST_F(FormatTestJS, TemplateStringASI) {
+  verifyFormat("var x = `hello${world}`;", "var x = `hello${\n"
+   "world\n"
+   "}`;");
+}
+
 TEST_F(FormatTestJS, NestedTemplateStrings) {
   verifyFormat(
   "var x = `${xs.map(x => `${x}`).join('\\n')}`;");
Index: lib/Format/UnwrappedLineParser.cpp
===
--- lib/Format/UnwrappedLineParser.cpp
+++ lib/Format/UnwrappedLineParser.cpp
@@ -727,6 +727,8 @@
 return;
 
   bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);
+  bool PreviousStartsTemplateExpr =
+  Previous->is(TT_TemplateString) && Previous->TokenText.endswith("${");
   if (PreviousMustBeValue && Line && Line->Tokens.size() > 1) {
 // If the token before the previous one is an '@', the previous token is an
 // annotation and can precede another identifier/value.
@@ -737,9 +739,12 @@
   if (Next->is(tok::exclaim) && PreviousMustBeValue)
 addUnwrappedLine();
   bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next);
-  if (NextMustBeValue && (PreviousMustBeValue ||
-  Previous->isOneOf(tok::r_square, tok::r_paren,
-tok::plusplus, tok::minusminus)))
+  bool NextEndsTemplateExpr =
+  Next->is(TT_TemplateString) && Next->TokenText.startswith("}");
+  if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr 
&&
+  (PreviousMustBeValue ||
+   Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
+ tok::minusminus)))
 addUnwrappedLine();
   if (PreviousMustBeValue && isJSDeclOrStmt(Keywords, Next))
 addUnwrappedLine();


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1276,6 +1276,12 @@
   verifyFormat("var x = ` \\${foo}`;\n");
 }
 
+TEST_F(FormatTestJS, TemplateStringASI) {
+  verifyFormat("var x = `hello${world}`;", "var x = `hello${\n"
+   "world\n"
+   "}`;");
+}
+
 TEST_F(FormatTestJS, NestedTemplateStrings) {
   verifyFormat(
   "var x = `${xs.map(x => `${x}`).join('\\n')}`;");
Index: lib/Format/UnwrappedLineParser.cpp
===
--- lib/Format/UnwrappedLineParser.cpp
+++ lib/Format/UnwrappedLineParser.cpp
@@ -727,6 +727,8 @@
 return;
 
   bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);
+  bool PreviousStartsTemplateExpr =
+  Previous->is(TT_TemplateString) && Previous->TokenText.endswith("${");
   if (PreviousMustBeValue && Line && Line->Tokens.size() > 1) {
 // If the token before the previous one is an '@', the previous token is an
 // annotation and can precede another identifier/value.
@@ -737,9 +739,12 @@
   if (Next->is(tok::exclaim) && PreviousMustBeValue)
 addUnwrappedLine();
   bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next);
-  if (NextMustBeValue && (PreviousMustBeValue ||
-  Previous->isOneOf(tok::r_square, tok::r_paren,
-tok::plusplus, tok::minusminus)))
+  bool NextEndsTemplateExpr =
+  Next->is(TT_TemplateString) && Next->TokenText.startswith("}");
+  if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
+  (PreviousMustBeValue ||
+   Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
+ tok::minusminus)))
 addUnwrappedLine();
   if (PreviousMustBeValue && isJSDeclOrStmt(Keywords, Next))
 addUnwrappedLine();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r318942 - clang-format: [JS] handle destructuring `of`.

2017-11-24 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Nov 24 02:48:25 2017
New Revision: 318942

URL: http://llvm.org/viewvc/llvm-project?rev=318942&view=rev
Log:
clang-format: [JS] handle destructuring `of`.

Summary:
Previously, clang-format would drop a space character between `of` and
then following (non-identifier) token if the preceding token was part of
a destructuring assignment (`}` or `]`).

Before:
for (const [a, b] of[]) {}

After:
for (const [a, b] of []) {}

Reviewers: djasper

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D40411

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=318942&r1=318941&r2=318942&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Fri Nov 24 02:48:25 2017
@@ -2397,9 +2397,11 @@ bool TokenAnnotator::spaceRequiredBefore
 if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
   tok::kw_const) ||
  // "of" is only a keyword if it appears after another identifier
- // (e.g. as "const x of y" in a for loop).
+ // (e.g. as "const x of y" in a for loop), or after a destructuring
+ // operation (const [x, y] of z, const {a, b} of c).
  (Left.is(Keywords.kw_of) && Left.Previous &&
-  Left.Previous->Tok.getIdentifierInfo())) &&
+  (Left.Previous->Tok.getIdentifierInfo() ||
+   Left.Previous->isOneOf(tok::r_square, tok::r_brace &&
 (!Left.Previous || !Left.Previous->is(tok::period)))
   return true;
 if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=318942&r1=318941&r2=318942&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Fri Nov 24 02:48:25 2017
@@ -1110,6 +1110,10 @@ TEST_F(FormatTestJS, ForLoops) {
"}");
   verifyFormat("for (let {a, b} of x) {\n"
"}");
+  verifyFormat("for (let {a, b} of [x]) {\n"
+   "}");
+  verifyFormat("for (let [a, b] of [x]) {\n"
+   "}");
   verifyFormat("for (let {a, b} in x) {\n"
"}");
 }


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r318957 - clang-format: [JS] space between ! assert and in.

2017-11-24 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Nov 24 09:04:40 2017
New Revision: 318957

URL: http://llvm.org/viewvc/llvm-project?rev=318957&view=rev
Log:
clang-format: [JS] space between ! assert and in.

Summary:
Before:
x = y!in z;
After:
x = y! in z;

Reviewers: djasper

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D40433

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=318957&r1=318956&r2=318957&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Fri Nov 24 09:04:40 2017
@@ -2433,8 +2433,9 @@ bool TokenAnnotator::spaceRequiredBefore
   return false;
 if (Right.is(TT_JsNonNullAssertion))
   return false;
-if (Left.is(TT_JsNonNullAssertion) && Right.is(Keywords.kw_as))
-  return true; // "x! as string"
+if (Left.is(TT_JsNonNullAssertion) &&
+Right.isOneOf(Keywords.kw_as, Keywords.kw_in))
+  return true; // "x! as string", "x! in y"
   } else if (Style.Language == FormatStyle::LK_Java) {
 if (Left.is(tok::r_square) && Right.is(tok::l_brace))
   return true;

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=318957&r1=318956&r2=318957&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Fri Nov 24 09:04:40 2017
@@ -1908,6 +1908,7 @@ TEST_F(FormatTestJS, CastSyntax) {
   verifyFormat("x = x as {a: string};");
   verifyFormat("x = x as (string);");
   verifyFormat("x = x! as (string);");
+  verifyFormat("x = y! in z;");
   verifyFormat("var x = something.someFunction() as\n"
"something;",
getGoogleJSStyleWithColumns(40));


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r318958 - clang-format: [JS] do not wrap before yield.

2017-11-24 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Nov 24 09:05:35 2017
New Revision: 318958

URL: http://llvm.org/viewvc/llvm-project?rev=318958&view=rev
Log:
clang-format: [JS] do not wrap before yield.

Summary: The same rules apply as for `return`.

Reviewers: djasper

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D40431

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=318958&r1=318957&r2=318958&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Fri Nov 24 09:05:35 2017
@@ -2699,8 +2699,8 @@ bool TokenAnnotator::canBreakBefore(cons
   } else if (Style.Language == FormatStyle::LK_JavaScript) {
 const FormatToken *NonComment = Right.getPreviousNonComment();
 if (NonComment &&
-NonComment->isOneOf(tok::kw_return, tok::kw_continue, tok::kw_break,
-tok::kw_throw, Keywords.kw_interface,
+NonComment->isOneOf(tok::kw_return, Keywords.kw_yield, 
tok::kw_continue,
+tok::kw_break, tok::kw_throw, 
Keywords.kw_interface,
 Keywords.kw_type, tok::kw_static, tok::kw_public,
 tok::kw_private, tok::kw_protected,
 Keywords.kw_readonly, Keywords.kw_abstract,

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=318958&r1=318957&r2=318958&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Fri Nov 24 09:05:35 2017
@@ -1123,6 +1123,7 @@ TEST_F(FormatTestJS, WrapRespectsAutomat
   // would change due to automatic semicolon insertion.
   // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1.
   verifyFormat("return a;", getGoogleJSStyleWithColumns(10));
+  verifyFormat("yield a;", getGoogleJSStyleWithColumns(10));
   verifyFormat("return /* hello! */ a;", getGoogleJSStyleWithColumns(10));
   verifyFormat("continue a;", getGoogleJSStyleWithColumns(10));
   verifyFormat("continue /* hello! */ a;", 
getGoogleJSStyleWithColumns(10));


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r318959 - clang-format: [JS] do not break in ArrayType[].

2017-11-24 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Nov 24 09:05:56 2017
New Revision: 318959

URL: http://llvm.org/viewvc/llvm-project?rev=318959&view=rev
Log:
clang-format: [JS] do not break in ArrayType[].

Summary:
Wrapping between the type name and the array type indicator creates
invalid syntax in TypeScript.

Before:
const xIsALongIdent:
YJustBarelyFitsLinex
[];  // illegal syntax.

After:
const xIsALongIdent:
YJustBarelyFitsLinex[];

Reviewers: djasper

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D40436

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=318959&r1=318958&r2=318959&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Fri Nov 24 09:05:56 2017
@@ -2706,6 +2706,9 @@ bool TokenAnnotator::canBreakBefore(cons
 Keywords.kw_readonly, Keywords.kw_abstract,
 Keywords.kw_get, Keywords.kw_set))
   return false; // Otherwise automatic semicolon insertion would trigger.
+if (Left.Tok.getIdentifierInfo() &&
+Right.startsSequence(tok::l_square, tok::r_square))
+  return false;  // breaking in "foo[]" creates illegal TS type syntax.
 if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
   return false;
 if (Left.is(TT_JsTypeColon))

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=318959&r1=318958&r2=318959&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Fri Nov 24 09:05:56 2017
@@ -1426,6 +1426,8 @@ TEST_F(FormatTestJS, TypeAnnotations) {
   verifyFormat(
   "var someValue = (v as [])\n"
   ".someFunction(aa);");
+  verifyFormat("const xIsALongIdent:\n""YJustBarelyFitsLinex[];",
+  getGoogleJSStyleWithColumns(20));
 }
 
 TEST_F(FormatTestJS, UnionIntersectionTypes) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r318973 - clang-format: [JS] disable ASI on decorators.

2017-11-25 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Sat Nov 25 01:19:42 2017
New Revision: 318973

URL: http://llvm.org/viewvc/llvm-project?rev=318973&view=rev
Log:
clang-format: [JS] disable ASI on decorators.

Summary:
Automatic Semicolon Insertion in clang-format tries to guess if a line
wrap should insert an implicit semicolong. The previous heuristic would
not trigger ASI if a token was immediately preceded by an `@` sign:

function foo(@Bar  // <-- does not trigger due to preceding @
baz) {}

However decorators can have arbitrary parameters:

function foo(@Bar(param, param, param)  // <-- precending @ missed
baz) {}

While it would be possible to precisely find the matching `@`, just
conversatively disabling ASI for the entire line is simpler, while also
not regressing ASI substatially.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D40410

Modified:
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=318973&r1=318972&r2=318973&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Sat Nov 25 01:19:42 2017
@@ -18,6 +18,8 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 
+#include 
+
 #define DEBUG_TYPE "format-parser"
 
 namespace clang {
@@ -891,11 +893,14 @@ void UnwrappedLineParser::readTokenWithJ
   bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);
   bool PreviousStartsTemplateExpr =
   Previous->is(TT_TemplateString) && Previous->TokenText.endswith("${");
-  if (PreviousMustBeValue && Line && Line->Tokens.size() > 1) {
-// If the token before the previous one is an '@', the previous token is an
-// annotation and can precede another identifier/value.
-const FormatToken *PrePrevious = std::prev(Line->Tokens.end(), 2)->Tok;
-if (PrePrevious->is(tok::at))
+  if (PreviousMustBeValue || Previous->is(tok::r_paren)) {
+// If the line contains an '@' sign, the previous token might be an
+// annotation, which can precede another identifier/value.
+bool HasAt = std::find_if(Line->Tokens.begin(), Line->Tokens.end(),
+  [](UnwrappedLineNode &LineNode) {
+return LineNode.Tok->is(tok::at);
+  }) != Line->Tokens.end();
+if (HasAt)
   return;
   }
   if (Next->is(tok::exclaim) && PreviousMustBeValue)

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=318973&r1=318972&r2=318973&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Sat Nov 25 01:19:42 2017
@@ -1197,6 +1197,8 @@ TEST_F(FormatTestJS, AutomaticSemicolonI
   "String");
   verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n"
   "  bar) {}");
+  verifyFormat("function f(@Foo(Param) bar) {}", "function f(@Foo(Param)\n"
+ "  bar) {}");
   verifyFormat("a = true\n"
"return 1",
"a = true\n"
@@ -1564,7 +1566,7 @@ TEST_F(FormatTestJS, EnumDeclarations) {
"}");
 }
 
-TEST_F(FormatTestJS, MetadataAnnotations) {
+TEST_F(FormatTestJS, Decorators) {
   verifyFormat("@A\nclass C {\n}");
   verifyFormat("@A({arg: 'value'})\nclass C {\n}");
   verifyFormat("@A\n@B\nclass C {\n}");


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r318974 - clang-format: [JS] handle `for` as object label.

2017-11-25 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Sat Nov 25 01:24:33 2017
New Revision: 318974

URL: http://llvm.org/viewvc/llvm-project?rev=318974&view=rev
Log:
clang-format: [JS] handle `for` as object label.

Summary: Previously, clang-format would fail formatting `{for: 1}`.

Reviewers: djasper

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D40441

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=318974&r1=318973&r2=318974&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Sat Nov 25 01:24:33 2017
@@ -617,7 +617,9 @@ private:
   break;
 case tok::kw_for:
   if (Style.Language == FormatStyle::LK_JavaScript) {
-if (Tok->Previous && Tok->Previous->is(tok::period))
+// x.for and {for: ...}
+if ((Tok->Previous && Tok->Previous->is(tok::period)) ||
+(Tok->Next && Tok->Next->is(tok::colon)))
   break;
 // JS' for await ( ...
 if (CurrentToken && CurrentToken->is(Keywords.kw_await))

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=318974&r1=318973&r2=318974&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Sat Nov 25 01:24:33 2017
@@ -323,6 +323,11 @@ TEST_F(FormatTestJS, ReservedWords) {
"  case: string;\n"
"  default: string;\n"
"}\n");
+  verifyFormat("const Axis = {\n"
+   "  for: 'for',\n"
+   "  x: 'x'\n"
+   "};",
+   "const Axis = {for: 'for', x:   'x'};");
 }
 
 TEST_F(FormatTestJS, ReservedWordsMethods) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r318975 - clang-format: [JS] handle semis in generic types.

2017-11-25 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Sat Nov 25 01:33:47 2017
New Revision: 318975

URL: http://llvm.org/viewvc/llvm-project?rev=318975&view=rev
Log:
clang-format: [JS] handle semis in generic types.

Summary:
TypeScript generic type arguments can contain object (literal) types,
which in turn can contain semicolons:

const x: Array<{a: number; b: string;} = [];

Previously, clang-format would incorrectly categorize the braced list as
a block and terminate the line at the openening `{`, and then format the
entire expression badly.

With this change, clang-format recognizes `<` preceding a `{` as
introducing a type expression. In JS, `<` comparison with an object
literal can never be true, so the chance of introducing false positives
here is very low.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D40424

Modified:
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=318975&r1=318974&r2=318975&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Sat Nov 25 01:33:47 2017
@@ -379,13 +379,16 @@ void UnwrappedLineParser::calculateBrace
 switch (Tok->Tok.getKind()) {
 case tok::l_brace:
   if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) {
-if (PrevTok->is(tok::colon))
-  // A colon indicates this code is in a type, or a braced list
-  // following a label in an object literal ({a: {b: 1}}). The code
-  // below could be confused by semicolons between the individual
-  // members in a type member list, which would normally trigger
-  // BK_Block. In both cases, this must be parsed as an inline braced
-  // init.
+if (PrevTok->isOneOf(tok::colon, tok::less))
+  // A ':' indicates this code is in a type, or a braced list
+  // following a label in an object literal ({a: {b: 1}}).
+  // A '<' could be an object used in a comparison, but that is 
nonsense
+  // code (can never return true), so more likely it is a generic type
+  // argument (`X<{a: string; b: number}>`).
+  // The code below could be confused by semicolons between the
+  // individual members in a type member list, which would normally
+  // trigger BK_Block. In both cases, this must be parsed as an inline
+  // braced init.
   Tok->BlockKind = BK_BracedInit;
 else if (PrevTok->is(tok::r_paren))
   // `) { }` can only occur in function or method declarations in JS.

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=318975&r1=318974&r2=318975&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Sat Nov 25 01:33:47 2017
@@ -1414,6 +1414,7 @@ TEST_F(FormatTestJS, TypeAnnotations) {
   verifyFormat("function x(y: {a?: number;} = {}): number {\n"
"  return 12;\n"
"}");
+  verifyFormat("const x: Array<{a: number; b: string;}> = [];");
   verifyFormat("((a: string, b: number): string => a + b);");
   verifyFormat("var x: (y: number) => string;");
   verifyFormat("var x: P string>;");


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r318976 - clang-format: [JS] do not collapse short classes.

2017-11-25 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Sat Nov 25 01:35:33 2017
New Revision: 318976

URL: http://llvm.org/viewvc/llvm-project?rev=318976&view=rev
Log:
clang-format: [JS] do not collapse short classes.

Summary:
clang-format does not collapse short records, interfaces, unions, etc.,
but fails to do so if the record is preceded by certain modifiers
(export, default, abstract, declare). This change skips over all
modifiers, and thus handles all record definitions uniformly.

Before:
export class Foo { bar: string; }
class Baz {
  bam: string;
}

After:
export class Foo {
  bar: string;
}
class Baz {
  bam: string;
}

Reviewers: djasper

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D40430

Modified:
cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp?rev=318976&r1=318975&r2=318976&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp Sat Nov 25 01:35:33 2017
@@ -517,8 +517,13 @@ private:
   } else if (Limit != 0 && !Line.startsWith(tok::kw_namespace) &&
  !startsExternCBlock(Line)) {
 // We don't merge short records.
-FormatToken *RecordTok =
-Line.First->is(tok::kw_typedef) ? Line.First->Next : Line.First;
+FormatToken *RecordTok = Line.First;
+// Skip record modifiers.
+while (RecordTok->Next &&
+   RecordTok->isOneOf(tok::kw_typedef, tok::kw_export,
+  Keywords.kw_declare, Keywords.kw_abstract,
+  tok::kw_default))
+  RecordTok = RecordTok->Next;
 if (RecordTok &&
 RecordTok->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct,
Keywords.kw_interface))

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=318976&r1=318975&r2=318976&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Sat Nov 25 01:35:33 2017
@@ -1674,9 +1674,15 @@ TEST_F(FormatTestJS, Modules) {
"  x: number;\n"
"  y: string;\n"
"}");
-  verifyFormat("export class X { y: number; }");
-  verifyFormat("export abstract class X { y: number; }");
-  verifyFormat("export default class X { y: number }");
+  verifyFormat("export class X {\n"
+   "  y: number;\n"
+   "}");
+  verifyFormat("export abstract class X {\n"
+   "  y: number;\n"
+   "}");
+  verifyFormat("export default class X {\n"
+   "  y: number\n"
+   "}");
   verifyFormat("export default function() {\n  return 1;\n}");
   verifyFormat("export var x = 12;");
   verifyFormat("class C {}\n"
@@ -1698,7 +1704,9 @@ TEST_F(FormatTestJS, Modules) {
"];");
   verifyFormat("export default [];");
   verifyFormat("export default () => {};");
-  verifyFormat("export interface Foo { foo: number; }\n"
+  verifyFormat("export interface Foo {\n"
+   "  foo: number;\n"
+   "}\n"
"export class Bar {\n"
"  blah(): string {\n"
"return this.blah;\n"


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r319415 - clang-format: [JS] do not wrap after async/await.

2017-11-30 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Thu Nov 30 02:25:17 2017
New Revision: 319415

URL: http://llvm.org/viewvc/llvm-project?rev=319415&view=rev
Log:
clang-format: [JS] do not wrap after async/await.

Summary:
Otherwise automatic semicolon insertion can trigger, i.e. wrapping
produces invalid syntax.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D40642

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=319415&r1=319414&r2=319415&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Thu Nov 30 02:25:17 2017
@@ -2701,12 +2701,12 @@ bool TokenAnnotator::canBreakBefore(cons
   } else if (Style.Language == FormatStyle::LK_JavaScript) {
 const FormatToken *NonComment = Right.getPreviousNonComment();
 if (NonComment &&
-NonComment->isOneOf(tok::kw_return, Keywords.kw_yield, 
tok::kw_continue,
-tok::kw_break, tok::kw_throw, 
Keywords.kw_interface,
-Keywords.kw_type, tok::kw_static, tok::kw_public,
-tok::kw_private, tok::kw_protected,
-Keywords.kw_readonly, Keywords.kw_abstract,
-Keywords.kw_get, Keywords.kw_set))
+NonComment->isOneOf(
+tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break,
+tok::kw_throw, Keywords.kw_interface, Keywords.kw_type,
+tok::kw_static, tok::kw_public, tok::kw_private, tok::kw_protected,
+Keywords.kw_readonly, Keywords.kw_abstract, Keywords.kw_get,
+Keywords.kw_set, Keywords.kw_async, Keywords.kw_await))
   return false; // Otherwise automatic semicolon insertion would trigger.
 if (Left.Tok.getIdentifierInfo() &&
 Right.startsSequence(tok::l_square, tok::r_square))

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=319415&r1=319414&r2=319415&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Thu Nov 30 02:25:17 2017
@@ -1152,6 +1152,11 @@ TEST_F(FormatTestJS, WrapRespectsAutomat
"const y = 3\n",
"const x = (   5 +9)\n"
"const y = 3\n");
+  // Ideally the foo() bit should be indented relative to the async function().
+  verifyFormat("async function\n"
+   "foo() {}",
+   getGoogleJSStyleWithColumns(10));
+  verifyFormat("await theReckoning;", getGoogleJSStyleWithColumns(10));
 }
 
 TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r369916 - clang-format: [JS] handle `as const`.

2019-08-26 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Aug 26 08:37:05 2019
New Revision: 369916

URL: http://llvm.org/viewvc/llvm-project?rev=369916&view=rev
Log:
clang-format: [JS] handle `as const`.

Summary:
TypeScript 3.4 supports casting into a const type using `as const`:

const x = {x: 1} as const;

Previously, clang-format would insert a space after the `const`. With
this patch, no space is inserted after the sequence `as const`.

Reviewers: krasimir

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D66736

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=369916&r1=369915&r2=369916&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon Aug 26 08:37:05 2019
@@ -2746,6 +2746,10 @@ bool TokenAnnotator::spaceRequiredBefore
tok::kw_void))
 return true;
 }
+// `foo as const;` casts into a const type.
+if (Left.endsSequence(tok::kw_const, Keywords.kw_as)) {
+  return false;
+}
 if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
   tok::kw_const) ||
  // "of" is only a keyword if it appears after another identifier

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=369916&r1=369915&r2=369916&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon Aug 26 08:37:05 2019
@@ -1479,6 +1479,9 @@ TEST_F(FormatTestJS, TypeAnnotations) {
   ".someFunction(aa);");
   verifyFormat("const xIsALongIdent:\n""YJustBarelyFitsLinex[];",
   getGoogleJSStyleWithColumns(20));
+  verifyFormat("const x = {\n"
+   "  y: 1\n"
+   "} as const;");
 }
 
 TEST_F(FormatTestJS, UnionIntersectionTypes) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r309695 - clang-format: [JS] handle object types in extends positions.

2017-08-01 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Aug  1 08:46:10 2017
New Revision: 309695

URL: http://llvm.org/viewvc/llvm-project?rev=309695&view=rev
Log:
clang-format: [JS] handle object types in extends positions.

Summary:
clang-format would previously drop the whitespace after `extends` in code such 
as:

class Foo extends {} {}

Where the first set of curly braces is an inline object literal type.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36131

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=309695&r1=309694&r2=309695&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Aug  1 08:46:10 2017
@@ -2341,7 +2341,8 @@ bool TokenAnnotator::spaceRequiredBefore
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
   return false;
 if (Right.isOneOf(tok::l_brace, tok::l_square) &&
-Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
+Left.isOneOf(Keywords.kw_function, Keywords.kw_yield,
+ Keywords.kw_extends, Keywords.kw_implements))
   return true;
 // JS methods can use some keywords as names (e.g. `delete()`).
 if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=309695&r1=309694&r2=309695&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Tue Aug  1 08:46:10 2017
@@ -1970,6 +1970,17 @@ void UnwrappedLineParser::parseRecord(bo
  ((Style.Language == FormatStyle::LK_Java ||
Style.Language == FormatStyle::LK_JavaScript) &&
   FormatTok->isOneOf(tok::period, tok::comma))) {
+if (Style.Language == FormatStyle::LK_JavaScript &&
+FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
+  // JavaScript/TypeScript supports inline object types in
+  // extends/implements positions:
+  // class Foo implements {bar: number} { }
+  nextToken();
+  if (FormatTok->is(tok::l_brace)) {
+tryToParseBracedList();
+continue;
+  }
+}
 bool IsNonMacroIdentifier =
 FormatTok->is(tok::identifier) &&
 FormatTok->TokenText != FormatTok->TokenText.upper();

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=309695&r1=309694&r2=309695&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Aug  1 08:46:10 2017
@@ -1400,6 +1400,17 @@ TEST_F(FormatTestJS, InterfaceDeclaratio
"}");
 }
 
+TEST_F(FormatTestJS, ObjectTypesInExtendsImplements) {
+  verifyFormat("class C extends {} {}");
+  verifyFormat("class C implements {bar: number} {}");
+  // Somewhat odd, but probably closest to reasonable formatting?
+  verifyFormat("class C implements {\n"
+   "  bar: number,\n"
+   "  baz: string,\n"
+   "} {}");
+  verifyFormat("class C {}");
+}
+
 TEST_F(FormatTestJS, EnumDeclarations) {
   verifyFormat("enum Foo {\n"
"  A = 1,\n"


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r309697 - clang-format: [JS] support default imports.

2017-08-01 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Aug  1 08:54:43 2017
New Revision: 309697

URL: http://llvm.org/viewvc/llvm-project?rev=309697&view=rev
Log:
clang-format: [JS] support default imports.

Summary: Formerly, `import {default as X} from y;` would not be recognized as 
an import.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36132

Modified:
cfe/trunk/lib/Format/SortJavaScriptImports.cpp
cfe/trunk/unittests/Format/SortImportsTestJS.cpp

Modified: cfe/trunk/lib/Format/SortJavaScriptImports.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/SortJavaScriptImports.cpp?rev=309697&r1=309696&r2=309697&view=diff
==
--- cfe/trunk/lib/Format/SortJavaScriptImports.cpp (original)
+++ cfe/trunk/lib/Format/SortJavaScriptImports.cpp Tue Aug  1 08:54:43 2017
@@ -413,7 +413,7 @@ private:
   nextToken();
   if (Current->is(tok::r_brace))
 break;
-  if (Current->isNot(tok::identifier))
+  if (!Current->isOneOf(tok::identifier, tok::kw_default))
 return false;
 
   JsImportedSymbol Symbol;
@@ -425,7 +425,7 @@ private:
 
   if (Current->is(Keywords.kw_as)) {
 nextToken();
-if (Current->isNot(tok::identifier))
+if (!Current->isOneOf(tok::identifier, tok::kw_default))
   return false;
 Symbol.Alias = Current->TokenText;
 nextToken();

Modified: cfe/trunk/unittests/Format/SortImportsTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/SortImportsTestJS.cpp?rev=309697&r1=309696&r2=309697&view=diff
==
--- cfe/trunk/unittests/Format/SortImportsTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/SortImportsTestJS.cpp Tue Aug  1 08:54:43 2017
@@ -300,6 +300,14 @@ TEST_F(SortImportsTestJS, SortMultiLine)
  "1;");
 }
 
+TEST_F(SortImportsTestJS, SortDefaultImports) {
+  // Reproduces issue where multi-line import was not parsed correctly.
+  verifySort("import {A} from 'a';\n"
+ "import {default as B} from 'b';\n",
+ "import {default as B} from 'b';\n"
+ "import {A} from 'a';\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r309703 - clang-format: [JS] consistenly format enums.

2017-08-01 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Aug  1 10:12:15 2017
New Revision: 309703

URL: http://llvm.org/viewvc/llvm-project?rev=309703&view=rev
Log:
clang-format: [JS] consistenly format enums.

Summary: Previously, const enums would get formatted differently because the 
modifier was not recognized.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36144

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=309703&r1=309702&r2=309703&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Aug  1 10:12:15 2017
@@ -2517,7 +2517,9 @@ bool TokenAnnotator::mustBreakBefore(con
   return true;
 if (Left.is(tok::l_brace) && Line.Level == 0 &&
 (Line.startsWith(tok::kw_enum) ||
- Line.startsWith(tok::kw_export, tok::kw_enum)))
+ Line.startsWith(tok::kw_const, tok::kw_enum) ||
+ Line.startsWith(tok::kw_export, tok::kw_enum) ||
+ Line.startsWith(tok::kw_export, tok::kw_const, tok::kw_enum)))
   // JavaScript top-level enum key/value pairs are put on separate lines
   // instead of bin-packing.
   return true;

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=309703&r1=309702&r2=309703&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Aug  1 10:12:15 2017
@@ -1425,6 +1425,14 @@ TEST_F(FormatTestJS, EnumDeclarations) {
"  B\n"
"}\n"
"var x = 1;");
+  verifyFormat("const enum Foo {\n"
+   "  A = 1,\n"
+   "  B\n"
+   "}");
+  verifyFormat("export const enum Foo {\n"
+   "  A = 1,\n"
+   "  B\n"
+   "}");
 }
 
 TEST_F(FormatTestJS, MetadataAnnotations) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r309707 - clang-format: [JS] handle union types in arrow functions.

2017-08-01 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Aug  1 10:19:32 2017
New Revision: 309707

URL: http://llvm.org/viewvc/llvm-project?rev=309707&view=rev
Log:
clang-format: [JS] handle union types in arrow functions.

Summary: clang-format would previously fail to detect that an arrow functions 
parameter block is not an expression, and thus insert whitespace around the `|` 
and `&` type operators in it.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36147

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=309707&r1=309706&r2=309707&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Aug  1 10:19:32 2017
@@ -533,6 +533,7 @@ private:
 Contexts.back().ContextKind == tok::l_square || // array type
 (Contexts.size() == 1 &&
  Line.MustBeDeclaration)) { // method/property declaration
+  Contexts.back().IsExpression = false;
   Tok->Type = TT_JsTypeColon;
   break;
 }

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=309707&r1=309706&r2=309707&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Aug  1 10:19:32 2017
@@ -988,6 +988,9 @@ TEST_F(FormatTestJS, ArrowFunctions) {
".doSomethingElse(\n"
"// break\n"
");");
+  verifyFormat("const f = (x: string|null): string|null => {\n"
+   "  return x;\n"
+   "}\n");
 }
 
 TEST_F(FormatTestJS, ReturnStatements) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r309710 - clang-format: [JS] whitespace between keywords and parenthesized expressions.

2017-08-01 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Aug  1 10:22:15 2017
New Revision: 309710

URL: http://llvm.org/viewvc/llvm-project?rev=309710&view=rev
Log:
clang-format: [JS] whitespace between keywords and parenthesized expressions.

Summary: `throw (...)` should have a whitespace following it, as do await and 
void.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36146

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=309710&r1=309709&r2=309710&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Aug  1 10:22:15 2017
@@ -2349,6 +2349,9 @@ bool TokenAnnotator::spaceRequiredBefore
 if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
 Left.Tok.getIdentifierInfo())
   return false;
+if (Right.is(tok::l_paren) &&
+Left.isOneOf(tok::kw_throw, Keywords.kw_await, tok::kw_void))
+  return true;
 if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
   tok::kw_const) ||
  // "of" is only a keyword if it appears after another identifier

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=309710&r1=309709&r2=309710&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Aug  1 10:22:15 2017
@@ -259,6 +259,15 @@ TEST_F(FormatTestJS, ReservedWordsMethod
   "}\n");
 }
 
+TEST_F(FormatTestJS, ReservedWordsParenthesized) {
+  // All of these are statements using the keyword, not function calls.
+  verifyFormat("throw (x + y);\n"
+   "await (await x).y;\n"
+   "void (0);\n"
+   "delete (x.y);\n"
+   "return (x);\n");
+}
+
 TEST_F(FormatTestJS, CppKeywords) {
   // Make sure we don't mess stuff up because of C++ keywords.
   verifyFormat("return operator && (aa);");


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r309712 - clang-format: [JS] prefer wrapping chains over empty literals.

2017-08-01 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Aug  1 10:35:57 2017
New Revision: 309712

URL: http://llvm.org/viewvc/llvm-project?rev=309712&view=rev
Log:
clang-format: [JS] prefer wrapping chains over empty literals.

Summary:
E.g. don't wrap like this:

(foo.bar.baz).and.bam(Blah.of({
}))

But rather:

(foo.bar.baz)
.and.bam(Blah.of({}))

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36139

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=309712&r1=309711&r2=309712&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Aug  1 10:35:57 2017
@@ -2006,6 +2006,9 @@ unsigned TokenAnnotator::splitPenalty(co
 if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
 (Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
   return 100;
+// Prefer breaking call chains (".foo") over empty "{}", "[]" or "()".
+if (Left.opensScope() && Right.closesScope())
+  return 200;
   }
 
   if (Right.is(tok::identifier) && Right.Next && 
Right.Next->is(TT_DictLiteral))

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=309712&r1=309711&r2=309712&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Aug  1 10:35:57 2017
@@ -841,6 +841,15 @@ TEST_F(FormatTestJS, FunctionLiterals) {
 
 }
 
+TEST_F(FormatTestJS, DontWrapEmptyLiterals) {
+  verifyFormat("(a.getData as jasmine.Spy)\n"
+   ".and.returnValue(Observable.of([]));");
+  verifyFormat("(a.getData as jasmine.Spy)\n"
+   ".and.returnValue(Observable.of({}));");
+  verifyFormat("(a.getData as jasmine.Spy)\n"
+   ".and.returnValue(Observable.of(()));");
+}
+
 TEST_F(FormatTestJS, InliningFunctionLiterals) {
   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r309713 - clang-format: [JS] no whitespace between typeof operator and l_paren.

2017-08-01 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Aug  1 10:42:16 2017
New Revision: 309713

URL: http://llvm.org/viewvc/llvm-project?rev=309713&view=rev
Log:
clang-format: [JS] no whitespace between typeof operator and l_paren.

Modified:
cfe/trunk/lib/Format/FormatToken.h
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/FormatToken.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=309713&r1=309712&r2=309713&view=diff
==
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Tue Aug  1 10:42:16 2017
@@ -644,6 +644,7 @@ struct AdditionalKeywords {
 kw_readonly = &IdentTable.get("readonly");
 kw_set = &IdentTable.get("set");
 kw_type = &IdentTable.get("type");
+kw_typeof = &IdentTable.get("typeof");
 kw_var = &IdentTable.get("var");
 kw_yield = &IdentTable.get("yield");
 
@@ -680,7 +681,7 @@ struct AdditionalKeywords {
 JsExtraKeywords = std::unordered_set(
 {kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,
  kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly,
- kw_set, kw_type, kw_var, kw_yield,
+ kw_set, kw_type, kw_typeof, kw_var, kw_yield,
  // Keywords from the Java section.
  kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});
   }
@@ -714,6 +715,7 @@ struct AdditionalKeywords {
   IdentifierInfo *kw_readonly;
   IdentifierInfo *kw_set;
   IdentifierInfo *kw_type;
+  IdentifierInfo *kw_typeof;
   IdentifierInfo *kw_var;
   IdentifierInfo *kw_yield;
 

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=309713&r1=309712&r2=309713&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Aug  1 10:42:16 2017
@@ -2353,7 +2353,7 @@ bool TokenAnnotator::spaceRequiredBefore
 Left.Tok.getIdentifierInfo())
   return false;
 if (Right.is(tok::l_paren) &&
-Left.isOneOf(tok::kw_throw, Keywords.kw_await, tok::kw_void))
+Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof, 
tok::kw_void))
   return true;
 if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
   tok::kw_const) ||

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=309713&r1=309712&r2=309713&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Aug  1 10:42:16 2017
@@ -263,6 +263,7 @@ TEST_F(FormatTestJS, ReservedWordsParent
   // All of these are statements using the keyword, not function calls.
   verifyFormat("throw (x + y);\n"
"await (await x).y;\n"
+   "typeof (x) === 'string';\n"
"void (0);\n"
"delete (x.y);\n"
"return (x);\n");


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r310070 - clang-format: [JS] support fields with case/switch/default labels.

2017-08-04 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Aug  4 10:07:15 2017
New Revision: 310070

URL: http://llvm.org/viewvc/llvm-project?rev=310070&view=rev
Log:
clang-format: [JS] support fields with case/switch/default labels.

Summary:
`case:` and `default:` would normally parse as labels for a `switch` block.
However in TypeScript, they can be used in field declarations, e.g.:

interface I {
  case: string;
}

This change special cases parsing them in declaration lines to avoid wrapping
them.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36148

Modified:
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=310070&r1=310069&r2=310070&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Fri Aug  4 10:07:15 2017
@@ -326,6 +326,11 @@ void UnwrappedLineParser::parseLevel(boo
   break;
 case tok::kw_default:
 case tok::kw_case:
+  if (Style.Language == FormatStyle::LK_JavaScript && 
Line->MustBeDeclaration) {
+// A 'case: string' style field declaration.
+parseStructuralElement();
+break;
+  }
   if (!SwitchLabelEncountered &&
   (Style.IndentCaseLabels || (Line->InPPDirective && Line->Level == 
1)))
 ++Line->Level;
@@ -953,13 +958,22 @@ void UnwrappedLineParser::parseStructura
 parseDoWhile();
 return;
   case tok::kw_switch:
+if (Style.Language == FormatStyle::LK_JavaScript && 
Line->MustBeDeclaration)
+  // 'switch: string' field declaration.
+  break;
 parseSwitch();
 return;
   case tok::kw_default:
+if (Style.Language == FormatStyle::LK_JavaScript && 
Line->MustBeDeclaration)
+  // 'default: string' field declaration.
+  break;
 nextToken();
 parseLabel();
 return;
   case tok::kw_case:
+if (Style.Language == FormatStyle::LK_JavaScript && 
Line->MustBeDeclaration)
+  // 'case: string' field declaration.
+  break;
 parseCaseLabel();
 return;
   case tok::kw_try:

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=310070&r1=310069&r2=310070&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Fri Aug  4 10:07:15 2017
@@ -242,6 +242,12 @@ TEST_F(FormatTestJS, ReservedWords) {
   verifyFormat("var interface = 2;");
   verifyFormat("interface = 2;");
   verifyFormat("x = interface instanceof y;");
+  verifyFormat("interface Test {\n"
+   "  x: string;\n"
+   "  switch: string;\n"
+   "  case: string;\n"
+   "  default: string;\n"
+   "}\n");
 }
 
 TEST_F(FormatTestJS, ReservedWordsMethods) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r310365 - clang-format: [JS] handle single lines comments ending in `\\`.

2017-08-08 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Aug  8 07:52:42 2017
New Revision: 310365

URL: http://llvm.org/viewvc/llvm-project?rev=310365&view=rev
Log:
clang-format: [JS] handle single lines comments ending in `\\`.

Summary:
Previously, clang-format would consider the following code line to be part of
the comment and incorrectly format the rest of the file.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36159

Modified:
cfe/trunk/lib/Format/FormatTokenLexer.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/FormatTokenLexer.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatTokenLexer.cpp?rev=310365&r1=310364&r2=310365&view=diff
==
--- cfe/trunk/lib/Format/FormatTokenLexer.cpp (original)
+++ cfe/trunk/lib/Format/FormatTokenLexer.cpp Tue Aug  8 07:52:42 2017
@@ -529,6 +529,34 @@ FormatToken *FormatTokenLexer::getNextTo
 readRawToken(*FormatTok);
   }
 
+  // JavaScript and Java do not allow to escape the end of the line with a
+  // backslash. Backslashes are syntax errors in plain source, but can occur in
+  // comments. When a single line comment ends with a \, it'll cause the next
+  // line of code to be lexed as a comment, breaking formatting. The code below
+  // finds comments that contain a backslash followed by a line break, 
truncates
+  // the comment token at the backslash, and resets the lexer to restart behind
+  // the backslash.
+  if ((Style.Language == FormatStyle::LK_JavaScript ||
+   Style.Language == FormatStyle::LK_Java) &&
+  FormatTok->is(tok::comment) && FormatTok->TokenText.startswith("//")) {
+size_t BackslashPos = FormatTok->TokenText.find('\\');
+while (BackslashPos != StringRef::npos) {
+  if (BackslashPos + 1 < FormatTok->TokenText.size() &&
+  FormatTok->TokenText[BackslashPos + 1] == '\n') {
+const char *Offset = Lex->getBufferLocation();
+Offset -= FormatTok->TokenText.size();
+Offset += BackslashPos + 1;
+resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset)));
+FormatTok->TokenText = FormatTok->TokenText.substr(0, BackslashPos + 
1);
+FormatTok->ColumnWidth = encoding::columnWidthWithTabs(
+FormatTok->TokenText, FormatTok->OriginalColumn, Style.TabWidth,
+Encoding);
+break;
+  }
+  BackslashPos = FormatTok->TokenText.find('\\', BackslashPos + 1);
+}
+  }
+
   // In case the token starts with escaped newlines, we want to
   // take them into account as whitespace - this pattern is quite frequent
   // in macro definitions.

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=310365&r1=310364&r2=310365&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Aug  8 07:52:42 2017
@@ -2074,5 +2074,27 @@ TEST_F(FormatTestJS, NestedLiterals) {
"};", FourSpaces);
 }
 
+TEST_F(FormatTestJS, BackslashesInComments) {
+  verifyFormat("// hello \\\n"
+   "if (x) foo();\n",
+   "// hello \\\n"
+   " if ( x) \n"
+   "   foo();\n");
+  verifyFormat("/* ignore \\\n"
+   " */\n"
+   "if (x) foo();\n",
+   "/* ignore \\\n"
+   " */\n"
+   " if (  x) foo();\n");
+  verifyFormat("// st \\ art\\\n"
+   "// comment"
+   "// continue \\\n"
+   "formatMe();\n",
+   "// st \\ art\\\n"
+   "// comment"
+   "// continue \\\n"
+   "formatMe( );\n");
+}
+
 } // end namespace tooling
 } // end namespace clang


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r310367 - clang-format: [JS] fix union type spacing in object & array types.

2017-08-08 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Tue Aug  8 08:00:58 2017
New Revision: 310367

URL: http://llvm.org/viewvc/llvm-project?rev=310367&view=rev
Log:
clang-format: [JS] fix union type spacing in object & array types.

Summary:
Previously, clang-format would insert whitespace in union types nested in object
and array types, as it wouldn't recognize those as a type operator:

const x: {foo: number | null};
const x: [number | null];

While this is correct for actual binary operators, clang-format should not
insert whitespace into union and intersection types to mark those:

const x: {foo: number|null};
const x: [number|null];

This change propagates that the context is not an expression by inspecting
the preceding token and marking as non-expression if it was a type colon.

Reviewers: djasper

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D36136

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=310367&r1=310366&r2=310367&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Aug  8 08:00:58 2017
@@ -372,6 +372,10 @@ private:
 
 ScopedContextCreator ContextCreator(*this, tok::l_square, BindingIncrease);
 Contexts.back().IsExpression = true;
+if (Style.Language == FormatStyle::LK_JavaScript && Parent &&
+Parent->is(TT_JsTypeColon))
+  Contexts.back().IsExpression = false;
+
 Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr;
 
 while (CurrentToken) {
@@ -439,6 +443,9 @@ private:
   Contexts.back().ColonIsDictLiteral = true;
   if (Left->BlockKind == BK_BracedInit)
 Contexts.back().IsExpression = true;
+  if (Style.Language == FormatStyle::LK_JavaScript && Left->Previous &&
+  Left->Previous->is(TT_JsTypeColon))
+Contexts.back().IsExpression = false;
 
   while (CurrentToken) {
 if (CurrentToken->is(tok::r_brace)) {
@@ -531,6 +538,8 @@ private:
  !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) ||
 Contexts.back().ContextKind == tok::l_paren ||  // function params
 Contexts.back().ContextKind == tok::l_square || // array type
+(!Contexts.back().IsExpression &&
+ Contexts.back().ContextKind == tok::l_brace) || // object type
 (Contexts.size() == 1 &&
  Line.MustBeDeclaration)) { // method/property declaration
   Contexts.back().IsExpression = false;

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=310367&r1=310366&r2=310367&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Aug  8 08:00:58 2017
@@ -1363,6 +1363,18 @@ TEST_F(FormatTestJS, UnionIntersectionTy
"};");
 }
 
+TEST_F(FormatTestJS, UnionIntersectionTypesInObjectType) {
+  verifyFormat("let x: {x: number|null} = {x: number | null};");
+  verifyFormat("let nested: {x: {y: number|null}};");
+  verifyFormat("let mixed: {x: [number|null, {w: number}]};");
+  verifyFormat("class X {\n"
+   "  contructor(x: {\n"
+   "a: a|null,\n"
+   "b: b|null,\n"
+   "  }) {}\n"
+   "}");
+}
+
 TEST_F(FormatTestJS, ClassDeclarations) {
   verifyFormat("class C {\n  x: string = 12;\n}");
   verifyFormat("class C {\n  x(): string => 12;\n}");


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r310482 - clang-format: [JS] detect ASI after closing parens.

2017-08-09 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Wed Aug  9 08:19:16 2017
New Revision: 310482

URL: http://llvm.org/viewvc/llvm-project?rev=310482&view=rev
Log:
clang-format: [JS] detect ASI after closing parens.

Summary: A closing parenthesis followed by a declaration or statement should 
always terminate the current statement.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36491

Modified:
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=310482&r1=310481&r2=310482&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Wed Aug  9 08:19:16 2017
@@ -853,7 +853,8 @@ void UnwrappedLineParser::readTokenWithJ
Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
  tok::minusminus)))
 return addUnwrappedLine();
-  if (PreviousMustBeValue && isJSDeclOrStmt(Keywords, Next))
+  if ((PreviousMustBeValue || Previous->is(tok::r_paren)) &&
+  isJSDeclOrStmt(Keywords, Next))
 return addUnwrappedLine();
 }
 

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=310482&r1=310481&r2=310482&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Wed Aug  9 08:19:16 2017
@@ -1106,6 +1106,10 @@ TEST_F(FormatTestJS, WrapRespectsAutomat
"  readonly ratherLongField = 1;\n"
"}",
getGoogleJSStyleWithColumns(20));
+  verifyFormat("const x = (5 + 9)\n"
+   "const y = 3\n",
+   "const x = (   5 +9)\n"
+   "const y = 3\n");
 }
 
 TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r310851 - clang-format: [JS] do not insert whitespace in call positions.

2017-08-14 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Aug 14 09:08:16 2017
New Revision: 310851

URL: http://llvm.org/viewvc/llvm-project?rev=310851&view=rev
Log:
clang-format: [JS] do not insert whitespace in call positions.

Summary:
In JavaScript, may keywords can be used in method names and thus call sites:

foo.delete();
foo.instanceof();

clang-format would previously insert whitespace after the `instanceof`. This
change generically skips inserting whitespace between a keyword and a
parenthesis if preceded by a dot, i.e. in a callsite.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D36142

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=310851&r1=310850&r2=310851&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon Aug 14 09:08:16 2017
@@ -2367,13 +2367,20 @@ bool TokenAnnotator::spaceRequiredBefore
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield,
  Keywords.kw_extends, Keywords.kw_implements))
   return true;
-// JS methods can use some keywords as names (e.g. `delete()`).
-if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
-Left.Tok.getIdentifierInfo())
-  return false;
-if (Right.is(tok::l_paren) &&
-Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof, 
tok::kw_void))
-  return true;
+if (Right.is(tok::l_paren)) {
+  // JS methods can use some keywords as names (e.g. `delete()`).
+  if (Line.MustBeDeclaration && Left.Tok.getIdentifierInfo())
+return false;
+  // Valid JS method names can include keywords, e.g. `foo.delete()` or
+  // `bar.instanceof()`. Recognize call positions by preceding period.
+  if (Left.Previous && Left.Previous->is(tok::period) &&
+  Left.Tok.getIdentifierInfo())
+return false;
+  // Additional unary JavaScript operators that need a space after.
+  if (Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof,
+   tok::kw_void))
+return true;
+}
 if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
   tok::kw_const) ||
  // "of" is only a keyword if it appears after another identifier

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=310851&r1=310850&r2=310851&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon Aug 14 09:08:16 2017
@@ -271,14 +271,21 @@ TEST_F(FormatTestJS, ReservedWords) {
   verifyFormat("x.case = 1;");
   verifyFormat("x.interface = 1;");
   verifyFormat("x.for = 1;");
-  verifyFormat("x.of() = 1;");
+  verifyFormat("x.of();");
   verifyFormat("of(null);");
   verifyFormat("import {of} from 'x';");
-  verifyFormat("x.in() = 1;");
-  verifyFormat("x.let() = 1;");
-  verifyFormat("x.var() = 1;");
-  verifyFormat("x.for() = 1;");
-  verifyFormat("x.as() = 1;");
+  verifyFormat("x.in();");
+  verifyFormat("x.let();");
+  verifyFormat("x.var();");
+  verifyFormat("x.for();");
+  verifyFormat("x.as();");
+  verifyFormat("x.instanceof();");
+  verifyFormat("x.switch();");
+  verifyFormat("x.case();");
+  verifyFormat("x.delete();");
+  verifyFormat("x.throw();");
+  verifyFormat("x.throws();");
+  verifyFormat("x.if();");
   verifyFormat("x = {\n"
"  a: 12,\n"
"  interface: 1,\n"
@@ -1228,7 +1235,6 @@ TEST_F(FormatTestJS, TryCatch) {
   // But, of course, "catch" is a perfectly fine function name in JavaScript.
   verifyFormat("someObject.catch();");
   verifyFormat("someObject.new();");
-  verifyFormat("someObject.delete();");
 }
 
 TEST_F(FormatTestJS, StringLiteralConcatenation) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r310852 - clang-format: [JS] wrap optional properties in type aliases.

2017-08-14 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Aug 14 09:09:08 2017
New Revision: 310852

URL: http://llvm.org/viewvc/llvm-project?rev=310852&view=rev
Log:
clang-format: [JS] wrap optional properties in type aliases.

Summary:
clang-format wraps object literal keys in an object literal if they are
marked as `TT_SelectorName`s and/or the colon is marked as
`TT_DictLiteral`. Previously, clang-format would accidentally work
because colons in type aliases were marked as `TT_DictLiteral`. r310367
fixed this to assing `TT_JsTypeColon`, which broke wrapping in certain
situations. However the root cause was that clang-format incorrectly
didn't skip questionmarks when detecting selector name.

This change fixes both locations to (1) assign `TT_SelectorName` and (2)
treat `TT_JsTypeColon` like `TT_DictLiteral`.

Previously:

type X = {
  a: string, b?: string,
};

Now:

type X = {
  a: string,
  b?: string,
};

Reviewers: djasper, sammccall

Subscribers: cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D36684

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=310852&r1=310851&r2=310852&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon Aug 14 09:09:08 2017
@@ -459,6 +459,8 @@ private:
 updateParameterCount(Left, CurrentToken);
 if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) {
   FormatToken *Previous = CurrentToken->getPreviousNonComment();
+  if (Previous->is(TT_JsTypeOptionalQuestion))
+Previous = Previous->getPreviousNonComment();
   if (((CurrentToken->is(tok::colon) &&
 (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) ||
Style.Language == FormatStyle::LK_Proto ||
@@ -1601,7 +1603,7 @@ private:
   if (Current->is(TT_ConditionalExpr))
 return prec::Conditional;
   if (NextNonComment && Current->is(TT_SelectorName) &&
-  (NextNonComment->is(TT_DictLiteral) ||
+  (NextNonComment->isOneOf(TT_DictLiteral, TT_JsTypeColon) ||
((Style.Language == FormatStyle::LK_Proto ||
  Style.Language == FormatStyle::LK_TextProto) &&
 NextNonComment->is(tok::less

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=310852&r1=310851&r2=310852&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon Aug 14 09:09:08 2017
@@ -1561,6 +1561,10 @@ TEST_F(FormatTestJS, TypeAliases) {
"  y: number\n"
"};\n"
"class C {}");
+  verifyFormat("export type X = {\n"
+   "  a: string,\n"
+   "  b?: string,\n"
+   "};\n");
 }
 
 TEST_F(FormatTestJS, TypeInterfaceLineWrapping) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 736a380 - clang-format: [JS] tests for async wrapping.

2020-01-16 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2020-01-16T11:23:11+01:00
New Revision: 736a3802124b57490fa1e67538415a2a77fa731c

URL: 
https://github.com/llvm/llvm-project/commit/736a3802124b57490fa1e67538415a2a77fa731c
DIFF: 
https://github.com/llvm/llvm-project/commit/736a3802124b57490fa1e67538415a2a77fa731c.diff

LOG: clang-format: [JS] tests for async wrapping.

Summary:
Adds tests to ensure that `async method() ...` does not wrap between async and
the method name, which would cause automatic semicolon insertion.

Reviewers: krasimir

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D70377

Added: 


Modified: 
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index 619a19f1a22d..f5be0d7a4ab1 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -737,6 +737,22 @@ TEST_F(FormatTestJS, AsyncFunctions) {
"   function a() {\n"
"  return   1;\n"
"}  \n");
+  // clang-format must not insert breaks between async and function, otherwise
+  // automatic semicolon insertion may trigger (in particular in a class body).
+  verifyFormat("async function\n"
+   "hello(\n"
+   "myparamnameiswaytoolng) {\n"
+   "}",
+   "async function hello(myparamnameiswaytoolng) {}",
+   getGoogleJSStyleWithColumns(10));
+  verifyFormat("class C {\n"
+   "  async hello(\n"
+   "  myparamnameiswaytoolng) {\n"
+   "  }\n"
+   "}",
+   "class C {\n"
+   "  async hello(myparamnameiswaytoolng) {} }",
+   getGoogleJSStyleWithColumns(10));
   verifyFormat("async function* f() {\n"
"  yield fetch(x);\n"
"}");



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 16212b8 - clang-format: [JS] support new assignment operators.

2020-11-10 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2020-11-10T09:26:46+01:00
New Revision: 16212b8b3e4fd5fbb73aecabf6f0b6fec91913d2

URL: 
https://github.com/llvm/llvm-project/commit/16212b8b3e4fd5fbb73aecabf6f0b6fec91913d2
DIFF: 
https://github.com/llvm/llvm-project/commit/16212b8b3e4fd5fbb73aecabf6f0b6fec91913d2.diff

LOG: clang-format: [JS] support new assignment operators.

Before:

a && = b;

After:

a &&= b;

These operators are new additions in ES2021.

Differential Revision: https://reviews.llvm.org/D91132

Added: 


Modified: 
clang/lib/Format/FormatToken.h
clang/lib/Format/FormatTokenLexer.cpp
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index a3cb81f1b1ef..d53c016fd4db 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -68,6 +68,9 @@ namespace format {
   TYPE(JsTypeColon)
\
   TYPE(JsTypeOperator) 
\
   TYPE(JsTypeOptionalQuestion) 
\
+  TYPE(JsAndAndEqual)  
\
+  TYPE(JsPipePipeEqual)
\
+  TYPE(JsNullishCoalescingEqual)   
\
   TYPE(LambdaArrow)
\
   TYPE(LambdaLBrace)   
\
   TYPE(LambdaLSquare)  
\

diff  --git a/clang/lib/Format/FormatTokenLexer.cpp 
b/clang/lib/Format/FormatTokenLexer.cpp
index 2415da3a7ffb..8733834a079a 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -121,6 +121,10 @@ void FormatTokenLexer::tryMergePreviousTokens() {
tok::period};
 static const tok::TokenKind JSNullishOperator[] = {tok::question,
tok::question};
+static const tok::TokenKind JSNullishEqual[] = {tok::question,
+tok::question, tok::equal};
+static const tok::TokenKind JSPipePipeEqual[] = {tok::pipepipe, 
tok::equal};
+static const tok::TokenKind JSAndAndEqual[] = {tok::ampamp, tok::equal};
 
 // FIXME: Investigate what token type gives the correct operator priority.
 if (tryMergeTokens(JSIdentity, TT_BinaryOperator))
@@ -148,6 +152,13 @@ void FormatTokenLexer::tryMergePreviousTokens() {
   Tokens.back()->Tok.setKind(tok::period);
   return;
 }
+if (tryMergeTokens(JSAndAndEqual, TT_JsAndAndEqual) ||
+tryMergeTokens(JSPipePipeEqual, TT_JsPipePipeEqual) ||
+tryMergeTokens(JSNullishEqual, TT_JsNullishCoalescingEqual)) {
+  // Treat like the "=" assignment operator.
+  Tokens.back()->Tok.setKind(tok::equal);
+  return;
+}
 if (tryMergeJSPrivateIdentifier())
   return;
   }

diff  --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index d140fe581f2a..84d76c67764a 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -2424,6 +2424,15 @@ TEST_F(FormatTestJS, NullishCoalescingOperator) {
   getGoogleJSStyleWithColumns(40));
 }
 
+TEST_F(FormatTestJS, AssignmentOperators) {
+  verifyFormat("a &&= b;\n");
+  verifyFormat("a ||= b;\n");
+  // NB: need to split ? ?= to avoid it being interpreted by C++ as a trigraph
+  // for #.
+  verifyFormat("a ?"
+   "?= b;\n");
+}
+
 TEST_F(FormatTestJS, Conditional) {
   verifyFormat("y = x ? 1 : 2;");
   verifyFormat("x ? 1 : 2;");



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 63042d4 - clang-format: [JS] don't sort named imports if off.

2021-06-11 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2021-06-11T12:02:33+02:00
New Revision: 63042d46bb0c2481a8b7aa1c324405c2720b3603

URL: 
https://github.com/llvm/llvm-project/commit/63042d46bb0c2481a8b7aa1c324405c2720b3603
DIFF: 
https://github.com/llvm/llvm-project/commit/63042d46bb0c2481a8b7aa1c324405c2720b3603.diff

LOG: clang-format: [JS] don't sort named imports if off.

The previous implementation would accidentally still sort the individual
named imports, even if the module reference was in a clang-format off
block.

Differential Revision: https://reviews.llvm.org/D104101

Added: 


Modified: 
clang/lib/Format/SortJavaScriptImports.cpp
clang/unittests/Format/SortImportsTestJS.cpp

Removed: 




diff  --git a/clang/lib/Format/SortJavaScriptImports.cpp 
b/clang/lib/Format/SortJavaScriptImports.cpp
index 4b88ece02a109..901204c297f9d 100644
--- a/clang/lib/Format/SortJavaScriptImports.cpp
+++ b/clang/lib/Format/SortJavaScriptImports.cpp
@@ -317,6 +317,11 @@ class JavaScriptImportSorter : public TokenAnalyzer {
 
   // Appends ``Reference`` to ``Buffer``.
   void appendReference(std::string &Buffer, JsModuleReference &Reference) {
+if (Reference.FormattingOff) {
+  Buffer +=
+  getSourceText(Reference.Range.getBegin(), Reference.Range.getEnd());
+  return;
+}
 // Sort the individual symbols within the import.
 // E.g. `import {b, a} from 'x';` -> `import {a, b} from 'x';`
 SmallVector Symbols = Reference.Symbols;

diff  --git a/clang/unittests/Format/SortImportsTestJS.cpp 
b/clang/unittests/Format/SortImportsTestJS.cpp
index 031dadaaa7a22..4b426375cfea8 100644
--- a/clang/unittests/Format/SortImportsTestJS.cpp
+++ b/clang/unittests/Format/SortImportsTestJS.cpp
@@ -431,6 +431,17 @@ TEST_F(SortImportsTestJS, RespectsClangFormatOff) {
  "// clang-format off\n");
 }
 
+TEST_F(SortImportsTestJS, RespectsClangFormatOffInNamedImports) {
+  verifySort("// clang-format off\n"
+ "import {B, A} from './b';\n"
+ "// clang-format on\n"
+ "const x = 1;",
+ "// clang-format off\n"
+ "import {B, A} from './b';\n"
+ "// clang-format on\n"
+ "const x =   1;");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] a7638d3 - clang-format: [JS] support null operators.

2019-11-11 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2019-11-11T16:35:35+01:00
New Revision: a7638d384983e8e3eb44a2d8c757238efc7096dc

URL: 
https://github.com/llvm/llvm-project/commit/a7638d384983e8e3eb44a2d8c757238efc7096dc
DIFF: 
https://github.com/llvm/llvm-project/commit/a7638d384983e8e3eb44a2d8c757238efc7096dc.diff

LOG: clang-format: [JS] support null operators.

Summary:
JavaScript / TypeScript is adding two new operators: the null
propagating operator `?.` and the nullish coalescing operator `??`.

const x = foo ?? 'default';
const z = foo?.bar?.baz;

This change adds support to lex and format both.

Reviewers: krasimir

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D69971

Added: 


Modified: 
clang/lib/Format/FormatToken.h
clang/lib/Format/FormatTokenLexer.cpp
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index b11f36559a8b..39498280fb6d 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -60,6 +60,8 @@ namespace format {
   TYPE(JsExponentiationEqual)  
\
   TYPE(JsFatArrow) 
\
   TYPE(JsNonNullAssertion) 
\
+  TYPE(JsNullishCoalescingOperator)
\
+  TYPE(JsNullPropagatingOperator)  
\
   TYPE(JsPrivateIdentifier)
\
   TYPE(JsTypeColon)
\
   TYPE(JsTypeOperator) 
\

diff  --git a/clang/lib/Format/FormatTokenLexer.cpp 
b/clang/lib/Format/FormatTokenLexer.cpp
index 5d8a77577c0b..ef20ba884fb3 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -100,6 +100,10 @@ void FormatTokenLexer::tryMergePreviousTokens() {
 static const tok::TokenKind JSExponentiation[] = {tok::star, tok::star};
 static const tok::TokenKind JSExponentiationEqual[] = {tok::star,
tok::starequal};
+static const tok::TokenKind JSNullPropagatingOperator[] = {tok::question,
+   tok::period};
+static const tok::TokenKind JSNullishOperator[] = {tok::question,
+   tok::question};
 
 // FIXME: Investigate what token type gives the correct operator priority.
 if (tryMergeTokens(JSIdentity, TT_BinaryOperator))
@@ -116,6 +120,14 @@ void FormatTokenLexer::tryMergePreviousTokens() {
   Tokens.back()->Tok.setKind(tok::starequal);
   return;
 }
+if (tryMergeTokens(JSNullishOperator, TT_JsNullishCoalescingOperator))
+  return;
+if (tryMergeTokens(JSNullPropagatingOperator,
+   TT_JsNullPropagatingOperator)) {
+  // Treat like a regular "." access.
+  Tokens.back()->Tok.setKind(tok::period);
+  return;
+}
 if (tryMergeJSPrivateIdentifier())
   return;
   }

diff  --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index ca2093a05cce..30a0b37ef69b 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -,6 +,16 @@ TEST_F(FormatTestJS, NonNullAssertionOperator) {
   verifyFormat("return !!x;\n");
 }
 
+TEST_F(FormatTestJS, NullPropagatingOperator) {
+  verifyFormat("let x = foo?.bar?.baz();\n");
+  verifyFormat("let x = foo?.(foo);\n");
+  verifyFormat("let x = foo?.['arr'];\n");
+}
+
+TEST_F(FormatTestJS, NullishCoalescingOperator) {
+  verifyFormat("const val = something ?? 'some other default';\n");
+}
+
 TEST_F(FormatTestJS, Conditional) {
   verifyFormat("y = x ? 1 : 2;");
   verifyFormat("x ? 1 : 2;");



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 6bcd8d4 - clang-format: [JS] test declared fields.

2019-11-11 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2019-11-11T16:36:00+01:00
New Revision: 6bcd8d4a18fc0604a2297a626c1fc808cbfb7b9b

URL: 
https://github.com/llvm/llvm-project/commit/6bcd8d4a18fc0604a2297a626c1fc808cbfb7b9b
DIFF: 
https://github.com/llvm/llvm-project/commit/6bcd8d4a18fc0604a2297a626c1fc808cbfb7b9b.diff

LOG: clang-format: [JS] test declared fields.

Summary:
TypeScript now supports declaring fields:

class Foo {
  declare field: string;
}

clang-format happens to already format this fine, so this change just
adds a regression test.

Reviewers: krasimir

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D69972

Added: 


Modified: 
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index 30a0b37ef69b..619a19f1a22d 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -2369,5 +2369,12 @@ TEST_F(FormatTestJS, SupportPrivateFieldsAndMethods) {
"  static #staticPrivateMethod() {}\n");
 }
 
+TEST_F(FormatTestJS, DeclaredFields) {
+  verifyFormat("class Example {\n"
+   "  declare pub: string;\n"
+   "  declare private priv: string;\n"
+   "}\n");
+}
+
 } // namespace format
 } // end namespace clang



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] dc04c54 - clang-format: [JS] document InsertTrailingCommas.

2020-02-02 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2020-02-03T08:51:52+01:00
New Revision: dc04c54fc1f6660770040f9a17ea600ce95e4b60

URL: 
https://github.com/llvm/llvm-project/commit/dc04c54fc1f6660770040f9a17ea600ce95e4b60
DIFF: 
https://github.com/llvm/llvm-project/commit/dc04c54fc1f6660770040f9a17ea600ce95e4b60.diff

LOG: clang-format: [JS] document InsertTrailingCommas.

Summary: In release notes and the regular docs.

Reviewers: MyDeveloperDay

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D73768

Added: 


Modified: 
clang/docs/ClangFormatStyleOptions.rst
clang/docs/ReleaseNotes.rst

Removed: 




diff  --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 981542451b29..0c515922e650 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -717,6 +717,26 @@ the configuration (without a prefix: ``Auto``).
 aaa);
 }
 
+
+**InsertTrailingCommas** (``TrailingCommaStyle``) can be set to ``TCS_Wrapped``
+  to insert trailing commas in container literals (arrays and objects) that 
wrap
+  across multiple lines. It is currently only available for JavaScript and
+  disabled by default (``TCS_None``).
+
+  ``InsertTrailingCommas`` cannot be used together with ``BinPackArguments`` as
+  inserting the comma disables bin-packing.
+
+  .. code-block:: c++
+
+TSC_Wrapped:
+const someArray = [
+  aa,
+  aa,
+  aa,
+  //^ inserted
+]
+
+
 **BinPackParameters** (``bool``)
   If ``false``, a function declaration's or function definition's
   parameters will either all be on the same line or will have one line each.

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index eae0dfb12151..cb8d73932bf6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -175,6 +175,11 @@ clang-format
   }
 }
 
+- Option ``InsertTrailingCommas`` can be set to ``TCS_Wrapped`` to insert
+  trailing commas in container literals (arrays and objects) that wrap across
+  multiple lines. It is currently only available for JavaScript and disabled by
+  default (``TCS_None``).
+
 libclang
 
 



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 0734fb2 - clang-format: [JS] Handle more keyword-named methods.

2020-01-17 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2020-01-17T10:10:16+01:00
New Revision: 0734fb21ed5e267dda1a91e5f8b82f653ac3562d

URL: 
https://github.com/llvm/llvm-project/commit/0734fb21ed5e267dda1a91e5f8b82f653ac3562d
DIFF: 
https://github.com/llvm/llvm-project/commit/0734fb21ed5e267dda1a91e5f8b82f653ac3562d.diff

LOG: clang-format: [JS] Handle more keyword-named methods.

Summary:
Including `do`, `for`, and `while`, `if`, `else`, `try`, `catch`, in
addition to the previously handled fields. The unit test explicitly uses
methods, but this code path handles both fields and methods.

Reviewers: krasimir

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D72827

Added: 


Modified: 
clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/lib/Format/UnwrappedLineParser.cpp 
b/clang/lib/Format/UnwrappedLineParser.cpp
index ead6b4743207..18b4cc5306f5 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1011,13 +1011,22 @@ void UnwrappedLineParser::parseStructuralElement() {
   parseAccessSpecifier();
 return;
   case tok::kw_if:
+if (Style.Language == FormatStyle::LK_JavaScript && 
Line->MustBeDeclaration)
+  // field/method declaration.
+  break;
 parseIfThenElse();
 return;
   case tok::kw_for:
   case tok::kw_while:
+if (Style.Language == FormatStyle::LK_JavaScript && 
Line->MustBeDeclaration)
+  // field/method declaration.
+  break;
 parseForOrWhileLoop();
 return;
   case tok::kw_do:
+if (Style.Language == FormatStyle::LK_JavaScript && 
Line->MustBeDeclaration)
+  // field/method declaration.
+  break;
 parseDoWhile();
 return;
   case tok::kw_switch:
@@ -1045,6 +1054,9 @@ void UnwrappedLineParser::parseStructuralElement() {
 return;
   case tok::kw_try:
   case tok::kw___try:
+if (Style.Language == FormatStyle::LK_JavaScript && 
Line->MustBeDeclaration)
+  // field/method declaration.
+  break;
 parseTryCatch();
 return;
   case tok::kw_extern:
@@ -1290,6 +1302,12 @@ void UnwrappedLineParser::parseStructuralElement() {
   // element continues.
   break;
 case tok::kw_try:
+  if (Style.Language == FormatStyle::LK_JavaScript &&
+  Line->MustBeDeclaration) {
+// field/method declaration.
+nextToken();
+break;
+  }
   // We arrive here when parsing function-try blocks.
   if (Style.BraceWrapping.AfterFunction)
 addUnwrappedLine();

diff  --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index f5be0d7a4ab1..0150b43a0787 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -358,6 +358,22 @@ TEST_F(FormatTestJS, ReservedWordsMethods) {
   "x();\n"
   "  }\n"
   "}\n");
+  verifyFormat("class KeywordNamedMethods {\n"
+   "  do() {\n"
+   "  }\n"
+   "  for() {\n"
+   "  }\n"
+   "  while() {\n"
+   "  }\n"
+   "  if() {\n"
+   "  }\n"
+   "  else() {\n"
+   "  }\n"
+   "  try() {\n"
+   "  }\n"
+   "  catch() {\n"
+   "  }\n"
+   "}\n");
 }
 
 TEST_F(FormatTestJS, ReservedWordsParenthesized) {



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 9835cf1 - clang-format: [JS] pragmas for tslint, tsc.

2020-01-17 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2020-01-17T13:39:05+01:00
New Revision: 9835cf159014f40e8ea655d0bb3a341ef7ec34f7

URL: 
https://github.com/llvm/llvm-project/commit/9835cf159014f40e8ea655d0bb3a341ef7ec34f7
DIFF: 
https://github.com/llvm/llvm-project/commit/9835cf159014f40e8ea655d0bb3a341ef7ec34f7.diff

LOG: clang-format: [JS] pragmas for tslint, tsc.

Summary:
tslint and tsc (the TypeScript compiler itself) use comment pragmas of
the style:

  // tslint:disable-next-line:foo
  // @ts-ignore

These must not be wrapped and must stay on their own line, in isolation.
For tslint, this required adding it to the pragma regexp. The comments
starting with `@` are already left alone, but this change adds test
coverage for them.

Reviewers: krasimir

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D72907

Added: 


Modified: 
clang/lib/Format/Format.cpp
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index f12bca48c630..cce9458cf22f 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -939,9 +939,9 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
 GoogleStyle.BreakBeforeTernaryOperators = false;
-// taze:, triple slash directives (`/// <...`), @see, which is commonly
-// followed by overlong URLs.
-GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|@see)";
+// taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
+// commonly followed by overlong URLs.
+GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
 GoogleStyle.MaxEmptyLinesToKeep = 3;
 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
 GoogleStyle.SpacesInContainerLiterals = false;

diff  --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index 0150b43a0787..ffeb53d9a33c 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -2168,6 +2168,38 @@ TEST_F(FormatTestJS, JSDocAnnotations) {
getGoogleJSStyleWithColumns(20)));
 }
 
+TEST_F(FormatTestJS, TslintComments) {
+  // tslint uses pragma comments that must be on their own line.
+  verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
+   "Comment that needs\n"
+   "// wrapping. Trailing line.\n"
+   "// tslint:disable-next-line:must-be-on-own-line",
+   "// Comment that needs wrapping. Comment that needs wrapping. "
+   "Comment that needs wrapping.\n"
+   "// Trailing line.\n"
+   "// tslint:disable-next-line:must-be-on-own-line");
+}
+
+TEST_F(FormatTestJS, TscComments) {
+  // As above, @ts-ignore and @ts-check comments must be on their own line.
+  verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
+   "Comment that needs\n"
+   "// wrapping. Trailing line.\n"
+   "// @ts-ignore",
+   "// Comment that needs wrapping. Comment that needs wrapping. "
+   "Comment that needs wrapping.\n"
+   "// Trailing line.\n"
+   "// @ts-ignore");
+  verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
+   "Comment that needs\n"
+   "// wrapping. Trailing line.\n"
+   "// @ts-check",
+   "// Comment that needs wrapping. Comment that needs wrapping. "
+   "Comment that needs wrapping.\n"
+   "// Trailing line.\n"
+   "// @ts-check");
+}
+
 TEST_F(FormatTestJS, RequoteStringsSingle) {
   verifyFormat("var x = 'foo';", "var x = \"foo\";");
   verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo'o'\";");



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 4c9d691 - clang-format: [JS] fix `??` opreator wrapping.

2020-01-20 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2020-01-20T17:07:14+01:00
New Revision: 4c9d6914453d970b7b8202b7efd7524b2f0a72ac

URL: 
https://github.com/llvm/llvm-project/commit/4c9d6914453d970b7b8202b7efd7524b2f0a72ac
DIFF: 
https://github.com/llvm/llvm-project/commit/4c9d6914453d970b7b8202b7efd7524b2f0a72ac.diff

LOG: clang-format: [JS] fix `??` opreator wrapping.

Summary:
clang-format currently treats the nullish coalescing operator `??` like
the ternary operator. That causes multiple nullish terms to be each
indented relative to the last `??`, as they would in a ternary.

The `??` operator is often used in chains though, and as such more
similar to other binary operators, such as `||`. So to fix the indent,
set its token type to `||`, so it inherits the same treatment.

This opens up the question of operator precedence. However, `??` is
required to be parenthesized when mixed with `||` and `&&`, so this is
not a problem that can come up in syntactically legal code.

Reviewers: krasimir

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D73026

Added: 


Modified: 
clang/lib/Format/FormatTokenLexer.cpp
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/lib/Format/FormatTokenLexer.cpp 
b/clang/lib/Format/FormatTokenLexer.cpp
index ef20ba884fb3..9c9fee2b0c32 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -120,8 +120,11 @@ void FormatTokenLexer::tryMergePreviousTokens() {
   Tokens.back()->Tok.setKind(tok::starequal);
   return;
 }
-if (tryMergeTokens(JSNullishOperator, TT_JsNullishCoalescingOperator))
+if (tryMergeTokens(JSNullishOperator, TT_JsNullishCoalescingOperator)) {
+  // Treat like the "||" operator (as opposed to the ternary ?).
+  Tokens.back()->Tok.setKind(tok::pipepipe);
   return;
+}
 if (tryMergeTokens(JSNullPropagatingOperator,
TT_JsNullPropagatingOperator)) {
   // Treat like a regular "." access.

diff  --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index ffeb53d9a33c..ef3c6361355a 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -2294,6 +2294,11 @@ TEST_F(FormatTestJS, NullPropagatingOperator) {
 
 TEST_F(FormatTestJS, NullishCoalescingOperator) {
   verifyFormat("const val = something ?? 'some other default';\n");
+  verifyFormat(
+  "const val = something ?? otherDefault ??\n"
+  "evenMore ?? evenMore;\n",
+  "const val = something ?? otherDefault ?? evenMore ?? evenMore;\n",
+  getGoogleJSStyleWithColumns(40));
 }
 
 TEST_F(FormatTestJS, Conditional) {



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 02656f2 - clang-format: [JS] options for arrow functions.

2020-01-27 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2020-01-27T16:27:25+01:00
New Revision: 02656f29abda4eedd22e3b2b30bf2f422983514e

URL: 
https://github.com/llvm/llvm-project/commit/02656f29abda4eedd22e3b2b30bf2f422983514e
DIFF: 
https://github.com/llvm/llvm-project/commit/02656f29abda4eedd22e3b2b30bf2f422983514e.diff

LOG: clang-format: [JS] options for arrow functions.

Summary:
clang-format currently always wraps the body of non-empty arrow
functions:

const x = () => {
  z();
};

This change implements support for the `AllowShortLambdasOnASingleLine`
style options, controlling the indent style for arrow function bodies
that have one or fewer statements. SLS_All puts all on a single line,
SLS_Inline only arrow functions used in an inline position.

const x = () => { z(); };

Multi-statement arrow functions continue to be wrapped. Function
expressions (`a = function() {}`) and function/method declarations are
unaffected as well.

Reviewers: krasimir

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D73335

Added: 


Modified: 
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index a962e32f66b0..bc9551756bee 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -939,6 +939,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind 
Language) {
 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
 GoogleStyle.AlignOperands = false;
 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+// TODO: still under discussion whether to switch to SLS_All.
+GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
 GoogleStyle.BreakBeforeTernaryOperators = false;
 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is

diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 723dc5c7ba88..8f9a29ab2f29 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -3144,6 +3144,26 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine 
&Line,
   // JavaScript top-level enum key/value pairs are put on separate lines
   // instead of bin-packing.
   return true;
+if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && Left.Previous &&
+Left.Previous->is(TT_JsFatArrow)) {
+  // JS arrow function (=> {...}).
+  switch (Style.AllowShortLambdasOnASingleLine) {
+  case FormatStyle::SLS_All:
+return false;
+  case FormatStyle::SLS_None:
+return true;
+  case FormatStyle::SLS_Empty:
+return !Left.Children.empty();
+  case FormatStyle::SLS_Inline:
+// allow one-lining inline (e.g. in function call args) and empty arrow
+// functions.
+return (Left.NestingLevel == 0 && Line.Level == 0) &&
+   !Left.Children.empty();
+  default:
+break;
+  }
+}
+
 if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&
 !Left.Children.empty())
   // Support AllowShortFunctionsOnASingleLine for JavaScript.

diff  --git a/clang/unittests/Format/FormatTestJS.cpp 
b/clang/unittests/Format/FormatTestJS.cpp
index ef3c6361355a..3c104b7aadbe 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -459,8 +459,9 @@ TEST_F(FormatTestJS, ContainerLiterals) {
   // Arrow functions in object literals.
   verifyFormat("var x = {\n"
"  y: (a) => {\n"
+   "x();\n"
"return a;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var x = {y: (a) => a};");
 
@@ -486,7 +487,8 @@ TEST_F(FormatTestJS, ContainerLiterals) {
 
   // Object literals can leave out labels.
   verifyFormat("f({a}, () => {\n"
-   "  g();  //\n"
+   "  x;\n"
+   "  g();\n"
"});");
 
   // Keys can be quoted.
@@ -1112,8 +1114,9 @@ TEST_F(FormatTestJS, MultipleFunctionLiterals) {
 
 TEST_F(FormatTestJS, ArrowFunctions) {
   verifyFormat("var x = (a) => {\n"
+   "  x;\n"
"  return a;\n"
-   "};");
+   "};\n");
   verifyFormat("var x = (a) => {\n"
"  function y() {\n"
"return 42;\n"
@@ -1121,6 +1124,7 @@ TEST_F(FormatTestJS, ArrowFunctions) {
"  return a;\n"
"};");
   verifyFormat("var x = (a: type): {some: type} => {\n"
+   "  y;\n"
"  return a;\n"
"};");
   verifyFormat("var x = (a) => a;");
@@ -1147,10 +1151,41 @@ TEST_F(FormatTestJS, ArrowFunctions) {
"// break\n"
  

[clang] a324fcf - clang-format: insert trailing commas into containers.

2020-01-29 Thread Martin Probst via cfe-commits

Author: Martin Probst
Date: 2020-01-29T13:23:54+01:00
New Revision: a324fcf1ae62d065b957e66a9d2f5c18b6259d27

URL: 
https://github.com/llvm/llvm-project/commit/a324fcf1ae62d065b957e66a9d2f5c18b6259d27
DIFF: 
https://github.com/llvm/llvm-project/commit/a324fcf1ae62d065b957e66a9d2f5c18b6259d27.diff

LOG: clang-format: insert trailing commas into containers.

Summary:
This change adds an option to insert trailing commas into container
literals. For example, in JavaScript:

const x = [
  a,
  b,
   ^ inserted if missing.
]

This is implemented as a seperate post-processing pass after formatting
(because formatting might change whether the container literal does or
does not wrap). This keeps the code relatively simple and orthogonal,
though it has the notable drawback that the newly inserted comma is not
taken into account for formatting decisions (e.g. it might exceed the 80
char limit). To avoid exceeding the ColumnLimit, a comma is only
inserted if it fits into the limit.

Trailing comma insertion conceptually conflicts with argument
bin-packing: inserting a comma disables bin-packing, so we cannot do
both. clang-format rejects FormatStyle configurations that do both with
this change.

Reviewers: krasimir, MyDeveloperDay

Subscribers: cfe-commits

Tags: #clang

Added: 


Modified: 
clang/include/clang/Format/Format.h
clang/lib/Format/Format.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/FormatTestJS.cpp

Removed: 




diff  --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 09a0556ab4c6..3891029a6f3a 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -35,7 +35,12 @@ class DiagnosticConsumer;
 
 namespace format {
 
-enum class ParseError { Success = 0, Error, Unsuitable };
+enum class ParseError {
+  Success = 0,
+  Error,
+  Unsuitable,
+  BinPackTrailingCommaConflict
+};
 class ParseErrorCategory final : public std::error_category {
 public:
   const char *name() const noexcept override;
@@ -544,6 +549,20 @@ struct FormatStyle {
   /// \endcode
   bool BinPackArguments;
 
+  /// The style of inserting trailing commas into container literals.
+  enum TrailingCommaStyle {
+/// Do not insert trailing commas.
+TCS_None,
+/// Insert trailing commas in container literals that were wrapped over
+/// multiple lines. Note that this is conceptually incompatible with
+/// bin-packing, because the trailing comma is used as an indicator
+/// that a container should be formatted one-per-line (i.e. not 
bin-packed).
+/// So inserting a trailing comma counteracts bin-packing.
+TCS_Wrapped,
+  };
+
+  TrailingCommaStyle InsertTrailingCommas;
+
   /// If ``false``, a function declaration's or function definition's
   /// parameters will either all be on the same line or will have one line 
each.
   /// \code

diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index dd131a93362c..6f585ae915a5 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -157,6 +157,13 @@ template <> struct 
ScalarEnumerationTraits {
   }
 };
 
+template <> struct ScalarEnumerationTraits {
+  static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
+IO.enumCase(Value, "None", FormatStyle::TCS_None);
+IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
+  }
+};
+
 template <> struct ScalarEnumerationTraits {
   static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
 IO.enumCase(Value, "All", FormatStyle::BOS_All);
@@ -486,6 +493,7 @@ template <> struct MappingTraits {
 IO.mapOptional("IndentWidth", Style.IndentWidth);
 IO.mapOptional("IndentWrappedFunctionNames",
Style.IndentWrappedFunctionNames);
+IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);
 IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
 IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
 IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
@@ -644,6 +652,8 @@ std::string ParseErrorCategory::message(int EV) const {
 return "Invalid argument";
   case ParseError::Unsuitable:
 return "Unsuitable";
+  case ParseError::BinPackTrailingCommaConflict:
+return "trailing comma insertion cannot be used with bin packing";
   }
   llvm_unreachable("unexpected parse error");
 }
@@ -788,6 +798,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
   LLVMStyle.IndentWrappedFunctionNames = false;
   LLVMStyle.IndentWidth = 2;
+  LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
   LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
   LLVMStyle.JavaScriptWrapImports = true;
   LLVMStyle.TabWidth = 8;
@@ -946,6 +957,9 @@ FormatStyle getGoogleStyle(FormatStyle::Langua

r318537 - clang-format: remove trailing lines in lamdas and arrow functions.

2017-11-17 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Nov 17 10:06:33 2017
New Revision: 318537

URL: http://llvm.org/viewvc/llvm-project?rev=318537&view=rev
Log:
clang-format: remove trailing lines in lamdas and arrow functions.

Summary:
clang-format already removes empty lines at the beginning & end of
blocks:

int x() {

  foo();  // lines before and after will be removed.

}

However because lamdas and arrow functions are parsed as expressions,
the existing logic to remove empty lines in UnwrappedLineFormatter
doesn't handle them.

This change special cases arrow functions in ContinuationIndenter to
remove empty lines:

x = []() {

  foo();  // lines before and after will now be removed.

};

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D40178

Modified:
cfe/trunk/lib/Format/ContinuationIndenter.cpp
cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp
cfe/trunk/unittests/Format/FormatTest.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=318537&r1=318536&r2=318537&view=diff
==
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Fri Nov 17 10:06:33 2017
@@ -701,8 +701,18 @@ unsigned ContinuationIndenter::addTokenO
 State.Stack.back().BreakBeforeParameter = false;
 
   if (!DryRun) {
+unsigned MaxEmptyLinesToKeep = Style.MaxEmptyLinesToKeep + 1;
+if (Current.is(tok::r_brace) && Current.MatchingParen &&
+// Only strip trailing empty lines for l_braces that have children, 
i.e.
+// for function expressions (lambdas, arrows, etc).
+!Current.MatchingParen->Children.empty()) {
+  // lambdas and arrow functions are expressions, thus their r_brace is not
+  // on its own line, and thus not covered by UnwrappedLineFormatter's 
logic
+  // about removing empty lines on closing blocks. Special case them here.
+  MaxEmptyLinesToKeep = 1;
+}
 unsigned Newlines = std::max(
-1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1));
+1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep));
 bool ContinuePPDirective =
 State.Line->InPPDirective && State.Line->Type != LT_ImportStatement;
 Whitespaces.replaceWhitespace(Current, Newlines, State.Column, 
State.Column,

Modified: cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp?rev=318537&r1=318536&r2=318537&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp Fri Nov 17 10:06:33 2017
@@ -1117,6 +1117,9 @@ void UnwrappedLineFormatter::formatFirst
   (!RootToken.Next ||
(RootToken.Next->is(tok::semi) && !RootToken.Next->Next)))
 Newlines = std::min(Newlines, 1u);
+  // Remove empty lines at the start of nested blocks (lambdas/arrow functions)
+  if (PreviousLine == nullptr && Line.Level > 0)
+Newlines = std::min(Newlines, 1u);
   if (Newlines == 0 && !RootToken.IsFirst)
 Newlines = 1;
   if (RootToken.IsFirst && !RootToken.HasUnescapedNewline)

Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=318537&r1=318536&r2=318537&view=diff
==
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Fri Nov 17 10:06:33 2017
@@ -70,18 +70,23 @@ protected:
 return getStyleWithColumns(getGoogleStyle(), ColumnLimit);
   }
 
-  void verifyFormat(llvm::StringRef Code,
+  void verifyFormat(llvm::StringRef Expected, llvm::StringRef Code,
 const FormatStyle &Style = getLLVMStyle()) {
-EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
+EXPECT_EQ(Expected.str(), format(Code, Style));
 if (Style.Language == FormatStyle::LK_Cpp) {
   // Objective-C++ is a superset of C++, so everything checked for C++
   // needs to be checked for Objective-C++ as well.
   FormatStyle ObjCStyle = Style;
   ObjCStyle.Language = FormatStyle::LK_ObjC;
-  EXPECT_EQ(Code.str(), format(test::messUp(Code), ObjCStyle));
+  EXPECT_EQ(Expected.str(), format(test::messUp(Code), ObjCStyle));
 }
   }
 
+  void verifyFormat(llvm::StringRef Code,
+const FormatStyle &Style = getLLVMStyle()) {
+verifyFormat(Code, test::messUp(Code), Style);
+  }
+
   void verifyIncompleteFormat(llvm::StringRef Code,
   const FormatStyle &Style = getLLVMStyle()) {
 EXPECT_EQ(Code.str(),
@@ -11089,6 +11094,17 @@ T

r290959 - clang-format: [JS] avoid indent after ambient function declarations.

2017-01-04 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Wed Jan  4 07:36:43 2017
New Revision: 290959

URL: http://llvm.org/viewvc/llvm-project?rev=290959&view=rev
Log:
clang-format: [JS] avoid indent after ambient function declarations.

Summary:
Before:
  declare function foo();
let x = 1;

After:
  declare function foo();
  let x = 1;

The problem was that clang-format would unconditionally try to parse a child 
block, even though ambient function declarations do not have a body (similar to 
forward declarations).

Reviewers: djasper

Subscribers: cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D28246

Modified:
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=290959&r1=290958&r2=290959&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Wed Jan  4 07:36:43 2017
@@ -1255,10 +1255,13 @@ void UnwrappedLineParser::tryToParseJSFu
 if (FormatTok->is(tok::l_brace))
   tryToParseBracedList();
 else
-  while (FormatTok->isNot(tok::l_brace) && !eof())
+  while (!FormatTok->isOneOf(tok::l_brace, tok::semi) && !eof())
 nextToken();
   }
 
+  if (FormatTok->is(tok::semi))
+return;
+
   parseChildBlock();
 }
 

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=290959&r1=290958&r2=290959&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Wed Jan  4 07:36:43 2017
@@ -377,6 +377,16 @@ TEST_F(FormatTestJS, AmbientDeclarations
   "declare function\n"
   "x();",  // TODO(martinprobst): should ideally be indented.
   NineCols);
+  verifyFormat("declare function foo();\n"
+   "let x = 1;\n");
+  verifyFormat("declare function foo(): string;\n"
+   "let x = 1;\n");
+  verifyFormat("declare function foo(): {x: number};\n"
+   "let x = 1;\n");
+  verifyFormat("declare class X {}\n"
+   "let x = 1;\n");
+  verifyFormat("declare interface Y {}\n"
+   "let x = 1;\n");
   verifyFormat(
   "declare enum X {\n"
   "}",


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r291428 - clang-format: [JS] ASI after imports

2017-01-09 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Jan  9 02:56:36 2017
New Revision: 291428

URL: http://llvm.org/viewvc/llvm-project?rev=291428&view=rev
Log:
clang-format: [JS] ASI after imports

Summary:
Automatic semicolon insertion should break import and export statements:

Before, this would format on one line:

  // Note: no semi after 'x' below!
  import {x} from 'x'
  export function foo() {}

Into:
  import {x} from 'x' export function foo() {}

With this change, the statements get separated.

This also improves automatic semicolon insertion to consider closing
braces preceding declarations and statements.

Reviewers: klimek

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D28465

Modified:
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=291428&r1=291427&r2=291428&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Mon Jan  9 02:56:36 2017
@@ -737,7 +737,7 @@ void UnwrappedLineParser::readTokenWithJ
   return;
   }
   if (Next->is(tok::exclaim) && PreviousMustBeValue)
-addUnwrappedLine();
+return addUnwrappedLine();
   bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next);
   bool NextEndsTemplateExpr =
   Next->is(TT_TemplateString) && Next->TokenText.startswith("}");
@@ -745,9 +745,10 @@ void UnwrappedLineParser::readTokenWithJ
   (PreviousMustBeValue ||
Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
  tok::minusminus)))
-addUnwrappedLine();
-  if (PreviousMustBeValue && isJSDeclOrStmt(Keywords, Next))
-addUnwrappedLine();
+return addUnwrappedLine();
+  if ((PreviousMustBeValue || Previous->is(tok::r_brace)) &&
+  isJSDeclOrStmt(Keywords, Next))
+return addUnwrappedLine();
 }
 
 void UnwrappedLineParser::parseStructuralElement() {
@@ -1974,7 +1975,14 @@ void UnwrappedLineParser::parseJavaScrip
   !FormatTok->isStringLiteral())
 return;
 
-  while (!eof() && FormatTok->isNot(tok::semi)) {
+  while (!eof()) {
+if (FormatTok->is(tok::semi))
+  return;
+if (Line->Tokens.size() == 0) {
+  // Common issue: Automatic Semicolon Insertion wrapped the line, so the
+  // import statement should terminate.
+  return;
+}
 if (FormatTok->is(tok::l_brace)) {
   FormatTok->BlockKind = BK_Block;
   parseBracedList();

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=291428&r1=291427&r2=291428&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon Jan  9 02:56:36 2017
@@ -858,6 +858,24 @@ TEST_F(FormatTestJS, AutomaticSemicolonI
"return 1",
"a = null\n"
"  return   1");
+  verifyFormat(
+  "x = {a: 1}\n"
+  "class Y {}",
+  "  x  =  {a  : 1}\n"
+  "   class  Y {  }");
+}
+
+TEST_F(FormatTestJS, ImportExportASI) {
+  verifyFormat(
+  "import {x} from 'y'\n"
+  "export function z() {}",
+  "import   {x} from 'y'\n"
+  "  export function z() {}");
+  verifyFormat(
+  "export {x}\n"
+  "class Y {}",
+  "  export {x}\n"
+  "  class  Y {\n}");
 }
 
 TEST_F(FormatTestJS, ClosureStyleCasts) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r291429 - clang-format: [JS] fix broken test.

2017-01-09 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Jan  9 03:00:58 2017
New Revision: 291429

URL: http://llvm.org/viewvc/llvm-project?rev=291429&view=rev
Log:
clang-format: [JS] fix broken test.

Modified:
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=291429&r1=291428&r2=291429&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon Jan  9 03:00:58 2017
@@ -859,7 +859,9 @@ TEST_F(FormatTestJS, AutomaticSemicolonI
"a = null\n"
"  return   1");
   verifyFormat(
-  "x = {a: 1}\n"
+  "x = {\n"
+  "  a: 1\n"
+  "}\n"
   "class Y {}",
   "  x  =  {a  : 1}\n"
   "   class  Y {  }");


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D23714: clang-format: [JS] handle object literals with casts.

2016-08-19 Thread Martin Probst via cfe-commits
mprobst created this revision.
mprobst added a reviewer: djasper.
mprobst added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

E.g. `{a: 1} as b`.

https://reviews.llvm.org/D23714

Files:
  lib/Format/UnwrappedLineParser.cpp
  unittests/Format/FormatTestJS.cpp

Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1218,6 +1218,7 @@
"  1,  //\n"
"  2\n"
"];");
+  verifyFormat("var x = [{x: 1} as type];");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {
Index: lib/Format/UnwrappedLineParser.cpp
===
--- lib/Format/UnwrappedLineParser.cpp
+++ lib/Format/UnwrappedLineParser.cpp
@@ -364,7 +364,8 @@
   // We exclude + and - as they can be ObjC visibility modifiers.
   ProbablyBracedList =
   (Style.Language == FormatStyle::LK_JavaScript &&
-   NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in)) ||
+   NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
+Keywords.kw_as)) ||
   NextTok->isOneOf(tok::comma, tok::period, tok::colon,
tok::r_paren, tok::r_square, tok::l_brace,
tok::l_square, tok::l_paren, tok::ellipsis) ||


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1218,6 +1218,7 @@
"  1,  //\n"
"  2\n"
"];");
+  verifyFormat("var x = [{x: 1} as type];");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {
Index: lib/Format/UnwrappedLineParser.cpp
===
--- lib/Format/UnwrappedLineParser.cpp
+++ lib/Format/UnwrappedLineParser.cpp
@@ -364,7 +364,8 @@
   // We exclude + and - as they can be ObjC visibility modifiers.
   ProbablyBracedList =
   (Style.Language == FormatStyle::LK_JavaScript &&
-   NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in)) ||
+   NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
+Keywords.kw_as)) ||
   NextTok->isOneOf(tok::comma, tok::period, tok::colon,
tok::r_paren, tok::r_square, tok::l_brace,
tok::l_square, tok::l_paren, tok::ellipsis) ||
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D22431: clang-format: [JS] nested and tagged template strings.

2016-08-19 Thread Martin Probst via cfe-commits
mprobst updated this revision to Diff 68687.
mprobst added a comment.

- Use a stack to parse nested template strings.
- move docs
- Fold GreaterStashed, LessStashed into TOKEN_STASHED lexer state.


https://reviews.llvm.org/D22431

Files:
  lib/Format/FormatTokenLexer.cpp
  lib/Format/FormatTokenLexer.h
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTestJS.cpp

Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1122,7 +1122,7 @@
 TEST_F(FormatTestJS, TemplateStrings) {
   // Keeps any whitespace/indentation within the template string.
   verifyFormat("var x = `hello\n"
-" ${  name}\n"
+" ${name}\n"
 "  !`;",
 "var x=`hello\n"
" ${  name}\n"
@@ -1208,6 +1208,16 @@
"var y;");
 }
 
+TEST_F(FormatTestJS, NestedTemplateStrings) {
+  verifyFormat(
+  "var x = `${xs.map(x => `${x}`).join('\\n')}`;");
+  verifyFormat("var x = `he${({text: 'll'}.text)}o`;");
+}
+
+TEST_F(FormatTestJS, TaggedTemplateStrings) {
+  verifyFormat("var x = html``;");
+}
+
 TEST_F(FormatTestJS, CastSyntax) {
   verifyFormat("var x = foo;");
   verifyFormat("var x = foo as type;");
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -858,7 +858,7 @@
 if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_ForEachMacro,
TT_FunctionLBrace, TT_ImplicitStringLiteral,
TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow,
-   TT_RegexLiteral))
+   TT_RegexLiteral, TT_TemplateString))
   CurrentToken->Type = TT_Unknown;
 CurrentToken->Role.reset();
 CurrentToken->MatchingParen = nullptr;
@@ -1816,6 +1816,9 @@
   return 100;
 if (Left.is(TT_JsTypeColon))
   return 35;
+if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+(Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+  return 100;
   }
 
   if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next &&
@@ -2114,6 +2117,11 @@
   } else if (Style.Language == FormatStyle::LK_JavaScript) {
 if (Left.is(TT_JsFatArrow))
   return true;
+if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+(Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+  return false;
+if (Left.is(tok::identifier) && Right.is(TT_TemplateString))
+  return false;
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
   return false;
Index: lib/Format/FormatTokenLexer.h
===
--- lib/Format/FormatTokenLexer.h
+++ lib/Format/FormatTokenLexer.h
@@ -23,9 +23,17 @@
 #include "clang/Format/Format.h"
 #include "llvm/Support/Regex.h"
 
+#include 
+
 namespace clang {
 namespace format {
 
+enum LexerState {
+  NORMAL,
+  TEMPLATE_STRING,
+  TOKEN_STASHED,
+};
+
 class FormatTokenLexer {
 public:
   FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
@@ -53,7 +61,16 @@
   // its text if successful.
   void tryParseJSRegexLiteral();
 
-  void tryParseTemplateString();
+  // Handles JavaScript template strings.
+  //
+  // JavaScript template strings use backticks ('`') as delimiters, and allow
+  // embedding expressions nested in ${expr-here}. Template strings can be
+  // nested recursively, i.e. expressions can contain template strings in turns.
+  //
+  // The code below parses starting from a backtick, up to a closing backtick or
+  // an opening ${. It also maintains a stack of lexing contexts to handle
+  // nested template parts by balancing curly braces.
+  void handleTemplateStrings();
 
   bool tryMerge_TMacro();
 
@@ -65,7 +82,7 @@
 
   FormatToken *FormatTok;
   bool IsFirstToken;
-  bool GreaterStashed, LessStashed;
+  std::stack StateStack;
   unsigned Column;
   unsigned TrailingWhitespace;
   std::unique_ptr Lex;
Index: lib/Format/FormatTokenLexer.cpp
===
--- lib/Format/FormatTokenLexer.cpp
+++ lib/Format/FormatTokenLexer.cpp
@@ -26,12 +26,11 @@
 FormatTokenLexer::FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
const FormatStyle &Style,
encoding::Encoding Encoding)
-: FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
-  LessStashed(false), Column(0), TrailingWhitespace(0),
-  SourceMgr(SourceMgr), ID(ID), Style(Style),
-  IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
-  Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false),
-  MacroBlockBeginRegex(Style.MacroBlock

Re: [PATCH] D22431: clang-format: [JS] nested and tagged template strings.

2016-08-19 Thread Martin Probst via cfe-commits
mprobst marked 9 inline comments as done.
mprobst added a comment.

https://reviews.llvm.org/D22431



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r279250 - clang-format: [JS] handle object literals with casts.

2016-08-19 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Aug 19 09:35:01 2016
New Revision: 279250

URL: http://llvm.org/viewvc/llvm-project?rev=279250&view=rev
Log:
clang-format: [JS] handle object literals with casts.

Summary: E.g. `{a: 1} as b`.

Reviewers: djasper

Subscribers: cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D23714

Modified:
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=279250&r1=279249&r2=279250&view=diff
==
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Fri Aug 19 09:35:01 2016
@@ -364,7 +364,8 @@ void UnwrappedLineParser::calculateBrace
   // We exclude + and - as they can be ObjC visibility modifiers.
   ProbablyBracedList =
   (Style.Language == FormatStyle::LK_JavaScript &&
-   NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in)) ||
+   NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
+Keywords.kw_as)) ||
   NextTok->isOneOf(tok::comma, tok::period, tok::colon,
tok::r_paren, tok::r_square, tok::l_brace,
tok::l_square, tok::l_paren, tok::ellipsis) ||

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=279250&r1=279249&r2=279250&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Fri Aug 19 09:35:01 2016
@@ -1218,6 +1218,7 @@ TEST_F(FormatTestJS, CastSyntax) {
"  1,  //\n"
"  2\n"
"];");
+  verifyFormat("var x = [{x: 1} as type];");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D23714: clang-format: [JS] handle object literals with casts.

2016-08-19 Thread Martin Probst via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL279250: clang-format: [JS] handle object literals with 
casts. (authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D23714?vs=68686&id=68688#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D23714

Files:
  cfe/trunk/lib/Format/UnwrappedLineParser.cpp
  cfe/trunk/unittests/Format/FormatTestJS.cpp

Index: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
===
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp
@@ -364,7 +364,8 @@
   // We exclude + and - as they can be ObjC visibility modifiers.
   ProbablyBracedList =
   (Style.Language == FormatStyle::LK_JavaScript &&
-   NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in)) ||
+   NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
+Keywords.kw_as)) ||
   NextTok->isOneOf(tok::comma, tok::period, tok::colon,
tok::r_paren, tok::r_square, tok::l_brace,
tok::l_square, tok::l_paren, tok::ellipsis) ||
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -1218,6 +1218,7 @@
"  1,  //\n"
"  2\n"
"];");
+  verifyFormat("var x = [{x: 1} as type];");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {


Index: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
===
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp
@@ -364,7 +364,8 @@
   // We exclude + and - as they can be ObjC visibility modifiers.
   ProbablyBracedList =
   (Style.Language == FormatStyle::LK_JavaScript &&
-   NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in)) ||
+   NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
+Keywords.kw_as)) ||
   NextTok->isOneOf(tok::comma, tok::period, tok::colon,
tok::r_paren, tok::r_square, tok::l_brace,
tok::l_square, tok::l_paren, tok::ellipsis) ||
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -1218,6 +1218,7 @@
"  1,  //\n"
"  2\n"
"];");
+  verifyFormat("var x = [{x: 1} as type];");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D23761: clang-format: [JS] supports casts to types starting with punctuation ("{[(").

2016-08-21 Thread Martin Probst via cfe-commits
mprobst created this revision.
mprobst added a reviewer: djasper.
mprobst added subscribers: cfe-commits, klimek.

https://reviews.llvm.org/D23761

Files:
  lib/Format/FormatTokenLexer.cpp
  lib/Format/FormatTokenLexer.h
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTestJS.cpp

Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1122,7 +1122,7 @@
 TEST_F(FormatTestJS, TemplateStrings) {
   // Keeps any whitespace/indentation within the template string.
   verifyFormat("var x = `hello\n"
-" ${  name}\n"
+" ${name}\n"
 "  !`;",
 "var x=`hello\n"
" ${  name}\n"
@@ -1206,6 +1206,12 @@
"var y;",
"var x = ` \\` a`;\n"
"var y;");
+  verifyFormat(
+  "var x = `${xs.map(x => `${x}`).join('\\n')}`;");
+}
+
+TEST_F(FormatTestJS, TaggedTemplateStrings) {
+  verifyFormat("var x = html``;");
 }
 
 TEST_F(FormatTestJS, CastSyntax) {
@@ -1219,6 +1225,9 @@
"  2\n"
"];");
   verifyFormat("var x = [{x: 1} as type];");
+  verifyFormat("x = x as [a, b];");
+  verifyFormat("x = x as {a: string};");
+  verifyFormat("x = x as (string);");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -858,7 +858,7 @@
 if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_ForEachMacro,
TT_FunctionLBrace, TT_ImplicitStringLiteral,
TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow,
-   TT_RegexLiteral))
+   TT_RegexLiteral, TT_TemplateString))
   CurrentToken->Type = TT_Unknown;
 CurrentToken->Role.reset();
 CurrentToken->MatchingParen = nullptr;
@@ -1816,6 +1816,9 @@
   return 100;
 if (Left.is(TT_JsTypeColon))
   return 35;
+if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+(Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+  return 100;
   }
 
   if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next &&
@@ -2114,13 +2117,21 @@
   } else if (Style.Language == FormatStyle::LK_JavaScript) {
 if (Left.is(TT_JsFatArrow))
   return true;
+if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+(Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+  return false;
+if (Left.is(tok::identifier) && Right.is(TT_TemplateString))
+  return false;
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
   return false;
 if (Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))
   return true;
+if (Left.is(Keywords.kw_as) &&
+Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren))
+  return true;
 if (Left.is(tok::kw_default) && Left.Previous &&
 Left.Previous->is(tok::kw_export))
   return true;
Index: lib/Format/FormatTokenLexer.h
===
--- lib/Format/FormatTokenLexer.h
+++ lib/Format/FormatTokenLexer.h
@@ -66,6 +66,7 @@
   FormatToken *FormatTok;
   bool IsFirstToken;
   bool GreaterStashed, LessStashed;
+  unsigned TemplateStringDepth;
   unsigned Column;
   unsigned TrailingWhitespace;
   std::unique_ptr Lex;
Index: lib/Format/FormatTokenLexer.cpp
===
--- lib/Format/FormatTokenLexer.cpp
+++ lib/Format/FormatTokenLexer.cpp
@@ -27,8 +27,8 @@
const FormatStyle &Style,
encoding::Encoding Encoding)
 : FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
-  LessStashed(false), Column(0), TrailingWhitespace(0),
-  SourceMgr(SourceMgr), ID(ID), Style(Style),
+  LessStashed(false), TemplateStringDepth(0), Column(0),
+  TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID), Style(Style),
   IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
   Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false),
   MacroBlockBeginRegex(Style.MacroBlockBegin),
@@ -230,15 +230,25 @@
 
 void FormatTokenLexer::tryParseTemplateString() {
   FormatToken *BacktickToken = Tokens.back();
-  if (!BacktickToken->is(tok::unknown) || BacktickToken->TokenText != "`")
+  if (TemplateStringDepth > 0 && BacktickToken->TokenText == "}")
+TemplateStringDepth--;
+  else if (!BacktickToken->is(tok::unknown) ||
+ BacktickToken->TokenText != "`")
 return;
 
   // 

Re: [PATCH] D23761: clang-format: [JS] supports casts to types starting with punctuation ("{[(").

2016-08-22 Thread Martin Probst via cfe-commits
mprobst updated this revision to Diff 68844.
mprobst added a comment.

- drop accidentally included template string patch from this diff.


https://reviews.llvm.org/D23761

Files:
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTestJS.cpp

Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1219,6 +1219,9 @@
"  2\n"
"];");
   verifyFormat("var x = [{x: 1} as type];");
+  verifyFormat("x = x as [a, b];");
+  verifyFormat("x = x as {a: string};");
+  verifyFormat("x = x as (string);");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -2121,6 +2121,9 @@
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))
   return true;
+if (Left.is(Keywords.kw_as) &&
+Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren))
+  return true;
 if (Left.is(tok::kw_default) && Left.Previous &&
 Left.Previous->is(tok::kw_export))
   return true;


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1219,6 +1219,9 @@
"  2\n"
"];");
   verifyFormat("var x = [{x: 1} as type];");
+  verifyFormat("x = x as [a, b];");
+  verifyFormat("x = x as {a: string};");
+  verifyFormat("x = x as (string);");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -2121,6 +2121,9 @@
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))
   return true;
+if (Left.is(Keywords.kw_as) &&
+Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren))
+  return true;
 if (Left.is(tok::kw_default) && Left.Previous &&
 Left.Previous->is(tok::kw_export))
   return true;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D23761: clang-format: [JS] supports casts to types starting with punctuation ("{[(").

2016-08-22 Thread Martin Probst via cfe-commits
mprobst marked an inline comment as done.


Comment at: lib/Format/FormatTokenLexer.cpp:245
@@ -241,1 +244,3 @@
   ++Offset; // Skip the escaped character.
+if (Offset + 1 < Lex->getBuffer().end() && *Offset == '$' &&
+*(Offset + 1) == '{') {

ygao wrote:
> What happens if the '${' is immediately after a backslash (the if statement 
> above), should the '${' get escaped?
Sorry, I accidentally included this in the wrong diff – the template string 
thing is in D22431. I'll answer there.


https://reviews.llvm.org/D23761



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D22431: clang-format: [JS] nested and tagged template strings.

2016-08-22 Thread Martin Probst via cfe-commits
mprobst updated this revision to Diff 68851.
mprobst added a comment.

- Test escaped dollar sign.


https://reviews.llvm.org/D22431

Files:
  lib/Format/FormatTokenLexer.cpp
  lib/Format/FormatTokenLexer.h
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTestJS.cpp

Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1122,7 +1122,7 @@
 TEST_F(FormatTestJS, TemplateStrings) {
   // Keeps any whitespace/indentation within the template string.
   verifyFormat("var x = `hello\n"
-" ${  name}\n"
+" ${name}\n"
 "  !`;",
 "var x=`hello\n"
" ${  name}\n"
@@ -1206,6 +1206,18 @@
"var y;",
"var x = ` \\` a`;\n"
"var y;");
+  // Escaped dollar.
+  verifyFormat("var x = ` \\${foo}`;\n");
+}
+
+TEST_F(FormatTestJS, NestedTemplateStrings) {
+  verifyFormat(
+  "var x = `${xs.map(x => `${x}`).join('\\n')}`;");
+  verifyFormat("var x = `he${({text: 'll'}.text)}o`;");
+}
+
+TEST_F(FormatTestJS, TaggedTemplateStrings) {
+  verifyFormat("var x = html``;");
 }
 
 TEST_F(FormatTestJS, CastSyntax) {
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -858,7 +858,7 @@
 if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_ForEachMacro,
TT_FunctionLBrace, TT_ImplicitStringLiteral,
TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow,
-   TT_RegexLiteral))
+   TT_RegexLiteral, TT_TemplateString))
   CurrentToken->Type = TT_Unknown;
 CurrentToken->Role.reset();
 CurrentToken->MatchingParen = nullptr;
@@ -1816,6 +1816,9 @@
   return 100;
 if (Left.is(TT_JsTypeColon))
   return 35;
+if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+(Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+  return 100;
   }
 
   if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next &&
@@ -2114,6 +2117,11 @@
   } else if (Style.Language == FormatStyle::LK_JavaScript) {
 if (Left.is(TT_JsFatArrow))
   return true;
+if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+(Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+  return false;
+if (Left.is(tok::identifier) && Right.is(TT_TemplateString))
+  return false;
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
   return false;
Index: lib/Format/FormatTokenLexer.h
===
--- lib/Format/FormatTokenLexer.h
+++ lib/Format/FormatTokenLexer.h
@@ -23,9 +23,17 @@
 #include "clang/Format/Format.h"
 #include "llvm/Support/Regex.h"
 
+#include 
+
 namespace clang {
 namespace format {
 
+enum LexerState {
+  NORMAL,
+  TEMPLATE_STRING,
+  TOKEN_STASHED,
+};
+
 class FormatTokenLexer {
 public:
   FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
@@ -53,7 +61,16 @@
   // its text if successful.
   void tryParseJSRegexLiteral();
 
-  void tryParseTemplateString();
+  // Handles JavaScript template strings.
+  //
+  // JavaScript template strings use backticks ('`') as delimiters, and allow
+  // embedding expressions nested in ${expr-here}. Template strings can be
+  // nested recursively, i.e. expressions can contain template strings in turns.
+  //
+  // The code below parses starting from a backtick, up to a closing backtick or
+  // an opening ${. It also maintains a stack of lexing contexts to handle
+  // nested template parts by balancing curly braces.
+  void handleTemplateStrings();
 
   bool tryMerge_TMacro();
 
@@ -65,7 +82,7 @@
 
   FormatToken *FormatTok;
   bool IsFirstToken;
-  bool GreaterStashed, LessStashed;
+  std::stack StateStack;
   unsigned Column;
   unsigned TrailingWhitespace;
   std::unique_ptr Lex;
Index: lib/Format/FormatTokenLexer.cpp
===
--- lib/Format/FormatTokenLexer.cpp
+++ lib/Format/FormatTokenLexer.cpp
@@ -26,12 +26,11 @@
 FormatTokenLexer::FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
const FormatStyle &Style,
encoding::Encoding Encoding)
-: FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
-  LessStashed(false), Column(0), TrailingWhitespace(0),
-  SourceMgr(SourceMgr), ID(ID), Style(Style),
-  IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
-  Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false),
-  MacroBlockBeginRegex(Style.MacroBlockBegin),
+: FormatTok(nullptr), IsFirstTo

Re: [PATCH] D22431: clang-format: [JS] nested and tagged template strings.

2016-08-22 Thread Martin Probst via cfe-commits
mprobst added inline comments.


Comment at: lib/Format/FormatTokenLexer.cpp:259
@@ -241,1 +258,3 @@
   ++Offset; // Skip the escaped character.
+if (Offset + 1 < Lex->getBuffer().end() && Offset[0] == '$' &&
+Offset[1] == '{') {

Question by @ygao in the other diff:

> What happens if the '${' is immediately after a backslash (the if statement 
> above), should the '${' get escaped?

A template like `foo\${bar}` is the literal string `'foo\${bar}'`, i.e. the `\` 
acts as an escape for the `'$'` sign. I've added a test to validate that.


https://reviews.llvm.org/D22431



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D22431: clang-format: [JS] nested and tagged template strings.

2016-08-22 Thread Martin Probst via cfe-commits
mprobst updated this revision to Diff 68853.
mprobst added a comment.

- Fix escaping issue.


https://reviews.llvm.org/D22431

Files:
  lib/Format/FormatTokenLexer.cpp
  lib/Format/FormatTokenLexer.h
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTestJS.cpp

Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1122,7 +1122,7 @@
 TEST_F(FormatTestJS, TemplateStrings) {
   // Keeps any whitespace/indentation within the template string.
   verifyFormat("var x = `hello\n"
-" ${  name}\n"
+" ${name}\n"
 "  !`;",
 "var x=`hello\n"
" ${  name}\n"
@@ -1206,6 +1206,18 @@
"var y;",
"var x = ` \\` a`;\n"
"var y;");
+  // Escaped dollar.
+  verifyFormat("var x = ` \\${foo}`;\n");
+}
+
+TEST_F(FormatTestJS, NestedTemplateStrings) {
+  verifyFormat(
+  "var x = `${xs.map(x => `${x}`).join('\\n')}`;");
+  verifyFormat("var x = `he${({text: 'll'}.text)}o`;");
+}
+
+TEST_F(FormatTestJS, TaggedTemplateStrings) {
+  verifyFormat("var x = html``;");
 }
 
 TEST_F(FormatTestJS, CastSyntax) {
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -858,7 +858,7 @@
 if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_ForEachMacro,
TT_FunctionLBrace, TT_ImplicitStringLiteral,
TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow,
-   TT_RegexLiteral))
+   TT_RegexLiteral, TT_TemplateString))
   CurrentToken->Type = TT_Unknown;
 CurrentToken->Role.reset();
 CurrentToken->MatchingParen = nullptr;
@@ -1816,6 +1816,9 @@
   return 100;
 if (Left.is(TT_JsTypeColon))
   return 35;
+if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+(Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+  return 100;
   }
 
   if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next &&
@@ -2114,6 +2117,11 @@
   } else if (Style.Language == FormatStyle::LK_JavaScript) {
 if (Left.is(TT_JsFatArrow))
   return true;
+if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+(Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+  return false;
+if (Left.is(tok::identifier) && Right.is(TT_TemplateString))
+  return false;
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
   return false;
Index: lib/Format/FormatTokenLexer.h
===
--- lib/Format/FormatTokenLexer.h
+++ lib/Format/FormatTokenLexer.h
@@ -23,9 +23,17 @@
 #include "clang/Format/Format.h"
 #include "llvm/Support/Regex.h"
 
+#include 
+
 namespace clang {
 namespace format {
 
+enum LexerState {
+  NORMAL,
+  TEMPLATE_STRING,
+  TOKEN_STASHED,
+};
+
 class FormatTokenLexer {
 public:
   FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
@@ -53,7 +61,16 @@
   // its text if successful.
   void tryParseJSRegexLiteral();
 
-  void tryParseTemplateString();
+  // Handles JavaScript template strings.
+  //
+  // JavaScript template strings use backticks ('`') as delimiters, and allow
+  // embedding expressions nested in ${expr-here}. Template strings can be
+  // nested recursively, i.e. expressions can contain template strings in turns.
+  //
+  // The code below parses starting from a backtick, up to a closing backtick or
+  // an opening ${. It also maintains a stack of lexing contexts to handle
+  // nested template parts by balancing curly braces.
+  void handleTemplateStrings();
 
   bool tryMerge_TMacro();
 
@@ -65,7 +82,7 @@
 
   FormatToken *FormatTok;
   bool IsFirstToken;
-  bool GreaterStashed, LessStashed;
+  std::stack StateStack;
   unsigned Column;
   unsigned TrailingWhitespace;
   std::unique_ptr Lex;
Index: lib/Format/FormatTokenLexer.cpp
===
--- lib/Format/FormatTokenLexer.cpp
+++ lib/Format/FormatTokenLexer.cpp
@@ -26,12 +26,11 @@
 FormatTokenLexer::FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
const FormatStyle &Style,
encoding::Encoding Encoding)
-: FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
-  LessStashed(false), Column(0), TrailingWhitespace(0),
-  SourceMgr(SourceMgr), ID(ID), Style(Style),
-  IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
-  Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false),
-  MacroBlockBeginRegex(Style.MacroBlockBegin),
+: FormatTok(nullptr), IsFirstToken(tr

r279436 - clang-format: [JS] supports casts to types starting with punctuation ("{[(").

2016-08-22 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Mon Aug 22 09:23:30 2016
New Revision: 279436

URL: http://llvm.org/viewvc/llvm-project?rev=279436&view=rev
Log:
clang-format: [JS] supports casts to types starting with punctuation ("{[(").

Before:

x as{x: number}

After:

x as {x: number}

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D23761

Modified:
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=279436&r1=279435&r2=279436&view=diff
==
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon Aug 22 09:23:30 2016
@@ -2121,6 +2121,9 @@ bool TokenAnnotator::spaceRequiredBefore
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))
   return true;
+if (Left.is(Keywords.kw_as) &&
+Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren))
+  return true;
 if (Left.is(tok::kw_default) && Left.Previous &&
 Left.Previous->is(tok::kw_export))
   return true;

Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=279436&r1=279435&r2=279436&view=diff
==
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Mon Aug 22 09:23:30 2016
@@ -1219,6 +1219,9 @@ TEST_F(FormatTestJS, CastSyntax) {
"  2\n"
"];");
   verifyFormat("var x = [{x: 1} as type];");
+  verifyFormat("x = x as [a, b];");
+  verifyFormat("x = x as {a: string};");
+  verifyFormat("x = x as (string);");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D23761: clang-format: [JS] supports casts to types starting with punctuation ("{[(").

2016-08-22 Thread Martin Probst via cfe-commits
This revision was automatically updated to reflect the committed changes.
mprobst marked an inline comment as done.
Closed by commit rL279436: clang-format: [JS] supports casts to types starting 
with punctuation ("{[("). (authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D23761?vs=68844&id=68858#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D23761

Files:
  cfe/trunk/lib/Format/TokenAnnotator.cpp
  cfe/trunk/unittests/Format/FormatTestJS.cpp

Index: cfe/trunk/lib/Format/TokenAnnotator.cpp
===
--- cfe/trunk/lib/Format/TokenAnnotator.cpp
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp
@@ -2121,6 +2121,9 @@
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))
   return true;
+if (Left.is(Keywords.kw_as) &&
+Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren))
+  return true;
 if (Left.is(tok::kw_default) && Left.Previous &&
 Left.Previous->is(tok::kw_export))
   return true;
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -1219,6 +1219,9 @@
"  2\n"
"];");
   verifyFormat("var x = [{x: 1} as type];");
+  verifyFormat("x = x as [a, b];");
+  verifyFormat("x = x as {a: string};");
+  verifyFormat("x = x as (string);");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {


Index: cfe/trunk/lib/Format/TokenAnnotator.cpp
===
--- cfe/trunk/lib/Format/TokenAnnotator.cpp
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp
@@ -2121,6 +2121,9 @@
  Keywords.kw_of, tok::kw_const) &&
 (!Left.Previous || !Left.Previous->is(tok::period)))
   return true;
+if (Left.is(Keywords.kw_as) &&
+Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren))
+  return true;
 if (Left.is(tok::kw_default) && Left.Previous &&
 Left.Previous->is(tok::kw_export))
   return true;
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -1219,6 +1219,9 @@
"  2\n"
"];");
   verifyFormat("var x = [{x: 1} as type];");
+  verifyFormat("x = x as [a, b];");
+  verifyFormat("x = x as {a: string};");
+  verifyFormat("x = x as (string);");
 }
 
 TEST_F(FormatTestJS, TypeArguments) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D22431: clang-format: [JS] nested and tagged template strings.

2016-08-25 Thread Martin Probst via cfe-commits
mprobst added a comment.

No worries, thanks for the review.


https://reviews.llvm.org/D22431



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r279727 - clang-format: [JS] nested and tagged template strings.

2016-08-25 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Thu Aug 25 05:13:21 2016
New Revision: 279727

URL: http://llvm.org/viewvc/llvm-project?rev=279727&view=rev
Log:
clang-format: [JS] nested and tagged template strings.

JavaScript template strings can be nested arbitrarily:

foo = `text ${es.map(e => { return `<${e}>`; })} text`;

This change lexes nested template strings using a stack of lexer states to
correctly switch back to template string lexing on closing braces.

Also, reuse the same stack for the token-stashed logic.

Reviewers: djasper

Subscribers: cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D22431

Modified:
cfe/trunk/lib/Format/FormatTokenLexer.cpp
cfe/trunk/lib/Format/FormatTokenLexer.h
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp

Modified: cfe/trunk/lib/Format/FormatTokenLexer.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatTokenLexer.cpp?rev=279727&r1=279726&r2=279727&view=diff
==
--- cfe/trunk/lib/Format/FormatTokenLexer.cpp (original)
+++ cfe/trunk/lib/Format/FormatTokenLexer.cpp Thu Aug 25 05:13:21 2016
@@ -26,12 +26,11 @@ namespace format {
 FormatTokenLexer::FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
const FormatStyle &Style,
encoding::Encoding Encoding)
-: FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
-  LessStashed(false), Column(0), TrailingWhitespace(0),
-  SourceMgr(SourceMgr), ID(ID), Style(Style),
-  IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
-  Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false),
-  MacroBlockBeginRegex(Style.MacroBlockBegin),
+: FormatTok(nullptr), IsFirstToken(true), StateStack({LexerState::NORMAL}),
+  Column(0), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),
+  Style(Style), IdentTable(getFormattingLangOpts(Style)),
+  Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0),
+  FormattingDisabled(false), MacroBlockBeginRegex(Style.MacroBlockBegin),
   MacroBlockEndRegex(Style.MacroBlockEnd) {
   Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr,
   getFormattingLangOpts(Style)));
@@ -49,7 +48,7 @@ ArrayRef FormatTokenLexer
 Tokens.push_back(getNextToken());
 if (Style.Language == FormatStyle::LK_JavaScript) {
   tryParseJSRegexLiteral();
-  tryParseTemplateString();
+  handleTemplateStrings();
 }
 tryMergePreviousTokens();
 if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
@@ -228,17 +227,42 @@ void FormatTokenLexer::tryParseJSRegexLi
   resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset)));
 }
 
-void FormatTokenLexer::tryParseTemplateString() {
+void FormatTokenLexer::handleTemplateStrings() {
   FormatToken *BacktickToken = Tokens.back();
-  if (!BacktickToken->is(tok::unknown) || BacktickToken->TokenText != "`")
+
+  if (BacktickToken->is(tok::l_brace)) {
+StateStack.push(LexerState::NORMAL);
 return;
+  }
+  if (BacktickToken->is(tok::r_brace)) {
+StateStack.pop();
+if (StateStack.top() != LexerState::TEMPLATE_STRING)
+  return;
+// If back in TEMPLATE_STRING, fallthrough and continue parsing the
+  } else if (BacktickToken->is(tok::unknown) &&
+ BacktickToken->TokenText == "`") {
+StateStack.push(LexerState::TEMPLATE_STRING);
+  } else {
+return; // Not actually a template
+  }
 
   // 'Manually' lex ahead in the current file buffer.
   const char *Offset = Lex->getBufferLocation();
   const char *TmplBegin = Offset - BacktickToken->TokenText.size(); // at "`"
-  for (; Offset != Lex->getBuffer().end() && *Offset != '`'; ++Offset) {
-if (*Offset == '\\')
+  for (; Offset != Lex->getBuffer().end(); ++Offset) {
+if (Offset[0] == '`') {
+  StateStack.pop();
+  break;
+}
+if (Offset[0] == '\\') {
   ++Offset; // Skip the escaped character.
+} else if (Offset + 1 < Lex->getBuffer().end() && Offset[0] == '$' &&
+   Offset[1] == '{') {
+  // '${' introduces an expression interpolation in the template string.
+  StateStack.push(LexerState::NORMAL);
+  ++Offset;
+  break;
+}
   }
 
   StringRef LiteralText(TmplBegin, Offset - TmplBegin + 1);
@@ -262,7 +286,10 @@ void FormatTokenLexer::tryParseTemplateS
 Style.TabWidth, Encoding);
   }
 
-  resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset + 1)));
+  SourceLocation loc = Offset < Lex->getBuffer().end()
+   ? Lex->getSourceLocation(Offset + 1)
+   : SourceMgr.getLocForEndOfFile(ID);
+  resetLexer(SourceMgr.getFileOffset(loc));
 }
 
 bool FormatTokenLexer::tryMerge_TMacro() {
@@ -384,12 +411,8 @@ FormatToken *FormatTokenLexer::getStashe
 }
 
 FormatToken *FormatTokenLexer::getNextToken() {
-  

Re: [PATCH] D22431: clang-format: [JS] nested and tagged template strings.

2016-08-25 Thread Martin Probst via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL279727: clang-format: [JS] nested and tagged template 
strings. (authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D22431?vs=68853&id=69219#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D22431

Files:
  cfe/trunk/lib/Format/FormatTokenLexer.cpp
  cfe/trunk/lib/Format/FormatTokenLexer.h
  cfe/trunk/lib/Format/TokenAnnotator.cpp
  cfe/trunk/unittests/Format/FormatTestJS.cpp

Index: cfe/trunk/lib/Format/FormatTokenLexer.h
===
--- cfe/trunk/lib/Format/FormatTokenLexer.h
+++ cfe/trunk/lib/Format/FormatTokenLexer.h
@@ -23,9 +23,17 @@
 #include "clang/Format/Format.h"
 #include "llvm/Support/Regex.h"
 
+#include 
+
 namespace clang {
 namespace format {
 
+enum LexerState {
+  NORMAL,
+  TEMPLATE_STRING,
+  TOKEN_STASHED,
+};
+
 class FormatTokenLexer {
 public:
   FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
@@ -53,7 +61,16 @@
   // its text if successful.
   void tryParseJSRegexLiteral();
 
-  void tryParseTemplateString();
+  // Handles JavaScript template strings.
+  //
+  // JavaScript template strings use backticks ('`') as delimiters, and allow
+  // embedding expressions nested in ${expr-here}. Template strings can be
+  // nested recursively, i.e. expressions can contain template strings in turn.
+  //
+  // The code below parses starting from a backtick, up to a closing backtick or
+  // an opening ${. It also maintains a stack of lexing contexts to handle
+  // nested template parts by balancing curly braces.
+  void handleTemplateStrings();
 
   bool tryMerge_TMacro();
 
@@ -65,7 +82,7 @@
 
   FormatToken *FormatTok;
   bool IsFirstToken;
-  bool GreaterStashed, LessStashed;
+  std::stack StateStack;
   unsigned Column;
   unsigned TrailingWhitespace;
   std::unique_ptr Lex;
Index: cfe/trunk/lib/Format/FormatTokenLexer.cpp
===
--- cfe/trunk/lib/Format/FormatTokenLexer.cpp
+++ cfe/trunk/lib/Format/FormatTokenLexer.cpp
@@ -26,12 +26,11 @@
 FormatTokenLexer::FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
const FormatStyle &Style,
encoding::Encoding Encoding)
-: FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
-  LessStashed(false), Column(0), TrailingWhitespace(0),
-  SourceMgr(SourceMgr), ID(ID), Style(Style),
-  IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
-  Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false),
-  MacroBlockBeginRegex(Style.MacroBlockBegin),
+: FormatTok(nullptr), IsFirstToken(true), StateStack({LexerState::NORMAL}),
+  Column(0), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),
+  Style(Style), IdentTable(getFormattingLangOpts(Style)),
+  Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0),
+  FormattingDisabled(false), MacroBlockBeginRegex(Style.MacroBlockBegin),
   MacroBlockEndRegex(Style.MacroBlockEnd) {
   Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr,
   getFormattingLangOpts(Style)));
@@ -49,7 +48,7 @@
 Tokens.push_back(getNextToken());
 if (Style.Language == FormatStyle::LK_JavaScript) {
   tryParseJSRegexLiteral();
-  tryParseTemplateString();
+  handleTemplateStrings();
 }
 tryMergePreviousTokens();
 if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
@@ -228,17 +227,42 @@
   resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset)));
 }
 
-void FormatTokenLexer::tryParseTemplateString() {
+void FormatTokenLexer::handleTemplateStrings() {
   FormatToken *BacktickToken = Tokens.back();
-  if (!BacktickToken->is(tok::unknown) || BacktickToken->TokenText != "`")
+
+  if (BacktickToken->is(tok::l_brace)) {
+StateStack.push(LexerState::NORMAL);
 return;
+  }
+  if (BacktickToken->is(tok::r_brace)) {
+StateStack.pop();
+if (StateStack.top() != LexerState::TEMPLATE_STRING)
+  return;
+// If back in TEMPLATE_STRING, fallthrough and continue parsing the
+  } else if (BacktickToken->is(tok::unknown) &&
+ BacktickToken->TokenText == "`") {
+StateStack.push(LexerState::TEMPLATE_STRING);
+  } else {
+return; // Not actually a template
+  }
 
   // 'Manually' lex ahead in the current file buffer.
   const char *Offset = Lex->getBufferLocation();
   const char *TmplBegin = Offset - BacktickToken->TokenText.size(); // at "`"
-  for (; Offset != Lex->getBuffer().end() && *Offset != '`'; ++Offset) {
-if (*Offset == '\\')
+  for (; Offset != Lex->getBuffer().end(); ++Offset) {
+if (Offset[0] == '`') {
+  StateStack.pop();
+  break;
+}
+if (Offset[0] == '\\') {
   ++Offset; // Skip the escaped character.
+} else if (Offset + 1 < Lex->getBuffer().end() && Offset[0] == '$' &&
+ 

[PATCH] D23972: clang-format: [JS] Sort all JavaScript imports if any changed.

2016-08-28 Thread Martin Probst via cfe-commits
mprobst created this revision.
mprobst added a reviewer: djasper.
mprobst added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

User feedback is that they expect *all* imports to be sorted if any import was
affected by a change, not just imports up to the first non-affected line, as
clang-format currently does.

https://reviews.llvm.org/D23972

Files:
  lib/Format/SortJavaScriptImports.cpp
  unittests/Format/SortImportsTestJS.cpp

Index: unittests/Format/SortImportsTestJS.cpp
===
--- unittests/Format/SortImportsTestJS.cpp
+++ unittests/Format/SortImportsTestJS.cpp
@@ -190,40 +190,29 @@
 }
 
 TEST_F(SortImportsTestJS, AffectedRange) {
-  // Sort excluding a suffix.
-  verifySort("import {sym} from 'b';\n"
+  // Affected range inside of import statements.
+  verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
  "import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
+ "\n"
  "let x = 1;",
  "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
  "let x = 1;",
  0, 30);
-  // Sort excluding a prefix.
+  // Affected range outside of import statements.
   verifySort("import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
- "import {sym} from 'b';\n"
- "\n"
- "let x = 1;",
- "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
  "\n"
  "let x = 1;",
- 30, 0);
-  // Sort a range within imports.
-  verifySort("import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
- "import {sym} from 'b';\n"
- "import {sym} from 'c';\n"
- "let x = 1;",
  "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
- "import {sym} from 'c';\n"
+ "\n"
  "let x = 1;",
- 24, 30);
+ 70, 1);
 }
 
 TEST_F(SortImportsTestJS, SortingCanShrink) {
Index: lib/Format/SortJavaScriptImports.cpp
===
--- lib/Format/SortJavaScriptImports.cpp
+++ lib/Format/SortJavaScriptImports.cpp
@@ -284,14 +284,8 @@
 SourceLocation Start;
 bool FoundLines = false;
 AnnotatedLine *FirstNonImportLine = nullptr;
+bool AnyImportAffected = false;
 for (auto Line : AnnotatedLines) {
-  if (!Line->Affected) {
-// Only sort the first contiguous block of affected lines.
-if (FoundLines)
-  break;
-else
-  continue;
-  }
   Current = Line->First;
   LineEnd = Line->Last;
   skipComments();
@@ -309,6 +303,7 @@
 FirstNonImportLine = Line;
 break;
   }
+  AnyImportAffected = AnyImportAffected || Line->Affected;
   Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
   DEBUG({
 llvm::dbgs() << "JsModuleReference: {"
@@ -325,6 +320,9 @@
   References.push_back(Reference);
   Start = SourceLocation();
 }
+// Sort imports if any import line was affected.
+if (!AnyImportAffected)
+  References.clear();
 return std::make_pair(References, FirstNonImportLine);
   }
 


Index: unittests/Format/SortImportsTestJS.cpp
===
--- unittests/Format/SortImportsTestJS.cpp
+++ unittests/Format/SortImportsTestJS.cpp
@@ -190,40 +190,29 @@
 }
 
 TEST_F(SortImportsTestJS, AffectedRange) {
-  // Sort excluding a suffix.
-  verifySort("import {sym} from 'b';\n"
+  // Affected range inside of import statements.
+  verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
  "import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
+ "\n"
  "let x = 1;",
  "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
  "let x = 1;",
  0, 30);
-  // Sort excluding a prefix.
+  // Affected range outside of import statements.
   verifySort("import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
- "import {sym} from 'b';\n"
- "\n"
- "let x = 1;",
- "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
  "\n"
  "let x = 1;",
- 30, 0);
-  // Sort a range within imports.
-  verifySort("import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
- "import {sym} from 'b';\n"
- "import {sym} from 'c';\n"
- "let x = 1;",
  "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
-   

[PATCH] D23973: clang-format: [JS] handle default bindings in imports.

2016-08-28 Thread Martin Probst via cfe-commits
mprobst created this revision.
mprobst added a reviewer: djasper.
mprobst added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

Default imports appear outside of named bindings in curly braces:

  import A from 'a';
  import A, {symbol} from 'a';

https://reviews.llvm.org/D23973

Files:
  lib/Format/SortJavaScriptImports.cpp
  unittests/Format/SortImportsTestJS.cpp

Index: unittests/Format/SortImportsTestJS.cpp
===
--- unittests/Format/SortImportsTestJS.cpp
+++ unittests/Format/SortImportsTestJS.cpp
@@ -70,6 +70,26 @@
  "let x = 1;");
 }
 
+TEST_F(SortImportsTestJS, DefaultBinding) {
+  verifySort("import A from 'a';\n"
+ "import B from 'b';\n"
+ "\n"
+ "let x = 1;",
+ "import B from 'b';\n"
+ "import A from 'a';\n"
+ "let x = 1;");
+}
+
+TEST_F(SortImportsTestJS, DefaultAndNamedBinding) {
+  verifySort("import A, {a} from 'a';\n"
+ "import B, {b} from 'b';\n"
+ "\n"
+ "let x = 1;",
+ "import B, {b} from 'b';\n"
+ "import A, {a} from 'a';\n"
+ "let x = 1;");
+}
+
 TEST_F(SortImportsTestJS, WrappedImportStatements) {
   verifySort("import {sym1, sym2} from 'a';\n"
  "import {sym} from 'b';\n"
Index: lib/Format/SortJavaScriptImports.cpp
===
--- lib/Format/SortJavaScriptImports.cpp
+++ lib/Format/SortJavaScriptImports.cpp
@@ -348,7 +348,6 @@
 
 if (!parseModuleBindings(Keywords, Reference))
   return false;
-nextToken();
 
 if (Current->is(Keywords.kw_from)) {
   // imports have a 'from' clause, exports might not.
@@ -391,19 +390,28 @@
 if (Current->isNot(tok::identifier))
   return false;
 Reference.Prefix = Current->TokenText;
+nextToken();
 return true;
   }
 
   bool parseNamedBindings(const AdditionalKeywords &Keywords,
   JsModuleReference &Reference) {
+if (Current->is(tok::identifier)) {
+  nextToken();
+  if (Current->is(Keywords.kw_from))
+return true;
+  if (Current->isNot(tok::comma))
+return false;
+  nextToken(); // eat comma.
+}
 if (Current->isNot(tok::l_brace))
   return false;
 
 // {sym as alias, sym2 as ...} from '...';
-nextToken();
-while (true) {
+while (Current->isNot(tok::r_brace)) {
+  nextToken();
   if (Current->is(tok::r_brace))
-return true;
+break;
   if (Current->isNot(tok::identifier))
 return false;
 
@@ -424,12 +432,11 @@
   Symbol.Range.setEnd(Current->Tok.getLocation());
   Reference.Symbols.push_back(Symbol);
 
-  if (Current->is(tok::r_brace))
-return true;
-  if (Current->isNot(tok::comma))
+  if (!Current->isOneOf(tok::r_brace, tok::comma))
 return false;
-  nextToken();
 }
+nextToken(); // consume r_brace
+return true;
   }
 };
 


Index: unittests/Format/SortImportsTestJS.cpp
===
--- unittests/Format/SortImportsTestJS.cpp
+++ unittests/Format/SortImportsTestJS.cpp
@@ -70,6 +70,26 @@
  "let x = 1;");
 }
 
+TEST_F(SortImportsTestJS, DefaultBinding) {
+  verifySort("import A from 'a';\n"
+ "import B from 'b';\n"
+ "\n"
+ "let x = 1;",
+ "import B from 'b';\n"
+ "import A from 'a';\n"
+ "let x = 1;");
+}
+
+TEST_F(SortImportsTestJS, DefaultAndNamedBinding) {
+  verifySort("import A, {a} from 'a';\n"
+ "import B, {b} from 'b';\n"
+ "\n"
+ "let x = 1;",
+ "import B, {b} from 'b';\n"
+ "import A, {a} from 'a';\n"
+ "let x = 1;");
+}
+
 TEST_F(SortImportsTestJS, WrappedImportStatements) {
   verifySort("import {sym1, sym2} from 'a';\n"
  "import {sym} from 'b';\n"
Index: lib/Format/SortJavaScriptImports.cpp
===
--- lib/Format/SortJavaScriptImports.cpp
+++ lib/Format/SortJavaScriptImports.cpp
@@ -348,7 +348,6 @@
 
 if (!parseModuleBindings(Keywords, Reference))
   return false;
-nextToken();
 
 if (Current->is(Keywords.kw_from)) {
   // imports have a 'from' clause, exports might not.
@@ -391,19 +390,28 @@
 if (Current->isNot(tok::identifier))
   return false;
 Reference.Prefix = Current->TokenText;
+nextToken();
 return true;
   }
 
   bool parseNamedBindings(const AdditionalKeywords &Keywords,
   JsModuleReference &Reference) {
+if (Current->is(tok::identifier)) {
+  nextToken();
+  if (Current->is(Keywords.kw_from))
+return true;
+  if (Current->isNot(tok::comma))
+return false;
+  nextToken(); // eat comma.
+}
 if (Current->isNot(tok::l_brace))
   return 

[PATCH] D24155: clang-format: [JS] merge requoting replacements.

2016-09-01 Thread Martin Probst via cfe-commits
mprobst created this revision.
mprobst added a reviewer: djasper.
mprobst added a subscriber: cfe-commits.
Herald added a subscriber: klimek.

When formatting source code that needs both requoting and reindentation,
merge the replacements to avoid erroring out for conflicting replacements.

https://reviews.llvm.org/D24155

Files:
  lib/Format/Format.cpp
  unittests/Format/FormatTestJS.cpp

Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1318,6 +1318,13 @@
"let x = \"single\";\n");
 }
 
+TEST_F(FormatTestJS, RequoteAndIndent) {
+  verifyFormat("let x = someVeryLongFunctionThatGoesOnAndOn(\n"
+   "'double quoted string that needs wrapping');",
+   "let x = someVeryLongFunctionThatGoesOnAndOn("
+   "\"double quoted string that needs wrapping\");");
+}
+
 TEST_F(FormatTestJS, RequoteStringsDouble) {
   FormatStyle DoubleQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
   DoubleQuotes.JavaScriptQuotes = FormatStyle::JSQS_Double;
Index: lib/Format/Format.cpp
===
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -803,13 +803,14 @@
   analyze(TokenAnnotator &Annotator,
   SmallVectorImpl &AnnotatedLines,
   FormatTokenLexer &Tokens, tooling::Replacements &Result) override {
+tooling::Replacements RunResult;
 deriveLocalStyle(AnnotatedLines);
 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
   AnnotatedLines.end());
 
 if (Style.Language == FormatStyle::LK_JavaScript &&
 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave)
-  requoteJSStringLiteral(AnnotatedLines, Result);
+  requoteJSStringLiteral(AnnotatedLines, RunResult);
 
 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
   Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
@@ -826,7 +827,8 @@
 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, 
Tokens.getKeywords(),
IncompleteFormat)
 .format(AnnotatedLines);
-return Whitespaces.generateReplacements();
+RunResult = RunResult.merge(Whitespaces.generateReplacements());
+return RunResult;
   }
 
 private:


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1318,6 +1318,13 @@
"let x = \"single\";\n");
 }
 
+TEST_F(FormatTestJS, RequoteAndIndent) {
+  verifyFormat("let x = someVeryLongFunctionThatGoesOnAndOn(\n"
+   "'double quoted string that needs wrapping');",
+   "let x = someVeryLongFunctionThatGoesOnAndOn("
+   "\"double quoted string that needs wrapping\");");
+}
+
 TEST_F(FormatTestJS, RequoteStringsDouble) {
   FormatStyle DoubleQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
   DoubleQuotes.JavaScriptQuotes = FormatStyle::JSQS_Double;
Index: lib/Format/Format.cpp
===
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -803,13 +803,14 @@
   analyze(TokenAnnotator &Annotator,
   SmallVectorImpl &AnnotatedLines,
   FormatTokenLexer &Tokens, tooling::Replacements &Result) override {
+tooling::Replacements RunResult;
 deriveLocalStyle(AnnotatedLines);
 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
   AnnotatedLines.end());
 
 if (Style.Language == FormatStyle::LK_JavaScript &&
 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave)
-  requoteJSStringLiteral(AnnotatedLines, Result);
+  requoteJSStringLiteral(AnnotatedLines, RunResult);
 
 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
   Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
@@ -826,7 +827,8 @@
 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(),
IncompleteFormat)
 .format(AnnotatedLines);
-return Whitespaces.generateReplacements();
+RunResult = RunResult.merge(Whitespaces.generateReplacements());
+return RunResult;
   }
 
 private:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D23973: clang-format: [JS] handle default bindings in imports.

2016-09-02 Thread Martin Probst via cfe-commits
mprobst added a comment.

Friendly ping.


https://reviews.llvm.org/D23973



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D23972: clang-format: [JS] Sort all JavaScript imports if any changed.

2016-09-02 Thread Martin Probst via cfe-commits
mprobst added a comment.

Friendly ping.


https://reviews.llvm.org/D23972



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r280485 - clang-format: [JS] Sort all JavaScript imports if any changed.

2016-09-02 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Sep  2 09:01:17 2016
New Revision: 280485

URL: http://llvm.org/viewvc/llvm-project?rev=280485&view=rev
Log:
clang-format: [JS] Sort all JavaScript imports if any changed.

Summary:
User feedback is that they expect *all* imports to be sorted if any import was
affected by a change, not just imports up to the first non-affected line, as
clang-format currently does.

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D23972

Modified:
cfe/trunk/lib/Format/SortJavaScriptImports.cpp
cfe/trunk/unittests/Format/SortImportsTestJS.cpp

Modified: cfe/trunk/lib/Format/SortJavaScriptImports.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/SortJavaScriptImports.cpp?rev=280485&r1=280484&r2=280485&view=diff
==
--- cfe/trunk/lib/Format/SortJavaScriptImports.cpp (original)
+++ cfe/trunk/lib/Format/SortJavaScriptImports.cpp Fri Sep  2 09:01:17 2016
@@ -284,14 +284,8 @@ private:
 SourceLocation Start;
 bool FoundLines = false;
 AnnotatedLine *FirstNonImportLine = nullptr;
+bool AnyImportAffected = false;
 for (auto Line : AnnotatedLines) {
-  if (!Line->Affected) {
-// Only sort the first contiguous block of affected lines.
-if (FoundLines)
-  break;
-else
-  continue;
-  }
   Current = Line->First;
   LineEnd = Line->Last;
   skipComments();
@@ -309,6 +303,7 @@ private:
 FirstNonImportLine = Line;
 break;
   }
+  AnyImportAffected = AnyImportAffected || Line->Affected;
   Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
   DEBUG({
 llvm::dbgs() << "JsModuleReference: {"
@@ -325,6 +320,9 @@ private:
   References.push_back(Reference);
   Start = SourceLocation();
 }
+// Sort imports if any import line was affected.
+if (!AnyImportAffected)
+  References.clear();
 return std::make_pair(References, FirstNonImportLine);
   }
 

Modified: cfe/trunk/unittests/Format/SortImportsTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/SortImportsTestJS.cpp?rev=280485&r1=280484&r2=280485&view=diff
==
--- cfe/trunk/unittests/Format/SortImportsTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/SortImportsTestJS.cpp Fri Sep  2 09:01:17 2016
@@ -190,40 +190,29 @@ TEST_F(SortImportsTestJS, SideEffectImpo
 }
 
 TEST_F(SortImportsTestJS, AffectedRange) {
-  // Sort excluding a suffix.
-  verifySort("import {sym} from 'b';\n"
+  // Affected range inside of import statements.
+  verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
  "import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
+ "\n"
  "let x = 1;",
  "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
  "let x = 1;",
  0, 30);
-  // Sort excluding a prefix.
+  // Affected range outside of import statements.
   verifySort("import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
- "import {sym} from 'b';\n"
- "\n"
- "let x = 1;",
- "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
  "\n"
  "let x = 1;",
- 30, 0);
-  // Sort a range within imports.
-  verifySort("import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
- "import {sym} from 'b';\n"
- "import {sym} from 'c';\n"
- "let x = 1;",
  "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
- "import {sym} from 'c';\n"
+ "\n"
  "let x = 1;",
- 24, 30);
+ 70, 1);
 }
 
 TEST_F(SortImportsTestJS, SortingCanShrink) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D23972: clang-format: [JS] Sort all JavaScript imports if any changed.

2016-09-02 Thread Martin Probst via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL280485: clang-format: [JS] Sort all JavaScript imports if 
any changed. (authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D23972?vs=69511&id=70158#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D23972

Files:
  cfe/trunk/lib/Format/SortJavaScriptImports.cpp
  cfe/trunk/unittests/Format/SortImportsTestJS.cpp

Index: cfe/trunk/lib/Format/SortJavaScriptImports.cpp
===
--- cfe/trunk/lib/Format/SortJavaScriptImports.cpp
+++ cfe/trunk/lib/Format/SortJavaScriptImports.cpp
@@ -284,14 +284,8 @@
 SourceLocation Start;
 bool FoundLines = false;
 AnnotatedLine *FirstNonImportLine = nullptr;
+bool AnyImportAffected = false;
 for (auto Line : AnnotatedLines) {
-  if (!Line->Affected) {
-// Only sort the first contiguous block of affected lines.
-if (FoundLines)
-  break;
-else
-  continue;
-  }
   Current = Line->First;
   LineEnd = Line->Last;
   skipComments();
@@ -309,6 +303,7 @@
 FirstNonImportLine = Line;
 break;
   }
+  AnyImportAffected = AnyImportAffected || Line->Affected;
   Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
   DEBUG({
 llvm::dbgs() << "JsModuleReference: {"
@@ -325,6 +320,9 @@
   References.push_back(Reference);
   Start = SourceLocation();
 }
+// Sort imports if any import line was affected.
+if (!AnyImportAffected)
+  References.clear();
 return std::make_pair(References, FirstNonImportLine);
   }
 
Index: cfe/trunk/unittests/Format/SortImportsTestJS.cpp
===
--- cfe/trunk/unittests/Format/SortImportsTestJS.cpp
+++ cfe/trunk/unittests/Format/SortImportsTestJS.cpp
@@ -190,40 +190,29 @@
 }
 
 TEST_F(SortImportsTestJS, AffectedRange) {
-  // Sort excluding a suffix.
-  verifySort("import {sym} from 'b';\n"
+  // Affected range inside of import statements.
+  verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
  "import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
+ "\n"
  "let x = 1;",
  "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
  "let x = 1;",
  0, 30);
-  // Sort excluding a prefix.
+  // Affected range outside of import statements.
   verifySort("import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
- "import {sym} from 'b';\n"
- "\n"
- "let x = 1;",
- "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
  "\n"
  "let x = 1;",
- 30, 0);
-  // Sort a range within imports.
-  verifySort("import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
- "import {sym} from 'b';\n"
- "import {sym} from 'c';\n"
- "let x = 1;",
  "import {sym} from 'c';\n"
  "import {sym} from 'b';\n"
  "import {sym} from 'a';\n"
- "import {sym} from 'c';\n"
+ "\n"
  "let x = 1;",
- 24, 30);
+ 70, 1);
 }
 
 TEST_F(SortImportsTestJS, SortingCanShrink) {


Index: cfe/trunk/lib/Format/SortJavaScriptImports.cpp
===
--- cfe/trunk/lib/Format/SortJavaScriptImports.cpp
+++ cfe/trunk/lib/Format/SortJavaScriptImports.cpp
@@ -284,14 +284,8 @@
 SourceLocation Start;
 bool FoundLines = false;
 AnnotatedLine *FirstNonImportLine = nullptr;
+bool AnyImportAffected = false;
 for (auto Line : AnnotatedLines) {
-  if (!Line->Affected) {
-// Only sort the first contiguous block of affected lines.
-if (FoundLines)
-  break;
-else
-  continue;
-  }
   Current = Line->First;
   LineEnd = Line->Last;
   skipComments();
@@ -309,6 +303,7 @@
 FirstNonImportLine = Line;
 break;
   }
+  AnyImportAffected = AnyImportAffected || Line->Affected;
   Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
   DEBUG({
 llvm::dbgs() << "JsModuleReference: {"
@@ -325,6 +320,9 @@
   References.push_back(Reference);
   Start = SourceLocation();
 }
+// Sort imports if any import line was affected.
+if (!AnyImportAffected)
+  References.clear();
 return std::make_pair(References, FirstNonImportLine);
   }
 
Index: cfe/trunk/unittests/Format/SortImportsTestJS.cpp
===
--- cfe/trunk/unittests/Format/SortImportsTestJS.cpp
+++ cfe/trunk/unittests/Format/SortImportsTestJS.cpp
@@ -190,40 +190,29 @@
 }
 
 TEST_F(SortImportsTestJS, AffectedRange) {

Re: [PATCH] D23973: clang-format: [JS] handle default bindings in imports.

2016-09-02 Thread Martin Probst via cfe-commits
mprobst added a comment.

In https://reviews.llvm.org/D23973#532801, @djasper wrote:

> It would be helpful to have a before/after to review these patches.


I assumed the test case was clear enough. Before, we couldn't parse default 
bindings at all, after, we do, and thus sort the imports in the test case.


https://reviews.llvm.org/D23973



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r280486 - clang-format: [JS] handle default bindings in imports.

2016-09-02 Thread Martin Probst via cfe-commits
Author: mprobst
Date: Fri Sep  2 09:06:32 2016
New Revision: 280486

URL: http://llvm.org/viewvc/llvm-project?rev=280486&view=rev
Log:
clang-format: [JS] handle default bindings in imports.

Summary:
Default imports appear outside of named bindings in curly braces:

  import A from 'a';
  import A, {symbol} from 'a';

Reviewers: djasper

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D23973

Modified:
cfe/trunk/lib/Format/SortJavaScriptImports.cpp
cfe/trunk/unittests/Format/SortImportsTestJS.cpp

Modified: cfe/trunk/lib/Format/SortJavaScriptImports.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/SortJavaScriptImports.cpp?rev=280486&r1=280485&r2=280486&view=diff
==
--- cfe/trunk/lib/Format/SortJavaScriptImports.cpp (original)
+++ cfe/trunk/lib/Format/SortJavaScriptImports.cpp Fri Sep  2 09:06:32 2016
@@ -346,7 +346,6 @@ private:
 
 if (!parseModuleBindings(Keywords, Reference))
   return false;
-nextToken();
 
 if (Current->is(Keywords.kw_from)) {
   // imports have a 'from' clause, exports might not.
@@ -389,19 +388,28 @@ private:
 if (Current->isNot(tok::identifier))
   return false;
 Reference.Prefix = Current->TokenText;
+nextToken();
 return true;
   }
 
   bool parseNamedBindings(const AdditionalKeywords &Keywords,
   JsModuleReference &Reference) {
+if (Current->is(tok::identifier)) {
+  nextToken();
+  if (Current->is(Keywords.kw_from))
+return true;
+  if (Current->isNot(tok::comma))
+return false;
+  nextToken(); // eat comma.
+}
 if (Current->isNot(tok::l_brace))
   return false;
 
 // {sym as alias, sym2 as ...} from '...';
-nextToken();
-while (true) {
+while (Current->isNot(tok::r_brace)) {
+  nextToken();
   if (Current->is(tok::r_brace))
-return true;
+break;
   if (Current->isNot(tok::identifier))
 return false;
 
@@ -422,12 +430,11 @@ private:
   Symbol.Range.setEnd(Current->Tok.getLocation());
   Reference.Symbols.push_back(Symbol);
 
-  if (Current->is(tok::r_brace))
-return true;
-  if (Current->isNot(tok::comma))
+  if (!Current->isOneOf(tok::r_brace, tok::comma))
 return false;
-  nextToken();
 }
+nextToken(); // consume r_brace
+return true;
   }
 };
 

Modified: cfe/trunk/unittests/Format/SortImportsTestJS.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/SortImportsTestJS.cpp?rev=280486&r1=280485&r2=280486&view=diff
==
--- cfe/trunk/unittests/Format/SortImportsTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/SortImportsTestJS.cpp Fri Sep  2 09:06:32 2016
@@ -70,6 +70,26 @@ TEST_F(SortImportsTestJS, BasicSorting)
  "let x = 1;");
 }
 
+TEST_F(SortImportsTestJS, DefaultBinding) {
+  verifySort("import A from 'a';\n"
+ "import B from 'b';\n"
+ "\n"
+ "let x = 1;",
+ "import B from 'b';\n"
+ "import A from 'a';\n"
+ "let x = 1;");
+}
+
+TEST_F(SortImportsTestJS, DefaultAndNamedBinding) {
+  verifySort("import A, {a} from 'a';\n"
+ "import B, {b} from 'b';\n"
+ "\n"
+ "let x = 1;",
+ "import B, {b} from 'b';\n"
+ "import A, {a} from 'a';\n"
+ "let x = 1;");
+}
+
 TEST_F(SortImportsTestJS, WrappedImportStatements) {
   verifySort("import {sym1, sym2} from 'a';\n"
  "import {sym} from 'b';\n"


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


  1   2   3   4   >