From 541e929b43ae413ac628fd8225928bf9042589dc Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Thu, 7 Sep 2017 13:26:32 -0300 Subject: [PATCH 01/19] Change how JSX mode is activated in ternaries --- src/printer.js | 11 +- tests/jsx/__snapshots__/jsfmt.spec.js.snap | 238 ++++++++++----------- tests/jsx/conditional-expression.js | 119 +++++------ 3 files changed, 178 insertions(+), 190 deletions(-) diff --git a/src/printer.js b/src/printer.js index 977da24c..403b0ebb 100644 --- a/src/printer.js +++ b/src/printer.js @@ -1244,8 +1244,6 @@ function genericPrintNoParens(path, options, print, args) { n.test.type === "JSXElement" || n.consequent.type === "JSXElement" || n.alternate.type === "JSXElement" || - parent.type === "JSXExpressionContainer" || - firstNonConditionalParent.type === "JSXExpressionContainer" || conditionalExpressionChainContainsJSX(lastConditionalParent) ) { jsxMode = true; @@ -1263,20 +1261,19 @@ function genericPrintNoParens(path, options, print, args) { ]); // The only things we don't wrap are: - // * Nested conditional expressions + // * Nested conditional expressions in alternates // * null - const shouldNotWrap = node => - node.type === "ConditionalExpression" || + const isNull = node => node.type === "NullLiteral" || (node.type === "Literal" && node.value === null); parts.push( " ? ", - shouldNotWrap(n.consequent) + isNull(n.consequent) ? path.call(print, "consequent") : wrap(path.call(print, "consequent")), " : ", - shouldNotWrap(n.alternate) + n.alternate.type === "ConditionalExpression" || isNull(n.alternate) ? path.call(print, "alternate") : wrap(path.call(print, "alternate")) ); diff --git a/tests/jsx/__snapshots__/jsfmt.spec.js.snap b/tests/jsx/__snapshots__/jsfmt.spec.js.snap index 8e0c4c78..076b2cfc 100644 --- a/tests/jsx/__snapshots__/jsfmt.spec.js.snap +++ b/tests/jsx/__snapshots__/jsfmt.spec.js.snap @@ -20,84 +20,70 @@ exports[`conditional-expression.js 1`] = ` // // test ? consequent : alternate; // -// We print a conditional expression in JSX mode if any of the following are -// true: -// * Its parent is a JSXExpressionContainer -// * Its test, consequent, or alternate are JSXElements -// * It is in a chain with other ConditionalExpressions, and the outermost -// one's parent is a JSXExpressionContainer -// * It is in a chain with other ConditionalExpressions, and any of the -// tests, consequents, or alternates of any of the ConditionalExpressions in -// the chain are JSXElements. +// We only print a conditional expression in JSX mode if its test, +// consequent, or alternate are JSXElements. // Otherwise, we print in normal mode. -// This ConditionalExpression does not meet any of the other criteria for -// printing in JSX mode, so it prints in normal mode. The line does not break. +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// The line does not break. normalModeNonBreaking ? "a" : "b"; -// This ConditionalExpression does not meet any of the criteria to print in JSX -// mode, so it prints in normal mode. Its consequent is very long, so it breaks -// out to multiple lines. +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// Its consequent is very long, so it breaks out to multiple lines. normalModeBreaking ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa : "c"; -// This ConditionalExpression prints in JSX mode because its parent is a +// This ConditionalExpression prints in normal mode even though its parent is a // JSXExpressionContainer. The line does not break, so it does not contain // parens.
{a ? "b" : "c"}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. Because the consequent is long enough to break the -// line, both its consequent and alternate break out and are wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the consequent is very long, they are broken in +// multiple lines but no parens are added.
- {a ? ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - ) : ( - "c" - )} + {a + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : "c"}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. The consequent is long enough to break the line, but -// because the alternate is null, only the consequent is wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the consequent is very long, they are broken in +// multiple lines but no parens are added.
- {a ? ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - ) : null} + {a + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : null}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. Because the alternate is long enough to break the -// line, both its consequent and alternate break out and are wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the alternate is very long, they are broken in +// multiple lines but no parens are added.
- {a ? ( - "b" - ) : ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - )} + {a + ? "b" + : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. The alternate is long enough to break the line, but -// because the consequent is null, only the alternate is wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the alternate is very long, they are broken in +// multiple lines but no parens are added.
- {a ? null : ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - )} + {a + ? null + : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. Because the test is long enough to break the -// line, both its consequent and alternate break out and are wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the test is very long, they are broken in +// multiple lines but no parens are added.
- {johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa ? ( - "b" - ) : ( - "c" - )} + {johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + ? "b" + : "c"}
; // This ConditionalExpression prints in JSX mode because its test is a @@ -153,17 +139,14 @@ jsxModeFromElementBreaking ? ( {a ? "a" : b ? "b" : "c"} ; -// This chain of ConditionalExpressions prints in JSX mode because the parent of -// the outermost ConditionalExpression is a JSXExpressionContainer. It is -// breaking. +// This chain of ConditionalExpressions prints in normal mode even though its parent is a +// JSXExpressionContainer. It is breaking.
- {a ? ( - "a" - ) : b ? ( - "b" - ) : ( - thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo - )} + {a + ? "a" + : b + ? "b" + : thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo}
; // This chain of ConditionalExpressions prints in JSX mode because there is a @@ -197,6 +180,20 @@ cable ? ( ) : affairs ? ( "network" ) : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is breaking; notice the consequents +// and alternates in the entire chain get wrapped in parens. +
+ {properties.length > 1 || + (properties.length === 1 && properties[0].apps.size > 1) ? ( + draggingApp == null || newPropertyName == null ? ( + + ) : ( + + ) + ) : null} +
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // There are two ways to print ConditionalExpressions: "normal mode" and // "JSX mode". This is normal mode (when breaking): @@ -217,82 +214,68 @@ cable ? ( // // test ? consequent : alternate; // -// We print a conditional expression in JSX mode if any of the following are -// true: -// * Its parent is a JSXExpressionContainer -// * Its test, consequent, or alternate are JSXElements -// * It is in a chain with other ConditionalExpressions, and the outermost -// one's parent is a JSXExpressionContainer -// * It is in a chain with other ConditionalExpressions, and any of the -// tests, consequents, or alternates of any of the ConditionalExpressions in -// the chain are JSXElements. +// We only print a conditional expression in JSX mode if its test, +// consequent, or alternate are JSXElements. // Otherwise, we print in normal mode. -// This ConditionalExpression does not meet any of the other criteria for -// printing in JSX mode, so it prints in normal mode. The line does not break. +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// The line does not break. normalModeNonBreaking ? "a" : "b"; -// This ConditionalExpression does not meet any of the criteria to print in JSX -// mode, so it prints in normal mode. Its consequent is very long, so it breaks -// out to multiple lines. +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// Its consequent is very long, so it breaks out to multiple lines. normalModeBreaking ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa : "c"; -// This ConditionalExpression prints in JSX mode because its parent is a +// This ConditionalExpression prints in normal mode even though its parent is a // JSXExpressionContainer. The line does not break, so it does not contain // parens.
{a ? "b" : "c"}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. Because the consequent is long enough to break the -// line, both its consequent and alternate break out and are wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the consequent is very long, they are broken in +// multiple lines but no parens are added.
- {a ? ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - ) : ( - "c" - )} + {a + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : "c"}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. The consequent is long enough to break the line, but -// because the alternate is null, only the consequent is wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the consequent is very long, they are broken in +// multiple lines but no parens are added.
- {a ? ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - ) : null} + {a + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : null}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. Because the alternate is long enough to break the -// line, both its consequent and alternate break out and are wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the alternate is very long, they are broken in +// multiple lines but no parens are added.
- {a ? ( - "b" - ) : ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - )} + {a + ? "b" + : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. The alternate is long enough to break the line, but -// because the consequent is null, only the alternate is wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the alternate is very long, they are broken in +// multiple lines but no parens are added.
- {a ? null : ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - )} + {a + ? null + : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. Because the test is long enough to break the -// line, both its consequent and alternate break out and are wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the test is very long, they are broken in +// multiple lines but no parens are added.
- {johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa ? ( - "b" - ) : ( - "c" - )} + {johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + ? "b" + : "c"}
; // This ConditionalExpression prints in JSX mode because its test is a @@ -352,17 +335,14 @@ jsxModeFromElementBreaking ? ( // non-breaking.
{a ? "a" : b ? "b" : "c"}
; -// This chain of ConditionalExpressions prints in JSX mode because the parent of -// the outermost ConditionalExpression is a JSXExpressionContainer. It is -// breaking. +// This chain of ConditionalExpressions prints in normal mode even though its parent is a +// JSXExpressionContainer. It is breaking.
- {a ? ( - "a" - ) : b ? ( - "b" - ) : ( - thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo - )} + {a + ? "a" + : b + ? "b" + : thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo}
; // This chain of ConditionalExpressions prints in JSX mode because there is a @@ -405,6 +385,20 @@ cable ? ( "dunno" ); +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is breaking; notice the consequents +// and alternates in the entire chain get wrapped in parens. +
+ {properties.length > 1 || + (properties.length === 1 && properties[0].apps.size > 1) ? ( + draggingApp == null || newPropertyName == null ? ( + + ) : ( + + ) + ) : null} +
; + `; exports[`expression.js 1`] = ` diff --git a/tests/jsx/conditional-expression.js b/tests/jsx/conditional-expression.js index 1ca836cd..4ba59739 100644 --- a/tests/jsx/conditional-expression.js +++ b/tests/jsx/conditional-expression.js @@ -17,84 +17,70 @@ // // test ? consequent : alternate; // -// We print a conditional expression in JSX mode if any of the following are -// true: -// * Its parent is a JSXExpressionContainer -// * Its test, consequent, or alternate are JSXElements -// * It is in a chain with other ConditionalExpressions, and the outermost -// one's parent is a JSXExpressionContainer -// * It is in a chain with other ConditionalExpressions, and any of the -// tests, consequents, or alternates of any of the ConditionalExpressions in -// the chain are JSXElements. +// We only print a conditional expression in JSX mode if its test, +// consequent, or alternate are JSXElements. // Otherwise, we print in normal mode. -// This ConditionalExpression does not meet any of the other criteria for -// printing in JSX mode, so it prints in normal mode. The line does not break. +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// The line does not break. normalModeNonBreaking ? "a" : "b"; -// This ConditionalExpression does not meet any of the criteria to print in JSX -// mode, so it prints in normal mode. Its consequent is very long, so it breaks -// out to multiple lines. +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// Its consequent is very long, so it breaks out to multiple lines. normalModeBreaking ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa : "c"; -// This ConditionalExpression prints in JSX mode because its parent is a +// This ConditionalExpression prints in normal mode even though its parent is a // JSXExpressionContainer. The line does not break, so it does not contain // parens.
{a ? "b" : "c"}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. Because the consequent is long enough to break the -// line, both its consequent and alternate break out and are wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the consequent is very long, they are broken in +// multiple lines but no parens are added.
- {a ? ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - ) : ( - "c" - )} + {a + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : "c"}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. The consequent is long enough to break the line, but -// because the alternate is null, only the consequent is wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the consequent is very long, they are broken in +// multiple lines but no parens are added.
- {a ? ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - ) : null} + {a + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : null}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. Because the alternate is long enough to break the -// line, both its consequent and alternate break out and are wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the alternate is very long, they are broken in +// multiple lines but no parens are added.
- {a ? ( - "b" - ) : ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - )} + {a + ? "b" + : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. The alternate is long enough to break the line, but -// because the consequent is null, only the alternate is wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the alternate is very long, they are broken in +// multiple lines but no parens are added.
- {a ? null : ( - johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - )} + {a + ? null + : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa}
; -// This ConditionalExpression prints in JSX mode because its parent is a -// JSXExpressionContainer. Because the test is long enough to break the -// line, both its consequent and alternate break out and are wrapped in parens. +// This ConditionalExpression prints in normal mode even though its parent is a +// JSXExpressionContainer. Because the test is very long, they are broken in +// multiple lines but no parens are added.
- {johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa ? ( - "b" - ) : ( - "c" - )} + {johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + ? "b" + : "c"}
; // This ConditionalExpression prints in JSX mode because its test is a @@ -150,17 +136,14 @@ jsxModeFromElementBreaking ? ( {a ? "a" : b ? "b" : "c"} ; -// This chain of ConditionalExpressions prints in JSX mode because the parent of -// the outermost ConditionalExpression is a JSXExpressionContainer. It is -// breaking. +// This chain of ConditionalExpressions prints in normal mode even though its parent is a +// JSXExpressionContainer. It is breaking.
- {a ? ( - "a" - ) : b ? ( - "b" - ) : ( - thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo - )} + {a + ? "a" + : b + ? "b" + : thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo}
; // This chain of ConditionalExpressions prints in JSX mode because there is a @@ -194,3 +177,17 @@ cable ? ( ) : affairs ? ( "network" ) : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is breaking; notice the consequents +// and alternates in the entire chain get wrapped in parens. +
+ {properties.length > 1 || + (properties.length === 1 && properties[0].apps.size > 1) ? ( + draggingApp == null || newPropertyName == null ? ( + + ) : ( + + ) + ) : null} +
; From f964be5f8ab67cb68706ab667adbab98cc7cad79 Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Thu, 7 Sep 2017 23:47:13 -0300 Subject: [PATCH 02/19] Remove unnecessary tests --- tests/jsx/__snapshots__/jsfmt.spec.js.snap | 122 --------------------- tests/jsx/conditional-expression.js | 62 ----------- 2 files changed, 184 deletions(-) diff --git a/tests/jsx/__snapshots__/jsfmt.spec.js.snap b/tests/jsx/__snapshots__/jsfmt.spec.js.snap index 076b2cfc..f3113b4b 100644 --- a/tests/jsx/__snapshots__/jsfmt.spec.js.snap +++ b/tests/jsx/__snapshots__/jsfmt.spec.js.snap @@ -34,58 +34,6 @@ normalModeBreaking ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa : "c"; -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. The line does not break, so it does not contain -// parens. -
- {a ? "b" : "c"} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the consequent is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - : "c"} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the consequent is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - : null} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the alternate is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? "b" - : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the alternate is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? null - : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the test is very long, they are broken in -// multiple lines but no parens are added. -
- {johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - ? "b" - : "c"} -
; - // This ConditionalExpression prints in JSX mode because its test is a // JSXElement. It is non-breaking. // Note: I have never, ever seen someone use a JSXElement as the test in a @@ -139,16 +87,6 @@ jsxModeFromElementBreaking ? ( {a ? "a" : b ? "b" : "c"} ; -// This chain of ConditionalExpressions prints in normal mode even though its parent is a -// JSXExpressionContainer. It is breaking. -
- {a - ? "a" - : b - ? "b" - : thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo} -
; - // This chain of ConditionalExpressions prints in JSX mode because there is a // JSX element somewhere in the chain. It is non-breaking. cable ? "satellite" : public ? "affairs" : network ? : "dunno"; @@ -228,56 +166,6 @@ normalModeBreaking ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa : "c"; -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. The line does not break, so it does not contain -// parens. -
{a ? "b" : "c"}
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the consequent is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - : "c"} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the consequent is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - : null} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the alternate is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? "b" - : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the alternate is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? null - : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the test is very long, they are broken in -// multiple lines but no parens are added. -
- {johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - ? "b" - : "c"} -
; - // This ConditionalExpression prints in JSX mode because its test is a // JSXElement. It is non-breaking. // Note: I have never, ever seen someone use a JSXElement as the test in a @@ -335,16 +223,6 @@ jsxModeFromElementBreaking ? ( // non-breaking.
{a ? "a" : b ? "b" : "c"}
; -// This chain of ConditionalExpressions prints in normal mode even though its parent is a -// JSXExpressionContainer. It is breaking. -
- {a - ? "a" - : b - ? "b" - : thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo} -
; - // This chain of ConditionalExpressions prints in JSX mode because there is a // JSX element somewhere in the chain. It is non-breaking. cable ? "satellite" : public ? "affairs" : network ? : "dunno"; diff --git a/tests/jsx/conditional-expression.js b/tests/jsx/conditional-expression.js index 4ba59739..5266662a 100644 --- a/tests/jsx/conditional-expression.js +++ b/tests/jsx/conditional-expression.js @@ -31,58 +31,6 @@ normalModeBreaking ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa : "c"; -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. The line does not break, so it does not contain -// parens. -
- {a ? "b" : "c"} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the consequent is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - : "c"} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the consequent is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - : null} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the alternate is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? "b" - : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the alternate is very long, they are broken in -// multiple lines but no parens are added. -
- {a - ? null - : johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa} -
; - -// This ConditionalExpression prints in normal mode even though its parent is a -// JSXExpressionContainer. Because the test is very long, they are broken in -// multiple lines but no parens are added. -
- {johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa - ? "b" - : "c"} -
; - // This ConditionalExpression prints in JSX mode because its test is a // JSXElement. It is non-breaking. // Note: I have never, ever seen someone use a JSXElement as the test in a @@ -136,16 +84,6 @@ jsxModeFromElementBreaking ? ( {a ? "a" : b ? "b" : "c"} ; -// This chain of ConditionalExpressions prints in normal mode even though its parent is a -// JSXExpressionContainer. It is breaking. -
- {a - ? "a" - : b - ? "b" - : thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo} -
; - // This chain of ConditionalExpressions prints in JSX mode because there is a // JSX element somewhere in the chain. It is non-breaking. cable ? "satellite" : public ? "affairs" : network ? : "dunno"; From 2c37697f82d3e4f36e831c2b1153b4ad1b68a42d Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Thu, 7 Sep 2017 15:28:12 -0300 Subject: [PATCH 03/19] Fix chained logical expressions with objects/array/etc inlined --- src/printer.js | 18 +-- .../__snapshots__/jsfmt.spec.js.snap | 114 ++++++++++++++++++ tests/binary-expressions/arrow.js | 8 ++ .../binary-expressions/inline-object-array.js | 30 +++++ tests/binary-expressions/jsx_parent.js | 15 +++ tests/jsx/__snapshots__/jsfmt.spec.js.snap | 25 ++++ tests/jsx/logical-expression.js | 8 ++ 7 files changed, 211 insertions(+), 7 deletions(-) diff --git a/src/printer.js b/src/printer.js index 403b0ebb..878a48c7 100644 --- a/src/printer.js +++ b/src/printer.js @@ -339,18 +339,22 @@ function genericPrintNoParens(path, options, print, args) { } // Avoid indenting sub-expressions in assignment/return/etc statements. - if ( - parent.type === "AssignmentExpression" || - parent.type === "VariableDeclarator" || - shouldInlineLogicalExpression(n) || + const willBreakRegardless = parent.type === "ReturnStatement" || (parent.type === "JSXExpressionContainer" && parentParent.type === "JSXAttribute") || (n === parent.body && parent.type === "ArrowFunctionExpression") || (n !== parent.body && parent.type === "ForStatement") || - parent.type === "ObjectProperty" || - parent.type === "Property" || - parent.type === "ConditionalExpression" + parent.type === "ConditionalExpression"; + + if ( + willBreakRegardless || + (shouldInlineLogicalExpression(n) && n.left.type !== n.type) || + (!shouldInlineLogicalExpression(n) && + (parent.type === "AssignmentExpression" || + parent.type === "VariableDeclarator" || + parent.type === "ObjectProperty" || + parent.type === "Property")) ) { return group(concat(parts)); } diff --git a/tests/binary-expressions/__snapshots__/jsfmt.spec.js.snap b/tests/binary-expressions/__snapshots__/jsfmt.spec.js.snap index dcb11e3f..fd0d05c8 100644 --- a/tests/binary-expressions/__snapshots__/jsfmt.spec.js.snap +++ b/tests/binary-expressions/__snapshots__/jsfmt.spec.js.snap @@ -6,6 +6,14 @@ function f() { entity => entity && entity.isInstallAvailable() && !entity.isQueue() && entity.isDisabled() ) } + +function f() { + const appEntitys = getAppEntitys(loadObject).map( + entity => entity && entity.isInstallAvailable() && !entity.isQueue() && entity.isDisabled() && { + id: entity.id + } + ) +} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ function f() { const appEntitys = getAppEntitys(loadObject).filter( @@ -17,6 +25,18 @@ function f() { ); } +function f() { + const appEntitys = getAppEntitys(loadObject).map( + entity => + entity && + entity.isInstallAvailable() && + !entity.isQueue() && + entity.isDisabled() && { + id: entity.id + } + ); +} + `; exports[`bitwise-flags.js 1`] = ` @@ -134,12 +154,42 @@ prevState = prevState || { selectedCatalog: null, }; +prevState = prevState || + defaultState || { + catalogs: [], + loadState: LOADED, + opened: false, + searchQuery: '', + selectedCatalog: null, + }; + this.steps = steps || [ { name: 'mock-module', path: '/nux/mock-module', }, ]; + +const create = () => { + const result = doSomething(); + return ( + shouldReturn && + result.ok && { + status: "ok", + createdAt: result.createdAt, + updatedAt: result.updatedAt + } + ); +} + +const obj = { + state: shouldHaveState && + stateIsOK && { + loadState: LOADED, + opened: false + }, + loaded: true +} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ prevState = prevState || { catalogs: [], @@ -149,6 +199,15 @@ prevState = prevState || { selectedCatalog: null }; +prevState = prevState || + defaultState || { + catalogs: [], + loadState: LOADED, + opened: false, + searchQuery: "", + selectedCatalog: null + }; + this.steps = steps || [ { name: "mock-module", @@ -156,6 +215,27 @@ this.steps = steps || [ } ]; +const create = () => { + const result = doSomething(); + return ( + shouldReturn && + result.ok && { + status: "ok", + createdAt: result.createdAt, + updatedAt: result.updatedAt + } + ); +}; + +const obj = { + state: shouldHaveState && + stateIsOK && { + loadState: LOADED, + opened: false + }, + loaded: true +}; + `; exports[`jsx_parent.js 1`] = ` @@ -172,6 +252,21 @@ exports[`jsx_parent.js 1`] = ` diffUpdateMessageInput != null && this.state.isUpdateMessageEmpty} ; + +
; + +
+ {!isJellyfishEnabled && + diffUpdateMessageInput != null &&
Text
} +
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; +
; + +
+ {!isJellyfishEnabled && + diffUpdateMessageInput != null && ( +
+ Text +
+ )} +
; + `; exports[`math.js 1`] = ` diff --git a/tests/binary-expressions/arrow.js b/tests/binary-expressions/arrow.js index 2fbafa9f..a5933903 100644 --- a/tests/binary-expressions/arrow.js +++ b/tests/binary-expressions/arrow.js @@ -3,3 +3,11 @@ function f() { entity => entity && entity.isInstallAvailable() && !entity.isQueue() && entity.isDisabled() ) } + +function f() { + const appEntitys = getAppEntitys(loadObject).map( + entity => entity && entity.isInstallAvailable() && !entity.isQueue() && entity.isDisabled() && { + id: entity.id + } + ) +} diff --git a/tests/binary-expressions/inline-object-array.js b/tests/binary-expressions/inline-object-array.js index 76d47eab..4aa40348 100644 --- a/tests/binary-expressions/inline-object-array.js +++ b/tests/binary-expressions/inline-object-array.js @@ -6,9 +6,39 @@ prevState = prevState || { selectedCatalog: null, }; +prevState = prevState || + defaultState || { + catalogs: [], + loadState: LOADED, + opened: false, + searchQuery: '', + selectedCatalog: null, + }; + this.steps = steps || [ { name: 'mock-module', path: '/nux/mock-module', }, ]; + +const create = () => { + const result = doSomething(); + return ( + shouldReturn && + result.ok && { + status: "ok", + createdAt: result.createdAt, + updatedAt: result.updatedAt + } + ); +} + +const obj = { + state: shouldHaveState && + stateIsOK && { + loadState: LOADED, + opened: false + }, + loaded: true +} diff --git a/tests/binary-expressions/jsx_parent.js b/tests/binary-expressions/jsx_parent.js index 0339b514..9340fcf6 100644 --- a/tests/binary-expressions/jsx_parent.js +++ b/tests/binary-expressions/jsx_parent.js @@ -11,3 +11,18 @@ diffUpdateMessageInput != null && this.state.isUpdateMessageEmpty}
; + +
; + +
+ {!isJellyfishEnabled && + diffUpdateMessageInput != null &&
Text
} +
; diff --git a/tests/jsx/__snapshots__/jsfmt.spec.js.snap b/tests/jsx/__snapshots__/jsfmt.spec.js.snap index f3113b4b..49b42843 100644 --- a/tests/jsx/__snapshots__/jsfmt.spec.js.snap +++ b/tests/jsx/__snapshots__/jsfmt.spec.js.snap @@ -528,6 +528,14 @@ exports[`logical-expression.js 1`] = ` {a && }
; +
+ {a && make this text just so long enough to break this to the next line} +
; + +
+ {a && b && make this text just so long enough to break this to the next line} +
; +
{a &&
@@ -544,6 +552,23 @@ exports[`logical-expression.js 1`] = `
{a && }
; +
+ {a && ( + + make this text just so long enough to break this to the next line + + )} +
; + +
+ {a && + b && ( + + make this text just so long enough to break this to the next line + + )} +
; +
{a && ( diff --git a/tests/jsx/logical-expression.js b/tests/jsx/logical-expression.js index 269a2e2d..948f1cfa 100644 --- a/tests/jsx/logical-expression.js +++ b/tests/jsx/logical-expression.js @@ -14,6 +14,14 @@ {a && }
; +
+ {a && make this text just so long enough to break this to the next line} +
; + +
+ {a && b && make this text just so long enough to break this to the next line} +
; +
{a &&
From 3cfee9c976bfe9dbf9ebae4a0afe7c6e677b91ab Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Fri, 8 Sep 2017 00:25:54 -0300 Subject: [PATCH 04/19] Clarification of code --- src/printer.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/printer.js b/src/printer.js index 878a48c7..f809cdb3 100644 --- a/src/printer.js +++ b/src/printer.js @@ -338,8 +338,9 @@ function genericPrintNoParens(path, options, print, args) { ); } - // Avoid indenting sub-expressions in assignment/return/etc statements. - const willBreakRegardless = + // Avoid indenting sub-expressions in some cases where the first sub-expression is already + // idented accordingly. We should ident sub-expressions where the first case isn't idented. + const shouldNotIdent = parent.type === "ReturnStatement" || (parent.type === "JSXExpressionContainer" && parentParent.type === "JSXAttribute") || @@ -347,14 +348,18 @@ function genericPrintNoParens(path, options, print, args) { (n !== parent.body && parent.type === "ForStatement") || parent.type === "ConditionalExpression"; + const shouldIdentIfInlining = + parent.type === "AssignmentExpression" || + parent.type === "VariableDeclarator" || + parent.type === "ObjectProperty" || + parent.type === "Property"; + + const logicalSubExpressionExists = n.left.type === "LogicalExpression"; + if ( - willBreakRegardless || + shouldNotIdent || (shouldInlineLogicalExpression(n) && n.left.type !== n.type) || - (!shouldInlineLogicalExpression(n) && - (parent.type === "AssignmentExpression" || - parent.type === "VariableDeclarator" || - parent.type === "ObjectProperty" || - parent.type === "Property")) + (!shouldInlineLogicalExpression(n) && shouldIdentIfInlining) ) { return group(concat(parts)); } From 85f135136679dc3b8f5b9c107866546071b4644a Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Fri, 8 Sep 2017 00:39:37 -0300 Subject: [PATCH 05/19] Fix unused var --- src/printer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/printer.js b/src/printer.js index f809cdb3..420e8726 100644 --- a/src/printer.js +++ b/src/printer.js @@ -354,11 +354,11 @@ function genericPrintNoParens(path, options, print, args) { parent.type === "ObjectProperty" || parent.type === "Property"; - const logicalSubExpressionExists = n.left.type === "LogicalExpression"; + const logicalSubExpression = n.left.type === "LogicalExpression"; if ( shouldNotIdent || - (shouldInlineLogicalExpression(n) && n.left.type !== n.type) || + (shouldInlineLogicalExpression(n) && !logicalSubExpression) || (!shouldInlineLogicalExpression(n) && shouldIdentIfInlining) ) { return group(concat(parts)); From 302de60bdc31f5700d0bd3f73fc7ae19190262c9 Mon Sep 17 00:00:00 2001 From: jackyho112 Date: Fri, 8 Sep 2017 10:12:10 -0700 Subject: [PATCH 06/19] Fix comment style when placed after if statement test (#2675) * Fix comment style when placed after the test of an if statement * Add tests * Do a bit of refactoring * Fix lint errors * Handle skipping comments * Account for multiple-line comments * Add more tests * Change function name * Add more tests * Refactor * Add some comments * Do away with getPreviousNonSpaceNonCommentCharacter * Improve comment and code on handling if statement comments * Refactor * Fix a bug --- src/comments.js | 16 ++- .../comments/__snapshots__/jsfmt.spec.js.snap | 97 ++++++++++++++++++- tests/comments/if.js | 41 +++++++- tests/if/__snapshots__/jsfmt.spec.js.snap | 42 ++++++++ tests/if/if_comments.js | 18 ++++ 5 files changed, 203 insertions(+), 11 deletions(-) diff --git a/src/comments.js b/src/comments.js index 1307bf12..b5e0675f 100644 --- a/src/comments.js +++ b/src/comments.js @@ -466,12 +466,12 @@ function handleIfStatementComments( } // We unfortunately have no way using the AST or location of nodes to know - // if the comment is positioned before or after the condition parenthesis: + // if the comment is positioned before the condition parenthesis: // if (a /* comment */) {} - // if (a) /* comment */ {} // The only workaround I found is to look at the next character to see if // it is a ). - if (getNextNonSpaceNonCommentCharacter(text, comment) === ")") { + const nextCharacter = getNextNonSpaceNonCommentCharacter(text, comment); + if (nextCharacter === ")") { addTrailingComment(precedingNode, comment); return true; } @@ -486,6 +486,16 @@ function handleIfStatementComments( return true; } + // For comments positioned after the condition parenthesis in an if statement + // before the consequent with or without brackets on, such as + // if (a) /* comment */ {} or if (a) /* comment */ true, + // we look at the next character to see if it is a { or if the following node + // is the consequent for the if statement + if (nextCharacter === "{" || enclosingNode.consequent === followingNode) { + addLeadingComment(followingNode, comment); + return true; + } + return false; } diff --git a/tests/comments/__snapshots__/jsfmt.spec.js.snap b/tests/comments/__snapshots__/jsfmt.spec.js.snap index 064265e3..7fab1166 100644 --- a/tests/comments/__snapshots__/jsfmt.spec.js.snap +++ b/tests/comments/__snapshots__/jsfmt.spec.js.snap @@ -328,10 +328,45 @@ else if (4) { else { } -if (1) -{} +if (5) // comment +true + +if (6) // comment +{true} +else if (7) // comment +true else // comment -{} +{true} + +if (8) // comment +// comment +{true} +else if (9) // comment +// comment +true +else // comment +// comment +{true} + +if (10) /* comment */ // comment +{true} +else if (11) /* comment */ +true +else if (12) // comment /* comment */ // comment +true +else if (13) /* comment */ /* comment */ // comment +true +else /* comment */ +{true} + +if (14) // comment +/* comment */ +// comment +{true} +else if (15) // comment +/* comment */ +/* comment */ // comment +true ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (1) { // comment @@ -352,11 +387,63 @@ else if (4) { // comment } -if (1) { -} else { +if (5) // comment + true; + +if (6) { + // comment + true; +} else if (7) + // comment + true; +else { + // comment + true; } +if (8) { + // comment + // comment + true; +} else if (9) + // comment + // comment + true; +else { + // comment + // comment + true; +} + +if (10) { + /* comment */ // comment + true; +} else if (11) + /* comment */ + true; +else if (12) + // comment /* comment */ // comment + true; +else if (13) + /* comment */ /* comment */ // comment + true; +else { + /* comment */ + true; +} + +if (14) { + // comment + /* comment */ + // comment + true; +} else if (15) + // comment + /* comment */ + /* comment */ // comment + true; + `; exports[`issues.js 1`] = ` diff --git a/tests/comments/if.js b/tests/comments/if.js index 26f895ba..ff4043ec 100644 --- a/tests/comments/if.js +++ b/tests/comments/if.js @@ -20,7 +20,42 @@ else if (4) { else { } -if (1) -{} +if (5) // comment +true + +if (6) // comment +{true} +else if (7) // comment +true else // comment -{} +{true} + +if (8) // comment +// comment +{true} +else if (9) // comment +// comment +true +else // comment +// comment +{true} + +if (10) /* comment */ // comment +{true} +else if (11) /* comment */ +true +else if (12) // comment /* comment */ // comment +true +else if (13) /* comment */ /* comment */ // comment +true +else /* comment */ +{true} + +if (14) // comment +/* comment */ +// comment +{true} +else if (15) // comment +/* comment */ +/* comment */ // comment +true diff --git a/tests/if/__snapshots__/jsfmt.spec.js.snap b/tests/if/__snapshots__/jsfmt.spec.js.snap index 7707ed25..50598c4e 100644 --- a/tests/if/__snapshots__/jsfmt.spec.js.snap +++ b/tests/if/__snapshots__/jsfmt.spec.js.snap @@ -54,6 +54,24 @@ async function f() { } } +async function f() { + if (untrackedChoice === 0) /* Cancel */ + null; + else if (untrackedChoice === 1) /* Add */ + shouldAmend = true; + else if (untrackedChoice === 2) /* Allow Untracked */ + allowUntracked = true; +} + +async function f() { + if (untrackedChoice === 0) /* Cancel */ // Cancel + null; + else if (untrackedChoice === 1) /* Add */ // Add + shouldAmend = true; + else if (untrackedChoice === 2) /* Allow Untracked */ // Allow Untracked + allowUntracked = true; +} + async function f() { if (untrackedChoice === 0) /* Cancel */ { @@ -92,6 +110,30 @@ async function f() { } } +async function f() { + if (untrackedChoice === 0) + /* Cancel */ + null; + else if (untrackedChoice === 1) + /* Add */ + shouldAmend = true; + else if (untrackedChoice === 2) + /* Allow Untracked */ + allowUntracked = true; +} + +async function f() { + if (untrackedChoice === 0) + /* Cancel */ // Cancel + null; + else if (untrackedChoice === 1) + /* Add */ // Add + shouldAmend = true; + else if (untrackedChoice === 2) + /* Allow Untracked */ // Allow Untracked + allowUntracked = true; +} + async function f() { if (untrackedChoice === 0) { /* Cancel */ return null; diff --git a/tests/if/if_comments.js b/tests/if/if_comments.js index 2b355299..2295fe83 100644 --- a/tests/if/if_comments.js +++ b/tests/if/if_comments.js @@ -9,6 +9,24 @@ async function f() { } } +async function f() { + if (untrackedChoice === 0) /* Cancel */ + null; + else if (untrackedChoice === 1) /* Add */ + shouldAmend = true; + else if (untrackedChoice === 2) /* Allow Untracked */ + allowUntracked = true; +} + +async function f() { + if (untrackedChoice === 0) /* Cancel */ // Cancel + null; + else if (untrackedChoice === 1) /* Add */ // Add + shouldAmend = true; + else if (untrackedChoice === 2) /* Allow Untracked */ // Allow Untracked + allowUntracked = true; +} + async function f() { if (untrackedChoice === 0) /* Cancel */ { From 3db840258be5a793eddb4caf7c2e7d8a3f34b8ab Mon Sep 17 00:00:00 2001 From: Ika Date: Sat, 9 Sep 2017 21:39:11 +0800 Subject: [PATCH 07/19] chore(build): update ISSUE_TEMPLATE.md before publish (#2776) --- scripts/build/build.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/build/build.js b/scripts/build/build.js index a0fc77ce..0be20271 100755 --- a/scripts/build/build.js +++ b/scripts/build/build.js @@ -98,6 +98,14 @@ shell.sed( "dist/bin/prettier.js" ); +shell.echo("Update ISSUE_TEMPLATE.md"); +shell.sed( + "-i", + /(?!Prettier Version.*?)\d+\.\d+\.\d+/, + pkg.version, + ".github/ISSUE_TEMPLATE.md" +); + shell.echo("Create prettier-version.js"); pipe(`prettierVersion = "${pkg.version}";\n`).to(`${docs}/prettier-version.js`); From bba7dcf498854853b44ec6a78a4c53b263f4236d Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Sun, 10 Sep 2017 02:18:40 -0300 Subject: [PATCH 08/19] Fix break on conditional expressions inside return Fixes #2777 Since we can't break after `return` and don't add `()` around ConditionalExpressions' tests, we end up with some weird indentation when breaking. --- src/printer.js | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 40 +++++++++++++++++++ tests/binary-expressions/return.js | 15 +++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/binary-expressions/return.js diff --git a/src/printer.js b/src/printer.js index 420e8726..6b333463 100644 --- a/src/printer.js +++ b/src/printer.js @@ -346,7 +346,8 @@ function genericPrintNoParens(path, options, print, args) { parentParent.type === "JSXAttribute") || (n === parent.body && parent.type === "ArrowFunctionExpression") || (n !== parent.body && parent.type === "ForStatement") || - parent.type === "ConditionalExpression"; + (parent.type === "ConditionalExpression" && + parentParent.type !== "ReturnStatement"); const shouldIdentIfInlining = parent.type === "AssignmentExpression" || diff --git a/tests/binary-expressions/__snapshots__/jsfmt.spec.js.snap b/tests/binary-expressions/__snapshots__/jsfmt.spec.js.snap index fd0d05c8..5c4ba464 100644 --- a/tests/binary-expressions/__snapshots__/jsfmt.spec.js.snap +++ b/tests/binary-expressions/__snapshots__/jsfmt.spec.js.snap @@ -352,6 +352,46 @@ x & (y >> z); `; +exports[`return.js 1`] = ` +function foo() { + return this.hasPlugin("dynamicImports") && this.lookahead().type === tt.parenLeft.right; +} + +function foo() { + return this.hasPlugin("dynamicImports") && this.lookahead().type === tt.parenLeft.right + ? true + : false; +} + +function foo() { + return this.calculate().compute().first.numberOfThings > this.calculate().compute().last.numberOfThings + ? true + : false; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function foo() { + return ( + this.hasPlugin("dynamicImports") && + this.lookahead().type === tt.parenLeft.right + ); +} + +function foo() { + return this.hasPlugin("dynamicImports") && + this.lookahead().type === tt.parenLeft.right + ? true + : false; +} + +function foo() { + return this.calculate().compute().first.numberOfThings > + this.calculate().compute().last.numberOfThings + ? true + : false; +} + +`; + exports[`short-right.js 1`] = ` this._cumulativeHeights && Math.abs( diff --git a/tests/binary-expressions/return.js b/tests/binary-expressions/return.js new file mode 100644 index 00000000..44ba5b06 --- /dev/null +++ b/tests/binary-expressions/return.js @@ -0,0 +1,15 @@ +function foo() { + return this.hasPlugin("dynamicImports") && this.lookahead().type === tt.parenLeft.right; +} + +function foo() { + return this.hasPlugin("dynamicImports") && this.lookahead().type === tt.parenLeft.right + ? true + : false; +} + +function foo() { + return this.calculate().compute().first.numberOfThings > this.calculate().compute().last.numberOfThings + ? true + : false; +} From 955a2c1472e7748c598e3ea08cad4f2d8a81d2a0 Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Sun, 10 Sep 2017 12:34:55 -0300 Subject: [PATCH 09/19] Keep conditional expressions in one line on method chains (#2784) Fixes #2775. This commit will make conditional expressions to match the behavior of logical expression in method chains: ```js (a ? b : c).map() // if the conditional fits in oneline (a ? b : c) .map() // if the conditional doesn't fit (a ? b : c) .map() ``` --- src/printer.js | 4 +++- .../__snapshots__/jsfmt.spec.js.snap | 21 +++++++++++++++++++ tests/method-chain/conditional.js | 9 ++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/method-chain/conditional.js diff --git a/src/printer.js b/src/printer.js index 6b333463..0d16304b 100644 --- a/src/printer.js +++ b/src/printer.js @@ -3705,7 +3705,9 @@ function printMemberChain(path, options, print) { groups.length <= cutoff && !hasComment && // (a || b).map() should be break before .map() instead of || - groups[0][0].node.type !== "LogicalExpression" + groups[0][0].node.type !== "LogicalExpression" && + // (a ? b : c).map() should be break before .map() instead of ? + groups[0][0].node.type !== "ConditionalExpression" ) { return group(oneLine); } diff --git a/tests/method-chain/__snapshots__/jsfmt.spec.js.snap b/tests/method-chain/__snapshots__/jsfmt.spec.js.snap index da56e5a0..a60288c2 100644 --- a/tests/method-chain/__snapshots__/jsfmt.spec.js.snap +++ b/tests/method-chain/__snapshots__/jsfmt.spec.js.snap @@ -416,6 +416,27 @@ exports[`computed-merge.js 1`] = ` `; +exports[`conditional.js 1`] = ` +(valid + ? helper.responseBody(this.currentUser) + : helper.response(401)) +.map(res => res.json()); + +(valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(defaultUser)) +.map(res => res.json()); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(valid ? helper.responseBody(this.currentUser) : helper.response(401)) + .map(res => res.json()); + +(valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(defaultUser)) + .map(res => res.json()); + +`; + exports[`first_long.js 1`] = ` export default function theFunction(action$, store) { return action$.ofType(THE_ACTION).switchMap(action => Observable diff --git a/tests/method-chain/conditional.js b/tests/method-chain/conditional.js new file mode 100644 index 00000000..5d3299d8 --- /dev/null +++ b/tests/method-chain/conditional.js @@ -0,0 +1,9 @@ +(valid + ? helper.responseBody(this.currentUser) + : helper.response(401)) +.map(res => res.json()); + +(valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(defaultUser)) +.map(res => res.json()); From 8b02f702d51759df453ee4e77ded34d8b89aff7e Mon Sep 17 00:00:00 2001 From: Ika Date: Sun, 10 Sep 2017 23:37:07 +0800 Subject: [PATCH 10/19] fix(build): update ISSUE_TEMPLATE version regex to work as intended (#2785) --- scripts/build/build.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build/build.js b/scripts/build/build.js index 0be20271..106f3921 100755 --- a/scripts/build/build.js +++ b/scripts/build/build.js @@ -101,8 +101,8 @@ shell.sed( shell.echo("Update ISSUE_TEMPLATE.md"); shell.sed( "-i", - /(?!Prettier Version.*?)\d+\.\d+\.\d+/, - pkg.version, + /(Prettier Version.+?)\d+\.\d+\.\d+/, + `$1${pkg.version}`, ".github/ISSUE_TEMPLATE.md" ); From df5482008ef97ce9172557e1ea200997aaeb3f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=95=BF=E5=A4=A9=E4=B9=8B=E4=BA=91?= Date: Mon, 11 Sep 2017 00:21:56 +0800 Subject: [PATCH 11/19] fix(prettierignore): support absolute filename (#2783) --- src/cli-util.js | 9 ++++++++- .../__snapshots__/ignore-absolute-path.js.snap | 6 ++++++ .../__tests__/ignore-absolute-path.js | 16 ++++++++++++++++ .../cli/ignore-absolute-path/.prettierignore | 2 ++ .../depth1/ignored/module.js | 1 + .../cli/ignore-absolute-path/ignored/module.js | 1 + .../cli/ignore-absolute-path/regular-module.js | 1 + 7 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tests_integration/__tests__/__snapshots__/ignore-absolute-path.js.snap create mode 100644 tests_integration/__tests__/ignore-absolute-path.js create mode 100644 tests_integration/cli/ignore-absolute-path/.prettierignore create mode 100644 tests_integration/cli/ignore-absolute-path/depth1/ignored/module.js create mode 100644 tests_integration/cli/ignore-absolute-path/ignored/module.js create mode 100644 tests_integration/cli/ignore-absolute-path/regular-module.js diff --git a/src/cli-util.js b/src/cli-util.js index 201d1617..3fd50001 100644 --- a/src/cli-util.js +++ b/src/cli-util.js @@ -292,7 +292,14 @@ function eachFilename(argv, patterns, callback) { } try { - const filePaths = globby.sync(patterns, { dot: true }); + const filePaths = globby + .sync(patterns, { dot: true }) + .map( + filePath => + path.isAbsolute(filePath) + ? path.relative(process.cwd(), filePath) + : filePath + ); if (filePaths.length === 0) { console.error(`No matching files. Patterns tried: ${patterns.join(" ")}`); process.exitCode = 2; diff --git a/tests_integration/__tests__/__snapshots__/ignore-absolute-path.js.snap b/tests_integration/__tests__/__snapshots__/ignore-absolute-path.js.snap new file mode 100644 index 00000000..a396d0f8 --- /dev/null +++ b/tests_integration/__tests__/__snapshots__/ignore-absolute-path.js.snap @@ -0,0 +1,6 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`support absolute filename 1`] = ` +"regular-module.js +" +`; diff --git a/tests_integration/__tests__/ignore-absolute-path.js b/tests_integration/__tests__/ignore-absolute-path.js new file mode 100644 index 00000000..8e46de3f --- /dev/null +++ b/tests_integration/__tests__/ignore-absolute-path.js @@ -0,0 +1,16 @@ +"use strict"; + +const path = require("path"); +const runPrettier = require("../runPrettier"); + +test("support absolute filename", () => { + const result = runPrettier("cli/ignore-absolute-path", [ + path.resolve(__dirname, "../cli/ignore-absolute-path/ignored/module.js"), + path.resolve(__dirname, "../cli/ignore-absolute-path/depth1/ignored/*.js"), + path.resolve(__dirname, "../cli/ignore-absolute-path/regular-module.js"), + "-l" + ]); + + expect(result.stdout).toMatchSnapshot(); + expect(result.status).toEqual(1); +}); diff --git a/tests_integration/cli/ignore-absolute-path/.prettierignore b/tests_integration/cli/ignore-absolute-path/.prettierignore new file mode 100644 index 00000000..c51aa823 --- /dev/null +++ b/tests_integration/cli/ignore-absolute-path/.prettierignore @@ -0,0 +1,2 @@ +/ignored/ +depth1/ignored/ diff --git a/tests_integration/cli/ignore-absolute-path/depth1/ignored/module.js b/tests_integration/cli/ignore-absolute-path/depth1/ignored/module.js new file mode 100644 index 00000000..ad9a93a7 --- /dev/null +++ b/tests_integration/cli/ignore-absolute-path/depth1/ignored/module.js @@ -0,0 +1 @@ +'use strict'; diff --git a/tests_integration/cli/ignore-absolute-path/ignored/module.js b/tests_integration/cli/ignore-absolute-path/ignored/module.js new file mode 100644 index 00000000..ad9a93a7 --- /dev/null +++ b/tests_integration/cli/ignore-absolute-path/ignored/module.js @@ -0,0 +1 @@ +'use strict'; diff --git a/tests_integration/cli/ignore-absolute-path/regular-module.js b/tests_integration/cli/ignore-absolute-path/regular-module.js new file mode 100644 index 00000000..ad9a93a7 --- /dev/null +++ b/tests_integration/cli/ignore-absolute-path/regular-module.js @@ -0,0 +1 @@ +'use strict'; From bd78572b19f8b53d093d2fdd771fe46934e4f3ff Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Sun, 10 Sep 2017 16:09:21 -0300 Subject: [PATCH 12/19] Break closing paren of ConditionalExpression in member chains --- src/printer.js | 15 ++++-- tests/member/__snapshots__/jsfmt.spec.js.snap | 12 +++++ tests/member/conditional.js | 4 ++ .../__snapshots__/jsfmt.spec.js.snap | 54 ++++++++++++++++--- tests/method-chain/conditional.js | 22 ++++++-- 5 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 tests/member/conditional.js diff --git a/src/printer.js b/src/printer.js index 0d16304b..98a04641 100644 --- a/src/printer.js +++ b/src/printer.js @@ -1309,10 +1309,19 @@ function genericPrintNoParens(path, options, print, args) { ? parent === firstNonConditionalParent ? group(doc) : doc : group(doc); // Always group in normal mode. + // Break the closing paren to keep the chain right after it: + // (a + // ? b + // : c + // ).call() + const breakClosingParen = + !jsxMode && parent.type === "MemberExpression" && !parent.computed; + return maybeGroup( concat([ path.call(print, "test"), - forceNoIndent ? concat(parts) : indent(concat(parts)) + forceNoIndent ? concat(parts) : indent(concat(parts)), + breakClosingParen ? ifBreak(softline, "") : "" ]) ); } @@ -3705,9 +3714,7 @@ function printMemberChain(path, options, print) { groups.length <= cutoff && !hasComment && // (a || b).map() should be break before .map() instead of || - groups[0][0].node.type !== "LogicalExpression" && - // (a ? b : c).map() should be break before .map() instead of ? - groups[0][0].node.type !== "ConditionalExpression" + groups[0][0].node.type !== "LogicalExpression" ) { return group(oneLine); } diff --git a/tests/member/__snapshots__/jsfmt.spec.js.snap b/tests/member/__snapshots__/jsfmt.spec.js.snap index e2dfaec7..989d5315 100644 --- a/tests/member/__snapshots__/jsfmt.spec.js.snap +++ b/tests/member/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`conditional.js 1`] = ` +(valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(this.defaultUser)) +.prop; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(this.defaultUser)).prop; + +`; + exports[`expand.js 1`] = ` const veryVeryVeryVeryVeryVeryVeryLong = doc.expandedStates[doc.expandedStates.length - 1]; const small = doc.expandedStates[doc.expandedStates.length - 1]; diff --git a/tests/member/conditional.js b/tests/member/conditional.js new file mode 100644 index 00000000..916a775f --- /dev/null +++ b/tests/member/conditional.js @@ -0,0 +1,4 @@ +(valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(this.defaultUser)) +.prop; diff --git a/tests/method-chain/__snapshots__/jsfmt.spec.js.snap b/tests/method-chain/__snapshots__/jsfmt.spec.js.snap index a60288c2..6fcd1c33 100644 --- a/tests/method-chain/__snapshots__/jsfmt.spec.js.snap +++ b/tests/method-chain/__snapshots__/jsfmt.spec.js.snap @@ -417,23 +417,63 @@ exports[`computed-merge.js 1`] = ` `; exports[`conditional.js 1`] = ` +(a ? b : c).d(); + +(a ? b : c).d().e(); + +(a ? b : c).d().e().f(); + (valid ? helper.responseBody(this.currentUser) - : helper.response(401)) -.map(res => res.json()); + : helper.responseBody(this.defaultUser)) +.map(); + +(valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(this.defaultUser)) +.map().filter(); (valid ? helper.responseBody(this.currentUser) : helper.responseBody(defaultUser)) -.map(res => res.json()); +.map(); + +object[valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(defaultUser)] +.map(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -(valid ? helper.responseBody(this.currentUser) : helper.response(401)) - .map(res => res.json()); +(a ? b : c).d(); + +(a ? b : c).d().e(); + +(a ? b : c) + .d() + .e() + .f(); (valid ? helper.responseBody(this.currentUser) - : helper.responseBody(defaultUser)) - .map(res => res.json()); + : helper.responseBody(this.defaultUser) +).map(); + +(valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(this.defaultUser) +) + .map() + .filter(); + +(valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(defaultUser) +).map(); + +object[ + valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(defaultUser) +].map(); `; diff --git a/tests/method-chain/conditional.js b/tests/method-chain/conditional.js index 5d3299d8..d7e61dee 100644 --- a/tests/method-chain/conditional.js +++ b/tests/method-chain/conditional.js @@ -1,9 +1,25 @@ +(a ? b : c).d(); + +(a ? b : c).d().e(); + +(a ? b : c).d().e().f(); + (valid ? helper.responseBody(this.currentUser) - : helper.response(401)) -.map(res => res.json()); + : helper.responseBody(this.defaultUser)) +.map(); + +(valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(this.defaultUser)) +.map().filter(); (valid ? helper.responseBody(this.currentUser) : helper.responseBody(defaultUser)) -.map(res => res.json()); +.map(); + +object[valid + ? helper.responseBody(this.currentUser) + : helper.responseBody(defaultUser)] +.map(); From 1b2127efb6ed186ce6ae388c32850002e112ee59 Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Sun, 10 Sep 2017 16:46:47 -0300 Subject: [PATCH 13/19] Update snapshot --- tests/member/__snapshots__/jsfmt.spec.js.snap | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/member/__snapshots__/jsfmt.spec.js.snap b/tests/member/__snapshots__/jsfmt.spec.js.snap index 989d5315..185cc948 100644 --- a/tests/member/__snapshots__/jsfmt.spec.js.snap +++ b/tests/member/__snapshots__/jsfmt.spec.js.snap @@ -8,7 +8,8 @@ exports[`conditional.js 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (valid ? helper.responseBody(this.currentUser) - : helper.responseBody(this.defaultUser)).prop; + : helper.responseBody(this.defaultUser) +).prop; `; From 902f7f0339060a395cb6a0bf9d7a3d3d2e87be0e Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Sun, 10 Sep 2017 16:55:00 -0300 Subject: [PATCH 14/19] Use same logic for binary chain --- src/printer.js | 17 +++++++---- tests/member/__snapshots__/jsfmt.spec.js.snap | 14 ++++++++++ tests/member/logical.js | 3 ++ .../__snapshots__/jsfmt.spec.js.snap | 28 ++++++++++++++++++- tests/method-chain/logical.js | 9 ++++++ 5 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 tests/member/logical.js diff --git a/src/printer.js b/src/printer.js index 98a04641..b92e6178 100644 --- a/src/printer.js +++ b/src/printer.js @@ -367,13 +367,22 @@ function genericPrintNoParens(path, options, print, args) { const rest = concat(parts.slice(1)); + // Break the closing paren to keep the chain right after it: + // (a && + // b && + // c + // ).call() + const breakClosingParen = + parent.type === "MemberExpression" && !parent.computed; + return group( concat([ // Don't include the initial expression in the indentation // level. The first item is guaranteed to be the first // left-most expression. parts.length > 0 ? parts[0] : "", - indent(rest) + indent(rest), + breakClosingParen ? softline : "" ]) ); } @@ -1321,7 +1330,7 @@ function genericPrintNoParens(path, options, print, args) { concat([ path.call(print, "test"), forceNoIndent ? concat(parts) : indent(concat(parts)), - breakClosingParen ? ifBreak(softline, "") : "" + breakClosingParen ? softline : "" ]) ); } @@ -3712,9 +3721,7 @@ function printMemberChain(path, options, print) { // render everything concatenated together. if ( groups.length <= cutoff && - !hasComment && - // (a || b).map() should be break before .map() instead of || - groups[0][0].node.type !== "LogicalExpression" + !hasComment ) { return group(oneLine); } diff --git a/tests/member/__snapshots__/jsfmt.spec.js.snap b/tests/member/__snapshots__/jsfmt.spec.js.snap index 185cc948..3a188295 100644 --- a/tests/member/__snapshots__/jsfmt.spec.js.snap +++ b/tests/member/__snapshots__/jsfmt.spec.js.snap @@ -66,3 +66,17 @@ const promises = [ ]; `; + +exports[`logical.js 1`] = ` +(veryLongVeryLongVeryLong || e).prop; + +(veryLongVeryLongVeryLong || anotherVeryLongVeryLongVeryLong || veryVeryVeryLongError).prop; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(veryLongVeryLongVeryLong || e).prop; + +(veryLongVeryLongVeryLong || + anotherVeryLongVeryLongVeryLong || + veryVeryVeryLongError +).prop; + +`; diff --git a/tests/member/logical.js b/tests/member/logical.js new file mode 100644 index 00000000..e9eb10f8 --- /dev/null +++ b/tests/member/logical.js @@ -0,0 +1,3 @@ +(veryLongVeryLongVeryLong || e).prop; + +(veryLongVeryLongVeryLong || anotherVeryLongVeryLongVeryLong || veryVeryVeryLongError).prop; diff --git a/tests/method-chain/__snapshots__/jsfmt.spec.js.snap b/tests/method-chain/__snapshots__/jsfmt.spec.js.snap index 6fcd1c33..4c0f2372 100644 --- a/tests/method-chain/__snapshots__/jsfmt.spec.js.snap +++ b/tests/method-chain/__snapshots__/jsfmt.spec.js.snap @@ -572,9 +572,35 @@ Object.keys( exports[`logical.js 1`] = ` (veryLongVeryLongVeryLong || e).map(tickets => TicketRecord.createFromSomeLongString()); + +(veryLongVeryLongVeryLong || e).map(tickets => + TicketRecord.createFromSomeLongString()).filter(obj => !!obj); + +(veryLongVeryLongVeryLong || anotherVeryLongVeryLongVeryLong || veryVeryVeryLongError).map(tickets => + TicketRecord.createFromSomeLongString()); + +(veryLongVeryLongVeryLong || anotherVeryLongVeryLongVeryLong || veryVeryVeryLongError).map(tickets => + TicketRecord.createFromSomeLongString()).filter(obj => !!obj); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(veryLongVeryLongVeryLong || e).map(tickets => + TicketRecord.createFromSomeLongString() +); + (veryLongVeryLongVeryLong || e) - .map(tickets => TicketRecord.createFromSomeLongString()); + .map(tickets => TicketRecord.createFromSomeLongString()) + .filter(obj => !!obj); + +(veryLongVeryLongVeryLong || + anotherVeryLongVeryLongVeryLong || + veryVeryVeryLongError +).map(tickets => TicketRecord.createFromSomeLongString()); + +(veryLongVeryLongVeryLong || + anotherVeryLongVeryLongVeryLong || + veryVeryVeryLongError +) + .map(tickets => TicketRecord.createFromSomeLongString()) + .filter(obj => !!obj); `; diff --git a/tests/method-chain/logical.js b/tests/method-chain/logical.js index a7ab0442..6d76f5cd 100644 --- a/tests/method-chain/logical.js +++ b/tests/method-chain/logical.js @@ -1,2 +1,11 @@ (veryLongVeryLongVeryLong || e).map(tickets => TicketRecord.createFromSomeLongString()); + +(veryLongVeryLongVeryLong || e).map(tickets => + TicketRecord.createFromSomeLongString()).filter(obj => !!obj); + +(veryLongVeryLongVeryLong || anotherVeryLongVeryLongVeryLong || veryVeryVeryLongError).map(tickets => + TicketRecord.createFromSomeLongString()); + +(veryLongVeryLongVeryLong || anotherVeryLongVeryLongVeryLong || veryVeryVeryLongError).map(tickets => + TicketRecord.createFromSomeLongString()).filter(obj => !!obj); From f51929e262f7e8bcd07c316ba8ed7d9b6d40b531 Mon Sep 17 00:00:00 2001 From: Lucas Duailibe Date: Sun, 10 Sep 2017 17:17:45 -0300 Subject: [PATCH 15/19] Lint fix --- src/printer.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/printer.js b/src/printer.js index b92e6178..0ab076f8 100644 --- a/src/printer.js +++ b/src/printer.js @@ -3719,10 +3719,7 @@ function printMemberChain(path, options, print) { // If we only have a single `.`, we shouldn't do anything fancy and just // render everything concatenated together. - if ( - groups.length <= cutoff && - !hasComment - ) { + if (groups.length <= cutoff && !hasComment) { return group(oneLine); } From 3f74c45b9173e794295cfc9a8f212cf0138da637 Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Tue, 12 Sep 2017 04:18:11 +1000 Subject: [PATCH 16/19] Support graphql(schema, `query`) (#2781) --- src/clean-ast.js | 14 ++++++++--- src/multiparser.js | 19 ++++++++------- .../__snapshots__/jsfmt.spec.js.snap | 23 +++++++++++++++++++ tests/multiparser_js_graphql/graphql.js | 6 +++++ tests_integration/cwd-serializer.js | 2 +- 5 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 tests/multiparser_js_graphql/graphql.js diff --git a/src/clean-ast.js b/src/clean-ast.js index 921f1dfd..489c7696 100644 --- a/src/clean-ast.js +++ b/src/clean-ast.js @@ -4,9 +4,9 @@ function cleanAST(ast) { return JSON.stringify(massageAST(ast), null, 2); } -function massageAST(ast) { +function massageAST(ast, parent) { if (Array.isArray(ast)) { - return ast.map(e => massageAST(e)).filter(e => e); + return ast.map(e => massageAST(e, parent)).filter(e => e); } if (ast && typeof ast === "object") { // We remove extra `;` and add them when needed @@ -29,7 +29,7 @@ function massageAST(ast) { const newObj = {}; for (const key in ast) { if (typeof ast[key] !== "function") { - newObj[key] = massageAST(ast[key]); + newObj[key] = massageAST(ast[key], ast); } } @@ -219,6 +219,7 @@ function massageAST(ast) { quasis.forEach(q => delete q.value); } + // styled-components and graphql if ( ast.type === "TaggedTemplateExpression" && @@ -231,6 +232,13 @@ function massageAST(ast) { ) { newObj.quasi.quasis.forEach(quasi => delete quasi.value); } + if ( + ast.type === "TemplateLiteral" && + parent.type === "CallExpression" && + parent.callee.name === "graphql" + ) { + newObj.quasis.forEach(quasi => delete quasi.value); + } return newObj; } diff --git a/src/multiparser.js b/src/multiparser.js index 8f0f7b02..574b5fa7 100644 --- a/src/multiparser.js +++ b/src/multiparser.js @@ -68,14 +68,17 @@ function fromBabylonFlowOrTypeScript(path) { */ if ( parentParent && - parentParent.type === "TaggedTemplateExpression" && - parent.quasis.length === 1 && - ((parentParent.tag.type === "MemberExpression" && - parentParent.tag.object.name === "graphql" && - parentParent.tag.property.name === "experimental") || - (parentParent.tag.type === "Identifier" && - (parentParent.tag.name === "gql" || - parentParent.tag.name === "graphql"))) + ((parentParent.type === "TaggedTemplateExpression" && + parent.quasis.length === 1 && + ((parentParent.tag.type === "MemberExpression" && + parentParent.tag.object.name === "graphql" && + parentParent.tag.property.name === "experimental") || + (parentParent.tag.type === "Identifier" && + (parentParent.tag.name === "gql" || + parentParent.tag.name === "graphql")))) || + (parentParent.type === "CallExpression" && + parentParent.callee.type === "Identifier" && + parentParent.callee.name === "graphql")) ) { return { options: { parser: "graphql" }, diff --git a/tests/multiparser_js_graphql/__snapshots__/jsfmt.spec.js.snap b/tests/multiparser_js_graphql/__snapshots__/jsfmt.spec.js.snap index 3719f9e4..ee69af2e 100644 --- a/tests/multiparser_js_graphql/__snapshots__/jsfmt.spec.js.snap +++ b/tests/multiparser_js_graphql/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,28 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`graphql.js 1`] = ` +graphql(schema, \` +mutation MarkReadNotificationMutation( + $input + : MarkReadNotificationData! + ) +{ markReadNotification(data: $input ) { notification {seenState} } }\`) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +graphql( + schema, + \` + mutation MarkReadNotificationMutation($input: MarkReadNotificationData!) { + markReadNotification(data: $input) { + notification { + seenState + } + } + } + \` +); + +`; + exports[`graphql-tag.js 1`] = ` import gql from "graphql-tag"; diff --git a/tests/multiparser_js_graphql/graphql.js b/tests/multiparser_js_graphql/graphql.js new file mode 100644 index 00000000..d41e7ac0 --- /dev/null +++ b/tests/multiparser_js_graphql/graphql.js @@ -0,0 +1,6 @@ +graphql(schema, ` +mutation MarkReadNotificationMutation( + $input + : MarkReadNotificationData! + ) +{ markReadNotification(data: $input ) { notification {seenState} } }`) diff --git a/tests_integration/cwd-serializer.js b/tests_integration/cwd-serializer.js index 88027d12..4cd7009a 100644 --- a/tests_integration/cwd-serializer.js +++ b/tests_integration/cwd-serializer.js @@ -4,5 +4,5 @@ module.exports = { test: value => typeof value === "string" && value.indexOf(process.cwd()) !== -1, print: (value, serializer) => - serializer(value.replace(process.cwd(), "")) + serializer(value.replace(process.cwd(), "").replace(/\\/g, "/")) }; From fd937ec33413dd2d61531c07c68b13ac39be2556 Mon Sep 17 00:00:00 2001 From: Stepan Burguchev Date: Wed, 13 Sep 2017 13:06:49 +0300 Subject: [PATCH 17/19] fix webstorm integration guide (#2796) --- editors/webstorm/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editors/webstorm/README.md b/editors/webstorm/README.md index c6c032b9..b32288b2 100644 --- a/editors/webstorm/README.md +++ b/editors/webstorm/README.md @@ -6,7 +6,7 @@ Go to *File | Settings | Tools | External Tools* for Windows and Linux or *WebSt * **Program** set `prettier` -> If on the other hand you have `prettier` installed locally, replace the **Program** with `./node_modules/.bin/prettier` (on OS X and Linux) or `.\node_modules\.bin\prettier.cmd` (on Windows). +> If on the other hand you have `prettier` installed locally, replace the **Program** with `$ProjectFileDir$/node_modules/.bin/prettier` (on OS X and Linux) or `$ProjectFileDir$\node_modules\.bin\prettier.cmd` (on Windows). * **Parameters** set `--write [other opts] $FilePathRelativeToProjectRoot$` * **Working directory** set `$ProjectFileDir$` @@ -16,7 +16,7 @@ Go to *File | Settings | Tools | External Tools* for Windows and Linux or *WebSt ### Process directories * Clone the External tool created above and name it `Prettier Directories` -* **Parameters** set `--write [other opts] $FileDirRelativeToProjectRoot$/**/(*.js|*.jsx)` +* **Parameters** set `--write [other opts] $FileDirRelativeToProjectRoot$/**/{*.js,*.jsx}` ## Usage From d5e5d664075727b0d2e5adca274368f785a2ce17 Mon Sep 17 00:00:00 2001 From: Will Binns-Smith Date: Wed, 13 Sep 2017 09:03:18 -0700 Subject: [PATCH 18/19] Add option to require @prettier or @format pragma (#2772) * Add option to require @prettier or @format pragma Fixes #2397. Inspired by `eslint-plugin-prettier` and the discussion in #2397, this implements requiring a special comment pragma to be present in a file's first comment in order to be formatted. This will help large codebases gradually transition to prettier over time without tons of churn or large code reviews. I implemented this as a standard prettier "option", not just a typical `argv` flag, as it is relevant in both the cli and the api. This way it can be provided programmatically, on the command line, or standardized in a prettierrc file so like the style options, every user can use this setting consistently and only apply prettier to relevant files, no mattier their editor integration. This requires the pragma begin with `@` (in fact it's inserted if the user doesn't provide it). Currently the usage implies it must be "prettier" or "format", but it can technically be any value other than "none", which is similar to the `trailingCommas` option. cc @vjeux * Don't quote anything in runPrettier; this is usually handled by a shell * Make --require-pragma a boolean option * Use jest-docblock to find pragmas without parsing the ast * Clarify docs * includes -> indexOf * Move test out of integration --- README.md | 13 +++- docs/options.md | 23 ++++++++ index.js | 10 ++++ package.json | 1 + src/cli-constant.js | 5 +- src/cli-util.js | 1 + src/options.js | 1 + .../__snapshots__/jsfmt.spec.js.snap | 59 +++++++++++++++++++ tests/require-pragma/jsfmt.spec.js | 1 + tests/require-pragma/module-with-pragma.js | 14 +++++ tests/require-pragma/module-without-pragma.js | 13 ++++ .../__snapshots__/early-exit.js.snap | 2 + yarn.lock | 4 ++ 13 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 tests/require-pragma/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/require-pragma/jsfmt.spec.js create mode 100644 tests/require-pragma/module-with-pragma.js create mode 100644 tests/require-pragma/module-without-pragma.js diff --git a/README.md b/README.md index 937fdcdc..3d6d8531 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,17 @@ you can pass `--no-config` instead. Path to a file containing patterns that describe files to ignore. By default, prettier looks for `./.prettierignore`. +#### `--require-pragma` + +Require a special comment, called a pragma, to be present in the file's first docblock comment in order for prettier to format it. +```js +/** + * @prettier + */ +``` + +Valid pragmas are `@prettier` and `@format`. + #### `--list-different` Another useful flag is `--list-different` (or `-l`) which prints the filenames of files that are different from Prettier formatting. If there are differences the script errors out, which is useful in a CI scenario. @@ -288,7 +299,7 @@ Do not look for a configuration file. The default settings will be used. #### `--config-precedence` -Defines how config file should be evaluated in combination of CLI options. +Defines how config file should be evaluated in combination of CLI options. **cli-override (default)** diff --git a/docs/options.md b/docs/options.md index 06406013..67c339da 100644 --- a/docs/options.md +++ b/docs/options.md @@ -133,3 +133,26 @@ Default | CLI Override | API Override --------|--------------|------------- None | `--stdin-filepath ` | `filepath: ""` +## Require pragma +Prettier can restrict itself to only format files that contain a special comment, called a pragma, at the top of the file. This is very useful +when gradually transitioning large, unformatted codebases to prettier. + +For example, a file with the following as its first comment will be formatted when `--require-pragma` is supplied: + +```js +/** + * @prettier + */ +``` + +or + +```js +/** + * @format + */ +``` + +Default | CLI Override | API Override +--------|--------------|------------- +None | `--require-pragma` | `requirePragma` diff --git a/index.js b/index.js index cb351acc..25452ce7 100644 --- a/index.js +++ b/index.js @@ -10,6 +10,7 @@ const normalizeOptions = require("./src/options").normalize; const parser = require("./src/parser"); const printDocToDebug = require("./src/doc-debug").printDocToDebug; const config = require("./src/resolve-config"); +const docblock = require("jest-docblock"); function guessLineEnding(text) { const index = text.indexOf("\n"); @@ -30,6 +31,11 @@ function attachComments(text, ast, opts) { return astComments; } +function hasPragma(text) { + const pragmas = Object.keys(docblock.parse(docblock.extract(text))); + return pragmas.indexOf("prettier") !== -1 || pragmas.indexOf("format") !== -1; +} + function ensureAllCommentsPrinted(astComments) { if (!astComments) { return; @@ -56,6 +62,10 @@ function ensureAllCommentsPrinted(astComments) { } function formatWithCursor(text, opts, addAlignmentSize) { + if (opts.requirePragma && !hasPragma(text)) { + return { formatted: text }; + } + text = stripBom(text); addAlignmentSize = addAlignmentSize || 0; diff --git a/package.json b/package.json index 305b4f87..49db81f5 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "globby": "^6.1.0", "graphql": "0.10.1", "ignore": "^3.3.3", + "jest-docblock": "^21.0.2", "jest-validate": "20.0.3", "minimatch": "3.0.4", "minimist": "1.2.0", diff --git a/src/cli-constant.js b/src/cli-constant.js index 516475bd..05de15a9 100644 --- a/src/cli-constant.js +++ b/src/cli-constant.js @@ -7,7 +7,8 @@ const booleanOptionNames = [ "bracket-spacing", "jsx-bracket-same-line", // Deprecated in 0.0.10 - "flow-parser" + "flow-parser", + "require-pragma" ]; const stringOptionNames = [ @@ -86,6 +87,8 @@ Available options: Finds and prints the path to a configuration file for a given input file. --ignore-path Path to a file containing patterns that describe files to ignore. Defaults to ./.prettierignore. + --require-pragma + Require either '@prettier' or '@format' to be present in the file's first docblock comment in order for it to be formatted. --stdin Read input from stdin. --stdin-filepath Path to the file used to read from stdin. --print-width Specify the length of line that the printer will wrap on. Defaults to 80. diff --git a/src/cli-util.js b/src/cli-util.js index 3fd50001..c6b6952e 100644 --- a/src/cli-util.js +++ b/src/cli-util.js @@ -25,6 +25,7 @@ function getOptions(argv) { printWidth: getIntOption(argv, "print-width"), tabWidth: getIntOption(argv, "tab-width"), bracketSpacing: argv["bracket-spacing"], + requirePragma: argv["require-pragma"], singleQuote: argv["single-quote"], jsxBracketSameLine: argv["jsx-bracket-same-line"], filepath: argv["stdin-filepath"], diff --git a/src/options.js b/src/options.js index 25ad8c86..fb824ae5 100644 --- a/src/options.js +++ b/src/options.js @@ -15,6 +15,7 @@ const defaults = { bracketSpacing: true, jsxBracketSameLine: false, parser: "babylon", + requirePragma: false, semi: true }; diff --git a/tests/require-pragma/__snapshots__/jsfmt.spec.js.snap b/tests/require-pragma/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 00000000..66392b09 --- /dev/null +++ b/tests/require-pragma/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`module-with-pragma.js 1`] = ` +/** + * @flow + * @format + */ + +function foo(bar) + + +{ + + return bar + + 3 + + 4; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/** + * @flow + * @format + */ + +function foo(bar) { + return bar + 3 + 4; +} + +`; + +exports[`module-without-pragma.js 1`] = ` +/** + * @flow + */ + +function foo(bar) + + +{ + + return bar + + 3 + + 4; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/** + * @flow + */ + +function foo(bar) + + +{ + + return bar + + 3 + + 4; +} + +`; diff --git a/tests/require-pragma/jsfmt.spec.js b/tests/require-pragma/jsfmt.spec.js new file mode 100644 index 00000000..61c7d29f --- /dev/null +++ b/tests/require-pragma/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, { requirePragma: true }); diff --git a/tests/require-pragma/module-with-pragma.js b/tests/require-pragma/module-with-pragma.js new file mode 100644 index 00000000..79499ba9 --- /dev/null +++ b/tests/require-pragma/module-with-pragma.js @@ -0,0 +1,14 @@ +/** + * @flow + * @format + */ + +function foo(bar) + + +{ + + return bar + + 3 + + 4; +} diff --git a/tests/require-pragma/module-without-pragma.js b/tests/require-pragma/module-without-pragma.js new file mode 100644 index 00000000..8ece3791 --- /dev/null +++ b/tests/require-pragma/module-without-pragma.js @@ -0,0 +1,13 @@ +/** + * @flow + */ + +function foo(bar) + + +{ + + return bar + + 3 + + 4; +} diff --git a/tests_integration/__tests__/__snapshots__/early-exit.js.snap b/tests_integration/__tests__/__snapshots__/early-exit.js.snap index 00097955..c41392de 100644 --- a/tests_integration/__tests__/__snapshots__/early-exit.js.snap +++ b/tests_integration/__tests__/__snapshots__/early-exit.js.snap @@ -19,6 +19,8 @@ Available options: Finds and prints the path to a configuration file for a given input file. --ignore-path Path to a file containing patterns that describe files to ignore. Defaults to ./.prettierignore. + --require-pragma + Require either '@prettier' or '@format' to be present in the file's first docblock comment in order for it to be formatted. --stdin Read input from stdin. --stdin-filepath Path to the file used to read from stdin. --print-width Specify the length of line that the printer will wrap on. Defaults to 80. diff --git a/yarn.lock b/yarn.lock index fbdccb6d..da7e212c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2258,6 +2258,10 @@ jest-docblock@^20.0.1, jest-docblock@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712" +jest-docblock@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.0.2.tgz#66f69ddb440799fc32f91d0ac3d8d35e99e2032f" + jest-environment-jsdom@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-20.0.3.tgz#048a8ac12ee225f7190417713834bb999787de99" From 71f5d185a702b147b70b886979bbfa8c8c330ff0 Mon Sep 17 00:00:00 2001 From: Ika Date: Thu, 14 Sep 2017 11:26:43 +0800 Subject: [PATCH 19/19] docs(readme): port requirePragma docs to README.md (#2812) * fix default value --- README.md | 24 ++++++++++++++++++++++++ docs/options.md | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d6d8531..be078454 100644 --- a/README.md +++ b/README.md @@ -670,6 +670,30 @@ Default | CLI Override | API Override --------|--------------|------------- None | `--stdin-filepath ` | `filepath: ""` +### Require pragma +Prettier can restrict itself to only format files that contain a special comment, called a pragma, at the top of the file. This is very useful +when gradually transitioning large, unformatted codebases to prettier. + +For example, a file with the following as its first comment will be formatted when `--require-pragma` is supplied: + +```js +/** + * @prettier + */ +``` + +or + +```js +/** + * @format + */ +``` + +Default | CLI Override | API Override +--------|--------------|------------- +`false` | `--require-pragma` | `requirePragma` + ## Configuration File Prettier uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for configuration file support. diff --git a/docs/options.md b/docs/options.md index 67c339da..5c9868be 100644 --- a/docs/options.md +++ b/docs/options.md @@ -155,4 +155,4 @@ or Default | CLI Override | API Override --------|--------------|------------- -None | `--require-pragma` | `requirePragma` +`false` | `--require-pragma` | `requirePragma`