diff --git a/CHANGELOG.md b/CHANGELOG.md index b7e2fabce..511506de4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,47 @@ +# 1.2.0 + +[link](https://github.com/jlongster/prettier/compare/1.1.0...1.2.0) + +* match jsx files in pre-commit hook (#1276) +* Fix isPreviousLineEmpty on Windows (#1263) +* Add --dev option to suggested install cmd (#1289) +* Write out change CLI changes synchronously. Fixes #1287. (#1292) +* Remove emoji part from lint-staged's name (#1302) +* omit 'doc' key from options object before passing it to format() (#1299) +* Skip globbing filenames with node-glob when the filename is not a glob (#1307) +* FIX: more documentation for jetbrains (#1265) +* Fix template literal comments (#1296) +* Double quotes for option values in Readme file (#1314) +* Do not print the sub-tree when using prettier-ignore (#1286) +* Bail when traversing === groups (#1294) +* Avoid breaking arguments for last arg expansion (#1305) +* Add typescript as a valid parser value (#1318) +* Add jestbrains filewatcher docs (#1310) +* Add prettier_d to Related Projects (#1328) +* Add parentheses for assignment as body of arrow (#1326) +* Add information about Vim's other autocmd events (#1333) +* add printer branch for TSFirstTypeNode (#1332) +* Optimize `prettier --help` for humans (#1340) +* Update link to @vjeux's React London presentation (#1330) +* Improve regex printing (#1341) +* Fix arrow function parenthesis with comments in flow (#1339) +* Break if () if conditional inside breaks (#1344) +* Don't inline paren at right of arguments (#1345) + # 1.1.0 [link](https://github.com/jlongster/prettier/compare/1.0.0...1.1.0) * Prettier 1.0 is the stabler release we've been waiting for (#1242) -* fix small typo (#1255) -* Fix : ReferenceError: err is not defined (#1254) -* Document debugging strategies (#1253) -* Do not inline member expressions as part of assignments (#1256) -* Fix flow union params (#1251) -* Use a whitelist instead of blacklist for member breaking (#1261) -* Remove trailing whitespace (#1259) -* Get rid of fixFaultyLocations code (#1252) -* Fixing n.comments check in printer (#1239) +* fix small typo (#1255) +* Fix : ReferenceError: err is not defined (#1254) +* Document debugging strategies (#1253) +* Do not inline member expressions as part of assignments (#1256) +* Fix flow union params (#1251) +* Use a whitelist instead of blacklist for member breaking (#1261) +* Remove trailing whitespace (#1259) +* Get rid of fixFaultyLocations code (#1252) +* Fixing n.comments check in printer (#1239) * [WIP] no-semi comments (#1257) # 1.0.1 diff --git a/docs/prettier.min.js b/docs/prettier.min.js index 27d3b7384..b9c5d3d8c 100644 --- a/docs/prettier.min.js +++ b/docs/prettier.min.js @@ -8447,6 +8447,39 @@ var babel6 = function (fork) { .build(); }; +var typescript = function (fork) { + fork.use(es7); + var types = fork.use(types$1); + var def = types.Type.def; + var or = types.Type.or; + + + def("TSAbstractClassDeclaration") + .build("Node") + .field("expression") + .field("type"); + def("TSAsExpression") + .build("Node"); + def("TSEnumDeclaration") + .build("Node"); + def("TSImportEqualsDeclaration") + .build("Node"); + def("TSIndexSignature") + .build("Node"); + def("TSInterfaceDeclaration") + .build("Node"); + def("TSModuleDeclaration") + .build("Node"); + def("TSNamespaceExportDeclaration") + .build("Node"); + def("TSParameterProperty") + .build("Node"); + def("TSTypeLiteral") + .build("Node"); + def("TSAbstractMethodDefinition") + .build("Node"); +}; + var main = fork([ // This core module of AST types captures ES5 as it is parsed today by // git://github.com/ariya/esprima.git#master. @@ -8462,38 +8495,40 @@ var main = fork([ flow, esprima, babel, - babel6 + babel6, + typescript ]); function traverseDoc(doc, onEnter, onExit, shouldTraverseConditionalGroups) { - var hasStopped = false; function traverseDocRec(doc) { + var shouldRecurse = true; if (onEnter) { - hasStopped = hasStopped || onEnter(doc) === false; - } - if (hasStopped) { - return; + if (onEnter(doc) === false) { + shouldRecurse = false; + } } - if (doc.type === "concat") { - for (var i = 0; i < doc.parts.length; i++) { - traverseDocRec(doc.parts[i]); - } - } else if (doc.type === "if-break") { - if (doc.breakContents) { - traverseDocRec(doc.breakContents); - } - if (doc.flatContents) { - traverseDocRec(doc.flatContents); - } - } else if (doc.type === "group" && doc.expandedStates) { - if (shouldTraverseConditionalGroups) { - doc.expandedStates.forEach(traverseDocRec); - } else { + if (shouldRecurse) { + if (doc.type === "concat") { + for (var i = 0; i < doc.parts.length; i++) { + traverseDocRec(doc.parts[i]); + } + } else if (doc.type === "if-break") { + if (doc.breakContents) { + traverseDocRec(doc.breakContents); + } + if (doc.flatContents) { + traverseDocRec(doc.flatContents); + } + } else if (doc.type === "group" && doc.expandedStates) { + if (shouldTraverseConditionalGroups) { + doc.expandedStates.forEach(traverseDocRec); + } else { + traverseDocRec(doc.contents); + } + } else if (doc.contents) { traverseDocRec(doc.contents); } - } else if (doc.contents) { - traverseDocRec(doc.contents); } if (onExit) { @@ -8525,10 +8560,14 @@ function mapDoc(doc, func) { function findInDoc(doc, fn, defaultValue) { var result = defaultValue; + var hasStopped = false; traverseDoc(doc, function(doc) { var maybeResult = fn(doc); if (maybeResult !== undefined) { + hasStopped = true; result = maybeResult; + } + if (hasStopped) { return false; } }); @@ -8585,6 +8624,7 @@ function breakParentGroup(groupStack) { } function propagateBreaks(doc) { + var alreadyVisited = new Map(); const groupStack = []; traverseDoc( doc, @@ -8594,6 +8634,10 @@ function propagateBreaks(doc) { } if (doc.type === "group") { groupStack.push(doc); + if (alreadyVisited.has(doc)) { + return false; + } + alreadyVisited.set(doc, true); } }, doc => { @@ -8844,6 +8888,9 @@ function skipNewline(text, index, opts) { const atIndex = text.charAt(index); if (backwards) { + if (text.charAt(index - 1) === "\r" && atIndex === "\n") { + return index - 2; + } if ( atIndex === "\n" || atIndex === "\r" || @@ -8852,9 +8899,6 @@ function skipNewline(text, index, opts) { ) { return index - 1; } - if (text.charAt(index - 1) === "\r" && atIndex === "\n") { - return index - 2; - } } else { if (atIndex === "\r" && text.charAt(index + 1) === "\n") { return index + 2; @@ -9261,7 +9305,7 @@ function attach(comments, ast, text, options) { ) || handleObjectPropertyAssignment(enclosingNode, precedingNode, comment) || handleTemplateLiteralComments(enclosingNode, comment) || - handleCommentInEmptyParens(enclosingNode, comment) || + handleCommentInEmptyParens(text, enclosingNode, comment) || handleOnlyComments(enclosingNode, ast, comment, isLastComment) ) { // We're good @@ -9522,7 +9566,7 @@ function handleObjectPropertyAssignment(enclosingNode, precedingNode, comment) { function handleTemplateLiteralComments(enclosingNode, comment) { if (enclosingNode && enclosingNode.type === "TemplateLiteral") { const expressionIndex = findExpressionIndexForComment( - enclosingNode.expressions, + enclosingNode.quasis, comment ); // Enforce all comments to be leading block comments. @@ -9533,7 +9577,11 @@ function handleTemplateLiteralComments(enclosingNode, comment) { return false; } -function handleCommentInEmptyParens(enclosingNode, comment) { +function handleCommentInEmptyParens(text, enclosingNode, comment) { + if (getNextNonSpaceNonCommentCharacter(text, comment) !== ")") { + return false; + } + // Only add dangling comments to fix the case when no params are present, // i.e. a function without any argument. if ( @@ -9797,27 +9845,21 @@ function printComment(commentPath) { } } -function findExpressionIndexForComment(expressions, comment) { - let match; +function findExpressionIndexForComment(quasis, comment) { const startPos = locStart(comment) - 1; - const endPos = locEnd(comment) + 1; - for (let i = 0; i < expressions.length; ++i) { - const range = getExpressionRange(expressions[i]); - - if ( - (startPos >= range.start && startPos <= range.end) || - (endPos >= range.start && endPos <= range.end) - ) { - match = i; - break; + for (let i = 1; i < quasis.length; ++i) { + if (startPos < getQuasiRange(quasis[i]).start) { + return i - 1; } } - return match; + // We haven't found it, it probably means that some of the locations are off. + // Let's just return the first one. + return 0; } -function getExpressionRange(expr) { +function getQuasiRange(expr) { if (expr.start !== undefined) { // Babylon return { start: expr.start, end: expr.end }; @@ -9946,7 +9988,7 @@ function printComments(path, print, options, needsSemi) { var comments$1 = { attach, printComments, printDanglingComments }; var name = "prettier"; -var version$2 = "1.1.0"; +var version$2 = "1.2.0"; var description = "Prettier is an opinionated JavaScript formatter"; var bin = {"prettier":"./bin/prettier.js"}; var repository = "prettier/prettier"; @@ -10427,7 +10469,7 @@ FPp.needsParens = function(assumeExpressionContext) { case "AssignmentExpression": if (parent.type === "ArrowFunctionExpression" && parent.body === node) { - return node.left.type === "ObjectPattern"; + return true; } else if ( parent.type === "ForStatement" && (parent.init === node || parent.update === node) @@ -10648,6 +10690,17 @@ function genericPrint(path, options, printPath, args) { assert$4.ok(path instanceof FastPath); var node = path.getValue(); + + // Escape hatch + if ( + node && + node.comments && + node.comments.length > 0 && + node.comments.some(comment => comment.value.trim() === "prettier-ignore") + ) { + return options.originalText.slice(util$4.locStart(node), util$4.locEnd(node)); + } + var parts = []; var needsParens = false; var linesWithoutParens = genericPrintNoParens(path, options, printPath, args); @@ -10656,15 +10709,6 @@ function genericPrint(path, options, printPath, args) { return linesWithoutParens; } - // Escape hatch - if ( - node.comments && - node.comments.length > 0 && - node.comments.some(comment => comment.value.trim() === "prettier-ignore") - ) { - return options.originalText.slice(util$4.locStart(node), util$4.locEnd(node)); - } - if ( node.decorators && node.decorators.length > 0 && @@ -10789,21 +10833,43 @@ function genericPrintNoParens(path, options, print, args) { ); case "BinaryExpression": case "LogicalExpression": { - const parts = printBinaryishExpressions(path, print, options); const parent = path.getParentNode(); + const isInsideParenthesis = + n !== parent.body && + (parent.type === "IfStatement" || + parent.type === "WhileStatement" || + parent.type === "DoStatement"); - // Avoid indenting sub-expressions in if/etc statements. + const parts = printBinaryishExpressions( + path, + print, + options, + /* isNested */ false, + isInsideParenthesis + ); + + // if ( + // this.hasPlugin("dynamicImports") && this.lookahead().type === tt.parenLeft + // ) { + // + // looks super weird, we want to break the children if the parent breaks + // + // if ( + // this.hasPlugin("dynamicImports") && + // this.lookahead().type === tt.parenLeft + // ) { + if (isInsideParenthesis) { + return concat$2(parts); + } + + // Avoid indenting sub-expressions in assignment/return/etc statements. if ( parent.type === "AssignmentExpression" || parent.type === "VariableDeclarator" || shouldInlineLogicalExpression(n) || parent.type === "ReturnStatement" || - (n !== parent.body && - (parent.type === "IfStatement" || - parent.type === "WhileStatement" || - parent.type === "DoStatement" || - parent.type === "ForStatement")) || - (n === parent.body && parent.type === "ArrowFunctionExpression") + (n === parent.body && parent.type === "ArrowFunctionExpression") || + (n !== parent.body && parent.type === "ForStatement") ) { return group$1(concat$2(parts)); } @@ -11471,11 +11537,13 @@ function genericPrintNoParens(path, options, print, args) { case "ThisExpression": return "this"; case "Super": - return "super"; // Babel 6 Literal split + return "super"; + // Babel 6 Literal split case "NullLiteral": - return "null"; // Babel 6 Literal split + return "null"; + // Babel 6 Literal split case "RegExpLiteral": - return n.extra.raw; + return printRegex(n); // Babel 6 Literal split case "NumericLiteral": return printNumber(n.extra.raw); @@ -11485,6 +11553,7 @@ function genericPrintNoParens(path, options, print, args) { case "StringLiteral": case "Literal": if (typeof n.value === "number") return printNumber(n.raw); + if (n.regex) return printRegex(n.regex); if (typeof n.value !== "string") return "" + n.value; return nodeStr(n, options); // Babel 6 @@ -12030,21 +12099,6 @@ function genericPrintNoParens(path, options, print, args) { case "TemplateLiteral": var expressions = path.map(print, "expressions"); - function removeLines(doc) { - // Force this doc into flat mode by statically converting all - // lines into spaces (or soft lines into nothing). Hard lines - // should still output because there's too great of a chance - // of breaking existing assumptions otherwise. - return docUtils$2.mapDoc(doc, d => { - if (d.type === "line" && !d.hard) { - return d.soft ? "" : " "; - } else if (d.type === "if-break") { - return d.flatContents || ""; - } - return d; - }); - } - parts.push("`"); path.each(function(childPath) { @@ -12095,7 +12149,11 @@ function genericPrintNoParens(path, options, print, args) { !shouldTypeScriptTypeAvoidColon(path) && // TypeScript should not have a colon before type parameter constraints !(path.getParentNode().type === "TypeParameter" && - path.getParentNode().constraint) + path.getParentNode().constraint) && + // TypeScript should not have a colon in TSFirstTypeNode nodes + // `a is number` + !(path.getParentNode().type === "TypeAnnotation" && + path.getParentNode().typeAnnotation.type === 'TSFirstTypeNode') ) { parts.push(": "); } @@ -12530,6 +12588,8 @@ function genericPrintNoParens(path, options, print, args) { "]: ", path.call(print, "typeAnnotation") ]); + case "TSFirstTypeNode": + return concat$2([n.parameterName.name, " is ", path.call(print, "typeAnnotation")]) // TODO case "ClassHeritage": // TODO @@ -12696,7 +12756,11 @@ function printMethod(path, options, print) { group$1( concat$2([ path.call(function(valuePath) { - return printFunctionParams(valuePath, print, options); + return comments$3.printComments( + path, + p => printFunctionParams(valuePath, print, options), + options + ) }, "value"), path.call(p => printReturnType(p, print), "value") ]) @@ -12884,7 +12948,7 @@ function printFunctionParams(path, print, options, expandArg) { // }) ) => { // }) if (expandArg) { - return group$1(concat$2(["(", join$2(", ", printed), ")"])); + return group$1(concat$2(["(", join$2(", ", printed.map(removeLines)), ")"])); } // Single object destructuring should hug @@ -12952,8 +13016,7 @@ function canPrintParamsWithoutParens(node) { !node.rest && node.params[0].type === "Identifier" && !node.params[0].typeAnnotation && - !node.params[0].leadingComments && - !node.params[0].trailingComments && + !node.params[0].comments && !node.params[0].optional && !node.predicate && !node.returnType @@ -13728,7 +13791,7 @@ function shouldInlineLogicalExpression(node) { // precedence level and the AST is structured based on precedence // level, things are naturally broken up correctly, i.e. `&&` is // broken before `+`. -function printBinaryishExpressions(path, print, options, isNested) { +function printBinaryishExpressions(path, print, options, isNested, isInsideParenthesis) { let parts = []; let node = path.getValue(); @@ -13755,7 +13818,8 @@ function printBinaryishExpressions(path, print, options, isNested) { left, print, options, - /* isNested */ true + /* isNested */ true, + isInsideParenthesis ), "left" ) @@ -13774,6 +13838,7 @@ function printBinaryishExpressions(path, print, options, isNested) { // in order to avoid having a small right part like -1 be on its own line. const parent = path.getParentNode(); const shouldGroup = + !isInsideParenthesis && parent.type !== node.type && node.left.type !== node.type && node.right.type !== node.type; @@ -13929,6 +13994,11 @@ function makeString(rawContent, enclosingQuote) { return enclosingQuote + newContent + enclosingQuote; } +function printRegex(node) { + const flags = node.flags.split('').sort().join(''); + return `/${node.pattern}/${flags}`; +} + function printNumber(rawNumber) { return ( rawNumber @@ -14157,6 +14227,21 @@ function printArrayItems(path, options, printPath, print) { return concat$2(printedElements); } +function removeLines(doc) { + // Force this doc into flat mode by statically converting all + // lines into spaces (or soft lines into nothing). Hard lines + // should still output because there's too great of a chance + // of breaking existing assumptions otherwise. + return docUtils$2.mapDoc(doc, d => { + if (d.type === "line" && !d.hard) { + return d.soft ? "" : " "; + } else if (d.type === "if-break") { + return d.flatContents || ""; + } + return d; + }); +} + function printAstToDoc$1(ast, options) { function printGenerically(path, args) { return comments$3.printComments( @@ -30360,11 +30445,11 @@ var docDebug = { } }; -var require$$2$11 = ( _package$1 && _package$1['default'] ) || _package$1; +var require$$2$10 = ( _package$1 && _package$1['default'] ) || _package$1; const codeFrame = index$2; const comments = comments$1; -const version = require$$2$11.version; +const version = require$$2$10.version; const printAstToDoc = printer.printAstToDoc; const printDocToString = docPrinter.printDocToString; const normalizeOptions = options.normalize; @@ -30418,6 +30503,14 @@ function attachComments(text, ast, opts) { } function ensureAllCommentsPrinted(astComments) { + for (let i = 0; i < astComments.length; ++i) { + if (astComments[i].value.trim() === "prettier-ignore") { + // If there's a prettier-ignore, we're not printing that sub-tree so we + // don't know if the comments was printed or not. + return; + } + } + astComments.forEach(comment => { if (!comment.printed) { throw new Error( diff --git a/package.json b/package.json index 910d3e986..6e453c2be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prettier", - "version": "1.1.0", + "version": "1.2.0", "description": "Prettier is an opinionated JavaScript formatter", "bin": { "prettier": "./bin/prettier.js"