Merge pull request #3584 from loganfsmyth/generator-refactor-cleanup2

babel-generator: More refactoring and optimizations
This commit is contained in:
Logan Smyth 2016-07-18 19:23:24 -07:00 committed by GitHub
commit a1c2d4dd5d
14 changed files with 302 additions and 298 deletions

View File

@ -58,6 +58,9 @@ export default class Buffer {
*/
queue(str: string): void {
// Drop trailing spaces when a newline is inserted.
if (str === "\n") while (this._queue.length > 0 && SPACES_RE.test(this._queue[0][0])) this._queue.shift();
const { line, column, filename } = this._sourcePosition;
this._queue.unshift([str, line, column, filename]);
}
@ -86,10 +89,6 @@ export default class Buffer {
}
}
removeTrailingSpaces(): void {
while (this._queue.length > 0 && SPACES_RE.test(this._queue[0][0])) this._queue.shift();
}
removeTrailingNewline(): void {
if (this._queue.length > 0 && this._queue[0][0] === "\n") this._queue.shift();
}
@ -98,10 +97,23 @@ export default class Buffer {
if (this._queue.length > 0 && this._queue[0][0] === ";") this._queue.shift();
}
endsWith(str: string): boolean {
endsWith(suffix: string): boolean {
// Fast path to avoid iterating over this._queue.
if (suffix.length === 1) {
let last;
if (this._queue.length > 0) {
const str = this._queue[0][0];
last = str[str.length - 1];
} else {
last = this._last;
}
return last === suffix;
}
const end = this._last + this._queue.reduce((acc, item) => item[0] + acc, "");
if (str.length <= end.length) {
return end.slice(-str.length) === str;
if (suffix.length <= end.length) {
return end.slice(-suffix.length) === suffix;
}
// We assume that everything being matched is at most a single token plus some whitespace,
@ -109,15 +121,6 @@ export default class Buffer {
return false;
}
getLast(): string {
if (this._queue.length > 0) {
const last = this._queue[0][0];
return last[last.length - 1];
}
return this._last;
}
hasContent(): boolean {
return this._queue.length > 0 || !!this._last;
}

View File

@ -21,9 +21,12 @@ export function BlockStatement(node: Object) {
if (node.directives && node.directives.length) this.newline();
this.printSequence(node.body, node, { indent: true });
if (!this.format.retainLines && !this.format.concise) this.removeTrailingNewline();
this.removeTrailingNewline();
this.source("end", node.loc);
if (!this.endsWith("\n")) this.newline();
this.rightBrace();
} else {
this.source("end", node.loc);

View File

@ -42,6 +42,8 @@ export function ClassBody(node: Object) {
this.printSequence(node.body, node);
this.dedent();
if (!this.endsWith("\n")) this.newline();
this.rightBrace();
}
}

View File

@ -1,13 +1,9 @@
/* eslint max-len: 0 */
import isInteger from "lodash/isInteger";
import isNumber from "lodash/isNumber";
import * as t from "babel-types";
import * as n from "../node";
const SCIENTIFIC_NOTATION = /e/i;
const ZERO_DECIMAL_INTEGER = /\.0+$/;
const NON_DECIMAL_LITERAL = /^0[box]/;
export function UnaryExpression(node: Object) {
if (node.operator === "void" || node.operator === "delete" || node.operator === "typeof") {
@ -89,15 +85,16 @@ export function Decorator(node: Object) {
function commaSeparatorNewline() {
this.token(",");
this.newline();
if (!this.endsWith("\n")) this.space();
}
export function CallExpression(node: Object) {
this.print(node.callee, node);
if (node.loc) this.printAuxAfterComment();
this.token("(");
let isPrettyCall = node._prettyCall && !this.format.retainLines && !this.format.compact;
let isPrettyCall = node._prettyCall;
let separator;
if (isPrettyCall) {
@ -208,17 +205,6 @@ export function MemberExpression(node: Object) {
this.print(node.property, node);
this.token("]");
} else {
if (t.isNumericLiteral(node.object)) {
let val = this.getPossibleRaw(node.object) || node.object.value;
if (isInteger(+val) &&
!NON_DECIMAL_LITERAL.test(val) &&
!SCIENTIFIC_NOTATION.test(val) &&
!ZERO_DECIMAL_INTEGER.test(val) &&
!this.endsWith(".")) {
this.token(".");
}
}
this.token(".");
this.print(node.property, node);
}

View File

@ -251,6 +251,7 @@ export function ObjectTypeAnnotation(node: Object) {
this.printJoin(props, node, {
indent: true,
statement: true,
iterator: () => {
if (props.length !== 1) {
this.semicolon();

View File

@ -1,7 +1,8 @@
import * as t from "babel-types";
export function WithStatement(node: Object) {
this.keyword("with");
this.word("with");
this.space();
this.token("(");
this.print(node.object, node);
this.token(")");
@ -9,7 +10,8 @@ export function WithStatement(node: Object) {
}
export function IfStatement(node: Object) {
this.keyword("if");
this.word("if");
this.space();
this.token("(");
this.print(node.test, node);
this.token(")");
@ -45,7 +47,8 @@ function getLastStatement(statement) {
}
export function ForStatement(node: Object) {
this.keyword("for");
this.word("for");
this.space();
this.token("(");
this.inForStatementInitCounter++;
@ -69,7 +72,8 @@ export function ForStatement(node: Object) {
}
export function WhileStatement(node: Object) {
this.keyword("while");
this.word("while");
this.space();
this.token("(");
this.print(node.test, node);
this.token(")");
@ -78,7 +82,8 @@ export function WhileStatement(node: Object) {
let buildForXStatement = function (op) {
return function (node: Object) {
this.keyword("for");
this.word("for");
this.space();
this.token("(");
this.print(node.left, node);
this.space();
@ -98,7 +103,8 @@ export function DoWhileStatement(node: Object) {
this.space();
this.print(node.body, node);
this.space();
this.keyword("while");
this.word("while");
this.space();
this.token("(");
this.print(node.test, node);
this.token(")");
@ -135,7 +141,8 @@ export function LabeledStatement(node: Object) {
}
export function TryStatement(node: Object) {
this.keyword("try");
this.word("try");
this.space();
this.print(node.block, node);
this.space();
@ -157,7 +164,8 @@ export function TryStatement(node: Object) {
}
export function CatchClause(node: Object) {
this.keyword("catch");
this.word("catch");
this.space();
this.token("(");
this.print(node.param, node);
this.token(")");
@ -166,7 +174,8 @@ export function CatchClause(node: Object) {
}
export function SwitchStatement(node: Object) {
this.keyword("switch");
this.word("switch");
this.space();
this.token("(");
this.print(node.discriminant, node);
this.token(")");
@ -209,14 +218,14 @@ function variableDeclarationIdent() {
// "let " or "var " indentation.
this.token(",");
this.newline();
for (let i = 0; i < 4; i++) this.space(true);
if (this.endsWith("\n")) for (let i = 0; i < 4; i++) this.space(true);
}
function constDeclarationIdent() {
// "const " indentation.
this.token(",");
this.newline();
for (let i = 0; i < 6; i++) this.space(true);
if (this.endsWith("\n")) for (let i = 0; i < 6; i++) this.space(true);
}
export function VariableDeclaration(node: Object, parent: Object) {
@ -247,7 +256,7 @@ export function VariableDeclaration(node: Object, parent: Object) {
//
let separator;
if (!this.format.compact && !this.format.concise && hasInits && !this.format.retainLines) {
if (hasInits) {
separator = node.kind === "const" ? constDeclarationIdent : variableDeclarationIdent;
}

View File

@ -38,7 +38,7 @@ export function ObjectExpression(node: Object) {
if (props.length) {
this.space();
this.printList(props, node, { indent: true });
this.printList(props, node, { indent: true, statement: true });
this.space();
}
@ -124,12 +124,8 @@ export function NullLiteral() {
export function NumericLiteral(node: Object) {
let raw = this.getPossibleRaw(node);
if (raw != null) {
this.word(raw);
return;
}
this.word(node.value + "");
this.number(raw == null ? node.value + "" : raw);
}
export function StringLiteral(node: Object, parent: Object) {

View File

@ -1,8 +1,8 @@
import detectIndent from "detect-indent";
import Whitespace from "./whitespace";
import SourceMap from "./source-map";
import * as messages from "babel-messages";
import Printer from "./printer";
import type {Format} from "./printer";
/**
* Babel's code generator, turns an ast into code, maintaining sourcemaps,
@ -14,119 +14,15 @@ class Generator extends Printer {
opts = opts || {};
const tokens = ast.tokens || [];
let format = Generator.normalizeOptions(code, opts, tokens);
let format = normalizeOptions(code, opts, tokens);
let map = opts.sourceMaps ? new SourceMap(opts, code) : null;
super(format, map, tokens);
let map = opts.sourceMaps ? new SourceMap(opts, code) : null;
super(format, map);
this.ast = ast;
this._whitespace = tokens.length > 0 ? new Whitespace(tokens) : null;
this.ast = ast;
}
format: {
shouldPrintComment: (comment: string) => boolean;
retainLines: boolean;
comments: boolean;
auxiliaryCommentBefore: string;
auxiliaryCommentAfter: string;
compact: boolean | "auto";
minified: boolean;
quotes: "single" | "double";
concise: boolean;
indent: {
adjustMultilineComment: boolean;
style: string;
base: number;
}
};
_whitespace: Whitespace;
ast: Object;
/**
* Normalize generator options, setting defaults.
*
* - Detects code indentation.
* - If `opts.compact = "auto"` and the code is over 100KB, `compact` will be set to `true`.
*/
static normalizeOptions(code, opts, tokens) {
let style = " ";
if (code && typeof code === "string") {
let indent = detectIndent(code).indent;
if (indent && indent !== " ") style = indent;
}
let format = {
auxiliaryCommentBefore: opts.auxiliaryCommentBefore,
auxiliaryCommentAfter: opts.auxiliaryCommentAfter,
shouldPrintComment: opts.shouldPrintComment,
retainLines: opts.retainLines,
comments: opts.comments == null || opts.comments,
compact: opts.compact,
minified: opts.minified,
concise: opts.concise,
quotes: opts.quotes || Generator.findCommonStringDelimiter(code, tokens),
indent: {
adjustMultilineComment: true,
style: style,
base: 0
}
};
if (format.minified) {
format.compact = true;
}
if (format.compact === "auto") {
format.compact = code.length > 100000; // 100KB
if (format.compact) {
console.error("[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "100KB"));
}
}
if (format.compact) {
format.indent.adjustMultilineComment = false;
}
return format;
}
/**
* Determine if input code uses more single or double quotes.
*/
static findCommonStringDelimiter(code, tokens) {
let occurences = {
single: 0,
double: 0
};
let checked = 0;
for (let i = 0; i < tokens.length; i++) {
let token = tokens[i];
if (token.type.label !== "string") continue;
let raw = code.slice(token.start, token.end);
if (raw[0] === "'") {
occurences.single++;
} else {
occurences.double++;
}
checked++;
if (checked >= 3) break;
}
if (occurences.single > occurences.double) {
return "single";
} else {
return "double";
}
}
/**
* Generate code and sourcemap from ast.
*
@ -134,13 +30,96 @@ class Generator extends Printer {
*/
generate() {
this.print(this.ast);
this.printAuxAfterComment();
return this._buf.get();
return super.generate(this.ast);
}
}
/**
* Normalize generator options, setting defaults.
*
* - Detects code indentation.
* - If `opts.compact = "auto"` and the code is over 100KB, `compact` will be set to `true`.
*/
function normalizeOptions(code, opts, tokens): Format {
let style = " ";
if (code && typeof code === "string") {
let indent = detectIndent(code).indent;
if (indent && indent !== " ") style = indent;
}
let format = {
auxiliaryCommentBefore: opts.auxiliaryCommentBefore,
auxiliaryCommentAfter: opts.auxiliaryCommentAfter,
shouldPrintComment: opts.shouldPrintComment,
retainLines: opts.retainLines,
comments: opts.comments == null || opts.comments,
compact: opts.compact,
minified: opts.minified,
concise: opts.concise,
quotes: opts.quotes || findCommonStringDelimiter(code, tokens),
indent: {
adjustMultilineComment: true,
style: style,
base: 0
}
};
if (format.minified) {
format.compact = true;
format.shouldPrintComment = format.shouldPrintComment || (() => format.comments);
} else {
format.shouldPrintComment = format.shouldPrintComment || ((value) => format.comments ||
(value.indexOf("@license") >= 0 || value.indexOf("@preserve") >= 0));
}
if (format.compact === "auto") {
format.compact = code.length > 100000; // 100KB
if (format.compact) {
console.error("[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "100KB"));
}
}
if (format.compact) {
format.indent.adjustMultilineComment = false;
}
return format;
}
/**
* Determine if input code uses more single or double quotes.
*/
function findCommonStringDelimiter(code, tokens) {
let occurences = {
single: 0,
double: 0
};
let checked = 0;
for (let i = 0; i < tokens.length; i++) {
let token = tokens[i];
if (token.type.label !== "string") continue;
let raw = code.slice(token.start, token.end);
if (raw[0] === "'") {
occurences.single++;
} else {
occurences.double++;
}
checked++;
if (checked >= 3) break;
}
if (occurences.single > occurences.double) {
return "single";
} else {
return "double";
}
}
/**
* We originally exported the Generator class above, but to make it extra clear that it is a private API,

View File

@ -53,11 +53,6 @@ function isOrHasCallExpression(node) {
}
}
export function isUserWhitespacable(node) {
return t.isUserWhitespacable(node);
}
export function needsWhitespace(node, parent, type) {
if (!node) return 0;

View File

@ -1,25 +1,63 @@
/* eslint max-len: 0 */
import find from "lodash/find";
import findLast from "lodash/findLast";
import isInteger from "lodash/isInteger";
import repeat from "lodash/repeat";
import Buffer from "./buffer";
import * as n from "./node";
import Whitespace from "./whitespace";
import * as t from "babel-types";
const SCIENTIFIC_NOTATION = /e/i;
const ZERO_DECIMAL_INTEGER = /\.0+$/;
const NON_DECIMAL_LITERAL = /^0[box]/;
export type Format = {
shouldPrintComment: (comment: string) => boolean;
retainLines: boolean;
comments: boolean;
auxiliaryCommentBefore: string;
auxiliaryCommentAfter: string;
compact: boolean | "auto";
minified: boolean;
quotes: "single" | "double";
concise: boolean;
indent: {
adjustMultilineComment: boolean;
style: string;
base: number;
}
};
export default class Printer {
constructor(format, map) {
constructor(format, map, tokens) {
this.format = format || {};
this._buf = new Buffer(map);
this.insideAux = false;
this._printAuxAfterOnNextUserNode = false;
this._printStack = [];
this._printedCommentStarts = {};
this._parenPushNewlineState = null;
this._indent = 0;
this.inForStatementInitCounter = 0;
this._whitespace = tokens.length > 0 ? new Whitespace(tokens) : null;
}
_printedCommentStarts: Object;
_parenPushNewlineState: ?Object;
format: Format;
inForStatementInitCounter: number = 0;
_buf: Buffer;
_whitespace: Whitespace;
_printStack: Array<Node> = [];
_indent: number = 0;
_insideAux: boolean = false;
_printedCommentStarts: Object = {};
_parenPushNewlineState: ?Object = null;
_printAuxAfterOnNextUserNode: boolean = false;
_printedComments: WeakSet = new WeakSet();
_endsWithInteger = false;
_endsWithWord = false;
generate(ast) {
this.print(ast);
this._maybeAddAuxComment();
return this._buf.get();
}
/**
* Increment indent size.
@ -46,6 +84,7 @@ export default class Printer {
*/
semicolon(force: boolean = false): void {
this._maybeAddAuxComment();
this._append(";", !force /* queue */);
}
@ -54,23 +93,12 @@ export default class Printer {
*/
rightBrace(): void {
if (!this.endsWith("\n")) this.newline();
if (this.format.minified) {
this._buf.removeLastSemicolon();
}
this.token("}");
}
/**
* Add a keyword to the buffer.
*/
keyword(name: string): void {
this.word(name);
this.space();
}
/**
* Add a space to the buffer unless it is compact.
*/
@ -90,27 +118,48 @@ export default class Printer {
word(str: string): void {
if (this._endsWithWord) this._space();
this._maybeAddAuxComment();
this._append(str);
this._endsWithWord = true;
}
/**
* Writes a number token so that we can validate if it is an integer.
*/
number(str: string): void {
this.word(str);
// Integer tokens need special handling because they cannot have '.'s inserted
// immediately after them.
this._endsWithInteger =
isInteger(+str) &&
!NON_DECIMAL_LITERAL.test(str) &&
!SCIENTIFIC_NOTATION.test(str) &&
!ZERO_DECIMAL_INTEGER.test(str) &&
str[str.length - 1] !== ".";
}
/**
* Writes a simple token.
*/
token(str: string): void {
const last = this._buf.getLast();
// space is mandatory to avoid outputting <!--
// http://javascript.spec.whatwg.org/#comment-syntax
if ((str === "--" && last === "!") ||
if ((str === "--" && this.endsWith("!")) ||
// Need spaces for operators of the same kind to avoid: `a+++b`
(str[0] === "+" && last === "+") ||
(str[0] === "-" && last === "-")) {
(str[0] === "+" && this.endsWith("+")) ||
(str[0] === "-" && this.endsWith("-")) ||
// Needs spaces to avoid changing '34' to '34.', which would still be a valid number.
(str[0] === "." && this._endsWithInteger)) {
this._space();
}
this._maybeAddAuxComment();
this._append(str);
}
@ -135,7 +184,6 @@ export default class Printer {
if (this.endsWith("{\n") || this.endsWith(":\n")) i--;
if (i <= 0) return;
this._buf.removeTrailingSpaces();
for (let j = 0; j < i; j++) {
this._newline();
}
@ -177,6 +225,7 @@ export default class Printer {
else this._buf.append(str);
this._endsWithWord = false;
this._endsWithInteger = false;
}
_maybeIndent(str: string): void {
@ -211,7 +260,9 @@ export default class Printer {
// catch up to this nodes newline if we're behind
const pos = loc ? loc[prop] : null;
if (pos && pos.line !== null) {
while (this._buf.getCurrentLine() < pos.line) {
const count = pos.line - this._buf.getCurrentLine();
for (let i = 0; i < count; i++) {
this._newline();
}
}
@ -259,7 +310,7 @@ export default class Printer {
}
}
print(node, parent, opts = {}) {
print(node, parent) {
if (!node) return;
let oldConcise = this.format.concise;
@ -274,38 +325,34 @@ export default class Printer {
this._printStack.push(node);
let oldInAux = this.insideAux;
this.insideAux = !node.loc;
if (!this.insideAux) this.printAuxAfterComment();
else if (!oldInAux) this._printAuxBeforeComment();
let oldInAux = this._insideAux;
this._insideAux = !node.loc;
this._maybeAddAuxComment(this._insideAux && !oldInAux);
let needsParens = n.needsParens(node, parent, this._printStack);
if (needsParens) this.token("(");
this._printLeadingComments(node, parent);
this._printNewline(true, node, parent, opts);
let loc = (t.isProgram(node) || t.isFile(node)) ? null : node.loc;
this.withSource("start", loc, () => {
this[node.type](node, parent);
});
// Check again if any of our children may have left an aux comment on the stack
if (!this.insideAux) this.printAuxAfterComment();
this._printTrailingComments(node, parent);
if (needsParens) this.token(")");
// end
this._printStack.pop();
if (opts.after) opts.after();
this.format.concise = oldConcise;
this.insideAux = oldInAux;
this._insideAux = oldInAux;
}
this._printNewline(false, node, parent, opts);
_maybeAddAuxComment(enteredPositionlessNode) {
if (enteredPositionlessNode) this._printAuxBeforeComment();
if (!this._insideAux) this._printAuxAfterComment();
}
_printAuxBeforeComment() {
@ -321,7 +368,7 @@ export default class Printer {
}
}
printAuxAfterComment() {
_printAuxAfterComment() {
if (!this._printAuxAfterOnNextUserNode) return;
this._printAuxAfterOnNextUserNode = false;
@ -346,32 +393,29 @@ export default class Printer {
printJoin(nodes: ?Array, parent: Object, opts = {}) {
if (!nodes || !nodes.length) return;
let len = nodes.length;
let node, i;
if (opts.indent) this.indent();
let printOpts = {
statement: opts.statement,
const newlineOpts = {
addNewlines: opts.addNewlines,
after: () => {
if (opts.iterator) {
opts.iterator(node, i);
}
if (opts.separator && parent.loc) {
this.printAuxAfterComment();
}
if (opts.separator && i < len - 1) {
opts.separator.call(this);
}
}
};
for (i = 0; i < nodes.length; i++) {
node = nodes[i];
this.print(node, parent, printOpts);
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (!node) continue;
if (opts.statement) this._printNewline(true, node, parent, newlineOpts);
this.print(node, parent);
if (opts.iterator) {
opts.iterator(node, i);
}
if (opts.separator && i < nodes.length - 1) {
opts.separator.call(this);
}
if (opts.statement) this._printNewline(false, node, parent, newlineOpts);
}
if (opts.indent) this.dedent();
@ -426,10 +470,6 @@ export default class Printer {
// Fast path since 'this.newline' does nothing when not tracking lines.
if (this.format.retainLines || this.format.compact) return;
if (!opts.statement && !n.isUserWhitespacable(node, parent)) {
return;
}
// Fast path for concise since 'this.newline' just inserts a space when
// concise formatting is in use.
if (this.format.concise) {
@ -442,9 +482,17 @@ export default class Printer {
if (node.start != null && !node._ignoreUserWhitespace && this._whitespace) {
// user node
if (leading) {
lines = this._whitespace.getNewlinesBefore(node);
const comments = node.leadingComments;
const comment = comments && find(comments, (comment) =>
!!comment.loc && this.format.shouldPrintComment(comment.value));
lines = this._whitespace.getNewlinesBefore(comment || node);
} else {
lines = this._whitespace.getNewlinesAfter(node);
const comments = node.trailingComments;
const comment = comments && findLast(comments, (comment) =>
!!comment.loc && this.format.shouldPrintComment(comment.value));
lines = this._whitespace.getNewlinesAfter(comment || node);
}
} else {
// generated node
@ -468,65 +516,48 @@ export default class Printer {
return (node && (leading ? node.leadingComments : node.trailingComments)) || [];
}
_shouldPrintComment(comment) {
if (this.format.shouldPrintComment) {
return this.format.shouldPrintComment(comment.value);
} else {
if (!this.format.minified &&
(comment.value.indexOf("@license") >= 0 || comment.value.indexOf("@preserve") >= 0)) {
return true;
} else {
return this.format.comments;
}
}
}
_printComment(comment) {
if (!this._shouldPrintComment(comment)) return;
if (!this.format.shouldPrintComment(comment.value)) return;
// Some plugins use this to mark comments as removed using the AST-root 'comments' property,
// where they can't manually mutate the AST node comment lists.
if (comment.ignore) return;
comment.ignore = true;
if (this._printedComments.has(comment)) return;
this._printedComments.add(comment);
if (comment.start != null) {
if (this._printedCommentStarts[comment.start]) return;
this._printedCommentStarts[comment.start] = true;
}
// Exclude comments from source mappings since they will only clutter things.
// whitespace before
this.newline(this._whitespace ? this._whitespace.getNewlinesBefore(comment) : 0);
if (!this.endsWith("[") && !this.endsWith("{")) this.space();
let val = comment.type === "CommentLine" ? `//${comment.value}\n` : `/*${comment.value}*/`;
//
if (comment.type === "CommentBlock" && this.format.indent.adjustMultilineComment) {
let offset = comment.loc && comment.loc.start.column;
if (offset) {
let newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g");
val = val.replace(newlineRegex, "\n");
}
let indentSize = Math.max(this._getIndent().length, this._buf.getCurrentColumn());
val = val.replace(/\n(?!$)/g, `\n${repeat(" ", indentSize)}`);
}
this.withSource("start", comment.loc, () => {
// whitespace before
this.newline(this._whitespace ? this._whitespace.getNewlinesBefore(comment) : 0);
if (!this.endsWith("[") && !this.endsWith("{")) this.space();
let val = comment.type === "CommentLine" ? `//${comment.value}` : `/*${comment.value}*/`;
//
if (comment.type === "CommentBlock" && this.format.indent.adjustMultilineComment) {
let offset = comment.loc && comment.loc.start.column;
if (offset) {
let newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g");
val = val.replace(newlineRegex, "\n");
}
let indentSize = Math.max(this._getIndent().length, this._buf.getCurrentColumn());
val = val.replace(/\n(?!$)/g, `\n${repeat(" ", indentSize)}`);
}
// 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) &&
comment.type === "CommentLine") {
val += "\n";
}
//
this.token(val);
// whitespace after
this.newline((this._whitespace ? this._whitespace.getNewlinesAfter(comment) : 0) ||
(comment.type === "CommentLine" ? 1 : 0));
this._append(val);
});
// whitespace after
this.newline((this._whitespace ? this._whitespace.getNewlinesAfter(comment) : 0) +
// Subtract one to account for the line force-added above.
(comment.type === "CommentLine" ? -1 : 0));
}
_printComments(comments?: Array<Object>) {

View File

@ -20,6 +20,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function test() {}
// Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>

View File

@ -6,6 +6,6 @@ function foo(l) {
function foo() {
return (
1 && 2 ||
1 && 2 ||
3);
}

View File

@ -5,7 +5,7 @@ function foo() {
}
function foo() {
return(
return (
// foobar
"bar"
);

View File

@ -4,20 +4,18 @@ Object.defineProperty(exports, "__esModule", {
value: true
});
exports.test = undefined;
/*after*/
/*before*/require("foo"); /*after*/
/*before*/require("foo-bar"); /*after*/
/*after*/ /*before*/require("foo") /*after*/;
/*before*/require("./directory/foo-bar"); /*after*/
/*before*/require("foo-bar") /*after*/;
/*before*/require("./directory/foo-bar") /*after*/;
var /*before*/_foo = require("foo2") /*after*/;
/*before*/
var _foo2 = babelHelpers.interopRequireDefault(_foo);
/*before*/var _foo2 = babelHelpers.interopRequireDefault(_foo);
/*after*/
var /*before*/_foo3 = require("foo3") /*after*/;
/*after*/var /*before*/_foo3 = require("foo3") /*after*/;
/*before*/var /*after*/foo2 = babelHelpers.interopRequireWildcard(_foo3);
@ -31,5 +29,5 @@ var test = /*before*/exports. /*after*/test = 5;
/*before*/(0, _foo4.bar) /*after*/( /*before*/_foo2.default /*after*/, /*before*/_foo5.foo /*after*/);
/* my comment */
/*before*/_foo5.foo; /*after*/
/*before*/_foo2.default; /*after*/
/*before*/_foo5.foo /*after*/;
/*before*/_foo2.default /*after*/;