Merge pull request #3492 from loganfsmyth/codegen-cleanup
Refactor space insertion and remove some unneeded function options
This commit is contained in:
commit
4e1b4aecfd
@ -26,6 +26,7 @@ export default class Buffer {
|
||||
column: null,
|
||||
filename: null,
|
||||
};
|
||||
this._endsWithWord = false;
|
||||
}
|
||||
|
||||
printedCommentStarts: Object;
|
||||
@ -44,7 +45,7 @@ export default class Buffer {
|
||||
// catch up to this nodes newline if we're behind
|
||||
if (node.loc && this.format.retainLines && this.buf) {
|
||||
while (this.position.line < node.loc.start.line) {
|
||||
this._push("\n");
|
||||
this.push("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -98,15 +99,7 @@ export default class Buffer {
|
||||
*/
|
||||
|
||||
semicolon() {
|
||||
this.push(";");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure last character is a semicolon.
|
||||
*/
|
||||
|
||||
ensureSemicolon() {
|
||||
if (!this.isLast(";")) this.semicolon();
|
||||
this.token(";");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,7 +111,7 @@ export default class Buffer {
|
||||
if (this.format.minified && !this._lastPrintedIsEmptyStatement) {
|
||||
this._removeLast(";");
|
||||
}
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,22 +119,52 @@ export default class Buffer {
|
||||
*/
|
||||
|
||||
keyword(name: string) {
|
||||
this.push(name);
|
||||
this.word(name);
|
||||
this.space();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a space to the buffer unless it is compact (override with force).
|
||||
* Add a space to the buffer unless it is compact.
|
||||
*/
|
||||
|
||||
space(force?: boolean) {
|
||||
if (!force && this.format.compact) return;
|
||||
space() {
|
||||
if (this.format.compact) return;
|
||||
|
||||
if (force || this.buf && !this.isLast(" ") && !this.isLast("\n")) {
|
||||
if (this.buf && !this.endsWith(" ") && !this.endsWith("\n")) {
|
||||
this.push(" ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a token that can't be safely parsed without taking whitespace into account.
|
||||
*/
|
||||
|
||||
word(str: string) {
|
||||
if (this._endsWithWord) this.push(" ");
|
||||
|
||||
this.push(str);
|
||||
this._endsWithWord = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a simple token.
|
||||
*/
|
||||
|
||||
token(str: string) {
|
||||
// space is mandatory to avoid outputting <!--
|
||||
// http://javascript.spec.whatwg.org/#comment-syntax
|
||||
if ((str === "--" && this.last === "!") ||
|
||||
|
||||
// Need spaces for operators of the same kind to avoid: `a+++b`
|
||||
(str[0] === "+" && this.last === "+") ||
|
||||
(str[0] === "-" && this.last === "-")) {
|
||||
this.push(" ");
|
||||
}
|
||||
|
||||
this.push(str);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the last character.
|
||||
*/
|
||||
@ -152,7 +175,7 @@ export default class Buffer {
|
||||
}
|
||||
|
||||
_removeLast(cha: string) {
|
||||
if (!this._isLast(cha)) return;
|
||||
if (!this.endsWith(cha)) return;
|
||||
this.buf = this.buf.slice(0, -1);
|
||||
this.last = this.buf[this.buf.length - 1];
|
||||
this.position.unshift(cha);
|
||||
@ -188,7 +211,7 @@ export default class Buffer {
|
||||
if (state.printed) {
|
||||
this.dedent();
|
||||
this.newline();
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,7 +245,9 @@ export default class Buffer {
|
||||
|
||||
this.removeLast(" ");
|
||||
this._removeSpacesAfterLastNewline();
|
||||
this._push(repeat("\n", i));
|
||||
for (let j = 0; j < i; j++) {
|
||||
this.push("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -232,8 +257,10 @@ export default class Buffer {
|
||||
_removeSpacesAfterLastNewline() {
|
||||
let lastNewlineIndex = this.buf.lastIndexOf("\n");
|
||||
if (lastNewlineIndex >= 0 && this.get().length <= lastNewlineIndex) {
|
||||
let toRemove = this.buf.slice(lastNewlineIndex + 1);
|
||||
this.buf = this.buf.substring(0, lastNewlineIndex + 1);
|
||||
this.last = "\n";
|
||||
this.position.unshift(toRemove);
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,6 +284,8 @@ export default class Buffer {
|
||||
*/
|
||||
|
||||
withSource(prop: string, loc: Location, cb: () => void) {
|
||||
if (!this.opts.sourceMaps) return cb();
|
||||
|
||||
// Use the call stack to manage a stack of "source location" data.
|
||||
let originalLine = this._sourcePosition.line;
|
||||
let originalColumn = this._sourcePosition.column;
|
||||
@ -275,26 +304,12 @@ export default class Buffer {
|
||||
* Push a string to the buffer, maintaining indentation and newlines.
|
||||
*/
|
||||
|
||||
push(str: string, noIndent?: boolean) {
|
||||
if (!this.format.compact && this._indent && !noIndent && str !== "\n") {
|
||||
// we have an indent level and we aren't pushing a newline
|
||||
let indent = this.getIndent();
|
||||
|
||||
// replace all newlines with newlines with the indentation
|
||||
str = str.replace(/\n/g, `\n${indent}`);
|
||||
|
||||
push(str: string) {
|
||||
if (!this.format.compact && this._indent && str[0] !== "\n") {
|
||||
// we've got a newline before us so prepend on the indentation
|
||||
if (this.isLast("\n")) this._push(indent);
|
||||
if (this.endsWith("\n")) str = this.getIndent() + str;
|
||||
}
|
||||
|
||||
this._push(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a string to the buffer.
|
||||
*/
|
||||
|
||||
_push(str: string): void {
|
||||
// see startTerminatorless() instance method
|
||||
let parenPushNewlineState = this.parenPushNewlineState;
|
||||
if (parenPushNewlineState) {
|
||||
@ -308,7 +323,7 @@ export default class Buffer {
|
||||
|
||||
if (cha === "\n" || cha === "/") {
|
||||
// we're going to break this terminator expression so we need to add a parentheses
|
||||
this._push("(");
|
||||
str = "(" + str;
|
||||
this.indent();
|
||||
parenPushNewlineState.printed = true;
|
||||
}
|
||||
@ -318,12 +333,15 @@ export default class Buffer {
|
||||
}
|
||||
|
||||
// If there the line is ending, adding a new mapping marker is redundant
|
||||
if (str[0] !== "\n") this.map.mark(this._sourcePosition);
|
||||
if (this.opts.sourceMaps && str[0] !== "\n") this.map.mark(this._sourcePosition);
|
||||
|
||||
//
|
||||
this.position.push(str);
|
||||
this.buf += str;
|
||||
this.last = str[str.length - 1];
|
||||
|
||||
// Clear any state-tracking flags that may have been set.
|
||||
this._endsWithWord = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,6 +349,8 @@ export default class Buffer {
|
||||
*/
|
||||
|
||||
endsWith(str: string): boolean {
|
||||
if (Array.isArray(str)) return str.some((s) => this.endsWith(s));
|
||||
|
||||
if (str.length === 1) {
|
||||
return this.last === str;
|
||||
} else {
|
||||
@ -338,22 +358,4 @@ export default class Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a character is last in the buffer.
|
||||
*/
|
||||
|
||||
isLast(cha: string): boolean {
|
||||
if (this.format.compact) return false;
|
||||
return this._isLast(cha);
|
||||
}
|
||||
|
||||
_isLast(cha: string): boolean {
|
||||
let last = this.last;
|
||||
|
||||
if (Array.isArray(cha)) {
|
||||
return cha.indexOf(last) >= 0;
|
||||
} else {
|
||||
return cha === last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ export function Program(node: Object) {
|
||||
}
|
||||
|
||||
export function BlockStatement(node: Object) {
|
||||
this.push("{");
|
||||
this.token("{");
|
||||
this.printInnerComments(node);
|
||||
if (node.body.length) {
|
||||
this.newline();
|
||||
@ -27,7 +27,7 @@ export function BlockStatement(node: Object) {
|
||||
this.rightBrace();
|
||||
} else {
|
||||
this.source("end", node.loc);
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,6 +38,4 @@ export function Directive(node: Object) {
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function DirectiveLiteral(node: Object) {
|
||||
this.push(this._stringLiteral(node.value));
|
||||
}
|
||||
export { StringLiteral as DirectiveLiteral } from "./types";
|
||||
|
||||
@ -1,23 +1,27 @@
|
||||
export function ClassDeclaration(node: Object) {
|
||||
this.printJoin(node.decorators, node, { separator: "" });
|
||||
this.push("class");
|
||||
this.printJoin(node.decorators, node);
|
||||
this.word("class");
|
||||
|
||||
if (node.id) {
|
||||
this.push(" ");
|
||||
this.space();
|
||||
this.print(node.id, node);
|
||||
}
|
||||
|
||||
this.print(node.typeParameters, node);
|
||||
|
||||
if (node.superClass) {
|
||||
this.push(" extends ");
|
||||
this.space();
|
||||
this.word("extends");
|
||||
this.space();
|
||||
this.print(node.superClass, node);
|
||||
this.print(node.superTypeParameters, node);
|
||||
}
|
||||
|
||||
if (node.implements) {
|
||||
this.push(" implements ");
|
||||
this.printJoin(node.implements, node, { separator: ", " });
|
||||
this.space();
|
||||
this.word("implements");
|
||||
this.space();
|
||||
this.printList(node.implements, node);
|
||||
}
|
||||
|
||||
this.space();
|
||||
@ -27,10 +31,10 @@ export function ClassDeclaration(node: Object) {
|
||||
export { ClassDeclaration as ClassExpression };
|
||||
|
||||
export function ClassBody(node: Object) {
|
||||
this.push("{");
|
||||
this.token("{");
|
||||
this.printInnerComments(node);
|
||||
if (node.body.length === 0) {
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
} else {
|
||||
this.newline();
|
||||
|
||||
@ -43,14 +47,17 @@ export function ClassBody(node: Object) {
|
||||
}
|
||||
|
||||
export function ClassProperty(node: Object) {
|
||||
this.printJoin(node.decorators, node, { separator: "" });
|
||||
this.printJoin(node.decorators, node);
|
||||
|
||||
if (node.static) this.push("static ");
|
||||
if (node.static) {
|
||||
this.word("static");
|
||||
this.space();
|
||||
}
|
||||
this.print(node.key, node);
|
||||
this.print(node.typeAnnotation, node);
|
||||
if (node.value) {
|
||||
this.space();
|
||||
this.push("=");
|
||||
this.token("=");
|
||||
this.space();
|
||||
this.print(node.value, node);
|
||||
}
|
||||
@ -58,14 +65,16 @@ export function ClassProperty(node: Object) {
|
||||
}
|
||||
|
||||
export function ClassMethod(node: Object) {
|
||||
this.printJoin(node.decorators, node, { separator: "" });
|
||||
this.printJoin(node.decorators, node);
|
||||
|
||||
if (node.static) {
|
||||
this.push("static ");
|
||||
this.word("static");
|
||||
this.space();
|
||||
}
|
||||
|
||||
if (node.kind === "constructorCall") {
|
||||
this.push("call ");
|
||||
this.word("call");
|
||||
this.space();
|
||||
}
|
||||
|
||||
this._method(node);
|
||||
|
||||
@ -10,67 +10,62 @@ const ZERO_DECIMAL_INTEGER = /\.0+$/;
|
||||
const NON_DECIMAL_LITERAL = /^0[box]/;
|
||||
|
||||
export function UnaryExpression(node: Object) {
|
||||
let needsSpace = /[a-z]$/.test(node.operator);
|
||||
let arg = node.argument;
|
||||
|
||||
if (t.isUpdateExpression(arg) || t.isUnaryExpression(arg)) {
|
||||
needsSpace = true;
|
||||
if (node.operator === "void" || node.operator === "delete" || node.operator === "typeof") {
|
||||
this.word(node.operator);
|
||||
this.space();
|
||||
} else {
|
||||
this.token(node.operator);
|
||||
}
|
||||
|
||||
if (t.isUnaryExpression(arg) && arg.operator === "!") {
|
||||
needsSpace = false;
|
||||
}
|
||||
|
||||
this.push(node.operator);
|
||||
if (needsSpace) this.push(" ");
|
||||
this.print(node.argument, node);
|
||||
}
|
||||
|
||||
export function DoExpression(node: Object) {
|
||||
this.push("do");
|
||||
this.word("do");
|
||||
this.space();
|
||||
this.print(node.body, node);
|
||||
}
|
||||
|
||||
export function ParenthesizedExpression(node: Object) {
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.print(node.expression, node);
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
}
|
||||
|
||||
export function UpdateExpression(node: Object) {
|
||||
if (node.prefix) {
|
||||
this.push(node.operator);
|
||||
this.token(node.operator);
|
||||
this.print(node.argument, node);
|
||||
} else {
|
||||
this.print(node.argument, node);
|
||||
this.push(node.operator);
|
||||
this.token(node.operator);
|
||||
}
|
||||
}
|
||||
|
||||
export function ConditionalExpression(node: Object) {
|
||||
this.print(node.test, node);
|
||||
this.space();
|
||||
this.push("?");
|
||||
this.token("?");
|
||||
this.space();
|
||||
this.print(node.consequent, node);
|
||||
this.space();
|
||||
this.push(":");
|
||||
this.token(":");
|
||||
this.space();
|
||||
this.print(node.alternate, node);
|
||||
}
|
||||
|
||||
export function NewExpression(node: Object, parent: Object) {
|
||||
this.push("new ");
|
||||
this.word("new");
|
||||
this.space();
|
||||
this.print(node.callee, node);
|
||||
if (node.arguments.length === 0 && this.format.minified &&
|
||||
!t.isCallExpression(parent, { callee: node }) &&
|
||||
!t.isMemberExpression(parent) &&
|
||||
!t.isNewExpression(parent)) return;
|
||||
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.printList(node.arguments, node);
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
}
|
||||
|
||||
export function SequenceExpression(node: Object) {
|
||||
@ -78,30 +73,35 @@ export function SequenceExpression(node: Object) {
|
||||
}
|
||||
|
||||
export function ThisExpression() {
|
||||
this.push("this");
|
||||
this.word("this");
|
||||
}
|
||||
|
||||
export function Super() {
|
||||
this.push("super");
|
||||
this.word("super");
|
||||
}
|
||||
|
||||
export function Decorator(node: Object) {
|
||||
this.push("@");
|
||||
this.token("@");
|
||||
this.print(node.expression, node);
|
||||
this.newline();
|
||||
}
|
||||
|
||||
function commaSeparatorNewline() {
|
||||
this.token(",");
|
||||
this.push("\n");
|
||||
}
|
||||
|
||||
export function CallExpression(node: Object) {
|
||||
this.print(node.callee, node);
|
||||
if (node.loc) this.printAuxAfterComment();
|
||||
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
|
||||
let isPrettyCall = node._prettyCall && !this.format.retainLines && !this.format.compact;
|
||||
|
||||
let separator;
|
||||
if (isPrettyCall) {
|
||||
separator = ",\n";
|
||||
separator = commaSeparatorNewline;
|
||||
this.newline();
|
||||
this.indent();
|
||||
}
|
||||
@ -113,19 +113,19 @@ export function CallExpression(node: Object) {
|
||||
this.dedent();
|
||||
}
|
||||
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
}
|
||||
|
||||
function buildYieldAwait(keyword: string) {
|
||||
return function (node: Object) {
|
||||
this.push(keyword);
|
||||
this.word(keyword);
|
||||
|
||||
if (node.delegate) {
|
||||
this.push("*");
|
||||
this.token("*");
|
||||
}
|
||||
|
||||
if (node.argument) {
|
||||
this.push(" ");
|
||||
this.space();
|
||||
let terminatorState = this.startTerminatorless();
|
||||
this.print(node.argument, node);
|
||||
this.endTerminatorless(terminatorState);
|
||||
@ -149,7 +149,7 @@ export function ExpressionStatement(node: Object) {
|
||||
export function AssignmentPattern(node: Object) {
|
||||
this.print(node.left, node);
|
||||
this.space();
|
||||
this.push("=");
|
||||
this.token("=");
|
||||
this.space();
|
||||
this.print(node.right, node);
|
||||
}
|
||||
@ -161,43 +161,29 @@ export function AssignmentExpression(node: Object, parent: Object) {
|
||||
!n.needsParens(node, parent);
|
||||
|
||||
if (parens) {
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
}
|
||||
|
||||
this.print(node.left, node);
|
||||
|
||||
let spaces = !this.format.compact || node.operator === "in" || node.operator === "instanceof";
|
||||
if (spaces) this.push(" ");
|
||||
|
||||
this.push(node.operator);
|
||||
|
||||
if (!spaces) {
|
||||
// space is mandatory to avoid outputting <!--
|
||||
// http://javascript.spec.whatwg.org/#comment-syntax
|
||||
spaces = node.operator === "<" &&
|
||||
t.isUnaryExpression(node.right, { prefix: true, operator: "!" }) &&
|
||||
t.isUnaryExpression(node.right.argument, { prefix: true, operator: "--" });
|
||||
|
||||
// Need spaces for operators of the same kind to avoid: `a+++b`
|
||||
if (!spaces) {
|
||||
let right = getLeftMost(node.right);
|
||||
spaces = t.isUnaryExpression(right, { prefix: true, operator: node.operator }) ||
|
||||
t.isUpdateExpression(right, { prefix: true, operator: node.operator + node.operator });
|
||||
}
|
||||
this.space();
|
||||
if (node.operator === "in" || node.operator === "instanceof") {
|
||||
this.word(node.operator);
|
||||
} else {
|
||||
this.token(node.operator);
|
||||
}
|
||||
|
||||
if (spaces) this.push(" ");
|
||||
this.space();
|
||||
|
||||
this.print(node.right, node);
|
||||
|
||||
if (parens) {
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
}
|
||||
}
|
||||
|
||||
export function BindExpression(node: Object) {
|
||||
this.print(node.object, node);
|
||||
this.push("::");
|
||||
this.token("::");
|
||||
this.print(node.callee, node);
|
||||
}
|
||||
|
||||
@ -219,9 +205,9 @@ export function MemberExpression(node: Object) {
|
||||
}
|
||||
|
||||
if (computed) {
|
||||
this.push("[");
|
||||
this.token("[");
|
||||
this.print(node.property, node);
|
||||
this.push("]");
|
||||
this.token("]");
|
||||
} else {
|
||||
if (t.isNumericLiteral(node.object)) {
|
||||
let val = this.getPossibleRaw(node.object) || node.object.value;
|
||||
@ -230,24 +216,17 @@ export function MemberExpression(node: Object) {
|
||||
!SCIENTIFIC_NOTATION.test(val) &&
|
||||
!ZERO_DECIMAL_INTEGER.test(val) &&
|
||||
!this.endsWith(".")) {
|
||||
this.push(".");
|
||||
this.token(".");
|
||||
}
|
||||
}
|
||||
|
||||
this.push(".");
|
||||
this.token(".");
|
||||
this.print(node.property, node);
|
||||
}
|
||||
}
|
||||
|
||||
export function MetaProperty(node: Object) {
|
||||
this.print(node.meta, node);
|
||||
this.push(".");
|
||||
this.token(".");
|
||||
this.print(node.property, node);
|
||||
}
|
||||
|
||||
function getLeftMost(binaryExpr) {
|
||||
if (!t.isBinaryExpression(binaryExpr)) {
|
||||
return binaryExpr;
|
||||
}
|
||||
return getLeftMost(binaryExpr.left);
|
||||
}
|
||||
|
||||
@ -3,89 +3,103 @@
|
||||
import * as t from "babel-types";
|
||||
|
||||
export function AnyTypeAnnotation() {
|
||||
this.push("any");
|
||||
this.word("any");
|
||||
}
|
||||
|
||||
export function ArrayTypeAnnotation(node: Object) {
|
||||
this.print(node.elementType, node);
|
||||
this.push("[");
|
||||
this.push("]");
|
||||
this.token("[");
|
||||
this.token("]");
|
||||
}
|
||||
|
||||
export function BooleanTypeAnnotation() {
|
||||
this.push("bool");
|
||||
this.word("bool");
|
||||
}
|
||||
|
||||
export function BooleanLiteralTypeAnnotation(node: Object) {
|
||||
this.push(node.value ? "true" : "false");
|
||||
this.word(node.value ? "true" : "false");
|
||||
}
|
||||
|
||||
export function NullLiteralTypeAnnotation() {
|
||||
this.push("null");
|
||||
this.word("null");
|
||||
}
|
||||
|
||||
export function DeclareClass(node: Object) {
|
||||
this.push("declare class ");
|
||||
this.word("declare");
|
||||
this.space();
|
||||
this.word("class");
|
||||
this.space();
|
||||
this._interfaceish(node);
|
||||
}
|
||||
|
||||
export function DeclareFunction(node: Object) {
|
||||
this.push("declare function ");
|
||||
this.word("declare");
|
||||
this.space();
|
||||
this.word("function");
|
||||
this.space();
|
||||
this.print(node.id, node);
|
||||
this.print(node.id.typeAnnotation.typeAnnotation, node);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function DeclareInterface(node: Object) {
|
||||
this.push("declare ");
|
||||
this.word("declare");
|
||||
this.space();
|
||||
this.InterfaceDeclaration(node);
|
||||
}
|
||||
|
||||
export function DeclareModule(node: Object) {
|
||||
this.push("declare module ");
|
||||
this.word("declare");
|
||||
this.space();
|
||||
this.word("module");
|
||||
this.space();
|
||||
this.print(node.id, node);
|
||||
this.space();
|
||||
this.print(node.body, node);
|
||||
}
|
||||
|
||||
export function DeclareTypeAlias(node: Object) {
|
||||
this.push("declare ");
|
||||
this.word("declare");
|
||||
this.space();
|
||||
this.TypeAlias(node);
|
||||
}
|
||||
|
||||
export function DeclareVariable(node: Object) {
|
||||
this.push("declare var ");
|
||||
this.word("declare");
|
||||
this.space();
|
||||
this.word("var");
|
||||
this.space();
|
||||
this.print(node.id, node);
|
||||
this.print(node.id.typeAnnotation, node);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function ExistentialTypeParam() {
|
||||
this.push("*");
|
||||
this.token("*");
|
||||
}
|
||||
|
||||
export function FunctionTypeAnnotation(node: Object, parent: Object) {
|
||||
this.print(node.typeParameters, node);
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.printList(node.params, node);
|
||||
|
||||
if (node.rest) {
|
||||
if (node.params.length) {
|
||||
this.push(",");
|
||||
this.token(",");
|
||||
this.space();
|
||||
}
|
||||
this.push("...");
|
||||
this.token("...");
|
||||
this.print(node.rest, node);
|
||||
}
|
||||
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
|
||||
// this node type is overloaded, not sure why but it makes it EXTREMELY annoying
|
||||
if (parent.type === "ObjectTypeProperty" || parent.type === "ObjectTypeCallProperty" || parent.type === "DeclareFunction") {
|
||||
this.push(":");
|
||||
this.token(":");
|
||||
} else {
|
||||
this.space();
|
||||
this.push("=>");
|
||||
this.token("=>");
|
||||
}
|
||||
|
||||
this.space();
|
||||
@ -94,8 +108,8 @@ export function FunctionTypeAnnotation(node: Object, parent: Object) {
|
||||
|
||||
export function FunctionTypeParam(node: Object) {
|
||||
this.print(node.name, node);
|
||||
if (node.optional) this.push("?");
|
||||
this.push(":");
|
||||
if (node.optional) this.token("?");
|
||||
this.token(":");
|
||||
this.space();
|
||||
this.print(node.typeAnnotation, node);
|
||||
}
|
||||
@ -111,90 +125,102 @@ export function _interfaceish(node: Object) {
|
||||
this.print(node.id, node);
|
||||
this.print(node.typeParameters, node);
|
||||
if (node.extends.length) {
|
||||
this.push(" extends ");
|
||||
this.printJoin(node.extends, node, { separator: ", " });
|
||||
this.space();
|
||||
this.word("extends");
|
||||
this.space();
|
||||
this.printList(node.extends, node);
|
||||
}
|
||||
if (node.mixins && node.mixins.length) {
|
||||
this.push(" mixins ");
|
||||
this.printJoin(node.mixins, node, { separator: ", " });
|
||||
this.space();
|
||||
this.word("mixins");
|
||||
this.space();
|
||||
this.printList(node.mixins, node);
|
||||
}
|
||||
this.space();
|
||||
this.print(node.body, node);
|
||||
}
|
||||
|
||||
export function InterfaceDeclaration(node: Object) {
|
||||
this.push("interface ");
|
||||
this.word("interface");
|
||||
this.space();
|
||||
this._interfaceish(node);
|
||||
}
|
||||
|
||||
function andSeparator() {
|
||||
this.space();
|
||||
this.token("&");
|
||||
this.space();
|
||||
}
|
||||
|
||||
export function IntersectionTypeAnnotation(node: Object) {
|
||||
this.printJoin(node.types, node, { separator: " & " });
|
||||
this.printJoin(node.types, node, { separator: andSeparator });
|
||||
}
|
||||
|
||||
export function MixedTypeAnnotation() {
|
||||
this.push("mixed");
|
||||
this.word("mixed");
|
||||
}
|
||||
|
||||
export function NullableTypeAnnotation(node: Object) {
|
||||
this.push("?");
|
||||
this.token("?");
|
||||
this.print(node.typeAnnotation, node);
|
||||
}
|
||||
|
||||
export { NumericLiteral as NumericLiteralTypeAnnotation } from "./types";
|
||||
export {
|
||||
NumericLiteral as NumericLiteralTypeAnnotation,
|
||||
StringLiteral as StringLiteralTypeAnnotation,
|
||||
} from "./types";
|
||||
|
||||
export function NumberTypeAnnotation() {
|
||||
this.push("number");
|
||||
}
|
||||
|
||||
export function StringLiteralTypeAnnotation(node: Object) {
|
||||
this.push(this._stringLiteral(node.value));
|
||||
this.word("number");
|
||||
}
|
||||
|
||||
export function StringTypeAnnotation() {
|
||||
this.push("string");
|
||||
this.word("string");
|
||||
}
|
||||
|
||||
export function ThisTypeAnnotation() {
|
||||
this.push("this");
|
||||
this.word("this");
|
||||
}
|
||||
|
||||
export function TupleTypeAnnotation(node: Object) {
|
||||
this.push("[");
|
||||
this.printJoin(node.types, node, { separator: ", " });
|
||||
this.push("]");
|
||||
this.token("[");
|
||||
this.printList(node.types, node);
|
||||
this.token("]");
|
||||
}
|
||||
|
||||
export function TypeofTypeAnnotation(node: Object) {
|
||||
this.push("typeof ");
|
||||
this.word("typeof");
|
||||
this.space();
|
||||
this.print(node.argument, node);
|
||||
}
|
||||
|
||||
export function TypeAlias(node: Object) {
|
||||
this.push("type ");
|
||||
this.word("type");
|
||||
this.space();
|
||||
this.print(node.id, node);
|
||||
this.print(node.typeParameters, node);
|
||||
this.space();
|
||||
this.push("=");
|
||||
this.token("=");
|
||||
this.space();
|
||||
this.print(node.right, node);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function TypeAnnotation(node: Object) {
|
||||
this.push(":");
|
||||
this.token(":");
|
||||
this.space();
|
||||
if (node.optional) this.push("?");
|
||||
if (node.optional) this.token("?");
|
||||
this.print(node.typeAnnotation, node);
|
||||
}
|
||||
|
||||
export function TypeParameter(node: Object) {
|
||||
if (node.variance === "plus") {
|
||||
this.push("+");
|
||||
this.token("+");
|
||||
} else if (node.variance === "minus") {
|
||||
this.push("-");
|
||||
this.token("-");
|
||||
}
|
||||
|
||||
this.push(node.name);
|
||||
this.word(node.name);
|
||||
|
||||
if (node.bound) {
|
||||
this.print(node.bound, node);
|
||||
@ -202,34 +228,32 @@ export function TypeParameter(node: Object) {
|
||||
|
||||
if (node.default) {
|
||||
this.space();
|
||||
this.push("=");
|
||||
this.token("=");
|
||||
this.space();
|
||||
this.print(node.default, node);
|
||||
}
|
||||
}
|
||||
|
||||
export function TypeParameterInstantiation(node: Object) {
|
||||
this.push("<");
|
||||
this.printJoin(node.params, node, {
|
||||
separator: ", ",
|
||||
this.token("<");
|
||||
this.printList(node.params, node, {
|
||||
iterator: (node: Object) => {
|
||||
this.print(node.typeAnnotation, node);
|
||||
}
|
||||
});
|
||||
this.push(">");
|
||||
this.token(">");
|
||||
}
|
||||
|
||||
export { TypeParameterInstantiation as TypeParameterDeclaration };
|
||||
|
||||
export function ObjectTypeAnnotation(node: Object) {
|
||||
this.push("{");
|
||||
this.token("{");
|
||||
let props = node.properties.concat(node.callProperties, node.indexers);
|
||||
|
||||
if (props.length) {
|
||||
this.space();
|
||||
|
||||
this.printJoin(props, node, {
|
||||
separator: false,
|
||||
indent: true,
|
||||
iterator: () => {
|
||||
if (props.length !== 1) {
|
||||
@ -242,33 +266,42 @@ export function ObjectTypeAnnotation(node: Object) {
|
||||
this.space();
|
||||
}
|
||||
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
}
|
||||
|
||||
export function ObjectTypeCallProperty(node: Object) {
|
||||
if (node.static) this.push("static ");
|
||||
if (node.static) {
|
||||
this.word("static");
|
||||
this.space();
|
||||
}
|
||||
this.print(node.value, node);
|
||||
}
|
||||
|
||||
export function ObjectTypeIndexer(node: Object) {
|
||||
if (node.static) this.push("static ");
|
||||
this.push("[");
|
||||
if (node.static) {
|
||||
this.word("static");
|
||||
this.space();
|
||||
}
|
||||
this.token("[");
|
||||
this.print(node.id, node);
|
||||
this.push(":");
|
||||
this.token(":");
|
||||
this.space();
|
||||
this.print(node.key, node);
|
||||
this.push("]");
|
||||
this.push(":");
|
||||
this.token("]");
|
||||
this.token(":");
|
||||
this.space();
|
||||
this.print(node.value, node);
|
||||
}
|
||||
|
||||
export function ObjectTypeProperty(node: Object) {
|
||||
if (node.static) this.push("static ");
|
||||
if (node.static) {
|
||||
this.word("static");
|
||||
this.space();
|
||||
}
|
||||
this.print(node.key, node);
|
||||
if (node.optional) this.push("?");
|
||||
if (node.optional) this.token("?");
|
||||
if (!t.isFunctionTypeAnnotation(node.value)) {
|
||||
this.push(":");
|
||||
this.token(":");
|
||||
this.space();
|
||||
}
|
||||
this.print(node.value, node);
|
||||
@ -276,21 +309,27 @@ export function ObjectTypeProperty(node: Object) {
|
||||
|
||||
export function QualifiedTypeIdentifier(node: Object) {
|
||||
this.print(node.qualification, node);
|
||||
this.push(".");
|
||||
this.token(".");
|
||||
this.print(node.id, node);
|
||||
}
|
||||
|
||||
function orSeparator() {
|
||||
this.space();
|
||||
this.token("|");
|
||||
this.space();
|
||||
}
|
||||
|
||||
export function UnionTypeAnnotation(node: Object) {
|
||||
this.printJoin(node.types, node, { separator: " | " });
|
||||
this.printJoin(node.types, node, { separator: orSeparator });
|
||||
}
|
||||
|
||||
export function TypeCastExpression(node: Object) {
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.print(node.expression, node);
|
||||
this.print(node.typeAnnotation, node);
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
}
|
||||
|
||||
export function VoidTypeAnnotation() {
|
||||
this.push("void");
|
||||
this.word("void");
|
||||
}
|
||||
|
||||
@ -1,41 +1,42 @@
|
||||
export function JSXAttribute(node: Object) {
|
||||
this.print(node.name, node);
|
||||
if (node.value) {
|
||||
this.push("=");
|
||||
this.token("=");
|
||||
this.print(node.value, node);
|
||||
}
|
||||
}
|
||||
|
||||
export function JSXIdentifier(node: Object) {
|
||||
this.push(node.name);
|
||||
this.word(node.name);
|
||||
}
|
||||
|
||||
export function JSXNamespacedName(node: Object) {
|
||||
this.print(node.namespace, node);
|
||||
this.push(":");
|
||||
this.token(":");
|
||||
this.print(node.name, node);
|
||||
}
|
||||
|
||||
export function JSXMemberExpression(node: Object) {
|
||||
this.print(node.object, node);
|
||||
this.push(".");
|
||||
this.token(".");
|
||||
this.print(node.property, node);
|
||||
}
|
||||
|
||||
export function JSXSpreadAttribute(node: Object) {
|
||||
this.push("{...");
|
||||
this.token("{");
|
||||
this.token("...");
|
||||
this.print(node.argument, node);
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
}
|
||||
|
||||
export function JSXExpressionContainer(node: Object) {
|
||||
this.push("{");
|
||||
this.token("{");
|
||||
this.print(node.expression, node);
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
}
|
||||
|
||||
export function JSXText(node: Object) {
|
||||
this.push(node.value, true);
|
||||
this.token(node.value);
|
||||
}
|
||||
|
||||
export function JSXElement(node: Object) {
|
||||
@ -52,20 +53,29 @@ export function JSXElement(node: Object) {
|
||||
this.print(node.closingElement, node);
|
||||
}
|
||||
|
||||
function spaceSeparator() {
|
||||
this.space();
|
||||
}
|
||||
|
||||
export function JSXOpeningElement(node: Object) {
|
||||
this.push("<");
|
||||
this.token("<");
|
||||
this.print(node.name, node);
|
||||
if (node.attributes.length > 0) {
|
||||
this.push(" ");
|
||||
this.printJoin(node.attributes, node, { separator: " " });
|
||||
this.space();
|
||||
this.printJoin(node.attributes, node, { separator: spaceSeparator });
|
||||
}
|
||||
if (node.selfClosing) {
|
||||
this.space();
|
||||
this.token("/>");
|
||||
} else {
|
||||
this.token(">");
|
||||
}
|
||||
this.push(node.selfClosing ? " />" : ">");
|
||||
}
|
||||
|
||||
export function JSXClosingElement(node: Object) {
|
||||
this.push("</");
|
||||
this.token("</");
|
||||
this.print(node.name, node);
|
||||
this.push(">");
|
||||
this.token(">");
|
||||
}
|
||||
|
||||
export function JSXEmptyExpression() {}
|
||||
|
||||
@ -2,14 +2,14 @@ import * as t from "babel-types";
|
||||
|
||||
export function _params(node: Object) {
|
||||
this.print(node.typeParameters, node);
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.printList(node.params, node, {
|
||||
iterator: (node) => {
|
||||
if (node.optional) this.push("?");
|
||||
if (node.optional) this.token("?");
|
||||
this.print(node.typeAnnotation, node);
|
||||
}
|
||||
});
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
|
||||
if (node.returnType) {
|
||||
this.print(node.returnType, node);
|
||||
@ -22,20 +22,24 @@ export function _method(node: Object) {
|
||||
|
||||
if (kind === "method" || kind === "init") {
|
||||
if (node.generator) {
|
||||
this.push("*");
|
||||
this.token("*");
|
||||
}
|
||||
}
|
||||
|
||||
if (kind === "get" || kind === "set") {
|
||||
this.push(kind + " ");
|
||||
this.word(kind);
|
||||
this.space();
|
||||
}
|
||||
|
||||
if (node.async) this.push("async ");
|
||||
if (node.async) {
|
||||
this.word("async");
|
||||
this.space();
|
||||
}
|
||||
|
||||
if (node.computed) {
|
||||
this.push("[");
|
||||
this.token("[");
|
||||
this.print(key, node);
|
||||
this.push("]");
|
||||
this.token("]");
|
||||
} else {
|
||||
this.print(key, node);
|
||||
}
|
||||
@ -46,12 +50,15 @@ export function _method(node: Object) {
|
||||
}
|
||||
|
||||
export function FunctionExpression(node: Object) {
|
||||
if (node.async) this.push("async ");
|
||||
this.push("function");
|
||||
if (node.generator) this.push("*");
|
||||
if (node.async) {
|
||||
this.word("async");
|
||||
this.space();
|
||||
}
|
||||
this.word("function");
|
||||
if (node.generator) this.token("*");
|
||||
|
||||
if (node.id) {
|
||||
this.push(" ");
|
||||
this.space();
|
||||
this.print(node.id, node);
|
||||
} else {
|
||||
this.space();
|
||||
@ -65,7 +72,10 @@ export function FunctionExpression(node: Object) {
|
||||
export { FunctionExpression as FunctionDeclaration };
|
||||
|
||||
export function ArrowFunctionExpression(node: Object) {
|
||||
if (node.async) this.push("async ");
|
||||
if (node.async) {
|
||||
this.word("async");
|
||||
this.space();
|
||||
}
|
||||
|
||||
if (node.params.length === 1 && t.isIdentifier(node.params[0])) {
|
||||
this.print(node.params[0], node);
|
||||
@ -73,7 +83,9 @@ export function ArrowFunctionExpression(node: Object) {
|
||||
this._params(node);
|
||||
}
|
||||
|
||||
this.push(" => ");
|
||||
this.space();
|
||||
this.token("=>");
|
||||
this.space();
|
||||
|
||||
this.print(node.body, node);
|
||||
}
|
||||
|
||||
@ -3,7 +3,9 @@ import * as t from "babel-types";
|
||||
export function ImportSpecifier(node: Object) {
|
||||
this.print(node.imported, node);
|
||||
if (node.local && node.local.name !== node.imported.name) {
|
||||
this.push(" as ");
|
||||
this.space();
|
||||
this.word("as");
|
||||
this.space();
|
||||
this.print(node.local, node);
|
||||
}
|
||||
}
|
||||
@ -19,34 +21,49 @@ export function ExportDefaultSpecifier(node: Object) {
|
||||
export function ExportSpecifier(node: Object) {
|
||||
this.print(node.local, node);
|
||||
if (node.exported && node.local.name !== node.exported.name) {
|
||||
this.push(" as ");
|
||||
this.space();
|
||||
this.word("as");
|
||||
this.space();
|
||||
this.print(node.exported, node);
|
||||
}
|
||||
}
|
||||
|
||||
export function ExportNamespaceSpecifier(node: Object) {
|
||||
this.push("* as ");
|
||||
this.token("*");
|
||||
this.space();
|
||||
this.word("as");
|
||||
this.space();
|
||||
this.print(node.exported, node);
|
||||
}
|
||||
|
||||
export function ExportAllDeclaration(node: Object) {
|
||||
this.push("export *");
|
||||
this.word("export");
|
||||
this.space();
|
||||
this.token("*");
|
||||
if (node.exported) {
|
||||
this.push(" as ");
|
||||
this.space();
|
||||
this.word("as");
|
||||
this.space();
|
||||
this.print(node.exported, node);
|
||||
}
|
||||
this.push(" from ");
|
||||
this.space();
|
||||
this.word("from");
|
||||
this.space();
|
||||
this.print(node.source, node);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function ExportNamedDeclaration() {
|
||||
this.push("export ");
|
||||
this.word("export");
|
||||
this.space();
|
||||
ExportDeclaration.apply(this, arguments);
|
||||
}
|
||||
|
||||
export function ExportDefaultDeclaration() {
|
||||
this.push("export default ");
|
||||
this.word("export");
|
||||
this.space();
|
||||
this.word("default");
|
||||
this.space();
|
||||
ExportDeclaration.apply(this, arguments);
|
||||
}
|
||||
|
||||
@ -54,10 +71,11 @@ function ExportDeclaration(node: Object) {
|
||||
if (node.declaration) {
|
||||
let declar = node.declaration;
|
||||
this.print(declar, node);
|
||||
if (t.isStatement(declar) || t.isFunction(declar) || t.isClass(declar)) return;
|
||||
if (!t.isStatement(declar)) this.semicolon();
|
||||
} else {
|
||||
if (node.exportKind === "type") {
|
||||
this.push("type ");
|
||||
this.word("type");
|
||||
this.space();
|
||||
}
|
||||
|
||||
let specifiers = node.specifiers.slice(0);
|
||||
@ -70,7 +88,8 @@ function ExportDeclaration(node: Object) {
|
||||
hasSpecial = true;
|
||||
this.print(specifiers.shift(), node);
|
||||
if (specifiers.length) {
|
||||
this.push(", ");
|
||||
this.token(",");
|
||||
this.space();
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
@ -78,29 +97,33 @@ function ExportDeclaration(node: Object) {
|
||||
}
|
||||
|
||||
if (specifiers.length || (!specifiers.length && !hasSpecial)) {
|
||||
this.push("{");
|
||||
this.token("{");
|
||||
if (specifiers.length) {
|
||||
this.space();
|
||||
this.printJoin(specifiers, node, { separator: ", " });
|
||||
this.printList(specifiers, node);
|
||||
this.space();
|
||||
}
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
}
|
||||
|
||||
if (node.source) {
|
||||
this.push(" from ");
|
||||
this.space();
|
||||
this.word("from");
|
||||
this.space();
|
||||
this.print(node.source, node);
|
||||
}
|
||||
}
|
||||
|
||||
this.ensureSemicolon();
|
||||
this.semicolon();
|
||||
}
|
||||
}
|
||||
|
||||
export function ImportDeclaration(node: Object) {
|
||||
this.push("import ");
|
||||
this.word("import");
|
||||
this.space();
|
||||
|
||||
if (node.importKind === "type" || node.importKind === "typeof") {
|
||||
this.push(node.importKind + " ");
|
||||
this.word(node.importKind);
|
||||
this.space();
|
||||
}
|
||||
|
||||
let specifiers = node.specifiers.slice(0);
|
||||
@ -111,7 +134,8 @@ export function ImportDeclaration(node: Object) {
|
||||
if (t.isImportDefaultSpecifier(first) || t.isImportNamespaceSpecifier(first)) {
|
||||
this.print(specifiers.shift(), node);
|
||||
if (specifiers.length) {
|
||||
this.push(", ");
|
||||
this.token(",");
|
||||
this.space();
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
@ -119,14 +143,16 @@ export function ImportDeclaration(node: Object) {
|
||||
}
|
||||
|
||||
if (specifiers.length) {
|
||||
this.push("{");
|
||||
this.token("{");
|
||||
this.space();
|
||||
this.printJoin(specifiers, node, { separator: ", " });
|
||||
this.printList(specifiers, node);
|
||||
this.space();
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
}
|
||||
|
||||
this.push(" from ");
|
||||
this.space();
|
||||
this.word("from");
|
||||
this.space();
|
||||
}
|
||||
|
||||
this.print(node.source, node);
|
||||
@ -134,6 +160,9 @@ export function ImportDeclaration(node: Object) {
|
||||
}
|
||||
|
||||
export function ImportNamespaceSpecifier(node: Object) {
|
||||
this.push("* as ");
|
||||
this.token("*");
|
||||
this.space();
|
||||
this.word("as");
|
||||
this.space();
|
||||
this.print(node.local, node);
|
||||
}
|
||||
|
||||
@ -1,26 +1,23 @@
|
||||
import repeat from "lodash/repeat";
|
||||
import * as t from "babel-types";
|
||||
|
||||
const NON_ALPHABETIC_UNARY_OPERATORS = t.UPDATE_OPERATORS.concat(t.NUMBER_UNARY_OPERATORS).concat(["!"]);
|
||||
|
||||
export function WithStatement(node: Object) {
|
||||
this.keyword("with");
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.print(node.object, node);
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
this.printBlock(node);
|
||||
}
|
||||
|
||||
export function IfStatement(node: Object) {
|
||||
this.keyword("if");
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.print(node.test, node);
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
this.space();
|
||||
|
||||
let needsBlock = node.alternate && t.isIfStatement(getLastStatement(node.consequent));
|
||||
if (needsBlock) {
|
||||
this.push("{");
|
||||
this.token("{");
|
||||
this.newline();
|
||||
this.indent();
|
||||
}
|
||||
@ -30,12 +27,13 @@ export function IfStatement(node: Object) {
|
||||
if (needsBlock) {
|
||||
this.dedent();
|
||||
this.newline();
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
}
|
||||
|
||||
if (node.alternate) {
|
||||
if (this.isLast("}")) this.space();
|
||||
this.push("else ");
|
||||
if (this.endsWith("}")) this.space();
|
||||
this.word("else");
|
||||
this.space();
|
||||
this.printAndIndentOnComments(node.alternate, node);
|
||||
}
|
||||
}
|
||||
@ -48,44 +46,46 @@ function getLastStatement(statement) {
|
||||
|
||||
export function ForStatement(node: Object) {
|
||||
this.keyword("for");
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
|
||||
this._inForStatementInitCounter++;
|
||||
this.print(node.init, node);
|
||||
this._inForStatementInitCounter--;
|
||||
this.push(";");
|
||||
this.token(";");
|
||||
|
||||
if (node.test) {
|
||||
this.space();
|
||||
this.print(node.test, node);
|
||||
}
|
||||
this.push(";");
|
||||
this.token(";");
|
||||
|
||||
if (node.update) {
|
||||
this.space();
|
||||
this.print(node.update, node);
|
||||
}
|
||||
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
this.printBlock(node);
|
||||
}
|
||||
|
||||
export function WhileStatement(node: Object) {
|
||||
this.keyword("while");
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.print(node.test, node);
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
this.printBlock(node);
|
||||
}
|
||||
|
||||
let buildForXStatement = function (op) {
|
||||
return function (node: Object) {
|
||||
this.keyword("for");
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.print(node.left, node);
|
||||
this.push(` ${op} `);
|
||||
this.space();
|
||||
this.word(op);
|
||||
this.space();
|
||||
this.print(node.right, node);
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
this.printBlock(node);
|
||||
};
|
||||
};
|
||||
@ -94,27 +94,24 @@ export let ForInStatement = buildForXStatement("in");
|
||||
export let ForOfStatement = buildForXStatement("of");
|
||||
|
||||
export function DoWhileStatement(node: Object) {
|
||||
this.push("do ");
|
||||
this.word("do");
|
||||
this.space();
|
||||
this.print(node.body, node);
|
||||
this.space();
|
||||
this.keyword("while");
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.print(node.test, node);
|
||||
this.push(");");
|
||||
this.token(")");
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
function buildLabelStatement(prefix, key = "label") {
|
||||
return function (node: Object) {
|
||||
this.push(prefix);
|
||||
this.word(prefix);
|
||||
|
||||
let label = node[key];
|
||||
if (label) {
|
||||
if (!(this.format.minified && ((t.isUnaryExpression(label, { prefix: true }) ||
|
||||
t.isUpdateExpression(label, { prefix: true })) &&
|
||||
NON_ALPHABETIC_UNARY_OPERATORS.indexOf(label.operator) > -1))) {
|
||||
this.push(" ");
|
||||
|
||||
}
|
||||
this.space();
|
||||
|
||||
let terminatorState = this.startTerminatorless();
|
||||
this.print(label, node);
|
||||
@ -132,7 +129,8 @@ export let ThrowStatement = buildLabelStatement("throw", "argument");
|
||||
|
||||
export function LabeledStatement(node: Object) {
|
||||
this.print(node.label, node);
|
||||
this.push(": ");
|
||||
this.token(":");
|
||||
this.space();
|
||||
this.print(node.body, node);
|
||||
}
|
||||
|
||||
@ -152,27 +150,28 @@ export function TryStatement(node: Object) {
|
||||
|
||||
if (node.finalizer) {
|
||||
this.space();
|
||||
this.push("finally ");
|
||||
this.word("finally");
|
||||
this.space();
|
||||
this.print(node.finalizer, node);
|
||||
}
|
||||
}
|
||||
|
||||
export function CatchClause(node: Object) {
|
||||
this.keyword("catch");
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.print(node.param, node);
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
this.space();
|
||||
this.print(node.body, node);
|
||||
}
|
||||
|
||||
export function SwitchStatement(node: Object) {
|
||||
this.keyword("switch");
|
||||
this.push("(");
|
||||
this.token("(");
|
||||
this.print(node.discriminant, node);
|
||||
this.push(")");
|
||||
this.token(")");
|
||||
this.space();
|
||||
this.push("{");
|
||||
this.token("{");
|
||||
|
||||
this.printSequence(node.cases, node, {
|
||||
indent: true,
|
||||
@ -181,16 +180,18 @@ export function SwitchStatement(node: Object) {
|
||||
}
|
||||
});
|
||||
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
}
|
||||
|
||||
export function SwitchCase(node: Object) {
|
||||
if (node.test) {
|
||||
this.push("case ");
|
||||
this.word("case");
|
||||
this.space();
|
||||
this.print(node.test, node);
|
||||
this.push(":");
|
||||
this.token(":");
|
||||
} else {
|
||||
this.push("default:");
|
||||
this.word("default");
|
||||
this.token(":");
|
||||
}
|
||||
|
||||
if (node.consequent.length) {
|
||||
@ -200,11 +201,27 @@ export function SwitchCase(node: Object) {
|
||||
}
|
||||
|
||||
export function DebuggerStatement() {
|
||||
this.push("debugger;");
|
||||
this.word("debugger");
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
function variableDeclarationIdent() {
|
||||
// "let " or "var " indentation.
|
||||
this.token(",");
|
||||
this.push("\n");
|
||||
for (let i = 0; i < 4; i++) this.push(" ");
|
||||
}
|
||||
|
||||
function constDeclarationIdent() {
|
||||
// "const " indentation.
|
||||
this.token(",");
|
||||
this.push("\n");
|
||||
for (let i = 0; i < 6; i++) this.push(" ");
|
||||
}
|
||||
|
||||
export function VariableDeclaration(node: Object, parent: Object) {
|
||||
this.push(node.kind + " ");
|
||||
this.word(node.kind);
|
||||
this.space();
|
||||
|
||||
let hasInits = false;
|
||||
// don't add whitespace to loop heads
|
||||
@ -229,14 +246,14 @@ export function VariableDeclaration(node: Object, parent: Object) {
|
||||
// bar = "foo";
|
||||
//
|
||||
|
||||
let sep;
|
||||
let separator;
|
||||
if (!this.format.compact && !this.format.concise && hasInits && !this.format.retainLines) {
|
||||
sep = `,\n${repeat(" ", node.kind.length + 1)}`;
|
||||
separator = node.kind === "const" ? constDeclarationIdent : variableDeclarationIdent;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
this.printList(node.declarations, node, { separator: sep });
|
||||
this.printList(node.declarations, node, { separator });
|
||||
|
||||
if (t.isFor(parent)) {
|
||||
// don't give semicolons to these nodes since they'll be inserted in the parent generator
|
||||
@ -251,7 +268,7 @@ export function VariableDeclarator(node: Object) {
|
||||
this.print(node.id.typeAnnotation, node);
|
||||
if (node.init) {
|
||||
this.space();
|
||||
this.push("=");
|
||||
this.token("=");
|
||||
this.space();
|
||||
this.print(node.init, node);
|
||||
}
|
||||
|
||||
@ -3,24 +3,25 @@ export function TaggedTemplateExpression(node: Object) {
|
||||
this.print(node.quasi, node);
|
||||
}
|
||||
|
||||
export function TemplateElement(node: Object) {
|
||||
this._push(node.value.raw);
|
||||
export function TemplateElement(node: Object, parent: Object) {
|
||||
const isFirst = parent.quasis[0] === node;
|
||||
const isLast = parent.quasis[parent.quasis.length - 1] === node;
|
||||
|
||||
let value = (isFirst ? "`" : "}") + node.value.raw + (isLast ? "`" : "${");
|
||||
|
||||
if (!isFirst) this.space();
|
||||
this.token(value);
|
||||
if (!isLast) this.space();
|
||||
}
|
||||
|
||||
export function TemplateLiteral(node: Object) {
|
||||
this.push("`");
|
||||
|
||||
let quasis = node.quasis;
|
||||
|
||||
for (let i = 0; i < quasis.length; i++) {
|
||||
this.print(quasis[i], node);
|
||||
|
||||
if (i + 1 < quasis.length) {
|
||||
this._push("${ ");
|
||||
this.print(node.expressions[i], node);
|
||||
this.push(" }");
|
||||
}
|
||||
}
|
||||
|
||||
this._push("`");
|
||||
}
|
||||
|
||||
@ -10,17 +10,17 @@ export function Identifier(node: Object) {
|
||||
// the next major.
|
||||
if (node.variance) {
|
||||
if (node.variance === "plus") {
|
||||
this.push("+");
|
||||
this.token("+");
|
||||
} else if (node.variance === "minus") {
|
||||
this.push("-");
|
||||
this.token("-");
|
||||
}
|
||||
}
|
||||
|
||||
this.push(node.name);
|
||||
this.word(node.name);
|
||||
}
|
||||
|
||||
export function RestElement(node: Object) {
|
||||
this.push("...");
|
||||
this.token("...");
|
||||
this.print(node.argument, node);
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ export {
|
||||
export function ObjectExpression(node: Object) {
|
||||
let props = node.properties;
|
||||
|
||||
this.push("{");
|
||||
this.token("{");
|
||||
this.printInnerComments(node);
|
||||
|
||||
if (props.length) {
|
||||
@ -42,23 +42,23 @@ export function ObjectExpression(node: Object) {
|
||||
this.space();
|
||||
}
|
||||
|
||||
this.push("}");
|
||||
this.token("}");
|
||||
}
|
||||
|
||||
export { ObjectExpression as ObjectPattern };
|
||||
|
||||
export function ObjectMethod(node: Object) {
|
||||
this.printJoin(node.decorators, node, { separator: "" });
|
||||
this.printJoin(node.decorators, node);
|
||||
this._method(node);
|
||||
}
|
||||
|
||||
export function ObjectProperty(node: Object) {
|
||||
this.printJoin(node.decorators, node, { separator: "" });
|
||||
this.printJoin(node.decorators, node);
|
||||
|
||||
if (node.computed) {
|
||||
this.push("[");
|
||||
this.token("[");
|
||||
this.print(node.key, node);
|
||||
this.push("]");
|
||||
this.token("]");
|
||||
} else {
|
||||
// print `({ foo: foo = 5 } = {})` as `({ foo = 5 } = {});`
|
||||
if (t.isAssignmentPattern(node.value) && t.isIdentifier(node.key) && node.key.name === node.value.left.name) {
|
||||
@ -77,7 +77,7 @@ export function ObjectProperty(node: Object) {
|
||||
}
|
||||
}
|
||||
|
||||
this.push(":");
|
||||
this.token(":");
|
||||
this.space();
|
||||
this.print(node.value, node);
|
||||
}
|
||||
@ -86,7 +86,7 @@ export function ArrayExpression(node: Object) {
|
||||
let elems = node.elements;
|
||||
let len = elems.length;
|
||||
|
||||
this.push("[");
|
||||
this.token("[");
|
||||
this.printInnerComments(node);
|
||||
|
||||
for (let i = 0; i < elems.length; i++) {
|
||||
@ -94,44 +94,52 @@ export function ArrayExpression(node: Object) {
|
||||
if (elem) {
|
||||
if (i > 0) this.space();
|
||||
this.print(elem, node);
|
||||
if (i < len - 1) this.push(",");
|
||||
if (i < len - 1) this.token(",");
|
||||
} else {
|
||||
// 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.
|
||||
this.push(",");
|
||||
this.token(",");
|
||||
}
|
||||
}
|
||||
|
||||
this.push("]");
|
||||
this.token("]");
|
||||
}
|
||||
|
||||
export { ArrayExpression as ArrayPattern };
|
||||
|
||||
export function RegExpLiteral(node: Object) {
|
||||
this.push(`/${node.pattern}/${node.flags}`);
|
||||
this.word(`/${node.pattern}/${node.flags}`);
|
||||
}
|
||||
|
||||
export function BooleanLiteral(node: Object) {
|
||||
this.push(node.value ? "true" : "false");
|
||||
this.word(node.value ? "true" : "false");
|
||||
}
|
||||
|
||||
export function NullLiteral() {
|
||||
this.push("null");
|
||||
this.word("null");
|
||||
}
|
||||
|
||||
export function NumericLiteral(node: Object) {
|
||||
this.push(node.value + "");
|
||||
let raw = this.getPossibleRaw(node);
|
||||
if (raw != null) {
|
||||
this.word(raw);
|
||||
return;
|
||||
}
|
||||
|
||||
this.word(node.value + "");
|
||||
}
|
||||
|
||||
export function StringLiteral(node: Object, parent: Object) {
|
||||
this.push(this._stringLiteral(node.value, parent));
|
||||
}
|
||||
let raw = this.getPossibleRaw(node);
|
||||
if (raw != null) {
|
||||
this.token(raw);
|
||||
return;
|
||||
}
|
||||
|
||||
export function _stringLiteral(val: string, parent: Object): string {
|
||||
val = JSON.stringify(val);
|
||||
let val = JSON.stringify(node.value);
|
||||
|
||||
// escape illegal js but valid json unicode characters
|
||||
val = val.replace(/[\u000A\u000D\u2028\u2029]/g, function (c) {
|
||||
@ -152,5 +160,5 @@ export function _stringLiteral(val: string, parent: Object): string {
|
||||
val = `'${val}'`;
|
||||
}
|
||||
|
||||
return val;
|
||||
return this.token(val);
|
||||
}
|
||||
|
||||
@ -10,13 +10,13 @@ import Printer from "./printer";
|
||||
* user preferences, and valid output.
|
||||
*/
|
||||
|
||||
export class CodeGenerator extends Printer {
|
||||
class Generator extends Printer {
|
||||
constructor(ast, opts, code) {
|
||||
opts = opts || {};
|
||||
|
||||
let comments = ast.comments || [];
|
||||
let tokens = ast.tokens || [];
|
||||
let format = CodeGenerator.normalizeOptions(code, opts, tokens);
|
||||
let format = Generator.normalizeOptions(code, opts, tokens);
|
||||
|
||||
let position = new Position;
|
||||
|
||||
@ -66,7 +66,6 @@ export class CodeGenerator extends Printer {
|
||||
*
|
||||
* - Detects code indentation.
|
||||
* - If `opts.compact = "auto"` and the code is over 100KB, `compact` will be set to `true`.
|
||||
|
||||
*/
|
||||
|
||||
static normalizeOptions(code, opts, tokens) {
|
||||
@ -85,7 +84,7 @@ export class CodeGenerator extends Printer {
|
||||
compact: opts.compact,
|
||||
minified: opts.minified,
|
||||
concise: opts.concise,
|
||||
quotes: opts.quotes || CodeGenerator.findCommonStringDelimiter(code, tokens),
|
||||
quotes: opts.quotes || Generator.findCommonStringDelimiter(code, tokens),
|
||||
indent: {
|
||||
adjustMultilineComment: true,
|
||||
style: style,
|
||||
@ -161,7 +160,23 @@ export class CodeGenerator extends Printer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* We originally exported the Generator class above, but to make it extra clear that it is a private API,
|
||||
* we have moved that to an internal class instance and simplified the interface to the two public methods
|
||||
* that we wish to support.
|
||||
*/
|
||||
|
||||
export class CodeGenerator {
|
||||
constructor(ast, opts, code) {
|
||||
this._generator = new Generator(ast, opts, code);
|
||||
}
|
||||
generate() {
|
||||
return this._generator.generate();
|
||||
}
|
||||
}
|
||||
|
||||
export default function (ast: Object, opts: Object, code: string): Object {
|
||||
let gen = new CodeGenerator(ast, opts, code);
|
||||
let gen = new Generator(ast, opts, code);
|
||||
return gen.generate();
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ export default class Printer extends Buffer {
|
||||
this.printAuxBeforeComment(oldInAux);
|
||||
|
||||
let needsParens = n.needsParens(node, parent, this._printStack);
|
||||
if (needsParens) this.push("(");
|
||||
if (needsParens) this.token("(");
|
||||
|
||||
this.printLeadingComments(node, parent);
|
||||
|
||||
@ -53,7 +53,7 @@ export default class Printer extends Buffer {
|
||||
|
||||
let loc = (t.isProgram(node) || t.isFile(node)) ? null : node.loc;
|
||||
this.withSource("start", loc, () => {
|
||||
this._print(node, parent);
|
||||
this[node.type](node, parent);
|
||||
});
|
||||
|
||||
// Check again if any of our children may have left an aux comment on the stack
|
||||
@ -61,7 +61,7 @@ export default class Printer extends Buffer {
|
||||
|
||||
this.printTrailingComments(node, parent);
|
||||
|
||||
if (needsParens) this.push(")");
|
||||
if (needsParens) this.token(")");
|
||||
|
||||
// end
|
||||
this._printStack.pop();
|
||||
@ -96,30 +96,14 @@ export default class Printer extends Buffer {
|
||||
}
|
||||
|
||||
getPossibleRaw(node) {
|
||||
if (this.format.minified) return;
|
||||
|
||||
let extra = node.extra;
|
||||
if (extra && extra.raw != null && extra.rawValue != null && node.value === extra.rawValue) {
|
||||
return extra.raw;
|
||||
}
|
||||
}
|
||||
|
||||
_print(node, parent) {
|
||||
// In minified mode we need to produce as little bytes as needed
|
||||
// and need to make sure that string quoting is consistent.
|
||||
// That means we have to always reprint as opposed to getting
|
||||
// the raw value.
|
||||
if (!this.format.minified) {
|
||||
let extra = this.getPossibleRaw(node);
|
||||
if (extra) {
|
||||
this.push("");
|
||||
this._push(extra);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let printMethod = this[node.type];
|
||||
printMethod.call(this, node, parent);
|
||||
}
|
||||
|
||||
printJoin(nodes: ?Array, parent: Object, opts = {}) {
|
||||
if (!nodes || !nodes.length) return;
|
||||
|
||||
@ -141,7 +125,7 @@ export default class Printer extends Buffer {
|
||||
}
|
||||
|
||||
if (opts.separator && i < len - 1) {
|
||||
this.push(opts.separator);
|
||||
opts.separator.call(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -203,8 +187,7 @@ export default class Printer extends Buffer {
|
||||
|
||||
printList(items, parent, opts = {}) {
|
||||
if (opts.separator == null) {
|
||||
opts.separator = ",";
|
||||
if (!this.format.compact) opts.separator += " ";
|
||||
opts.separator = commaSeparator;
|
||||
}
|
||||
|
||||
return this.printJoin(items, parent, opts);
|
||||
@ -287,14 +270,11 @@ export default class Printer extends Buffer {
|
||||
// whitespace before
|
||||
this.newline(this.whitespace.getNewlinesBefore(comment));
|
||||
|
||||
if (!this.endsWith(["[", "{"])) this.space();
|
||||
|
||||
let column = this.position.column;
|
||||
let val = this.generateComment(comment);
|
||||
|
||||
if (column && !this.isLast(["\n", " ", "[", "{"])) {
|
||||
this._push(" ");
|
||||
column++;
|
||||
}
|
||||
|
||||
//
|
||||
if (comment.type === "CommentBlock" && this.format.indent.adjustMultilineComment) {
|
||||
let offset = comment.loc && comment.loc.start.column;
|
||||
@ -307,10 +287,6 @@ export default class Printer extends Buffer {
|
||||
val = val.replace(/\n/g, `\n${repeat(" ", indent)}`);
|
||||
}
|
||||
|
||||
if (column === 0) {
|
||||
val = this.getIndent() + val;
|
||||
}
|
||||
|
||||
// force a newline for line comments when retainLines is set in case the next printed node
|
||||
// doesn't catch up
|
||||
if ((this.format.compact || this.format.concise || this.format.retainLines) &&
|
||||
@ -319,7 +295,7 @@ export default class Printer extends Buffer {
|
||||
}
|
||||
|
||||
//
|
||||
this._push(val);
|
||||
this.push(val);
|
||||
|
||||
// whitespace after
|
||||
this.newline(this.whitespace.getNewlinesAfter(comment));
|
||||
@ -335,6 +311,11 @@ export default class Printer extends Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
function commaSeparator() {
|
||||
this.token(",");
|
||||
this.space();
|
||||
}
|
||||
|
||||
for (let generator of [
|
||||
require("./generators/template-literals"),
|
||||
require("./generators/expressions"),
|
||||
|
||||
@ -1 +1 @@
|
||||
x=1;var {y=1}=obj;
|
||||
x=1;var{y=1}=obj;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
function foo(l){
|
||||
return (
|
||||
return(
|
||||
|
||||
l);}
|
||||
|
||||
8
packages/babel-generator/test/fixtures/minified/arrow-functions/actual.js
vendored
Normal file
8
packages/babel-generator/test/fixtures/minified/arrow-functions/actual.js
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
var foo = (arg1, arg2) => {
|
||||
arg1;
|
||||
arg2;
|
||||
};
|
||||
var foo2 = (arg1, arg2) => {
|
||||
arg1;
|
||||
};
|
||||
var foo3 = arg1 => arg1;
|
||||
1
packages/babel-generator/test/fixtures/minified/arrow-functions/expected.js
vendored
Normal file
1
packages/babel-generator/test/fixtures/minified/arrow-functions/expected.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
var foo=(arg1,arg2)=>{arg1;arg2};var foo2=(arg1,arg2)=>{arg1};var foo3=arg1=>arg1;
|
||||
12
packages/babel-generator/test/fixtures/minified/block-statements/actual.js
vendored
Normal file
12
packages/babel-generator/test/fixtures/minified/block-statements/actual.js
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
if (true) {
|
||||
foo;
|
||||
bar2;
|
||||
} else {
|
||||
foo;
|
||||
bar2;
|
||||
}
|
||||
|
||||
function fn () {
|
||||
foo;
|
||||
bar2;
|
||||
}
|
||||
1
packages/babel-generator/test/fixtures/minified/block-statements/expected.js
vendored
Normal file
1
packages/babel-generator/test/fixtures/minified/block-statements/expected.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
if(true){foo;bar2}else{foo;bar2}function fn(){foo;bar2}
|
||||
7
packages/babel-generator/test/fixtures/minified/modules/actual.js
vendored
Normal file
7
packages/babel-generator/test/fixtures/minified/modules/actual.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import * as foo from "foo";
|
||||
import {foo as bar, foo2 as bar2} from "foo";
|
||||
import {foo2} from "foo";
|
||||
|
||||
export * from "foo";
|
||||
export {foo as bar} from "foo";
|
||||
export {foo} from "foo";
|
||||
1
packages/babel-generator/test/fixtures/minified/modules/expected.js
vendored
Normal file
1
packages/babel-generator/test/fixtures/minified/modules/expected.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import*as foo from"foo";import{foo as bar,foo2 as bar2}from"foo";import{foo2}from"foo";export*from"foo";export{foo as bar}from"foo";export{foo}from"foo";
|
||||
@ -1,4 +1,5 @@
|
||||
var Whitespace = require("../lib/whitespace");
|
||||
var Printer = require("../lib/printer");
|
||||
var generate = require("../lib");
|
||||
var assert = require("assert");
|
||||
var parse = require("babylon").parse;
|
||||
@ -9,10 +10,10 @@ var _ = require("lodash");
|
||||
suite("generation", function () {
|
||||
test("completeness", function () {
|
||||
_.each(t.VISITOR_KEYS, function (keys, type) {
|
||||
assert.ok(!!generate.CodeGenerator.prototype[type], type + " should exist");
|
||||
assert.ok(!!Printer.prototype[type], type + " should exist");
|
||||
});
|
||||
|
||||
_.each(generate.CodeGenerator.prototype, function (fn, type) {
|
||||
_.each(Printer.prototype, function (fn, type) {
|
||||
if (!/[A-Z]/.test(type[0])) return;
|
||||
assert.ok(t.VISITOR_KEYS[type], type + " should not exist");
|
||||
});
|
||||
|
||||
@ -17,4 +17,4 @@ export default (param => {
|
||||
prop1: 'prop1',
|
||||
prop2: 'prop2'
|
||||
}, _temp;
|
||||
})
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user