react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / node_modules / commoner / node_modules / recast / lib / printer.js
81169 viewsvar assert = require("assert");1var sourceMap = require("source-map");2var printComments = require("./comments").printComments;3var linesModule = require("./lines");4var fromString = linesModule.fromString;5var concat = linesModule.concat;6var normalizeOptions = require("./options").normalize;7var getReprinter = require("./patcher").getReprinter;8var types = require("./types");9var namedTypes = types.namedTypes;10var isString = types.builtInTypes.string;11var isObject = types.builtInTypes.object;12var FastPath = require("./fast-path");13var util = require("./util");1415function PrintResult(code, sourceMap) {16assert.ok(this instanceof PrintResult);1718isString.assert(code);19this.code = code;2021if (sourceMap) {22isObject.assert(sourceMap);23this.map = sourceMap;24}25}2627var PRp = PrintResult.prototype;28var warnedAboutToString = false;2930PRp.toString = function() {31if (!warnedAboutToString) {32console.warn(33"Deprecation warning: recast.print now returns an object with " +34"a .code property. You appear to be treating the object as a " +35"string, which might still work but is strongly discouraged."36);3738warnedAboutToString = true;39}4041return this.code;42};4344var emptyPrintResult = new PrintResult("");4546function Printer(originalOptions) {47assert.ok(this instanceof Printer);4849var explicitTabWidth = originalOptions && originalOptions.tabWidth;50var options = normalizeOptions(originalOptions);51assert.notStrictEqual(options, originalOptions);5253// It's common for client code to pass the same options into both54// recast.parse and recast.print, but the Printer doesn't need (and55// can be confused by) options.sourceFileName, so we null it out.56options.sourceFileName = null;5758function printWithComments(path) {59assert.ok(path instanceof FastPath);60return printComments(path.getNode().comments, print(path), options);61}6263function print(path, includeComments) {64if (includeComments)65return printWithComments(path);6667assert.ok(path instanceof FastPath);6869if (!explicitTabWidth) {70var oldTabWidth = options.tabWidth;71var loc = path.getNode().loc;72if (loc && loc.lines && loc.lines.guessTabWidth) {73options.tabWidth = loc.lines.guessTabWidth();74var lines = maybeReprint(path);75options.tabWidth = oldTabWidth;76return lines;77}78}7980return maybeReprint(path);81}8283function maybeReprint(path) {84var reprinter = getReprinter(path);85if (reprinter)86return maybeAddParens(path, reprinter(maybeReprint));87return printRootGenerically(path);88}8990// Print the root node generically, but then resume reprinting its91// children non-generically.92function printRootGenerically(path) {93return genericPrint(path, options, printWithComments);94}9596// Print the entire AST generically.97function printGenerically(path) {98return genericPrint(path, options, printGenerically);99}100101this.print = function(ast) {102if (!ast) {103return emptyPrintResult;104}105106var lines = print(FastPath.from(ast), true);107108return new PrintResult(109lines.toString(options),110util.composeSourceMaps(111options.inputSourceMap,112lines.getSourceMap(113options.sourceMapName,114options.sourceRoot115)116)117);118};119120this.printGenerically = function(ast) {121if (!ast) {122return emptyPrintResult;123}124125var path = FastPath.from(ast);126var oldReuseWhitespace = options.reuseWhitespace;127128// Do not reuse whitespace (or anything else, for that matter)129// when printing generically.130options.reuseWhitespace = false;131var pr = new PrintResult(printGenerically(path).toString(options));132options.reuseWhitespace = oldReuseWhitespace;133return pr;134};135}136137exports.Printer = Printer;138139function maybeAddParens(path, lines) {140return path.needsParens() ? concat(["(", lines, ")"]) : lines;141}142143function genericPrint(path, options, printPath) {144assert.ok(path instanceof FastPath);145return maybeAddParens(path, genericPrintNoParens(path, options, printPath));146}147148function genericPrintNoParens(path, options, print) {149var n = path.getValue();150151if (!n) {152return fromString("");153}154155if (typeof n === "string") {156return fromString(n, options);157}158159namedTypes.Node.assert(n);160161switch (n.type) {162case "File":163return path.call(print, "program");164165case "Program":166return maybeAddSemicolon(path.call(function(bodyPath) {167return printStatementSequence(bodyPath, options, print);168}, "body"));169170case "EmptyStatement":171return fromString("");172173case "ExpressionStatement":174return concat([path.call(print, "expression"), ";"]);175176case "BinaryExpression":177case "LogicalExpression":178case "AssignmentExpression":179return fromString(" ").join([180path.call(print, "left"),181n.operator,182path.call(print, "right")183]);184185case "MemberExpression":186var parts = [path.call(print, "object")];187188if (n.computed)189parts.push("[", path.call(print, "property"), "]");190else191parts.push(".", path.call(print, "property"));192193return concat(parts);194195case "Path":196return fromString(".").join(n.body);197198case "Identifier":199return fromString(n.name, options);200201case "SpreadElement":202case "SpreadElementPattern":203case "SpreadProperty":204case "SpreadPropertyPattern":205return concat(["...", path.call(print, "argument")]);206207case "FunctionDeclaration":208case "FunctionExpression":209var parts = [];210211if (n.async)212parts.push("async ");213214parts.push("function");215216if (n.generator)217parts.push("*");218219if (n.id)220parts.push(" ", path.call(print, "id"));221222parts.push(223"(",224printFunctionParams(path, options, print),225") ",226path.call(print, "body")227);228229return concat(parts);230231case "ArrowFunctionExpression":232var parts = [];233234if (n.async)235parts.push("async ");236237if (n.params.length === 1) {238parts.push(path.call(print, "params", 0));239} else {240parts.push(241"(",242printFunctionParams(path, options, print),243")"244);245}246247parts.push(" => ", path.call(print, "body"));248249return concat(parts);250251case "MethodDefinition":252var parts = [];253254if (n.static) {255parts.push("static ");256}257258parts.push(printMethod(path, options, print));259260return concat(parts);261262case "YieldExpression":263var parts = ["yield"];264265if (n.delegate)266parts.push("*");267268if (n.argument)269parts.push(" ", path.call(print, "argument"));270271return concat(parts);272273case "AwaitExpression":274var parts = ["await"];275276if (n.all)277parts.push("*");278279if (n.argument)280parts.push(" ", path.call(print, "argument"));281282return concat(parts);283284case "ModuleDeclaration":285var parts = ["module", path.call(print, "id")];286287if (n.source) {288assert.ok(!n.body);289parts.push("from", path.call(print, "source"));290} else {291parts.push(path.call(print, "body"));292}293294return fromString(" ").join(parts);295296case "ImportSpecifier":297case "ExportSpecifier":298var parts = [path.call(print, "id")];299300if (n.name)301parts.push(" as ", path.call(print, "name"));302303return concat(parts);304305case "ExportBatchSpecifier":306return fromString("*");307308case "ImportNamespaceSpecifier":309return concat(["* as ", path.call(print, "id")]);310311case "ImportDefaultSpecifier":312return path.call(print, "id");313314case "ExportDeclaration":315var parts = ["export"];316317if (n["default"]) {318parts.push(" default");319320} else if (n.specifiers &&321n.specifiers.length > 0) {322323if (n.specifiers.length === 1 &&324n.specifiers[0].type === "ExportBatchSpecifier") {325parts.push(" *");326} else {327parts.push(328" { ",329fromString(", ").join(path.map(print, "specifiers")),330" }"331);332}333334if (n.source)335parts.push(" from ", path.call(print, "source"));336337parts.push(";");338339return concat(parts);340}341342if (n.declaration) {343if (!namedTypes.Node.check(n.declaration)) {344console.log(JSON.stringify(n, null, 2));345}346var decLines = path.call(print, "declaration");347parts.push(" ", decLines);348if (lastNonSpaceCharacter(decLines) !== ";") {349parts.push(";");350}351}352353return concat(parts);354355case "ImportDeclaration":356var parts = ["import "];357358if (n.specifiers &&359n.specifiers.length > 0) {360361var foundImportSpecifier = false;362363path.each(function(specifierPath) {364var i = specifierPath.getName();365if (i > 0) {366parts.push(", ");367}368369var value = specifierPath.getValue();370371if (namedTypes.ImportDefaultSpecifier.check(value) ||372namedTypes.ImportNamespaceSpecifier.check(value)) {373assert.strictEqual(foundImportSpecifier, false);374} else {375namedTypes.ImportSpecifier.assert(value);376if (!foundImportSpecifier) {377foundImportSpecifier = true;378parts.push("{");379}380}381382parts.push(print(specifierPath));383}, "specifiers");384385if (foundImportSpecifier) {386parts.push("}");387}388389parts.push(" from ");390}391392parts.push(path.call(print, "source"), ";");393394return concat(parts);395396case "BlockStatement":397var naked = path.call(function(bodyPath) {398return printStatementSequence(bodyPath, options, print);399}, "body");400401if (naked.isEmpty()) {402return fromString("{}");403}404405return concat([406"{\n",407naked.indent(options.tabWidth),408"\n}"409]);410411case "ReturnStatement":412var parts = ["return"];413414if (n.argument) {415var argLines = path.call(print, "argument");416if (argLines.length > 1 &&417namedTypes.XJSElement &&418namedTypes.XJSElement.check(n.argument)) {419parts.push(420" (\n",421argLines.indent(options.tabWidth),422"\n)"423);424} else {425parts.push(" ", argLines);426}427}428429parts.push(";");430431return concat(parts);432433case "CallExpression":434return concat([435path.call(print, "callee"),436printArgumentsList(path, options, print)437]);438439case "ObjectExpression":440case "ObjectPattern":441var allowBreak = false,442len = n.properties.length,443parts = [len > 0 ? "{\n" : "{"];444445path.map(function(childPath) {446var i = childPath.getName();447var prop = childPath.getValue();448var lines = print(childPath).indent(options.tabWidth);449450var multiLine = lines.length > 1;451if (multiLine && allowBreak) {452// Similar to the logic for BlockStatement.453parts.push("\n");454}455456parts.push(lines);457458if (i < len - 1) {459// Add an extra line break if the previous object property460// had a multi-line value.461parts.push(multiLine ? ",\n\n" : ",\n");462allowBreak = !multiLine;463}464}, "properties");465466parts.push(len > 0 ? "\n}" : "}");467468return concat(parts);469470case "PropertyPattern":471return concat([472path.call(print, "key"),473": ",474path.call(print, "pattern")475]);476477case "Property": // Non-standard AST node type.478if (n.method || n.kind === "get" || n.kind === "set") {479return printMethod(path, options, print);480}481482if (n.shorthand) {483return path.call(print, "key");484}485486return concat([487path.call(print, "key"),488": ",489path.call(print, "value")490]);491492case "ArrayExpression":493case "ArrayPattern":494var elems = n.elements,495len = elems.length,496parts = ["["];497498path.each(function(elemPath) {499var i = elemPath.getName();500var elem = elemPath.getValue();501if (!elem) {502// If the array expression ends with a hole, that hole503// will be ignored by the interpreter, but if it ends with504// two (or more) holes, we need to write out two (or more)505// commas so that the resulting code is interpreted with506// both (all) of the holes.507parts.push(",");508} else {509if (i > 0)510parts.push(" ");511parts.push(print(elemPath));512if (i < len - 1)513parts.push(",");514}515}, "elements");516517parts.push("]");518519return concat(parts);520521case "SequenceExpression":522return fromString(", ").join(path.map(print, "expressions"));523524case "ThisExpression":525return fromString("this");526527case "Literal":528if (typeof n.value !== "string")529return fromString(n.value, options);530531// intentionally fall through...532533case "ModuleSpecifier":534// A ModuleSpecifier is a string-valued Literal.535return fromString(nodeStr(n, options), options);536537case "UnaryExpression":538var parts = [n.operator];539if (/[a-z]$/.test(n.operator))540parts.push(" ");541parts.push(path.call(print, "argument"));542return concat(parts);543544case "UpdateExpression":545var parts = [path.call(print, "argument"), n.operator];546547if (n.prefix)548parts.reverse();549550return concat(parts);551552case "ConditionalExpression":553return concat([554"(", path.call(print, "test"),555" ? ", path.call(print, "consequent"),556" : ", path.call(print, "alternate"), ")"557]);558559case "NewExpression":560var parts = ["new ", path.call(print, "callee")];561var args = n.arguments;562if (args) {563parts.push(printArgumentsList(path, options, print));564}565566return concat(parts);567568case "VariableDeclaration":569var parts = [n.kind, " "];570var maxLen = 0;571var printed = path.map(function(childPath) {572var lines = print(childPath);573maxLen = Math.max(lines.length, maxLen);574return lines;575}, "declarations");576577if (maxLen === 1) {578parts.push(fromString(", ").join(printed));579} else if (printed.length > 1 ) {580parts.push(581fromString(",\n").join(printed)582.indentTail(n.kind.length + 1)583);584} else {585parts.push(printed[0]);586}587588// We generally want to terminate all variable declarations with a589// semicolon, except when they are children of for loops.590var parentNode = path.getParentNode();591if (!namedTypes.ForStatement.check(parentNode) &&592!namedTypes.ForInStatement.check(parentNode) &&593!(namedTypes.ForOfStatement &&594namedTypes.ForOfStatement.check(parentNode))) {595parts.push(";");596}597598return concat(parts);599600case "VariableDeclarator":601return n.init ? fromString(" = ").join([602path.call(print, "id"),603path.call(print, "init")604]) : path.call(print, "id");605606case "WithStatement":607return concat([608"with (",609path.call(print, "object"),610") ",611path.call(print, "body")612]);613614case "IfStatement":615var con = adjustClause(path.call(print, "consequent"), options),616parts = ["if (", path.call(print, "test"), ")", con];617618if (n.alternate)619parts.push(620endsWithBrace(con) ? " else" : "\nelse",621adjustClause(path.call(print, "alternate"), options));622623return concat(parts);624625case "ForStatement":626// TODO Get the for (;;) case right.627var init = path.call(print, "init"),628sep = init.length > 1 ? ";\n" : "; ",629forParen = "for (",630indented = fromString(sep).join([631init,632path.call(print, "test"),633path.call(print, "update")634]).indentTail(forParen.length),635head = concat([forParen, indented, ")"]),636clause = adjustClause(path.call(print, "body"), options),637parts = [head];638639if (head.length > 1) {640parts.push("\n");641clause = clause.trimLeft();642}643644parts.push(clause);645646return concat(parts);647648case "WhileStatement":649return concat([650"while (",651path.call(print, "test"),652")",653adjustClause(path.call(print, "body"), options)654]);655656case "ForInStatement":657// Note: esprima can't actually parse "for each (".658return concat([659n.each ? "for each (" : "for (",660path.call(print, "left"),661" in ",662path.call(print, "right"),663")",664adjustClause(path.call(print, "body"), options)665]);666667case "ForOfStatement":668return concat([669"for (",670path.call(print, "left"),671" of ",672path.call(print, "right"),673")",674adjustClause(path.call(print, "body"), options)675]);676677case "DoWhileStatement":678var doBody = concat([679"do",680adjustClause(path.call(print, "body"), options)681]), parts = [doBody];682683if (endsWithBrace(doBody))684parts.push(" while");685else686parts.push("\nwhile");687688parts.push(" (", path.call(print, "test"), ");");689690return concat(parts);691692case "BreakStatement":693var parts = ["break"];694if (n.label)695parts.push(" ", path.call(print, "label"));696parts.push(";");697return concat(parts);698699case "ContinueStatement":700var parts = ["continue"];701if (n.label)702parts.push(" ", path.call(print, "label"));703parts.push(";");704return concat(parts);705706case "LabeledStatement":707return concat([708path.call(print, "label"),709":\n",710path.call(print, "body")711]);712713case "TryStatement":714var parts = [715"try ",716path.call(print, "block")717];718719path.each(function(handlerPath) {720parts.push(" ", print(handlerPath));721}, "handlers");722723if (n.finalizer)724parts.push(" finally ", path.call(print, "finalizer"));725726return concat(parts);727728case "CatchClause":729var parts = ["catch (", path.call(print, "param")];730731if (n.guard)732// Note: esprima does not recognize conditional catch clauses.733parts.push(" if ", path.call(print, "guard"));734735parts.push(") ", path.call(print, "body"));736737return concat(parts);738739case "ThrowStatement":740return concat(["throw ", path.call(print, "argument"), ";"]);741742case "SwitchStatement":743return concat([744"switch (",745path.call(print, "discriminant"),746") {\n",747fromString("\n").join(path.map(print, "cases")),748"\n}"749]);750751// Note: ignoring n.lexical because it has no printing consequences.752753case "SwitchCase":754var parts = [];755756if (n.test)757parts.push("case ", path.call(print, "test"), ":");758else759parts.push("default:");760761if (n.consequent.length > 0) {762parts.push("\n", path.call(function(consequentPath) {763return printStatementSequence(consequentPath, options, print);764}, "consequent").indent(options.tabWidth));765}766767return concat(parts);768769case "DebuggerStatement":770return fromString("debugger;");771772// XJS extensions below.773774case "XJSAttribute":775var parts = [path.call(print, "name")];776if (n.value)777parts.push("=", path.call(print, "value"));778return concat(parts);779780case "XJSIdentifier":781return fromString(n.name, options);782783case "XJSNamespacedName":784return fromString(":").join([785path.call(print, "namespace"),786path.call(print, "name")787]);788789case "XJSMemberExpression":790return fromString(".").join([791path.call(print, "object"),792path.call(print, "property")793]);794795case "XJSSpreadAttribute":796return concat(["{...", path.call(print, "argument"), "}"]);797798case "XJSExpressionContainer":799return concat(["{", path.call(print, "expression"), "}"]);800801case "XJSElement":802var openingLines = path.call(print, "openingElement");803804if (n.openingElement.selfClosing) {805assert.ok(!n.closingElement);806return openingLines;807}808809var childLines = concat(810path.map(function(childPath) {811var child = childPath.getValue();812813if (namedTypes.Literal.check(child) &&814typeof child.value === "string") {815if (/\S/.test(child.value)) {816return child.value.replace(/^\s+|\s+$/g, "");817} else if (/\n/.test(child.value)) {818return "\n";819}820}821822return print(childPath);823}, "children")824).indentTail(options.tabWidth);825826var closingLines = path.call(print, "closingElement");827828return concat([829openingLines,830childLines,831closingLines832]);833834case "XJSOpeningElement":835var parts = ["<", path.call(print, "name")];836var attrParts = [];837838path.each(function(attrPath) {839attrParts.push(" ", print(attrPath));840}, "attributes");841842var attrLines = concat(attrParts);843844var needLineWrap = (845attrLines.length > 1 ||846attrLines.getLineLength(1) > options.wrapColumn847);848849if (needLineWrap) {850attrParts.forEach(function(part, i) {851if (part === " ") {852assert.strictEqual(i % 2, 0);853attrParts[i] = "\n";854}855});856857attrLines = concat(attrParts).indentTail(options.tabWidth);858}859860parts.push(attrLines, n.selfClosing ? " />" : ">");861862return concat(parts);863864case "XJSClosingElement":865return concat(["</", path.call(print, "name"), ">"]);866867case "XJSText":868return fromString(n.value, options);869870case "XJSEmptyExpression":871return fromString("");872873case "TypeAnnotatedIdentifier":874return concat([875path.call(print, "annotation"),876" ",877path.call(print, "identifier")878]);879880case "ClassBody":881if (n.body.length === 0) {882return fromString("{}");883}884885return concat([886"{\n",887path.call(function(bodyPath) {888return printStatementSequence(bodyPath, options, print);889}, "body").indent(options.tabWidth),890"\n}"891]);892893case "ClassPropertyDefinition":894var parts = ["static ", path.call(print, "definition")];895if (!namedTypes.MethodDefinition.check(n.definition))896parts.push(";");897return concat(parts);898899case "ClassProperty":900return concat([path.call(print, "id"), ";"]);901902case "ClassDeclaration":903case "ClassExpression":904var parts = ["class"];905906if (n.id)907parts.push(" ", path.call(print, "id"));908909if (n.superClass)910parts.push(" extends ", path.call(print, "superClass"));911912parts.push(" ", path.call(print, "body"));913914return concat(parts);915916// These types are unprintable because they serve as abstract917// supertypes for other (printable) types.918case "Node":919case "Printable":920case "SourceLocation":921case "Position":922case "Statement":923case "Function":924case "Pattern":925case "Expression":926case "Declaration":927case "Specifier":928case "NamedSpecifier":929case "Block": // Block comment.930case "Line": // Line comment.931throw new Error("unprintable type: " + JSON.stringify(n.type));932933// Unhandled types below. If encountered, nodes of these types should934// be either left alone or desugared into AST types that are fully935// supported by the pretty-printer.936937case "ClassHeritage": // TODO938case "ComprehensionBlock": // TODO939case "ComprehensionExpression": // TODO940case "Glob": // TODO941case "TaggedTemplateExpression": // TODO942case "TemplateElement": // TODO943case "TemplateLiteral": // TODO944case "GeneratorExpression": // TODO945case "LetStatement": // TODO946case "LetExpression": // TODO947case "GraphExpression": // TODO948case "GraphIndexExpression": // TODO949950// Type Annotations for Facebook Flow, typically stripped out or951// transformed away before printing.952case "AnyTypeAnnotation": // TODO953case "ArrayTypeAnnotation": // TODO954case "BooleanTypeAnnotation": // TODO955case "ClassImplements": // TODO956case "DeclareClass": // TODO957case "DeclareFunction": // TODO958case "DeclareModule": // TODO959case "DeclareVariable": // TODO960case "FunctionTypeAnnotation": // TODO961case "FunctionTypeParam": // TODO962case "GenericTypeAnnotation": // TODO963case "InterfaceDeclaration": // TODO964case "InterfaceExtends": // TODO965case "IntersectionTypeAnnotation": // TODO966case "MemberTypeAnnotation": // TODO967case "NullableTypeAnnotation": // TODO968case "NumberTypeAnnotation": // TODO969case "ObjectTypeAnnotation": // TODO970case "ObjectTypeCallProperty": // TODO971case "ObjectTypeIndexer": // TODO972case "ObjectTypeProperty": // TODO973case "QualifiedTypeIdentifier": // TODO974case "StringLiteralTypeAnnotation": // TODO975case "StringTypeAnnotation": // TODO976case "TupleTypeAnnotation": // TODO977case "Type": // TODO978case "TypeAlias": // TODO979case "TypeAnnotation": // TODO980case "TypeCastExpression": // TODO981case "TypeParameterDeclaration": // TODO982case "TypeParameterInstantiation": // TODO983case "TypeofTypeAnnotation": // TODO984case "UnionTypeAnnotation": // TODO985case "VoidTypeAnnotation": // TODO986987// XML types that nobody cares about or needs to print.988case "XMLDefaultDeclaration":989case "XMLAnyName":990case "XMLQualifiedIdentifier":991case "XMLFunctionQualifiedIdentifier":992case "XMLAttributeSelector":993case "XMLFilterExpression":994case "XML":995case "XMLElement":996case "XMLList":997case "XMLEscape":998case "XMLText":999case "XMLStartTag":1000case "XMLEndTag":1001case "XMLPointTag":1002case "XMLName":1003case "XMLAttribute":1004case "XMLCdata":1005case "XMLComment":1006case "XMLProcessingInstruction":1007default:1008debugger;1009throw new Error("unknown type: " + JSON.stringify(n.type));1010}10111012return p;1013}10141015function printStatementSequence(path, options, print) {1016var inClassBody =1017namedTypes.ClassBody &&1018namedTypes.ClassBody.check(path.getParentNode());10191020var filtered = [];1021path.each(function(stmtPath) {1022var i = stmtPath.getName();1023var stmt = stmtPath.getValue();10241025// Just in case the AST has been modified to contain falsy1026// "statements," it's safer simply to skip them.1027if (!stmt) {1028return;1029}10301031// Skip printing EmptyStatement nodes to avoid leaving stray1032// semicolons lying around.1033if (stmt.type === "EmptyStatement") {1034return;1035}10361037if (!inClassBody) {1038namedTypes.Statement.assert(stmt);1039}10401041// We can't hang onto stmtPath outside of this function, because1042// it's just a reference to a mutable FastPath object, so we have1043// to go ahead and print it here.1044filtered.push({1045node: stmt,1046printed: print(stmtPath)1047});1048});10491050var prevTrailingSpace = null;1051var len = filtered.length;1052var parts = [];10531054filtered.forEach(function(info, i) {1055var printed = info.printed;1056var stmt = info.node;1057var needSemicolon = true;1058var multiLine = printed.length > 1;1059var notFirst = i > 0;1060var notLast = i < len - 1;1061var leadingSpace;1062var trailingSpace;10631064if (inClassBody) {1065if (namedTypes.MethodDefinition.check(stmt) ||1066(namedTypes.ClassPropertyDefinition.check(stmt) &&1067namedTypes.MethodDefinition.check(stmt.definition))) {1068needSemicolon = false;1069}1070}10711072if (needSemicolon) {1073// Try to add a semicolon to anything that isn't a method in a1074// class body.1075printed = maybeAddSemicolon(printed);1076}10771078var trueLoc = options.reuseWhitespace && getTrueLoc(stmt);1079var lines = trueLoc && trueLoc.lines;10801081if (notFirst) {1082if (lines) {1083var beforeStart = lines.skipSpaces(trueLoc.start, true);1084var beforeStartLine = beforeStart ? beforeStart.line : 1;1085var leadingGap = trueLoc.start.line - beforeStartLine;1086leadingSpace = Array(leadingGap + 1).join("\n");1087} else {1088leadingSpace = multiLine ? "\n\n" : "\n";1089}1090} else {1091leadingSpace = "";1092}10931094if (notLast) {1095if (lines) {1096var afterEnd = lines.skipSpaces(trueLoc.end);1097var afterEndLine = afterEnd ? afterEnd.line : lines.length;1098var trailingGap = afterEndLine - trueLoc.end.line;1099trailingSpace = Array(trailingGap + 1).join("\n");1100} else {1101trailingSpace = multiLine ? "\n\n" : "\n";1102}1103} else {1104trailingSpace = "";1105}11061107parts.push(1108maxSpace(prevTrailingSpace, leadingSpace),1109printed1110);11111112if (notLast) {1113prevTrailingSpace = trailingSpace;1114} else if (trailingSpace) {1115parts.push(trailingSpace);1116}1117});11181119return concat(parts);1120}11211122function getTrueLoc(node) {1123// It's possible that node is newly-created (not parsed by Esprima),1124// in which case it probably won't have a .loc property (or an1125// .original property for that matter). That's fine; we'll just1126// pretty-print it as usual.1127if (!node.loc) {1128return null;1129}11301131if (!node.comments) {1132// If the node has no comments, regard node.loc as true.1133return node.loc;1134}11351136var start = node.loc.start;1137var end = node.loc.end;11381139// If the node has any comments, their locations might contribute to1140// the true start/end positions of the node.1141node.comments.forEach(function(comment) {1142if (comment.loc) {1143if (util.comparePos(comment.loc.start, start) < 0) {1144start = comment.loc.start;1145}11461147if (util.comparePos(end, comment.loc.end) < 0) {1148end = comment.loc.end;1149}1150}1151});11521153return {1154lines: node.loc.lines,1155start: start,1156end: end1157};1158}11591160function maxSpace(s1, s2) {1161if (!s1 && !s2) {1162return fromString("");1163}11641165if (!s1) {1166return fromString(s2);1167}11681169if (!s2) {1170return fromString(s1);1171}11721173var spaceLines1 = fromString(s1);1174var spaceLines2 = fromString(s2);11751176if (spaceLines2.length > spaceLines1.length) {1177return spaceLines2;1178}11791180return spaceLines1;1181}11821183function printMethod(path, options, print) {1184var node = path.getNode();1185var kind = node.kind;1186var parts = [];11871188namedTypes.FunctionExpression.assert(node.value);11891190if (node.value.async) {1191parts.push("async ");1192}11931194if (!kind || kind === "init") {1195if (node.value.generator) {1196parts.push("*");1197}1198} else {1199assert.ok(kind === "get" || kind === "set");1200parts.push(kind, " ");1201}12021203parts.push(1204path.call(print, "key"),1205"(",1206path.call(function(valuePath) {1207return printFunctionParams(valuePath, options, print);1208}, "value"),1209") ",1210path.call(print, "value", "body")1211);12121213return concat(parts);1214}12151216function printArgumentsList(path, options, print) {1217var printed = path.map(print, "arguments");12181219var joined = fromString(", ").join(printed);1220if (joined.getLineLength(1) > options.wrapColumn) {1221joined = fromString(",\n").join(printed);1222return concat(["(\n", joined.indent(options.tabWidth), "\n)"]);1223}12241225return concat(["(", joined, ")"]);1226}12271228function printFunctionParams(path, options, print) {1229var fun = path.getValue();1230namedTypes.Function.assert(fun);12311232var printed = path.map(print, "params");12331234if (fun.defaults) {1235path.each(function(defExprPath) {1236var i = defExprPath.getName();1237var p = printed[i];1238if (p && defExprPath.getValue()) {1239printed[i] = concat([p, "=", print(defExprPath)]);1240}1241}, "defaults");1242}12431244if (fun.rest) {1245printed.push(concat(["...", path.call(print, "rest")]));1246}12471248var joined = fromString(", ").join(printed);1249if (joined.length > 1 ||1250joined.getLineLength(1) > options.wrapColumn) {1251joined = fromString(",\n").join(printed);1252return concat(["\n", joined.indent(options.tabWidth)]);1253}12541255return joined;1256}12571258function adjustClause(clause, options) {1259if (clause.length > 1)1260return concat([" ", clause]);12611262return concat([1263"\n",1264maybeAddSemicolon(clause).indent(options.tabWidth)1265]);1266}12671268function lastNonSpaceCharacter(lines) {1269var pos = lines.lastPos();1270do {1271var ch = lines.charAt(pos);1272if (/\S/.test(ch))1273return ch;1274} while (lines.prevPos(pos));1275}12761277function endsWithBrace(lines) {1278return lastNonSpaceCharacter(lines) === "}";1279}12801281function swapQuotes(str) {1282return str.replace(/['"]/g, function(m) {1283return m === '"' ? '\'' : '"';1284});1285}12861287function nodeStr(n, options) {1288namedTypes.Literal.assert(n);1289isString.assert(n.value);1290switch (options.quote) {1291case "auto":1292var double = JSON.stringify(n.value);1293var single = swapQuotes(JSON.stringify(swapQuotes(n.value)));1294return double.length > single.length ? single : double;1295case "single":1296return swapQuotes(JSON.stringify(swapQuotes(n.value)));1297case "double":1298default:1299return JSON.stringify(n.value);1300}1301}13021303function maybeAddSemicolon(lines) {1304var eoc = lastNonSpaceCharacter(lines);1305if (!eoc || "\n};".indexOf(eoc) < 0)1306return concat([lines, ";"]);1307return lines;1308}130913101311