2016-12-23 21:38:10 +03:00
|
|
|
var assert = require("assert");
|
|
|
|
var sourceMap = require("source-map");
|
|
|
|
var printComments = require("./comments").printComments;
|
|
|
|
var pp = require("./pp");
|
|
|
|
var fromString = pp.fromString;
|
|
|
|
var concat = pp.concat;
|
|
|
|
var isEmpty = pp.isEmpty;
|
|
|
|
var join = pp.join;
|
|
|
|
var line = pp.line;
|
|
|
|
var hardline = pp.hardline;
|
|
|
|
var softline = pp.softline;
|
|
|
|
var literalline = pp.literalline;
|
|
|
|
var group = pp.group;
|
|
|
|
var multilineGroup = pp.multilineGroup;
|
|
|
|
var indent = pp.indent;
|
|
|
|
var getFirstString = pp.getFirstString;
|
|
|
|
var hasHardLine = pp.hasHardLine;
|
|
|
|
var normalizeOptions = require("./options").normalize;
|
|
|
|
var types = require("ast-types");
|
|
|
|
var namedTypes = types.namedTypes;
|
|
|
|
var isString = types.builtInTypes.string;
|
|
|
|
var isObject = types.builtInTypes.object;
|
|
|
|
var FastPath = require("./fast-path");
|
|
|
|
var util = require("./util");
|
|
|
|
|
|
|
|
function PrintResult(code, sourceMap) {
|
|
|
|
assert.ok(this instanceof PrintResult);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
isString.assert(code);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
this.code = code;
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (sourceMap) {
|
|
|
|
isObject.assert(sourceMap);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
this.map = sourceMap;
|
|
|
|
}
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
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."
|
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
warnedAboutToString = true;
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
return this.code;
|
|
|
|
};
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
var emptyPrintResult = new PrintResult("");
|
|
|
|
|
|
|
|
function Printer(originalOptions) {
|
|
|
|
assert.ok(this instanceof Printer);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
var explicitTabWidth = originalOptions && originalOptions.tabWidth;
|
|
|
|
var options = normalizeOptions(originalOptions);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
assert.notStrictEqual(options, originalOptions);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
// 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) options.sourceFileName, so we null it out.
|
|
|
|
options.sourceFileName = null;
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
function printWithComments(path) {
|
|
|
|
assert.ok(path instanceof FastPath);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
return printComments(path, print);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
function print(path, includeComments) {
|
|
|
|
if (includeComments)
|
|
|
|
return printWithComments(path);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
assert.ok(path instanceof FastPath);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (!explicitTabWidth) {
|
|
|
|
var oldTabWidth = options.tabWidth;
|
|
|
|
var loc = path.getNode().loc;
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (loc && loc.lines && loc.lines.guessTabWidth) {
|
|
|
|
options.tabWidth = loc.lines.guessTabWidth();
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
var lines = maybeReprint(path);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
options.tabWidth = oldTabWidth;
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
return lines;
|
|
|
|
}
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
return maybeReprint(path);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
function maybeReprint(path) {
|
|
|
|
// TODO: remove this function entirely as we don't ever keep the
|
|
|
|
// previous formatting
|
|
|
|
return printRootGenerically(path);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
// Print the root node generically, but then resume reprinting its
|
|
|
|
// children non-generically.
|
|
|
|
function printRootGenerically(path, includeComments) {
|
2016-12-31 07:03:22 +03:00
|
|
|
return (includeComments ? printComments(
|
|
|
|
path,
|
|
|
|
printRootGenerically
|
|
|
|
) : genericPrint(path, options, printWithComments));
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
// Print the entire AST generically.
|
|
|
|
function printGenerically(path) {
|
|
|
|
// return genericPrint(path, options, printGenerically);
|
|
|
|
return printComments(path, p => genericPrint(p, options, printGenerically));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
this.print = function(ast) {
|
|
|
|
if (!ast) {
|
|
|
|
return emptyPrintResult;
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
var lines = print(FastPath.from(ast), true);
|
|
|
|
return new PrintResult(
|
|
|
|
lines.toString(options),
|
|
|
|
util.composeSourceMaps(
|
|
|
|
options.inputSourceMap,
|
2016-12-31 07:03:22 +03:00
|
|
|
lines.getSourceMap(options.sourceMapName, options.sourceRoot)
|
2016-12-23 21:38:10 +03:00
|
|
|
)
|
|
|
|
);
|
|
|
|
};
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
this.printGenerically = function(ast) {
|
|
|
|
if (!ast) {
|
|
|
|
return emptyPrintResult;
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
var path = FastPath.from(ast);
|
|
|
|
var oldReuseWhitespace = options.reuseWhitespace;
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
// Do not reuse whitespace (or anything else, for that matter)
|
|
|
|
// when printing generically.
|
|
|
|
options.reuseWhitespace = false;
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
var res = printGenerically(path);
|
|
|
|
var pr = new PrintResult(pp.print(options.wrapColumn, res));
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
options.reuseWhitespace = oldReuseWhitespace;
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
return pr;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.Printer = Printer;
|
|
|
|
|
|
|
|
function maybeAddParens(path, lines) {
|
2016-12-31 07:03:22 +03:00
|
|
|
return (path.needsParens() ? concat([ "(", lines, ")" ]) : lines);
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function genericPrint(path, options, printPath) {
|
|
|
|
assert.ok(path instanceof FastPath);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
var node = path.getValue();
|
|
|
|
var parts = [];
|
|
|
|
var needsParens = false;
|
2016-12-31 07:03:22 +03:00
|
|
|
var linesWithoutParens = genericPrintNoParens(path, options, printPath);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 01:00:11 +03:00
|
|
|
if (!node || isEmpty(linesWithoutParens)) {
|
2016-12-23 21:38:10 +03:00
|
|
|
return linesWithoutParens;
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (
|
|
|
|
node.decorators && node.decorators.length > 0 &&
|
2016-12-23 21:38:10 +03:00
|
|
|
// If the parent node is an export declaration, it will be
|
|
|
|
// responsible for printing node.decorators.
|
2016-12-31 07:03:22 +03:00
|
|
|
!util.getParentExportDeclaration(path)
|
|
|
|
) {
|
|
|
|
path.each(
|
|
|
|
function(decoratorPath) {
|
|
|
|
parts.push(printPath(decoratorPath), line);
|
|
|
|
},
|
|
|
|
"decorators"
|
|
|
|
);
|
|
|
|
} else
|
|
|
|
if (
|
|
|
|
util.isExportDeclaration(node) && node.declaration &&
|
|
|
|
node.declaration.decorators
|
|
|
|
) {
|
|
|
|
// Export declarations are responsible for printing any decorators
|
|
|
|
// that logically apply to node.declaration.
|
|
|
|
path.each(
|
|
|
|
function(decoratorPath) {
|
|
|
|
parts.push(printPath(decoratorPath), line);
|
|
|
|
},
|
|
|
|
"declaration",
|
|
|
|
"decorators"
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
// Nodes with decorators can't have parentheses, so we can avoid
|
|
|
|
// computing path.needsParens() except in this case.
|
|
|
|
needsParens = path.needsParens();
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (needsParens) {
|
|
|
|
parts.unshift("(");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(linesWithoutParens);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (needsParens) {
|
|
|
|
parts.push(")");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
return concat(parts);
|
|
|
|
}
|
|
|
|
|
|
|
|
function genericPrintNoParens(path, options, print) {
|
|
|
|
var n = path.getValue();
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (!n) {
|
|
|
|
return fromString("");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (typeof n === "string") {
|
|
|
|
return fromString(n, options);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-27 21:28:04 +03:00
|
|
|
// TODO: For some reason NumericLiteralTypeAnnotation is not
|
|
|
|
// printable so this throws, but I think that's a bug in ast-types.
|
|
|
|
// This assert isn't very useful though.
|
|
|
|
// namedTypes.Printable.assert(n);
|
2016-12-23 21:38:10 +03:00
|
|
|
var parts = [];
|
|
|
|
switch (n.type) {
|
2016-12-31 07:03:22 +03:00
|
|
|
case "File":
|
|
|
|
return path.call(print, "program");
|
|
|
|
case "Program":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
// Babel 6
|
|
|
|
if (n.directives) {
|
|
|
|
path.each(
|
|
|
|
function(childPath) {
|
2016-12-31 07:01:07 +03:00
|
|
|
parts.push(print(childPath), ";", hardline);
|
2016-12-31 07:03:22 +03:00
|
|
|
},
|
|
|
|
"directives"
|
|
|
|
);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(
|
|
|
|
path.call(
|
|
|
|
function(bodyPath) {
|
|
|
|
return printStatementSequence(bodyPath, options, print);
|
|
|
|
},
|
|
|
|
"body"
|
|
|
|
)
|
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
// Make sure the file always ends with a newline
|
|
|
|
parts.push(hardline);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
// Babel extension.
|
|
|
|
case "Noop":
|
|
|
|
case "EmptyStatement":
|
|
|
|
return fromString("");
|
|
|
|
case "ExpressionStatement":
|
|
|
|
return concat([ path.call(print, "expression"), ";" ]);
|
|
|
|
case // Babel extension.
|
|
|
|
"ParenthesizedExpression":
|
|
|
|
return concat([ "(", path.call(print, "expression"), ")" ]);
|
|
|
|
case "AssignmentExpression":
|
|
|
|
return group(
|
|
|
|
concat(
|
|
|
|
[
|
|
|
|
path.call(print, "left"),
|
2016-12-23 21:38:10 +03:00
|
|
|
" ",
|
2016-12-31 07:03:22 +03:00
|
|
|
n.operator,
|
|
|
|
" ",
|
|
|
|
path.call(print, "right")
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
case "BinaryExpression":
|
|
|
|
case "LogicalExpression":
|
|
|
|
return group(
|
|
|
|
concat(
|
|
|
|
[
|
|
|
|
path.call(print, "left"),
|
|
|
|
" ",
|
|
|
|
n.operator,
|
|
|
|
indent(options.tabWidth, concat([ line, path.call(print, "right") ]))
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
case "AssignmentPattern":
|
|
|
|
return concat(
|
|
|
|
[ path.call(print, "left"), " = ", path.call(print, "right") ]
|
|
|
|
);
|
|
|
|
case "MemberExpression":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(path.call(print, "object"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
var property = path.call(print, "property");
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.computed) {
|
|
|
|
parts.push("[", property, "]");
|
|
|
|
} else {
|
|
|
|
parts.push(".", property);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "MetaProperty":
|
|
|
|
return concat(
|
|
|
|
[ path.call(print, "meta"), ".", path.call(print, "property") ]
|
|
|
|
);
|
|
|
|
case "BindExpression":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.object) {
|
|
|
|
parts.push(path.call(print, "object"));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("::", path.call(print, "callee"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "Path":
|
|
|
|
return fromString(".").join(n.body);
|
|
|
|
case "Identifier":
|
|
|
|
return concat(
|
|
|
|
[ n.name, (n.optional ? "?" : ""), path.call(print, "typeAnnotation") ]
|
|
|
|
);
|
|
|
|
case "SpreadElement":
|
|
|
|
case "SpreadElementPattern":
|
|
|
|
// Babel 6 for ObjectPattern
|
|
|
|
case "RestProperty":
|
|
|
|
case "SpreadProperty":
|
|
|
|
case "SpreadPropertyPattern":
|
|
|
|
case "RestElement":
|
|
|
|
return concat([ "...", path.call(print, "argument") ]);
|
|
|
|
case "FunctionDeclaration":
|
|
|
|
case "FunctionExpression":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.async)
|
|
|
|
parts.push("async ");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("function");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.generator)
|
|
|
|
parts.push("*");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.id) {
|
|
|
|
parts.push(" ", path.call(print, "id"));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(
|
|
|
|
path.call(print, "typeParameters"),
|
|
|
|
group(
|
|
|
|
concat(
|
|
|
|
[
|
|
|
|
"(",
|
|
|
|
indent(
|
|
|
|
options.tabWidth,
|
|
|
|
concat([ softline, printFunctionParams(path, print) ])
|
|
|
|
),
|
|
|
|
softline,
|
|
|
|
")"
|
|
|
|
]
|
|
|
|
)
|
|
|
|
),
|
|
|
|
printReturnType(path, print),
|
|
|
|
" ",
|
|
|
|
path.call(print, "body")
|
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return group(concat(parts));
|
|
|
|
case "ArrowFunctionExpression":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.async)
|
|
|
|
parts.push("async ");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.typeParameters) {
|
|
|
|
parts.push(path.call(print, "typeParameters"));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (
|
|
|
|
!options.arrowParensAlways && n.params.length === 1 && !n.rest &&
|
|
|
|
n.params[0].type === "Identifier" &&
|
|
|
|
!n.params[0].typeAnnotation &&
|
|
|
|
!n.predicate &&
|
|
|
|
!n.returnType
|
|
|
|
) {
|
|
|
|
parts.push(path.call(print, "params", 0));
|
|
|
|
} else {
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(
|
2016-12-31 07:03:22 +03:00
|
|
|
"(",
|
|
|
|
printFunctionParams(path, print),
|
|
|
|
")",
|
|
|
|
printReturnType(path, print)
|
2016-12-23 21:38:10 +03:00
|
|
|
);
|
2016-12-31 07:03:22 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(" => ", path.call(print, "body"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "MethodDefinition":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.static) {
|
|
|
|
parts.push("static ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(printMethod(path, options, print));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "YieldExpression":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("yield");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.delegate)
|
|
|
|
parts.push("*");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.argument)
|
|
|
|
parts.push(" ", path.call(print, "argument"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "AwaitExpression":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("await");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.all)
|
|
|
|
parts.push("*");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.argument)
|
|
|
|
parts.push(" ", path.call(print, "argument"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ModuleDeclaration":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("module", path.call(print, "id"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.source) {
|
|
|
|
assert.ok(!n.body);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("from", path.call(print, "source"));
|
|
|
|
} else {
|
|
|
|
parts.push(path.call(print, "body"));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return fromString(" ").join(parts);
|
|
|
|
case "ImportSpecifier":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.imported) {
|
|
|
|
parts.push(path.call(print, "imported"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.local && n.local.name !== n.imported.name) {
|
|
|
|
parts.push(" as ", path.call(print, "local"));
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:03:22 +03:00
|
|
|
} else
|
|
|
|
if (n.id) {
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(path.call(print, "id"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (n.name) {
|
|
|
|
parts.push(" as ", path.call(print, "name"));
|
|
|
|
}
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ExportSpecifier":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.local) {
|
|
|
|
parts.push(path.call(print, "local"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.exported && n.exported.name !== n.local.name) {
|
|
|
|
parts.push(" as ", path.call(print, "exported"));
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if (n.id) {
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(path.call(print, "id"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (n.name) {
|
|
|
|
parts.push(" as ", path.call(print, "name"));
|
|
|
|
}
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ExportBatchSpecifier":
|
|
|
|
return fromString("*");
|
|
|
|
case "ImportNamespaceSpecifier":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("* as ");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.local) {
|
|
|
|
parts.push(path.call(print, "local"));
|
|
|
|
} else
|
|
|
|
if (n.id) {
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(path.call(print, "id"));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ImportDefaultSpecifier":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.local) {
|
|
|
|
return path.call(print, "local");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return path.call(print, "id");
|
|
|
|
case "ExportDeclaration":
|
|
|
|
case "ExportDefaultDeclaration":
|
|
|
|
case "ExportNamedDeclaration":
|
|
|
|
return printExportDeclaration(path, options, print);
|
|
|
|
case "ExportAllDeclaration":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("export *");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.exported) {
|
|
|
|
parts.push(" as ", path.call(print, "exported"));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(" from ", path.call(print, "source"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ExportNamespaceSpecifier":
|
|
|
|
return concat([ "* as ", path.call(print, "exported") ]);
|
|
|
|
case "ExportDefaultSpecifier":
|
|
|
|
return path.call(print, "exported");
|
|
|
|
case "ImportDeclaration":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("import ");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.importKind && n.importKind !== "value") {
|
|
|
|
parts.push(n.importKind + " ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.specifiers && n.specifiers.length > 0) {
|
|
|
|
var foundImportSpecifier = false;
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
path.each(
|
|
|
|
function(specifierPath) {
|
2016-12-23 21:38:10 +03:00
|
|
|
var i = specifierPath.getName();
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (i > 0) {
|
|
|
|
parts.push(", ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
var value = specifierPath.getValue();
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (
|
|
|
|
namedTypes.ImportDefaultSpecifier.check(value) ||
|
|
|
|
namedTypes.ImportNamespaceSpecifier.check(value)
|
|
|
|
) {
|
2016-12-23 21:38:10 +03:00
|
|
|
assert.strictEqual(foundImportSpecifier, false);
|
|
|
|
} else {
|
|
|
|
namedTypes.ImportSpecifier.assert(value);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (!foundImportSpecifier) {
|
|
|
|
foundImportSpecifier = true;
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push((options.objectCurlySpacing ? "{ " : "{"));
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(print(specifierPath));
|
2016-12-31 07:03:22 +03:00
|
|
|
},
|
|
|
|
"specifiers"
|
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (foundImportSpecifier) {
|
|
|
|
parts.push((options.objectCurlySpacing ? " }" : "}"));
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(" from ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(path.call(print, "source"), ";");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "BlockStatement":
|
|
|
|
var naked = path.call(
|
|
|
|
function(bodyPath) {
|
2016-12-23 21:38:10 +03:00
|
|
|
return printStatementSequence(bodyPath, options, print);
|
2016-12-31 07:03:22 +03:00
|
|
|
},
|
|
|
|
"body"
|
|
|
|
);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
// If there are no contents, return a simple block
|
|
|
|
if (!getFirstString(naked)) {
|
|
|
|
return "{}";
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("{");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
// Babel 6
|
|
|
|
if (n.directives) {
|
|
|
|
path.each(
|
|
|
|
function(childPath) {
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(
|
2016-12-31 07:03:22 +03:00
|
|
|
indent(
|
|
|
|
options.tabWidth,
|
|
|
|
concat([ line, print(childPath), ";", line ])
|
|
|
|
)
|
2016-12-23 21:38:10 +03:00
|
|
|
);
|
2016-12-31 07:03:22 +03:00
|
|
|
},
|
|
|
|
"directives"
|
|
|
|
);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(indent(options.tabWidth, concat([ hardline, naked ])));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(hardline, "}");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ReturnStatement":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("return");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
var arg = path.call(print, "argument");
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.argument) {
|
|
|
|
if (
|
|
|
|
namedTypes.JSXElement && namedTypes.JSXElement.check(n.argument) &&
|
|
|
|
hasHardLine(arg)
|
|
|
|
) {
|
2016-12-31 01:00:11 +03:00
|
|
|
parts.push(
|
2016-12-31 07:03:22 +03:00
|
|
|
" (",
|
|
|
|
indent(options.tabWidth, concat([ hardline, arg ])),
|
|
|
|
hardline,
|
|
|
|
")"
|
2016-12-31 01:00:11 +03:00
|
|
|
);
|
2016-12-31 07:03:22 +03:00
|
|
|
} else {
|
|
|
|
parts.push(" ", arg);
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:03:22 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(";");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "CallExpression":
|
|
|
|
return concat(
|
|
|
|
[ path.call(print, "callee"), printArgumentsList(path, options, print) ]
|
|
|
|
);
|
|
|
|
case "ObjectExpression":
|
|
|
|
case "ObjectPattern":
|
|
|
|
case "ObjectTypeAnnotation":
|
|
|
|
var allowBreak = false;
|
|
|
|
var isTypeAnnotation = n.type === "ObjectTypeAnnotation";
|
|
|
|
var separator = (isTypeAnnotation ? ";" : ",");
|
|
|
|
var fields = [];
|
|
|
|
var leftBrace = (n.exact ? "{|" : "{");
|
|
|
|
var rightBrace = (n.exact ? "|}" : "}");
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (isTypeAnnotation) {
|
|
|
|
fields.push("indexers", "callProperties");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
fields.push("properties");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
var i = 0;
|
|
|
|
var props = [];
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
fields.forEach(
|
|
|
|
function(field) {
|
|
|
|
path.each(
|
|
|
|
function(childPath) {
|
|
|
|
props.push(group(print(childPath)));
|
|
|
|
},
|
|
|
|
field
|
2016-12-23 21:38:10 +03:00
|
|
|
);
|
|
|
|
}
|
2016-12-31 07:03:22 +03:00
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (props.length === 0) {
|
|
|
|
return "{}";
|
|
|
|
} else {
|
|
|
|
return multilineGroup(
|
|
|
|
concat(
|
|
|
|
[
|
|
|
|
leftBrace,
|
|
|
|
indent(
|
|
|
|
options.tabWidth,
|
|
|
|
concat([ line, join(concat([ separator, line ]), props) ])
|
|
|
|
),
|
|
|
|
line,
|
|
|
|
rightBrace,
|
|
|
|
path.call(print, "typeAnnotation")
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
case "PropertyPattern":
|
|
|
|
return concat(
|
|
|
|
[ path.call(print, "key"), ": ", path.call(print, "pattern") ]
|
|
|
|
);
|
|
|
|
// Babel 6
|
|
|
|
case "ObjectProperty":
|
|
|
|
case // Non-standard AST node type.
|
|
|
|
"Property":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.method || n.kind === "get" || n.kind === "set") {
|
|
|
|
return printMethod(path, options, print);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.computed) {
|
|
|
|
parts.push("[", path.call(print, "key"), "]");
|
|
|
|
} else {
|
|
|
|
parts.push(path.call(print, (n.shorthand ? "value" : "key")));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (!n.shorthand) {
|
|
|
|
parts.push(": ", path.call(print, "value"));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case // Babel 6
|
|
|
|
"ClassMethod":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.static) {
|
|
|
|
parts.push("static ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts = parts.concat(printObjectMethod(path, options, print));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case // Babel 6
|
|
|
|
"ObjectMethod":
|
|
|
|
return printObjectMethod(path, options, print);
|
|
|
|
case "Decorator":
|
|
|
|
return concat([ "@", path.call(print, "expression") ]);
|
|
|
|
case "ArrayExpression":
|
|
|
|
case "ArrayPattern":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.elements.length === 0) {
|
|
|
|
parts.push("[]");
|
|
|
|
} else {
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(
|
2016-12-31 07:03:22 +03:00
|
|
|
multilineGroup(
|
|
|
|
concat(
|
|
|
|
[
|
|
|
|
"[",
|
|
|
|
indent(
|
|
|
|
options.tabWidth,
|
|
|
|
concat(
|
|
|
|
[
|
|
|
|
line,
|
|
|
|
join(concat([ ",", line ]), path.map(print, "elements"))
|
|
|
|
]
|
|
|
|
)
|
|
|
|
),
|
|
|
|
line,
|
|
|
|
"]"
|
|
|
|
]
|
|
|
|
)
|
|
|
|
)
|
2016-12-23 21:38:10 +03:00
|
|
|
);
|
2016-12-31 07:03:22 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.typeAnnotation)
|
|
|
|
parts.push(path.call(print, "typeAnnotation"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "SequenceExpression":
|
|
|
|
return join(", ", path.map(print, "expressions"));
|
|
|
|
case "ThisExpression":
|
|
|
|
return fromString("this");
|
|
|
|
case "Super":
|
|
|
|
return fromString("super");
|
|
|
|
case // Babel 6 Literal split
|
|
|
|
"NullLiteral":
|
|
|
|
return fromString("null");
|
|
|
|
case // Babel 6 Literal split
|
|
|
|
"RegExpLiteral":
|
|
|
|
return fromString(n.extra.raw);
|
|
|
|
// Babel 6 Literal split
|
|
|
|
case "BooleanLiteral":
|
|
|
|
// Babel 6 Literal split
|
|
|
|
case "NumericLiteral":
|
|
|
|
// Babel 6 Literal split
|
|
|
|
case "StringLiteral":
|
|
|
|
case "Literal":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (typeof n.value !== "string")
|
|
|
|
return fromString(n.value, options);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return nodeStr(n.value, options);
|
|
|
|
case // Babel 6
|
|
|
|
"Directive":
|
|
|
|
return path.call(print, "value");
|
|
|
|
case // Babel 6
|
|
|
|
"DirectiveLiteral":
|
|
|
|
return fromString(nodeStr(n.value, options));
|
|
|
|
case "ModuleSpecifier":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.local) {
|
|
|
|
throw new Error("The ESTree ModuleSpecifier type should be abstract");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
// The Esprima ModuleSpecifier type is just a string-valued
|
|
|
|
// Literal identifying the imported-from module.
|
|
|
|
return fromString(nodeStr(n.value, options), options);
|
|
|
|
case "UnaryExpression":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(n.operator);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (/[a-z]$/.test(n.operator))
|
|
|
|
parts.push(" ");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(path.call(print, "argument"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "UpdateExpression":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(path.call(print, "argument"), n.operator);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.prefix)
|
|
|
|
parts.reverse();
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ConditionalExpression":
|
|
|
|
return concat(
|
|
|
|
[
|
|
|
|
"(",
|
|
|
|
path.call(print, "test"),
|
|
|
|
" ? ",
|
|
|
|
path.call(print, "consequent"),
|
|
|
|
" : ",
|
|
|
|
path.call(print, "alternate"),
|
|
|
|
")"
|
|
|
|
]
|
|
|
|
);
|
|
|
|
case "NewExpression":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("new ", path.call(print, "callee"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
var args = n.arguments;
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (args) {
|
|
|
|
parts.push(printArgumentsList(path, options, print));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "VariableDeclaration":
|
|
|
|
var printed = path.map(
|
|
|
|
function(childPath) {
|
2016-12-23 21:38:10 +03:00
|
|
|
return print(childPath);
|
2016-12-31 07:03:22 +03:00
|
|
|
},
|
|
|
|
"declarations"
|
|
|
|
);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts = [
|
|
|
|
n.kind,
|
|
|
|
" ",
|
|
|
|
printed[0],
|
|
|
|
indent(
|
|
|
|
options.tabWidth,
|
|
|
|
concat(printed.slice(1).map(p => concat([ ",", line, p ])))
|
|
|
|
)
|
|
|
|
];
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
// We generally want to terminate all variable declarations with a
|
|
|
|
// semicolon, except when they are children of for loops.
|
|
|
|
var parentNode = path.getParentNode();
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (
|
|
|
|
!namedTypes.ForStatement.check(parentNode) &&
|
|
|
|
!namedTypes.ForInStatement.check(parentNode) &&
|
|
|
|
!(namedTypes.ForOfStatement &&
|
|
|
|
namedTypes.ForOfStatement.check(parentNode)) &&
|
|
|
|
!(namedTypes.ForAwaitStatement &&
|
|
|
|
namedTypes.ForAwaitStatement.check(parentNode))
|
|
|
|
) {
|
|
|
|
parts.push(";");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return multilineGroup(concat(parts));
|
|
|
|
case "VariableDeclarator":
|
|
|
|
return (n.init ? concat(
|
|
|
|
[ path.call(print, "id"), " = ", path.call(print, "init") ]
|
|
|
|
) : path.call(print, "id"));
|
|
|
|
case "WithStatement":
|
|
|
|
return concat(
|
|
|
|
[ "with (", path.call(print, "object"), ") ", path.call(print, "body") ]
|
|
|
|
);
|
|
|
|
// var con = adjustClause(path.call(print, "consequent"), options),
|
|
|
|
// parts = ["if (", path.call(print, "test"), ")", con];
|
|
|
|
// if (n.alternate)
|
|
|
|
// parts.push(
|
|
|
|
// endsWithBrace(con) ? " else" : "\nelse",
|
|
|
|
// adjustClause(path.call(print, "alternate"), options));
|
|
|
|
// return concat(parts);
|
|
|
|
case "IfStatement":
|
|
|
|
const con = adjustClause(path.call(print, "consequent"), options);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts = [
|
|
|
|
"if (",
|
|
|
|
group(
|
|
|
|
concat(
|
|
|
|
[
|
|
|
|
indent(
|
|
|
|
options.tabWidth,
|
|
|
|
concat([ softline, path.call(print, "test") ])
|
|
|
|
),
|
|
|
|
softline
|
|
|
|
]
|
|
|
|
)
|
|
|
|
),
|
|
|
|
")",
|
|
|
|
con
|
|
|
|
];
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.alternate) {
|
|
|
|
const hasBraces = getFirstString(con) === "{";
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(
|
|
|
|
(hasBraces ? " else" : "\nelse"),
|
|
|
|
adjustClause(path.call(print, "alternate"), options)
|
|
|
|
);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ForStatement":
|
|
|
|
// TODO Get the for (;;) case right.
|
|
|
|
return concat(
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
"for (",
|
2016-12-31 07:03:22 +03:00
|
|
|
group(
|
|
|
|
concat(
|
|
|
|
[
|
|
|
|
indent(
|
|
|
|
options.tabWidth,
|
|
|
|
concat(
|
|
|
|
[
|
|
|
|
softline,
|
|
|
|
path.call(print, "init"),
|
|
|
|
";",
|
|
|
|
line,
|
|
|
|
path.call(print, "test"),
|
|
|
|
";",
|
|
|
|
line,
|
|
|
|
path.call(print, "update")
|
|
|
|
]
|
|
|
|
)
|
|
|
|
),
|
|
|
|
softline
|
|
|
|
]
|
|
|
|
)
|
|
|
|
),
|
2016-12-23 21:38:10 +03:00
|
|
|
")",
|
|
|
|
adjustClause(path.call(print, "body"), options)
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "WhileStatement":
|
|
|
|
return concat(
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
"while (",
|
|
|
|
path.call(print, "test"),
|
|
|
|
")",
|
|
|
|
adjustClause(path.call(print, "body"), options)
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "ForInStatement":
|
|
|
|
// Note: esprima can't actually parse "for each (".
|
|
|
|
return concat(
|
|
|
|
[
|
|
|
|
(n.each ? "for each (" : "for ("),
|
2016-12-23 21:38:10 +03:00
|
|
|
path.call(print, "left"),
|
|
|
|
" in ",
|
|
|
|
path.call(print, "right"),
|
|
|
|
")",
|
|
|
|
adjustClause(path.call(print, "body"), options)
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "ForOfStatement":
|
|
|
|
return concat(
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
"for (",
|
|
|
|
path.call(print, "left"),
|
|
|
|
" of ",
|
|
|
|
path.call(print, "right"),
|
|
|
|
")",
|
|
|
|
adjustClause(path.call(print, "body"), options)
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "ForAwaitStatement":
|
|
|
|
return concat(
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
"for await (",
|
|
|
|
path.call(print, "left"),
|
|
|
|
" of ",
|
|
|
|
path.call(print, "right"),
|
|
|
|
")",
|
|
|
|
adjustClause(path.call(print, "body"), options)
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "DoWhileStatement":
|
|
|
|
var clause = adjustClause(path.call(print, "body"), options);
|
|
|
|
var doBody = concat([ "do", clause ]);
|
|
|
|
var parts = [ doBody ];
|
|
|
|
const hasBraces = getFirstString(clause) === "{";
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (hasBraces)
|
|
|
|
parts.push(" while");
|
|
|
|
else
|
|
|
|
parts.push(concat([ line, "while" ]));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(" (", path.call(print, "test"), ");");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "DoExpression":
|
|
|
|
var statements = path.call(
|
|
|
|
function(bodyPath) {
|
2016-12-23 21:38:10 +03:00
|
|
|
return printStatementSequence(bodyPath, options, print);
|
2016-12-31 07:03:22 +03:00
|
|
|
},
|
|
|
|
"body"
|
|
|
|
);
|
|
|
|
return concat([ "do {\n", statements.indent(options.tabWidth), "\n}" ]);
|
|
|
|
case "BreakStatement":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("break");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.label)
|
|
|
|
parts.push(" ", path.call(print, "label"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(";");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ContinueStatement":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("continue");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.label)
|
|
|
|
parts.push(" ", path.call(print, "label"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(";");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "LabeledStatement":
|
|
|
|
return concat(
|
|
|
|
[ path.call(print, "label"), ":", hardline, path.call(print, "body") ]
|
|
|
|
);
|
|
|
|
case "TryStatement":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("try ", path.call(print, "block"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.handler) {
|
|
|
|
parts.push(" ", path.call(print, "handler"));
|
|
|
|
} else
|
|
|
|
if (n.handlers) {
|
|
|
|
path.each(
|
|
|
|
function(handlerPath) {
|
|
|
|
parts.push(" ", print(handlerPath));
|
|
|
|
},
|
|
|
|
"handlers"
|
|
|
|
);
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.finalizer) {
|
|
|
|
parts.push(" finally ", path.call(print, "finalizer"));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "CatchClause":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("catch (", path.call(print, "param"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.guard)
|
|
|
|
// Note: esprima does not recognize conditional catch clauses.
|
|
|
|
parts.push(" if ", path.call(print, "guard"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(") ", path.call(print, "body"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ThrowStatement":
|
|
|
|
return concat([ "throw ", path.call(print, "argument"), ";" ]);
|
|
|
|
// Note: ignoring n.lexical because it has no printing consequences.
|
|
|
|
case "SwitchStatement":
|
|
|
|
return concat(
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
"switch (",
|
|
|
|
path.call(print, "discriminant"),
|
2016-12-27 21:28:04 +03:00
|
|
|
") {",
|
|
|
|
hardline,
|
|
|
|
join(hardline, path.map(print, "cases")),
|
|
|
|
hardline,
|
|
|
|
"}"
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "SwitchCase":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.test)
|
|
|
|
parts.push("case ", path.call(print, "test"), ":");
|
|
|
|
else
|
|
|
|
parts.push("default:");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.consequent.length > 0) {
|
|
|
|
parts.push(
|
|
|
|
indent(
|
2016-12-27 21:28:04 +03:00
|
|
|
options.tabWidth,
|
2016-12-31 07:03:22 +03:00
|
|
|
concat(
|
|
|
|
[
|
|
|
|
hardline,
|
|
|
|
path.call(
|
|
|
|
function(consequentPath) {
|
|
|
|
return printStatementSequence(consequentPath, options, print);
|
|
|
|
},
|
|
|
|
"consequent"
|
|
|
|
)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
// JSX extensions below.
|
|
|
|
case "DebuggerStatement":
|
|
|
|
return fromString("debugger;");
|
|
|
|
case "JSXAttribute":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(path.call(print, "name"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.value)
|
|
|
|
parts.push("=", path.call(print, "value"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "JSXIdentifier":
|
|
|
|
return fromString(n.name, options);
|
|
|
|
case "JSXNamespacedName":
|
|
|
|
return fromString(":").join(
|
|
|
|
[ path.call(print, "namespace"), path.call(print, "name") ]
|
|
|
|
);
|
|
|
|
case "JSXMemberExpression":
|
|
|
|
return fromString(".").join(
|
|
|
|
[ path.call(print, "object"), path.call(print, "property") ]
|
|
|
|
);
|
|
|
|
case "JSXSpreadAttribute":
|
|
|
|
return concat([ "{...", path.call(print, "argument"), "}" ]);
|
|
|
|
case "JSXExpressionContainer":
|
|
|
|
return concat([ "{", path.call(print, "expression"), "}" ]);
|
|
|
|
case "JSXElement":
|
|
|
|
var openingLines = path.call(print, "openingElement");
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.openingElement.selfClosing) {
|
|
|
|
assert.ok(!n.closingElement);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return openingLines;
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
var children = [];
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
path.map(
|
|
|
|
function(childPath) {
|
2016-12-23 21:38:10 +03:00
|
|
|
var child = childPath.getValue();
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (
|
|
|
|
namedTypes.Literal.check(child) && typeof child.value === "string"
|
|
|
|
) {
|
2016-12-23 21:38:10 +03:00
|
|
|
if (/\S/.test(child.value)) {
|
2016-12-31 01:00:11 +03:00
|
|
|
const beginBreak = child.value.match(/^\s*\n/);
|
|
|
|
const endBreak = child.value.match(/\n\s*$/);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 01:00:11 +03:00
|
|
|
children.push(
|
2016-12-31 07:03:22 +03:00
|
|
|
(beginBreak ? hardline : ""),
|
2016-12-31 01:00:11 +03:00
|
|
|
child.value.replace(/^\s+|\s+$/g, ""),
|
2016-12-31 07:03:22 +03:00
|
|
|
(endBreak ? hardline : "")
|
2016-12-31 01:00:11 +03:00
|
|
|
);
|
2016-12-31 07:03:22 +03:00
|
|
|
} else
|
|
|
|
if (/\n/.test(child.value)) {
|
|
|
|
children.push(hardline);
|
|
|
|
}
|
|
|
|
} else {
|
2016-12-31 01:00:11 +03:00
|
|
|
children.push(print(childPath));
|
|
|
|
}
|
2016-12-31 07:03:22 +03:00
|
|
|
},
|
|
|
|
"children"
|
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
var mostChildren = children.slice(0, -1);
|
|
|
|
var lastChild = children[children.length - 1];
|
|
|
|
var closingLines = path.call(print, "closingElement");
|
|
|
|
return concat(
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
openingLines,
|
|
|
|
indent(options.tabWidth, concat(mostChildren)),
|
2016-12-28 05:40:04 +03:00
|
|
|
lastChild || "",
|
2016-12-23 21:38:10 +03:00
|
|
|
closingLines
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "JSXOpeningElement":
|
|
|
|
return group(
|
|
|
|
concat(
|
|
|
|
[
|
|
|
|
"<",
|
|
|
|
path.call(print, "name"),
|
|
|
|
concat(path.map(attr => concat([ " ", print(attr) ]), "attributes")),
|
|
|
|
(n.selfClosing ? "/>" : ">")
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
case "JSXClosingElement":
|
|
|
|
return concat([ "</", path.call(print, "name"), ">" ]);
|
|
|
|
case "JSXText":
|
|
|
|
throw new Error("JSXTest should be handled by JSXElement");
|
|
|
|
case "JSXEmptyExpression":
|
|
|
|
return "";
|
|
|
|
case "TypeAnnotatedIdentifier":
|
|
|
|
return concat(
|
|
|
|
[ path.call(print, "annotation"), " ", path.call(print, "identifier") ]
|
|
|
|
);
|
|
|
|
case "ClassBody":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.body.length === 0) {
|
|
|
|
return fromString("{}");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
"{",
|
|
|
|
indent(
|
|
|
|
options.tabWidth,
|
2016-12-31 07:03:22 +03:00
|
|
|
concat(
|
|
|
|
[
|
|
|
|
hardline,
|
|
|
|
path.call(
|
|
|
|
function(bodyPath) {
|
|
|
|
return printStatementSequence(bodyPath, options, print);
|
|
|
|
},
|
|
|
|
"body"
|
|
|
|
)
|
|
|
|
]
|
|
|
|
)
|
2016-12-23 21:38:10 +03:00
|
|
|
),
|
|
|
|
hardline,
|
|
|
|
"}"
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "ClassPropertyDefinition":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("static ", path.call(print, "definition"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (!namedTypes.MethodDefinition.check(n.definition))
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(";");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ClassProperty":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.static)
|
|
|
|
parts.push("static ");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
var key = path.call(print, "key");
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.computed) {
|
|
|
|
key = concat([ "[", key, "]" ]);
|
|
|
|
} else
|
|
|
|
if (n.variance === "plus") {
|
|
|
|
key = concat([ "+", key ]);
|
|
|
|
} else
|
|
|
|
if (n.variance === "minus") {
|
|
|
|
key = concat([ "-", key ]);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(key);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.typeAnnotation)
|
|
|
|
parts.push(path.call(print, "typeAnnotation"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.value)
|
|
|
|
parts.push(" = ", path.call(print, "value"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(";");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ClassDeclaration":
|
|
|
|
case "ClassExpression":
|
|
|
|
return concat(printClass(path, print));
|
|
|
|
case "TemplateElement":
|
|
|
|
return join(literalline, n.value.raw.split("\n"));
|
|
|
|
case "TemplateLiteral":
|
|
|
|
var expressions = path.map(print, "expressions");
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("`");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
path.each(
|
|
|
|
function(childPath) {
|
2016-12-23 21:38:10 +03:00
|
|
|
var i = childPath.getName();
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(print(childPath));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (i < expressions.length) {
|
|
|
|
parts.push("${", expressions[i], "}");
|
|
|
|
}
|
2016-12-31 07:03:22 +03:00
|
|
|
},
|
|
|
|
"quasis"
|
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("`");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
// These types are unprintable because they serve as abstract
|
|
|
|
// supertypes for other (printable) types.
|
|
|
|
case "TaggedTemplateExpression":
|
|
|
|
return concat([ path.call(print, "tag"), path.call(print, "quasi") ]);
|
|
|
|
case "Node":
|
|
|
|
case "Printable":
|
|
|
|
case "SourceLocation":
|
|
|
|
case "Position":
|
|
|
|
case "Statement":
|
|
|
|
case "Function":
|
|
|
|
case "Pattern":
|
|
|
|
case "Expression":
|
|
|
|
case "Declaration":
|
|
|
|
case "Specifier":
|
|
|
|
case "NamedSpecifier":
|
|
|
|
// Supertype of Block and Line.
|
|
|
|
case "Comment":
|
|
|
|
// Flow
|
|
|
|
case "MemberTypeAnnotation":
|
|
|
|
case // Flow
|
|
|
|
"Type":
|
|
|
|
throw new Error("unprintable type: " + JSON.stringify(n.type));
|
|
|
|
// Babel block comment.
|
|
|
|
case "CommentBlock":
|
|
|
|
case // Esprima block comment.
|
|
|
|
"Block":
|
|
|
|
return concat([ "/*", fromString(n.value, options), "*/" ]);
|
|
|
|
// Babel line comment.
|
|
|
|
case "CommentLine":
|
|
|
|
case // Esprima line comment.
|
|
|
|
"Line":
|
|
|
|
return concat([ "//", fromString(n.value, options) ]);
|
|
|
|
// Type Annotations for Facebook Flow, typically stripped out or
|
|
|
|
// transformed away before printing.
|
|
|
|
case "TypeAnnotation":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.typeAnnotation) {
|
|
|
|
if (n.typeAnnotation.type !== "FunctionTypeAnnotation") {
|
|
|
|
parts.push(": ");
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(path.call(print, "typeAnnotation"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return "";
|
|
|
|
case "TupleTypeAnnotation":
|
|
|
|
return concat([ "[", join(", ", path.map(print, "types")), "]" ]);
|
|
|
|
case "ExistentialTypeParam":
|
|
|
|
case "ExistsTypeAnnotation":
|
|
|
|
return fromString("*", options);
|
|
|
|
case "EmptyTypeAnnotation":
|
|
|
|
return fromString("empty", options);
|
|
|
|
case "AnyTypeAnnotation":
|
|
|
|
return fromString("any", options);
|
|
|
|
case "MixedTypeAnnotation":
|
|
|
|
return fromString("mixed", options);
|
|
|
|
case "ArrayTypeAnnotation":
|
|
|
|
return concat([ path.call(print, "elementType"), "[]" ]);
|
|
|
|
case "BooleanTypeAnnotation":
|
|
|
|
return fromString("boolean", options);
|
|
|
|
case "NumericLiteralTypeAnnotation":
|
|
|
|
case "BooleanLiteralTypeAnnotation":
|
|
|
|
return "" + n.value;
|
|
|
|
case "DeclareClass":
|
|
|
|
return printFlowDeclaration(path, printClass(path, print));
|
|
|
|
case "DeclareFunction":
|
|
|
|
return printFlowDeclaration(
|
|
|
|
path,
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
"function ",
|
|
|
|
path.call(print, "id"),
|
2016-12-31 07:03:22 +03:00
|
|
|
(n.predicate ? " " : ""),
|
2016-12-30 22:10:52 +03:00
|
|
|
path.call(print, "predicate"),
|
2016-12-23 21:38:10 +03:00
|
|
|
";"
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "DeclareModule":
|
|
|
|
return printFlowDeclaration(
|
|
|
|
path,
|
|
|
|
[ "module ", path.call(print, "id"), " ", path.call(print, "body") ]
|
|
|
|
);
|
|
|
|
case "DeclareModuleExports":
|
|
|
|
return printFlowDeclaration(
|
|
|
|
path,
|
|
|
|
[ "module.exports", path.call(print, "typeAnnotation"), ";" ]
|
|
|
|
);
|
|
|
|
case "DeclareVariable":
|
|
|
|
return printFlowDeclaration(path, [ "var ", path.call(print, "id"), ";" ]);
|
|
|
|
case "DeclareExportAllDeclaration":
|
|
|
|
return concat([ "declare export * from ", path.call(print, "source") ]);
|
|
|
|
case "DeclareExportDeclaration":
|
|
|
|
return concat([ "declare ", printExportDeclaration(path, options, print) ]);
|
|
|
|
case "FunctionTypeAnnotation":
|
|
|
|
// FunctionTypeAnnotation is ambiguous:
|
|
|
|
// declare function foo(a: B): void; OR
|
|
|
|
// var A: (a: B) => void;
|
|
|
|
var parent = path.getParentNode(0);
|
|
|
|
var isArrowFunctionTypeAnnotation = !(!parent.variance &&
|
|
|
|
!parent.optional &&
|
|
|
|
namedTypes.ObjectTypeProperty.check(parent) ||
|
|
|
|
namedTypes.ObjectTypeCallProperty.check(parent) ||
|
|
|
|
namedTypes.DeclareFunction.check(path.getParentNode(2)));
|
|
|
|
var needsColon = isArrowFunctionTypeAnnotation &&
|
|
|
|
namedTypes.TypeAnnotation.check(parent);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (needsColon) {
|
|
|
|
parts.push(": ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(path.call(print, "typeParameters"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("(", printFunctionParams(path, print), ")");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
// The returnType is not wrapped in a TypeAnnotation, so the colon
|
|
|
|
// needs to be added separately.
|
|
|
|
if (n.returnType || n.predicate) {
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(
|
2016-12-31 07:03:22 +03:00
|
|
|
(isArrowFunctionTypeAnnotation ? " => " : ": "),
|
|
|
|
path.call(print, "returnType"),
|
|
|
|
path.call(print, "predicate")
|
2016-12-23 21:38:10 +03:00
|
|
|
);
|
2016-12-31 07:03:22 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "FunctionTypeParam":
|
|
|
|
return concat(
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
path.call(print, "name"),
|
2016-12-31 07:03:22 +03:00
|
|
|
(n.optional ? "?" : ""),
|
2016-12-23 21:38:10 +03:00
|
|
|
": ",
|
|
|
|
path.call(print, "typeAnnotation")
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "GenericTypeAnnotation":
|
|
|
|
return concat(
|
|
|
|
[ path.call(print, "id"), path.call(print, "typeParameters") ]
|
|
|
|
);
|
|
|
|
case "DeclareInterface":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("declare ");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
case "InterfaceDeclaration":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(
|
|
|
|
fromString("interface ", options),
|
|
|
|
path.call(print, "id"),
|
|
|
|
path.call(print, "typeParameters"),
|
|
|
|
" "
|
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n["extends"].length > 0) {
|
|
|
|
parts.push("extends ", join(", ", path.map(print, "extends")));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(" ", path.call(print, "body"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ClassImplements":
|
|
|
|
case "InterfaceExtends":
|
|
|
|
return concat(
|
|
|
|
[ path.call(print, "id"), path.call(print, "typeParameters") ]
|
|
|
|
);
|
|
|
|
case "IntersectionTypeAnnotation":
|
|
|
|
return join(" & ", path.map(print, "types"));
|
|
|
|
case "NullableTypeAnnotation":
|
|
|
|
return concat([ "?", path.call(print, "typeAnnotation") ]);
|
|
|
|
case "NullLiteralTypeAnnotation":
|
|
|
|
return fromString("null", options);
|
|
|
|
case "ThisTypeAnnotation":
|
|
|
|
return fromString("this", options);
|
|
|
|
case "NumberTypeAnnotation":
|
|
|
|
return fromString("number", options);
|
|
|
|
case "ObjectTypeCallProperty":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.static) {
|
|
|
|
parts.push("static ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(path.call(print, "value"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "ObjectTypeIndexer":
|
|
|
|
var variance = (n.variance === "plus" ? "+" : (n.variance ===
|
|
|
|
"minus" ? "-" : ""));
|
|
|
|
return concat(
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
variance,
|
|
|
|
"[",
|
|
|
|
path.call(print, "id"),
|
|
|
|
": ",
|
|
|
|
path.call(print, "key"),
|
|
|
|
"]: ",
|
|
|
|
path.call(print, "value")
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "ObjectTypeProperty":
|
|
|
|
var variance = (n.variance === "plus" ? "+" : (n.variance ===
|
|
|
|
"minus" ? "-" : ""));
|
|
|
|
// TODO: This is a bad hack and we need a better way to know
|
|
|
|
// when to emit an arrow function or not.
|
|
|
|
var isFunction = !n.variance && !n.optional &&
|
|
|
|
n.value.type === "FunctionTypeAnnotation";
|
|
|
|
return concat(
|
|
|
|
[
|
|
|
|
(n.static ? "static " : ""),
|
2016-12-23 21:38:10 +03:00
|
|
|
variance,
|
|
|
|
path.call(print, "key"),
|
2016-12-31 07:03:22 +03:00
|
|
|
(n.optional ? "?" : ""),
|
|
|
|
(isFunction ? "" : ": "),
|
2016-12-23 21:38:10 +03:00
|
|
|
path.call(print, "value")
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "QualifiedTypeIdentifier":
|
|
|
|
return concat(
|
|
|
|
[ path.call(print, "qualification"), ".", path.call(print, "id") ]
|
|
|
|
);
|
|
|
|
case "StringLiteralTypeAnnotation":
|
|
|
|
return fromString(nodeStr(n.value, options), options);
|
|
|
|
case "NumberLiteralTypeAnnotation":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
assert.strictEqual(typeof n.value, "number");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return fromString("" + n.value, options);
|
|
|
|
case "StringTypeAnnotation":
|
|
|
|
return fromString("string", options);
|
|
|
|
case "DeclareTypeAlias":
|
|
|
|
case "TypeAlias":
|
|
|
|
{
|
2016-12-30 08:01:44 +03:00
|
|
|
const parent = path.getParentNode(1);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (
|
|
|
|
n.type === "DeclareTypeAlias" ||
|
|
|
|
parent && parent.type === "DeclareModule"
|
|
|
|
) {
|
2016-12-30 08:01:44 +03:00
|
|
|
parts.push("declare ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-30 08:01:44 +03:00
|
|
|
parts.push(
|
2016-12-23 21:38:10 +03:00
|
|
|
"type ",
|
|
|
|
path.call(print, "id"),
|
|
|
|
path.call(print, "typeParameters"),
|
|
|
|
" = ",
|
|
|
|
path.call(print, "right"),
|
|
|
|
";"
|
2016-12-30 08:01:44 +03:00
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-30 08:01:44 +03:00
|
|
|
return concat(parts);
|
|
|
|
}
|
2016-12-31 07:03:22 +03:00
|
|
|
case "TypeCastExpression":
|
|
|
|
return concat(
|
|
|
|
[
|
2016-12-23 21:38:10 +03:00
|
|
|
"(",
|
|
|
|
path.call(print, "expression"),
|
|
|
|
path.call(print, "typeAnnotation"),
|
|
|
|
")"
|
2016-12-31 07:03:22 +03:00
|
|
|
]
|
|
|
|
);
|
|
|
|
case "TypeParameterDeclaration":
|
|
|
|
case "TypeParameterInstantiation":
|
|
|
|
return concat([ "<", join(", ", path.map(print, "params")), ">" ]);
|
|
|
|
case "TypeParameter":
|
|
|
|
switch (n.variance) {
|
|
|
|
case "plus":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("+");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
break;
|
|
|
|
case "minus":
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push("-");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
break;
|
2016-12-23 21:38:10 +03:00
|
|
|
default:
|
2016-12-31 07:03:22 +03:00
|
|
|
}
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(path.call(print, "name"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.bound) {
|
|
|
|
parts.push(path.call(print, "bound"));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n["default"]) {
|
|
|
|
parts.push("=", path.call(print, "default"));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return concat(parts);
|
|
|
|
case "TypeofTypeAnnotation":
|
|
|
|
return concat(
|
|
|
|
[ fromString("typeof ", options), path.call(print, "argument") ]
|
|
|
|
);
|
|
|
|
case "UnionTypeAnnotation":
|
|
|
|
return join(" | ", path.map(print, "types"));
|
|
|
|
case "VoidTypeAnnotation":
|
|
|
|
return "void";
|
|
|
|
case "NullTypeAnnotation":
|
|
|
|
return "null";
|
|
|
|
case "InferredPredicate":
|
|
|
|
return "%checks";
|
|
|
|
// Unhandled types below. If encountered, nodes of these types should
|
|
|
|
// be either left alone or desugared into AST types that are fully
|
|
|
|
// supported by the pretty-printer.
|
|
|
|
case "DeclaredPredicate":
|
|
|
|
return concat([ "%checks(", path.call(print, "value"), ")" ]);
|
|
|
|
// TODO
|
|
|
|
case "ClassHeritage":
|
|
|
|
// TODO
|
|
|
|
case "ComprehensionBlock":
|
|
|
|
// TODO
|
|
|
|
case "ComprehensionExpression":
|
|
|
|
// TODO
|
|
|
|
case "Glob":
|
|
|
|
// TODO
|
|
|
|
case "GeneratorExpression":
|
|
|
|
// TODO
|
|
|
|
case "LetStatement":
|
|
|
|
// TODO
|
|
|
|
case "LetExpression":
|
|
|
|
// TODO
|
|
|
|
case "GraphExpression":
|
|
|
|
// TODO
|
|
|
|
// XML types that nobody cares about or needs to print.
|
|
|
|
case "GraphIndexExpression":
|
|
|
|
case "XMLDefaultDeclaration":
|
|
|
|
case "XMLAnyName":
|
|
|
|
case "XMLQualifiedIdentifier":
|
|
|
|
case "XMLFunctionQualifiedIdentifier":
|
|
|
|
case "XMLAttributeSelector":
|
|
|
|
case "XMLFilterExpression":
|
|
|
|
case "XML":
|
|
|
|
case "XMLElement":
|
|
|
|
case "XMLList":
|
|
|
|
case "XMLEscape":
|
|
|
|
case "XMLText":
|
|
|
|
case "XMLStartTag":
|
|
|
|
case "XMLEndTag":
|
|
|
|
case "XMLPointTag":
|
|
|
|
case "XMLName":
|
|
|
|
case "XMLAttribute":
|
|
|
|
case "XMLCdata":
|
|
|
|
case "XMLComment":
|
|
|
|
case "XMLProcessingInstruction":
|
|
|
|
default:
|
|
|
|
debugger;
|
|
|
|
throw new Error("unknown type: " + JSON.stringify(n.type));
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
function printStatementSequence(path, options, print) {
|
2016-12-31 07:10:22 +03:00
|
|
|
let inClassBody = namedTypes.ClassBody &&
|
2016-12-31 07:03:22 +03:00
|
|
|
namedTypes.ClassBody.check(path.getParentNode());
|
2016-12-31 07:10:22 +03:00
|
|
|
let printed = [];
|
|
|
|
let prevAddSpacing = false;
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
path.map(
|
|
|
|
function(stmtPath, i) {
|
|
|
|
var stmt = stmtPath.getValue();
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
// Just in case the AST has been modified to contain falsy
|
|
|
|
// "statements," it's safer simply to skip them.
|
|
|
|
if (!stmt) {
|
|
|
|
return;
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
// Skip printing EmptyStatement nodes to avoid leaving stray
|
|
|
|
// semicolons lying around.
|
|
|
|
if (stmt.type === "EmptyStatement") {
|
|
|
|
return;
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
const addSpacing = shouldAddSpacing(stmt);
|
|
|
|
const stmtPrinted = print(stmtPath);
|
|
|
|
const parts = [];
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:10:22 +03:00
|
|
|
if (!prevAddSpacing && addSpacing && !isFirstStatement(stmtPath)) {
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(hardline);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(stmtPrinted);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
|
|
|
if (addSpacing && !isLastStatement(stmtPath)) {
|
2016-12-31 22:38:33 +03:00
|
|
|
parts.push(hardline);
|
2016-12-31 07:03:22 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
printed.push(concat(parts));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
|
|
|
prevAddSpacing = addSpacing;
|
2016-12-31 07:01:07 +03:00
|
|
|
}
|
2016-12-31 07:03:22 +03:00
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:01:07 +03:00
|
|
|
return join(hardline, printed);
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function printMethod(path, options, print) {
|
|
|
|
var node = path.getNode();
|
|
|
|
var kind = node.kind;
|
|
|
|
var parts = [];
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (node.type === "ObjectMethod" || node.type === "ClassMethod") {
|
|
|
|
node.value = node;
|
|
|
|
} else {
|
|
|
|
namedTypes.FunctionExpression.assert(node.value);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (node.value.async) {
|
|
|
|
parts.push("async ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (!kind || kind === "init" || kind === "method" || kind === "constructor") {
|
|
|
|
if (node.value.generator) {
|
|
|
|
parts.push("*");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
assert.ok(kind === "get" || kind === "set");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(kind, " ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
var key = path.call(print, "key");
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (node.computed) {
|
2016-12-31 07:03:22 +03:00
|
|
|
key = concat([ "[", key, "]" ]);
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(
|
|
|
|
key,
|
|
|
|
path.call(print, "value", "typeParameters"),
|
|
|
|
"(",
|
2016-12-31 07:03:22 +03:00
|
|
|
path.call(
|
|
|
|
function(valuePath) {
|
|
|
|
return printFunctionParams(valuePath, print);
|
|
|
|
},
|
|
|
|
"value"
|
|
|
|
),
|
2016-12-23 21:38:10 +03:00
|
|
|
")",
|
2016-12-30 21:32:43 +03:00
|
|
|
path.call(p => printReturnType(p, print), "value"),
|
2016-12-23 21:38:10 +03:00
|
|
|
" ",
|
|
|
|
path.call(print, "value", "body")
|
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
return concat(parts);
|
|
|
|
}
|
|
|
|
|
|
|
|
function printArgumentsList(path, options, print) {
|
|
|
|
var printed = path.map(print, "arguments");
|
|
|
|
var trailingComma = util.isTrailingCommaEnabled(options, "parameters");
|
|
|
|
var args;
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (printed.length === 0) {
|
2016-12-23 21:38:10 +03:00
|
|
|
args = "";
|
2016-12-31 07:03:22 +03:00
|
|
|
} else
|
|
|
|
if (printed.length === 1 && getFirstString(printed[0]) === "{") {
|
|
|
|
// If the only argument is an object, don't force it to be on
|
|
|
|
// newline and keep the braces on the same line as the parens
|
|
|
|
args = printed[0];
|
|
|
|
} else {
|
|
|
|
args = concat(
|
|
|
|
[
|
|
|
|
indent(
|
|
|
|
options.tabWidth,
|
|
|
|
concat([ softline, join(concat([ ",", line ]), printed) ])
|
|
|
|
),
|
|
|
|
softline
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return multilineGroup(concat([ "(", args, ")" ]));
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
|
|
|
|
2016-12-30 08:01:44 +03:00
|
|
|
function printFunctionParams(path, print) {
|
2016-12-23 21:38:10 +03:00
|
|
|
var fun = path.getValue();
|
2016-12-30 08:01:44 +03:00
|
|
|
// namedTypes.Function.assert(fun);
|
2016-12-23 21:38:10 +03:00
|
|
|
var printed = path.map(print, "params");
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (fun.defaults) {
|
2016-12-31 07:03:22 +03:00
|
|
|
path.each(
|
|
|
|
function(defExprPath) {
|
|
|
|
var i = defExprPath.getName();
|
|
|
|
var p = printed[i];
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (p && defExprPath.getValue()) {
|
|
|
|
printed[i] = concat([ p, " = ", print(defExprPath) ]);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"defaults"
|
|
|
|
);
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (fun.rest) {
|
2016-12-31 07:03:22 +03:00
|
|
|
printed.push(concat([ "...", path.call(print, "rest") ]));
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return group(join(concat([ ",", line ]), printed));
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function printObjectMethod(path, options, print) {
|
|
|
|
var objMethod = path.getValue();
|
|
|
|
var parts = [];
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (objMethod.async)
|
|
|
|
parts.push("async ");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (objMethod.generator)
|
|
|
|
parts.push("*");
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (
|
|
|
|
objMethod.method || objMethod.kind === "get" || objMethod.kind === "set"
|
|
|
|
) {
|
2016-12-23 21:38:10 +03:00
|
|
|
return printMethod(path, options, print);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
var key = path.call(print, "key");
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (objMethod.computed) {
|
|
|
|
parts.push("[", key, "]");
|
|
|
|
} else {
|
|
|
|
parts.push(key);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push(
|
|
|
|
"(",
|
2016-12-30 08:01:44 +03:00
|
|
|
printFunctionParams(path, print),
|
2016-12-23 21:38:10 +03:00
|
|
|
")",
|
2016-12-30 21:32:43 +03:00
|
|
|
printReturnType(path, print),
|
2016-12-23 21:38:10 +03:00
|
|
|
" ",
|
|
|
|
path.call(print, "body")
|
|
|
|
);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
return concat(parts);
|
|
|
|
}
|
|
|
|
|
2016-12-30 21:32:43 +03:00
|
|
|
function printReturnType(path, print) {
|
|
|
|
const n = path.getValue();
|
2016-12-31 07:03:22 +03:00
|
|
|
const parts = [ path.call(print, "returnType") ];
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n.predicate) {
|
2016-12-31 07:10:22 +03:00
|
|
|
// The return type will already add the colon, but otherwise we
|
|
|
|
// need to do it ourselves
|
|
|
|
parts.push((n.returnType ? " " : ": "), path.call(print, "predicate"));
|
2016-12-30 21:32:43 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-30 21:32:43 +03:00
|
|
|
return concat(parts);
|
|
|
|
}
|
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
function printExportDeclaration(path, options, print) {
|
|
|
|
var decl = path.getValue();
|
2016-12-31 07:03:22 +03:00
|
|
|
var parts = [ "export " ];
|
2016-12-23 21:38:10 +03:00
|
|
|
var shouldPrintSpaces = options.objectCurlySpacing;
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
namedTypes.Declaration.assert(decl);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (decl["default"] || decl.type === "ExportDefaultDeclaration") {
|
2016-12-23 21:38:10 +03:00
|
|
|
parts.push("default ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (decl.declaration) {
|
|
|
|
parts.push(path.call(print, "declaration"));
|
2016-12-31 07:03:22 +03:00
|
|
|
} else
|
|
|
|
if (decl.specifiers && decl.specifiers.length > 0) {
|
|
|
|
if (
|
|
|
|
decl.specifiers.length === 1 &&
|
|
|
|
decl.specifiers[0].type === "ExportBatchSpecifier"
|
|
|
|
) {
|
|
|
|
parts.push("*");
|
|
|
|
} else {
|
|
|
|
parts.push(
|
|
|
|
(decl.exportKind === "type" ? "type " : ""),
|
|
|
|
(shouldPrintSpaces ? "{ " : "{"),
|
|
|
|
join(", ", path.map(print, "specifiers")),
|
|
|
|
(shouldPrintSpaces ? " }" : "}")
|
|
|
|
);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (decl.source) {
|
|
|
|
parts.push(" from ", path.call(print, "source"));
|
|
|
|
}
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
return concat(parts);
|
|
|
|
}
|
|
|
|
|
|
|
|
function printFlowDeclaration(path, parts) {
|
|
|
|
var parentExportDecl = util.getParentExportDeclaration(path);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (parentExportDecl) {
|
2016-12-31 07:03:22 +03:00
|
|
|
assert.strictEqual(parentExportDecl.type, "DeclareExportDeclaration");
|
2016-12-23 21:38:10 +03:00
|
|
|
} else {
|
|
|
|
// If the parent node has type DeclareExportDeclaration, then it
|
|
|
|
// will be responsible for printing the "declare" token. Otherwise
|
|
|
|
// it needs to be printed with this non-exported declaration node.
|
|
|
|
parts.unshift("declare ");
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
return concat(parts);
|
|
|
|
}
|
|
|
|
|
2016-12-30 08:01:44 +03:00
|
|
|
function printClass(path, print) {
|
|
|
|
const n = path.getValue();
|
2016-12-31 07:03:22 +03:00
|
|
|
const parts = [ "class" ];
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-30 08:01:44 +03:00
|
|
|
if (n.id) {
|
2016-12-31 07:03:22 +03:00
|
|
|
parts.push(" ", path.call(print, "id"), path.call(print, "typeParameters"));
|
2016-12-30 08:01:44 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-30 08:01:44 +03:00
|
|
|
if (n.superClass) {
|
|
|
|
parts.push(
|
|
|
|
" extends ",
|
|
|
|
path.call(print, "superClass"),
|
|
|
|
path.call(print, "superTypeParameters")
|
|
|
|
);
|
2016-12-31 07:03:22 +03:00
|
|
|
} else
|
|
|
|
if (n.extends && n.extends.length > 0) {
|
|
|
|
parts.push(" extends ", join(", ", path.map(print, "extends")));
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
if (n["implements"] && n["implements"].length > 0) {
|
2016-12-30 08:01:44 +03:00
|
|
|
parts.push(
|
|
|
|
" implements ",
|
|
|
|
fromString(", ").join(path.map(print, "implements"))
|
|
|
|
);
|
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-30 08:01:44 +03:00
|
|
|
parts.push(" ", path.call(print, "body"));
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-30 08:01:44 +03:00
|
|
|
return parts;
|
|
|
|
}
|
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
function adjustClause(clause, options) {
|
2016-12-31 07:03:22 +03:00
|
|
|
if (getFirstString(clause) === "{") {
|
|
|
|
return concat([ " ", clause ]);
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-31 07:03:22 +03:00
|
|
|
return indent(options.tabWidth, concat([ hardline, clause ]));
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function lastNonSpaceCharacter(lines) {
|
|
|
|
var pos = lines.lastPos();
|
|
|
|
do {
|
|
|
|
var ch = lines.charAt(pos);
|
2016-12-31 22:38:58 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
if (/\S/.test(ch))
|
|
|
|
return ch;
|
|
|
|
} while (lines.prevPos(pos));
|
|
|
|
}
|
|
|
|
|
|
|
|
function swapQuotes(str) {
|
2016-12-31 07:03:22 +03:00
|
|
|
return str.replace(
|
|
|
|
/['"]/g,
|
|
|
|
function(m) {
|
|
|
|
return (m === "\"" ? "'" : "\"");
|
|
|
|
}
|
|
|
|
);
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function nodeStr(str, options) {
|
|
|
|
isString.assert(str);
|
2016-12-31 07:10:22 +03:00
|
|
|
|
2016-12-23 21:38:10 +03:00
|
|
|
switch (options.quote) {
|
2016-12-31 07:03:22 +03:00
|
|
|
case "auto":
|
|
|
|
var double = JSON.stringify(str);
|
|
|
|
var single = swapQuotes(JSON.stringify(swapQuotes(str)));
|
|
|
|
return (double.length > single.length ? single : double);
|
|
|
|
case "single":
|
|
|
|
return swapQuotes(JSON.stringify(swapQuotes(str)));
|
|
|
|
case "double":
|
|
|
|
default:
|
|
|
|
return JSON.stringify(str);
|
2016-12-23 21:38:10 +03:00
|
|
|
}
|
|
|
|
}
|
2016-12-31 07:01:07 +03:00
|
|
|
|
|
|
|
function shouldAddSpacing(node) {
|
2016-12-31 07:03:22 +03:00
|
|
|
return node.type === "IfStatement" || node.type === "ForStatement" ||
|
2016-12-31 07:01:07 +03:00
|
|
|
node.type === "ForInStatement" ||
|
|
|
|
node.type === "ForOfStatement" ||
|
|
|
|
node.type === "ExpressionStatement" ||
|
|
|
|
node.type === "FunctionDeclaration";
|
|
|
|
}
|
|
|
|
|
|
|
|
function isFirstStatement(path) {
|
|
|
|
const parent = path.getParentNode();
|
|
|
|
const node = path.getValue();
|
|
|
|
const body = parent.body;
|
|
|
|
return body && body[0] === node;
|
|
|
|
}
|
|
|
|
|
|
|
|
function isLastStatement(path) {
|
|
|
|
const parent = path.getParentNode();
|
|
|
|
const node = path.getValue();
|
|
|
|
const body = parent.body;
|
|
|
|
return body && body[body.length - 1] === node;
|
|
|
|
}
|