[PATCH] D118448: clang-format: [JS] fix uninitialized memory.

2022-01-28 Thread Martin Probst via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGc26729251588: clang-format: [JS] fix uninitialized memory. 
(authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118448/new/

https://reviews.llvm.org/D118448

Files:
  clang/lib/Format/SortJavaScriptImports.cpp


Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -133,7 +133,10 @@
 public:
   JavaScriptImportSorter(const Environment , const FormatStyle )
   : TokenAnalyzer(Env, Style),
-FileContents(Env.getSourceManager().getBufferData(Env.getFileID())) {}
+FileContents(Env.getSourceManager().getBufferData(Env.getFileID())) {
+// FormatToken.Tok starts out in an uninitialized state.
+invalidToken.Tok.startToken();
+  }
 
   std::pair
   analyze(TokenAnnotator ,
@@ -232,7 +235,6 @@
 if (!Current || Current == LineEnd->Next) {
   // Set the current token to an invalid token, so that further parsing on
   // this line fails.
-  invalidToken.Tok.setKind(tok::unknown);
   Current = 
 }
   }


Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -133,7 +133,10 @@
 public:
   JavaScriptImportSorter(const Environment , const FormatStyle )
   : TokenAnalyzer(Env, Style),
-FileContents(Env.getSourceManager().getBufferData(Env.getFileID())) {}
+FileContents(Env.getSourceManager().getBufferData(Env.getFileID())) {
+// FormatToken.Tok starts out in an uninitialized state.
+invalidToken.Tok.startToken();
+  }
 
   std::pair
   analyze(TokenAnnotator ,
@@ -232,7 +235,6 @@
 if (!Current || Current == LineEnd->Next) {
   // Set the current token to an invalid token, so that further parsing on
   // this line fails.
-  invalidToken.Tok.setKind(tok::unknown);
   Current = 
 }
   }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D118448: clang-format: [JS] fix uninitialized memory.

2022-01-28 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added reviewers: jankuehle, krasimir.
mprobst requested review of this revision.
Herald added a project: clang.

SortJavaScriptImports attempts to set its currently parsed token to an
invalid token when it reaches the end of the line. However in doing so,
it used a `FormatToken`, which contains a `Token Tok`. `Token` does not
have a constructor, so its fields start out as uninitialized memory.

`Token::startToken()` initializes all fields. Calling it in
`JavaScriptImportSorter`'s constructor thus fixes the problem.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D118448

Files:
  clang/lib/Format/SortJavaScriptImports.cpp


Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -133,7 +133,10 @@
 public:
   JavaScriptImportSorter(const Environment , const FormatStyle )
   : TokenAnalyzer(Env, Style),
-FileContents(Env.getSourceManager().getBufferData(Env.getFileID())) {}
+FileContents(Env.getSourceManager().getBufferData(Env.getFileID())) {
+// FormatToken.Tok starts out in an uninitialized state.
+invalidToken.Tok.startToken();
+  }
 
   std::pair
   analyze(TokenAnnotator ,
@@ -232,7 +235,6 @@
 if (!Current || Current == LineEnd->Next) {
   // Set the current token to an invalid token, so that further parsing on
   // this line fails.
-  invalidToken.Tok.setKind(tok::unknown);
   Current = 
 }
   }


Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -133,7 +133,10 @@
 public:
   JavaScriptImportSorter(const Environment , const FormatStyle )
   : TokenAnalyzer(Env, Style),
-FileContents(Env.getSourceManager().getBufferData(Env.getFileID())) {}
+FileContents(Env.getSourceManager().getBufferData(Env.getFileID())) {
+// FormatToken.Tok starts out in an uninitialized state.
+invalidToken.Tok.startToken();
+  }
 
   std::pair
   analyze(TokenAnnotator ,
@@ -232,7 +235,6 @@
 if (!Current || Current == LineEnd->Next) {
   // Set the current token to an invalid token, so that further parsing on
   // this line fails.
-  invalidToken.Tok.setKind(tok::unknown);
   Current = 
 }
   }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D118446: clang-format: [JS] sort import aliases. Users can define aliases for long symbols using import aliases:

2022-01-28 Thread Martin Probst via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG03c59765b3eb: clang-format: [JS] sort import aliases. Users 
can define aliases for long… (authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118446/new/

https://reviews.llvm.org/D118446

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


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -446,6 +446,25 @@
  "const x =   1;");
 }
 
+TEST_F(SortImportsTestJS, ImportEqAliases) {
+  verifySort("import {B} from 'bar';\n"
+ "import {A} from 'foo';\n"
+ "\n"
+ "import Z = A.C;\n"
+ "import Y = B.C.Z;\n"
+ "\n"
+ "export {Z};\n"
+ "\n"
+ "console.log(Z);\n",
+ "import {A} from 'foo';\n"
+ "import Z = A.C;\n"
+ "export {Z};\n"
+ "import {B} from 'bar';\n"
+ "import Y = B.C.Z;\n"
+ "\n"
+ "console.log(Z);\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -78,6 +78,7 @@
 ABSOLUTE,// from 'something'
 RELATIVE_PARENT, // from '../*'
 RELATIVE,// from './*'
+ALIAS,   // import X = A.B;
   };
   ReferenceCategory Category = ReferenceCategory::SIDE_EFFECT;
   // The URL imported, e.g. `import .. from 'url';`. Empty for `export {a, 
b};`.
@@ -105,10 +106,12 @@
 return LHS.IsExport < RHS.IsExport;
   if (LHS.Category != RHS.Category)
 return LHS.Category < RHS.Category;
-  if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT)
-// Side effect imports might be ordering sensitive. Consider them equal so
-// that they maintain their relative order in the stable sort below.
-// This retains transitivity because LHS.Category == RHS.Category here.
+  if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT ||
+  LHS.Category == JsModuleReference::ReferenceCategory::ALIAS)
+// Side effect imports and aliases might be ordering sensitive. Consider
+// them equal so that they maintain their relative order in the stable sort
+// below. This retains transitivity because LHS.Category == RHS.Category
+// here.
 return false;
   // Empty URLs sort *last* (for export {...};).
   if (LHS.URL.empty() != RHS.URL.empty())
@@ -398,6 +401,8 @@
   JsModuleReference Reference;
   Reference.FormattingOff = FormattingOff;
   Reference.Range.setBegin(Start);
+  // References w/o a URL, e.g. export {A}, groups with RELATIVE.
+  Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
   if (!parseModuleReference(Keywords, Reference)) {
 if (!FirstNonImportLine)
   FirstNonImportLine = Line; // if no comment before.
@@ -463,9 +468,6 @@
 Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
   else
 Reference.Category = JsModuleReference::ReferenceCategory::ABSOLUTE;
-} else {
-  // w/o URL groups with "empty".
-  Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
 }
 return true;
   }
@@ -501,6 +503,20 @@
   nextToken();
   if (Current->is(Keywords.kw_from))
 return true;
+  // import X = A.B.C;
+  if (Current->is(tok::equal)) {
+Reference.Category = JsModuleReference::ReferenceCategory::ALIAS;
+nextToken();
+while (Current->is(tok::identifier)) {
+  nextToken();
+  if (Current->is(tok::semi)) {
+return true;
+  }
+  if (!Current->is(tok::period))
+return false;
+  nextToken();
+}
+  }
   if (Current->isNot(tok::comma))
 return false;
   nextToken(); // eat comma.


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -446,6 +446,25 @@
  "const x =   1;");
 }
 
+TEST_F(SortImportsTestJS, ImportEqAliases) {
+  verifySort("import {B} from 'bar';\n"
+ "import {A} from 'foo';\n"
+ "\n"
+ "import Z = A.C;\n"
+ "import Y = B.C.Z;\n"
+ "\n"
+ "export {Z};\n"
+ "\n"
+ "console.log(Z);\n",
+ "import {A} from 'foo';\n"
+ "import Z = 

[PATCH] D118446: clang-format: [JS] sort import aliases. Users can define aliases for long symbols using import aliases:

2022-01-28 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: jankuehle.
Herald added a subscriber: jeroen.dobbelaere.
mprobst requested review of this revision.
Herald added a project: clang.

  import X = A.B.C;

Previously, these were unhandled and would terminate import sorting.
With this change, aliases sort as their own group, coming last after all
other imports.

Aliases are not sorted within their group, as they may reference each
other, so order is significant.

This reverts commit f750c3d95a0c8bf1d21380ae753fce12010a7561 
. It fixes
the msan issue by not parsing past the end of the line when handling
import aliases.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D118446

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


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -446,6 +446,25 @@
  "const x =   1;");
 }
 
+TEST_F(SortImportsTestJS, ImportEqAliases) {
+  verifySort("import {B} from 'bar';\n"
+ "import {A} from 'foo';\n"
+ "\n"
+ "import Z = A.C;\n"
+ "import Y = B.C.Z;\n"
+ "\n"
+ "export {Z};\n"
+ "\n"
+ "console.log(Z);\n",
+ "import {A} from 'foo';\n"
+ "import Z = A.C;\n"
+ "export {Z};\n"
+ "import {B} from 'bar';\n"
+ "import Y = B.C.Z;\n"
+ "\n"
+ "console.log(Z);\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -78,6 +78,7 @@
 ABSOLUTE,// from 'something'
 RELATIVE_PARENT, // from '../*'
 RELATIVE,// from './*'
+ALIAS,   // import X = A.B;
   };
   ReferenceCategory Category = ReferenceCategory::SIDE_EFFECT;
   // The URL imported, e.g. `import .. from 'url';`. Empty for `export {a, 
b};`.
@@ -105,10 +106,12 @@
 return LHS.IsExport < RHS.IsExport;
   if (LHS.Category != RHS.Category)
 return LHS.Category < RHS.Category;
-  if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT)
-// Side effect imports might be ordering sensitive. Consider them equal so
-// that they maintain their relative order in the stable sort below.
-// This retains transitivity because LHS.Category == RHS.Category here.
+  if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT ||
+  LHS.Category == JsModuleReference::ReferenceCategory::ALIAS)
+// Side effect imports and aliases might be ordering sensitive. Consider
+// them equal so that they maintain their relative order in the stable sort
+// below. This retains transitivity because LHS.Category == RHS.Category
+// here.
 return false;
   // Empty URLs sort *last* (for export {...};).
   if (LHS.URL.empty() != RHS.URL.empty())
@@ -398,6 +401,8 @@
   JsModuleReference Reference;
   Reference.FormattingOff = FormattingOff;
   Reference.Range.setBegin(Start);
+  // References w/o a URL, e.g. export {A}, groups with RELATIVE.
+  Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
   if (!parseModuleReference(Keywords, Reference)) {
 if (!FirstNonImportLine)
   FirstNonImportLine = Line; // if no comment before.
@@ -463,9 +468,6 @@
 Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
   else
 Reference.Category = JsModuleReference::ReferenceCategory::ABSOLUTE;
-} else {
-  // w/o URL groups with "empty".
-  Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
 }
 return true;
   }
@@ -501,6 +503,20 @@
   nextToken();
   if (Current->is(Keywords.kw_from))
 return true;
+  // import X = A.B.C;
+  if (Current->is(tok::equal)) {
+Reference.Category = JsModuleReference::ReferenceCategory::ALIAS;
+nextToken();
+while (Current->is(tok::identifier)) {
+  nextToken();
+  if (Current->is(tok::semi)) {
+return true;
+  }
+  if (!Current->is(tok::period))
+return false;
+  nextToken();
+}
+  }
   if (Current->isNot(tok::comma))
 return false;
   nextToken(); // eat comma.


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -446,6 +446,25 @@
  "const x =   1;");
 }
 

[PATCH] D118363: clang-format: [JS] sort import aliases.

2022-01-27 Thread Martin Probst via Phabricator via cfe-commits
mprobst closed this revision.
mprobst added a comment.

Landed in 
https://github.com/llvm/llvm-project/commit/c6d5efb5d98093c4bd7578b2ea52c9032d20dea3


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118363/new/

https://reviews.llvm.org/D118363

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


[PATCH] D118361: clang-format: [JS] sort import aliases.

2022-01-27 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 403646.
mprobst added a comment.

- make test break if we used alphasort


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118361/new/

https://reviews.llvm.org/D118361

Files:
  clang/unittests/Format/SortImportsTestJS.cpp


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -450,17 +450,17 @@
   verifySort("import {B} from 'bar';\n"
  "import {A} from 'foo';\n"
  "\n"
- "import C = A.C;\n"
- "import Z = B.C.Z;\n"
+ "import Z = A.C;\n"
+ "import Y = B.C.Z;\n"
  "\n"
- "export {C};\n"
+ "export {Z};\n"
  "\n"
  "console.log(Z);\n",
  "import {A} from 'foo';\n"
- "import C = A.C;\n"
- "export {C};\n"
+ "import Z = A.C;\n"
+ "export {Z};\n"
  "import {B} from 'bar';\n"
- "import Z = B.C.Z;\n"
+ "import Y = B.C.Z;\n"
  "\n"
  "console.log(Z);\n");
 }


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -450,17 +450,17 @@
   verifySort("import {B} from 'bar';\n"
  "import {A} from 'foo';\n"
  "\n"
- "import C = A.C;\n"
- "import Z = B.C.Z;\n"
+ "import Z = A.C;\n"
+ "import Y = B.C.Z;\n"
  "\n"
- "export {C};\n"
+ "export {Z};\n"
  "\n"
  "console.log(Z);\n",
  "import {A} from 'foo';\n"
- "import C = A.C;\n"
- "export {C};\n"
+ "import Z = A.C;\n"
+ "export {Z};\n"
  "import {B} from 'bar';\n"
- "import Z = B.C.Z;\n"
+ "import Y = B.C.Z;\n"
  "\n"
  "console.log(Z);\n");
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D118361: clang-format: [JS] sort import aliases.

2022-01-27 Thread Martin Probst via Phabricator via cfe-commits
mprobst abandoned this revision.
mprobst added a comment.

Superseded by https://reviews.llvm.org/D118363 (sorry for the diff confusion).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118361/new/

https://reviews.llvm.org/D118361

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


[PATCH] D118363: clang-format: [JS] sort import aliases.

2022-01-27 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a subscriber: jeroen.dobbelaere.
mprobst requested review of this revision.
Herald added a project: clang.

Users can define aliases for long symbols using import aliases:

  import X = A.B.C;

Previously, these were unhandled and would terminate import sorting.
With this change, aliases sort as their own group, coming last after all
other imports.

Aliases are not sorted within their group, as they may reference each
other, so order is significant.

Revision URI: https://reviews.llvm.org/D118361


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D118363

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


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -446,6 +446,25 @@
  "const x =   1;");
 }
 
+TEST_F(SortImportsTestJS, ImportEqAliases) {
+  verifySort("import {B} from 'bar';\n"
+ "import {A} from 'foo';\n"
+ "\n"
+ "import C = A.C;\n"
+ "import Z = B.C.Z;\n"
+ "\n"
+ "export {C};\n"
+ "\n"
+ "console.log(Z);\n",
+ "import {A} from 'foo';\n"
+ "import C = A.C;\n"
+ "export {C};\n"
+ "import {B} from 'bar';\n"
+ "import Z = B.C.Z;\n"
+ "\n"
+ "console.log(Z);\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -78,6 +78,7 @@
 ABSOLUTE,// from 'something'
 RELATIVE_PARENT, // from '../*'
 RELATIVE,// from './*'
+ALIAS,   // import X = A.B;
   };
   ReferenceCategory Category = ReferenceCategory::SIDE_EFFECT;
   // The URL imported, e.g. `import .. from 'url';`. Empty for `export {a, 
b};`.
@@ -105,10 +106,12 @@
 return LHS.IsExport < RHS.IsExport;
   if (LHS.Category != RHS.Category)
 return LHS.Category < RHS.Category;
-  if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT)
-// Side effect imports might be ordering sensitive. Consider them equal so
-// that they maintain their relative order in the stable sort below.
-// This retains transitivity because LHS.Category == RHS.Category here.
+  if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT ||
+  LHS.Category == JsModuleReference::ReferenceCategory::ALIAS)
+// Side effect imports and aliases might be ordering sensitive. Consider
+// them equal so that they maintain their relative order in the stable sort
+// below. This retains transitivity because LHS.Category == RHS.Category
+// here.
 return false;
   // Empty URLs sort *last* (for export {...};).
   if (LHS.URL.empty() != RHS.URL.empty())
@@ -398,6 +401,8 @@
   JsModuleReference Reference;
   Reference.FormattingOff = FormattingOff;
   Reference.Range.setBegin(Start);
+  // References w/o a URL, e.g. export {A}, groups with RELATIVE.
+  Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
   if (!parseModuleReference(Keywords, Reference)) {
 if (!FirstNonImportLine)
   FirstNonImportLine = Line; // if no comment before.
@@ -463,9 +468,6 @@
 Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
   else
 Reference.Category = JsModuleReference::ReferenceCategory::ABSOLUTE;
-} else {
-  // w/o URL groups with "empty".
-  Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
 }
 return true;
   }
@@ -501,6 +503,21 @@
   nextToken();
   if (Current->is(Keywords.kw_from))
 return true;
+  // import X = A.B.C;
+  if (Current->is(tok::equal)) {
+Reference.Category = JsModuleReference::ReferenceCategory::ALIAS;
+nextToken();
+while (Current->is(tok::identifier)) {
+  nextToken();
+  if (Current->is(tok::semi)) {
+nextToken();
+return true;
+  }
+  if (!Current->is(tok::period))
+return false;
+  nextToken();
+}
+  }
   if (Current->isNot(tok::comma))
 return false;
   nextToken(); // eat comma.


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -446,6 +446,25 @@
  "const x =   1;");
 }
 
+TEST_F(SortImportsTestJS, ImportEqAliases) {
+  verifySort("import {B} from 'bar';\n"
+ "import 

[PATCH] D118361: clang-format: [JS] sort import aliases.

2022-01-27 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a subscriber: jeroen.dobbelaere.
mprobst requested review of this revision.
Herald added a project: clang.

Users can define aliases for long symbols using import aliases:

  import X = A.B.C;

Previously, these were unhandled and would terminate import sorting.
With this change, aliases sort as their own group, coming last after all
other imports.

Aliases are not sorted within their group, as they may reference each
other, so order is significant. Aliases sort before ES module exports,
as exports may reference aliases.

  import {A} from 'foo';
  
  import X = A.B.C;
  
  export {X};


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D118361

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

Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -446,6 +446,25 @@
  "const x =   1;");
 }
 
+TEST_F(SortImportsTestJS, ImportEqAliases) {
+  verifySort("import {B} from 'bar';\n"
+ "import {A} from 'foo';\n"
+ "\n"
+ "import C = A.C;\n"
+ "import Z = B.C.Z;\n"
+ "\n"
+ "export {C};\n"
+ "\n"
+ "console.log(Z);\n",
+ "import {A} from 'foo';\n"
+ "import C = A.C;\n"
+ "export {C};\n"
+ "import {B} from 'bar';\n"
+ "import Z = B.C.Z;\n"
+ "\n"
+ "console.log(Z);\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -71,8 +71,14 @@
 // required for sorting module references.
 struct JsModuleReference {
   bool FormattingOff = false;
-  bool IsExport = false;
-  // Module references are sorted into these categories, in order.
+  // Module references are sorted coarsely into these three groups, in order.
+  enum ReferenceKind {
+IMPORT,  // import ... from or side-effect imports.
+ALIAS,   // import A = B.C;
+EXPORT,  // export ...
+  };
+  ReferenceKind Kind = ReferenceKind::IMPORT;
+  // Module references are then sorted by these categories, in order.
   enum ReferenceCategory {
 SIDE_EFFECT, // "import 'something';"
 ABSOLUTE,// from 'something'
@@ -101,14 +107,16 @@
 };
 
 bool operator<(const JsModuleReference , const JsModuleReference ) {
-  if (LHS.IsExport != RHS.IsExport)
-return LHS.IsExport < RHS.IsExport;
+  if (LHS.Kind != RHS.Kind)
+return LHS.Kind < RHS.Kind;
   if (LHS.Category != RHS.Category)
 return LHS.Category < RHS.Category;
-  if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT)
-// Side effect imports might be ordering sensitive. Consider them equal so
-// that they maintain their relative order in the stable sort below.
-// This retains transitivity because LHS.Category == RHS.Category here.
+  if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT ||
+  LHS.Kind == JsModuleReference::ReferenceKind::ALIAS)
+// Side effect imports and aliases might be ordering sensitive. Consider
+// them equal so that they maintain their relative order in the stable sort
+// below. This retains transitivity because LHS.Category == RHS.Category
+// here.
 return false;
   // Empty URLs sort *last* (for export {...};).
   if (LHS.URL.empty() != RHS.URL.empty())
@@ -162,9 +170,10 @@
 // Insert breaks between imports and exports.
 ReferencesText += "\n";
 // Separate imports groups with two line breaks, but keep all exports
-// in a single group.
-if (!Reference.IsExport &&
-(Reference.IsExport != References[I + 1].IsExport ||
+// and aliases in a single group.
+// NB: exports sort last, so there is no need to check the next.
+if (Reference.Kind != JsModuleReference::ReferenceKind::EXPORT &&
+(Reference.Kind != References[I + 1].Kind ||
  Reference.Category != References[I + 1].Category))
   ReferencesText += "\n";
   }
@@ -298,7 +307,7 @@
   //   mismatching
   if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
   PreviousReference->Category == JsModuleReference::SIDE_EFFECT ||
-  Reference->IsExport != PreviousReference->IsExport ||
+  Reference->Kind != PreviousReference->Kind ||
   !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
   !PreviousReference->DefaultImport.empty() ||
   !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
@@ -398,6 +407,8 @@
  

[PATCH] D117197: [clang-format] Add new option to support adding a space between Javascript Union and Intersection types

2022-01-14 Thread Martin Probst via Phabricator via cfe-commits
mprobst added inline comments.



Comment at: clang/lib/Format/TokenAnnotator.cpp:3522
+  if ((Left.is(TT_JsTypeOperator) && Right.isTypeOrIdentifier()) ||
+  (Left.isTypeOrIdentifier() || Left.is(TT_TemplateCloser)) &&
+  Right.is(TT_JsTypeOperator))

MyDeveloperDay wrote:
> mprobst wrote:
> > Why do we need this further qualification here? I'd have expect that you 
> > can simply "return Style.SpacesInJavaScriptUnion;"? identifier || template 
> > closer also sounds oddly specific, why exactly those?
> Left =  template closer, Right =JsTypeOperator is for this case
> 
> ```
> type Foo = Bar | Baz;
>^
> ```
> 
> Left =  type or identifier, Right =JsTypeOperator is for this case
> 
> 
> ```
> let x: A | B = A | B;
> ^
> ```
What about:

```
let x: {foo: string}&{bar: number};
```

I'm not sure including curlies would be comprehensive. It might be worth 
checking the TS grammar.

But coming back, did you try this:

```
if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator)) {
  return Style.SpacesInJavaScriptUnion;
```

(We might also need to do something in `spaceRequiredBefore`, maybe that fires 
earlier?)




CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D117197/new/

https://reviews.llvm.org/D117197

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


[PATCH] D117197: [clang-format] Add new option to support adding a space between Javascript Union and Intersection types

2022-01-14 Thread Martin Probst via Phabricator via cfe-commits
mprobst added inline comments.



Comment at: clang/lib/Format/TokenAnnotator.cpp:3522
+  if ((Left.is(TT_JsTypeOperator) && Right.isTypeOrIdentifier()) ||
+  (Left.isTypeOrIdentifier() || Left.is(TT_TemplateCloser)) &&
+  Right.is(TT_JsTypeOperator))

Why do we need this further qualification here? I'd have expect that you can 
simply "return Style.SpacesInJavaScriptUnion;"? identifier || template closer 
also sounds oddly specific, why exactly those?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D117197/new/

https://reviews.llvm.org/D117197

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


[PATCH] D117197: [clang-format] Add new option to support adding a space between Javascript Union and Intersection types

2022-01-13 Thread Martin Probst via Phabricator via cfe-commits
mprobst added inline comments.



Comment at: clang/lib/Format/TokenAnnotator.cpp:3524
   return false;
 if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator))
   return false;

curdeius wrote:
> HazardyKnusperkeks wrote:
> > mprobst wrote:
> > > MyDeveloperDay wrote:
> > > > mprobst wrote:
> > > > > shouldn't you change this line here?
> > > > You know I thought the same and this was where I first put the code 
> > > > change in, but this code doesn't seem to have any effect and I've been 
> > > > caught out by this before... (anyone else seen that?)
> > > > 
> > > > I'm not sure if something has been changed, but I'm finding that often 
> > > > I add code into spaceRequiredBetween() and despite it being executed 
> > > > correctly it doesn't have the desired effect, which is why the code is 
> > > > in spaceRequiredBefore()
> > > Generally we put space between two operators. So this line must have some 
> > > effect, as otherwise we'd always emit `A | B`. Given that, I think we 
> > > need more debugging here to make this change - working around by some 
> > > more code somewhere else doesn't seem like a good long term approach.
> > > 
> > > Also, note that this is all in `spaceRequiredBefore`, right?
> > It's on my plan to refactor these 2 methods, because I think they can and 
> > should be made easier to understand and reason about.
> > 
> > So from my point of view one can accept this patch.
> I modified it like this and it passes all the tests. Please recheck.
I appreciate the intention to refactor this in the future.

I still believe we really have to understand how this code works though, and 
why changing this line doesn't have the effect we'd expect, before we land the 
fix. Chances are there is some substantial misunderstanding how this all fits 
together, which usually leads to bugs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D117197/new/

https://reviews.llvm.org/D117197

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


[PATCH] D117197: [clang-format] Add new option to support adding a space between Javascript Union and Intersection types

2022-01-13 Thread Martin Probst via Phabricator via cfe-commits
mprobst added inline comments.



Comment at: clang/lib/Format/TokenAnnotator.cpp:3524
   return false;
 if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator))
   return false;

MyDeveloperDay wrote:
> mprobst wrote:
> > shouldn't you change this line here?
> You know I thought the same and this was where I first put the code change 
> in, but this code doesn't seem to have any effect and I've been caught out by 
> this before... (anyone else seen that?)
> 
> I'm not sure if something has been changed, but I'm finding that often I add 
> code into spaceRequiredBetween() and despite it being executed correctly it 
> doesn't have the desired effect, which is why the code is in 
> spaceRequiredBefore()
Generally we put space between two operators. So this line must have some 
effect, as otherwise we'd always emit `A | B`. Given that, I think we need more 
debugging here to make this change - working around by some more code somewhere 
else doesn't seem like a good long term approach.

Also, note that this is all in `spaceRequiredBefore`, right?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D117197/new/

https://reviews.llvm.org/D117197

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


[PATCH] D117197: [clang-format] Add new option to support adding a space between Javascript Union and Intersection types

2022-01-13 Thread Martin Probst via Phabricator via cfe-commits
mprobst added inline comments.



Comment at: clang/lib/Format/TokenAnnotator.cpp:3524
   return false;
 if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator))
   return false;

shouldn't you change this line here?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D117197/new/

https://reviews.llvm.org/D117197

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


[PATCH] D116638: [clang-format] Fix ignoring JavaScriptWrapImport when ColumnWidth: 0

2022-01-05 Thread Martin Probst via Phabricator via cfe-commits
mprobst added inline comments.



Comment at: clang/docs/ClangFormatStyleOptions.rst:2827
 
-**JavaScriptWrapImports** (``Boolean``) :versionbadge:`clang-format 3.9`
-  Whether to wrap JavaScript import/export statements.
+  * If ``ColumnWidth`` is 0 (no limit on the number of columns), then import
+statements will keep the number of lines they start with.

andmis wrote:
> HazardyKnusperkeks wrote:
> > mprobst wrote:
> > > this seems odd to me: my understanding is that clang-format always 
> > > reflows the entire document, there's no logic to ever "keep" whitespace.
> > > 
> > > Are you sure you are seeing this behaviour? The logic change below sounds 
> > > more as if the ColumnWidth: 0, import lines might not break (mustBreak 
> > > returns false), but might still break?
> > From what I can tell with `ColumnLimit` (and not `ColumnWidth`) 0, then 
> > `clang-format` does many things differently. If by design or by accident 
> > I'm not sure. I can see that often, since I format my code with a limit, 
> > but my tests without.
> I just double-checked and yes, as-implemented, with `ColumnLimit: 0` and 
> `JavaScriptWrapImports: true`, import statements retain the number of lines 
> they started with.
> 
> It is explicit in the code that with `ColumnLimit: 0`, we decide whether to 
> break on a token based on whether there was a preexisting line break. (Check 
> out `NoColumnLimitLineFormatter`.) I think you're right that usually 
> clang-format reflows everything and I was also confused about this point.
> 
> There are other options that do similar things, for example 
> `EmptyLineAfterAccessModifier`.
Can you check with code that would normally cause reformatting? E.g.

```
import {
  A, B,
  C,
} from 'url';
```



CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116638/new/

https://reviews.llvm.org/D116638

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


[PATCH] D116638: [clang-format] Fix ignoring JavaScriptWrapImport when ColumnWidth: 0

2022-01-05 Thread Martin Probst via Phabricator via cfe-commits
mprobst added inline comments.



Comment at: clang/docs/ClangFormatStyleOptions.rst:2827
 
-**JavaScriptWrapImports** (``Boolean``) :versionbadge:`clang-format 3.9`
-  Whether to wrap JavaScript import/export statements.
+  * If ``ColumnWidth`` is 0 (no limit on the number of columns), then import
+statements will keep the number of lines they start with.

this seems odd to me: my understanding is that clang-format always reflows the 
entire document, there's no logic to ever "keep" whitespace.

Are you sure you are seeing this behaviour? The logic change below sounds more 
as if the ColumnWidth: 0, import lines might not break (mustBreak returns 
false), but might still break?



Comment at: clang/unittests/Format/FormatTestJS.cpp:1975
+   Style);
+  // Using the input_code/expected version of verifyFormat because we can't
+  // indiscriminately test::messUp on these tests.

I'm not sure this test case really repros the doc changes you made (keeps any 
line wraps with ColW: 0).

I think if you wanted to demonstrate that, you'd need to add a test case where 
clang-format would normally make a change, and show that it does not with ColW: 
0.

However I think that's not feasible: by design, clang-format cannot not make a 
change, it always reformats all code. You might need to rethink the intent here.



Comment at: clang/unittests/Format/FormatTestJS.cpp:1990
   Style.ColumnLimit = 40;
-  // Using this version of verifyFormat because test::messUp hides the issue.
+  Style.JavaScriptWrapImports = true;
   verifyFormat("import {\n"

curdeius wrote:
> It's already true, cf. line 1977. Remove this line.
FWIW, I think the tests might be more readable if each configuration ({true, 
false} x {col: 0, col: 40}) explicitly set all the options, even if it's a bit 
redundant.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116638/new/

https://reviews.llvm.org/D116638

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


[PATCH] D115147: clang-format: [JS] test case for numeric separators.

2021-12-06 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG327d966365d7: clang-format: [JS] test case for numeric 
separators. (authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D115147/new/

https://reviews.llvm.org/D115147

Files:
  clang/unittests/Format/FormatTestJS.cpp


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2692,5 +2692,9 @@
   "}\n");
 }
 
+TEST_F(FormatTestJS, NumericSeparators) {
+  verifyFormat("x = 1_000_000 + 12;", "x = 1_000_000   + 12;");
+}
+
 } // namespace format
 } // end namespace clang


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2692,5 +2692,9 @@
   "}\n");
 }
 
+TEST_F(FormatTestJS, NumericSeparators) {
+  verifyFormat("x = 1_000_000 + 12;", "x = 1_000_000   + 12;");
+}
+
 } // namespace format
 } // end namespace clang
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D115147: clang-format: [JS] test case for numeric separators.

2021-12-06 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
mprobst requested review of this revision.
Herald added a project: clang.

ES2021 allows numeric literals using `_` as a separator. This already
works, but had no test.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D115147

Files:
  clang/unittests/Format/FormatTestJS.cpp


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2692,5 +2692,9 @@
   "}\n");
 }
 
+TEST_F(FormatTestJS, NumericSeparators) {
+  verifyFormat("x = 1_000_000 + 12;", "x = 1_000_000   + 12;");
+}
+
 } // namespace format
 } // end namespace clang


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2692,5 +2692,9 @@
   "}\n");
 }
 
+TEST_F(FormatTestJS, NumericSeparators) {
+  verifyFormat("x = 1_000_000 + 12;", "x = 1_000_000   + 12;");
+}
+
 } // namespace format
 } // end namespace clang
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105087: [clang-format] PR49960 clang-format doesn't handle ASI after "return" on JavaScript

2021-07-01 Thread Martin Probst via Phabricator via cfe-commits
mprobst accepted this revision.
mprobst added inline comments.



Comment at: clang/lib/Format/UnwrappedLineParser.cpp:1001
+  if (TokenPosition < AllTokens.size()) {
+FormatToken *PeekNext = AllTokens[TokenPosition];
+return PeekNext;

nit: just `return AllTokens[TokenPosition]`?



Comment at: clang/lib/Format/UnwrappedLineParser.cpp:1024
+// Don't go past the end of the file.
+if (!eof()) {
+  // Look for  return xxx = val; but not return xxx().

do you still need this, given peeknext protects against running past the doc 
end?



Comment at: clang/lib/Format/UnwrappedLineParser.h:188
 
+  // Peek to the next token
+  FormatToken *peekNextToken() const;

cam you document what this does to the "current token" pointer?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105087/new/

https://reviews.llvm.org/D105087

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


[PATCH] D105087: [clang-format] PR49960 clang-format doesn't handle ASI after "return" on JavaScript

2021-06-29 Thread Martin Probst via Phabricator via cfe-commits
mprobst added inline comments.



Comment at: clang/lib/Format/UnwrappedLineParser.cpp:1015
+if (!eof()) {
+  if (Next->is(tok::identifier)) {
+// Peek the next token.

can you add comments explaining what syntax is being detected here?



Comment at: clang/lib/Format/UnwrappedLineParser.cpp:1019
+FormatToken *NextNext = Tokens->getNextToken();
+Tokens->setPosition(StoredPosition);
+if (NextNext && NextNext->is(tok::equal))

parsePPEndIf uses a different method to peek - any opinion on why you're doing 
it differently here?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105087/new/

https://reviews.llvm.org/D105087

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


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

2021-06-11 Thread Martin Probst via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG63042d46bb0c: clang-format: [JS] dont sort named 
imports if off. (authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104101/new/

https://reviews.llvm.org/D104101

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


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -431,6 +431,17 @@
  "// 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
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -317,6 +317,11 @@
 
   // Appends ``Reference`` to ``Buffer``.
   void appendReference(std::string , JsModuleReference ) {
+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;


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -431,6 +431,17 @@
  "// 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
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -317,6 +317,11 @@
 
   // Appends ``Reference`` to ``Buffer``.
   void appendReference(std::string , JsModuleReference ) {
+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;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2021-06-11 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
mprobst requested review of this revision.
Herald added a project: clang.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D104101

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


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -431,6 +431,17 @@
  "// 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
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -317,6 +317,11 @@
 
   // Appends ``Reference`` to ``Buffer``.
   void appendReference(std::string , JsModuleReference ) {
+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;


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -431,6 +431,17 @@
  "// 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
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -317,6 +317,11 @@
 
   // Appends ``Reference`` to ``Buffer``.
   void appendReference(std::string , JsModuleReference ) {
+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;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D101515: clang-format: [JS] handle "off" in imports

2021-04-30 Thread Martin Probst via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb2780cd744ea: clang-format: [JS] handle off in 
imports (authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101515/new/

https://reviews.llvm.org/D101515

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

Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -358,7 +358,8 @@
 
   // do not merge imports and exports
   verifySort("import {A} from 'foo';\n"
- "export {B} from 'foo';",
+ "\n"
+ "export {B} from 'foo';\n",
  "import {A} from 'foo';\n"
  "export   {B} from 'foo';");
   // do merge exports
@@ -373,6 +374,63 @@
  "import './a';\n");
 }
 
+TEST_F(SortImportsTestJS, RespectsClangFormatOff) {
+  verifySort("// clang-format off\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format on\n",
+ "// clang-format off\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format on\n");
+
+  verifySort("import {A} from './sorted1_a';\n"
+ "import {B} from './sorted1_b';\n"
+ "// clang-format off\n"
+ "import {B} from './unsorted_b';\n"
+ "import {A} from './unsorted_a';\n"
+ "// clang-format on\n"
+ "import {A} from './sorted2_a';\n"
+ "import {B} from './sorted2_b';\n",
+ "import {B} from './sorted1_b';\n"
+ "import {A} from './sorted1_a';\n"
+ "// clang-format off\n"
+ "import {B} from './unsorted_b';\n"
+ "import {A} from './unsorted_a';\n"
+ "// clang-format on\n"
+ "import {B} from './sorted2_b';\n"
+ "import {A} from './sorted2_a';\n");
+
+  // Boundary cases
+  verifySort("// clang-format on\n", "// clang-format on\n");
+  verifySort("// clang-format off\n", "// clang-format off\n");
+  verifySort("// clang-format on\n"
+ "// clang-format off\n",
+ "// clang-format on\n"
+ "// clang-format off\n");
+  verifySort("// clang-format off\n"
+ "// clang-format on\n"
+ "import {A} from './a';\n"
+ "import {B} from './b';\n",
+ "// clang-format off\n"
+ "// clang-format on\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n");
+  // section ends with comment
+  verifySort("// clang-format on\n"
+ "import {A} from './a';\n"
+ "import {B} from './b';\n"
+ "import {C} from './c';\n"
+ "\n" // inserted empty line is working as intended: splits imports
+  // section from main code body
+ "// clang-format off\n",
+ "// clang-format on\n"
+ "import {C} from './c';\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format off\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -19,6 +19,7 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
@@ -69,6 +70,7 @@
 // This struct represents both exports and imports to build up the information
 // required for sorting module references.
 struct JsModuleReference {
+  bool FormattingOff = false;
   bool IsExport = false;
   // Module references are sorted into these categories, in order.
   enum ReferenceCategory {
@@ -146,39 +148,31 @@
 if (References.empty())
   return {Result, 0};
 
-SmallVector Indices;
-for (unsigned i = 0, e = References.size(); i != e; ++i)
-  Indices.push_back(i);
-llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return References[LHSI] < References[RHSI];
-});
-bool ReferencesInOrder = llvm::is_sorted(Indices);
+// The text range of all parsed imports, to be replaced later.
+SourceRange InsertionPoint = References[0].Range;
+InsertionPoint.setEnd(References[References.size() - 1].Range.getEnd());
 
-mergeModuleReferences(References, Indices);
+References = sortModuleReferences(References);
 
 std::string ReferencesText;
-bool SymbolsInOrder = true;
-

[PATCH] D101515: clang-format: [JS] handle "off" in imports

2021-04-30 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 341849.
mprobst added a comment.

- review comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101515/new/

https://reviews.llvm.org/D101515

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

Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -358,7 +358,8 @@
 
   // do not merge imports and exports
   verifySort("import {A} from 'foo';\n"
- "export {B} from 'foo';",
+ "\n"
+ "export {B} from 'foo';\n",
  "import {A} from 'foo';\n"
  "export   {B} from 'foo';");
   // do merge exports
@@ -373,6 +374,63 @@
  "import './a';\n");
 }
 
+TEST_F(SortImportsTestJS, RespectsClangFormatOff) {
+  verifySort("// clang-format off\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format on\n",
+ "// clang-format off\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format on\n");
+
+  verifySort("import {A} from './sorted1_a';\n"
+ "import {B} from './sorted1_b';\n"
+ "// clang-format off\n"
+ "import {B} from './unsorted_b';\n"
+ "import {A} from './unsorted_a';\n"
+ "// clang-format on\n"
+ "import {A} from './sorted2_a';\n"
+ "import {B} from './sorted2_b';\n",
+ "import {B} from './sorted1_b';\n"
+ "import {A} from './sorted1_a';\n"
+ "// clang-format off\n"
+ "import {B} from './unsorted_b';\n"
+ "import {A} from './unsorted_a';\n"
+ "// clang-format on\n"
+ "import {B} from './sorted2_b';\n"
+ "import {A} from './sorted2_a';\n");
+
+  // Boundary cases
+  verifySort("// clang-format on\n", "// clang-format on\n");
+  verifySort("// clang-format off\n", "// clang-format off\n");
+  verifySort("// clang-format on\n"
+ "// clang-format off\n",
+ "// clang-format on\n"
+ "// clang-format off\n");
+  verifySort("// clang-format off\n"
+ "// clang-format on\n"
+ "import {A} from './a';\n"
+ "import {B} from './b';\n",
+ "// clang-format off\n"
+ "// clang-format on\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n");
+  // section ends with comment
+  verifySort("// clang-format on\n"
+ "import {A} from './a';\n"
+ "import {B} from './b';\n"
+ "import {C} from './c';\n"
+ "\n" // inserted empty line is working as intended: splits imports
+  // section from main code body
+ "// clang-format off\n",
+ "// clang-format on\n"
+ "import {C} from './c';\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format off\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -19,6 +19,7 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
@@ -69,6 +70,7 @@
 // This struct represents both exports and imports to build up the information
 // required for sorting module references.
 struct JsModuleReference {
+  bool FormattingOff = false;
   bool IsExport = false;
   // Module references are sorted into these categories, in order.
   enum ReferenceCategory {
@@ -146,39 +148,31 @@
 if (References.empty())
   return {Result, 0};
 
-SmallVector Indices;
-for (unsigned i = 0, e = References.size(); i != e; ++i)
-  Indices.push_back(i);
-llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return References[LHSI] < References[RHSI];
-});
-bool ReferencesInOrder = llvm::is_sorted(Indices);
+// The text range of all parsed imports, to be replaced later.
+SourceRange InsertionPoint = References[0].Range;
+InsertionPoint.setEnd(References[References.size() - 1].Range.getEnd());
 
-mergeModuleReferences(References, Indices);
+References = sortModuleReferences(References);
 
 std::string ReferencesText;
-bool SymbolsInOrder = true;
-for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
-  JsModuleReference Reference = References[Indices[i]];
-  if 

[PATCH] D101515: clang-format: [JS] handle "off" in imports

2021-04-30 Thread Martin Probst via Phabricator via cfe-commits
mprobst marked an inline comment as done.
mprobst added a comment.

added test for merging


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101515/new/

https://reviews.llvm.org/D101515

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


[PATCH] D101515: clang-format: [JS] handle "off" in imports

2021-04-30 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 341815.
mprobst added a comment.

- test for avoiding merges


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101515/new/

https://reviews.llvm.org/D101515

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

Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -358,7 +358,8 @@
 
   // do not merge imports and exports
   verifySort("import {A} from 'foo';\n"
- "export {B} from 'foo';",
+ "\n"
+ "export {B} from 'foo';\n",
  "import {A} from 'foo';\n"
  "export   {B} from 'foo';");
   // do merge exports
@@ -373,6 +374,63 @@
  "import './a';\n");
 }
 
+TEST_F(SortImportsTestJS, RespectsClangFormatOff) {
+  verifySort("// clang-format off\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format on\n",
+ "// clang-format off\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format on\n");
+
+  verifySort("import {A} from './sorted1_a';\n"
+ "import {B} from './sorted1_b';\n"
+ "// clang-format off\n"
+ "import {B} from './unsorted_b';\n"
+ "import {A} from './unsorted_a';\n"
+ "// clang-format on\n"
+ "import {A} from './sorted2_a';\n"
+ "import {B} from './sorted2_b';\n",
+ "import {B} from './sorted1_b';\n"
+ "import {A} from './sorted1_a';\n"
+ "// clang-format off\n"
+ "import {B} from './unsorted_b';\n"
+ "import {A} from './unsorted_a';\n"
+ "// clang-format on\n"
+ "import {B} from './sorted2_b';\n"
+ "import {A} from './sorted2_a';\n");
+
+  // Boundary cases
+  verifySort("// clang-format on\n", "// clang-format on\n");
+  verifySort("// clang-format off\n", "// clang-format off\n");
+  verifySort("// clang-format on\n"
+ "// clang-format off\n",
+ "// clang-format on\n"
+ "// clang-format off\n");
+  verifySort("// clang-format off\n"
+ "// clang-format on\n"
+ "import {A} from './a';\n"
+ "import {B} from './b';\n",
+ "// clang-format off\n"
+ "// clang-format on\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n");
+  // section ends with comment
+  verifySort("// clang-format on\n"
+ "import {A} from './a';\n"
+ "import {B} from './b';\n"
+ "import {C} from './c';\n"
+ "\n" // inserted empty line is working as intended: splits imports
+  // section from main code body
+ "// clang-format off\n",
+ "// clang-format on\n"
+ "import {C} from './c';\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format off\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -19,6 +19,7 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
@@ -69,6 +70,7 @@
 // This struct represents both exports and imports to build up the information
 // required for sorting module references.
 struct JsModuleReference {
+  bool FormattingOff = false;
   bool IsExport = false;
   // Module references are sorted into these categories, in order.
   enum ReferenceCategory {
@@ -146,39 +148,31 @@
 if (References.empty())
   return {Result, 0};
 
-SmallVector Indices;
-for (unsigned i = 0, e = References.size(); i != e; ++i)
-  Indices.push_back(i);
-llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return References[LHSI] < References[RHSI];
-});
-bool ReferencesInOrder = llvm::is_sorted(Indices);
+// The text range of all parsed imports, to be replaced later.
+SourceRange InsertionPoint = References[0].Range;
+InsertionPoint.setEnd(References[References.size() - 1].Range.getEnd());
 
-mergeModuleReferences(References, Indices);
+References = sortModuleReferences(References);
 
 std::string ReferencesText;
-bool SymbolsInOrder = true;
-for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
-  JsModuleReference Reference = References[Indices[i]];
-  if 

[PATCH] D101515: clang-format: [JS] handle "off" in imports

2021-04-30 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 341814.
mprobst marked 4 inline comments as done.
mprobst added a comment.

- review comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101515/new/

https://reviews.llvm.org/D101515

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

Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -358,7 +358,8 @@
 
   // do not merge imports and exports
   verifySort("import {A} from 'foo';\n"
- "export {B} from 'foo';",
+ "\n"
+ "export {B} from 'foo';\n",
  "import {A} from 'foo';\n"
  "export   {B} from 'foo';");
   // do merge exports
@@ -373,6 +374,63 @@
  "import './a';\n");
 }
 
+TEST_F(SortImportsTestJS, RespectsClangFormatOff) {
+  verifySort("// clang-format off\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format on\n",
+ "// clang-format off\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format on\n");
+
+  verifySort("import {A} from './sorted1_a';\n"
+ "import {B} from './sorted1_b';\n"
+ "// clang-format off\n"
+ "import {B} from './unsorted_b';\n"
+ "import {A} from './unsorted_a';\n"
+ "// clang-format on\n"
+ "import {A} from './sorted2_a';\n"
+ "import {B} from './sorted2_b';\n",
+ "import {B} from './sorted1_b';\n"
+ "import {A} from './sorted1_a';\n"
+ "// clang-format off\n"
+ "import {B} from './unsorted_b';\n"
+ "import {A} from './unsorted_a';\n"
+ "// clang-format on\n"
+ "import {B} from './sorted2_b';\n"
+ "import {A} from './sorted2_a';\n");
+
+  // Boundary cases
+  verifySort("// clang-format on\n", "// clang-format on\n");
+  verifySort("// clang-format off\n", "// clang-format off\n");
+  verifySort("// clang-format on\n"
+ "// clang-format off\n",
+ "// clang-format on\n"
+ "// clang-format off\n");
+  verifySort("// clang-format off\n"
+ "// clang-format on\n"
+ "import {A} from './a';\n"
+ "import {B} from './b';\n",
+ "// clang-format off\n"
+ "// clang-format on\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n");
+  // section ends with comment
+  verifySort("// clang-format on\n"
+ "import {A} from './a';\n"
+ "import {B} from './b';\n"
+ "import {C} from './c';\n"
+ "\n" // inserted empty line is working as intended: splits imports
+  // section from main code body
+ "// clang-format off\n",
+ "// clang-format on\n"
+ "import {C} from './c';\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format off\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -19,6 +19,7 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
@@ -69,6 +70,7 @@
 // This struct represents both exports and imports to build up the information
 // required for sorting module references.
 struct JsModuleReference {
+  bool FormattingOff = false;
   bool IsExport = false;
   // Module references are sorted into these categories, in order.
   enum ReferenceCategory {
@@ -146,39 +148,31 @@
 if (References.empty())
   return {Result, 0};
 
-SmallVector Indices;
-for (unsigned i = 0, e = References.size(); i != e; ++i)
-  Indices.push_back(i);
-llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return References[LHSI] < References[RHSI];
-});
-bool ReferencesInOrder = llvm::is_sorted(Indices);
+// The text range of all parsed imports, to be replaced later.
+SourceRange InsertionPoint = References[0].Range;
+InsertionPoint.setEnd(References[References.size() - 1].Range.getEnd());
 
-mergeModuleReferences(References, Indices);
+References = sortModuleReferences(References);
 
 std::string ReferencesText;
-bool SymbolsInOrder = true;
-for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
-  JsModuleReference Reference = 

[PATCH] D101515: clang-format: [JS] handle "off" in imports

2021-04-30 Thread Martin Probst via Phabricator via cfe-commits
mprobst marked 9 inline comments as done.
mprobst added a comment.

PTAL, addressed review comments.




Comment at: clang/lib/Format/SortJavaScriptImports.cpp:191
+!(FirstNonImportLine->First->is(tok::comment) &&
+  FirstNonImportLine->First->TokenText.trim() == "// clang-format on"))
   ReferencesText += "\n";

krasimir wrote:
> note that we generally also support `/* clang-format off/on */`: 
> https://github.com/llvm/llvm-project/blob/aaf026d9da3885a951dcdc5edd64c8e7d23b6285/clang/lib/Format/Format.cpp#L2390
We don't in the C++ import sorter. Sigh.

I think the Real Fix (tm) would be folding the clang-format off thing in import 
sorting with affected lines, wouldn't it? I don't quite know how to untangle 
this, but it seems suboptimal that each sorter here re-implements the same 
logic.



Comment at: clang/lib/Format/SortJavaScriptImports.cpp:251
+  // references that have formatting enabled in individual chunks.
+  SmallVector
+  sortModuleReferences(SmallVector ) {

krasimir wrote:
> We should pass in and return `llvm::SmallVectorImpl` (the 
> size version is mainly for local vars). Also, take the arg by `const` 
> reference.
That gives me:

`error: no viable conversion from 'SmallVector<[...], 16>' to 'const 
SmallVector<[...], (default) 
CalculateSmallVectorDefaultInlinedElements::value aka 1>'`



Comment at: clang/lib/Format/SortJavaScriptImports.cpp:288
+  // longer needed references).
+  void mergeModuleReferences(SmallVector ) {
+if (References.empty())

krasimir wrote:
> use `llvm::SmallVectorImpl`
As above, this seems not possible.



Comment at: clang/lib/Format/SortJavaScriptImports.cpp:377
+  }
   skipComments();
   if (Start.isInvalid() || References.empty())

h-joo wrote:
> I think this has a potential bug that if the user makes
> ```
> // clang-format off
> // clang-format on
> ```
> Every subsequent import will fail to be sorted. 
> 
> or maybe something like below
> ```
> //clang-format off
> import {A, B} from "./a"
> //clang-format on
> //clang-format off
> ```
> will make the 'should not be sorted' part of the code be sorted.
> 
> Even if this is not the case, could you write a test for this one?
Nice, good catch! Done.



Comment at: clang/unittests/Format/SortImportsTestJS.cpp:362
+ "\n"
+ "export {B} from 'foo';\n",
  "import {A} from 'foo';\n"

krasimir wrote:
> Was this change intended? It doesn't seem related to this patch.
the empty line is intended. Previously this wouldn't end up formatting because 
the code was trying to be too clever in detecting changes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101515/new/

https://reviews.llvm.org/D101515

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


[PATCH] D101515: clang-format: [JS] handle "off" in imports

2021-04-29 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added reviewers: krasimir, h-joo.
mprobst requested review of this revision.
Herald added a project: clang.

Previously, the JavaScript import sorter would ignore `// clang-format
off` and `on` comments. This change fixes that. It tracks whether
formatting is enabled for a stretch of imports, and then only sorts and
merges the imports where formatting is enabled, in individual chunks.

This means that there's no meaningful total order when module references are 
mixed
with blocks that have formatting disabled. The alternative approach
would have been to sort all imports that have formatting enabled in one
group. However that raises the question where to insert the
formatting-off block, which can also impact symbol visibility (in
particular for exports). In practice, sorting in chunks probably isn't a
big problem.

This change also simplifies the general algorithm: instead of tracking
indices separately and sorting them, it just sorts the vector of module
references. And instead of attempting to do fine grained tracking of
whether the code changed order, it just prints out the module references
text, and compares that to the previous text. Given that source files
typically have dozens, but not even hundreds of imports, the performance
impact seems negligible.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101515

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

Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -358,7 +358,8 @@
 
   // do not merge imports and exports
   verifySort("import {A} from 'foo';\n"
- "export {B} from 'foo';",
+ "\n"
+ "export {B} from 'foo';\n",
  "import {A} from 'foo';\n"
  "export   {B} from 'foo';");
   // do merge exports
@@ -373,6 +374,42 @@
  "import './a';\n");
 }
 
+TEST_F(SortImportsTestJS, RespectsClangFormatOff) {
+  verifySort("// clang-format off\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format on\n",
+ "// clang-format off\n"
+ "import {B} from './b';\n"
+ "import {A} from './a';\n"
+ "// clang-format on\n");
+
+  verifySort("import {A} from './sorted1_a';\n"
+ "import {B} from './sorted1_b';\n"
+ "// clang-format off\n"
+ "import {B} from './unsorted_b';\n"
+ "import {A} from './unsorted_a';\n"
+ "// clang-format on\n"
+ "import {A} from './sorted2_a';\n"
+ "import {B} from './sorted2_b';\n",
+ "import {B} from './sorted1_b';\n"
+ "import {A} from './sorted1_a';\n"
+ "// clang-format off\n"
+ "import {B} from './unsorted_b';\n"
+ "import {A} from './unsorted_a';\n"
+ "// clang-format on\n"
+ "import {B} from './sorted2_b';\n"
+ "import {A} from './sorted2_a';\n");
+
+  // Boundary cases
+  verifySort("// clang-format on\n", "// clang-format on\n");
+  verifySort("// clang-format off\n", "// clang-format off\n");
+  verifySort("// clang-format on\n"
+ "// clang-format off\n",
+ "// clang-format on\n"
+ "// clang-format off\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -19,6 +19,7 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
@@ -69,6 +70,7 @@
 // This struct represents both exports and imports to build up the information
 // required for sorting module references.
 struct JsModuleReference {
+  bool FormattingOff = false;
   bool IsExport = false;
   // Module references are sorted into these categories, in order.
   enum ReferenceCategory {
@@ -146,39 +148,31 @@
 if (References.empty())
   return {Result, 0};
 
-SmallVector Indices;
-for (unsigned i = 0, e = References.size(); i != e; ++i)
-  Indices.push_back(i);
-llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return References[LHSI] < References[RHSI];
-});
-bool ReferencesInOrder = llvm::is_sorted(Indices);
+// The text range of all parsed imports, to be replaced later.
+SourceRange InsertionPoint = References[0].Range;
+InsertionPoint.setEnd(References[References.size() - 1].Range.getEnd());
 
-

[PATCH] D101020: clang-format: [JS] do not merge side-effect imports.

2021-04-22 Thread Martin Probst via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGfbc6f42dbee5: clang-format: [JS] do not merge side-effect 
imports. (authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101020/new/

https://reviews.llvm.org/D101020

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


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -364,6 +364,13 @@
   // do merge exports
   verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"
 "export   {B} from 'foo';");
+
+  // do not merge side effect imports with named ones
+  verifySort("import './a';\n"
+ "\n"
+ "import {bar} from './a';\n",
+ "import {bar} from './a';\n"
+ "import './a';\n");
 }
 
 } // end namespace
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -271,6 +271,7 @@
   //   import Default from 'foo'; on either previous or this.
   //   mismatching
   if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  PreviousReference->Category == JsModuleReference::SIDE_EFFECT ||
   Reference->IsExport != PreviousReference->IsExport ||
   !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
   !PreviousReference->DefaultImport.empty() ||


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -364,6 +364,13 @@
   // do merge exports
   verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"
 "export   {B} from 'foo';");
+
+  // do not merge side effect imports with named ones
+  verifySort("import './a';\n"
+ "\n"
+ "import {bar} from './a';\n",
+ "import {bar} from './a';\n"
+ "import './a';\n");
 }
 
 } // end namespace
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -271,6 +271,7 @@
   //   import Default from 'foo'; on either previous or this.
   //   mismatching
   if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  PreviousReference->Category == JsModuleReference::SIDE_EFFECT ||
   Reference->IsExport != PreviousReference->IsExport ||
   !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
   !PreviousReference->DefaultImport.empty() ||
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D101020: clang-format: [JS] do not merge side-effect imports.

2021-04-21 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added reviewers: krasimir, h-joo.
mprobst requested review of this revision.
Herald added a project: clang.

The if condition was testing the current element, but
forgot to check the previous element (doh), so it
would fail depending on sort order of the imports.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101020

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


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -364,6 +364,13 @@
   // do merge exports
   verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"
 "export   {B} from 'foo';");
+
+  // do not merge side effect imports with named ones
+  verifySort("import './a';\n"
+ "\n"
+ "import {bar} from './a';\n",
+ "import {bar} from './a';\n"
+ "import './a';\n");
 }
 
 } // end namespace
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -271,6 +271,7 @@
   //   import Default from 'foo'; on either previous or this.
   //   mismatching
   if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  PreviousReference->Category == JsModuleReference::SIDE_EFFECT ||
   Reference->IsExport != PreviousReference->IsExport ||
   !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
   !PreviousReference->DefaultImport.empty() ||


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -364,6 +364,13 @@
   // do merge exports
   verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"
 "export   {B} from 'foo';");
+
+  // do not merge side effect imports with named ones
+  verifySort("import './a';\n"
+ "\n"
+ "import {bar} from './a';\n",
+ "import {bar} from './a';\n"
+ "import './a';\n");
 }
 
 } // end namespace
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -271,6 +271,7 @@
   //   import Default from 'foo'; on either previous or this.
   //   mismatching
   if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  PreviousReference->Category == JsModuleReference::SIDE_EFFECT ||
   Reference->IsExport != PreviousReference->IsExport ||
   !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
   !PreviousReference->DefaultImport.empty() ||
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100953: clang-format: [JS] do not wrap after `asserts`

2021-04-21 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG70ae843d9980: clang-format: [JS] do not wrap after `asserts` 
(authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100953/new/

https://reviews.llvm.org/D100953

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2589,5 +2589,20 @@
"}\n");
 }
 
+TEST_F(FormatTestJS, NoBreakAfterAsserts) {
+  verifyFormat(
+  "interface Assertable {\n"
+  "  assert(\n"
+  "  callback: Callback):\n"
+  "  asserts this is ExtendedState;\n"
+  "}\n",
+  "interface Assertable {\n"
+  "  assert(callback: Callback): asserts "
+  "this is ExtendedState;\n"
+  "}\n");
+}
+
 } // namespace format
 } // end namespace clang
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3853,6 +3853,9 @@
  Left.isOneOf(tok::r_square, tok::r_paren)) &&
 Right.isOneOf(tok::l_square, tok::l_paren))
   return false; // Otherwise automatic semicolon insertion would trigger.
+if (NonComment && NonComment->is(tok::identifier) &&
+NonComment->TokenText == "asserts")
+  return false;
 if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
   return false;
 if (Left.is(TT_JsTypeColon))


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2589,5 +2589,20 @@
"}\n");
 }
 
+TEST_F(FormatTestJS, NoBreakAfterAsserts) {
+  verifyFormat(
+  "interface Assertable {\n"
+  "  assert(\n"
+  "  callback: Callback):\n"
+  "  asserts this is ExtendedState;\n"
+  "}\n",
+  "interface Assertable {\n"
+  "  assert(callback: Callback): asserts "
+  "this is ExtendedState;\n"
+  "}\n");
+}
+
 } // namespace format
 } // end namespace clang
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3853,6 +3853,9 @@
  Left.isOneOf(tok::r_square, tok::r_paren)) &&
 Right.isOneOf(tok::l_square, tok::l_paren))
   return false; // Otherwise automatic semicolon insertion would trigger.
+if (NonComment && NonComment->is(tok::identifier) &&
+NonComment->TokenText == "asserts")
+  return false;
 if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
   return false;
 if (Left.is(TT_JsTypeColon))
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100953: clang-format: [JS] do not wrap after `asserts`

2021-04-21 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added reviewers: krasimir, h-joo.
mprobst requested review of this revision.
Herald added a project: clang.

`asserts` is a pseudo keyword in TypeScript used in return types.
Wrapping after it triggers automatic semicolon insertion, which
breaks the code semantics/syntax.

`asserts` is different from other pseudo keywords in that it is
specific to TS and only carries meaning in a very specific location.
Thus introducing a token type is probably overkill.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D100953

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2589,5 +2589,20 @@
"}\n");
 }
 
+TEST_F(FormatTestJS, NoBreakAfterAsserts) {
+  verifyFormat(
+  "interface Assertable {\n"
+  "  assert(\n"
+  "  callback: Callback):\n"
+  "  asserts this is ExtendedState;\n"
+  "}\n",
+  "interface Assertable {\n"
+  "  assert(callback: Callback): asserts "
+  "this is ExtendedState;\n"
+  "}\n");
+}
+
 } // namespace format
 } // end namespace clang
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3853,6 +3853,9 @@
  Left.isOneOf(tok::r_square, tok::r_paren)) &&
 Right.isOneOf(tok::l_square, tok::l_paren))
   return false; // Otherwise automatic semicolon insertion would trigger.
+if (NonComment && NonComment->is(tok::identifier) &&
+NonComment->TokenText == "asserts")
+  return false;
 if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
   return false;
 if (Left.is(TT_JsTypeColon))


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2589,5 +2589,20 @@
"}\n");
 }
 
+TEST_F(FormatTestJS, NoBreakAfterAsserts) {
+  verifyFormat(
+  "interface Assertable {\n"
+  "  assert(\n"
+  "  callback: Callback):\n"
+  "  asserts this is ExtendedState;\n"
+  "}\n",
+  "interface Assertable {\n"
+  "  assert(callback: Callback): asserts "
+  "this is ExtendedState;\n"
+  "}\n");
+}
+
 } // namespace format
 } // end namespace clang
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3853,6 +3853,9 @@
  Left.isOneOf(tok::r_square, tok::r_paren)) &&
 Right.isOneOf(tok::l_square, tok::l_paren))
   return false; // Otherwise automatic semicolon insertion would trigger.
+if (NonComment && NonComment->is(tok::identifier) &&
+NonComment->TokenText == "asserts")
+  return false;
 if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
   return false;
 if (Left.is(TT_JsTypeColon))
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100752: clang-format: [JS] do not merge imports and exports.

2021-04-20 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3d4a6037ff46: clang-format: [JS] do not merge imports and 
exports. (authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100752/new/

https://reviews.llvm.org/D100752

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


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -355,6 +355,15 @@
  "import {/* x */ X} from 'a';\n"
  "\n"
  "X + Y + Z;\n");
+
+  // do not merge imports and exports
+  verifySort("import {A} from 'foo';\n"
+ "export {B} from 'foo';",
+ "import {A} from 'foo';\n"
+ "export   {B} from 'foo';");
+  // do merge exports
+  verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"
+"export   {B} from 'foo';");
 }
 
 } // end namespace
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -271,6 +271,7 @@
   //   import Default from 'foo'; on either previous or this.
   //   mismatching
   if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  Reference->IsExport != PreviousReference->IsExport ||
   !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
   !PreviousReference->DefaultImport.empty() ||
   !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -355,6 +355,15 @@
  "import {/* x */ X} from 'a';\n"
  "\n"
  "X + Y + Z;\n");
+
+  // do not merge imports and exports
+  verifySort("import {A} from 'foo';\n"
+ "export {B} from 'foo';",
+ "import {A} from 'foo';\n"
+ "export   {B} from 'foo';");
+  // do merge exports
+  verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"
+"export   {B} from 'foo';");
 }
 
 } // end namespace
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -271,6 +271,7 @@
   //   import Default from 'foo'; on either previous or this.
   //   mismatching
   if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  Reference->IsExport != PreviousReference->IsExport ||
   !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
   !PreviousReference->DefaultImport.empty() ||
   !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100752: clang-format: [JS] do not merge imports and exports.

2021-04-19 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
mprobst requested review of this revision.
Herald added a project: clang.

Previously, clang-format would erroneously merge import and export
statements. These need to be kept separate, as the semantics differ.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D100752

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


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -355,6 +355,15 @@
  "import {/* x */ X} from 'a';\n"
  "\n"
  "X + Y + Z;\n");
+
+  // do not merge imports and exports
+  verifySort("import {A} from 'foo';\n"
+ "export {B} from 'foo';",
+ "import {A} from 'foo';\n"
+ "export   {B} from 'foo';");
+  // do merge exports
+  verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"
+"export   {B} from 'foo';");
 }
 
 } // end namespace
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -271,6 +271,7 @@
   //   import Default from 'foo'; on either previous or this.
   //   mismatching
   if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  Reference->IsExport != PreviousReference->IsExport ||
   !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
   !PreviousReference->DefaultImport.empty() ||
   !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||


Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -355,6 +355,15 @@
  "import {/* x */ X} from 'a';\n"
  "\n"
  "X + Y + Z;\n");
+
+  // do not merge imports and exports
+  verifySort("import {A} from 'foo';\n"
+ "export {B} from 'foo';",
+ "import {A} from 'foo';\n"
+ "export   {B} from 'foo';");
+  // do merge exports
+  verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"
+"export   {B} from 'foo';");
 }
 
 } // end namespace
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -271,6 +271,7 @@
   //   import Default from 'foo'; on either previous or this.
   //   mismatching
   if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  Reference->IsExport != PreviousReference->IsExport ||
   !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
   !PreviousReference->DefaultImport.empty() ||
   !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100466: clang-format: [JS] merge import lines.

2021-04-14 Thread Martin Probst via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
mprobst marked an inline comment as done.
Closed by commit rGd45df0d29f70: clang-format: [JS] merge import lines. 
(authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D100466?vs=337456=337464#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100466/new/

https://reviews.llvm.org/D100466

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

Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -307,6 +307,52 @@
  "import {A} from 'a';\n");
 }
 
+TEST_F(SortImportsTestJS, MergeImports) {
+  // basic operation
+  verifySort("import {X, Y} from 'a';\n"
+ "import {Z} from 'z';\n"
+ "\n"
+ "X + Y + Z;\n",
+ "import {X} from 'a';\n"
+ "import {Z} from 'z';\n"
+ "import {Y} from 'a';\n"
+ "\n"
+ "X + Y + Z;\n");
+
+  // empty imports
+  verifySort("import {A} from 'foo';\n", "import {} from 'foo';\n"
+ "import {A} from 'foo';");
+
+  // ignores import *
+  verifySort("import * as foo from 'foo';\n"
+ "import {A} from 'foo';\n",
+ "import   * as foo from 'foo';\n"
+ "import {A} from 'foo';\n");
+
+  // ignores default import
+  verifySort("import X from 'foo';\n"
+ "import {A} from 'foo';\n",
+ "importX from 'foo';\n"
+ "import {A} from 'foo';\n");
+
+  // keeps comments
+  // known issue: loses the 'also a' comment.
+  verifySort("// a\n"
+ "import {/* x */ X, /* y */ Y} from 'a';\n"
+ "// z\n"
+ "import {Z} from 'z';\n"
+ "\n"
+ "X + Y + Z;\n",
+ "// a\n"
+ "import {/* y */ Y} from 'a';\n"
+ "// z\n"
+ "import {Z} from 'z';\n"
+ "// also a\n"
+ "import {/* x */ X} from 'a';\n"
+ "\n"
+ "X + Y + Z;\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -83,8 +83,13 @@
   // Prefix from "import * as prefix". Empty for symbol imports and `export *`.
   // Implies an empty names list.
   StringRef Prefix;
+  // Default import from "import DefaultName from '...';".
+  StringRef DefaultImport;
   // Symbols from `import {SymbolA, SymbolB, ...} from ...;`.
   SmallVector Symbols;
+  // The source location just after { and just before } in the import.
+  // Extracted eagerly to allow modification of Symbols later on.
+  SourceLocation SymbolsStart, SymbolsEnd;
   // Textual position of the import/export, including preceding and trailing
   // comments.
   SourceRange Range;
@@ -146,6 +151,41 @@
 });
 bool ReferencesInOrder = llvm::is_sorted(Indices);
 
+// Merge module references:
+// After sorting, find all references that import named symbols from the
+// same URL and merge their names. E.g.
+//   import {X} from 'a';
+//   import {Y} from 'a';
+// should be rewritten to:
+//   import {X, Y} from 'a';
+// Note: this removes merged imports from Indices, but not from References.
+// The loop below iterates Indices, so things work out.
+JsModuleReference *PreviousReference = [Indices[0]];
+auto *it = std::next(Indices.begin());
+bool ImportsMerged = false;
+while (it != std::end(Indices)) {
+  JsModuleReference *Reference = [*it];
+  // Skip:
+  //   import 'foo';
+  //   import * as foo from 'foo'; on either previous or this.
+  //   import Default from 'foo'; on either previous or this.
+  //   mismatching
+  if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
+  !PreviousReference->DefaultImport.empty() ||
+  !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
+  PreviousReference->URL != Reference->URL) {
+PreviousReference = Reference;
+++it;
+continue;
+  }
+  // Merge symbols from identical imports.
+  PreviousReference->Symbols.append(Reference->Symbols);
+  ImportsMerged = true;
+  // Remove the merged import.
+  it = Indices.erase(it);
+}
+
 std::string ReferencesText;
 bool SymbolsInOrder = true;
 for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
@@ -164,7 +204,7 @@
   }
 }
 
-if (ReferencesInOrder 

[PATCH] D100466: clang-format: [JS] merge import lines.

2021-04-14 Thread Martin Probst via Phabricator via cfe-commits
mprobst marked 3 inline comments as done.
mprobst added inline comments.



Comment at: clang/lib/Format/SortJavaScriptImports.cpp:92
+  // reference needs re-formatting.
+  bool SymbolsMerged;
   // The source location just after { and just before } in the import.

FYI I restructured the algorithm a bit here.



Comment at: clang/unittests/Format/SortImportsTestJS.cpp:333
+  // ignores default import
+  verifySort("import X from 'foo';\n"
+ "import {A} from 'foo';\n",

h-joo wrote:
> I'm a bit confused on what this is trying to test. Could you explain?
This makes sure we don't collapse `import * as foo` imports with `import {A}` 
style imports.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100466/new/

https://reviews.llvm.org/D100466

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


[PATCH] D100466: clang-format: [JS] merge import lines.

2021-04-14 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 337456.
mprobst added a comment.

address review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100466/new/

https://reviews.llvm.org/D100466

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

Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -319,6 +319,10 @@
  "\n"
  "X + Y + Z;\n");
 
+  // merge only, no resorting.
+  verifySort("import {A, B} from 'foo';\n", "import {A} from 'foo';\n"
+"import {B} from 'foo';");
+
   // empty imports
   verifySort("import {A} from 'foo';\n", "import {} from 'foo';\n"
  "import {A} from 'foo';");
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -87,6 +87,9 @@
   StringRef DefaultImport;
   // Symbols from `import {SymbolA, SymbolB, ...} from ...;`.
   SmallVector Symbols;
+  // Whether some symbols were merged into this one. Controls if the module
+  // reference needs re-formatting.
+  bool SymbolsMerged;
   // The source location just after { and just before } in the import.
   // Extracted eagerly to allow modification of Symbols later on.
   SourceLocation SymbolsStart, SymbolsEnd;
@@ -151,40 +154,7 @@
 });
 bool ReferencesInOrder = llvm::is_sorted(Indices);
 
-// Merge module references:
-// After sorting, find all references that import named symbols from the
-// same URL and merge their names. E.g.
-//   import {X} from 'a';
-//   import {Y} from 'a';
-// should be rewritten to:
-//   import {X, Y} from 'a';
-// Note: this removes merged imports from Indices, but not from References.
-// The loop below iterates Indices, so things work out.
-JsModuleReference *PreviousReference = [Indices[0]];
-auto *it = std::next(Indices.begin());
-bool ImportsMerged = false;
-while (it != std::end(Indices)) {
-  JsModuleReference *Reference = [*it];
-  // Skip:
-  //   import 'foo';
-  //   import * as foo from 'foo'; on either previous or this.
-  //   import Default from 'foo'; on either previous or this.
-  //   mismatching
-  if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
-  !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
-  !PreviousReference->DefaultImport.empty() ||
-  !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
-  PreviousReference->URL != Reference->URL) {
-PreviousReference = Reference;
-++it;
-continue;
-  }
-  // Merge symbols from identical imports.
-  PreviousReference->Symbols.append(Reference->Symbols);
-  ImportsMerged = true;
-  // Remove the merged import.
-  it = Indices.erase(it);
-}
+mergeModuleReferences(References, Indices);
 
 std::string ReferencesText;
 bool SymbolsInOrder = true;
@@ -203,8 +173,7 @@
   ReferencesText += "\n";
   }
 }
-
-if (ReferencesInOrder && SymbolsInOrder && !ImportsMerged)
+if (ReferencesInOrder && SymbolsInOrder)
   return {Result, 0};
 
 SourceRange InsertionPoint = References[0].Range;
@@ -279,22 +248,61 @@
SM.getFileOffset(End) - SM.getFileOffset(Begin));
   }
 
+  // Merge module references.
+  // After sorting, find all references that import named symbols from the
+  // same URL and merge their names. E.g.
+  //   import {X} from 'a';
+  //   import {Y} from 'a';
+  // should be rewritten to:
+  //   import {X, Y} from 'a';
+  // Note: this modifies the passed in ``Indices`` vector (by removing no longer
+  // needed references), but not ``References``.
+  // ``JsModuleReference``s that get merged have the ``SymbolsMerged`` flag
+  // flipped to true.
+  void mergeModuleReferences(SmallVector ,
+ SmallVector ) {
+JsModuleReference *PreviousReference = [Indices[0]];
+auto *It = std::next(Indices.begin());
+while (It != std::end(Indices)) {
+  JsModuleReference *Reference = [*It];
+  // Skip:
+  //   import 'foo';
+  //   import * as foo from 'foo'; on either previous or this.
+  //   import Default from 'foo'; on either previous or this.
+  //   mismatching
+  if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
+  !PreviousReference->DefaultImport.empty() ||
+  !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
+  PreviousReference->URL != 

[PATCH] D100466: clang-format: [JS] merge import lines.

2021-04-14 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
mprobst requested review of this revision.
Herald added a project: clang.

Multiple lines importing from the same URL can be merged:

  import {X} from 'a';
  import {Y} from 'a';

Merge to:

  import {X, Y} from 'a';

This change implements this merge operation. It takes care not to merge in
various corner case situations (default imports, star imports).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D100466

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

Index: clang/unittests/Format/SortImportsTestJS.cpp
===
--- clang/unittests/Format/SortImportsTestJS.cpp
+++ clang/unittests/Format/SortImportsTestJS.cpp
@@ -307,6 +307,52 @@
  "import {A} from 'a';\n");
 }
 
+TEST_F(SortImportsTestJS, MergeImports) {
+  // basic operation
+  verifySort("import {X, Y} from 'a';\n"
+ "import {Z} from 'z';\n"
+ "\n"
+ "X + Y + Z;\n",
+ "import {X} from 'a';\n"
+ "import {Z} from 'z';\n"
+ "import {Y} from 'a';\n"
+ "\n"
+ "X + Y + Z;\n");
+
+  // empty imports
+  verifySort("import {A} from 'foo';\n", "import {} from 'foo';\n"
+ "import {A} from 'foo';");
+
+  // ignores import *
+  verifySort("import * as foo from 'foo';\n"
+ "import {A} from 'foo';\n",
+ "import   * as foo from 'foo';\n"
+ "import {A} from 'foo';\n");
+
+  // ignores default import
+  verifySort("import X from 'foo';\n"
+ "import {A} from 'foo';\n",
+ "importX from 'foo';\n"
+ "import {A} from 'foo';\n");
+
+  // keeps comments
+  // known issue: loses the 'also a' comment.
+  verifySort("// a\n"
+ "import {/* x */ X, /* y */ Y} from 'a';\n"
+ "// z\n"
+ "import {Z} from 'z';\n"
+ "\n"
+ "X + Y + Z;\n",
+ "// a\n"
+ "import {/* y */ Y} from 'a';\n"
+ "// z\n"
+ "import {Z} from 'z';\n"
+ "// also a\n"
+ "import {/* x */ X} from 'a';\n"
+ "\n"
+ "X + Y + Z;\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
Index: clang/lib/Format/SortJavaScriptImports.cpp
===
--- clang/lib/Format/SortJavaScriptImports.cpp
+++ clang/lib/Format/SortJavaScriptImports.cpp
@@ -83,8 +83,13 @@
   // Prefix from "import * as prefix". Empty for symbol imports and `export *`.
   // Implies an empty names list.
   StringRef Prefix;
+  // Default import from "import DefaultName from '...';".
+  StringRef DefaultImport;
   // Symbols from `import {SymbolA, SymbolB, ...} from ...;`.
   SmallVector Symbols;
+  // The source location just after { and just before } in the import.
+  // Extracted eagerly to allow modification of Symbols later on.
+  SourceLocation SymbolsStart, SymbolsEnd;
   // Textual position of the import/export, including preceding and trailing
   // comments.
   SourceRange Range;
@@ -146,6 +151,41 @@
 });
 bool ReferencesInOrder = llvm::is_sorted(Indices);
 
+// Merge module references:
+// After sorting, find all references that import named symbols from the
+// same URL and merge their names. E.g.
+//   import {X} from 'a';
+//   import {Y} from 'a';
+// should be rewritten to:
+//   import {X, Y} from 'a';
+// Note: this removes merged imports from Indices, but not from References.
+// The loop below iterates Indices, so things work out.
+JsModuleReference *PreviousReference = [Indices[0]];
+auto *it = std::next(Indices.begin());
+bool ImportsMerged = false;
+while (it != std::end(Indices)) {
+  JsModuleReference *Reference = [*it];
+  // Skip:
+  //   import 'foo';
+  //   import * as foo from 'foo'; on either previous or this.
+  //   import Default from 'foo'; on either previous or this.
+  //   mismatching
+  if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+  !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
+  !PreviousReference->DefaultImport.empty() ||
+  !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
+  PreviousReference->URL != Reference->URL) {
+PreviousReference = Reference;
+++it;
+continue;
+  }
+  // Merge symbols from identical imports.
+  PreviousReference->Symbols.append(Reference->Symbols);
+  ImportsMerged = true;
+  // Remove the merged import.
+  it = Indices.erase(it);
+}
+
 std::string ReferencesText;
 bool SymbolsInOrder = true;
 for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
@@ -164,7 +204,7 @@
   }
 }
 
-if 

[PATCH] D99495: clang-format: [JS] do not collapse - - to --.

2021-03-30 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG2b30bd2be0a8: clang-format: [JS] do not collapse - - to --. 
(authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D99495/new/

https://reviews.llvm.org/D99495

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -276,6 +276,12 @@
   // ES6 spread operator.
   verifyFormat("someFunction(...a);");
   verifyFormat("var x = [1, ...a, 2];");
+
+  // "- -1" is legal JS syntax, but must not collapse into "--".
+  verifyFormat("- -1;", " - -1;");
+  verifyFormat("-- -1;", " -- -1;");
+  verifyFormat("+ +1;", " + +1;");
+  verifyFormat("++ +1;", " ++ +1;");
 }
 
 TEST_F(FormatTestJS, UnderstandsAmpAmp) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3370,6 +3370,12 @@
  Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
 return true;
   }
+  // Do not merge "- -" into "--".
+  if ((Left.isOneOf(tok::minus, tok::minusminus) &&
+   Right.isOneOf(tok::minus, tok::minusminus)) ||
+  (Left.isOneOf(tok::plus, tok::plusplus) &&
+   Right.isOneOf(tok::plus, tok::plusplus)))
+return true;
   if (Left.is(TT_UnaryOperator)) {
 if (!Right.is(tok::l_paren)) {
   // The alternative operators for ~ and ! are "compl" and "not".


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -276,6 +276,12 @@
   // ES6 spread operator.
   verifyFormat("someFunction(...a);");
   verifyFormat("var x = [1, ...a, 2];");
+
+  // "- -1" is legal JS syntax, but must not collapse into "--".
+  verifyFormat("- -1;", " - -1;");
+  verifyFormat("-- -1;", " -- -1;");
+  verifyFormat("+ +1;", " + +1;");
+  verifyFormat("++ +1;", " ++ +1;");
 }
 
 TEST_F(FormatTestJS, UnderstandsAmpAmp) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3370,6 +3370,12 @@
  Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
 return true;
   }
+  // Do not merge "- -" into "--".
+  if ((Left.isOneOf(tok::minus, tok::minusminus) &&
+   Right.isOneOf(tok::minus, tok::minusminus)) ||
+  (Left.isOneOf(tok::plus, tok::plusplus) &&
+   Right.isOneOf(tok::plus, tok::plusplus)))
+return true;
   if (Left.is(TT_UnaryOperator)) {
 if (!Right.is(tok::l_paren)) {
   // The alternative operators for ~ and ! are "compl" and "not".
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D99495: clang-format: [JS] do not collapse - - to --.

2021-03-29 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
mprobst requested review of this revision.
Herald added a project: clang.

In JavaScript, `- -1;` is legal syntax, the language allows unary minus.
However the two tokens must not collapse together: `--1` is prefix
decrement, i.e. different syntax.

Before:

- -1; ==> --1;

After:

- -1; ==> - -1;

This change makes no attempt to format this "nicely", given by all
likelihood this represents a programming mistake by the user, or odd
generated code.

The check is not guarded by language: this appears to be a problem in
Java as well, and will also be beneficial when formatting syntactically
incorrect C++ (e.g. during editing).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D99495

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -276,6 +276,12 @@
   // ES6 spread operator.
   verifyFormat("someFunction(...a);");
   verifyFormat("var x = [1, ...a, 2];");
+
+  // "- -1" is legal JS syntax, but must not collapse into "--".
+  verifyFormat("- -1;", " - -1;");
+  verifyFormat("-- -1;", " -- -1;");
+  verifyFormat("+ +1;", " + +1;");
+  verifyFormat("++ +1;", " ++ +1;");
 }
 
 TEST_F(FormatTestJS, UnderstandsAmpAmp) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3370,6 +3370,12 @@
  Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
 return true;
   }
+  // Do not merge "- -" into "--".
+  if ((Left.isOneOf(tok::minus, tok::minusminus) &&
+   Right.isOneOf(tok::minus, tok::minusminus)) ||
+  (Left.isOneOf(tok::plus, tok::plusplus) &&
+   Right.isOneOf(tok::plus, tok::plusplus)))
+return true;
   if (Left.is(TT_UnaryOperator)) {
 if (!Right.is(tok::l_paren)) {
   // The alternative operators for ~ and ! are "compl" and "not".


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -276,6 +276,12 @@
   // ES6 spread operator.
   verifyFormat("someFunction(...a);");
   verifyFormat("var x = [1, ...a, 2];");
+
+  // "- -1" is legal JS syntax, but must not collapse into "--".
+  verifyFormat("- -1;", " - -1;");
+  verifyFormat("-- -1;", " -- -1;");
+  verifyFormat("+ +1;", " + +1;");
+  verifyFormat("++ +1;", " ++ +1;");
 }
 
 TEST_F(FormatTestJS, UnderstandsAmpAmp) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3370,6 +3370,12 @@
  Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
 return true;
   }
+  // Do not merge "- -" into "--".
+  if ((Left.isOneOf(tok::minus, tok::minusminus) &&
+   Right.isOneOf(tok::minus, tok::minusminus)) ||
+  (Left.isOneOf(tok::plus, tok::plusplus) &&
+   Right.isOneOf(tok::plus, tok::plusplus)))
+return true;
   if (Left.is(TT_UnaryOperator)) {
 if (!Right.is(tok::l_paren)) {
   // The alternative operators for ~ and ! are "compl" and "not".
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D91078: [clang-format] do not break before @tags in JS comments

2020-11-10 Thread Martin Probst via Phabricator via cfe-commits
mprobst added a comment.

For posterity: there was a question whether this is legal syntax in JSDoc in 
the first place (e.g. whether it should be escaped). That remains unclear - 
Closure Compiler parser however does ignore JSDoc tags if the line does not 
start with an `@` tag. So the safe thing is to do what this revision does, 
avoid wrapping.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91078/new/

https://reviews.llvm.org/D91078

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


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

2020-11-10 Thread Martin Probst via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG16212b8b3e4f: clang-format: [JS] support new assignment 
operators. (authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91132/new/

https://reviews.llvm.org/D91132

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2424,6 +2424,15 @@
   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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -121,6 +121,10 @@
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 @@
   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;
   }
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -68,6 +68,9 @@
   TYPE(JsTypeColon)
\
   TYPE(JsTypeOperator) 
\
   TYPE(JsTypeOptionalQuestion) 
\
+  TYPE(JsAndAndEqual)  
\
+  TYPE(JsPipePipeEqual)
\
+  TYPE(JsNullishCoalescingEqual)   
\
   TYPE(LambdaArrow)
\
   TYPE(LambdaLBrace)   
\
   TYPE(LambdaLSquare)  
\


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2424,6 +2424,15 @@
   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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -121,6 +121,10 @@
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 @@
   

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

2020-11-10 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 304069.
mprobst added a comment.

- fix comment


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91132/new/

https://reviews.llvm.org/D91132

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2424,6 +2424,15 @@
   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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -121,6 +121,10 @@
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 @@
   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;
   }
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -68,6 +68,9 @@
   TYPE(JsTypeColon)
\
   TYPE(JsTypeOperator) 
\
   TYPE(JsTypeOptionalQuestion) 
\
+  TYPE(JsAndAndEqual)  
\
+  TYPE(JsPipePipeEqual)
\
+  TYPE(JsNullishCoalescingEqual)   
\
   TYPE(LambdaArrow)
\
   TYPE(LambdaLBrace)   
\
   TYPE(LambdaLSquare)  
\


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2424,6 +2424,15 @@
   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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -121,6 +121,10 @@
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 @@
   Tokens.back()->Tok.setKind(tok::period);
   return;
 }
+if (tryMergeTokens(JSAndAndEqual, TT_JsAndAndEqual) ||
+tryMergeTokens(JSPipePipeEqual, 

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

2020-11-10 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a project: clang.
mprobst requested review of this revision.

Before:

  a && = b;

After:

  a &&= b;

These operators are new additions in ES2021.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D91132

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2424,6 +2424,15 @@
   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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -121,6 +121,10 @@
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 @@
   Tokens.back()->Tok.setKind(tok::period);
   return;
 }
+if (tryMergeTokens(JSAndAndEqual, TT_JsAndAndEqual) ||
+tryMergeTokens(JSPipePipeEqual, TT_JsPipePipeEqual) ||
+tryMergeTokens(JSNullishEqual, TT_JsNullishCoalescingEqual)) {
+  // Treat like the "||" operator (as opposed to the ternary ?).
+  Tokens.back()->Tok.setKind(tok::equal);
+  return;
+}
 if (tryMergeJSPrivateIdentifier())
   return;
   }
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -68,6 +68,9 @@
   TYPE(JsTypeColon)
\
   TYPE(JsTypeOperator) 
\
   TYPE(JsTypeOptionalQuestion) 
\
+  TYPE(JsAndAndEqual)  
\
+  TYPE(JsPipePipeEqual)
\
+  TYPE(JsNullishCoalescingEqual)   
\
   TYPE(LambdaArrow)
\
   TYPE(LambdaLBrace)   
\
   TYPE(LambdaLSquare)  
\


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2424,6 +2424,15 @@
   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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -121,6 +121,10 @@
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 @@
   Tokens.back()->Tok.setKind(tok::period);
   return;
 }
+if 

[PATCH] D91078: [clang-format] do not break before @tags in JS comments

2020-11-09 Thread Martin Probst via Phabricator via cfe-commits
mprobst added a comment.

See my comment on the upstream bug, let's chat a bit about whether we need this.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91078/new/

https://reviews.llvm.org/D91078

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


[PATCH] D77548: clang-format: [JS] handle pseudo-keywords.

2020-04-06 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG92201505cdec: clang-format: [JS] handle pseudo-keywords. 
(authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D77548?vs=255314=255357#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77548/new/

https://reviews.llvm.org/D77548

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2412,6 +2412,11 @@
   verifyFormat("using!;");
   verifyFormat("virtual!;");
   verifyFormat("wchar_t!;");
+
+  // Positive tests:
+  verifyFormat("x.type!;");
+  verifyFormat("x.get!;");
+  verifyFormat("x.set!;");
 }
 
 TEST_F(FormatTestJS, NullPropagatingOperator) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -1522,9 +1522,11 @@
 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 @@
   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))
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -909,7 +909,11 @@
 
   /// 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 ) 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 ,
+  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 @@
 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.


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2412,6 +2412,11 @@
   verifyFormat("using!;");
   verifyFormat("virtual!;");
   verifyFormat("wchar_t!;");
+
+  // Positive tests:
+  verifyFormat("x.type!;");
+  verifyFormat("x.get!;");
+  verifyFormat("x.set!;");
 }
 
 TEST_F(FormatTestJS, NullPropagatingOperator) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -1522,9 +1522,11 @@
 if (Style.Language == FormatStyle::LK_JavaScript) {
   if (Current.is(tok::exclaim)) {
 if 

[PATCH] D77548: clang-format: [JS] handle pseudo-keywords.

2020-04-06 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D77548

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2412,6 +2412,11 @@
   verifyFormat("using!;");
   verifyFormat("virtual!;");
   verifyFormat("wchar_t!;");
+
+  // Positive tests:
+  verifyFormat("x.type!;");
+  verifyFormat("x.get!;");
+  verifyFormat("x.set!;");
 }
 
 TEST_F(FormatTestJS, NullPropagatingOperator) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -1522,9 +1522,11 @@
 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 @@
   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))
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -909,7 +909,11 @@
 
   /// 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 ) 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 ,
+  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 @@
 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.


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2412,6 +2412,11 @@
   verifyFormat("using!;");
   verifyFormat("virtual!;");
   verifyFormat("wchar_t!;");
+
+  // Positive tests:
+  

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

2020-04-03 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
mprobst marked an inline comment as done.
Closed by commit rG146d685cd657: clang-format: [JS] detect C++ keywords. 
(authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D77311?vs=254741=254763#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77311/new/

https://reviews.llvm.org/D77311

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

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -386,13 +386,6 @@
"return (x);\n");
 }
 
-TEST_F(FormatTestJS, CppKeywords) {
-  // Make sure we don't mess stuff up because of C++ keywords.
-  verifyFormat("return operator && (aa);");
-  // .. or QT ones.
-  verifyFormat("slots: Slot[];");
-}
-
 TEST_F(FormatTestJS, ES6DestructuringAssignment) {
   verifyFormat("var [a, b, c] = [1, 2, 3];");
   verifyFormat("const [a, b, c] = [1, 2, 3];");
@@ -2366,6 +2359,61 @@
   verifyFormat("return !!x;\n");
 }
 
+TEST_F(FormatTestJS, CppKeywords) {
+  // Make sure we don't mess stuff up because of C++ keywords.
+  verifyFormat("return operator && (aa);");
+  // .. or QT ones.
+  verifyFormat("const slots: Slot[];");
+  // use the "!" assertion operator to validate that clang-format understands
+  // these C++ keywords aren't keywords in JS/TS.
+  verifyFormat("auto!;");
+  verifyFormat("char!;");
+  verifyFormat("concept!;");
+  verifyFormat("double!;");
+  verifyFormat("extern!;");
+  verifyFormat("float!;");
+  verifyFormat("inline!;");
+  verifyFormat("int!;");
+  verifyFormat("long!;");
+  verifyFormat("register!;");
+  verifyFormat("restrict!;");
+  verifyFormat("sizeof!;");
+  verifyFormat("struct!;");
+  verifyFormat("typedef!;");
+  verifyFormat("union!;");
+  verifyFormat("unsigned!;");
+  verifyFormat("volatile!;");
+  verifyFormat("_Alignas!;");
+  verifyFormat("_Alignof!;");
+  verifyFormat("_Atomic!;");
+  verifyFormat("_Bool!;");
+  verifyFormat("_Complex!;");
+  verifyFormat("_Generic!;");
+  verifyFormat("_Imaginary!;");
+  verifyFormat("_Noreturn!;");
+  verifyFormat("_Static_assert!;");
+  verifyFormat("_Thread_local!;");
+  verifyFormat("__func__!;");
+  verifyFormat("__objc_yes!;");
+  verifyFormat("__objc_no!;");
+  verifyFormat("asm!;");
+  verifyFormat("bool!;");
+  verifyFormat("const_cast!;");
+  verifyFormat("dynamic_cast!;");
+  verifyFormat("explicit!;");
+  verifyFormat("friend!;");
+  verifyFormat("mutable!;");
+  verifyFormat("operator!;");
+  verifyFormat("reinterpret_cast!;");
+  verifyFormat("static_cast!;");
+  verifyFormat("template!;");
+  verifyFormat("typename!;");
+  verifyFormat("typeid!;");
+  verifyFormat("using!;");
+  verifyFormat("virtual!;");
+  verifyFormat("wchar_t!;");
+}
+
 TEST_F(FormatTestJS, NullPropagatingOperator) {
   verifyFormat("let x = foo?.bar?.baz();\n");
   verifyFormat("let x = foo?.(foo);\n");
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -1522,9 +1522,9 @@
 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 @@
 (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(Left) &&
-Right.is(TT_TemplateString))
+// the tag identifier and the template string.
+if (Keywords.IsJavaScriptIdentifier(Left) && Right.is(TT_TemplateString))
   return false;
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -910,9 +910,64 @@
   /// Returns \c true if \p Tok is a true JavaScript identifier, returns
   /// \c 

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

2020-04-03 Thread Martin Probst via Phabricator via cfe-commits
mprobst marked 2 inline comments as done.
mprobst added inline comments.



Comment at: clang/lib/Format/FormatToken.h:913
   bool IsJavaScriptIdentifier(const FormatToken ) const {
-return Tok.is(tok::identifier) &&
-   JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==
-   JsExtraKeywords.end();
+switch (Tok.Tok.getKind()) {
+case tok::kw_break:

krasimir wrote:
> nit: may be worth adding a comment linking to:
> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords
Done, though I used the TS list of keywords (as it's a superset of the JS 
keywords).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77311/new/

https://reviews.llvm.org/D77311



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


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

2020-04-03 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 254740.
mprobst added a comment.

- - improve handling of keywors - rather than blacklisting all C++


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77311/new/

https://reviews.llvm.org/D77311

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

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -386,13 +386,6 @@
"return (x);\n");
 }
 
-TEST_F(FormatTestJS, CppKeywords) {
-  // Make sure we don't mess stuff up because of C++ keywords.
-  verifyFormat("return operator && (aa);");
-  // .. or QT ones.
-  verifyFormat("slots: Slot[];");
-}
-
 TEST_F(FormatTestJS, ES6DestructuringAssignment) {
   verifyFormat("var [a, b, c] = [1, 2, 3];");
   verifyFormat("const [a, b, c] = [1, 2, 3];");
@@ -2366,6 +2359,61 @@
   verifyFormat("return !!x;\n");
 }
 
+TEST_F(FormatTestJS, CppKeywords) {
+  // Make sure we don't mess stuff up because of C++ keywords.
+  verifyFormat("return operator && (aa);");
+  // .. or QT ones.
+  verifyFormat("const slots: Slot[];");
+  // use the "!" assertion operator to validate that clang-format understands
+  // these C++ keywords aren't keywords in JS/TS.
+  verifyFormat("auto!;");
+  verifyFormat("char!;");
+  verifyFormat("concept!;");
+  verifyFormat("double!;");
+  verifyFormat("extern!;");
+  verifyFormat("float!;");
+  verifyFormat("inline!;");
+  verifyFormat("int!;");
+  verifyFormat("long!;");
+  verifyFormat("register!;");
+  verifyFormat("restrict!;");
+  verifyFormat("sizeof!;");
+  verifyFormat("struct!;");
+  verifyFormat("typedef!;");
+  verifyFormat("union!;");
+  verifyFormat("unsigned!;");
+  verifyFormat("volatile!;");
+  verifyFormat("_Alignas!;");
+  verifyFormat("_Alignof!;");
+  verifyFormat("_Atomic!;");
+  verifyFormat("_Bool!;");
+  verifyFormat("_Complex!;");
+  verifyFormat("_Generic!;");
+  verifyFormat("_Imaginary!;");
+  verifyFormat("_Noreturn!;");
+  verifyFormat("_Static_assert!;");
+  verifyFormat("_Thread_local!;");
+  verifyFormat("__func__!;");
+  verifyFormat("__objc_yes!;");
+  verifyFormat("__objc_no!;");
+  verifyFormat("asm!;");
+  verifyFormat("bool!;");
+  verifyFormat("const_cast!;");
+  verifyFormat("dynamic_cast!;");
+  verifyFormat("explicit!;");
+  verifyFormat("friend!;");
+  verifyFormat("mutable!;");
+  verifyFormat("operator!;");
+  verifyFormat("reinterpret_cast!;");
+  verifyFormat("static_cast!;");
+  verifyFormat("template!;");
+  verifyFormat("typename!;");
+  verifyFormat("typeid!;");
+  verifyFormat("using!;");
+  verifyFormat("virtual!;");
+  verifyFormat("wchar_t!;");
+}
+
 TEST_F(FormatTestJS, NullPropagatingOperator) {
   verifyFormat("let x = foo?.bar?.baz();\n");
   verifyFormat("let x = foo?.(foo);\n");
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -1522,9 +1522,9 @@
 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 @@
 (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(Left) &&
-Right.is(TT_TemplateString))
+// the tag identifier and the template string.
+if (Keywords.IsJavaScriptIdentifier(Left) && Right.is(TT_TemplateString))
   return false;
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -910,9 +910,62 @@
   /// 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 ) const {
-return Tok.is(tok::identifier) &&
-   

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

2020-04-03 Thread Martin Probst via Phabricator via cfe-commits
mprobst added a comment.

Thanks for the feedback. Indeed, whitelisting the JS keywords is better, but we 
still needed a way to blacklist all C++ keywords then - Krasimir's suggestion 
with the #include did the trick, thanks.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77311/new/

https://reviews.llvm.org/D77311



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


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

2020-04-03 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 254741.
mprobst added a comment.

- fix formatting


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77311/new/

https://reviews.llvm.org/D77311

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

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -386,13 +386,6 @@
"return (x);\n");
 }
 
-TEST_F(FormatTestJS, CppKeywords) {
-  // Make sure we don't mess stuff up because of C++ keywords.
-  verifyFormat("return operator && (aa);");
-  // .. or QT ones.
-  verifyFormat("slots: Slot[];");
-}
-
 TEST_F(FormatTestJS, ES6DestructuringAssignment) {
   verifyFormat("var [a, b, c] = [1, 2, 3];");
   verifyFormat("const [a, b, c] = [1, 2, 3];");
@@ -2366,6 +2359,61 @@
   verifyFormat("return !!x;\n");
 }
 
+TEST_F(FormatTestJS, CppKeywords) {
+  // Make sure we don't mess stuff up because of C++ keywords.
+  verifyFormat("return operator && (aa);");
+  // .. or QT ones.
+  verifyFormat("const slots: Slot[];");
+  // use the "!" assertion operator to validate that clang-format understands
+  // these C++ keywords aren't keywords in JS/TS.
+  verifyFormat("auto!;");
+  verifyFormat("char!;");
+  verifyFormat("concept!;");
+  verifyFormat("double!;");
+  verifyFormat("extern!;");
+  verifyFormat("float!;");
+  verifyFormat("inline!;");
+  verifyFormat("int!;");
+  verifyFormat("long!;");
+  verifyFormat("register!;");
+  verifyFormat("restrict!;");
+  verifyFormat("sizeof!;");
+  verifyFormat("struct!;");
+  verifyFormat("typedef!;");
+  verifyFormat("union!;");
+  verifyFormat("unsigned!;");
+  verifyFormat("volatile!;");
+  verifyFormat("_Alignas!;");
+  verifyFormat("_Alignof!;");
+  verifyFormat("_Atomic!;");
+  verifyFormat("_Bool!;");
+  verifyFormat("_Complex!;");
+  verifyFormat("_Generic!;");
+  verifyFormat("_Imaginary!;");
+  verifyFormat("_Noreturn!;");
+  verifyFormat("_Static_assert!;");
+  verifyFormat("_Thread_local!;");
+  verifyFormat("__func__!;");
+  verifyFormat("__objc_yes!;");
+  verifyFormat("__objc_no!;");
+  verifyFormat("asm!;");
+  verifyFormat("bool!;");
+  verifyFormat("const_cast!;");
+  verifyFormat("dynamic_cast!;");
+  verifyFormat("explicit!;");
+  verifyFormat("friend!;");
+  verifyFormat("mutable!;");
+  verifyFormat("operator!;");
+  verifyFormat("reinterpret_cast!;");
+  verifyFormat("static_cast!;");
+  verifyFormat("template!;");
+  verifyFormat("typename!;");
+  verifyFormat("typeid!;");
+  verifyFormat("using!;");
+  verifyFormat("virtual!;");
+  verifyFormat("wchar_t!;");
+}
+
 TEST_F(FormatTestJS, NullPropagatingOperator) {
   verifyFormat("let x = foo?.bar?.baz();\n");
   verifyFormat("let x = foo?.(foo);\n");
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -1522,9 +1522,9 @@
 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 @@
 (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(Left) &&
-Right.is(TT_TemplateString))
+// the tag identifier and the template string.
+if (Keywords.IsJavaScriptIdentifier(Left) && Right.is(TT_TemplateString))
   return false;
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -910,9 +910,62 @@
   /// 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 ) const {
-return Tok.is(tok::identifier) &&
-   JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==

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

2020-04-02 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added subscribers: cfe-commits, jfb.
Herald added a project: clang.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D77311

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

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2366,6 +2366,58 @@
   verifyFormat("return !!x;\n");
 }
 
+TEST_F(FormatTestJS, CppKeywordsInJavaScript) {
+  // use the "!" assertion operator to validate that clang-format understands
+  // these C++ keywords aren't keywords in JS/TS.
+  verifyFormat("auto!;");
+  verifyFormat("char!;");
+  verifyFormat("concept!;");
+  verifyFormat("double!;");
+  verifyFormat("extern!;");
+  verifyFormat("float!;");
+  verifyFormat("inline!;");
+  verifyFormat("int!;");
+  verifyFormat("long!;");
+  verifyFormat("register!;");
+  verifyFormat("restrict!;");
+  verifyFormat("sizeof!;");
+  verifyFormat("static!;");
+  verifyFormat("struct!;");
+  verifyFormat("typedef!;");
+  verifyFormat("union!;");
+  verifyFormat("unsigned!;");
+  verifyFormat("volatile!;");
+  verifyFormat("_Alignas!;");
+  verifyFormat("_Alignof!;");
+  verifyFormat("_Atomic!;");
+  verifyFormat("_Bool!;");
+  verifyFormat("_Complex!;");
+  verifyFormat("_Generic!;");
+  verifyFormat("_Imaginary!;");
+  verifyFormat("_Noreturn!;");
+  verifyFormat("_Static_assert!;");
+  verifyFormat("_Thread_local!;");
+  verifyFormat("__func__!;");
+  verifyFormat("__objc_yes!;");
+  verifyFormat("__objc_no!;");
+  verifyFormat("asm!;");
+  verifyFormat("bool!;");
+  verifyFormat("const_cast!;");
+  verifyFormat("dynamic_cast!;");
+  verifyFormat("explicit!;");
+  verifyFormat("friend!;");
+  verifyFormat("mutable!;");
+  verifyFormat("operator!;");
+  verifyFormat("reinterpret_cast!;");
+  verifyFormat("static_cast!;");
+  verifyFormat("template!;");
+  verifyFormat("typename!;");
+  verifyFormat("typeid!;");
+  verifyFormat("using!;");
+  verifyFormat("virtual!;");
+  verifyFormat("wchar_t!;");
+}
+
 TEST_F(FormatTestJS, NullPropagatingOperator) {
   verifyFormat("let x = foo?.bar?.baz();\n");
   verifyFormat("let x = foo?.(foo);\n");
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -1522,9 +1522,9 @@
 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 @@
 (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(Left) &&
-Right.is(TT_TemplateString))
+// the tag identifier and the template string.
+if (Keywords.IsJavaScriptIdentifier(Left) && Right.is(TT_TemplateString))
   return false;
 if (Right.is(tok::star) &&
 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -910,9 +910,65 @@
   /// 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 ) const {
-return Tok.is(tok::identifier) &&
-   JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==
-   JsExtraKeywords.end();
+switch (Tok.Tok.getKind()) {
+case tok::kw_auto:
+case tok::kw_char:
+case tok::kw_concept:
+case tok::kw_double:
+case tok::kw_extern:
+case tok::kw_float:
+case tok::kw_inline:
+case tok::kw_int:
+case 

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

2020-02-03 Thread Martin Probst via Phabricator via cfe-commits
mprobst closed this revision.
mprobst marked an inline comment as done.
mprobst added a comment.

This has landed as https://reviews.llvm.org/rGa324fcf1ae6 (not sure why this 
hasn't closed automatically).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73354/new/

https://reviews.llvm.org/D73354



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


[PATCH] D73768: clang-format: [JS] document InsertTrailingCommas.

2020-02-02 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGdc04c54fc1f6: clang-format: [JS] document 
InsertTrailingCommas. (authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73768/new/

https://reviews.llvm.org/D73768

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


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -175,6 +175,11 @@
   }
 }
 
+- 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
 
 
Index: clang/docs/ClangFormatStyleOptions.rst
===
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -717,6 +717,26 @@
 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.


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -175,6 +175,11 @@
   }
 }
 
+- 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
 
 
Index: clang/docs/ClangFormatStyleOptions.rst
===
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -717,6 +717,26 @@
 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.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D73768: clang-format: [JS] document InsertTrailingCommas.

2020-01-31 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: MyDeveloperDay.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

In release notes and the regular docs.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D73768

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


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -172,6 +172,11 @@
   }
 }
 
+- 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
 
 
Index: clang/docs/ClangFormatStyleOptions.rst
===
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -717,6 +717,26 @@
 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.


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -172,6 +172,11 @@
   }
 }
 
+- 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
 
 
Index: clang/docs/ClangFormatStyleOptions.rst
===
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -717,6 +717,26 @@
 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.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2020-01-29 Thread Martin Probst via Phabricator via cfe-commits
mprobst marked 4 inline comments as done.
mprobst added inline comments.



Comment at: clang/include/clang/Format/Format.h:42
+  Unsuitable,
+  BinBackTrailingCommaConflict
+};

sammccall wrote:
> Back->Pack?
That's what you get when you fix my auto-complete: consistent misspelling.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73354/new/

https://reviews.llvm.org/D73354



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


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

2020-01-29 Thread Martin Probst via Phabricator via cfe-commits
mprobst marked 2 inline comments as done.
mprobst added inline comments.



Comment at: clang/lib/Format/Format.cpp:2531
+});
+
   auto Env =

MyDeveloperDay wrote:
> Ok, this comment is more a discussion point rather than a review comment. Was 
> there a reason you needed to put the TrailingCommaInserter pass after the 
> Formatter pass? (maybe you needed the Tokens annotated?)
> 
> From my understanding of some of the other conversations, it seemed the 
> reason for ignoring the Column limit was because the "," insertion came after 
> it had been formatted (is that correct?)
> 
> If there was a good reason that's also fine, I was just interested to learn 
> if there was some part of the Formatter that perhaps needs to be pulled out 
> into its own separate pass.
> 
> 
The problem with inserting the comma during formatting is that it'd need to be 
inserted during the state exploration as part of Dijkstra's implemented in 
clang-format. I've considered that, but it'd be complex (if we make formatting 
decision X, we now add a token, which might invalidate the formatting 
decision). Keeping it as a separate pass has drawbacks, such as potentially not 
ending up with perfect formatting, thus the backing off to insert over 
ColumnLimit, but seems overall simpler.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73354/new/

https://reviews.llvm.org/D73354



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


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

2020-01-28 Thread Martin Probst via Phabricator via cfe-commits
mprobst marked 6 inline comments as done.
mprobst added a comment.

PTAL.




Comment at: clang/include/clang/Format/Format.h:552
+/// Insert trailing commas in container literals that were wrapped over
+/// multiple lines.
+TCS_Wrapped,

mprobst wrote:
> sammccall wrote:
> > Hadn't occurred to me that this will interact with bin-packing. That seems 
> > to increase the chances of going over the column limit :(
> Uh. Turns out we don't have a separate option for bin packing containers, 
> only for bin packing arguments and parameters.
> 
> Should we add that option to make this setting work?
> Should we have this setting imply bin packing containers (as opposed to 
> parameters) is disabled?
OK, so I added a bit of validation logic to reject bin packing arguments 
together with TSC_Wrapped. We can figure out in a next step whether we want to 
expose an option for bin packing containers, or whether we can just disable bin 
packing for those people who want trailing commas.



Comment at: clang/unittests/Format/FormatTestJS.cpp:1229
"  (param): param is {\n"
-   "a: SomeType\n"
+   "a: SomeType;\n"
"  } => 1)\n"

MyDeveloperDay wrote:
> mprobst wrote:
> > MyDeveloperDay wrote:
> > > is this correct?
> > Yes, type definitions should use `;`
> if you hadn't added this to the test would it have added a "," ?
More precisely:
you can  use either `;` or `,` to separate entries in object literal types. So 
using `;` is correct here, but c-f with this option would insert a `,`, which 
is correct as well. I've added a test.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73354/new/

https://reviews.llvm.org/D73354



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


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

2020-01-28 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 240873.
mprobst marked an inline comment as done.
mprobst added a comment.

- - only run comma insertion for JavaScript.
- review fixes
- Fix col limit
- test for comma insertion
- - validate options, reject bin packing + trailing commas


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73354/new/

https://reviews.llvm.org/D73354

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

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -878,6 +878,45 @@
"]);");
 }
 
+TEST_F(FormatTestJS, TrailingCommaInsertion) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
+  Style.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
+  // Insert comma in wrapped array.
+  verifyFormat("const x = [\n"
+   "  1,  //\n"
+   "  2,\n"
+   "];",
+   "const x = [\n"
+   "  1,  //\n"
+   "  2];",
+   Style);
+  // Insert comma in newly wrapped array.
+  Style.ColumnLimit = 30;
+  verifyFormat("const x = [\n"
+   "  a,\n"
+   "];",
+   "const x = [a];", Style);
+  // Do not insert trailing commas if they'd exceed the colum limit
+  verifyFormat("const x = [\n"
+   "  \n"
+   "];",
+   "const x = [];", Style);
+  // Object literals.
+  verifyFormat("const x = {\n"
+   "  a: a,\n"
+   "};",
+   "const x = {a: a};", Style);
+  verifyFormat("const x = {\n"
+   "  a: a\n"
+   "};",
+   "const x = {a: a};", Style);
+  // Object literal types.
+  verifyFormat("let x: {\n"
+   "  a: a,\n"
+   "};",
+   "let x: {a: a};", Style);
+}
+
 TEST_F(FormatTestJS, FunctionLiterals) {
   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
Index: clang/unittests/Format/FormatTest.cpp
===
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -13031,6 +13031,12 @@
"IndentWidth: 34",
),
 ParseError::Unsuitable);
+  FormatStyle BinPackedTCS = {};
+  BinPackedTCS.Language = FormatStyle::LK_JavaScript;
+  EXPECT_EQ(parseConfiguration("BinPackArguments: true\n"
+   "InsertTrailingCommas: Wrapped",
+   ),
+ParseError::BinBackTrailingCommaConflict);
   EXPECT_EQ(12u, Style.IndentWidth);
   CHECK_PARSE("IndentWidth: 56", IndentWidth, 56u);
   EXPECT_EQ(FormatStyle::LK_Cpp, Style.Language);
Index: clang/lib/Format/Format.cpp
===
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -157,6 +157,13 @@
   }
 };
 
+template <> struct ScalarEnumerationTraits {
+  static void enumeration(IO , FormatStyle::TrailingCommaStyle ) {
+IO.enumCase(Value, "None", FormatStyle::TCS_None);
+IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
+  }
+};
+
 template <> struct ScalarEnumerationTraits {
   static void enumeration(IO , FormatStyle::BinaryOperatorStyle ) {
 IO.enumCase(Value, "All", FormatStyle::BOS_All);
@@ -486,6 +493,7 @@
 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 @@
 return "Invalid argument";
   case ParseError::Unsuitable:
 return "Unsuitable";
+  case ParseError::BinBackTrailingCommaConflict:
+return "trailing comma insertion cannot be used with bin packing";
   }
   llvm_unreachable("unexpected parse error");
 }
@@ -788,6 +798,7 @@
   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 @@
 // taze:, triple 

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

2020-01-28 Thread Martin Probst via Phabricator via cfe-commits
mprobst marked 2 inline comments as done.
mprobst added inline comments.



Comment at: clang/lib/Format/TokenAnnotator.cpp:3165
+  }
+}
+

RKSimon wrote:
> @mprobst - this is breaking buildbots: 
> http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-android/builds/27196/steps/bootstrap%20clang/logs/stdio
> 
> Please can you remove the default case and add a suitable llvm_unreachable() 
> after the switch statement ?
Sorry for the breakage, and thanks to Jinsong Ji for fixing while I was OOO.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73335/new/

https://reviews.llvm.org/D73335



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


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

2020-01-28 Thread Martin Probst via Phabricator via cfe-commits
mprobst marked 3 inline comments as done.
mprobst added inline comments.



Comment at: clang/include/clang/Format/Format.h:552
+/// Insert trailing commas in container literals that were wrapped over
+/// multiple lines.
+TCS_Wrapped,

sammccall wrote:
> Hadn't occurred to me that this will interact with bin-packing. That seems to 
> increase the chances of going over the column limit :(
Uh. Turns out we don't have a separate option for bin packing containers, only 
for bin packing arguments and parameters.

Should we add that option to make this setting work?
Should we have this setting imply bin packing containers (as opposed to 
parameters) is disabled?



Comment at: clang/lib/Format/Format.cpp:956
 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
+GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
 GoogleStyle.MaxEmptyLinesToKeep = 3;

MyDeveloperDay wrote:
> Are you sure the right decision is to make this on by default for something 
> that's going to insert the comma? is this in google's javascript style guide?
> 
> I think this could cause clang-format to suddenly start adding lost of commas 
> (as we see  with the tests)
It matches the style guide: 
https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma

But it's indeed not entirely clear re bin packing, and certainly a good idea to 
split adding the option vs landing it.



Comment at: clang/lib/Format/Format.cpp:1477
 
+/// TrailingCommaInserter inserts trailing commas into container literals.
+/// E.g.:

MyDeveloperDay wrote:
> sammccall wrote:
> > Inlining this in format.cpp seems worse than having passes in their own 
> > files, but is the pattern so far. Ugh, up to you.
> Actually I think there is precedent to put TokenAnalyzers in their own class, 
> I don't think it should be in Format.cpp
Re inlining vs separate file, idk. On one hand, this file is on the large side, 
otoh these ~60 LOC don't carry their own weight in a separate file. Maybe in a 
follow up we should extract all passes into a separate file (maybe all passes 
except the actual indenter?).



Comment at: clang/lib/Format/Format.cpp:1482
+/// ];
+class TrailingCommaInserter : public TokenAnalyzer {
+public:

krasimir wrote:
> sammccall wrote:
> > Worth a comment (somewhere) about the fact that this never rewraps, in 
> > particular if the line is long, for simplicity.
> > 
> > Another policy that occurred to me: don't insert the comma if you're 
> > exactly at the line limit.
> +1 for "Another policy that occurred to me: don't insert the comma if you're 
> exactly at the line limit." (or //over// the column limit). Seems like that 
> would be enough to keep it idempotent.
Done re comment, and also done re policy, good idea.

I've also added a comment that this doesn't work together with bin packing.



Comment at: clang/lib/Format/Format.cpp:1511
+FormatToken *Matching = FormatTok->MatchingParen;
+if (!Matching || !FormatTok->Previous)
+  continue;

sammccall wrote:
> You're checking for the existence of a previous token, and below you use 
> getPreviousNonComment() without a null-check.
> 
> I think you want to either assume that the existence of a match means there's 
> a prev token (and remove the check here), or you want to verify in which case 
> I think you also need to guard against it being a comment (by checking Prev 
> below instead)
Good catch. I think the right fix is to check if there is a previous non 
comment token, as that's what I'm using below.



Comment at: clang/unittests/Format/FormatTestJS.cpp:343
"  for: 'for',\n"
-   "  x: 'x'\n"
+   "  x: 'x',\n"
"};",

sammccall wrote:
> AFAICT one-arg verifyFormat doesn't actually test this change - the new tests 
> with commas should pass both before/after this change. 
> So there's just one testcase, I think.
Ha, I just adjusted the test cases to my change, but forgot uploading the patch 
with the tests.

I've reverted all these changes (because I'm splitting flipping the default 
from this), but added an explicit test.



Comment at: clang/unittests/Format/FormatTestJS.cpp:1229
"  (param): param is {\n"
-   "a: SomeType\n"
+   "a: SomeType;\n"
"  } => 1)\n"

MyDeveloperDay wrote:
> is this correct?
Yes, type definitions should use `;`



Comment at: clang/unittests/Format/FormatTestJS.cpp:1701
   verifyFormat("type X = {\n"
-   "  y: number\n"
+   "  y: number;\n"
"};\n"

MyDeveloperDay wrote:
> is this correct?
Yes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  

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

2020-01-28 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 240847.
mprobst marked 16 inline comments as done.
mprobst added a comment.

- - only run comma insertion for JavaScript.
- review fixes
- Fix col limit
- test for comma insertion


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73354/new/

https://reviews.llvm.org/D73354

Files:
  clang/include/clang/Format/Format.h
  clang/lib/Format/Format.cpp
  clang/unittests/Format/FormatTestJS.cpp

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -878,6 +878,41 @@
"]);");
 }
 
+TEST_F(FormatTestJS, TrailingCommaInsertion) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
+  Style.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
+  // Insert comma in wrapped array.
+  verifyFormat("const x = [\n"
+   "  1,  //\n"
+   "  2,\n"
+   "];",
+   "const x = [\n"
+   "  1,  //\n"
+   "  2];",
+   Style);
+  // Insert comma in newly wrapped array.
+  Style.ColumnLimit = 30;
+  verifyFormat("const x = [\n"
+   "  a,\n"
+   "];",
+   "const x = [a];", Style);
+  // Do not insert trailing commas if they'd exceed the colum limit
+  verifyFormat("const x = [\n"
+   "  \n"
+   "];",
+   "const x = [];", Style);
+  // Object literals.
+  verifyFormat("const x = {\n"
+   "  a: a,\n"
+   "};",
+   "const x = {a: a};", Style);
+  verifyFormat("const x = {\n"
+   "  a: a\n"
+   "};",
+   "const x = {a: a};", Style);
+
+}
+
 TEST_F(FormatTestJS, FunctionLiterals) {
   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
Index: clang/lib/Format/Format.cpp
===
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -157,6 +157,13 @@
   }
 };
 
+template <> struct ScalarEnumerationTraits {
+  static void enumeration(IO , FormatStyle::TrailingCommaStyle ) {
+IO.enumCase(Value, "None", FormatStyle::TCS_None);
+IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
+  }
+};
+
 template <> struct ScalarEnumerationTraits {
   static void enumeration(IO , FormatStyle::BinaryOperatorStyle ) {
 IO.enumCase(Value, "All", FormatStyle::BOS_All);
@@ -486,6 +493,7 @@
 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);
@@ -788,6 +796,7 @@
   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 +955,9 @@
 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
 // commonly followed by overlong URLs.
 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
+// TODO: enable once decided, in particular re disabling bin packing.
+// https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
+// GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
 GoogleStyle.MaxEmptyLinesToKeep = 3;
 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
 GoogleStyle.SpacesInContainerLiterals = false;
@@ -1466,6 +1478,75 @@
   FormattingAttemptStatus *Status;
 };
 
+/// TrailingCommaInserter inserts trailing commas into container literals.
+/// E.g.:
+/// const x = [
+///   1,
+/// ];
+/// TrailingCommaInserter runs after formatting. To avoid causing a required
+/// reformatting (and thus reflow), it never inserts a comma that'd exceed the
+/// ColumnLimit.
+///
+/// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
+/// is conceptually incompatible with bin packing.
+class TrailingCommaInserter : public TokenAnalyzer {
+public:
+  TrailingCommaInserter(const Environment , const FormatStyle )
+  : TokenAnalyzer(Env, Style) {}
+
+  std::pair
+  analyze(TokenAnnotator ,
+  SmallVectorImpl ,
+  FormatTokenLexer ) override {
+

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

2020-01-27 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG02656f29abda: clang-format: [JS] options for arrow 
functions. (authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D73335?vs=240202=240575#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73335/new/

https://reviews.llvm.org/D73335

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

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -459,8 +459,9 @@
   // 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 @@
 
   // 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, 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 @@
"  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 @@
"// break\n"
");");
   verifyFormat("const f = (x: string|null): string|null => {\n"
+   "  y;\n"
"  return x;\n"
"}\n");
 }
 
+TEST_F(FormatTestJS, ArrowFunctionStyle) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
+  verifyFormat("const arr = () => { x; };", Style);
+  verifyFormat("const arrInlineAll = () => {};", Style);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_None;
+  verifyFormat("const arr = () => {\n"
+   "  x;\n"
+   "};",
+   Style);
+  verifyFormat("const arrInlineNone = () => {\n"
+   "};",
+   Style);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
+  verifyFormat("const arr = () => {\n"
+   "  x;\n"
+   "};",
+   Style);
+  verifyFormat("const arrInlineEmpty = () => {};",
+   Style);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Inline;
+  verifyFormat("const arr = () => {\n"
+   "  x;\n"
+   "};",
+   Style);
+  verifyFormat("foo(() => {});",
+   Style);
+  verifyFormat("const arrInlineInline = () => {};", Style);
+}
+
 TEST_F(FormatTestJS, ReturnStatements) {
   verifyFormat("function() {\n"
"  return [hello, world];\n"
@@ -1711,10 +1746,12 @@
 TEST_F(FormatTestJS, RemoveEmptyLinesInArrowFunctions) {
   verifyFormat("x = () => {\n"
"  foo();\n"
+   "  bar();\n"
"};\n",
"x = () => {\n"
"\n"
"  foo();\n"
+   "  bar();\n"
"\n"
"};\n");
 }
@@ -1791,6 +1828,10 @@
"];");
   verifyFormat("export default [];");
   verifyFormat("export default () => {};");
+  verifyFormat("export default () => {\n"
+   "  x;\n"
+   "  x;\n"
+   "};");
   verifyFormat("export interface Foo {\n"
"  foo: number;\n"
"}\n"
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3144,6 +3144,26 @@
   // 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) &&
+   

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

2020-01-24 Thread Martin Probst via Phabricator via cfe-commits
mprobst added a comment.

> If that's the case, consider adding the option to the style in a follow-up 
> patch:
> 
>   GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
>
> 
> that would have an advantage of making clear which test case diffs are result 
> of the implementation and which are result of the style flip.

Done!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73335/new/

https://reviews.llvm.org/D73335



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


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

2020-01-24 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 240202.
mprobst added a comment.

- Disable arrow functions on single lines by default.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73335/new/

https://reviews.llvm.org/D73335

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

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -459,8 +459,9 @@
   // 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 @@
 
   // 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, 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 @@
"  return a;\n"
"};");
   verifyFormat("var x = (a: type): {some: type} => {\n"
+   "  y;\n"
"  return a;\n"
"};");
   verifyFormat("var x = (a) => a;");
@@ -1147,10 +1151,36 @@
"// break\n"
");");
   verifyFormat("const f = (x: string|null): string|null => {\n"
+   "  y;\n"
"  return x;\n"
"}\n");
 }
 
+TEST_F(FormatTestJS, ArrowFunctionStyle) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
+  verifyFormat("const arr = () => { x; };", Style);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_None;
+  verifyFormat("const arr = () => {\n"
+   "  x;\n"
+   "};",
+   Style);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
+  verifyFormat("const arr = () => {\n"
+   "  x;\n"
+   "};",
+   Style);
+  verifyFormat("const arr = () => {};",
+   Style);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Inline;
+  verifyFormat("const arr = () => {\n"
+   "  x;\n"
+   "};",
+   Style);
+  verifyFormat("foo(() => {});",
+   Style);
+}
+
 TEST_F(FormatTestJS, ReturnStatements) {
   verifyFormat("function() {\n"
"  return [hello, world];\n"
@@ -1711,10 +1741,12 @@
 TEST_F(FormatTestJS, RemoveEmptyLinesInArrowFunctions) {
   verifyFormat("x = () => {\n"
"  foo();\n"
+   "  bar();\n"
"};\n",
"x = () => {\n"
"\n"
"  foo();\n"
+   "  bar();\n"
"\n"
"};\n");
 }
@@ -1790,7 +1822,10 @@
"  bb\n"
"];");
   verifyFormat("export default [];");
-  verifyFormat("export default () => {};");
+  verifyFormat("export default () => {\n"
+   "  x;\n"
+   "  x;\n"
+   "};");
   verifyFormat("export interface Foo {\n"
"  foo: number;\n"
"}\n"
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3142,6 +3142,23 @@
   // 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:
+return (Left.NestingLevel == 0 && Line.Level == 0);
+  default:
+break;
+  }
+}
+
 if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&
 !Left.Children.empty())
   // Support AllowShortFunctionsOnASingleLine for JavaScript.
Index: clang/lib/Format/Format.cpp
===
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -939,6 +939,8 @@
 GoogleStyle.AlignAfterOpenBracket = 

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

2020-01-24 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 240194.
mprobst added a comment.

- - only run comma insertion for JavaScript.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73354/new/

https://reviews.llvm.org/D73354

Files:
  clang/include/clang/Format/Format.h
  clang/lib/Format/Format.cpp
  clang/unittests/Format/FormatTestJS.cpp

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -340,7 +340,7 @@
"}\n");
   verifyFormat("const Axis = {\n"
"  for: 'for',\n"
-   "  x: 'x'\n"
+   "  x: 'x',\n"
"};",
"const Axis = {for: 'for', x:   'x'};");
 }
@@ -405,18 +405,18 @@
   verifyFormat("var x = {\n"
"  y: function(a) {\n"
"return a;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("return {\n"
"  link: function() {\n"
"f();  //\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("return {\n"
"  a: a,\n"
"  link: function() {\n"
"f();  //\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("return {\n"
"  a: a,\n"
@@ -425,7 +425,7 @@
"  },\n"
"  link: function() {\n"
"f();  //\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var stuff = {\n"
"  // comment for update\n"
@@ -433,23 +433,27 @@
"  // comment for modules\n"
"  modules: false,\n"
"  // comment for tasks\n"
-   "  tasks: false\n"
+   "  tasks: false,\n"
"};");
   verifyFormat("return {\n"
"  'finish':\n"
"  //\n"
-   "  a\n"
+   "  a,\n"
"};");
   verifyFormat("var obj = {\n"
"  fo: function(x) {\n"
"return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
-   "  }\n"
+   "  },\n"
"};");
   // Simple object literal, as opposed to enum style below.
   verifyFormat("var obj = {a: 123};");
   // Enum style top level assignment.
-  verifyFormat("X = {\n  a: 123\n};");
-  verifyFormat("X.Y = {\n  a: 123\n};");
+  verifyFormat("X = {\n"
+   "  a: 123,\n"
+   "};");
+  verifyFormat("X.Y = {\n"
+   "  a: 123,\n"
+   "};");
   // But only on the top level, otherwise its a plain object literal assignment.
   verifyFormat("function x() {\n"
"  y = {z: 1};\n"
@@ -460,7 +464,7 @@
   verifyFormat("var x = {\n"
"  y: (a) => {\n"
"return a;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var x = {y: (a) => a};");
 
@@ -468,12 +472,12 @@
   verifyFormat("var x = {\n"
"  y(a: string): number {\n"
"return a;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var x = {\n"
"  y(a: string) {\n"
"return a;\n"
-   "  }\n"
+   "  },\n"
"};");
 
   // Computed keys.
@@ -514,19 +518,19 @@
"  value: 'test',\n"
"  get value() {  // getter\n"
"return this.value;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var o = {\n"
"  value: 'test',\n"
"  set value(val) {  // setter\n"
"this.value = val;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var o = {\n"
"  value: 'test',\n"
"  someMethod(val) {  // method\n"
"doSomething(this.value + val);\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var o = {\n"
"  someMethod(val) {  // method\n"
@@ -534,7 +538,7 @@
"  },\n"
"  someOtherMethod(val) {  // method\n"
"doSomething(this.value + val);\n"
-   "  }\n"
+   "  },\n"
"};");
 }
 
@@ -563,7 +567,7 @@
 
   verifyFormat("var object_literal_with_long_name = {\n"
"  a: 'aa',\n"
-   "  b: 'bb'\n"
+   "  b: 'bb',\n"
"};");
 
   verifyFormat("f({a: 1, b: 2, c: 3});",
@@ -730,7 +734,7 @@
   verifyFormat("var x = {\n"
"  a: function*() {\n"
"//\n"
-   "  }\n"
+   " 

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

2020-01-24 Thread Martin Probst via Phabricator via cfe-commits
mprobst added a comment.

This is required by JavaScript style, but this change as is optimistically runs 
the tool for any language. I think that's probably not what we want here 
initially, just throwing it out there. WDYT?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73354/new/

https://reviews.llvm.org/D73354



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


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

2020-01-24 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added reviewers: krasimir, MyDeveloperDay.
Herald added a project: clang.

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).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D73354

Files:
  clang/include/clang/Format/Format.h
  clang/lib/Format/Format.cpp
  clang/unittests/Format/FormatTestJS.cpp

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -340,7 +340,7 @@
"}\n");
   verifyFormat("const Axis = {\n"
"  for: 'for',\n"
-   "  x: 'x'\n"
+   "  x: 'x',\n"
"};",
"const Axis = {for: 'for', x:   'x'};");
 }
@@ -405,18 +405,18 @@
   verifyFormat("var x = {\n"
"  y: function(a) {\n"
"return a;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("return {\n"
"  link: function() {\n"
"f();  //\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("return {\n"
"  a: a,\n"
"  link: function() {\n"
"f();  //\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("return {\n"
"  a: a,\n"
@@ -425,7 +425,7 @@
"  },\n"
"  link: function() {\n"
"f();  //\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var stuff = {\n"
"  // comment for update\n"
@@ -433,23 +433,27 @@
"  // comment for modules\n"
"  modules: false,\n"
"  // comment for tasks\n"
-   "  tasks: false\n"
+   "  tasks: false,\n"
"};");
   verifyFormat("return {\n"
"  'finish':\n"
"  //\n"
-   "  a\n"
+   "  a,\n"
"};");
   verifyFormat("var obj = {\n"
"  fo: function(x) {\n"
"return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
-   "  }\n"
+   "  },\n"
"};");
   // Simple object literal, as opposed to enum style below.
   verifyFormat("var obj = {a: 123};");
   // Enum style top level assignment.
-  verifyFormat("X = {\n  a: 123\n};");
-  verifyFormat("X.Y = {\n  a: 123\n};");
+  verifyFormat("X = {\n"
+   "  a: 123,\n"
+   "};");
+  verifyFormat("X.Y = {\n"
+   "  a: 123,\n"
+   "};");
   // But only on the top level, otherwise its a plain object literal assignment.
   verifyFormat("function x() {\n"
"  y = {z: 1};\n"
@@ -460,7 +464,7 @@
   verifyFormat("var x = {\n"
"  y: (a) => {\n"
"return a;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var x = {y: (a) => a};");
 
@@ -468,12 +472,12 @@
   verifyFormat("var x = {\n"
"  y(a: string): number {\n"
"return a;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var x = {\n"
"  y(a: string) {\n"
"return a;\n"
-   "  }\n"
+   "  },\n"
"};");
 
   // Computed keys.
@@ -514,19 +518,19 @@
"  value: 'test',\n"
"  get value() {  // getter\n"
"return this.value;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var o = {\n"
"  value: 'test',\n"
"  set value(val) {  // setter\n"
"this.value = val;\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var o = {\n"
"  value: 'test',\n"
"  someMethod(val) {  // method\n"
"doSomething(this.value + val);\n"
-   "  }\n"
+   "  },\n"
"};");
   verifyFormat("var o = {\n"
"  someMethod(val) {  // method\n"
@@ -534,7 +538,7 @@
"  },\n"
"  someOtherMethod(val) {  // method\n"
"doSomething(this.value + val);\n"
-   "  }\n"
+   "  

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

2020-01-24 Thread Martin Probst via Phabricator via cfe-commits
mprobst added a comment.

FYI I've started a conversation on whether `SLS_All` should be the default 
Google style. But the option I think is useful in either case.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73335/new/

https://reviews.llvm.org/D73335



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


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

2020-01-24 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a project: clang.

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

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

This change implements support for the `AllowShortLambdasOnASingleLine`
style options, and also sets the default Google style to `SLS_All`, i.e.
to indent arrow function bodies that have one or fewer statements on a
single line:

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

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D73335

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

Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -458,9 +458,7 @@
 
   // Arrow functions in object literals.
   verifyFormat("var x = {\n"
-   "  y: (a) => {\n"
-   "return a;\n"
-   "  }\n"
+   "  y: (a) => { return a; },\n"
"};");
   verifyFormat("var x = {y: (a) => a};");
 
@@ -485,9 +483,7 @@
"};");
 
   // Object literals can leave out labels.
-  verifyFormat("f({a}, () => {\n"
-   "  g();  //\n"
-   "});");
+  verifyFormat("f({a}, () => { g(); });");
 
   // Keys can be quoted.
   verifyFormat("var x = {\n"
@@ -,9 +1107,7 @@
 }
 
 TEST_F(FormatTestJS, ArrowFunctions) {
-  verifyFormat("var x = (a) => {\n"
-   "  return a;\n"
-   "};");
+  verifyFormat("var x = (a) => { return a; };\n");
   verifyFormat("var x = (a) => {\n"
"  function y() {\n"
"return 42;\n"
@@ -1121,6 +1115,7 @@
"  return a;\n"
"};");
   verifyFormat("var x = (a: type): {some: type} => {\n"
+   "  y;\n"
"  return a;\n"
"};");
   verifyFormat("var x = (a) => a;");
@@ -1147,10 +1142,36 @@
"// break\n"
");");
   verifyFormat("const f = (x: string|null): string|null => {\n"
+   "  y;\n"
"  return x;\n"
"}\n");
 }
 
+TEST_F(FormatTestJS, ArrowFunctionStyle) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
+  verifyFormat("const arr = () => { x; };", Style);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_None;
+  verifyFormat("const arr = () => {\n"
+   "  x;\n"
+   "};",
+   Style);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
+  verifyFormat("const arr = () => {\n"
+   "  x;\n"
+   "};",
+   Style);
+  verifyFormat("const arr = () => {};",
+   Style);
+  Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Inline;
+  verifyFormat("const arr = () => {\n"
+   "  x;\n"
+   "};",
+   Style);
+  verifyFormat("foo(() => {});",
+   Style);
+}
+
 TEST_F(FormatTestJS, ReturnStatements) {
   verifyFormat("function() {\n"
"  return [hello, world];\n"
@@ -1711,10 +1732,12 @@
 TEST_F(FormatTestJS, RemoveEmptyLinesInArrowFunctions) {
   verifyFormat("x = () => {\n"
"  foo();\n"
+   "  bar();\n"
"};\n",
"x = () => {\n"
"\n"
"  foo();\n"
+   "  bar();\n"
"\n"
"};\n");
 }
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3142,6 +3142,23 @@
   // 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:
+return (Left.NestingLevel == 0 && Line.Level == 0);
+  default:
+break;
+  }
+}
+
 if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&
 !Left.Children.empty())
   // Support AllowShortFunctionsOnASingleLine for JavaScript.
Index: clang/lib/Format/Format.cpp
===
--- clang/lib/Format/Format.cpp
+++ 

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

2020-01-20 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG4c9d6914453d: clang-format: [JS] fix `??` opreator wrapping. 
(authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73026/new/

https://reviews.llvm.org/D73026

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2294,6 +2294,11 @@
 
 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) {
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -120,8 +120,11 @@
   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.


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2294,6 +2294,11 @@
 
 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) {
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -120,8 +120,11 @@
   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.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2020-01-20 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a project: clang.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D73026

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2294,6 +2294,11 @@
 
 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) {
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -120,8 +120,11 @@
   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.


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2294,6 +2294,11 @@
 
 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) {
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -120,8 +120,11 @@
   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.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2020-01-17 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG9835cf159014: clang-format: [JS] pragmas for tslint, tsc. 
(authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72907/new/

https://reviews.llvm.org/D72907

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2168,6 +2168,38 @@
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'\";");
Index: clang/lib/Format/Format.cpp
===
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -939,9 +939,9 @@
 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;


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2168,6 +2168,38 @@
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"
+

[PATCH] D72911: clang-format: fix spacing in `operator const char*()`

2020-01-17 Thread Martin Probst via Phabricator via cfe-commits
mprobst accepted this revision.
mprobst added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/lib/Format/TokenAnnotator.cpp:2717
+//   operator Foo*()
+// dependant on PointerAlignment style.
+

typo dependent



Comment at: clang/lib/Format/TokenAnnotator.cpp:2722
+FormatToken *Before = Left.getPreviousNonComment();
+while (Before && Before->isOneOf(tok::kw_const, tok::kw_volatile)) {
+  Before = Before->getPreviousNonComment();

how many const and volatile may be there, and is their order fixed?

We also have the `endsSequence` helper on FormatToken that might express the 
concept better (`Left.endsSequence(tok::kw_const, tok::kw_volatile) || ...`). 
YMMV, with the tokens being optional that might lead to too many alternates to 
check for.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72911/new/

https://reviews.llvm.org/D72911



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


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

2020-01-17 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
mprobst added a project: clang.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D72907

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2168,6 +2168,38 @@
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'\";");
Index: clang/lib/Format/Format.cpp
===
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -939,9 +939,9 @@
 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;


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2168,6 +2168,38 @@
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. 

[PATCH] D72827: clang-format: [JS] Handle keyword-named methods.

2020-01-17 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG0734fb21ed5e: clang-format: [JS] Handle more keyword-named 
methods. (authored by mprobst).

Changed prior to commit:
  https://reviews.llvm.org/D72827?vs=238442=238713#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72827/new/

https://reviews.llvm.org/D72827

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -358,6 +358,22 @@
   "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) {
Index: clang/lib/Format/UnwrappedLineParser.cpp
===
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ clang/lib/Format/UnwrappedLineParser.cpp
@@ -1011,13 +1011,22 @@
   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 @@
 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 @@
   // 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();


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -358,6 +358,22 @@
   "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) {
Index: clang/lib/Format/UnwrappedLineParser.cpp
===
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ clang/lib/Format/UnwrappedLineParser.cpp
@@ -1011,13 +1011,22 @@
   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 @@
 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 @@
   // element continues.
   break;
 case tok::kw_try:
+  if (Style.Language == FormatStyle::LK_JavaScript &&
+  Line->MustBeDeclaration) {
+// 

[PATCH] D72827: clang-format: [JS] Handle keyword-named methods.

2020-01-17 Thread Martin Probst via Phabricator via cfe-commits
mprobst added a comment.

I've added tests and a fix for try/catch and if/else.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72827/new/

https://reviews.llvm.org/D72827



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


[PATCH] D72827: clang-format: [JS] Handle keyword-named methods.

2020-01-17 Thread Martin Probst via Phabricator via cfe-commits
mprobst added a comment.

In D72827#1823895 , @krasimir wrote:

> How about `if` and `try`? Is there a list somewhere for all such valid 
> identifiers?


This is a bit annoying - generally speaking, we should parse all keywords in 
declaration locations as simple names. However `UnwrappedLineParser` isn't 
really structured to support that, nor is it precise enough to reliably detect 
these situations :-/ So I think the best we can do is incrementally detect 
these issues and fix as they come up.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72827/new/

https://reviews.llvm.org/D72827



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


[PATCH] D72827: clang-format: [JS] Handle keyword-named methods.

2020-01-16 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a project: clang.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D72827

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -343,6 +343,14 @@
"  x: 'x'\n"
"};",
"const Axis = {for: 'for', x:   'x'};");
+  verifyFormat("class KeywordNamedMethods {\n"
+   "  do() {\n"
+   "  }\n"
+   "  for() {\n"
+   "  }\n"
+   "  while() {\n"
+   "  }\n"
+   "}\n");
 }
 
 TEST_F(FormatTestJS, ReservedWordsMethods) {
Index: clang/lib/Format/UnwrappedLineParser.cpp
===
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ clang/lib/Format/UnwrappedLineParser.cpp
@@ -1015,9 +1015,15 @@
 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:


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -343,6 +343,14 @@
"  x: 'x'\n"
"};",
"const Axis = {for: 'for', x:   'x'};");
+  verifyFormat("class KeywordNamedMethods {\n"
+   "  do() {\n"
+   "  }\n"
+   "  for() {\n"
+   "  }\n"
+   "  while() {\n"
+   "  }\n"
+   "}\n");
 }
 
 TEST_F(FormatTestJS, ReservedWordsMethods) {
Index: clang/lib/Format/UnwrappedLineParser.cpp
===
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ clang/lib/Format/UnwrappedLineParser.cpp
@@ -1015,9 +1015,15 @@
 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:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2020-01-16 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG736a3802124b: clang-format: [JS] tests for async wrapping. 
(authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70377/new/

https://reviews.llvm.org/D70377

Files:
  clang/unittests/Format/FormatTestJS.cpp


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -737,6 +737,22 @@
"   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"
"}");


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -737,6 +737,22 @@
"   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


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

2019-11-18 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70377

Files:
  clang/unittests/Format/FormatTestJS.cpp


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -737,6 +737,22 @@
"   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"
"}");


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -737,6 +737,22 @@
"   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


[PATCH] D69971: clang-format: [JS] support null operators.

2019-11-11 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa7638d384983: clang-format: [JS] support null operators. 
(authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69971/new/

https://reviews.llvm.org/D69971

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -,6 +,16 @@
   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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -100,6 +100,10 @@
 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 @@
   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;
   }
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -60,6 +60,8 @@
   TYPE(JsExponentiationEqual)  
\
   TYPE(JsFatArrow) 
\
   TYPE(JsNonNullAssertion) 
\
+  TYPE(JsNullishCoalescingOperator)
\
+  TYPE(JsNullPropagatingOperator)  
\
   TYPE(JsPrivateIdentifier)
\
   TYPE(JsTypeColon)
\
   TYPE(JsTypeOperator) 
\


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -,6 +,16 @@
   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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -100,6 +100,10 @@
 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 @@
   Tokens.back()->Tok.setKind(tok::starequal);
   return;
 }
+if 

[PATCH] D69972: clang-format: [JS] test declared fields.

2019-11-11 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG6bcd8d4a18fc: clang-format: [JS] test declared fields. 
(authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69972/new/

https://reviews.llvm.org/D69972

Files:
  clang/unittests/Format/FormatTestJS.cpp


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2369,5 +2369,12 @@
"  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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2369,5 +2369,12 @@
"  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


[PATCH] D69971: clang-format: [JS] support null operators.

2019-11-08 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 228495.
mprobst added a comment.

Add tests for .?(foo) and .?[foo].


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69971/new/

https://reviews.llvm.org/D69971

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -,6 +,16 @@
   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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -100,6 +100,10 @@
 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 @@
   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;
   }
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -60,6 +60,8 @@
   TYPE(JsExponentiationEqual)  
\
   TYPE(JsFatArrow) 
\
   TYPE(JsNonNullAssertion) 
\
+  TYPE(JsNullishCoalescingOperator)
\
+  TYPE(JsNullPropagatingOperator)  
\
   TYPE(JsPrivateIdentifier)
\
   TYPE(JsTypeColon)
\
   TYPE(JsTypeOperator) 
\


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -,6 +,16 @@
   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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -100,6 +100,10 @@
 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 @@
   Tokens.back()->Tok.setKind(tok::starequal);
   return;
 }
+if (tryMergeTokens(JSNullishOperator, TT_JsNullishCoalescingOperator))
+  

[PATCH] D69972: clang-format: [JS] test declared fields.

2019-11-07 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a project: clang.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D69972

Files:
  clang/unittests/Format/FormatTestJS.cpp


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2359,5 +2359,12 @@
"  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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -2359,5 +2359,12 @@
"  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


[PATCH] D69971: clang-format: [JS] support null operators.

2019-11-07 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a project: clang.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D69971

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -,6 +,14 @@
   verifyFormat("return !!x;\n");
 }
 
+TEST_F(FormatTestJS, NullPropagatingOperator) {
+  verifyFormat("let x = foo?.bar?.baz();\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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -100,6 +100,10 @@
 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 @@
   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;
   }
Index: clang/lib/Format/FormatToken.h
===
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -60,6 +60,8 @@
   TYPE(JsExponentiationEqual)  
\
   TYPE(JsFatArrow) 
\
   TYPE(JsNonNullAssertion) 
\
+  TYPE(JsNullishCoalescingOperator)
\
+  TYPE(JsNullPropagatingOperator)  
\
   TYPE(JsPrivateIdentifier)
\
   TYPE(JsTypeColon)
\
   TYPE(JsTypeOperator) 
\


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -,6 +,14 @@
   verifyFormat("return !!x;\n");
 }
 
+TEST_F(FormatTestJS, NullPropagatingOperator) {
+  verifyFormat("let x = foo?.bar?.baz();\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;");
Index: clang/lib/Format/FormatTokenLexer.cpp
===
--- clang/lib/Format/FormatTokenLexer.cpp
+++ clang/lib/Format/FormatTokenLexer.cpp
@@ -100,6 +100,10 @@
 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 @@
   Tokens.back()->Tok.setKind(tok::starequal);
   return;
 }
+if (tryMergeTokens(JSNullishOperator, TT_JsNullishCoalescingOperator))
+  return;

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

2019-08-26 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG5836472ac488: clang-format: [JS] handle `as const`. 
(authored by mprobst).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66736/new/

https://reviews.llvm.org/D66736

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -1479,6 +1479,9 @@
   ".someFunction(aa);");
   verifyFormat("const xIsALongIdent:\n""YJustBarelyFitsLinex[];",
   getGoogleJSStyleWithColumns(20));
+  verifyFormat("const x = {\n"
+   "  y: 1\n"
+   "} as const;");
 }
 
 TEST_F(FormatTestJS, UnionIntersectionTypes) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -2746,6 +2746,10 @@
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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -1479,6 +1479,9 @@
   ".someFunction(aa);");
   verifyFormat("const xIsALongIdent:\n""YJustBarelyFitsLinex[];",
   getGoogleJSStyleWithColumns(20));
+  verifyFormat("const x = {\n"
+   "  y: 1\n"
+   "} as const;");
 }
 
 TEST_F(FormatTestJS, UnionIntersectionTypes) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -2746,6 +2746,10 @@
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
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2019-08-26 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.
Herald added a project: clang.

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`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66736

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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -1479,6 +1479,9 @@
   ".someFunction(aa);");
   verifyFormat("const xIsALongIdent:\n""YJustBarelyFitsLinex[];",
   getGoogleJSStyleWithColumns(20));
+  verifyFormat("const x = {\n"
+   "  y: 1\n"
+   "} as const;");
 }
 
 TEST_F(FormatTestJS, UnionIntersectionTypes) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -2746,6 +2746,10 @@
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


Index: clang/unittests/Format/FormatTestJS.cpp
===
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -1479,6 +1479,9 @@
   ".someFunction(aa);");
   verifyFormat("const xIsALongIdent:\n""YJustBarelyFitsLinex[];",
   getGoogleJSStyleWithColumns(20));
+  verifyFormat("const x = {\n"
+   "  y: 1\n"
+   "} as const;");
 }
 
 TEST_F(FormatTestJS, UnionIntersectionTypes) {
Index: clang/lib/Format/TokenAnnotator.cpp
===
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -2746,6 +2746,10 @@
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
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59292: [clang-format] messes up indentation when using JavaScript private fields and methods

2019-03-19 Thread Martin Probst via Phabricator via cfe-commits
mprobst closed this revision.
mprobst added a comment.

Landed in r356449, thanks!


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59292/new/

https://reviews.llvm.org/D59292



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


[PATCH] D59292: [clang-format] messes up indentation when using JavaScript private fields and methods

2019-03-19 Thread Martin Probst via Phabricator via cfe-commits
mprobst accepted this revision.
mprobst added a comment.
This revision is now accepted and ready to land.

Actually I'll fix the nits.




Comment at: clang/docs/ReleaseNotes.rst:174
 
-- ...
+- Add support for correct indenting of private fields and methods in 
Javascript.
 

Honestly, I think we don't really do release notes for clang-format. Revert 
this, or I'll drop it when committing your change.



Comment at: clang/lib/Format/FormatToken.h:66
   TYPE(JsTypeOptionalQuestion) 
\
+  TYPE(JsPrivateIdentifier)
\
   TYPE(LambdaArrow)
\

nit: please keep alpha sorted, i.e. before Js[T]


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59292/new/

https://reviews.llvm.org/D59292



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


[PATCH] D59527: [clang-format] Don't insert break between JS template string and tag identifier

2019-03-19 Thread Martin Probst via Phabricator via cfe-commits
mprobst closed this revision.
mprobst added a comment.

Landed as r356447.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59527/new/

https://reviews.llvm.org/D59527



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


[PATCH] D59527: [clang-format] Don't insert break between JS template string and tag identifier

2019-03-19 Thread Martin Probst via Phabricator via cfe-commits
mprobst accepted this revision.
mprobst added a comment.
This revision is now accepted and ready to land.

LGTM.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59527/new/

https://reviews.llvm.org/D59527



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


[PATCH] D56385: clang-format: [JS] support goog.requireType.

2019-01-07 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL350516: clang-format: [JS] support goog.requireType. 
(authored by mprobst, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56385/new/

https://reviews.llvm.org/D56385

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
@@ -1123,6 +1123,7 @@
(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);
   }
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -600,6 +600,8 @@
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));
 


Index: cfe/trunk/lib/Format/TokenAnnotator.cpp
===
--- cfe/trunk/lib/Format/TokenAnnotator.cpp
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp
@@ -1123,6 +1123,7 @@
(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);
   }
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -600,6 +600,8 @@
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


[PATCH] D56385: clang-format: [JS] support goog.requireType.

2019-01-07 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.

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


Repository:
  rC Clang

https://reviews.llvm.org/D56385

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


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -600,6 +600,8 @@
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));
 
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -1123,6 +1123,7 @@
(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);
   }


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -600,6 +600,8 @@
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));
 
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -1123,6 +1123,7 @@
(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);
   }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52536: clang-format: [JS] conditional types.

2018-09-27 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL343179: clang-format: [JS] conditional types. (authored by 
mprobst, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D52536

Files:
  cfe/trunk/lib/Format/FormatToken.h
  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
@@ -3088,6 +3088,12 @@
   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))
Index: cfe/trunk/lib/Format/FormatToken.h
===
--- cfe/trunk/lib/Format/FormatToken.h
+++ cfe/trunk/lib/Format/FormatToken.h
@@ -680,6 +680,7 @@
 kw_function = ("function");
 kw_get = ("get");
 kw_import = ("import");
+kw_infer = ("infer");
 kw_is = ("is");
 kw_let = ("let");
 kw_module = ("module");
@@ -751,6 +752,7 @@
   IdentifierInfo *kw_function;
   IdentifierInfo *kw_get;
   IdentifierInfo *kw_import;
+  IdentifierInfo *kw_infer;
   IdentifierInfo *kw_is;
   IdentifierInfo *kw_let;
   IdentifierInfo *kw_module;
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -2308,5 +2308,14 @@
   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


Index: cfe/trunk/lib/Format/TokenAnnotator.cpp
===
--- cfe/trunk/lib/Format/TokenAnnotator.cpp
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp
@@ -3088,6 +3088,12 @@
   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))
Index: cfe/trunk/lib/Format/FormatToken.h
===
--- cfe/trunk/lib/Format/FormatToken.h
+++ cfe/trunk/lib/Format/FormatToken.h
@@ -680,6 +680,7 @@
 kw_function = ("function");
 kw_get = ("get");
 kw_import = ("import");
+kw_infer = ("infer");
 kw_is = ("is");
 kw_let = ("let");
 kw_module = ("module");
@@ -751,6 +752,7 @@
   IdentifierInfo *kw_function;
   IdentifierInfo *kw_get;
   IdentifierInfo *kw_import;
+  IdentifierInfo *kw_infer;
   IdentifierInfo *kw_is;
   IdentifierInfo *kw_let;
   IdentifierInfo *kw_module;
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -2308,5 +2308,14 @@
   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


[PATCH] D52536: clang-format: [JS] conditional types.

2018-09-27 Thread Martin Probst via Phabricator via cfe-commits
mprobst updated this revision to Diff 167239.
mprobst added a comment.

- comment in test


Repository:
  rC Clang

https://reviews.llvm.org/D52536

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


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -2308,5 +2308,14 @@
   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
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -3088,6 +3088,12 @@
   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))
Index: lib/Format/FormatToken.h
===
--- lib/Format/FormatToken.h
+++ lib/Format/FormatToken.h
@@ -680,6 +680,7 @@
 kw_function = ("function");
 kw_get = ("get");
 kw_import = ("import");
+kw_infer = ("infer");
 kw_is = ("is");
 kw_let = ("let");
 kw_module = ("module");
@@ -751,6 +752,7 @@
   IdentifierInfo *kw_function;
   IdentifierInfo *kw_get;
   IdentifierInfo *kw_import;
+  IdentifierInfo *kw_infer;
   IdentifierInfo *kw_is;
   IdentifierInfo *kw_let;
   IdentifierInfo *kw_module;


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -2308,5 +2308,14 @@
   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
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -3088,6 +3088,12 @@
   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))
Index: lib/Format/FormatToken.h
===
--- lib/Format/FormatToken.h
+++ lib/Format/FormatToken.h
@@ -680,6 +680,7 @@
 kw_function = ("function");
 kw_get = ("get");
 kw_import = ("import");
+kw_infer = ("infer");
 kw_is = ("is");
 kw_let = ("let");
 kw_module = ("module");
@@ -751,6 +752,7 @@
   IdentifierInfo *kw_function;
   IdentifierInfo *kw_get;
   IdentifierInfo *kw_import;
+  IdentifierInfo *kw_infer;
   IdentifierInfo *kw_is;
   IdentifierInfo *kw_let;
   IdentifierInfo *kw_module;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D52536: clang-format: [JS] conditional types.

2018-09-26 Thread Martin Probst via Phabricator via cfe-commits
mprobst created this revision.
mprobst added a reviewer: krasimir.

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.


Repository:
  rC Clang

https://reviews.llvm.org/D52536

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


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -2308,5 +2308,12 @@
   verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
 }
 
+TEST_F(FormatTestJS, ConditionalTypes) {
+  verifyFormat("type UnionToIntersection =\n"
+   "(U extends any ? (k: U) => void :\n"
+   " never) extends((k: infer I) => void) ? I "
+   ": never;");
+}
+
 } // end namespace tooling
 } // end namespace clang
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -3088,6 +3088,12 @@
   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))
Index: lib/Format/FormatToken.h
===
--- lib/Format/FormatToken.h
+++ lib/Format/FormatToken.h
@@ -680,6 +680,7 @@
 kw_function = ("function");
 kw_get = ("get");
 kw_import = ("import");
+kw_infer = ("infer");
 kw_is = ("is");
 kw_let = ("let");
 kw_module = ("module");
@@ -751,6 +752,7 @@
   IdentifierInfo *kw_function;
   IdentifierInfo *kw_get;
   IdentifierInfo *kw_import;
+  IdentifierInfo *kw_infer;
   IdentifierInfo *kw_is;
   IdentifierInfo *kw_let;
   IdentifierInfo *kw_module;


Index: unittests/Format/FormatTestJS.cpp
===
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -2308,5 +2308,12 @@
   verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
 }
 
+TEST_F(FormatTestJS, ConditionalTypes) {
+  verifyFormat("type UnionToIntersection =\n"
+   "(U extends any ? (k: U) => void :\n"
+   " never) extends((k: infer I) => void) ? I "
+   ": never;");
+}
+
 } // end namespace tooling
 } // end namespace clang
Index: lib/Format/TokenAnnotator.cpp
===
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -3088,6 +3088,12 @@
   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))
Index: lib/Format/FormatToken.h
===
--- lib/Format/FormatToken.h
+++ lib/Format/FormatToken.h
@@ -680,6 +680,7 @@
 kw_function = ("function");
 kw_get = ("get");
 kw_import = ("import");
+kw_infer = ("infer");
 kw_is = ("is");
 kw_let = ("let");
 kw_module = ("module");
@@ -751,6 +752,7 @@
   IdentifierInfo *kw_function;
   IdentifierInfo *kw_get;
   IdentifierInfo *kw_import;
+  IdentifierInfo *kw_infer;
   IdentifierInfo *kw_is;
   IdentifierInfo *kw_let;
   IdentifierInfo *kw_module;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


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

2018-09-26 Thread Martin Probst via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL343080: clang-format: [JS] space after parameter naming. 
(authored by mprobst, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D52535

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
@@ -2517,7 +2517,9 @@
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)))
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -2304,5 +2304,9 @@
  "};"));
 }
 
+TEST_F(FormatTestJS, ParameterNamingComment) {
+  verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
+}
+
 } // end namespace tooling
 } // end namespace clang


Index: cfe/trunk/lib/Format/TokenAnnotator.cpp
===
--- cfe/trunk/lib/Format/TokenAnnotator.cpp
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp
@@ -2517,7 +2517,9 @@
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)))
Index: cfe/trunk/unittests/Format/FormatTestJS.cpp
===
--- cfe/trunk/unittests/Format/FormatTestJS.cpp
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp
@@ -2304,5 +2304,9 @@
  "};"));
 }
 
+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


  1   2   3   >