printer.js 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776
  1. "use strict";
  2. var assert = require("assert");
  3. var sourceMap = require("source-map");
  4. var printComments = require("./comments").printComments;
  5. var linesModule = require("./lines");
  6. var fromString = linesModule.fromString;
  7. var concat = linesModule.concat;
  8. var normalizeOptions = require("./options").normalize;
  9. var getReprinter = require("./patcher").getReprinter;
  10. var types = require("./types");
  11. var namedTypes = types.namedTypes;
  12. var isString = types.builtInTypes.string;
  13. var isObject = types.builtInTypes.object;
  14. var FastPath = require("./fast-path");
  15. var util = require("./util");
  16. function PrintResult(code, sourceMap) {
  17. assert.ok(this instanceof PrintResult);
  18. isString.assert(code);
  19. this.code = code;
  20. if (sourceMap) {
  21. isObject.assert(sourceMap);
  22. this.map = sourceMap;
  23. }
  24. }
  25. var PRp = PrintResult.prototype;
  26. var warnedAboutToString = false;
  27. PRp.toString = function() {
  28. if (!warnedAboutToString) {
  29. console.warn(
  30. "Deprecation warning: recast.print now returns an object with " +
  31. "a .code property. You appear to be treating the object as a " +
  32. "string, which might still work but is strongly discouraged."
  33. );
  34. warnedAboutToString = true;
  35. }
  36. return this.code;
  37. };
  38. var emptyPrintResult = new PrintResult("");
  39. function Printer(originalOptions) {
  40. assert.ok(this instanceof Printer);
  41. var explicitTabWidth = originalOptions && originalOptions.tabWidth;
  42. var options = normalizeOptions(originalOptions);
  43. assert.notStrictEqual(options, originalOptions);
  44. // It's common for client code to pass the same options into both
  45. // recast.parse and recast.print, but the Printer doesn't need (and
  46. // can be confused by) options.sourceFileName, so we null it out.
  47. options.sourceFileName = null;
  48. function printWithComments(path) {
  49. assert.ok(path instanceof FastPath);
  50. return printComments(path, print);
  51. }
  52. function print(path, includeComments) {
  53. if (includeComments)
  54. return printWithComments(path);
  55. assert.ok(path instanceof FastPath);
  56. if (!explicitTabWidth) {
  57. var oldTabWidth = options.tabWidth;
  58. var loc = path.getNode().loc;
  59. if (loc && loc.lines && loc.lines.guessTabWidth) {
  60. options.tabWidth = loc.lines.guessTabWidth();
  61. var lines = maybeReprint(path);
  62. options.tabWidth = oldTabWidth;
  63. return lines;
  64. }
  65. }
  66. return maybeReprint(path);
  67. }
  68. function maybeReprint(path) {
  69. var reprinter = getReprinter(path);
  70. if (reprinter) {
  71. // Since the print function that we pass to the reprinter will
  72. // be used to print "new" nodes, it's tempting to think we
  73. // should pass printRootGenerically instead of print, to avoid
  74. // calling maybeReprint again, but that would be a mistake
  75. // because the new nodes might not be entirely new, but merely
  76. // moved from elsewhere in the AST. The print function is the
  77. // right choice because it gives us the opportunity to reprint
  78. // such nodes using their original source.
  79. return maybeAddParens(path, reprinter(print));
  80. }
  81. return printRootGenerically(path);
  82. }
  83. // Print the root node generically, but then resume reprinting its
  84. // children non-generically.
  85. function printRootGenerically(path, includeComments) {
  86. return includeComments
  87. ? printComments(path, printRootGenerically)
  88. : genericPrint(path, options, printWithComments);
  89. }
  90. // Print the entire AST generically.
  91. function printGenerically(path) {
  92. return genericPrint(path, options, printGenerically);
  93. }
  94. this.print = function(ast) {
  95. if (!ast) {
  96. return emptyPrintResult;
  97. }
  98. var lines = print(FastPath.from(ast), true);
  99. return new PrintResult(
  100. lines.toString(options),
  101. util.composeSourceMaps(
  102. options.inputSourceMap,
  103. lines.getSourceMap(
  104. options.sourceMapName,
  105. options.sourceRoot
  106. )
  107. )
  108. );
  109. };
  110. this.printGenerically = function(ast) {
  111. if (!ast) {
  112. return emptyPrintResult;
  113. }
  114. var path = FastPath.from(ast);
  115. var oldReuseWhitespace = options.reuseWhitespace;
  116. // Do not reuse whitespace (or anything else, for that matter)
  117. // when printing generically.
  118. options.reuseWhitespace = false;
  119. // TODO Allow printing of comments?
  120. var pr = new PrintResult(printGenerically(path).toString(options));
  121. options.reuseWhitespace = oldReuseWhitespace;
  122. return pr;
  123. };
  124. }
  125. exports.Printer = Printer;
  126. function maybeAddParens(path, lines) {
  127. return path.needsParens() ? concat(["(", lines, ")"]) : lines;
  128. }
  129. function genericPrint(path, options, printPath) {
  130. assert.ok(path instanceof FastPath);
  131. var node = path.getValue();
  132. var parts = [];
  133. var needsParens = false;
  134. var linesWithoutParens =
  135. genericPrintNoParens(path, options, printPath);
  136. if (! node || linesWithoutParens.isEmpty()) {
  137. return linesWithoutParens;
  138. }
  139. if (node.decorators &&
  140. node.decorators.length > 0 &&
  141. // If the parent node is an export declaration, it will be
  142. // responsible for printing node.decorators.
  143. ! util.getParentExportDeclaration(path)) {
  144. path.each(function(decoratorPath) {
  145. parts.push(printPath(decoratorPath), "\n");
  146. }, "decorators");
  147. } else if (util.isExportDeclaration(node) &&
  148. node.declaration &&
  149. node.declaration.decorators) {
  150. // Export declarations are responsible for printing any decorators
  151. // that logically apply to node.declaration.
  152. path.each(function(decoratorPath) {
  153. parts.push(printPath(decoratorPath), "\n");
  154. }, "declaration", "decorators");
  155. } else {
  156. // Nodes with decorators can't have parentheses, so we can avoid
  157. // computing path.needsParens() except in this case.
  158. needsParens = path.needsParens();
  159. }
  160. if (needsParens) {
  161. parts.unshift("(");
  162. }
  163. parts.push(linesWithoutParens);
  164. if (needsParens) {
  165. parts.push(")");
  166. }
  167. return concat(parts);
  168. }
  169. function genericPrintNoParens(path, options, print) {
  170. var n = path.getValue();
  171. if (!n) {
  172. return fromString("");
  173. }
  174. if (typeof n === "string") {
  175. return fromString(n, options);
  176. }
  177. namedTypes.Printable.assert(n);
  178. var parts = [];
  179. switch (n.type) {
  180. case "File":
  181. return path.call(print, "program");
  182. case "Program":
  183. // Babel 6
  184. if (n.directives) {
  185. path.each(function(childPath) {
  186. parts.push(print(childPath), ";\n");
  187. }, "directives");
  188. }
  189. parts.push(path.call(function(bodyPath) {
  190. return printStatementSequence(bodyPath, options, print);
  191. }, "body"));
  192. return concat(parts);
  193. case "Noop": // Babel extension.
  194. case "EmptyStatement":
  195. return fromString("");
  196. case "ExpressionStatement":
  197. return concat([path.call(print, "expression"), ";"]);
  198. case "ParenthesizedExpression": // Babel extension.
  199. return concat(["(", path.call(print, "expression"), ")"]);
  200. case "BinaryExpression":
  201. case "LogicalExpression":
  202. case "AssignmentExpression":
  203. return fromString(" ").join([
  204. path.call(print, "left"),
  205. n.operator,
  206. path.call(print, "right")
  207. ]);
  208. case "AssignmentPattern":
  209. return concat([
  210. path.call(print, "left"),
  211. " = ",
  212. path.call(print, "right")
  213. ]);
  214. case "MemberExpression":
  215. case "OptionalMemberExpression":
  216. parts.push(path.call(print, "object"));
  217. var property = path.call(print, "property");
  218. var optional = n.type === "OptionalMemberExpression";
  219. if (n.computed) {
  220. parts.push(optional ? "?.[" : "[", property, "]");
  221. } else {
  222. parts.push(optional ? "?." : ".", property);
  223. }
  224. return concat(parts);
  225. case "MetaProperty":
  226. return concat([
  227. path.call(print, "meta"),
  228. ".",
  229. path.call(print, "property")
  230. ]);
  231. case "BindExpression":
  232. if (n.object) {
  233. parts.push(path.call(print, "object"));
  234. }
  235. parts.push("::", path.call(print, "callee"));
  236. return concat(parts);
  237. case "Path":
  238. return fromString(".").join(n.body);
  239. case "Identifier":
  240. return concat([
  241. fromString(n.name, options),
  242. n.optional ? "?" : "",
  243. path.call(print, "typeAnnotation")
  244. ]);
  245. case "SpreadElement":
  246. case "SpreadElementPattern":
  247. case "RestProperty": // Babel 6 for ObjectPattern
  248. case "SpreadProperty":
  249. case "SpreadPropertyPattern":
  250. case "ObjectTypeSpreadProperty":
  251. case "RestElement":
  252. return concat([
  253. "...",
  254. path.call(print, "argument"),
  255. path.call(print, "typeAnnotation")
  256. ]);
  257. case "FunctionDeclaration":
  258. case "FunctionExpression":
  259. case "TSDeclareFunction":
  260. if (n.declare) {
  261. parts.push("declare ");
  262. }
  263. if (n.async) {
  264. parts.push("async ");
  265. }
  266. parts.push("function");
  267. if (n.generator)
  268. parts.push("*");
  269. if (n.id) {
  270. parts.push(
  271. " ",
  272. path.call(print, "id"),
  273. path.call(print, "typeParameters")
  274. );
  275. }
  276. parts.push(
  277. "(",
  278. printFunctionParams(path, options, print),
  279. ")",
  280. path.call(print, "returnType")
  281. );
  282. if (n.body) {
  283. parts.push(" ", path.call(print, "body"));
  284. }
  285. return concat(parts);
  286. case "ArrowFunctionExpression":
  287. if (n.async) {
  288. parts.push("async ");
  289. }
  290. if (n.typeParameters) {
  291. parts.push(path.call(print, "typeParameters"));
  292. }
  293. if (! options.arrowParensAlways &&
  294. n.params.length === 1 &&
  295. ! n.rest &&
  296. n.params[0].type === 'Identifier' &&
  297. ! n.params[0].typeAnnotation &&
  298. ! n.returnType) {
  299. parts.push(path.call(print, "params", 0));
  300. } else {
  301. parts.push(
  302. "(",
  303. printFunctionParams(path, options, print),
  304. ")",
  305. path.call(print, "returnType")
  306. );
  307. }
  308. parts.push(" => ", path.call(print, "body"));
  309. return concat(parts);
  310. case "MethodDefinition":
  311. return printMethod(path, options, print);
  312. case "YieldExpression":
  313. parts.push("yield");
  314. if (n.delegate)
  315. parts.push("*");
  316. if (n.argument)
  317. parts.push(" ", path.call(print, "argument"));
  318. return concat(parts);
  319. case "AwaitExpression":
  320. parts.push("await");
  321. if (n.all)
  322. parts.push("*");
  323. if (n.argument)
  324. parts.push(" ", path.call(print, "argument"));
  325. return concat(parts);
  326. case "ModuleDeclaration":
  327. parts.push("module", path.call(print, "id"));
  328. if (n.source) {
  329. assert.ok(!n.body);
  330. parts.push("from", path.call(print, "source"));
  331. } else {
  332. parts.push(path.call(print, "body"));
  333. }
  334. return fromString(" ").join(parts);
  335. case "ImportSpecifier":
  336. if (n.importKind && n.importKind !== "value") {
  337. parts.push(n.importKind + " ");
  338. }
  339. if (n.imported) {
  340. parts.push(path.call(print, "imported"));
  341. if (n.local &&
  342. n.local.name !== n.imported.name) {
  343. parts.push(" as ", path.call(print, "local"));
  344. }
  345. } else if (n.id) {
  346. parts.push(path.call(print, "id"));
  347. if (n.name) {
  348. parts.push(" as ", path.call(print, "name"));
  349. }
  350. }
  351. return concat(parts);
  352. case "ExportSpecifier":
  353. if (n.local) {
  354. parts.push(path.call(print, "local"));
  355. if (n.exported &&
  356. n.exported.name !== n.local.name) {
  357. parts.push(" as ", path.call(print, "exported"));
  358. }
  359. } else if (n.id) {
  360. parts.push(path.call(print, "id"));
  361. if (n.name) {
  362. parts.push(" as ", path.call(print, "name"));
  363. }
  364. }
  365. return concat(parts);
  366. case "ExportBatchSpecifier":
  367. return fromString("*");
  368. case "ImportNamespaceSpecifier":
  369. parts.push("* as ");
  370. if (n.local) {
  371. parts.push(path.call(print, "local"));
  372. } else if (n.id) {
  373. parts.push(path.call(print, "id"));
  374. }
  375. return concat(parts);
  376. case "ImportDefaultSpecifier":
  377. if (n.local) {
  378. return path.call(print, "local");
  379. }
  380. return path.call(print, "id");
  381. case "TSExportAssignment":
  382. return concat(["export = ", path.call(print, "expression")]);
  383. case "ExportDeclaration":
  384. case "ExportDefaultDeclaration":
  385. case "ExportNamedDeclaration":
  386. return printExportDeclaration(path, options, print);
  387. case "ExportAllDeclaration":
  388. parts.push("export *");
  389. if (n.exported) {
  390. parts.push(" as ", path.call(print, "exported"));
  391. }
  392. parts.push(
  393. " from ",
  394. path.call(print, "source")
  395. );
  396. return concat(parts);
  397. case "TSNamespaceExportDeclaration":
  398. parts.push("export as namespace ", path.call(print, "id"));
  399. return maybeAddSemicolon(concat(parts));
  400. case "ExportNamespaceSpecifier":
  401. return concat(["* as ", path.call(print, "exported")]);
  402. case "ExportDefaultSpecifier":
  403. return path.call(print, "exported");
  404. case "Import":
  405. return fromString("import", options);
  406. case "ImportDeclaration": {
  407. parts.push("import ");
  408. if (n.importKind && n.importKind !== "value") {
  409. parts.push(n.importKind + " ");
  410. }
  411. if (n.specifiers &&
  412. n.specifiers.length > 0) {
  413. const unbracedSpecifiers = [];
  414. const bracedSpecifiers = [];
  415. path.each(function (specifierPath) {
  416. const spec = specifierPath.getValue();
  417. if (spec.type === "ImportSpecifier") {
  418. bracedSpecifiers.push(print(specifierPath));
  419. } else if (spec.type === "ImportDefaultSpecifier" ||
  420. spec.type === "ImportNamespaceSpecifier") {
  421. unbracedSpecifiers.push(print(specifierPath));
  422. }
  423. }, "specifiers");
  424. unbracedSpecifiers.forEach((lines, i) => {
  425. if (i > 0) {
  426. parts.push(", ");
  427. }
  428. parts.push(lines);
  429. });
  430. if (bracedSpecifiers.length > 0) {
  431. let lines = fromString(", ").join(bracedSpecifiers);
  432. if (lines.getLineLength(1) > options.wrapColumn) {
  433. lines = concat([
  434. fromString(",\n").join(
  435. bracedSpecifiers
  436. ).indent(options.tabWidth),
  437. ","
  438. ]);
  439. }
  440. if (unbracedSpecifiers.length > 0) {
  441. parts.push(", ");
  442. }
  443. if (lines.length > 1) {
  444. parts.push("{\n", lines, "\n}");
  445. } else if (options.objectCurlySpacing) {
  446. parts.push("{ ", lines, " }");
  447. } else {
  448. parts.push("{", lines, "}");
  449. }
  450. }
  451. parts.push(" from ");
  452. }
  453. parts.push(path.call(print, "source"), ";");
  454. return concat(parts);
  455. }
  456. case "BlockStatement":
  457. var naked = path.call(function(bodyPath) {
  458. return printStatementSequence(bodyPath, options, print);
  459. }, "body");
  460. if (naked.isEmpty()) {
  461. if (!n.directives || n.directives.length === 0) {
  462. return fromString("{}");
  463. }
  464. }
  465. parts.push("{\n");
  466. // Babel 6
  467. if (n.directives) {
  468. path.each(function(childPath) {
  469. parts.push(
  470. print(childPath).indent(options.tabWidth),
  471. ";",
  472. n.directives.length > 1 || !naked.isEmpty() ? "\n" : ""
  473. );
  474. }, "directives");
  475. }
  476. parts.push(naked.indent(options.tabWidth));
  477. parts.push("\n}");
  478. return concat(parts);
  479. case "ReturnStatement":
  480. parts.push("return");
  481. if (n.argument) {
  482. var argLines = path.call(print, "argument");
  483. if (argLines.startsWithComment() ||
  484. (argLines.length > 1 &&
  485. namedTypes.JSXElement &&
  486. namedTypes.JSXElement.check(n.argument)
  487. )) {
  488. parts.push(
  489. " (\n",
  490. argLines.indent(options.tabWidth),
  491. "\n)"
  492. );
  493. } else {
  494. parts.push(" ", argLines);
  495. }
  496. }
  497. parts.push(";");
  498. return concat(parts);
  499. case "CallExpression":
  500. case "OptionalCallExpression":
  501. var parts = [path.call(print, "callee")];
  502. if (n.type === "OptionalCallExpression" &&
  503. n.callee.type !== "OptionalMemberExpression") {
  504. parts.push("?.");
  505. }
  506. parts.push(printArgumentsList(path, options, print));
  507. return concat(parts);
  508. case "ObjectExpression":
  509. case "ObjectPattern":
  510. case "ObjectTypeAnnotation":
  511. var allowBreak = false;
  512. var isTypeAnnotation = n.type === "ObjectTypeAnnotation";
  513. var separator = options.flowObjectCommas ? "," : (isTypeAnnotation ? ";" : ",");
  514. var fields = [];
  515. if (isTypeAnnotation) {
  516. fields.push("indexers", "callProperties");
  517. }
  518. fields.push("properties");
  519. var len = 0;
  520. fields.forEach(function(field) {
  521. len += n[field].length;
  522. });
  523. var oneLine = (isTypeAnnotation && len === 1) || len === 0;
  524. var leftBrace = n.exact ? "{|" : "{";
  525. var rightBrace = n.exact ? "|}" : "}";
  526. parts.push(oneLine ? leftBrace : leftBrace + "\n");
  527. var leftBraceIndex = parts.length - 1;
  528. var i = 0;
  529. fields.forEach(function(field) {
  530. path.each(function(childPath) {
  531. var lines = print(childPath);
  532. if (!oneLine) {
  533. lines = lines.indent(options.tabWidth);
  534. }
  535. var multiLine = !isTypeAnnotation && lines.length > 1;
  536. if (multiLine && allowBreak) {
  537. // Similar to the logic for BlockStatement.
  538. parts.push("\n");
  539. }
  540. parts.push(lines);
  541. if (i < len - 1) {
  542. // Add an extra line break if the previous object property
  543. // had a multi-line value.
  544. parts.push(separator + (multiLine ? "\n\n" : "\n"));
  545. allowBreak = !multiLine;
  546. } else if (len !== 1 && isTypeAnnotation) {
  547. parts.push(separator);
  548. } else if (!oneLine && util.isTrailingCommaEnabled(options, "objects")) {
  549. parts.push(separator);
  550. }
  551. i++;
  552. }, field);
  553. });
  554. parts.push(oneLine ? rightBrace : "\n" + rightBrace);
  555. if (i !== 0 && oneLine && options.objectCurlySpacing) {
  556. parts[leftBraceIndex] = leftBrace + " ";
  557. parts[parts.length - 1] = " " + rightBrace;
  558. }
  559. return concat(parts);
  560. case "PropertyPattern":
  561. return concat([
  562. path.call(print, "key"),
  563. ": ",
  564. path.call(print, "pattern")
  565. ]);
  566. case "ObjectProperty": // Babel 6
  567. case "Property": // Non-standard AST node type.
  568. if (n.method || n.kind === "get" || n.kind === "set") {
  569. return printMethod(path, options, print);
  570. }
  571. var key = path.call(print, "key");
  572. if (n.computed) {
  573. parts.push("[", key, "]");
  574. } else {
  575. parts.push(key);
  576. }
  577. if (! n.shorthand) {
  578. parts.push(": ", path.call(print, "value"));
  579. }
  580. return concat(parts);
  581. case "ClassMethod": // Babel 6
  582. case "ObjectMethod": // Babel 6
  583. case "TSDeclareMethod":
  584. return printMethod(path, options, print);
  585. case "Decorator":
  586. return concat(["@", path.call(print, "expression")]);
  587. case "ArrayExpression":
  588. case "ArrayPattern":
  589. var elems = n.elements,
  590. len = elems.length;
  591. var printed = path.map(print, "elements");
  592. var joined = fromString(", ").join(printed);
  593. var oneLine = joined.getLineLength(1) <= options.wrapColumn;
  594. if (oneLine) {
  595. if (options.arrayBracketSpacing) {
  596. parts.push("[ ");
  597. } else {
  598. parts.push("[");
  599. }
  600. } else {
  601. parts.push("[\n");
  602. }
  603. path.each(function(elemPath) {
  604. var i = elemPath.getName();
  605. var elem = elemPath.getValue();
  606. if (!elem) {
  607. // If the array expression ends with a hole, that hole
  608. // will be ignored by the interpreter, but if it ends with
  609. // two (or more) holes, we need to write out two (or more)
  610. // commas so that the resulting code is interpreted with
  611. // both (all) of the holes.
  612. parts.push(",");
  613. } else {
  614. var lines = printed[i];
  615. if (oneLine) {
  616. if (i > 0)
  617. parts.push(" ");
  618. } else {
  619. lines = lines.indent(options.tabWidth);
  620. }
  621. parts.push(lines);
  622. if (i < len - 1 || (!oneLine && util.isTrailingCommaEnabled(options, "arrays")))
  623. parts.push(",");
  624. if (!oneLine)
  625. parts.push("\n");
  626. }
  627. }, "elements");
  628. if (oneLine && options.arrayBracketSpacing) {
  629. parts.push(" ]");
  630. } else {
  631. parts.push("]");
  632. }
  633. return concat(parts);
  634. case "SequenceExpression":
  635. return fromString(", ").join(path.map(print, "expressions"));
  636. case "ThisExpression":
  637. return fromString("this");
  638. case "Super":
  639. return fromString("super");
  640. case "NullLiteral": // Babel 6 Literal split
  641. return fromString("null");
  642. case "RegExpLiteral": // Babel 6 Literal split
  643. return fromString(n.extra.raw);
  644. case "BigIntLiteral": // Babel 7 Literal split
  645. return fromString(n.value + "n");
  646. case "NumericLiteral": // Babel 6 Literal Split
  647. // Keep original representation for numeric values not in base 10.
  648. if (n.extra &&
  649. typeof n.extra.raw === "string" &&
  650. Number(n.extra.raw) === n.value) {
  651. return fromString(n.extra.raw, options);
  652. }
  653. return fromString(n.value, options);
  654. case "BooleanLiteral": // Babel 6 Literal split
  655. case "StringLiteral": // Babel 6 Literal split
  656. case "Literal":
  657. // Numeric values may be in bases other than 10. Use their raw
  658. // representation if equivalent.
  659. if (typeof n.value === "number" &&
  660. typeof n.raw === "string" &&
  661. Number(n.raw) === n.value) {
  662. return fromString(n.raw, options);
  663. }
  664. if (typeof n.value !== "string") {
  665. return fromString(n.value, options);
  666. }
  667. return fromString(nodeStr(n.value, options), options);
  668. case "Directive": // Babel 6
  669. return path.call(print, "value");
  670. case "DirectiveLiteral": // Babel 6
  671. return fromString(nodeStr(n.value, options));
  672. case "ModuleSpecifier":
  673. if (n.local) {
  674. throw new Error(
  675. "The ESTree ModuleSpecifier type should be abstract"
  676. );
  677. }
  678. // The Esprima ModuleSpecifier type is just a string-valued
  679. // Literal identifying the imported-from module.
  680. return fromString(nodeStr(n.value, options), options);
  681. case "UnaryExpression":
  682. parts.push(n.operator);
  683. if (/[a-z]$/.test(n.operator))
  684. parts.push(" ");
  685. parts.push(path.call(print, "argument"));
  686. return concat(parts);
  687. case "UpdateExpression":
  688. parts.push(
  689. path.call(print, "argument"),
  690. n.operator
  691. );
  692. if (n.prefix)
  693. parts.reverse();
  694. return concat(parts);
  695. case "ConditionalExpression":
  696. return concat([
  697. "(", path.call(print, "test"),
  698. " ? ", path.call(print, "consequent"),
  699. " : ", path.call(print, "alternate"), ")"
  700. ]);
  701. case "NewExpression":
  702. parts.push("new ", path.call(print, "callee"));
  703. var args = n.arguments;
  704. if (args) {
  705. parts.push(printArgumentsList(path, options, print));
  706. }
  707. return concat(parts);
  708. case "VariableDeclaration":
  709. if (n.declare) {
  710. parts.push("declare ");
  711. }
  712. parts.push(n.kind, " ");
  713. var maxLen = 0;
  714. var printed = path.map(function(childPath) {
  715. var lines = print(childPath);
  716. maxLen = Math.max(lines.length, maxLen);
  717. return lines;
  718. }, "declarations");
  719. if (maxLen === 1) {
  720. parts.push(fromString(", ").join(printed));
  721. } else if (printed.length > 1 ) {
  722. parts.push(
  723. fromString(",\n").join(printed)
  724. .indentTail(n.kind.length + 1)
  725. );
  726. } else {
  727. parts.push(printed[0]);
  728. }
  729. // We generally want to terminate all variable declarations with a
  730. // semicolon, except when they are children of for loops.
  731. var parentNode = path.getParentNode();
  732. if (!namedTypes.ForStatement.check(parentNode) &&
  733. !namedTypes.ForInStatement.check(parentNode) &&
  734. !(namedTypes.ForOfStatement &&
  735. namedTypes.ForOfStatement.check(parentNode)) &&
  736. !(namedTypes.ForAwaitStatement &&
  737. namedTypes.ForAwaitStatement.check(parentNode))) {
  738. parts.push(";");
  739. }
  740. return concat(parts);
  741. case "VariableDeclarator":
  742. return n.init ? fromString(" = ").join([
  743. path.call(print, "id"),
  744. path.call(print, "init")
  745. ]) : path.call(print, "id");
  746. case "WithStatement":
  747. return concat([
  748. "with (",
  749. path.call(print, "object"),
  750. ") ",
  751. path.call(print, "body")
  752. ]);
  753. case "IfStatement":
  754. var con = adjustClause(path.call(print, "consequent"), options),
  755. parts = ["if (", path.call(print, "test"), ")", con];
  756. if (n.alternate)
  757. parts.push(
  758. endsWithBrace(con) ? " else" : "\nelse",
  759. adjustClause(path.call(print, "alternate"), options));
  760. return concat(parts);
  761. case "ForStatement":
  762. // TODO Get the for (;;) case right.
  763. var init = path.call(print, "init"),
  764. sep = init.length > 1 ? ";\n" : "; ",
  765. forParen = "for (",
  766. indented = fromString(sep).join([
  767. init,
  768. path.call(print, "test"),
  769. path.call(print, "update")
  770. ]).indentTail(forParen.length),
  771. head = concat([forParen, indented, ")"]),
  772. clause = adjustClause(path.call(print, "body"), options),
  773. parts = [head];
  774. if (head.length > 1) {
  775. parts.push("\n");
  776. clause = clause.trimLeft();
  777. }
  778. parts.push(clause);
  779. return concat(parts);
  780. case "WhileStatement":
  781. return concat([
  782. "while (",
  783. path.call(print, "test"),
  784. ")",
  785. adjustClause(path.call(print, "body"), options)
  786. ]);
  787. case "ForInStatement":
  788. // Note: esprima can't actually parse "for each (".
  789. return concat([
  790. n.each ? "for each (" : "for (",
  791. path.call(print, "left"),
  792. " in ",
  793. path.call(print, "right"),
  794. ")",
  795. adjustClause(path.call(print, "body"), options)
  796. ]);
  797. case "ForOfStatement":
  798. case "ForAwaitStatement":
  799. parts.push("for ");
  800. if (n.await || n.type === "ForAwaitStatement") {
  801. parts.push("await ");
  802. }
  803. parts.push(
  804. "(",
  805. path.call(print, "left"),
  806. " of ",
  807. path.call(print, "right"),
  808. ")",
  809. adjustClause(path.call(print, "body"), options)
  810. );
  811. return concat(parts);
  812. case "DoWhileStatement":
  813. var doBody = concat([
  814. "do",
  815. adjustClause(path.call(print, "body"), options)
  816. ]), parts = [doBody];
  817. if (endsWithBrace(doBody))
  818. parts.push(" while");
  819. else
  820. parts.push("\nwhile");
  821. parts.push(" (", path.call(print, "test"), ");");
  822. return concat(parts);
  823. case "DoExpression":
  824. var statements = path.call(function(bodyPath) {
  825. return printStatementSequence(bodyPath, options, print);
  826. }, "body");
  827. return concat([
  828. "do {\n",
  829. statements.indent(options.tabWidth),
  830. "\n}"
  831. ]);
  832. case "BreakStatement":
  833. parts.push("break");
  834. if (n.label)
  835. parts.push(" ", path.call(print, "label"));
  836. parts.push(";");
  837. return concat(parts);
  838. case "ContinueStatement":
  839. parts.push("continue");
  840. if (n.label)
  841. parts.push(" ", path.call(print, "label"));
  842. parts.push(";");
  843. return concat(parts);
  844. case "LabeledStatement":
  845. return concat([
  846. path.call(print, "label"),
  847. ":\n",
  848. path.call(print, "body")
  849. ]);
  850. case "TryStatement":
  851. parts.push(
  852. "try ",
  853. path.call(print, "block")
  854. );
  855. if (n.handler) {
  856. parts.push(" ", path.call(print, "handler"));
  857. } else if (n.handlers) {
  858. path.each(function(handlerPath) {
  859. parts.push(" ", print(handlerPath));
  860. }, "handlers");
  861. }
  862. if (n.finalizer) {
  863. parts.push(" finally ", path.call(print, "finalizer"));
  864. }
  865. return concat(parts);
  866. case "CatchClause":
  867. parts.push("catch ");
  868. if (n.param) {
  869. parts.push("(", path.call(print, "param"));
  870. }
  871. if (n.guard) {
  872. // Note: esprima does not recognize conditional catch clauses.
  873. parts.push(" if ", path.call(print, "guard"));
  874. }
  875. if (n.param) {
  876. parts.push(") ");
  877. }
  878. parts.push(path.call(print, "body"));
  879. return concat(parts);
  880. case "ThrowStatement":
  881. return concat(["throw ", path.call(print, "argument"), ";"]);
  882. case "SwitchStatement":
  883. return concat([
  884. "switch (",
  885. path.call(print, "discriminant"),
  886. ") {\n",
  887. fromString("\n").join(path.map(print, "cases")),
  888. "\n}"
  889. ]);
  890. // Note: ignoring n.lexical because it has no printing consequences.
  891. case "SwitchCase":
  892. if (n.test)
  893. parts.push("case ", path.call(print, "test"), ":");
  894. else
  895. parts.push("default:");
  896. if (n.consequent.length > 0) {
  897. parts.push("\n", path.call(function(consequentPath) {
  898. return printStatementSequence(consequentPath, options, print);
  899. }, "consequent").indent(options.tabWidth));
  900. }
  901. return concat(parts);
  902. case "DebuggerStatement":
  903. return fromString("debugger;");
  904. // JSX extensions below.
  905. case "JSXAttribute":
  906. parts.push(path.call(print, "name"));
  907. if (n.value)
  908. parts.push("=", path.call(print, "value"));
  909. return concat(parts);
  910. case "JSXIdentifier":
  911. return fromString(n.name, options);
  912. case "JSXNamespacedName":
  913. return fromString(":").join([
  914. path.call(print, "namespace"),
  915. path.call(print, "name")
  916. ]);
  917. case "JSXMemberExpression":
  918. return fromString(".").join([
  919. path.call(print, "object"),
  920. path.call(print, "property")
  921. ]);
  922. case "JSXSpreadAttribute":
  923. return concat(["{...", path.call(print, "argument"), "}"]);
  924. case "JSXSpreadChild":
  925. return concat(["{...", path.call(print, "expression"), "}"]);
  926. case "JSXExpressionContainer":
  927. return concat(["{", path.call(print, "expression"), "}"]);
  928. case "JSXElement":
  929. case "JSXFragment":
  930. var openingPropName = "opening" + (
  931. n.type === "JSXElement" ? "Element" : "Fragment");
  932. var closingPropName = "closing" + (
  933. n.type === "JSXElement" ? "Element" : "Fragment");
  934. var openingLines = path.call(print, openingPropName);
  935. if (n[openingPropName].selfClosing) {
  936. assert.ok(
  937. !n[closingPropName],
  938. "unexpected " + closingPropName + " element in self-closing " + n.type
  939. );
  940. return openingLines;
  941. }
  942. var childLines = concat(
  943. path.map(function(childPath) {
  944. var child = childPath.getValue();
  945. if (namedTypes.Literal.check(child) &&
  946. typeof child.value === "string") {
  947. if (/\S/.test(child.value)) {
  948. return child.value.replace(/^\s+|\s+$/g, "");
  949. } else if (/\n/.test(child.value)) {
  950. return "\n";
  951. }
  952. }
  953. return print(childPath);
  954. }, "children")
  955. ).indentTail(options.tabWidth);
  956. var closingLines = path.call(print, closingPropName);
  957. return concat([
  958. openingLines,
  959. childLines,
  960. closingLines
  961. ]);
  962. case "JSXOpeningElement":
  963. parts.push("<", path.call(print, "name"));
  964. var attrParts = [];
  965. path.each(function(attrPath) {
  966. attrParts.push(" ", print(attrPath));
  967. }, "attributes");
  968. var attrLines = concat(attrParts);
  969. var needLineWrap = (
  970. attrLines.length > 1 ||
  971. attrLines.getLineLength(1) > options.wrapColumn
  972. );
  973. if (needLineWrap) {
  974. attrParts.forEach(function(part, i) {
  975. if (part === " ") {
  976. assert.strictEqual(i % 2, 0);
  977. attrParts[i] = "\n";
  978. }
  979. });
  980. attrLines = concat(attrParts).indentTail(options.tabWidth);
  981. }
  982. parts.push(attrLines, n.selfClosing ? " />" : ">");
  983. return concat(parts);
  984. case "JSXClosingElement":
  985. return concat(["</", path.call(print, "name"), ">"]);
  986. case "JSXOpeningFragment":
  987. return fromString("<>");
  988. case "JSXClosingFragment":
  989. return fromString("</>")
  990. case "JSXText":
  991. return fromString(n.value, options);
  992. case "JSXEmptyExpression":
  993. return fromString("");
  994. case "TypeAnnotatedIdentifier":
  995. return concat([
  996. path.call(print, "annotation"),
  997. " ",
  998. path.call(print, "identifier")
  999. ]);
  1000. case "ClassBody":
  1001. if (n.body.length === 0) {
  1002. return fromString("{}");
  1003. }
  1004. return concat([
  1005. "{\n",
  1006. path.call(function(bodyPath) {
  1007. return printStatementSequence(bodyPath, options, print);
  1008. }, "body").indent(options.tabWidth),
  1009. "\n}"
  1010. ]);
  1011. case "ClassPropertyDefinition":
  1012. parts.push("static ", path.call(print, "definition"));
  1013. if (!namedTypes.MethodDefinition.check(n.definition))
  1014. parts.push(";");
  1015. return concat(parts);
  1016. case "ClassProperty":
  1017. if (typeof n.accessibility === "string") {
  1018. parts.push(n.accessibility, " ");
  1019. }
  1020. if (n.static) {
  1021. parts.push("static ");
  1022. }
  1023. if (n.abstract) {
  1024. parts.push("abstract ");
  1025. }
  1026. if (n.readonly) {
  1027. parts.push("readonly ");
  1028. }
  1029. var key = path.call(print, "key");
  1030. if (n.computed) {
  1031. key = concat(["[", key, "]"]);
  1032. }
  1033. if (n.variance) {
  1034. key = concat([printVariance(path, print), key]);
  1035. }
  1036. parts.push(key);
  1037. if (n.optional) {
  1038. parts.push("?");
  1039. }
  1040. if (n.typeAnnotation) {
  1041. parts.push(path.call(print, "typeAnnotation"));
  1042. }
  1043. if (n.value) {
  1044. parts.push(" = ", path.call(print, "value"));
  1045. }
  1046. parts.push(";");
  1047. return concat(parts);
  1048. case "ClassDeclaration":
  1049. case "ClassExpression":
  1050. if (n.declare) {
  1051. parts.push("declare ");
  1052. }
  1053. if (n.abstract) {
  1054. parts.push("abstract ");
  1055. }
  1056. parts.push("class");
  1057. if (n.id) {
  1058. parts.push(
  1059. " ",
  1060. path.call(print, "id")
  1061. );
  1062. }
  1063. if (n.typeParameters) {
  1064. parts.push(path.call(print, "typeParameters"));
  1065. }
  1066. if (n.superClass) {
  1067. parts.push(
  1068. " extends ",
  1069. path.call(print, "superClass"),
  1070. path.call(print, "superTypeParameters")
  1071. );
  1072. }
  1073. if (n["implements"] && n['implements'].length > 0) {
  1074. parts.push(
  1075. " implements ",
  1076. fromString(", ").join(path.map(print, "implements"))
  1077. );
  1078. }
  1079. parts.push(" ", path.call(print, "body"));
  1080. return concat(parts);
  1081. case "TemplateElement":
  1082. return fromString(n.value.raw, options).lockIndentTail();
  1083. case "TemplateLiteral":
  1084. var expressions = path.map(print, "expressions");
  1085. parts.push("`");
  1086. path.each(function(childPath) {
  1087. var i = childPath.getName();
  1088. parts.push(print(childPath));
  1089. if (i < expressions.length) {
  1090. parts.push("${", expressions[i], "}");
  1091. }
  1092. }, "quasis");
  1093. parts.push("`");
  1094. return concat(parts).lockIndentTail();
  1095. case "TaggedTemplateExpression":
  1096. return concat([
  1097. path.call(print, "tag"),
  1098. path.call(print, "quasi")
  1099. ]);
  1100. // These types are unprintable because they serve as abstract
  1101. // supertypes for other (printable) types.
  1102. case "Node":
  1103. case "Printable":
  1104. case "SourceLocation":
  1105. case "Position":
  1106. case "Statement":
  1107. case "Function":
  1108. case "Pattern":
  1109. case "Expression":
  1110. case "Declaration":
  1111. case "Specifier":
  1112. case "NamedSpecifier":
  1113. case "Comment": // Supertype of Block and Line
  1114. case "Flow": // Supertype of all Flow AST node types
  1115. case "FlowType": // Supertype of all Flow types
  1116. case "FlowPredicate": // Supertype of InferredPredicate and DeclaredPredicate
  1117. case "MemberTypeAnnotation": // Flow
  1118. case "Type": // Flow
  1119. case "TSHasOptionalTypeParameters":
  1120. case "TSHasOptionalTypeAnnotation":
  1121. throw new Error("unprintable type: " + JSON.stringify(n.type));
  1122. case "CommentBlock": // Babel block comment.
  1123. case "Block": // Esprima block comment.
  1124. return concat(["/*", fromString(n.value, options), "*/"]);
  1125. case "CommentLine": // Babel line comment.
  1126. case "Line": // Esprima line comment.
  1127. return concat(["//", fromString(n.value, options)]);
  1128. // Type Annotations for Facebook Flow, typically stripped out or
  1129. // transformed away before printing.
  1130. case "TypeAnnotation":
  1131. if (n.typeAnnotation) {
  1132. if (n.typeAnnotation.type !== "FunctionTypeAnnotation") {
  1133. parts.push(": ");
  1134. }
  1135. parts.push(path.call(print, "typeAnnotation"));
  1136. return concat(parts);
  1137. }
  1138. return fromString("");
  1139. case "ExistentialTypeParam":
  1140. case "ExistsTypeAnnotation":
  1141. return fromString("*", options);
  1142. case "EmptyTypeAnnotation":
  1143. return fromString("empty", options);
  1144. case "AnyTypeAnnotation":
  1145. return fromString("any", options);
  1146. case "MixedTypeAnnotation":
  1147. return fromString("mixed", options);
  1148. case "ArrayTypeAnnotation":
  1149. return concat([
  1150. path.call(print, "elementType"),
  1151. "[]"
  1152. ]);
  1153. case "TupleTypeAnnotation":
  1154. var printed = path.map(print, "types");
  1155. var joined = fromString(", ").join(printed);
  1156. var oneLine = joined.getLineLength(1) <= options.wrapColumn;
  1157. if (oneLine) {
  1158. if (options.arrayBracketSpacing) {
  1159. parts.push("[ ");
  1160. } else {
  1161. parts.push("[");
  1162. }
  1163. } else {
  1164. parts.push("[\n");
  1165. }
  1166. path.each(function(elemPath) {
  1167. var i = elemPath.getName();
  1168. var elem = elemPath.getValue();
  1169. if (!elem) {
  1170. // If the array expression ends with a hole, that hole
  1171. // will be ignored by the interpreter, but if it ends with
  1172. // two (or more) holes, we need to write out two (or more)
  1173. // commas so that the resulting code is interpreted with
  1174. // both (all) of the holes.
  1175. parts.push(",");
  1176. } else {
  1177. var lines = printed[i];
  1178. if (oneLine) {
  1179. if (i > 0)
  1180. parts.push(" ");
  1181. } else {
  1182. lines = lines.indent(options.tabWidth);
  1183. }
  1184. parts.push(lines);
  1185. if (i < n.types.length - 1 || (!oneLine && util.isTrailingCommaEnabled(options, "arrays")))
  1186. parts.push(",");
  1187. if (!oneLine)
  1188. parts.push("\n");
  1189. }
  1190. }, "types");
  1191. if (oneLine && options.arrayBracketSpacing) {
  1192. parts.push(" ]");
  1193. } else {
  1194. parts.push("]");
  1195. }
  1196. return concat(parts);
  1197. case "BooleanTypeAnnotation":
  1198. return fromString("boolean", options);
  1199. case "BooleanLiteralTypeAnnotation":
  1200. assert.strictEqual(typeof n.value, "boolean");
  1201. return fromString("" + n.value, options);
  1202. case "DeclareClass":
  1203. return printFlowDeclaration(path, [
  1204. "class ",
  1205. path.call(print, "id"),
  1206. " ",
  1207. path.call(print, "body"),
  1208. ]);
  1209. case "DeclareFunction":
  1210. return printFlowDeclaration(path, [
  1211. "function ",
  1212. path.call(print, "id"),
  1213. ";"
  1214. ]);
  1215. case "DeclareModule":
  1216. return printFlowDeclaration(path, [
  1217. "module ",
  1218. path.call(print, "id"),
  1219. " ",
  1220. path.call(print, "body"),
  1221. ]);
  1222. case "DeclareModuleExports":
  1223. return printFlowDeclaration(path, [
  1224. "module.exports",
  1225. path.call(print, "typeAnnotation"),
  1226. ]);
  1227. case "DeclareVariable":
  1228. return printFlowDeclaration(path, [
  1229. "var ",
  1230. path.call(print, "id"),
  1231. ";"
  1232. ]);
  1233. case "DeclareExportDeclaration":
  1234. case "DeclareExportAllDeclaration":
  1235. return concat([
  1236. "declare ",
  1237. printExportDeclaration(path, options, print)
  1238. ]);
  1239. case "InferredPredicate":
  1240. return fromString("%checks", options);
  1241. case "DeclaredPredicate":
  1242. return concat([
  1243. "%checks(",
  1244. path.call(print, "value"),
  1245. ")"
  1246. ]);
  1247. case "FunctionTypeAnnotation":
  1248. // FunctionTypeAnnotation is ambiguous:
  1249. // declare function(a: B): void; OR
  1250. // var A: (a: B) => void;
  1251. var parent = path.getParentNode(0);
  1252. var isArrowFunctionTypeAnnotation = !(
  1253. namedTypes.ObjectTypeCallProperty.check(parent) ||
  1254. namedTypes.DeclareFunction.check(path.getParentNode(2))
  1255. );
  1256. var needsColon =
  1257. isArrowFunctionTypeAnnotation &&
  1258. !namedTypes.FunctionTypeParam.check(parent);
  1259. if (needsColon) {
  1260. parts.push(": ");
  1261. }
  1262. parts.push(
  1263. "(",
  1264. fromString(", ").join(path.map(print, "params")),
  1265. ")"
  1266. );
  1267. // The returnType is not wrapped in a TypeAnnotation, so the colon
  1268. // needs to be added separately.
  1269. if (n.returnType) {
  1270. parts.push(
  1271. isArrowFunctionTypeAnnotation ? " => " : ": ",
  1272. path.call(print, "returnType")
  1273. );
  1274. }
  1275. return concat(parts);
  1276. case "FunctionTypeParam":
  1277. return concat([
  1278. path.call(print, "name"),
  1279. n.optional ? '?' : '',
  1280. ": ",
  1281. path.call(print, "typeAnnotation"),
  1282. ]);
  1283. case "GenericTypeAnnotation":
  1284. return concat([
  1285. path.call(print, "id"),
  1286. path.call(print, "typeParameters")
  1287. ]);
  1288. case "DeclareInterface":
  1289. parts.push("declare ");
  1290. // Fall through to InterfaceDeclaration...
  1291. case "InterfaceDeclaration":
  1292. case "TSInterfaceDeclaration":
  1293. if (n.declare) {
  1294. parts.push("declare ");
  1295. }
  1296. parts.push(
  1297. "interface ",
  1298. path.call(print, "id"),
  1299. path.call(print, "typeParameters"),
  1300. " "
  1301. );
  1302. if (n["extends"] && n["extends"].length > 0) {
  1303. parts.push(
  1304. "extends ",
  1305. fromString(", ").join(path.map(print, "extends")),
  1306. " "
  1307. );
  1308. }
  1309. if (n.body) {
  1310. parts.push(path.call(print, "body"));
  1311. }
  1312. return concat(parts);
  1313. case "ClassImplements":
  1314. case "InterfaceExtends":
  1315. return concat([
  1316. path.call(print, "id"),
  1317. path.call(print, "typeParameters")
  1318. ]);
  1319. case "IntersectionTypeAnnotation":
  1320. return fromString(" & ").join(path.map(print, "types"));
  1321. case "NullableTypeAnnotation":
  1322. return concat([
  1323. "?",
  1324. path.call(print, "typeAnnotation")
  1325. ]);
  1326. case "NullLiteralTypeAnnotation":
  1327. return fromString("null", options);
  1328. case "ThisTypeAnnotation":
  1329. return fromString("this", options);
  1330. case "NumberTypeAnnotation":
  1331. return fromString("number", options);
  1332. case "ObjectTypeCallProperty":
  1333. return path.call(print, "value");
  1334. case "ObjectTypeIndexer":
  1335. return concat([
  1336. printVariance(path, print),
  1337. "[",
  1338. path.call(print, "id"),
  1339. ": ",
  1340. path.call(print, "key"),
  1341. "]: ",
  1342. path.call(print, "value")
  1343. ]);
  1344. case "ObjectTypeProperty":
  1345. return concat([
  1346. printVariance(path, print),
  1347. path.call(print, "key"),
  1348. n.optional ? "?" : "",
  1349. ": ",
  1350. path.call(print, "value")
  1351. ]);
  1352. case "QualifiedTypeIdentifier":
  1353. return concat([
  1354. path.call(print, "qualification"),
  1355. ".",
  1356. path.call(print, "id")
  1357. ]);
  1358. case "StringLiteralTypeAnnotation":
  1359. return fromString(nodeStr(n.value, options), options);
  1360. case "NumberLiteralTypeAnnotation":
  1361. case "NumericLiteralTypeAnnotation":
  1362. assert.strictEqual(typeof n.value, "number");
  1363. return fromString(JSON.stringify(n.value), options);
  1364. case "StringTypeAnnotation":
  1365. return fromString("string", options);
  1366. case "DeclareTypeAlias":
  1367. parts.push("declare ");
  1368. // Fall through to TypeAlias...
  1369. case "TypeAlias":
  1370. return concat([
  1371. "type ",
  1372. path.call(print, "id"),
  1373. path.call(print, "typeParameters"),
  1374. " = ",
  1375. path.call(print, "right"),
  1376. ";"
  1377. ]);
  1378. case "DeclareOpaqueType":
  1379. parts.push("declare ");
  1380. // Fall through to OpaqueType...
  1381. case "OpaqueType":
  1382. parts.push(
  1383. "opaque type ",
  1384. path.call(print, "id"),
  1385. path.call(print, "typeParameters")
  1386. );
  1387. if (n["supertype"]) {
  1388. parts.push(": ", path.call(print, "supertype"));
  1389. }
  1390. if (n["impltype"]) {
  1391. parts.push(" = ", path.call(print, "impltype"));
  1392. }
  1393. parts.push(";");
  1394. return concat(parts);
  1395. case "TypeCastExpression":
  1396. return concat([
  1397. "(",
  1398. path.call(print, "expression"),
  1399. path.call(print, "typeAnnotation"),
  1400. ")"
  1401. ]);
  1402. case "TypeParameterDeclaration":
  1403. case "TypeParameterInstantiation":
  1404. return concat([
  1405. "<",
  1406. fromString(", ").join(path.map(print, "params")),
  1407. ">"
  1408. ]);
  1409. case "Variance":
  1410. if (n.kind === "plus") {
  1411. return fromString("+");
  1412. }
  1413. if (n.kind === "minus") {
  1414. return fromString("-");
  1415. }
  1416. return fromString("");
  1417. case "TypeParameter":
  1418. if (n.variance) {
  1419. parts.push(printVariance(path, print));
  1420. }
  1421. parts.push(path.call(print, 'name'));
  1422. if (n.bound) {
  1423. parts.push(path.call(print, 'bound'));
  1424. }
  1425. if (n['default']) {
  1426. parts.push('=', path.call(print, 'default'));
  1427. }
  1428. return concat(parts);
  1429. case "TypeofTypeAnnotation":
  1430. return concat([
  1431. fromString("typeof ", options),
  1432. path.call(print, "argument")
  1433. ]);
  1434. case "UnionTypeAnnotation":
  1435. return fromString(" | ").join(path.map(print, "types"));
  1436. case "VoidTypeAnnotation":
  1437. return fromString("void", options);
  1438. case "NullTypeAnnotation":
  1439. return fromString("null", options);
  1440. // Type Annotations for TypeScript (when using Babylon as parser)
  1441. case "TSType":
  1442. throw new Error("unprintable type: " + JSON.stringify(n.type));
  1443. case "TSNumberKeyword":
  1444. return fromString("number", options);
  1445. case "TSObjectKeyword":
  1446. return fromString("object", options);
  1447. case "TSBooleanKeyword":
  1448. return fromString("boolean", options);
  1449. case "TSStringKeyword":
  1450. return fromString("string", options);
  1451. case "TSSymbolKeyword":
  1452. return fromString("symbol", options);
  1453. case "TSAnyKeyword":
  1454. return fromString("any", options);
  1455. case "TSVoidKeyword":
  1456. return fromString("void", options);
  1457. case "TSThisType":
  1458. return fromString("this", options);
  1459. case "TSNullKeyword":
  1460. return fromString("null", options);
  1461. case "TSUndefinedKeyword":
  1462. return fromString("undefined", options);
  1463. case "TSNeverKeyword":
  1464. return fromString("never", options);
  1465. case "TSArrayType":
  1466. return concat([
  1467. path.call(print, "elementType"),
  1468. "[]"
  1469. ]);
  1470. case "TSLiteralType":
  1471. return path.call(print, "literal")
  1472. case "TSUnionType":
  1473. return fromString(" | ").join(path.map(print, "types"));
  1474. case "TSIntersectionType":
  1475. return fromString(" & ").join(path.map(print, "types"));
  1476. case "TSConditionalType":
  1477. parts.push(
  1478. path.call(print, "checkType"),
  1479. " extends ",
  1480. path.call(print, "extendsType"),
  1481. " ? ",
  1482. path.call(print, "trueType"),
  1483. " : ",
  1484. path.call(print, "falseType")
  1485. );
  1486. return concat(parts);
  1487. case "TSInferType":
  1488. parts.push(
  1489. "infer ",
  1490. path.call(print, "typeParameter")
  1491. );
  1492. return concat(parts);
  1493. case "TSParenthesizedType":
  1494. return concat([
  1495. "(",
  1496. path.call(print, "typeAnnotation"),
  1497. ")"
  1498. ]);
  1499. case "TSFunctionType":
  1500. case "TSConstructorType":
  1501. return concat([
  1502. path.call(print, "typeParameters"),
  1503. "(",
  1504. printFunctionParams(path, options, print),
  1505. ")",
  1506. path.call(print, "typeAnnotation")
  1507. ]);
  1508. case "TSMappedType": {
  1509. parts.push(
  1510. n.readonly ? "readonly " : "",
  1511. "[",
  1512. path.call(print, "typeParameter"),
  1513. "]",
  1514. n.optional ? "?" : ""
  1515. );
  1516. if (n.typeAnnotation) {
  1517. parts.push(": ", path.call(print, "typeAnnotation"), ";");
  1518. }
  1519. return concat([
  1520. "{\n",
  1521. concat(parts).indent(options.tabWidth),
  1522. "\n}",
  1523. ]);
  1524. }
  1525. case "TSTupleType":
  1526. return concat([
  1527. "[",
  1528. fromString(", ").join(path.map(print, "elementTypes")),
  1529. "]"
  1530. ]);
  1531. case "TSIndexedAccessType":
  1532. return concat([
  1533. path.call(print, "objectType"),
  1534. "[",
  1535. path.call(print, "indexType"),
  1536. "]"
  1537. ]);
  1538. case "TSTypeOperator":
  1539. return concat([
  1540. path.call(print, "operator"),
  1541. " ",
  1542. path.call(print, "typeAnnotation")
  1543. ]);
  1544. case "TSTypeLiteral": {
  1545. const memberLines =
  1546. fromString(",\n").join(path.map(print, "members"));
  1547. if (memberLines.isEmpty()) {
  1548. return fromString("{}", options);
  1549. }
  1550. parts.push(
  1551. "{\n",
  1552. memberLines.indent(options.tabWidth),
  1553. "\n}"
  1554. );
  1555. return concat(parts);
  1556. }
  1557. case "TSEnumMember":
  1558. parts.push(path.call(print, "id"));
  1559. if (n.initializer) {
  1560. parts.push(
  1561. " = ",
  1562. path.call(print, "initializer")
  1563. );
  1564. }
  1565. return concat(parts);
  1566. case "TSTypeQuery":
  1567. return concat([
  1568. "typeof ",
  1569. path.call(print, "exprName"),
  1570. ]);
  1571. case "TSParameterProperty":
  1572. if (n.accessibility) {
  1573. parts.push(n.accessibility, " ");
  1574. }
  1575. if (n.export) {
  1576. parts.push("export ");
  1577. }
  1578. if (n.static) {
  1579. parts.push("static ");
  1580. }
  1581. if (n.readonly) {
  1582. parts.push("readonly ");
  1583. }
  1584. parts.push(path.call(print, "parameter"));
  1585. return concat(parts);
  1586. case "TSTypeReference":
  1587. return concat([
  1588. path.call(print, "typeName"),
  1589. path.call(print, "typeParameters")
  1590. ]);
  1591. case "TSQualifiedName":
  1592. return concat([
  1593. path.call(print, "left"),
  1594. ".",
  1595. path.call(print, "right")
  1596. ]);
  1597. case "TSAsExpression": {
  1598. var withParens = n.extra && n.extra.parenthesized === true;
  1599. parts = [];
  1600. if (withParens) parts.push("(");
  1601. parts.push(
  1602. path.call(print, "expression"),
  1603. fromString(" as "),
  1604. path.call(print, "typeAnnotation")
  1605. );
  1606. if (withParens) parts.push(")");
  1607. return concat(parts);
  1608. }
  1609. case "TSNonNullExpression":
  1610. return concat([
  1611. path.call(print, "expression"),
  1612. "!"
  1613. ]);
  1614. case "TSTypeAnnotation": {
  1615. // similar to flow's FunctionTypeAnnotation, this can be
  1616. // ambiguous: it can be prefixed by => or :
  1617. // in a type predicate, it takes the for u is U
  1618. var parent = path.getParentNode(0);
  1619. var prefix = ": ";
  1620. var isFunctionType = namedTypes.TSFunctionType.check(parent);
  1621. if (namedTypes.TSFunctionType.check(parent)) {
  1622. prefix = " => ";
  1623. }
  1624. if (namedTypes.TSTypePredicate.check(parent)) {
  1625. prefix = " is ";
  1626. }
  1627. return concat([
  1628. prefix,
  1629. path.call(print, "typeAnnotation")
  1630. ]);
  1631. }
  1632. case "TSIndexSignature":
  1633. return concat([
  1634. n.readonly ? "readonly " : "",
  1635. "[",
  1636. path.map(print, "parameters"),
  1637. "]",
  1638. path.call(print, "typeAnnotation")
  1639. ]);
  1640. case "TSPropertySignature":
  1641. parts.push(
  1642. printVariance(path, print),
  1643. n.readonly ? "readonly " : ""
  1644. );
  1645. if (n.computed) {
  1646. parts.push(
  1647. "[",
  1648. path.call(print, "key"),
  1649. "]"
  1650. );
  1651. } else {
  1652. parts.push(path.call(print, "key"));
  1653. }
  1654. parts.push(
  1655. n.optional ? "?" : "",
  1656. path.call(print, "typeAnnotation")
  1657. );
  1658. return concat(parts);
  1659. case "TSMethodSignature":
  1660. if (n.computed) {
  1661. parts.push(
  1662. "[",
  1663. path.call(print, "key"),
  1664. "]"
  1665. );
  1666. } else {
  1667. parts.push(path.call(print, "key"));
  1668. }
  1669. if (n.optional) {
  1670. parts.push("?");
  1671. }
  1672. parts.push(
  1673. path.call(print, "typeParameters"),
  1674. "(",
  1675. printFunctionParams(path, options, print),
  1676. ")",
  1677. path.call(print, "typeAnnotation")
  1678. );
  1679. return concat(parts);
  1680. case "TSTypePredicate":
  1681. return concat([
  1682. path.call(print, "parameterName"),
  1683. path.call(print, "typeAnnotation")
  1684. ]);
  1685. case "TSCallSignatureDeclaration":
  1686. return concat([
  1687. path.call(print, "typeParameters"),
  1688. "(",
  1689. printFunctionParams(path, options, print),
  1690. ")",
  1691. path.call(print, "typeAnnotation")
  1692. ]);
  1693. case "TSConstructSignatureDeclaration":
  1694. if (n.typeParameters) {
  1695. parts.push(
  1696. "new",
  1697. path.call(print, "typeParameters")
  1698. );
  1699. } else {
  1700. parts.push("new ");
  1701. }
  1702. parts.push(
  1703. "(",
  1704. printFunctionParams(path, options, print),
  1705. ")",
  1706. path.call(print, "typeAnnotation")
  1707. );
  1708. return concat(parts);
  1709. case "TSTypeAliasDeclaration":
  1710. return concat([
  1711. n.declare ? "declare " : "",
  1712. "type ",
  1713. path.call(print, "id"),
  1714. path.call(print, "typeParameters"),
  1715. " = ",
  1716. path.call(print, "typeAnnotation"),
  1717. ";"
  1718. ]);
  1719. case "TSTypeParameter":
  1720. parts.push(path.call(print, "name"));
  1721. // ambiguous because of TSMappedType
  1722. var parent = path.getParentNode(0);
  1723. var isInMappedType = namedTypes.TSMappedType.check(parent);
  1724. if (n.constraint) {
  1725. parts.push(
  1726. isInMappedType ? " in " : " extends ",
  1727. path.call(print, "constraint")
  1728. );
  1729. }
  1730. if (n["default"]) {
  1731. parts.push(" = ", path.call(print, "default"));
  1732. }
  1733. return concat(parts);
  1734. case "TSTypeAssertion":
  1735. var withParens = n.extra && n.extra.parenthesized === true;
  1736. if (withParens) {
  1737. parts.push("(");
  1738. }
  1739. parts.push(
  1740. "<",
  1741. path.call(print, "typeAnnotation"),
  1742. "> ",
  1743. path.call(print, "expression")
  1744. );
  1745. if (withParens) {
  1746. parts.push(")");
  1747. }
  1748. return concat(parts);
  1749. case "TSTypeParameterDeclaration":
  1750. case "TSTypeParameterInstantiation":
  1751. return concat([
  1752. "<",
  1753. fromString(", ").join(path.map(print, "params")),
  1754. ">"
  1755. ]);
  1756. case "TSEnumDeclaration":
  1757. parts.push(
  1758. n.declare ? "declare " : "",
  1759. n.const ? "const " : "",
  1760. "enum ",
  1761. path.call(print, "id")
  1762. );
  1763. const memberLines =
  1764. fromString(",\n").join(path.map(print, "members"));
  1765. if (memberLines.isEmpty()) {
  1766. parts.push(" {}");
  1767. } else {
  1768. parts.push(
  1769. " {\n",
  1770. memberLines.indent(options.tabWidth),
  1771. "\n}"
  1772. );
  1773. }
  1774. return concat(parts);
  1775. case "TSExpressionWithTypeArguments":
  1776. return concat([
  1777. path.call(print, "expression"),
  1778. path.call(print, "typeParameters")
  1779. ]);
  1780. case "TSInterfaceBody":
  1781. var lines = fromString(";\n").join(path.map(print, "body"));
  1782. if (lines.isEmpty()) {
  1783. return fromString("{}", options);
  1784. }
  1785. return concat([
  1786. "{\n",
  1787. lines.indent(options.tabWidth), ";",
  1788. "\n}",
  1789. ]);
  1790. case "TSImportEqualsDeclaration":
  1791. if (n.isExport) {
  1792. parts.push("export ");
  1793. }
  1794. parts.push(
  1795. "import ",
  1796. path.call(print, "id"),
  1797. " = ",
  1798. path.call(print, "moduleReference")
  1799. );
  1800. return maybeAddSemicolon(concat(parts));
  1801. case "TSExternalModuleReference":
  1802. return concat(["require(", path.call(print, "expression"), ")"]);
  1803. case "TSModuleDeclaration": {
  1804. const parent = path.getParentNode();
  1805. if (parent.type === "TSModuleDeclaration") {
  1806. parts.push(".");
  1807. } else {
  1808. if (n.declare) {
  1809. parts.push("declare ");
  1810. }
  1811. if (! n.global) {
  1812. const isExternal = n.id.type === "StringLiteral" ||
  1813. (n.id.type === "Literal" &&
  1814. typeof n.id.value === "string");
  1815. if (isExternal) {
  1816. parts.push("module ");
  1817. } else if (n.loc &&
  1818. n.loc.lines &&
  1819. n.id.loc) {
  1820. const prefix = n.loc.lines.sliceString(
  1821. n.loc.start,
  1822. n.id.loc.start
  1823. );
  1824. // These keywords are fundamentally ambiguous in the
  1825. // Babylon parser, and not reflected in the AST, so
  1826. // the best we can do is to match the original code,
  1827. // when possible.
  1828. if (prefix.indexOf("module") >= 0) {
  1829. parts.push("module ");
  1830. } else {
  1831. parts.push("namespace ");
  1832. }
  1833. } else {
  1834. parts.push("namespace ");
  1835. }
  1836. }
  1837. }
  1838. parts.push(path.call(print, "id"));
  1839. if (n.body && n.body.type === "TSModuleDeclaration") {
  1840. parts.push(path.call(print, "body"));
  1841. } else if (n.body) {
  1842. const bodyLines = path.call(print, "body");
  1843. if (bodyLines.isEmpty()) {
  1844. parts.push(" {}");
  1845. } else {
  1846. parts.push(
  1847. " {\n",
  1848. bodyLines.indent(options.tabWidth),
  1849. "\n}"
  1850. );
  1851. }
  1852. }
  1853. return concat(parts);
  1854. }
  1855. case "TSModuleBlock":
  1856. return path.call(function (bodyPath) {
  1857. return printStatementSequence(bodyPath, options, print);
  1858. }, "body");
  1859. // Unhandled types below. If encountered, nodes of these types should
  1860. // be either left alone or desugared into AST types that are fully
  1861. // supported by the pretty-printer.
  1862. case "ClassHeritage": // TODO
  1863. case "ComprehensionBlock": // TODO
  1864. case "ComprehensionExpression": // TODO
  1865. case "Glob": // TODO
  1866. case "GeneratorExpression": // TODO
  1867. case "LetStatement": // TODO
  1868. case "LetExpression": // TODO
  1869. case "GraphExpression": // TODO
  1870. case "GraphIndexExpression": // TODO
  1871. // XML types that nobody cares about or needs to print.
  1872. case "XMLDefaultDeclaration":
  1873. case "XMLAnyName":
  1874. case "XMLQualifiedIdentifier":
  1875. case "XMLFunctionQualifiedIdentifier":
  1876. case "XMLAttributeSelector":
  1877. case "XMLFilterExpression":
  1878. case "XML":
  1879. case "XMLElement":
  1880. case "XMLList":
  1881. case "XMLEscape":
  1882. case "XMLText":
  1883. case "XMLStartTag":
  1884. case "XMLEndTag":
  1885. case "XMLPointTag":
  1886. case "XMLName":
  1887. case "XMLAttribute":
  1888. case "XMLCdata":
  1889. case "XMLComment":
  1890. case "XMLProcessingInstruction":
  1891. default:
  1892. debugger;
  1893. throw new Error("unknown type: " + JSON.stringify(n.type));
  1894. }
  1895. return p;
  1896. }
  1897. function printStatementSequence(path, options, print) {
  1898. var inClassBody =
  1899. namedTypes.ClassBody &&
  1900. namedTypes.ClassBody.check(path.getParentNode());
  1901. var filtered = [];
  1902. var sawComment = false;
  1903. var sawStatement = false;
  1904. path.each(function(stmtPath) {
  1905. var i = stmtPath.getName();
  1906. var stmt = stmtPath.getValue();
  1907. // Just in case the AST has been modified to contain falsy
  1908. // "statements," it's safer simply to skip them.
  1909. if (!stmt) {
  1910. return;
  1911. }
  1912. // Skip printing EmptyStatement nodes to avoid leaving stray
  1913. // semicolons lying around.
  1914. if (stmt.type === "EmptyStatement") {
  1915. return;
  1916. }
  1917. if (namedTypes.Comment.check(stmt)) {
  1918. // The pretty printer allows a dangling Comment node to act as
  1919. // a Statement when the Comment can't be attached to any other
  1920. // non-Comment node in the tree.
  1921. sawComment = true;
  1922. } else if (namedTypes.Statement.check(stmt)) {
  1923. sawStatement = true;
  1924. } else {
  1925. // When the pretty printer encounters a string instead of an
  1926. // AST node, it just prints the string. This behavior can be
  1927. // useful for fine-grained formatting decisions like inserting
  1928. // blank lines.
  1929. isString.assert(stmt);
  1930. }
  1931. // We can't hang onto stmtPath outside of this function, because
  1932. // it's just a reference to a mutable FastPath object, so we have
  1933. // to go ahead and print it here.
  1934. filtered.push({
  1935. node: stmt,
  1936. printed: print(stmtPath)
  1937. });
  1938. });
  1939. if (sawComment) {
  1940. assert.strictEqual(
  1941. sawStatement, false,
  1942. "Comments may appear as statements in otherwise empty statement " +
  1943. "lists, but may not coexist with non-Comment nodes."
  1944. );
  1945. }
  1946. var prevTrailingSpace = null;
  1947. var len = filtered.length;
  1948. var parts = [];
  1949. filtered.forEach(function(info, i) {
  1950. var printed = info.printed;
  1951. var stmt = info.node;
  1952. var multiLine = printed.length > 1;
  1953. var notFirst = i > 0;
  1954. var notLast = i < len - 1;
  1955. var leadingSpace;
  1956. var trailingSpace;
  1957. var lines = stmt && stmt.loc && stmt.loc.lines;
  1958. var trueLoc = lines && options.reuseWhitespace &&
  1959. util.getTrueLoc(stmt, lines);
  1960. if (notFirst) {
  1961. if (trueLoc) {
  1962. var beforeStart = lines.skipSpaces(trueLoc.start, true);
  1963. var beforeStartLine = beforeStart ? beforeStart.line : 1;
  1964. var leadingGap = trueLoc.start.line - beforeStartLine;
  1965. leadingSpace = Array(leadingGap + 1).join("\n");
  1966. } else {
  1967. leadingSpace = multiLine ? "\n\n" : "\n";
  1968. }
  1969. } else {
  1970. leadingSpace = "";
  1971. }
  1972. if (notLast) {
  1973. if (trueLoc) {
  1974. var afterEnd = lines.skipSpaces(trueLoc.end);
  1975. var afterEndLine = afterEnd ? afterEnd.line : lines.length;
  1976. var trailingGap = afterEndLine - trueLoc.end.line;
  1977. trailingSpace = Array(trailingGap + 1).join("\n");
  1978. } else {
  1979. trailingSpace = multiLine ? "\n\n" : "\n";
  1980. }
  1981. } else {
  1982. trailingSpace = "";
  1983. }
  1984. parts.push(
  1985. maxSpace(prevTrailingSpace, leadingSpace),
  1986. printed
  1987. );
  1988. if (notLast) {
  1989. prevTrailingSpace = trailingSpace;
  1990. } else if (trailingSpace) {
  1991. parts.push(trailingSpace);
  1992. }
  1993. });
  1994. return concat(parts);
  1995. }
  1996. function maxSpace(s1, s2) {
  1997. if (!s1 && !s2) {
  1998. return fromString("");
  1999. }
  2000. if (!s1) {
  2001. return fromString(s2);
  2002. }
  2003. if (!s2) {
  2004. return fromString(s1);
  2005. }
  2006. var spaceLines1 = fromString(s1);
  2007. var spaceLines2 = fromString(s2);
  2008. if (spaceLines2.length > spaceLines1.length) {
  2009. return spaceLines2;
  2010. }
  2011. return spaceLines1;
  2012. }
  2013. function printMethod(path, options, print) {
  2014. var node = path.getNode();
  2015. var kind = node.kind;
  2016. var parts = [];
  2017. var nodeValue = node.value;
  2018. if (! namedTypes.FunctionExpression.check(nodeValue)) {
  2019. nodeValue = node;
  2020. }
  2021. var access = node.accessibility || node.access;
  2022. if (typeof access === "string") {
  2023. parts.push(access, " ");
  2024. }
  2025. if (node.static) {
  2026. parts.push("static ");
  2027. }
  2028. if (node.abstract) {
  2029. parts.push("abstract ");
  2030. }
  2031. if (node.readonly) {
  2032. parts.push("readonly ");
  2033. }
  2034. if (nodeValue.async) {
  2035. parts.push("async ");
  2036. }
  2037. if (nodeValue.generator) {
  2038. parts.push("*");
  2039. }
  2040. if (kind === "get" || kind === "set") {
  2041. parts.push(kind, " ");
  2042. }
  2043. var key = path.call(print, "key");
  2044. if (node.computed) {
  2045. key = concat(["[", key, "]"]);
  2046. }
  2047. parts.push(key);
  2048. if (node.optional) {
  2049. parts.push("?");
  2050. }
  2051. if (node === nodeValue) {
  2052. parts.push(
  2053. path.call(print, "typeParameters"),
  2054. "(",
  2055. printFunctionParams(path, options, print),
  2056. ")",
  2057. path.call(print, "returnType")
  2058. );
  2059. if (node.body) {
  2060. parts.push(" ", path.call(print, "body"));
  2061. } else {
  2062. parts.push(";");
  2063. }
  2064. } else {
  2065. parts.push(
  2066. path.call(print, "value", "typeParameters"),
  2067. "(",
  2068. path.call(function(valuePath) {
  2069. return printFunctionParams(valuePath, options, print);
  2070. }, "value"),
  2071. ")",
  2072. path.call(print, "value", "returnType")
  2073. );
  2074. if (nodeValue.body) {
  2075. parts.push(" ", path.call(print, "value", "body"));
  2076. } else {
  2077. parts.push(";");
  2078. }
  2079. }
  2080. return concat(parts);
  2081. }
  2082. function printArgumentsList(path, options, print) {
  2083. var printed = path.map(print, "arguments");
  2084. var trailingComma = util.isTrailingCommaEnabled(options, "parameters");
  2085. var joined = fromString(", ").join(printed);
  2086. if (joined.getLineLength(1) > options.wrapColumn) {
  2087. joined = fromString(",\n").join(printed);
  2088. return concat([
  2089. "(\n",
  2090. joined.indent(options.tabWidth),
  2091. trailingComma ? ",\n)" : "\n)"
  2092. ]);
  2093. }
  2094. return concat(["(", joined, ")"]);
  2095. }
  2096. function printFunctionParams(path, options, print) {
  2097. var fun = path.getValue();
  2098. if (fun.params) {
  2099. var params = fun.params;
  2100. var printed = path.map(print, "params");
  2101. } else if (fun.parameters) {
  2102. params = fun.parameters;
  2103. printed = path.map(print, "parameters");
  2104. }
  2105. if (fun.defaults) {
  2106. path.each(function(defExprPath) {
  2107. var i = defExprPath.getName();
  2108. var p = printed[i];
  2109. if (p && defExprPath.getValue()) {
  2110. printed[i] = concat([p, " = ", print(defExprPath)]);
  2111. }
  2112. }, "defaults");
  2113. }
  2114. if (fun.rest) {
  2115. printed.push(concat(["...", path.call(print, "rest")]));
  2116. }
  2117. var joined = fromString(", ").join(printed);
  2118. if (joined.length > 1 ||
  2119. joined.getLineLength(1) > options.wrapColumn) {
  2120. joined = fromString(",\n").join(printed);
  2121. if (util.isTrailingCommaEnabled(options, "parameters") &&
  2122. !fun.rest &&
  2123. params[params.length - 1].type !== 'RestElement') {
  2124. joined = concat([joined, ",\n"]);
  2125. } else {
  2126. joined = concat([joined, "\n"]);
  2127. }
  2128. return concat(["\n", joined.indent(options.tabWidth)]);
  2129. }
  2130. return joined;
  2131. }
  2132. function printExportDeclaration(path, options, print) {
  2133. var decl = path.getValue();
  2134. var parts = ["export "];
  2135. if (decl.exportKind && decl.exportKind !== "value") {
  2136. parts.push(decl.exportKind + " ");
  2137. }
  2138. var shouldPrintSpaces = options.objectCurlySpacing;
  2139. namedTypes.Declaration.assert(decl);
  2140. if (decl["default"] ||
  2141. decl.type === "ExportDefaultDeclaration") {
  2142. parts.push("default ");
  2143. }
  2144. if (decl.declaration) {
  2145. parts.push(path.call(print, "declaration"));
  2146. } else if (decl.specifiers &&
  2147. decl.specifiers.length > 0) {
  2148. if (decl.specifiers.length === 1 &&
  2149. decl.specifiers[0].type === "ExportBatchSpecifier") {
  2150. parts.push("*");
  2151. } else {
  2152. parts.push(
  2153. shouldPrintSpaces ? "{ " : "{",
  2154. fromString(", ").join(path.map(print, "specifiers")),
  2155. shouldPrintSpaces ? " }" : "}"
  2156. );
  2157. }
  2158. if (decl.source) {
  2159. parts.push(" from ", path.call(print, "source"));
  2160. }
  2161. }
  2162. var lines = concat(parts);
  2163. if (lastNonSpaceCharacter(lines) !== ";" &&
  2164. ! (decl.declaration &&
  2165. (decl.declaration.type === "FunctionDeclaration" ||
  2166. decl.declaration.type === "ClassDeclaration" ||
  2167. decl.declaration.type === "TSModuleDeclaration" ||
  2168. decl.declaration.type === "TSInterfaceDeclaration" ||
  2169. decl.declaration.type === "TSEnumDeclaration"))) {
  2170. lines = concat([lines, ";"]);
  2171. }
  2172. return lines;
  2173. }
  2174. function printFlowDeclaration(path, parts) {
  2175. var parentExportDecl = util.getParentExportDeclaration(path);
  2176. if (parentExportDecl) {
  2177. assert.strictEqual(
  2178. parentExportDecl.type,
  2179. "DeclareExportDeclaration"
  2180. );
  2181. } else {
  2182. // If the parent node has type DeclareExportDeclaration, then it
  2183. // will be responsible for printing the "declare" token. Otherwise
  2184. // it needs to be printed with this non-exported declaration node.
  2185. parts.unshift("declare ");
  2186. }
  2187. return concat(parts);
  2188. }
  2189. function printVariance(path, print) {
  2190. return path.call(function (variancePath) {
  2191. var value = variancePath.getValue();
  2192. if (value) {
  2193. if (value === "plus") {
  2194. return fromString("+");
  2195. }
  2196. if (value === "minus") {
  2197. return fromString("-");
  2198. }
  2199. return print(variancePath);
  2200. }
  2201. return fromString("");
  2202. }, "variance");
  2203. }
  2204. function adjustClause(clause, options) {
  2205. if (clause.length > 1)
  2206. return concat([" ", clause]);
  2207. return concat([
  2208. "\n",
  2209. maybeAddSemicolon(clause).indent(options.tabWidth)
  2210. ]);
  2211. }
  2212. function lastNonSpaceCharacter(lines) {
  2213. var pos = lines.lastPos();
  2214. do {
  2215. var ch = lines.charAt(pos);
  2216. if (/\S/.test(ch))
  2217. return ch;
  2218. } while (lines.prevPos(pos));
  2219. }
  2220. function endsWithBrace(lines) {
  2221. return lastNonSpaceCharacter(lines) === "}";
  2222. }
  2223. function swapQuotes(str) {
  2224. return str.replace(/['"]/g, function(m) {
  2225. return m === '"' ? '\'' : '"';
  2226. });
  2227. }
  2228. function nodeStr(str, options) {
  2229. isString.assert(str);
  2230. switch (options.quote) {
  2231. case "auto":
  2232. var double = JSON.stringify(str);
  2233. var single = swapQuotes(JSON.stringify(swapQuotes(str)));
  2234. return double.length > single.length ? single : double;
  2235. case "single":
  2236. return swapQuotes(JSON.stringify(swapQuotes(str)));
  2237. case "double":
  2238. default:
  2239. return JSON.stringify(str);
  2240. }
  2241. }
  2242. function maybeAddSemicolon(lines) {
  2243. var eoc = lastNonSpaceCharacter(lines);
  2244. if (!eoc || "\n};".indexOf(eoc) < 0)
  2245. return concat([lines, ";"]);
  2246. return lines;
  2247. }