create-expo-cljs-app
Version:
Create a react native application with Expo and Shadow-CLJS!
1,210 lines (1,209 loc) • 91.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Printer = void 0;
var tslib_1 = require("tslib");
var assert_1 = tslib_1.__importDefault(require("assert"));
var comments_1 = require("./comments");
var lines_1 = require("./lines");
var options_1 = require("./options");
var patcher_1 = require("./patcher");
var types = tslib_1.__importStar(require("ast-types"));
var namedTypes = types.namedTypes;
var isString = types.builtInTypes.string;
var isObject = types.builtInTypes.object;
var fast_path_1 = tslib_1.__importDefault(require("./fast-path"));
var util = tslib_1.__importStar(require("./util"));
var PrintResult = function PrintResult(code, sourceMap) {
assert_1.default.ok(this instanceof PrintResult);
isString.assert(code);
this.code = code;
if (sourceMap) {
isObject.assert(sourceMap);
this.map = sourceMap;
}
};
var PRp = PrintResult.prototype;
var warnedAboutToString = false;
PRp.toString = function () {
if (!warnedAboutToString) {
console.warn("Deprecation warning: recast.print now returns an object with " +
"a .code property. You appear to be treating the object as a " +
"string, which might still work but is strongly discouraged.");
warnedAboutToString = true;
}
return this.code;
};
var emptyPrintResult = new PrintResult("");
var Printer = function Printer(config) {
assert_1.default.ok(this instanceof Printer);
var explicitTabWidth = config && config.tabWidth;
config = options_1.normalize(config);
// It's common for client code to pass the same options into both
// recast.parse and recast.print, but the Printer doesn't need (and
// can be confused by) config.sourceFileName, so we null it out.
config.sourceFileName = null;
// Non-destructively modifies options with overrides, and returns a
// new print function that uses the modified options.
function makePrintFunctionWith(options, overrides) {
options = Object.assign({}, options, overrides);
return function (path) { return print(path, options); };
}
function print(path, options) {
assert_1.default.ok(path instanceof fast_path_1.default);
options = options || {};
if (options.includeComments) {
return comments_1.printComments(path, makePrintFunctionWith(options, {
includeComments: false,
}));
}
var oldTabWidth = config.tabWidth;
if (!explicitTabWidth) {
var loc = path.getNode().loc;
if (loc && loc.lines && loc.lines.guessTabWidth) {
config.tabWidth = loc.lines.guessTabWidth();
}
}
var reprinter = patcher_1.getReprinter(path);
var lines = reprinter
? // Since the print function that we pass to the reprinter will
// be used to print "new" nodes, it's tempting to think we
// should pass printRootGenerically instead of print, to avoid
// calling maybeReprint again, but that would be a mistake
// because the new nodes might not be entirely new, but merely
// moved from elsewhere in the AST. The print function is the
// right choice because it gives us the opportunity to reprint
// such nodes using their original source.
reprinter(print)
: genericPrint(path, config, options, makePrintFunctionWith(options, {
includeComments: true,
avoidRootParens: false,
}));
config.tabWidth = oldTabWidth;
return lines;
}
this.print = function (ast) {
if (!ast) {
return emptyPrintResult;
}
var lines = print(fast_path_1.default.from(ast), {
includeComments: true,
avoidRootParens: false,
});
return new PrintResult(lines.toString(config), util.composeSourceMaps(config.inputSourceMap, lines.getSourceMap(config.sourceMapName, config.sourceRoot)));
};
this.printGenerically = function (ast) {
if (!ast) {
return emptyPrintResult;
}
// Print the entire AST generically.
function printGenerically(path) {
return comments_1.printComments(path, function (path) {
return genericPrint(path, config, {
includeComments: true,
avoidRootParens: false,
}, printGenerically);
});
}
var path = fast_path_1.default.from(ast);
var oldReuseWhitespace = config.reuseWhitespace;
// Do not reuse whitespace (or anything else, for that matter)
// when printing generically.
config.reuseWhitespace = false;
// TODO Allow printing of comments?
var pr = new PrintResult(printGenerically(path).toString(config));
config.reuseWhitespace = oldReuseWhitespace;
return pr;
};
};
exports.Printer = Printer;
function genericPrint(path, config, options, printPath) {
assert_1.default.ok(path instanceof fast_path_1.default);
var node = path.getValue();
var parts = [];
var linesWithoutParens = genericPrintNoParens(path, config, printPath);
if (!node || linesWithoutParens.isEmpty()) {
return linesWithoutParens;
}
var shouldAddParens = node.extra ? node.extra.parenthesized : false;
var decoratorsLines = printDecorators(path, printPath);
if (decoratorsLines.isEmpty()) {
// Nodes with decorators can't have parentheses, so we can avoid
// computing path.needsParens() except in this case.
if (!options.avoidRootParens) {
shouldAddParens = shouldAddParens || path.needsParens();
}
}
else {
parts.push(decoratorsLines);
}
if (shouldAddParens) {
parts.unshift("(");
}
parts.push(linesWithoutParens);
if (shouldAddParens) {
parts.push(")");
}
return lines_1.concat(parts);
}
// Note that the `options` parameter of this function is what other
// functions in this file call the `config` object (that is, the
// configuration object originally passed into the Printer constructor).
// Its properties are documented in lib/options.js.
function genericPrintNoParens(path, options, print) {
var n = path.getValue();
if (!n) {
return lines_1.fromString("");
}
if (typeof n === "string") {
return lines_1.fromString(n, options);
}
namedTypes.Printable.assert(n);
var parts = [];
switch (n.type) {
case "File":
return path.call(print, "program");
case "Program":
// Babel 6
if (n.directives) {
path.each(function (childPath) {
parts.push(print(childPath), ";\n");
}, "directives");
}
if (n.interpreter) {
parts.push(path.call(print, "interpreter"));
}
parts.push(path.call(function (bodyPath) { return printStatementSequence(bodyPath, options, print); }, "body"));
return lines_1.concat(parts);
case "Noop": // Babel extension.
case "EmptyStatement":
return lines_1.fromString("");
case "ExpressionStatement":
return lines_1.concat([path.call(print, "expression"), ";"]);
case "ParenthesizedExpression": // Babel extension.
return lines_1.concat(["(", path.call(print, "expression"), ")"]);
case "BinaryExpression":
case "LogicalExpression":
case "AssignmentExpression":
return lines_1.fromString(" ").join([
path.call(print, "left"),
n.operator,
path.call(print, "right"),
]);
case "AssignmentPattern":
return lines_1.concat([
path.call(print, "left"),
" = ",
path.call(print, "right"),
]);
case "MemberExpression":
case "OptionalMemberExpression": {
parts.push(path.call(print, "object"));
var property = path.call(print, "property");
// Like n.optional, except with defaults applied, so optional
// defaults to true for OptionalMemberExpression nodes.
var optional = types.getFieldValue(n, "optional");
if (n.computed) {
parts.push(optional ? "?.[" : "[", property, "]");
}
else {
parts.push(optional ? "?." : ".", property);
}
return lines_1.concat(parts);
}
case "ChainExpression":
return path.call(print, "expression");
case "MetaProperty":
return lines_1.concat([
path.call(print, "meta"),
".",
path.call(print, "property"),
]);
case "BindExpression":
if (n.object) {
parts.push(path.call(print, "object"));
}
parts.push("::", path.call(print, "callee"));
return lines_1.concat(parts);
case "Path":
return lines_1.fromString(".").join(n.body);
case "Identifier":
return lines_1.concat([
lines_1.fromString(n.name, options),
n.optional ? "?" : "",
path.call(print, "typeAnnotation"),
]);
case "SpreadElement":
case "SpreadElementPattern":
case "RestProperty": // Babel 6 for ObjectPattern
case "SpreadProperty":
case "SpreadPropertyPattern":
case "ObjectTypeSpreadProperty":
case "RestElement":
return lines_1.concat([
"...",
path.call(print, "argument"),
path.call(print, "typeAnnotation"),
]);
case "FunctionDeclaration":
case "FunctionExpression":
case "TSDeclareFunction":
if (n.declare) {
parts.push("declare ");
}
if (n.async) {
parts.push("async ");
}
parts.push("function");
if (n.generator)
parts.push("*");
if (n.id) {
parts.push(" ", path.call(print, "id"), path.call(print, "typeParameters"));
}
else {
if (n.typeParameters) {
parts.push(path.call(print, "typeParameters"));
}
}
parts.push("(", printFunctionParams(path, options, print), ")", path.call(print, "returnType"));
if (n.body) {
parts.push(" ", path.call(print, "body"));
}
return lines_1.concat(parts);
case "ArrowFunctionExpression":
if (n.async) {
parts.push("async ");
}
if (n.typeParameters) {
parts.push(path.call(print, "typeParameters"));
}
if (!options.arrowParensAlways &&
n.params.length === 1 &&
!n.rest &&
n.params[0].type === "Identifier" &&
!n.params[0].typeAnnotation &&
!n.returnType) {
parts.push(path.call(print, "params", 0));
}
else {
parts.push("(", printFunctionParams(path, options, print), ")", path.call(print, "returnType"));
}
parts.push(" => ", path.call(print, "body"));
return lines_1.concat(parts);
case "MethodDefinition":
return printMethod(path, options, print);
case "YieldExpression":
parts.push("yield");
if (n.delegate)
parts.push("*");
if (n.argument)
parts.push(" ", path.call(print, "argument"));
return lines_1.concat(parts);
case "AwaitExpression":
parts.push("await");
if (n.all)
parts.push("*");
if (n.argument)
parts.push(" ", path.call(print, "argument"));
return lines_1.concat(parts);
case "ModuleDeclaration":
parts.push("module", path.call(print, "id"));
if (n.source) {
assert_1.default.ok(!n.body);
parts.push("from", path.call(print, "source"));
}
else {
parts.push(path.call(print, "body"));
}
return lines_1.fromString(" ").join(parts);
case "ImportSpecifier":
if (n.importKind && n.importKind !== "value") {
parts.push(n.importKind + " ");
}
if (n.imported) {
parts.push(path.call(print, "imported"));
if (n.local && n.local.name !== n.imported.name) {
parts.push(" as ", path.call(print, "local"));
}
}
else if (n.id) {
parts.push(path.call(print, "id"));
if (n.name) {
parts.push(" as ", path.call(print, "name"));
}
}
return lines_1.concat(parts);
case "ExportSpecifier":
if (n.local) {
parts.push(path.call(print, "local"));
if (n.exported && n.exported.name !== n.local.name) {
parts.push(" as ", path.call(print, "exported"));
}
}
else if (n.id) {
parts.push(path.call(print, "id"));
if (n.name) {
parts.push(" as ", path.call(print, "name"));
}
}
return lines_1.concat(parts);
case "ExportBatchSpecifier":
return lines_1.fromString("*");
case "ImportNamespaceSpecifier":
parts.push("* as ");
if (n.local) {
parts.push(path.call(print, "local"));
}
else if (n.id) {
parts.push(path.call(print, "id"));
}
return lines_1.concat(parts);
case "ImportDefaultSpecifier":
if (n.local) {
return path.call(print, "local");
}
return path.call(print, "id");
case "TSExportAssignment":
return lines_1.concat(["export = ", path.call(print, "expression")]);
case "ExportDeclaration":
case "ExportDefaultDeclaration":
case "ExportNamedDeclaration":
return printExportDeclaration(path, options, print);
case "ExportAllDeclaration":
parts.push("export *");
if (n.exported) {
parts.push(" as ", path.call(print, "exported"));
}
parts.push(" from ", path.call(print, "source"), ";");
return lines_1.concat(parts);
case "TSNamespaceExportDeclaration":
parts.push("export as namespace ", path.call(print, "id"));
return maybeAddSemicolon(lines_1.concat(parts));
case "ExportNamespaceSpecifier":
return lines_1.concat(["* as ", path.call(print, "exported")]);
case "ExportDefaultSpecifier":
return path.call(print, "exported");
case "Import":
return lines_1.fromString("import", options);
// Recast and ast-types currently support dynamic import(...) using
// either this dedicated ImportExpression type or a CallExpression
// whose callee has type Import.
// https://github.com/benjamn/ast-types/pull/365#issuecomment-605214486
case "ImportExpression":
return lines_1.concat(["import(", path.call(print, "source"), ")"]);
case "ImportDeclaration": {
parts.push("import ");
if (n.importKind && n.importKind !== "value") {
parts.push(n.importKind + " ");
}
if (n.specifiers && n.specifiers.length > 0) {
var unbracedSpecifiers_1 = [];
var bracedSpecifiers_1 = [];
path.each(function (specifierPath) {
var spec = specifierPath.getValue();
if (spec.type === "ImportSpecifier") {
bracedSpecifiers_1.push(print(specifierPath));
}
else if (spec.type === "ImportDefaultSpecifier" ||
spec.type === "ImportNamespaceSpecifier") {
unbracedSpecifiers_1.push(print(specifierPath));
}
}, "specifiers");
unbracedSpecifiers_1.forEach(function (lines, i) {
if (i > 0) {
parts.push(", ");
}
parts.push(lines);
});
if (bracedSpecifiers_1.length > 0) {
var lines = lines_1.fromString(", ").join(bracedSpecifiers_1);
if (lines.getLineLength(1) > options.wrapColumn) {
lines = lines_1.concat([
lines_1.fromString(",\n").join(bracedSpecifiers_1).indent(options.tabWidth),
",",
]);
}
if (unbracedSpecifiers_1.length > 0) {
parts.push(", ");
}
if (lines.length > 1) {
parts.push("{\n", lines, "\n}");
}
else if (options.objectCurlySpacing) {
parts.push("{ ", lines, " }");
}
else {
parts.push("{", lines, "}");
}
}
parts.push(" from ");
}
parts.push(path.call(print, "source"), ";");
return lines_1.concat(parts);
}
case "BlockStatement": {
var naked_1 = path.call(function (bodyPath) { return printStatementSequence(bodyPath, options, print); }, "body");
if (naked_1.isEmpty()) {
if (!n.directives || n.directives.length === 0) {
return lines_1.fromString("{}");
}
}
parts.push("{\n");
// Babel 6
if (n.directives) {
path.each(function (childPath) {
parts.push(maybeAddSemicolon(print(childPath).indent(options.tabWidth)), n.directives.length > 1 || !naked_1.isEmpty() ? "\n" : "");
}, "directives");
}
parts.push(naked_1.indent(options.tabWidth));
parts.push("\n}");
return lines_1.concat(parts);
}
case "ReturnStatement": {
parts.push("return");
if (n.argument) {
var argLines = path.call(print, "argument");
if (argLines.startsWithComment() ||
(argLines.length > 1 &&
namedTypes.JSXElement &&
namedTypes.JSXElement.check(n.argument))) {
parts.push(" (\n", argLines.indent(options.tabWidth), "\n)");
}
else {
parts.push(" ", argLines);
}
}
parts.push(";");
return lines_1.concat(parts);
}
case "CallExpression":
case "OptionalCallExpression":
parts.push(path.call(print, "callee"));
if (n.typeParameters) {
parts.push(path.call(print, "typeParameters"));
}
if (n.typeArguments) {
parts.push(path.call(print, "typeArguments"));
}
// Like n.optional, but defaults to true for OptionalCallExpression
// nodes that are missing an n.optional property (unusual),
// according to the OptionalCallExpression definition in ast-types.
if (types.getFieldValue(n, "optional")) {
parts.push("?.");
}
parts.push(printArgumentsList(path, options, print));
return lines_1.concat(parts);
case "ObjectExpression":
case "ObjectPattern":
case "ObjectTypeAnnotation": {
var isTypeAnnotation_1 = n.type === "ObjectTypeAnnotation";
var separator_1 = options.flowObjectCommas
? ","
: isTypeAnnotation_1
? ";"
: ",";
var fields = [];
var allowBreak_1 = false;
if (isTypeAnnotation_1) {
fields.push("indexers", "callProperties");
if (n.internalSlots != null) {
fields.push("internalSlots");
}
}
fields.push("properties");
var len_1 = 0;
fields.forEach(function (field) {
len_1 += n[field].length;
});
var oneLine_1 = (isTypeAnnotation_1 && len_1 === 1) || len_1 === 0;
var leftBrace = n.exact ? "{|" : "{";
var rightBrace = n.exact ? "|}" : "}";
parts.push(oneLine_1 ? leftBrace : leftBrace + "\n");
var leftBraceIndex = parts.length - 1;
var i_1 = 0;
fields.forEach(function (field) {
path.each(function (childPath) {
var lines = print(childPath);
if (!oneLine_1) {
lines = lines.indent(options.tabWidth);
}
var multiLine = !isTypeAnnotation_1 && lines.length > 1;
if (multiLine && allowBreak_1) {
// Similar to the logic for BlockStatement.
parts.push("\n");
}
parts.push(lines);
if (i_1 < len_1 - 1) {
// Add an extra line break if the previous object property
// had a multi-line value.
parts.push(separator_1 + (multiLine ? "\n\n" : "\n"));
allowBreak_1 = !multiLine;
}
else if (len_1 !== 1 && isTypeAnnotation_1) {
parts.push(separator_1);
}
else if (!oneLine_1 &&
util.isTrailingCommaEnabled(options, "objects") &&
childPath.getValue().type !== "RestElement") {
parts.push(separator_1);
}
i_1++;
}, field);
});
if (n.inexact) {
var line = lines_1.fromString("...", options);
if (oneLine_1) {
if (len_1 > 0) {
parts.push(separator_1, " ");
}
parts.push(line);
}
else {
// No trailing separator after ... to maintain parity with prettier.
parts.push("\n", line.indent(options.tabWidth));
}
}
parts.push(oneLine_1 ? rightBrace : "\n" + rightBrace);
if (i_1 !== 0 && oneLine_1 && options.objectCurlySpacing) {
parts[leftBraceIndex] = leftBrace + " ";
parts[parts.length - 1] = " " + rightBrace;
}
if (n.typeAnnotation) {
parts.push(path.call(print, "typeAnnotation"));
}
return lines_1.concat(parts);
}
case "PropertyPattern":
return lines_1.concat([
path.call(print, "key"),
": ",
path.call(print, "pattern"),
]);
case "ObjectProperty": // Babel 6
case "Property": {
// Non-standard AST node type.
if (n.method || n.kind === "get" || n.kind === "set") {
return printMethod(path, options, print);
}
if (n.shorthand && n.value.type === "AssignmentPattern") {
return path.call(print, "value");
}
var key = path.call(print, "key");
if (n.computed) {
parts.push("[", key, "]");
}
else {
parts.push(key);
}
if (!n.shorthand || n.key.name !== n.value.name) {
parts.push(": ", path.call(print, "value"));
}
return lines_1.concat(parts);
}
case "ClassMethod": // Babel 6
case "ObjectMethod": // Babel 6
case "ClassPrivateMethod":
case "TSDeclareMethod":
return printMethod(path, options, print);
case "PrivateName":
return lines_1.concat(["#", path.call(print, "id")]);
case "Decorator":
return lines_1.concat(["@", path.call(print, "expression")]);
case "ArrayExpression":
case "ArrayPattern": {
var elems = n.elements;
var len_2 = elems.length;
var printed_1 = path.map(print, "elements");
var joined = lines_1.fromString(", ").join(printed_1);
var oneLine_2 = joined.getLineLength(1) <= options.wrapColumn;
if (oneLine_2) {
if (options.arrayBracketSpacing) {
parts.push("[ ");
}
else {
parts.push("[");
}
}
else {
parts.push("[\n");
}
path.each(function (elemPath) {
var i = elemPath.getName();
var elem = elemPath.getValue();
if (!elem) {
// If the array expression ends with a hole, that hole
// will be ignored by the interpreter, but if it ends with
// two (or more) holes, we need to write out two (or more)
// commas so that the resulting code is interpreted with
// both (all) of the holes.
parts.push(",");
}
else {
var lines = printed_1[i];
if (oneLine_2) {
if (i > 0)
parts.push(" ");
}
else {
lines = lines.indent(options.tabWidth);
}
parts.push(lines);
if (i < len_2 - 1 ||
(!oneLine_2 && util.isTrailingCommaEnabled(options, "arrays")))
parts.push(",");
if (!oneLine_2)
parts.push("\n");
}
}, "elements");
if (oneLine_2 && options.arrayBracketSpacing) {
parts.push(" ]");
}
else {
parts.push("]");
}
if (n.typeAnnotation) {
parts.push(path.call(print, "typeAnnotation"));
}
return lines_1.concat(parts);
}
case "SequenceExpression":
return lines_1.fromString(", ").join(path.map(print, "expressions"));
case "ThisExpression":
return lines_1.fromString("this");
case "Super":
return lines_1.fromString("super");
case "NullLiteral": // Babel 6 Literal split
return lines_1.fromString("null");
case "RegExpLiteral": // Babel 6 Literal split
return lines_1.fromString(n.extra.raw);
case "BigIntLiteral": // Babel 7 Literal split
return lines_1.fromString(n.value + "n");
case "NumericLiteral": // Babel 6 Literal Split
// Keep original representation for numeric values not in base 10.
if (n.extra &&
typeof n.extra.raw === "string" &&
Number(n.extra.raw) === n.value) {
return lines_1.fromString(n.extra.raw, options);
}
return lines_1.fromString(n.value, options);
case "BooleanLiteral": // Babel 6 Literal split
case "StringLiteral": // Babel 6 Literal split
case "Literal":
// Numeric values may be in bases other than 10. Use their raw
// representation if equivalent.
if (typeof n.value === "number" &&
typeof n.raw === "string" &&
Number(n.raw) === n.value) {
return lines_1.fromString(n.raw, options);
}
if (typeof n.value !== "string") {
return lines_1.fromString(n.value, options);
}
return lines_1.fromString(nodeStr(n.value, options), options);
case "Directive": // Babel 6
return path.call(print, "value");
case "DirectiveLiteral": // Babel 6
return lines_1.fromString(nodeStr(n.value, options));
case "InterpreterDirective":
return lines_1.fromString("#!" + n.value + "\n", options);
case "ModuleSpecifier":
if (n.local) {
throw new Error("The ESTree ModuleSpecifier type should be abstract");
}
// The Esprima ModuleSpecifier type is just a string-valued
// Literal identifying the imported-from module.
return lines_1.fromString(nodeStr(n.value, options), options);
case "UnaryExpression":
parts.push(n.operator);
if (/[a-z]$/.test(n.operator))
parts.push(" ");
parts.push(path.call(print, "argument"));
return lines_1.concat(parts);
case "UpdateExpression":
parts.push(path.call(print, "argument"), n.operator);
if (n.prefix)
parts.reverse();
return lines_1.concat(parts);
case "ConditionalExpression":
return lines_1.concat([
path.call(print, "test"),
" ? ",
path.call(print, "consequent"),
" : ",
path.call(print, "alternate"),
]);
case "NewExpression": {
parts.push("new ", path.call(print, "callee"));
if (n.typeParameters) {
parts.push(path.call(print, "typeParameters"));
}
if (n.typeArguments) {
parts.push(path.call(print, "typeArguments"));
}
var args = n.arguments;
if (args) {
parts.push(printArgumentsList(path, options, print));
}
return lines_1.concat(parts);
}
case "VariableDeclaration": {
if (n.declare) {
parts.push("declare ");
}
parts.push(n.kind, " ");
var maxLen_1 = 0;
var printed = path.map(function (childPath) {
var lines = print(childPath);
maxLen_1 = Math.max(lines.length, maxLen_1);
return lines;
}, "declarations");
if (maxLen_1 === 1) {
parts.push(lines_1.fromString(", ").join(printed));
}
else if (printed.length > 1) {
parts.push(lines_1.fromString(",\n")
.join(printed)
.indentTail(n.kind.length + 1));
}
else {
parts.push(printed[0]);
}
// We generally want to terminate all variable declarations with a
// semicolon, except when they are children of for loops.
var parentNode = path.getParentNode();
if (!namedTypes.ForStatement.check(parentNode) &&
!namedTypes.ForInStatement.check(parentNode) &&
!(namedTypes.ForOfStatement &&
namedTypes.ForOfStatement.check(parentNode)) &&
!(namedTypes.ForAwaitStatement &&
namedTypes.ForAwaitStatement.check(parentNode))) {
parts.push(";");
}
return lines_1.concat(parts);
}
case "VariableDeclarator":
return n.init
? lines_1.fromString(" = ").join([
path.call(print, "id"),
path.call(print, "init"),
])
: path.call(print, "id");
case "WithStatement":
return lines_1.concat([
"with (",
path.call(print, "object"),
") ",
path.call(print, "body"),
]);
case "IfStatement": {
var con = adjustClause(path.call(print, "consequent"), options);
parts.push("if (", path.call(print, "test"), ")", con);
if (n.alternate)
parts.push(endsWithBrace(con) ? " else" : "\nelse", adjustClause(path.call(print, "alternate"), options));
return lines_1.concat(parts);
}
case "ForStatement": {
// TODO Get the for (;;) case right.
var init = path.call(print, "init");
var sep = init.length > 1 ? ";\n" : "; ";
var forParen = "for (";
var indented = lines_1.fromString(sep)
.join([init, path.call(print, "test"), path.call(print, "update")])
.indentTail(forParen.length);
var head = lines_1.concat([forParen, indented, ")"]);
var clause = adjustClause(path.call(print, "body"), options);
parts.push(head);
if (head.length > 1) {
parts.push("\n");
clause = clause.trimLeft();
}
parts.push(clause);
return lines_1.concat(parts);
}
case "WhileStatement":
return lines_1.concat([
"while (",
path.call(print, "test"),
")",
adjustClause(path.call(print, "body"), options),
]);
case "ForInStatement":
// Note: esprima can't actually parse "for each (".
return lines_1.concat([
n.each ? "for each (" : "for (",
path.call(print, "left"),
" in ",
path.call(print, "right"),
")",
adjustClause(path.call(print, "body"), options),
]);
case "ForOfStatement":
case "ForAwaitStatement":
parts.push("for ");
if (n.await || n.type === "ForAwaitStatement") {
parts.push("await ");
}
parts.push("(", path.call(print, "left"), " of ", path.call(print, "right"), ")", adjustClause(path.call(print, "body"), options));
return lines_1.concat(parts);
case "DoWhileStatement": {
var doBody = lines_1.concat([
"do",
adjustClause(path.call(print, "body"), options),
]);
parts.push(doBody);
if (endsWithBrace(doBody))
parts.push(" while");
else
parts.push("\nwhile");
parts.push(" (", path.call(print, "test"), ");");
return lines_1.concat(parts);
}
case "DoExpression": {
var statements = path.call(function (bodyPath) { return printStatementSequence(bodyPath, options, print); }, "body");
return lines_1.concat(["do {\n", statements.indent(options.tabWidth), "\n}"]);
}
case "BreakStatement":
parts.push("break");
if (n.label)
parts.push(" ", path.call(print, "label"));
parts.push(";");
return lines_1.concat(parts);
case "ContinueStatement":
parts.push("continue");
if (n.label)
parts.push(" ", path.call(print, "label"));
parts.push(";");
return lines_1.concat(parts);
case "LabeledStatement":
return lines_1.concat([
path.call(print, "label"),
":\n",
path.call(print, "body"),
]);
case "TryStatement":
parts.push("try ", path.call(print, "block"));
if (n.handler) {
parts.push(" ", path.call(print, "handler"));
}
else if (n.handlers) {
path.each(function (handlerPath) {
parts.push(" ", print(handlerPath));
}, "handlers");
}
if (n.finalizer) {
parts.push(" finally ", path.call(print, "finalizer"));
}
return lines_1.concat(parts);
case "CatchClause":
parts.push("catch ");
if (n.param) {
parts.push("(", path.call(print, "param"));
}
if (n.guard) {
// Note: esprima does not recognize conditional catch clauses.
parts.push(" if ", path.call(print, "guard"));
}
if (n.param) {
parts.push(") ");
}
parts.push(path.call(print, "body"));
return lines_1.concat(parts);
case "ThrowStatement":
return lines_1.concat(["throw ", path.call(print, "argument"), ";"]);
case "SwitchStatement":
return lines_1.concat([
"switch (",
path.call(print, "discriminant"),
") {\n",
lines_1.fromString("\n").join(path.map(print, "cases")),
"\n}",
]);
// Note: ignoring n.lexical because it has no printing consequences.
case "SwitchCase":
if (n.test)
parts.push("case ", path.call(print, "test"), ":");
else
parts.push("default:");
if (n.consequent.length > 0) {
parts.push("\n", path
.call(function (consequentPath) {
return printStatementSequence(consequentPath, options, print);
}, "consequent")
.indent(options.tabWidth));
}
return lines_1.concat(parts);
case "DebuggerStatement":
return lines_1.fromString("debugger;");
// JSX extensions below.
case "JSXAttribute":
parts.push(path.call(print, "name"));
if (n.value)
parts.push("=", path.call(print, "value"));
return lines_1.concat(parts);
case "JSXIdentifier":
return lines_1.fromString(n.name, options);
case "JSXNamespacedName":
return lines_1.fromString(":").join([
path.call(print, "namespace"),
path.call(print, "name"),
]);
case "JSXMemberExpression":
return lines_1.fromString(".").join([
path.call(print, "object"),
path.call(print, "property"),
]);
case "JSXSpreadAttribute":
return lines_1.concat(["{...", path.call(print, "argument"), "}"]);
case "JSXSpreadChild":
return lines_1.concat(["{...", path.call(print, "expression"), "}"]);
case "JSXExpressionContainer":
return lines_1.concat(["{", path.call(print, "expression"), "}"]);
case "JSXElement":
case "JSXFragment": {
var openingPropName = "opening" + (n.type === "JSXElement" ? "Element" : "Fragment");
var closingPropName = "closing" + (n.type === "JSXElement" ? "Element" : "Fragment");
var openingLines = path.call(print, openingPropName);
if (n[openingPropName].selfClosing) {
assert_1.default.ok(!n[closingPropName], "unexpected " +
closingPropName +
" element in self-closing " +
n.type);
return openingLines;
}
var childLines = lines_1.concat(path.map(function (childPath) {
var child = childPath.getValue();
if (namedTypes.Literal.check(child) &&
typeof child.value === "string") {
if (/\S/.test(child.value)) {
return child.value.replace(/^\s+|\s+$/g, "");
}
else if (/\n/.test(child.value)) {
return "\n";
}
}
return print(childPath);
}, "children")).indentTail(options.tabWidth);
var closingLines = path.call(print, closingPropName);
return lines_1.concat([openingLines, childLines, closingLines]);
}
case "JSXOpeningElement": {
parts.push("<", path.call(print, "name"));
var attrParts_1 = [];
path.each(function (attrPath) {
attrParts_1.push(" ", print(attrPath));
}, "attributes");
var attrLines = lines_1.concat(attrParts_1);
var needLineWrap = attrLines.length > 1 || attrLines.getLineLength(1) > options.wrapColumn;
if (needLineWrap) {
attrParts_1.forEach(function (part, i) {
if (part === " ") {
assert_1.default.strictEqual(i % 2, 0);
attrParts_1[i] = "\n";
}
});
attrLines = lines_1.concat(attrParts_1).indentTail(options.tabWidth);
}
parts.push(attrLines, n.selfClosing ? " />" : ">");
return lines_1.concat(parts);
}
case "JSXClosingElement":
return lines_1.concat(["</", path.call(print, "name"), ">"]);
case "JSXOpeningFragment":
return lines_1.fromString("<>");
case "JSXClosingFragment":
return lines_1.fromString("</>");
case "JSXText":
return lines_1.fromString(n.value, options);
case "JSXEmptyExpression":
return lines_1.fromString("");
case "TypeAnnotatedIdentifier":
return lines_1.concat([
path.call(print, "annotation"),
" ",
path.call(print, "identifier"),
]);
case "ClassBody":
if (n.body.length === 0) {
return lines_1.fromString("{}");
}
return lines_1.concat([
"{\n",
path
.call(function (bodyPath) { return printStatementSequence(bodyPath, options, print); }, "body")
.indent(options.tabWidth),
"\n}",
]);
case "ClassPropertyDefinition":
parts.push("static ", path.call(print, "definition"));
if (!namedTypes.MethodDefinition.check(n.definition))
parts.push(";");
return lines_1.concat(parts);
case "ClassProperty": {
if (n.declare) {
parts.push("declare ");
}
var access = n.accessibility || n.access;
if (typeof access === "string") {
parts.push(access, " ");
}
if (n.static) {
parts.push("static ");
}
if (n.abstract) {
parts.push("abstract ");
}
if (n.readonly) {
parts.push("readonly ");
}
var key = path.call(print, "key");
if (n.computed) {
key = lines_1.concat(["[", key, "]"]);
}
if (n.variance) {
key = lines_1.concat([printVariance(path, print), key]);
}
parts.push(key);
if (n.optional) {
parts.push("?");
}
if (n.typeAnnotation) {
parts.push(path.call(print, "typeAnnotation"));
}
if (n.value) {
parts.push(" = ", path.call(print, "value"));
}
parts.push(";");
return lines_1.concat(parts);
}
case "ClassPrivateProperty":
if (n.static) {
parts.push("static ");
}
parts.push(path.call(print, "key"));
if (n.typeAnnotation) {
parts.push(path.call(print, "typeAnnotation"));
}
if (n.value) {
parts.push(" = ", path.call(print, "value"));
}
parts.push(";");
return lines_1.concat(parts);
case "ClassDeclaration":
case "ClassExpression":
if (n.declare) {
parts.push("declare ");
}
if (n.abstract) {
parts.push("abstract ");
}
parts.push("class");
if (n.id) {
parts.push(" ", path.call(print, "id"));
}
if (n.typeParameters) {
parts.push(path.call(print, "typeParameters"));
}
if (n.superClass) {
parts.push(" extends ", path.call(print, "superClass"), path.call(print, "superTypeParameters"));
}
if (n["implements"] && n["implements"].length > 0) {
parts.push(" implements ", lines_1.fromString(", ").join(path.map(print, "implements")));
}
parts.push(" ", path.call(print, "body"));
return lines_1.concat(parts);
case "TemplateElement":
return lines_1.fromString(n.value.raw, options).lockIndentTail();
case "TemplateLiteral": {
var expressions_1 = path.map(print, "expressions");
parts.push("`");
path.each(function (childPath) {
var i = childPath.getName();
parts.push(print(childPath));
if (i < expressions_1.length) {
parts.push("${", expressions_1[i], "}");
}
}, "quasis");
parts.push("`");
return lines_1.concat(parts).lockIndentTail();
}
case "TaggedTemplateExpression":
return lines_1.concat([path.call(print, "tag"), path.call(print, "quasi")]);
// These types are unprintable because they serve as abstract
// supertypes for other (printable) types.
case "Node":
case "Printable":
case "SourceLocation":
case "Position":
case "Statement":
case "Function":
case "Pattern":
case "Expression":
case "Declaration":
case "Specifier":
case "NamedSpecifier":
case "Comment": // Supertype of Block and Line
case "Flow": // Supertype of all Flow AST node types
case "FlowType": // Supertype of all Flow types
case "FlowPredicate": // Supertype of InferredPredicate and DeclaredPredicate
case "MemberTypeAnnotation": // Flow
case "Type": // Flow
case "TSHasOptionalTypeParameterInstantiation":
case "TSHasOptionalTypeParameters":
case "TSHasOptionalTypeAnnotation":
case "ChainElement": // Supertype of MemberExpression and CallExpression
throw new Error("unprintable type: " + JSON.stringify(n.type));
case "CommentBlock": // Babel block comment.
case "Block": // Esprima block comment.
return lines_1.concat(["/*", lines_1.fromString(n.value, options), "*/"]);
case "CommentLine": // Babel line comment.
case "Line": // Esprima line comment.
return lines_1.concat(["//", lines_1.fromString(n.value, options)]);
// Type Annotations for Facebook Flow, typically stripped out or
// transformed away before printing.
case "TypeAnnotation":
if (n.typeAnnotation) {
if (n.typeAnnotation.type !== "FunctionTypeAnnotation") {
parts.push(": ");
}
parts.push(path.call(print, "typeAnnotation"));
return lines_1.concat(parts);
}
return lines_1.fromString("");
case "ExistentialTypeParam":
case "ExistsTypeAnnotation":
return lines_1.fromString("*", options);
case "EmptyTypeAnnotation":
return lines_1.fromString("empty", options);
case "AnyTypeAnnotation":
return lines_1.fromString("any", options);
case "MixedTypeAnnotation":
return lines_1.fromString("mixed", options);
case "ArrayTypeAnnotation":
return lines_1.concat([path.call(print, "elementType"), "[]"]);
case "TupleTypeAnnotation": {
var printed_2 = path.map(print, "types");
var joined = lines_1.fromString(", ").join(printed_2);
var oneLine_3 = joined.getLineLength(1) <= options.wrapColumn;
if (oneLine_3) {
if (options.arrayBracketSpacing) {
parts.push("[ ");
}
else {
parts.push("[");
}
}
else {
parts.push("[\n");
}
path.each(function (elemPath) {
var i = elemPath.getName();
var elem = elemPath.getValue();
if (!elem) {
// If the array expression ends with a hole, that hole
// will be ignored by the interpreter, but if it ends with
// two (or more) holes, we need to write out two (or more)
// commas so that the resulting code is interpreted with
// both (all) of the holes.
parts.push(",");
}
else {
var lines = printed_2[i];