FormatTestJS.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. //===- unittest/Format/FormatTestJS.cpp - Formatting unit tests for JS ----===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "FormatTestUtils.h"
  10. #include "clang/Format/Format.h"
  11. #include "llvm/Support/Debug.h"
  12. #include "gtest/gtest.h"
  13. #define DEBUG_TYPE "format-test"
  14. namespace clang {
  15. namespace format {
  16. class FormatTestJS : public ::testing::Test {
  17. protected:
  18. static std::string format(llvm::StringRef Code, unsigned Offset,
  19. unsigned Length, const FormatStyle &Style) {
  20. DEBUG(llvm::errs() << "---\n");
  21. DEBUG(llvm::errs() << Code << "\n\n");
  22. std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
  23. bool IncompleteFormat = false;
  24. tooling::Replacements Replaces =
  25. reformat(Style, Code, Ranges, "<stdin>", &IncompleteFormat);
  26. EXPECT_FALSE(IncompleteFormat);
  27. std::string Result = applyAllReplacements(Code, Replaces);
  28. EXPECT_NE("", Result);
  29. DEBUG(llvm::errs() << "\n" << Result << "\n\n");
  30. return Result;
  31. }
  32. static std::string format(
  33. llvm::StringRef Code,
  34. const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
  35. return format(Code, 0, Code.size(), Style);
  36. }
  37. static FormatStyle getGoogleJSStyleWithColumns(unsigned ColumnLimit) {
  38. FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
  39. Style.ColumnLimit = ColumnLimit;
  40. return Style;
  41. }
  42. static void verifyFormat(
  43. llvm::StringRef Code,
  44. const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
  45. EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
  46. }
  47. };
  48. TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) {
  49. verifyFormat("a == = b;");
  50. verifyFormat("a != = b;");
  51. verifyFormat("a === b;");
  52. verifyFormat("aaaaaaa ===\n b;", getGoogleJSStyleWithColumns(10));
  53. verifyFormat("a !== b;");
  54. verifyFormat("aaaaaaa !==\n b;", getGoogleJSStyleWithColumns(10));
  55. verifyFormat("if (a + b + c +\n"
  56. " d !==\n"
  57. " e + f + g)\n"
  58. " q();",
  59. getGoogleJSStyleWithColumns(20));
  60. verifyFormat("a >> >= b;");
  61. verifyFormat("a >>> b;");
  62. verifyFormat("aaaaaaa >>>\n b;", getGoogleJSStyleWithColumns(10));
  63. verifyFormat("a >>>= b;");
  64. verifyFormat("aaaaaaa >>>=\n b;", getGoogleJSStyleWithColumns(10));
  65. verifyFormat("if (a + b + c +\n"
  66. " d >>>\n"
  67. " e + f + g)\n"
  68. " q();",
  69. getGoogleJSStyleWithColumns(20));
  70. verifyFormat("var x = aaaaaaaaaa ?\n"
  71. " bbbbbb :\n"
  72. " ccc;",
  73. getGoogleJSStyleWithColumns(20));
  74. verifyFormat("var b = a.map((x) => x + 1);");
  75. verifyFormat("return ('aaa') in bbbb;");
  76. // ES6 spread operator.
  77. verifyFormat("someFunction(...a);");
  78. verifyFormat("var x = [1, ...a, 2];");
  79. }
  80. TEST_F(FormatTestJS, UnderstandsAmpAmp) {
  81. verifyFormat("e && e.SomeFunction();");
  82. }
  83. TEST_F(FormatTestJS, LiteralOperatorsCanBeKeywords) {
  84. verifyFormat("not.and.or.not_eq = 1;");
  85. }
  86. TEST_F(FormatTestJS, ES6DestructuringAssignment) {
  87. verifyFormat("var [a, b, c] = [1, 2, 3];");
  88. verifyFormat("var {a, b} = {a: 1, b: 2};");
  89. }
  90. TEST_F(FormatTestJS, ContainerLiterals) {
  91. verifyFormat("var x = {y: function(a) { return a; }};");
  92. verifyFormat("return {\n"
  93. " link: function() {\n"
  94. " f(); //\n"
  95. " }\n"
  96. "};");
  97. verifyFormat("return {\n"
  98. " a: a,\n"
  99. " link: function() {\n"
  100. " f(); //\n"
  101. " }\n"
  102. "};");
  103. verifyFormat("return {\n"
  104. " a: a,\n"
  105. " link: function() {\n"
  106. " f(); //\n"
  107. " },\n"
  108. " link: function() {\n"
  109. " f(); //\n"
  110. " }\n"
  111. "};");
  112. verifyFormat("var stuff = {\n"
  113. " // comment for update\n"
  114. " update: false,\n"
  115. " // comment for modules\n"
  116. " modules: false,\n"
  117. " // comment for tasks\n"
  118. " tasks: false\n"
  119. "};");
  120. verifyFormat("return {\n"
  121. " 'finish':\n"
  122. " //\n"
  123. " a\n"
  124. "};");
  125. verifyFormat("var obj = {\n"
  126. " fooooooooo: function(x) {\n"
  127. " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
  128. " }\n"
  129. "};");
  130. // Simple object literal, as opposed to enum style below.
  131. verifyFormat("var obj = {a: 123};");
  132. // Enum style top level assignment.
  133. verifyFormat("X = {\n a: 123\n};");
  134. verifyFormat("X.Y = {\n a: 123\n};");
  135. // But only on the top level, otherwise its a plain object literal assignment.
  136. verifyFormat("function x() {\n"
  137. " y = {z: 1};\n"
  138. "}");
  139. verifyFormat("x = foo && {a: 123};");
  140. // Arrow functions in object literals.
  141. verifyFormat("var x = {y: (a) => { return a; }};");
  142. verifyFormat("var x = {y: (a) => a};");
  143. // Computed keys.
  144. verifyFormat("var x = {[a]: 1, b: 2, [c]: 3};");
  145. verifyFormat("var x = {\n"
  146. " [a]: 1,\n"
  147. " b: 2,\n"
  148. " [c]: 3,\n"
  149. "};");
  150. }
  151. TEST_F(FormatTestJS, MethodsInObjectLiterals) {
  152. verifyFormat("var o = {\n"
  153. " value: 'test',\n"
  154. " get value() { // getter\n"
  155. " return this.value;\n"
  156. " }\n"
  157. "};");
  158. verifyFormat("var o = {\n"
  159. " value: 'test',\n"
  160. " set value(val) { // setter\n"
  161. " this.value = val;\n"
  162. " }\n"
  163. "};");
  164. verifyFormat("var o = {\n"
  165. " value: 'test',\n"
  166. " someMethod(val) { // method\n"
  167. " doSomething(this.value + val);\n"
  168. " }\n"
  169. "};");
  170. verifyFormat("var o = {\n"
  171. " someMethod(val) { // method\n"
  172. " doSomething(this.value + val);\n"
  173. " },\n"
  174. " someOtherMethod(val) { // method\n"
  175. " doSomething(this.value + val);\n"
  176. " }\n"
  177. "};");
  178. }
  179. TEST_F(FormatTestJS, SpacesInContainerLiterals) {
  180. verifyFormat("var arr = [1, 2, 3];");
  181. verifyFormat("f({a: 1, b: 2, c: 3});");
  182. verifyFormat("var object_literal_with_long_name = {\n"
  183. " a: 'aaaaaaaaaaaaaaaaaa',\n"
  184. " b: 'bbbbbbbbbbbbbbbbbb'\n"
  185. "};");
  186. verifyFormat("f({a: 1, b: 2, c: 3});",
  187. getChromiumStyle(FormatStyle::LK_JavaScript));
  188. verifyFormat("f({'a': [{}]});");
  189. }
  190. TEST_F(FormatTestJS, SingleQuoteStrings) {
  191. verifyFormat("this.function('', true);");
  192. }
  193. TEST_F(FormatTestJS, GoogScopes) {
  194. verifyFormat("goog.scope(function() {\n"
  195. "var x = a.b;\n"
  196. "var y = c.d;\n"
  197. "}); // goog.scope");
  198. verifyFormat("goog.scope(function() {\n"
  199. "// test\n"
  200. "var x = 0;\n"
  201. "// test\n"
  202. "});");
  203. }
  204. TEST_F(FormatTestJS, GoogModules) {
  205. verifyFormat("goog.module('this.is.really.absurdly.long');",
  206. getGoogleJSStyleWithColumns(40));
  207. verifyFormat("goog.require('this.is.really.absurdly.long');",
  208. getGoogleJSStyleWithColumns(40));
  209. verifyFormat("goog.provide('this.is.really.absurdly.long');",
  210. getGoogleJSStyleWithColumns(40));
  211. verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
  212. getGoogleJSStyleWithColumns(40));
  213. // These should be wrapped normally.
  214. verifyFormat(
  215. "var MyLongClassName =\n"
  216. " goog.module.get('my.long.module.name.followedBy.MyLongClassName');");
  217. }
  218. TEST_F(FormatTestJS, FormatsFreestandingFunctions) {
  219. verifyFormat("function outer1(a, b) {\n"
  220. " function inner1(a, b) { return a; }\n"
  221. " inner1(a, b);\n"
  222. "}\n"
  223. "function outer2(a, b) {\n"
  224. " function inner2(a, b) { return a; }\n"
  225. " inner2(a, b);\n"
  226. "}");
  227. verifyFormat("function f() {}");
  228. }
  229. TEST_F(FormatTestJS, ArrayLiterals) {
  230. verifyFormat("var aaaaa: List<SomeThing> =\n"
  231. " [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");
  232. verifyFormat("return [\n"
  233. " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  234. " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
  235. " ccccccccccccccccccccccccccc\n"
  236. "];");
  237. verifyFormat("var someVariable = SomeFuntion([\n"
  238. " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  239. " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
  240. " ccccccccccccccccccccccccccc\n"
  241. "]);");
  242. verifyFormat("var someVariable = SomeFuntion([\n"
  243. " [aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbb],\n"
  244. "]);",
  245. getGoogleJSStyleWithColumns(51));
  246. verifyFormat("var someVariable = SomeFuntion(aaaa, [\n"
  247. " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  248. " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
  249. " ccccccccccccccccccccccccccc\n"
  250. "]);");
  251. verifyFormat("var someVariable = SomeFuntion(aaaa,\n"
  252. " [\n"
  253. " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  254. " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
  255. " ccccccccccccccccccccccccccc\n"
  256. " ],\n"
  257. " aaaa);");
  258. verifyFormat("someFunction([], {a: a});");
  259. }
  260. TEST_F(FormatTestJS, FunctionLiterals) {
  261. verifyFormat("doFoo(function() {});");
  262. verifyFormat("doFoo(function() { return 1; });");
  263. verifyFormat("var func = function() {\n"
  264. " return 1;\n"
  265. "};");
  266. verifyFormat("var func = //\n"
  267. " function() {\n"
  268. " return 1;\n"
  269. "};");
  270. verifyFormat("return {\n"
  271. " body: {\n"
  272. " setAttribute: function(key, val) { this[key] = val; },\n"
  273. " getAttribute: function(key) { return this[key]; },\n"
  274. " style: {direction: ''}\n"
  275. " }\n"
  276. "};");
  277. EXPECT_EQ("abc = xyz ?\n"
  278. " function() {\n"
  279. " return 1;\n"
  280. " } :\n"
  281. " function() {\n"
  282. " return -1;\n"
  283. " };",
  284. format("abc=xyz?function(){return 1;}:function(){return -1;};"));
  285. verifyFormat("var closure = goog.bind(\n"
  286. " function() { // comment\n"
  287. " foo();\n"
  288. " bar();\n"
  289. " },\n"
  290. " this, arg1IsReallyLongAndNeeedsLineBreaks,\n"
  291. " arg3IsReallyLongAndNeeedsLineBreaks);");
  292. verifyFormat("var closure = goog.bind(function() { // comment\n"
  293. " foo();\n"
  294. " bar();\n"
  295. "}, this);");
  296. verifyFormat("return {\n"
  297. " a: 'E',\n"
  298. " b: function() {\n"
  299. " return function() {\n"
  300. " f(); //\n"
  301. " };\n"
  302. " }\n"
  303. "};");
  304. verifyFormat("{\n"
  305. " var someVariable = function(x) {\n"
  306. " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
  307. " };\n"
  308. "}");
  309. verifyFormat("someLooooooooongFunction(\n"
  310. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  311. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  312. " function(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
  313. " // code\n"
  314. " });");
  315. verifyFormat("f({a: function() { return 1; }});",
  316. getGoogleJSStyleWithColumns(33));
  317. verifyFormat("f({\n"
  318. " a: function() { return 1; }\n"
  319. "});",
  320. getGoogleJSStyleWithColumns(32));
  321. verifyFormat("return {\n"
  322. " a: function SomeFunction() {\n"
  323. " // ...\n"
  324. " return 1;\n"
  325. " }\n"
  326. "};");
  327. verifyFormat("this.someObject.doSomething(aaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
  328. " .then(goog.bind(function(aaaaaaaaaaa) {\n"
  329. " someFunction();\n"
  330. " someFunction();\n"
  331. " }, this), aaaaaaaaaaaaaaaaa);");
  332. // FIXME: This is not ideal yet.
  333. verifyFormat("someFunction(goog.bind(\n"
  334. " function() {\n"
  335. " doSomething();\n"
  336. " doSomething();\n"
  337. " },\n"
  338. " this),\n"
  339. " goog.bind(function() {\n"
  340. " doSomething();\n"
  341. " doSomething();\n"
  342. " }, this));");
  343. // FIXME: This is bad, we should be wrapping before "function() {".
  344. verifyFormat("someFunction(function() {\n"
  345. " doSomething(); // break\n"
  346. "})\n"
  347. " .doSomethingElse(\n"
  348. " // break\n"
  349. " );");
  350. }
  351. TEST_F(FormatTestJS, InliningFunctionLiterals) {
  352. FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
  353. Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
  354. verifyFormat("var func = function() {\n"
  355. " return 1;\n"
  356. "};",
  357. Style);
  358. verifyFormat("var func = doSomething(function() { return 1; });", Style);
  359. verifyFormat("var outer = function() {\n"
  360. " var inner = function() { return 1; }\n"
  361. "};",
  362. Style);
  363. verifyFormat("function outer1(a, b) {\n"
  364. " function inner1(a, b) { return a; }\n"
  365. "}",
  366. Style);
  367. Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
  368. verifyFormat("var func = function() { return 1; };", Style);
  369. verifyFormat("var func = doSomething(function() { return 1; });", Style);
  370. verifyFormat(
  371. "var outer = function() { var inner = function() { return 1; } };",
  372. Style);
  373. verifyFormat("function outer1(a, b) {\n"
  374. " function inner1(a, b) { return a; }\n"
  375. "}",
  376. Style);
  377. Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
  378. verifyFormat("var func = function() {\n"
  379. " return 1;\n"
  380. "};",
  381. Style);
  382. verifyFormat("var func = doSomething(function() {\n"
  383. " return 1;\n"
  384. "});",
  385. Style);
  386. verifyFormat("var outer = function() {\n"
  387. " var inner = function() {\n"
  388. " return 1;\n"
  389. " }\n"
  390. "};",
  391. Style);
  392. verifyFormat("function outer1(a, b) {\n"
  393. " function inner1(a, b) {\n"
  394. " return a;\n"
  395. " }\n"
  396. "}",
  397. Style);
  398. }
  399. TEST_F(FormatTestJS, MultipleFunctionLiterals) {
  400. verifyFormat("promise.then(\n"
  401. " function success() {\n"
  402. " doFoo();\n"
  403. " doBar();\n"
  404. " },\n"
  405. " function error() {\n"
  406. " doFoo();\n"
  407. " doBaz();\n"
  408. " },\n"
  409. " []);\n");
  410. verifyFormat("promise.then(\n"
  411. " function success() {\n"
  412. " doFoo();\n"
  413. " doBar();\n"
  414. " },\n"
  415. " [],\n"
  416. " function error() {\n"
  417. " doFoo();\n"
  418. " doBaz();\n"
  419. " });\n");
  420. // FIXME: Here, we should probably break right after the "(" for consistency.
  421. verifyFormat("promise.then([],\n"
  422. " function success() {\n"
  423. " doFoo();\n"
  424. " doBar();\n"
  425. " },\n"
  426. " function error() {\n"
  427. " doFoo();\n"
  428. " doBaz();\n"
  429. " });\n");
  430. verifyFormat("getSomeLongPromise()\n"
  431. " .then(function(value) { body(); })\n"
  432. " .thenCatch(function(error) {\n"
  433. " body();\n"
  434. " body();\n"
  435. " });");
  436. verifyFormat("getSomeLongPromise()\n"
  437. " .then(function(value) {\n"
  438. " body();\n"
  439. " body();\n"
  440. " })\n"
  441. " .thenCatch(function(error) {\n"
  442. " body();\n"
  443. " body();\n"
  444. " });");
  445. verifyFormat("getSomeLongPromise()\n"
  446. " .then(function(value) { body(); })\n"
  447. " .thenCatch(function(error) { body(); });");
  448. }
  449. TEST_F(FormatTestJS, ArrowFunctions) {
  450. verifyFormat("var x = (a) => {\n"
  451. " return a;\n"
  452. "};");
  453. verifyFormat("var x = (a) => {\n"
  454. " function y() { return 42; }\n"
  455. " return a;\n"
  456. "};");
  457. verifyFormat("var x = (a: type): {some: type} => {\n"
  458. " return a;\n"
  459. "};");
  460. verifyFormat("var x = (a) => a;");
  461. verifyFormat("return () => [];");
  462. verifyFormat("var aaaaaaaaaaaaaaaaaaaa = {\n"
  463. " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n"
  464. " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  465. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n"
  466. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  467. "};");
  468. verifyFormat(
  469. "var a = a.aaaaaaa((a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n"
  470. " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
  471. verifyFormat(
  472. "var a = a.aaaaaaa((a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) ?\n"
  473. " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb) :\n"
  474. " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
  475. // FIXME: This is bad, we should be wrapping before "() => {".
  476. verifyFormat("someFunction(() => {\n"
  477. " doSomething(); // break\n"
  478. "})\n"
  479. " .doSomethingElse(\n"
  480. " // break\n"
  481. " );");
  482. }
  483. TEST_F(FormatTestJS, ReturnStatements) {
  484. verifyFormat("function() {\n"
  485. " return [hello, world];\n"
  486. "}");
  487. }
  488. TEST_F(FormatTestJS, AutomaticSemicolonInsertion) {
  489. // The following statements must not wrap, as otherwise the program meaning
  490. // would change due to automatic semicolon insertion.
  491. // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1.
  492. verifyFormat("return aaaaa;", getGoogleJSStyleWithColumns(10));
  493. verifyFormat("continue aaaaa;", getGoogleJSStyleWithColumns(10));
  494. verifyFormat("break aaaaa;", getGoogleJSStyleWithColumns(10));
  495. verifyFormat("throw aaaaa;", getGoogleJSStyleWithColumns(10));
  496. verifyFormat("aaaaaaaaa++;", getGoogleJSStyleWithColumns(10));
  497. verifyFormat("aaaaaaaaa--;", getGoogleJSStyleWithColumns(10));
  498. }
  499. TEST_F(FormatTestJS, ClosureStyleCasts) {
  500. verifyFormat("var x = /** @type {foo} */ (bar);");
  501. }
  502. TEST_F(FormatTestJS, TryCatch) {
  503. verifyFormat("try {\n"
  504. " f();\n"
  505. "} catch (e) {\n"
  506. " g();\n"
  507. "} finally {\n"
  508. " h();\n"
  509. "}");
  510. // But, of course, "catch" is a perfectly fine function name in JavaScript.
  511. verifyFormat("someObject.catch();");
  512. verifyFormat("someObject.new();");
  513. verifyFormat("someObject.delete();");
  514. }
  515. TEST_F(FormatTestJS, StringLiteralConcatenation) {
  516. verifyFormat("var literal = 'hello ' +\n"
  517. " 'world';");
  518. }
  519. TEST_F(FormatTestJS, RegexLiteralClassification) {
  520. // Regex literals.
  521. verifyFormat("var regex = /abc/;");
  522. verifyFormat("f(/abc/);");
  523. verifyFormat("f(abc, /abc/);");
  524. verifyFormat("some_map[/abc/];");
  525. verifyFormat("var x = a ? /abc/ : /abc/;");
  526. verifyFormat("for (var i = 0; /abc/.test(s[i]); i++) {\n}");
  527. verifyFormat("var x = !/abc/.test(y);");
  528. verifyFormat("var x = a && /abc/.test(y);");
  529. verifyFormat("var x = a || /abc/.test(y);");
  530. verifyFormat("var x = a + /abc/.search(y);");
  531. verifyFormat("/abc/.search(y);");
  532. verifyFormat("var regexs = {/abc/, /abc/};");
  533. verifyFormat("return /abc/;");
  534. // Not regex literals.
  535. verifyFormat("var a = a / 2 + b / 3;");
  536. }
  537. TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) {
  538. verifyFormat("var regex = /=/;");
  539. verifyFormat("var regex = /a*/;");
  540. verifyFormat("var regex = /a+/;");
  541. verifyFormat("var regex = /a?/;");
  542. verifyFormat("var regex = /.a./;");
  543. verifyFormat("var regex = /a\\*/;");
  544. verifyFormat("var regex = /^a$/;");
  545. verifyFormat("var regex = /\\/a/;");
  546. verifyFormat("var regex = /(?:x)/;");
  547. verifyFormat("var regex = /x(?=y)/;");
  548. verifyFormat("var regex = /x(?!y)/;");
  549. verifyFormat("var regex = /x|y/;");
  550. verifyFormat("var regex = /a{2}/;");
  551. verifyFormat("var regex = /a{1,3}/;");
  552. verifyFormat("var regex = /[abc]/;");
  553. verifyFormat("var regex = /[^abc]/;");
  554. verifyFormat("var regex = /[\\b]/;");
  555. verifyFormat("var regex = /\\b/;");
  556. verifyFormat("var regex = /\\B/;");
  557. verifyFormat("var regex = /\\d/;");
  558. verifyFormat("var regex = /\\D/;");
  559. verifyFormat("var regex = /\\f/;");
  560. verifyFormat("var regex = /\\n/;");
  561. verifyFormat("var regex = /\\r/;");
  562. verifyFormat("var regex = /\\s/;");
  563. verifyFormat("var regex = /\\S/;");
  564. verifyFormat("var regex = /\\t/;");
  565. verifyFormat("var regex = /\\v/;");
  566. verifyFormat("var regex = /\\w/;");
  567. verifyFormat("var regex = /\\W/;");
  568. verifyFormat("var regex = /a(a)\\1/;");
  569. verifyFormat("var regex = /\\0/;");
  570. verifyFormat("var regex = /\\\\/g;");
  571. verifyFormat("var regex = /\\a\\\\/g;");
  572. verifyFormat("var regex = /\a\\//g;");
  573. verifyFormat("var regex = /a\\//;\n"
  574. "var x = 0;");
  575. EXPECT_EQ("var regex = /'/g;", format("var regex = /'/g ;"));
  576. EXPECT_EQ("var regex = /'/g; //'", format("var regex = /'/g ; //'"));
  577. EXPECT_EQ("var regex = /\\/*/;\n"
  578. "var x = 0;",
  579. format("var regex = /\\/*/;\n"
  580. "var x=0;"));
  581. EXPECT_EQ("var x = /a\\//;", format("var x = /a\\// \n;"));
  582. verifyFormat("var regex = /\"/;", getGoogleJSStyleWithColumns(16));
  583. verifyFormat("var regex =\n"
  584. " /\"/;",
  585. getGoogleJSStyleWithColumns(15));
  586. verifyFormat("var regex = //\n"
  587. " /a/;");
  588. verifyFormat("var regexs = [\n"
  589. " /d/, //\n"
  590. " /aa/, //\n"
  591. "];");
  592. }
  593. TEST_F(FormatTestJS, RegexLiteralModifiers) {
  594. verifyFormat("var regex = /abc/g;");
  595. verifyFormat("var regex = /abc/i;");
  596. verifyFormat("var regex = /abc/m;");
  597. verifyFormat("var regex = /abc/y;");
  598. }
  599. TEST_F(FormatTestJS, RegexLiteralLength) {
  600. verifyFormat("var regex = /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
  601. getGoogleJSStyleWithColumns(60));
  602. verifyFormat("var regex =\n"
  603. " /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
  604. getGoogleJSStyleWithColumns(60));
  605. verifyFormat("var regex = /\\xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
  606. getGoogleJSStyleWithColumns(50));
  607. }
  608. TEST_F(FormatTestJS, RegexLiteralExamples) {
  609. verifyFormat("var regex = search.match(/(?:\?|&)times=([^?&]+)/i);");
  610. }
  611. TEST_F(FormatTestJS, TypeAnnotations) {
  612. verifyFormat("var x: string;");
  613. verifyFormat("function x(): string {\n return 'x';\n}");
  614. verifyFormat("function x(): {x: string} {\n return {x: 'x'};\n}");
  615. verifyFormat("function x(y: string): string {\n return 'x';\n}");
  616. verifyFormat("for (var y: string in x) {\n x();\n}");
  617. verifyFormat("((a: string, b: number): string => a + b);");
  618. verifyFormat("var x: (y: number) => string;");
  619. verifyFormat("var x: P<string, (a: number) => string>;");
  620. verifyFormat("var x = {y: function(): z { return 1; }};");
  621. verifyFormat("var x = {y: function(): {a: number} { return 1; }};");
  622. }
  623. TEST_F(FormatTestJS, ClassDeclarations) {
  624. verifyFormat("class C {\n x: string = 12;\n}");
  625. verifyFormat("class C {\n x(): string => 12;\n}");
  626. verifyFormat("class C {\n ['x' + 2]: string = 12;\n}");
  627. verifyFormat("class C {\n private x: string = 12;\n}");
  628. verifyFormat("class C {\n private static x: string = 12;\n}");
  629. verifyFormat("class C {\n static x(): string { return 'asd'; }\n}");
  630. verifyFormat("class C extends P implements I {}");
  631. verifyFormat("class C extends p.P implements i.I {}");
  632. verifyFormat("class Test {\n"
  633. " aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaaa):\n"
  634. " aaaaaaaaaaaaaaaaaaaaaa {}\n"
  635. "}");
  636. // ':' is not a type declaration here.
  637. verifyFormat("class X {\n"
  638. " subs = {\n"
  639. " 'b': {\n"
  640. " 'c': 1,\n"
  641. " },\n"
  642. " };\n"
  643. "}");
  644. }
  645. TEST_F(FormatTestJS, InterfaceDeclarations) {
  646. verifyFormat("interface I {\n"
  647. " x: string;\n"
  648. "}\n"
  649. "var y;");
  650. // Ensure that state is reset after parsing the interface.
  651. verifyFormat("interface a {}\n"
  652. "export function b() {}\n"
  653. "var x;");
  654. }
  655. TEST_F(FormatTestJS, EnumDeclarations) {
  656. verifyFormat("enum Foo {\n"
  657. " A = 1,\n"
  658. " B\n"
  659. "}");
  660. verifyFormat("export /* somecomment*/ enum Foo {\n"
  661. " A = 1,\n"
  662. " B\n"
  663. "}");
  664. verifyFormat("enum Foo {\n"
  665. " A = 1, // comment\n"
  666. " B\n"
  667. "}\n"
  668. "var x = 1;");
  669. }
  670. TEST_F(FormatTestJS, MetadataAnnotations) {
  671. verifyFormat("@A\nclass C {\n}");
  672. verifyFormat("@A({arg: 'value'})\nclass C {\n}");
  673. verifyFormat("@A\n@B\nclass C {\n}");
  674. verifyFormat("class C {\n @A x: string;\n}");
  675. verifyFormat("class C {\n"
  676. " @A\n"
  677. " private x(): string {\n"
  678. " return 'y';\n"
  679. " }\n"
  680. "}");
  681. verifyFormat("class X {}\n"
  682. "class Y {}");
  683. }
  684. TEST_F(FormatTestJS, Modules) {
  685. verifyFormat("import SomeThing from 'some/module.js';");
  686. verifyFormat("import {X, Y} from 'some/module.js';");
  687. verifyFormat("import {\n"
  688. " VeryLongImportsAreAnnoying,\n"
  689. " VeryLongImportsAreAnnoying,\n"
  690. " VeryLongImportsAreAnnoying,\n"
  691. " VeryLongImportsAreAnnoying\n"
  692. "} from 'some/module.js';");
  693. verifyFormat("import {\n"
  694. " X,\n"
  695. " Y,\n"
  696. "} from 'some/module.js';");
  697. verifyFormat("import {\n"
  698. " X,\n"
  699. " Y,\n"
  700. "} from 'some/long/module.js';",
  701. getGoogleJSStyleWithColumns(20));
  702. verifyFormat("import {X as myLocalX, Y as myLocalY} from 'some/module.js';");
  703. verifyFormat("import * as lib from 'some/module.js';");
  704. verifyFormat("var x = {import: 1};\nx.import = 2;");
  705. verifyFormat("export function fn() {\n"
  706. " return 'fn';\n"
  707. "}");
  708. verifyFormat("export function A() {}\n"
  709. "export default function B() {}\n"
  710. "export function C() {}");
  711. verifyFormat("export const x = 12;");
  712. verifyFormat("export default class X {}");
  713. verifyFormat("export {X, Y} from 'some/module.js';");
  714. verifyFormat("export {\n"
  715. " X,\n"
  716. " Y,\n"
  717. "} from 'some/module.js';");
  718. verifyFormat("export class C {\n"
  719. " x: number;\n"
  720. " y: string;\n"
  721. "}");
  722. verifyFormat("export class X { y: number; }");
  723. verifyFormat("export default class X { y: number }");
  724. verifyFormat("export default function() {\n return 1;\n}");
  725. verifyFormat("export var x = 12;");
  726. verifyFormat("class C {}\n"
  727. "export function f() {}\n"
  728. "var v;");
  729. verifyFormat("export var x: number = 12;");
  730. verifyFormat("export const y = {\n"
  731. " a: 1,\n"
  732. " b: 2\n"
  733. "};");
  734. verifyFormat("export enum Foo {\n"
  735. " BAR,\n"
  736. " // adsdasd\n"
  737. " BAZ\n"
  738. "}");
  739. }
  740. TEST_F(FormatTestJS, TemplateStrings) {
  741. // Keeps any whitespace/indentation within the template string.
  742. EXPECT_EQ("var x = `hello\n"
  743. " ${ name }\n"
  744. " !`;",
  745. format("var x = `hello\n"
  746. " ${ name }\n"
  747. " !`;"));
  748. verifyFormat("var x =\n"
  749. " `hello ${world}` >= some();",
  750. getGoogleJSStyleWithColumns(34)); // Barely doesn't fit.
  751. verifyFormat("var x = `hello ${world}` >= some();",
  752. getGoogleJSStyleWithColumns(35)); // Barely fits.
  753. EXPECT_EQ("var x = `hello\n"
  754. " ${world}` >=\n"
  755. " some();",
  756. format("var x =\n"
  757. " `hello\n"
  758. " ${world}` >= some();",
  759. getGoogleJSStyleWithColumns(21))); // Barely doesn't fit.
  760. EXPECT_EQ("var x = `hello\n"
  761. " ${world}` >= some();",
  762. format("var x =\n"
  763. " `hello\n"
  764. " ${world}` >= some();",
  765. getGoogleJSStyleWithColumns(22))); // Barely fits.
  766. verifyFormat("var x =\n"
  767. " `h`;",
  768. getGoogleJSStyleWithColumns(11));
  769. EXPECT_EQ(
  770. "var x =\n `multi\n line`;",
  771. format("var x = `multi\n line`;", getGoogleJSStyleWithColumns(13)));
  772. verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
  773. " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`);");
  774. // Make sure template strings get a proper ColumnWidth assigned, even if they
  775. // are first token in line.
  776. verifyFormat(
  777. "var a = aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
  778. " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;");
  779. // Two template strings.
  780. verifyFormat("var x = `hello` == `hello`;");
  781. // Comments in template strings.
  782. EXPECT_EQ("var x = `//a`;\n"
  783. "var y;",
  784. format("var x =\n `//a`;\n"
  785. "var y ;"));
  786. EXPECT_EQ("var x = `/*a`;\n"
  787. "var y;",
  788. format("var x =\n `/*a`;\n"
  789. "var y;"));
  790. // Unterminated string literals in a template string.
  791. verifyFormat("var x = `'`; // comment with matching quote '\n"
  792. "var y;");
  793. verifyFormat("var x = `\"`; // comment with matching quote \"\n"
  794. "var y;");
  795. // Backticks in a comment - not a template string.
  796. EXPECT_EQ("var x = 1 // `/*a`;\n"
  797. " ;",
  798. format("var x =\n 1 // `/*a`;\n"
  799. " ;"));
  800. EXPECT_EQ("/* ` */ var x = 1; /* ` */",
  801. format("/* ` */ var x\n= 1; /* ` */"));
  802. // Comment spans multiple template strings.
  803. EXPECT_EQ("var x = `/*a`;\n"
  804. "var y = ` */ `;",
  805. format("var x =\n `/*a`;\n"
  806. "var y =\n ` */ `;"));
  807. // Escaped backtick.
  808. EXPECT_EQ("var x = ` \\` a`;\n"
  809. "var y;",
  810. format("var x = ` \\` a`;\n"
  811. "var y;"));
  812. }
  813. TEST_F(FormatTestJS, CastSyntax) { verifyFormat("var x = <type>foo;"); }
  814. TEST_F(FormatTestJS, TypeArguments) {
  815. verifyFormat("class X<Y> {}");
  816. verifyFormat("new X<Y>();");
  817. verifyFormat("foo<Y>(a);");
  818. verifyFormat("var x: X<Y>[];");
  819. verifyFormat("class C extends D<E> implements F<G>, H<I> {}");
  820. verifyFormat("function f(a: List<any> = null) {}");
  821. verifyFormat("function f(): List<any> {}");
  822. verifyFormat("function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa():\n"
  823. " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}");
  824. verifyFormat("function aaaaaaaaaa(aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaa,\n"
  825. " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaa):\n"
  826. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {}");
  827. }
  828. TEST_F(FormatTestJS, OptionalTypes) {
  829. verifyFormat("function x(a?: b, c?, d?) {}");
  830. verifyFormat("class X {\n"
  831. " y?: z;\n"
  832. " z?;\n"
  833. "}");
  834. verifyFormat("interface X {\n"
  835. " y?(): z;\n"
  836. "}");
  837. verifyFormat("x ? 1 : 2;");
  838. verifyFormat("constructor({aa}: {\n"
  839. " aa?: string,\n"
  840. " aaaaaaaa?: string,\n"
  841. " aaaaaaaaaaaaaaa?: boolean,\n"
  842. " aaaaaa?: List<string>\n"
  843. "}) {}");
  844. }
  845. TEST_F(FormatTestJS, IndexSignature) {
  846. verifyFormat("var x: {[k: string]: v};");
  847. }
  848. } // end namespace tooling
  849. } // end namespace clang