FormatTestJS.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  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. std::string Result = format(test::messUp(Code), Style);
  46. EXPECT_EQ(Code.str(), Result) << "Formatted:\n" << Result;
  47. }
  48. static void verifyFormat(
  49. llvm::StringRef Expected,
  50. llvm::StringRef Code,
  51. const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
  52. std::string Result = format(Code, Style);
  53. EXPECT_EQ(Expected.str(), Result) << "Formatted:\n" << Result;
  54. }
  55. };
  56. TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) {
  57. verifyFormat("a == = b;");
  58. verifyFormat("a != = b;");
  59. verifyFormat("a === b;");
  60. verifyFormat("aaaaaaa ===\n b;", getGoogleJSStyleWithColumns(10));
  61. verifyFormat("a !== b;");
  62. verifyFormat("aaaaaaa !==\n b;", getGoogleJSStyleWithColumns(10));
  63. verifyFormat("if (a + b + c +\n"
  64. " d !==\n"
  65. " e + f + g)\n"
  66. " q();",
  67. getGoogleJSStyleWithColumns(20));
  68. verifyFormat("a >> >= b;");
  69. verifyFormat("a >>> b;");
  70. verifyFormat("aaaaaaa >>>\n b;", getGoogleJSStyleWithColumns(10));
  71. verifyFormat("a >>>= b;");
  72. verifyFormat("aaaaaaa >>>=\n b;", getGoogleJSStyleWithColumns(10));
  73. verifyFormat("if (a + b + c +\n"
  74. " d >>>\n"
  75. " e + f + g)\n"
  76. " q();",
  77. getGoogleJSStyleWithColumns(20));
  78. verifyFormat("var x = aaaaaaaaaa ?\n"
  79. " bbbbbb :\n"
  80. " ccc;",
  81. getGoogleJSStyleWithColumns(20));
  82. verifyFormat("var b = a.map((x) => x + 1);");
  83. verifyFormat("return ('aaa') in bbbb;");
  84. verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
  85. " aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
  86. FormatStyle Style = getGoogleJSStyleWithColumns(80);
  87. Style.AlignOperands = true;
  88. verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
  89. " aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
  90. Style);
  91. Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
  92. verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa()\n"
  93. " in aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
  94. Style);
  95. // ES6 spread operator.
  96. verifyFormat("someFunction(...a);");
  97. verifyFormat("var x = [1, ...a, 2];");
  98. }
  99. TEST_F(FormatTestJS, UnderstandsAmpAmp) {
  100. verifyFormat("e && e.SomeFunction();");
  101. }
  102. TEST_F(FormatTestJS, LiteralOperatorsCanBeKeywords) {
  103. verifyFormat("not.and.or.not_eq = 1;");
  104. }
  105. TEST_F(FormatTestJS, ReservedWords) {
  106. // JavaScript reserved words (aka keywords) are only illegal when used as
  107. // Identifiers, but are legal as IdentifierNames.
  108. verifyFormat("x.class.struct = 1;");
  109. verifyFormat("x.case = 1;");
  110. verifyFormat("x.interface = 1;");
  111. verifyFormat("x.for = 1;");
  112. verifyFormat("x.of() = 1;");
  113. verifyFormat("x.in() = 1;");
  114. verifyFormat("x.let() = 1;");
  115. verifyFormat("x.var() = 1;");
  116. verifyFormat("x = {\n"
  117. " a: 12,\n"
  118. " interface: 1,\n"
  119. " switch: 1,\n"
  120. "};");
  121. verifyFormat("var struct = 2;");
  122. verifyFormat("var union = 2;");
  123. verifyFormat("var interface = 2;");
  124. verifyFormat("interface = 2;");
  125. verifyFormat("x = interface instanceof y;");
  126. }
  127. TEST_F(FormatTestJS, CppKeywords) {
  128. // Make sure we don't mess stuff up because of C++ keywords.
  129. verifyFormat("return operator && (aa);");
  130. }
  131. TEST_F(FormatTestJS, ES6DestructuringAssignment) {
  132. verifyFormat("var [a, b, c] = [1, 2, 3];");
  133. verifyFormat("const [a, b, c] = [1, 2, 3];");
  134. verifyFormat("let [a, b, c] = [1, 2, 3];");
  135. verifyFormat("var {a, b} = {a: 1, b: 2};");
  136. verifyFormat("let {a, b} = {a: 1, b: 2};");
  137. }
  138. TEST_F(FormatTestJS, ContainerLiterals) {
  139. verifyFormat("var x = {y: function(a) { return a; }};");
  140. verifyFormat("return {\n"
  141. " link: function() {\n"
  142. " f(); //\n"
  143. " }\n"
  144. "};");
  145. verifyFormat("return {\n"
  146. " a: a,\n"
  147. " link: function() {\n"
  148. " f(); //\n"
  149. " }\n"
  150. "};");
  151. verifyFormat("return {\n"
  152. " a: a,\n"
  153. " link: function() {\n"
  154. " f(); //\n"
  155. " },\n"
  156. " link: function() {\n"
  157. " f(); //\n"
  158. " }\n"
  159. "};");
  160. verifyFormat("var stuff = {\n"
  161. " // comment for update\n"
  162. " update: false,\n"
  163. " // comment for modules\n"
  164. " modules: false,\n"
  165. " // comment for tasks\n"
  166. " tasks: false\n"
  167. "};");
  168. verifyFormat("return {\n"
  169. " 'finish':\n"
  170. " //\n"
  171. " a\n"
  172. "};");
  173. verifyFormat("var obj = {\n"
  174. " fooooooooo: function(x) {\n"
  175. " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
  176. " }\n"
  177. "};");
  178. // Simple object literal, as opposed to enum style below.
  179. verifyFormat("var obj = {a: 123};");
  180. // Enum style top level assignment.
  181. verifyFormat("X = {\n a: 123\n};");
  182. verifyFormat("X.Y = {\n a: 123\n};");
  183. // But only on the top level, otherwise its a plain object literal assignment.
  184. verifyFormat("function x() {\n"
  185. " y = {z: 1};\n"
  186. "}");
  187. verifyFormat("x = foo && {a: 123};");
  188. // Arrow functions in object literals.
  189. verifyFormat("var x = {y: (a) => { return a; }};");
  190. verifyFormat("var x = {y: (a) => a};");
  191. // Computed keys.
  192. verifyFormat("var x = {[a]: 1, b: 2, [c]: 3};");
  193. verifyFormat("var x = {\n"
  194. " [a]: 1,\n"
  195. " b: 2,\n"
  196. " [c]: 3,\n"
  197. "};");
  198. // Object literals can leave out labels.
  199. verifyFormat("f({a}, () => {\n"
  200. " g(); //\n"
  201. "});");
  202. // Keys can be quoted.
  203. verifyFormat("var x = {\n"
  204. " a: a,\n"
  205. " b: b,\n"
  206. " 'c': c,\n"
  207. "};");
  208. }
  209. TEST_F(FormatTestJS, MethodsInObjectLiterals) {
  210. verifyFormat("var o = {\n"
  211. " value: 'test',\n"
  212. " get value() { // getter\n"
  213. " return this.value;\n"
  214. " }\n"
  215. "};");
  216. verifyFormat("var o = {\n"
  217. " value: 'test',\n"
  218. " set value(val) { // setter\n"
  219. " this.value = val;\n"
  220. " }\n"
  221. "};");
  222. verifyFormat("var o = {\n"
  223. " value: 'test',\n"
  224. " someMethod(val) { // method\n"
  225. " doSomething(this.value + val);\n"
  226. " }\n"
  227. "};");
  228. verifyFormat("var o = {\n"
  229. " someMethod(val) { // method\n"
  230. " doSomething(this.value + val);\n"
  231. " },\n"
  232. " someOtherMethod(val) { // method\n"
  233. " doSomething(this.value + val);\n"
  234. " }\n"
  235. "};");
  236. }
  237. TEST_F(FormatTestJS, SpacesInContainerLiterals) {
  238. verifyFormat("var arr = [1, 2, 3];");
  239. verifyFormat("f({a: 1, b: 2, c: 3});");
  240. verifyFormat("var object_literal_with_long_name = {\n"
  241. " a: 'aaaaaaaaaaaaaaaaaa',\n"
  242. " b: 'bbbbbbbbbbbbbbbbbb'\n"
  243. "};");
  244. verifyFormat("f({a: 1, b: 2, c: 3});",
  245. getChromiumStyle(FormatStyle::LK_JavaScript));
  246. verifyFormat("f({'a': [{}]});");
  247. }
  248. TEST_F(FormatTestJS, SingleQuotedStrings) {
  249. verifyFormat("this.function('', true);");
  250. }
  251. TEST_F(FormatTestJS, GoogScopes) {
  252. verifyFormat("goog.scope(function() {\n"
  253. "var x = a.b;\n"
  254. "var y = c.d;\n"
  255. "}); // goog.scope");
  256. verifyFormat("goog.scope(function() {\n"
  257. "// test\n"
  258. "var x = 0;\n"
  259. "// test\n"
  260. "});");
  261. }
  262. TEST_F(FormatTestJS, GoogModules) {
  263. verifyFormat("goog.module('this.is.really.absurdly.long');",
  264. getGoogleJSStyleWithColumns(40));
  265. verifyFormat("goog.require('this.is.really.absurdly.long');",
  266. getGoogleJSStyleWithColumns(40));
  267. verifyFormat("goog.provide('this.is.really.absurdly.long');",
  268. getGoogleJSStyleWithColumns(40));
  269. verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
  270. getGoogleJSStyleWithColumns(40));
  271. verifyFormat("goog.setTestOnly('this.is.really.absurdly.long');",
  272. getGoogleJSStyleWithColumns(40));
  273. verifyFormat("goog.forwardDeclare('this.is.really.absurdly.long');",
  274. getGoogleJSStyleWithColumns(40));
  275. // These should be wrapped normally.
  276. verifyFormat(
  277. "var MyLongClassName =\n"
  278. " goog.module.get('my.long.module.name.followedBy.MyLongClassName');");
  279. }
  280. TEST_F(FormatTestJS, FormatsFreestandingFunctions) {
  281. verifyFormat("function outer1(a, b) {\n"
  282. " function inner1(a, b) { return a; }\n"
  283. " inner1(a, b);\n"
  284. "}\n"
  285. "function outer2(a, b) {\n"
  286. " function inner2(a, b) { return a; }\n"
  287. " inner2(a, b);\n"
  288. "}");
  289. verifyFormat("function f() {}");
  290. }
  291. TEST_F(FormatTestJS, GeneratorFunctions) {
  292. verifyFormat("function* f() {\n"
  293. " let x = 1;\n"
  294. " yield x;\n"
  295. " yield* something();\n"
  296. "}");
  297. verifyFormat("function*\n"
  298. " f() {\n"
  299. "}",
  300. getGoogleJSStyleWithColumns(8));
  301. verifyFormat("export function* f() {\n"
  302. " yield 1;\n"
  303. "}\n");
  304. verifyFormat("class X {\n"
  305. " * generatorMethod() { yield x; }\n"
  306. "}");
  307. }
  308. TEST_F(FormatTestJS, AsyncFunctions) {
  309. verifyFormat("async function f() {\n"
  310. " let x = 1;\n"
  311. " return fetch(x);\n"
  312. "}");
  313. verifyFormat("async function* f() {\n"
  314. " yield fetch(x);\n"
  315. "}");
  316. verifyFormat("export async function f() {\n"
  317. " return fetch(x);\n"
  318. "}");
  319. verifyFormat("class X {\n"
  320. " async asyncMethod() { return fetch(1); }\n"
  321. "}");
  322. verifyFormat("function initialize() {\n"
  323. " // Comment.\n"
  324. " return async.then();\n"
  325. "}\n");
  326. }
  327. TEST_F(FormatTestJS, ArrayLiterals) {
  328. verifyFormat("var aaaaa: List<SomeThing> =\n"
  329. " [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");
  330. verifyFormat("return [\n"
  331. " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
  332. " ccccccccccccccccccccccccccc\n"
  333. "];");
  334. verifyFormat("return [\n"
  335. " aaaa().bbbbbbbb('A'),\n"
  336. " aaaa().bbbbbbbb('B'),\n"
  337. " aaaa().bbbbbbbb('C'),\n"
  338. "];");
  339. verifyFormat("var someVariable = SomeFunction([\n"
  340. " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
  341. " ccccccccccccccccccccccccccc\n"
  342. "]);");
  343. verifyFormat("var someVariable = SomeFunction([\n"
  344. " [aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbb],\n"
  345. "]);",
  346. getGoogleJSStyleWithColumns(51));
  347. verifyFormat("var someVariable = SomeFunction(aaaa, [\n"
  348. " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
  349. " ccccccccccccccccccccccccccc\n"
  350. "]);");
  351. verifyFormat("var someVariable = SomeFunction(\n"
  352. " aaaa,\n"
  353. " [\n"
  354. " aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
  355. " cccccccccccccccccccccccccc\n"
  356. " ],\n"
  357. " aaaa);");
  358. verifyFormat("var aaaa = aaaaa || // wrap\n"
  359. " [];");
  360. verifyFormat("someFunction([], {a: a});");
  361. }
  362. TEST_F(FormatTestJS, ColumnLayoutForArrayLiterals) {
  363. verifyFormat("var array = [\n"
  364. " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
  365. " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
  366. "];");
  367. verifyFormat("var array = someFunction([\n"
  368. " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
  369. " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
  370. "]);");
  371. }
  372. TEST_F(FormatTestJS, FunctionLiterals) {
  373. verifyFormat("doFoo(function() {});");
  374. verifyFormat("doFoo(function() { return 1; });");
  375. verifyFormat("var func = function() {\n"
  376. " return 1;\n"
  377. "};");
  378. verifyFormat("var func = //\n"
  379. " function() {\n"
  380. " return 1;\n"
  381. "};");
  382. verifyFormat("return {\n"
  383. " body: {\n"
  384. " setAttribute: function(key, val) { this[key] = val; },\n"
  385. " getAttribute: function(key) { return this[key]; },\n"
  386. " style: {direction: ''}\n"
  387. " }\n"
  388. "};");
  389. verifyFormat("abc = xyz ? function() {\n"
  390. " return 1;\n"
  391. "} : function() {\n"
  392. " return -1;\n"
  393. "};");
  394. verifyFormat("var closure = goog.bind(\n"
  395. " function() { // comment\n"
  396. " foo();\n"
  397. " bar();\n"
  398. " },\n"
  399. " this, arg1IsReallyLongAndNeeedsLineBreaks,\n"
  400. " arg3IsReallyLongAndNeeedsLineBreaks);");
  401. verifyFormat("var closure = goog.bind(function() { // comment\n"
  402. " foo();\n"
  403. " bar();\n"
  404. "}, this);");
  405. verifyFormat("return {\n"
  406. " a: 'E',\n"
  407. " b: function() {\n"
  408. " return function() {\n"
  409. " f(); //\n"
  410. " };\n"
  411. " }\n"
  412. "};");
  413. verifyFormat("{\n"
  414. " var someVariable = function(x) {\n"
  415. " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
  416. " };\n"
  417. "}");
  418. verifyFormat("someLooooooooongFunction(\n"
  419. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  420. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  421. " function(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
  422. " // code\n"
  423. " });");
  424. verifyFormat("f({a: function() { return 1; }});",
  425. getGoogleJSStyleWithColumns(33));
  426. verifyFormat("f({\n"
  427. " a: function() { return 1; }\n"
  428. "});",
  429. getGoogleJSStyleWithColumns(32));
  430. verifyFormat("return {\n"
  431. " a: function SomeFunction() {\n"
  432. " // ...\n"
  433. " return 1;\n"
  434. " }\n"
  435. "};");
  436. verifyFormat("this.someObject.doSomething(aaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
  437. " .then(goog.bind(function(aaaaaaaaaaa) {\n"
  438. " someFunction();\n"
  439. " someFunction();\n"
  440. " }, this), aaaaaaaaaaaaaaaaa);");
  441. verifyFormat("someFunction(goog.bind(function() {\n"
  442. " doSomething();\n"
  443. " doSomething();\n"
  444. "}, this), goog.bind(function() {\n"
  445. " doSomething();\n"
  446. " doSomething();\n"
  447. "}, this));");
  448. // FIXME: This is bad, we should be wrapping before "function() {".
  449. verifyFormat("someFunction(function() {\n"
  450. " doSomething(); // break\n"
  451. "})\n"
  452. " .doSomethingElse(\n"
  453. " // break\n"
  454. " );");
  455. }
  456. TEST_F(FormatTestJS, InliningFunctionLiterals) {
  457. FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
  458. Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
  459. verifyFormat("var func = function() {\n"
  460. " return 1;\n"
  461. "};",
  462. Style);
  463. verifyFormat("var func = doSomething(function() { return 1; });", Style);
  464. verifyFormat("var outer = function() {\n"
  465. " var inner = function() { return 1; }\n"
  466. "};",
  467. Style);
  468. verifyFormat("function outer1(a, b) {\n"
  469. " function inner1(a, b) { return a; }\n"
  470. "}",
  471. Style);
  472. Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
  473. verifyFormat("var func = function() { return 1; };", Style);
  474. verifyFormat("var func = doSomething(function() { return 1; });", Style);
  475. verifyFormat(
  476. "var outer = function() { var inner = function() { return 1; } };",
  477. Style);
  478. verifyFormat("function outer1(a, b) {\n"
  479. " function inner1(a, b) { return a; }\n"
  480. "}",
  481. Style);
  482. Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
  483. verifyFormat("var func = function() {\n"
  484. " return 1;\n"
  485. "};",
  486. Style);
  487. verifyFormat("var func = doSomething(function() {\n"
  488. " return 1;\n"
  489. "});",
  490. Style);
  491. verifyFormat("var outer = function() {\n"
  492. " var inner = function() {\n"
  493. " return 1;\n"
  494. " }\n"
  495. "};",
  496. Style);
  497. verifyFormat("function outer1(a, b) {\n"
  498. " function inner1(a, b) {\n"
  499. " return a;\n"
  500. " }\n"
  501. "}",
  502. Style);
  503. Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
  504. verifyFormat("var func = function() {\n"
  505. " return 1;\n"
  506. "};",
  507. Style);
  508. }
  509. TEST_F(FormatTestJS, MultipleFunctionLiterals) {
  510. verifyFormat("promise.then(\n"
  511. " function success() {\n"
  512. " doFoo();\n"
  513. " doBar();\n"
  514. " },\n"
  515. " function error() {\n"
  516. " doFoo();\n"
  517. " doBaz();\n"
  518. " },\n"
  519. " []);\n");
  520. verifyFormat("promise.then(\n"
  521. " function success() {\n"
  522. " doFoo();\n"
  523. " doBar();\n"
  524. " },\n"
  525. " [],\n"
  526. " function error() {\n"
  527. " doFoo();\n"
  528. " doBaz();\n"
  529. " });\n");
  530. verifyFormat("promise.then(\n"
  531. " [],\n"
  532. " function success() {\n"
  533. " doFoo();\n"
  534. " doBar();\n"
  535. " },\n"
  536. " function error() {\n"
  537. " doFoo();\n"
  538. " doBaz();\n"
  539. " });\n");
  540. verifyFormat("getSomeLongPromise()\n"
  541. " .then(function(value) { body(); })\n"
  542. " .thenCatch(function(error) {\n"
  543. " body();\n"
  544. " body();\n"
  545. " });");
  546. verifyFormat("getSomeLongPromise()\n"
  547. " .then(function(value) {\n"
  548. " body();\n"
  549. " body();\n"
  550. " })\n"
  551. " .thenCatch(function(error) {\n"
  552. " body();\n"
  553. " body();\n"
  554. " });");
  555. verifyFormat("getSomeLongPromise()\n"
  556. " .then(function(value) { body(); })\n"
  557. " .thenCatch(function(error) { body(); });");
  558. verifyFormat("return [aaaaaaaaaaaaaaaaaaaaaa]\n"
  559. " .aaaaaaa(function() {\n"
  560. " //\n"
  561. " })\n"
  562. " .bbbbbb();");
  563. }
  564. TEST_F(FormatTestJS, ArrowFunctions) {
  565. verifyFormat("var x = (a) => {\n"
  566. " return a;\n"
  567. "};");
  568. verifyFormat("var x = (a) => {\n"
  569. " function y() { return 42; }\n"
  570. " return a;\n"
  571. "};");
  572. verifyFormat("var x = (a: type): {some: type} => {\n"
  573. " return a;\n"
  574. "};");
  575. verifyFormat("var x = (a) => a;");
  576. verifyFormat("return () => [];");
  577. verifyFormat("var aaaaaaaaaaaaaaaaaaaa = {\n"
  578. " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n"
  579. " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  580. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n"
  581. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  582. "};");
  583. verifyFormat("var a = a.aaaaaaa(\n"
  584. " (a: a) => aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n"
  585. " aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
  586. verifyFormat("var a = a.aaaaaaa(\n"
  587. " (a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) ?\n"
  588. " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb) :\n"
  589. " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
  590. // FIXME: This is bad, we should be wrapping before "() => {".
  591. verifyFormat("someFunction(() => {\n"
  592. " doSomething(); // break\n"
  593. "})\n"
  594. " .doSomethingElse(\n"
  595. " // break\n"
  596. " );");
  597. }
  598. TEST_F(FormatTestJS, ReturnStatements) {
  599. verifyFormat("function() {\n"
  600. " return [hello, world];\n"
  601. "}");
  602. }
  603. TEST_F(FormatTestJS, ForLoops) {
  604. verifyFormat("for (var i in [2, 3]) {\n"
  605. "}");
  606. verifyFormat("for (var i of [2, 3]) {\n"
  607. "}");
  608. verifyFormat("for (let {a, b} of x) {\n"
  609. "}");
  610. verifyFormat("for (let {a, b} in x) {\n"
  611. "}");
  612. }
  613. TEST_F(FormatTestJS, WrapRespectsAutomaticSemicolonInsertion) {
  614. // The following statements must not wrap, as otherwise the program meaning
  615. // would change due to automatic semicolon insertion.
  616. // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1.
  617. verifyFormat("return aaaaa;", getGoogleJSStyleWithColumns(10));
  618. verifyFormat("continue aaaaa;", getGoogleJSStyleWithColumns(10));
  619. verifyFormat("break aaaaa;", getGoogleJSStyleWithColumns(10));
  620. verifyFormat("throw aaaaa;", getGoogleJSStyleWithColumns(10));
  621. verifyFormat("aaaaaaaaa++;", getGoogleJSStyleWithColumns(10));
  622. verifyFormat("aaaaaaaaa--;", getGoogleJSStyleWithColumns(10));
  623. verifyFormat("return [\n"
  624. " aaa\n"
  625. "];",
  626. getGoogleJSStyleWithColumns(12));
  627. }
  628. TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {
  629. verifyFormat("a\n"
  630. "b;",
  631. " a \n"
  632. " b ;");
  633. verifyFormat("a()\n"
  634. "b;",
  635. " a ()\n"
  636. " b ;");
  637. verifyFormat("a[b]\n"
  638. "c;",
  639. "a [b]\n"
  640. "c ;");
  641. verifyFormat("1\n"
  642. "a;",
  643. "1 \n"
  644. "a ;");
  645. verifyFormat("a\n"
  646. "1;",
  647. "a \n"
  648. "1 ;");
  649. verifyFormat("a\n"
  650. "'x';",
  651. "a \n"
  652. " 'x';");
  653. verifyFormat("a++\n"
  654. "b;",
  655. "a ++\n"
  656. "b ;");
  657. verifyFormat("a\n"
  658. "!b && c;",
  659. "a \n"
  660. " ! b && c;");
  661. verifyFormat("a\n"
  662. "if (1) f();",
  663. " a\n"
  664. " if (1) f();");
  665. verifyFormat("a\n"
  666. "class X {}",
  667. " a\n"
  668. " class X {}");
  669. verifyFormat("var a", "var\n"
  670. "a");
  671. verifyFormat("x instanceof String", "x\n"
  672. "instanceof\n"
  673. "String");
  674. verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n"
  675. " bar) {}");
  676. }
  677. TEST_F(FormatTestJS, ClosureStyleCasts) {
  678. verifyFormat("var x = /** @type {foo} */ (bar);");
  679. }
  680. TEST_F(FormatTestJS, TryCatch) {
  681. verifyFormat("try {\n"
  682. " f();\n"
  683. "} catch (e) {\n"
  684. " g();\n"
  685. "} finally {\n"
  686. " h();\n"
  687. "}");
  688. // But, of course, "catch" is a perfectly fine function name in JavaScript.
  689. verifyFormat("someObject.catch();");
  690. verifyFormat("someObject.new();");
  691. verifyFormat("someObject.delete();");
  692. }
  693. TEST_F(FormatTestJS, StringLiteralConcatenation) {
  694. verifyFormat("var literal = 'hello ' +\n"
  695. " 'world';");
  696. }
  697. TEST_F(FormatTestJS, RegexLiteralClassification) {
  698. // Regex literals.
  699. verifyFormat("var regex = /abc/;");
  700. verifyFormat("f(/abc/);");
  701. verifyFormat("f(abc, /abc/);");
  702. verifyFormat("some_map[/abc/];");
  703. verifyFormat("var x = a ? /abc/ : /abc/;");
  704. verifyFormat("for (var i = 0; /abc/.test(s[i]); i++) {\n}");
  705. verifyFormat("var x = !/abc/.test(y);");
  706. verifyFormat("var x = a && /abc/.test(y);");
  707. verifyFormat("var x = a || /abc/.test(y);");
  708. verifyFormat("var x = a + /abc/.search(y);");
  709. verifyFormat("/abc/.search(y);");
  710. verifyFormat("var regexs = {/abc/, /abc/};");
  711. verifyFormat("return /abc/;");
  712. // Not regex literals.
  713. verifyFormat("var a = a / 2 + b / 3;");
  714. verifyFormat("var a = a++ / 2;");
  715. // Prefix unary can operate on regex literals, not that it makes sense.
  716. verifyFormat("var a = ++/a/;");
  717. // This is a known issue, regular expressions are incorrectly detected if
  718. // directly following a closing parenthesis.
  719. verifyFormat("if (foo) / bar /.exec(baz);");
  720. }
  721. TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) {
  722. verifyFormat("var regex = /=/;");
  723. verifyFormat("var regex = /a*/;");
  724. verifyFormat("var regex = /a+/;");
  725. verifyFormat("var regex = /a?/;");
  726. verifyFormat("var regex = /.a./;");
  727. verifyFormat("var regex = /a\\*/;");
  728. verifyFormat("var regex = /^a$/;");
  729. verifyFormat("var regex = /\\/a/;");
  730. verifyFormat("var regex = /(?:x)/;");
  731. verifyFormat("var regex = /x(?=y)/;");
  732. verifyFormat("var regex = /x(?!y)/;");
  733. verifyFormat("var regex = /x|y/;");
  734. verifyFormat("var regex = /a{2}/;");
  735. verifyFormat("var regex = /a{1,3}/;");
  736. verifyFormat("var regex = /[abc]/;");
  737. verifyFormat("var regex = /[^abc]/;");
  738. verifyFormat("var regex = /[\\b]/;");
  739. verifyFormat("var regex = /[/]/;");
  740. verifyFormat("var regex = /[\\/]/;");
  741. verifyFormat("var regex = /\\[/;");
  742. verifyFormat("var regex = /\\\\[/]/;");
  743. verifyFormat("var regex = /}[\"]/;");
  744. verifyFormat("var regex = /}[/\"]/;");
  745. verifyFormat("var regex = /}[\"/]/;");
  746. verifyFormat("var regex = /\\b/;");
  747. verifyFormat("var regex = /\\B/;");
  748. verifyFormat("var regex = /\\d/;");
  749. verifyFormat("var regex = /\\D/;");
  750. verifyFormat("var regex = /\\f/;");
  751. verifyFormat("var regex = /\\n/;");
  752. verifyFormat("var regex = /\\r/;");
  753. verifyFormat("var regex = /\\s/;");
  754. verifyFormat("var regex = /\\S/;");
  755. verifyFormat("var regex = /\\t/;");
  756. verifyFormat("var regex = /\\v/;");
  757. verifyFormat("var regex = /\\w/;");
  758. verifyFormat("var regex = /\\W/;");
  759. verifyFormat("var regex = /a(a)\\1/;");
  760. verifyFormat("var regex = /\\0/;");
  761. verifyFormat("var regex = /\\\\/g;");
  762. verifyFormat("var regex = /\\a\\\\/g;");
  763. verifyFormat("var regex = /\a\\//g;");
  764. verifyFormat("var regex = /a\\//;\n"
  765. "var x = 0;");
  766. verifyFormat("var regex = /'/g;", "var regex = /'/g ;");
  767. verifyFormat("var regex = /'/g; //'", "var regex = /'/g ; //'");
  768. verifyFormat("var regex = /\\/*/;\n"
  769. "var x = 0;",
  770. "var regex = /\\/*/;\n"
  771. "var x=0;");
  772. verifyFormat("var x = /a\\//;", "var x = /a\\// \n;");
  773. verifyFormat("var regex = /\"/;", getGoogleJSStyleWithColumns(16));
  774. verifyFormat("var regex =\n"
  775. " /\"/;",
  776. getGoogleJSStyleWithColumns(15));
  777. verifyFormat("var regex = //\n"
  778. " /a/;");
  779. verifyFormat("var regexs = [\n"
  780. " /d/, //\n"
  781. " /aa/, //\n"
  782. "];");
  783. }
  784. TEST_F(FormatTestJS, RegexLiteralModifiers) {
  785. verifyFormat("var regex = /abc/g;");
  786. verifyFormat("var regex = /abc/i;");
  787. verifyFormat("var regex = /abc/m;");
  788. verifyFormat("var regex = /abc/y;");
  789. }
  790. TEST_F(FormatTestJS, RegexLiteralLength) {
  791. verifyFormat("var regex = /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
  792. getGoogleJSStyleWithColumns(60));
  793. verifyFormat("var regex =\n"
  794. " /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
  795. getGoogleJSStyleWithColumns(60));
  796. verifyFormat("var regex = /\\xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
  797. getGoogleJSStyleWithColumns(50));
  798. }
  799. TEST_F(FormatTestJS, RegexLiteralExamples) {
  800. verifyFormat("var regex = search.match(/(?:\?|&)times=([^?&]+)/i);");
  801. }
  802. TEST_F(FormatTestJS, TypeAnnotations) {
  803. verifyFormat("var x: string;");
  804. verifyFormat("var x: {a: string; b: number;} = {};");
  805. verifyFormat("function x(): string {\n return 'x';\n}");
  806. verifyFormat("function x(): {x: string} {\n return {x: 'x'};\n}");
  807. verifyFormat("function x(y: string): string {\n return 'x';\n}");
  808. verifyFormat("for (var y: string in x) {\n x();\n}");
  809. verifyFormat("for (var y: string of x) {\n x();\n}");
  810. verifyFormat("function x(y: {a?: number;} = {}): number {\n"
  811. " return 12;\n"
  812. "}");
  813. verifyFormat("((a: string, b: number): string => a + b);");
  814. verifyFormat("var x: (y: number) => string;");
  815. verifyFormat("var x: P<string, (a: number) => string>;");
  816. verifyFormat("var x = {y: function(): z { return 1; }};");
  817. verifyFormat("var x = {y: function(): {a: number} { return 1; }};");
  818. verifyFormat("function someFunc(args: string[]):\n"
  819. " {longReturnValue: string[]} {}",
  820. getGoogleJSStyleWithColumns(60));
  821. }
  822. TEST_F(FormatTestJS, UnionIntersectionTypes) {
  823. verifyFormat("let x: A|B = A | B;");
  824. verifyFormat("let x: A&B|C = A & B;");
  825. verifyFormat("let x: Foo<A|B> = new Foo<A|B>();");
  826. verifyFormat("function(x: A|B): C&D {}");
  827. verifyFormat("function(x: A|B = A | B): C&D {}");
  828. }
  829. TEST_F(FormatTestJS, ClassDeclarations) {
  830. verifyFormat("class C {\n x: string = 12;\n}");
  831. verifyFormat("class C {\n x(): string => 12;\n}");
  832. verifyFormat("class C {\n ['x' + 2]: string = 12;\n}");
  833. verifyFormat("class C {\n private x: string = 12;\n}");
  834. verifyFormat("class C {\n private static x: string = 12;\n}");
  835. verifyFormat("class C {\n static x(): string { return 'asd'; }\n}");
  836. verifyFormat("class C extends P implements I {}");
  837. verifyFormat("class C extends p.P implements i.I {}");
  838. verifyFormat("class Test {\n"
  839. " aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaaa):\n"
  840. " aaaaaaaaaaaaaaaaaaaaaa {}\n"
  841. "}");
  842. verifyFormat("foo = class Name {\n"
  843. " constructor() {}\n"
  844. "};");
  845. verifyFormat("foo = class {\n"
  846. " constructor() {}\n"
  847. "};");
  848. verifyFormat("class C {\n"
  849. " x: {y: Z;} = {};\n"
  850. " private y: {y: Z;} = {};\n"
  851. "}");
  852. // ':' is not a type declaration here.
  853. verifyFormat("class X {\n"
  854. " subs = {\n"
  855. " 'b': {\n"
  856. " 'c': 1,\n"
  857. " },\n"
  858. " };\n"
  859. "}");
  860. }
  861. TEST_F(FormatTestJS, InterfaceDeclarations) {
  862. verifyFormat("interface I {\n"
  863. " x: string;\n"
  864. " enum: string[];\n"
  865. " enum?: string[];\n"
  866. "}\n"
  867. "var y;");
  868. // Ensure that state is reset after parsing the interface.
  869. verifyFormat("interface a {}\n"
  870. "export function b() {}\n"
  871. "var x;");
  872. // Arrays of object type literals.
  873. verifyFormat("interface I {\n"
  874. " o: {}[];\n"
  875. "}");
  876. }
  877. TEST_F(FormatTestJS, EnumDeclarations) {
  878. verifyFormat("enum Foo {\n"
  879. " A = 1,\n"
  880. " B\n"
  881. "}");
  882. verifyFormat("export /* somecomment*/ enum Foo {\n"
  883. " A = 1,\n"
  884. " B\n"
  885. "}");
  886. verifyFormat("enum Foo {\n"
  887. " A = 1, // comment\n"
  888. " B\n"
  889. "}\n"
  890. "var x = 1;");
  891. }
  892. TEST_F(FormatTestJS, MetadataAnnotations) {
  893. verifyFormat("@A\nclass C {\n}");
  894. verifyFormat("@A({arg: 'value'})\nclass C {\n}");
  895. verifyFormat("@A\n@B\nclass C {\n}");
  896. verifyFormat("class C {\n @A x: string;\n}");
  897. verifyFormat("class C {\n"
  898. " @A\n"
  899. " private x(): string {\n"
  900. " return 'y';\n"
  901. " }\n"
  902. "}");
  903. verifyFormat("class C {\n"
  904. " private x(@A x: string) {}\n"
  905. "}");
  906. verifyFormat("class X {}\n"
  907. "class Y {}");
  908. }
  909. TEST_F(FormatTestJS, TypeAliases) {
  910. verifyFormat("type X = number;\n"
  911. "class C {}");
  912. verifyFormat("type X<Y> = Z<Y>;");
  913. verifyFormat("type X = {\n"
  914. " y: number\n"
  915. "};\n"
  916. "class C {}");
  917. }
  918. TEST_F(FormatTestJS, Modules) {
  919. verifyFormat("import SomeThing from 'some/module.js';");
  920. verifyFormat("import {X, Y} from 'some/module.js';");
  921. verifyFormat("import a, {X, Y} from 'some/module.js';");
  922. verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
  923. " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
  924. "} from 'some/module.js';");
  925. verifyFormat("import {X, Y,} from 'some/module.js';");
  926. verifyFormat("import {X as myLocalX, Y as myLocalY} from 'some/module.js';");
  927. verifyFormat("import * as lib from 'some/module.js';");
  928. verifyFormat("var x = {import: 1};\nx.import = 2;");
  929. verifyFormat("export function fn() {\n"
  930. " return 'fn';\n"
  931. "}");
  932. verifyFormat("export function A() {}\n"
  933. "export default function B() {}\n"
  934. "export function C() {}");
  935. verifyFormat("export default () => {\n"
  936. " let x = 1;\n"
  937. " return x;\n"
  938. "}");
  939. verifyFormat("export const x = 12;");
  940. verifyFormat("export default class X {}");
  941. verifyFormat("export {X, Y} from 'some/module.js';");
  942. verifyFormat("export {X, Y,} from 'some/module.js';");
  943. verifyFormat("export {SomeVeryLongExport as X, "
  944. "SomeOtherVeryLongExport as Y} from 'some/module.js';");
  945. // export without 'from' is wrapped.
  946. verifyFormat("export let someRatherLongVariableName =\n"
  947. " someSurprisinglyLongVariable + someOtherRatherLongVar;");
  948. // ... but not if from is just an identifier.
  949. verifyFormat("export {\n"
  950. " from as from,\n"
  951. " someSurprisinglyLongVariable\n"
  952. " as from\n"
  953. "};",
  954. getGoogleJSStyleWithColumns(20));
  955. verifyFormat("export class C {\n"
  956. " x: number;\n"
  957. " y: string;\n"
  958. "}");
  959. verifyFormat("export class X { y: number; }");
  960. verifyFormat("export abstract class X { y: number; }");
  961. verifyFormat("export default class X { y: number }");
  962. verifyFormat("export default function() {\n return 1;\n}");
  963. verifyFormat("export var x = 12;");
  964. verifyFormat("class C {}\n"
  965. "export function f() {}\n"
  966. "var v;");
  967. verifyFormat("export var x: number = 12;");
  968. verifyFormat("export const y = {\n"
  969. " a: 1,\n"
  970. " b: 2\n"
  971. "};");
  972. verifyFormat("export enum Foo {\n"
  973. " BAR,\n"
  974. " // adsdasd\n"
  975. " BAZ\n"
  976. "}");
  977. verifyFormat("export default [\n"
  978. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
  979. " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
  980. "];");
  981. verifyFormat("export default [];");
  982. verifyFormat("export default () => {};");
  983. verifyFormat("export interface Foo { foo: number; }\n"
  984. "export class Bar {\n"
  985. " blah(): string { return this.blah; };\n"
  986. "}");
  987. }
  988. TEST_F(FormatTestJS, TemplateStrings) {
  989. // Keeps any whitespace/indentation within the template string.
  990. verifyFormat("var x = `hello\n"
  991. " ${ name }\n"
  992. " !`;",
  993. "var x = `hello\n"
  994. " ${ name }\n"
  995. " !`;");
  996. verifyFormat("var x =\n"
  997. " `hello ${world}` >= some();",
  998. getGoogleJSStyleWithColumns(34)); // Barely doesn't fit.
  999. verifyFormat("var x = `hello ${world}` >= some();",
  1000. getGoogleJSStyleWithColumns(35)); // Barely fits.
  1001. verifyFormat("var x = `hellö ${wörld}` >= söme();",
  1002. getGoogleJSStyleWithColumns(35)); // Fits due to UTF-8.
  1003. verifyFormat("var x = `hello\n"
  1004. " ${world}` >=\n"
  1005. " some();",
  1006. "var x =\n"
  1007. " `hello\n"
  1008. " ${world}` >= some();",
  1009. getGoogleJSStyleWithColumns(21)); // Barely doesn't fit.
  1010. verifyFormat("var x = `hello\n"
  1011. " ${world}` >= some();",
  1012. "var x =\n"
  1013. " `hello\n"
  1014. " ${world}` >= some();",
  1015. getGoogleJSStyleWithColumns(22)); // Barely fits.
  1016. verifyFormat("var x =\n"
  1017. " `h`;",
  1018. getGoogleJSStyleWithColumns(11));
  1019. verifyFormat("var x =\n `multi\n line`;", "var x = `multi\n line`;",
  1020. getGoogleJSStyleWithColumns(13));
  1021. verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
  1022. " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`);");
  1023. // Repro for an obscure width-miscounting issue with template strings.
  1024. verifyFormat(
  1025. "someLongVariable =\n"
  1026. " "
  1027. "`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;",
  1028. "someLongVariable = "
  1029. "`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;");
  1030. // Make sure template strings get a proper ColumnWidth assigned, even if they
  1031. // are first token in line.
  1032. verifyFormat(
  1033. "var a = aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
  1034. " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;");
  1035. // Two template strings.
  1036. verifyFormat("var x = `hello` == `hello`;");
  1037. // Comments in template strings.
  1038. verifyFormat("var x = `//a`;\n"
  1039. "var y;",
  1040. "var x =\n `//a`;\n"
  1041. "var y ;");
  1042. verifyFormat("var x = `/*a`;\n"
  1043. "var y;",
  1044. "var x =\n `/*a`;\n"
  1045. "var y;");
  1046. // Unterminated string literals in a template string.
  1047. verifyFormat("var x = `'`; // comment with matching quote '\n"
  1048. "var y;");
  1049. verifyFormat("var x = `\"`; // comment with matching quote \"\n"
  1050. "var y;");
  1051. verifyFormat("it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa);",
  1052. "it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa) ;",
  1053. getGoogleJSStyleWithColumns(40));
  1054. // Backticks in a comment - not a template string.
  1055. verifyFormat("var x = 1 // `/*a`;\n"
  1056. " ;",
  1057. "var x =\n 1 // `/*a`;\n"
  1058. " ;");
  1059. verifyFormat("/* ` */ var x = 1; /* ` */", "/* ` */ var x\n= 1; /* ` */");
  1060. // Comment spans multiple template strings.
  1061. verifyFormat("var x = `/*a`;\n"
  1062. "var y = ` */ `;",
  1063. "var x =\n `/*a`;\n"
  1064. "var y =\n ` */ `;");
  1065. // Escaped backtick.
  1066. verifyFormat("var x = ` \\` a`;\n"
  1067. "var y;",
  1068. "var x = ` \\` a`;\n"
  1069. "var y;");
  1070. }
  1071. TEST_F(FormatTestJS, CastSyntax) {
  1072. verifyFormat("var x = <type>foo;");
  1073. verifyFormat("var x = foo as type;");
  1074. }
  1075. TEST_F(FormatTestJS, TypeArguments) {
  1076. verifyFormat("class X<Y> {}");
  1077. verifyFormat("new X<Y>();");
  1078. verifyFormat("foo<Y>(a);");
  1079. verifyFormat("var x: X<Y>[];");
  1080. verifyFormat("class C extends D<E> implements F<G>, H<I> {}");
  1081. verifyFormat("function f(a: List<any> = null) {}");
  1082. verifyFormat("function f(): List<any> {}");
  1083. verifyFormat("function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa():\n"
  1084. " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}");
  1085. verifyFormat("function aaaaaaaaaa(\n"
  1086. " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa,\n"
  1087. " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa):\n"
  1088. " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {}");
  1089. }
  1090. TEST_F(FormatTestJS, UserDefinedTypeGuards) {
  1091. verifyFormat(
  1092. "function foo(check: Object):\n"
  1093. " check is {foo: string, bar: string, baz: string, foobar: string} {\n"
  1094. " return 'bar' in check;\n"
  1095. "}\n");
  1096. }
  1097. TEST_F(FormatTestJS, OptionalTypes) {
  1098. verifyFormat("function x(a?: b, c?, d?) {}");
  1099. verifyFormat("class X {\n"
  1100. " y?: z;\n"
  1101. " z?;\n"
  1102. "}");
  1103. verifyFormat("interface X {\n"
  1104. " y?(): z;\n"
  1105. "}");
  1106. verifyFormat("x ? 1 : 2;");
  1107. verifyFormat("constructor({aa}: {\n"
  1108. " aa?: string,\n"
  1109. " aaaaaaaa?: string,\n"
  1110. " aaaaaaaaaaaaaaa?: boolean,\n"
  1111. " aaaaaa?: List<string>\n"
  1112. "}) {}");
  1113. }
  1114. TEST_F(FormatTestJS, IndexSignature) {
  1115. verifyFormat("var x: {[k: string]: v};");
  1116. }
  1117. TEST_F(FormatTestJS, WrapAfterParen) {
  1118. verifyFormat("xxxxxxxxxxx(\n"
  1119. " aaa, aaa);",
  1120. getGoogleJSStyleWithColumns(20));
  1121. verifyFormat("xxxxxxxxxxx(\n"
  1122. " aaa, aaa, aaa,\n"
  1123. " aaa, aaa, aaa);",
  1124. getGoogleJSStyleWithColumns(20));
  1125. verifyFormat("xxxxxxxxxxx(\n"
  1126. " aaaaaaaaaaaaaaaaaaaaaaaa,\n"
  1127. " function(x) {\n"
  1128. " y(); //\n"
  1129. " });",
  1130. getGoogleJSStyleWithColumns(40));
  1131. verifyFormat("while (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n"
  1132. " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}");
  1133. }
  1134. TEST_F(FormatTestJS, JSDocAnnotations) {
  1135. verifyFormat("/**\n"
  1136. " * @export {this.is.a.long.path.to.a.Type}\n"
  1137. " */",
  1138. "/**\n"
  1139. " * @export {this.is.a.long.path.to.a.Type}\n"
  1140. " */",
  1141. getGoogleJSStyleWithColumns(20));
  1142. }
  1143. TEST_F(FormatTestJS, RequoteStringsSingle) {
  1144. verifyFormat("var x = 'foo';", "var x = \"foo\";");
  1145. verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo'o'\";");
  1146. verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo\\'o'\";");
  1147. verifyFormat(
  1148. "var x =\n"
  1149. " 'foo\\'';",
  1150. // Code below is 15 chars wide, doesn't fit into the line with the
  1151. // \ escape added.
  1152. "var x = \"foo'\";", getGoogleJSStyleWithColumns(15));
  1153. // Removes no-longer needed \ escape from ".
  1154. verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";");
  1155. // Code below fits into 15 chars *after* removing the \ escape.
  1156. verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";",
  1157. getGoogleJSStyleWithColumns(15));
  1158. verifyFormat("// clang-format off\n"
  1159. "let x = \"double\";\n"
  1160. "// clang-format on\n"
  1161. "let x = 'single';\n",
  1162. "// clang-format off\n"
  1163. "let x = \"double\";\n"
  1164. "// clang-format on\n"
  1165. "let x = \"single\";\n");
  1166. }
  1167. TEST_F(FormatTestJS, RequoteStringsDouble) {
  1168. FormatStyle DoubleQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
  1169. DoubleQuotes.JavaScriptQuotes = FormatStyle::JSQS_Double;
  1170. verifyFormat("var x = \"foo\";", DoubleQuotes);
  1171. verifyFormat("var x = \"foo\";", "var x = 'foo';", DoubleQuotes);
  1172. verifyFormat("var x = \"fo'o\";", "var x = 'fo\\'o';", DoubleQuotes);
  1173. }
  1174. TEST_F(FormatTestJS, RequoteStringsLeave) {
  1175. FormatStyle LeaveQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
  1176. LeaveQuotes.JavaScriptQuotes = FormatStyle::JSQS_Leave;
  1177. verifyFormat("var x = \"foo\";", LeaveQuotes);
  1178. verifyFormat("var x = 'foo';", LeaveQuotes);
  1179. }
  1180. } // end namespace tooling
  1181. } // end namespace clang