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 977da24c4..403b0ebbf 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 8e0c4c78c..076b2cfc9 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 1ca836cd3..4ba597390 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 076b2cfc9..f3113b4bb 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 4ba597390..5266662a9 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 403b0ebbf..878a48c7e 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 dcb11e3f0..fd0d05c85 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 2fbafa9f0..a59339032 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 76d47eabc..4aa40348c 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 0339b5146..9340fcf68 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 f3113b4bb..49b42843b 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 269a2e2df..948f1cfa0 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 878a48c7e..f809cdb3b 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 f809cdb3b..420e87260 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 1307bf12d..b5e0675f7 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 064265e30..7fab11669 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 26f895ba4..ff4043ec1 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 7707ed254..50598c4e4 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 2b3552999..2295fe836 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 a0fc77ced..0be202710 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 420e87260..6b3334634 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 fd0d05c85..5c4ba464f 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 000000000..44ba5b067 --- /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 6b3334634..0d16304bf 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 da56e5a02..a60288c29 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 000000000..5d3299d89 --- /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 0be202710..106f3921a 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 201d16178..3fd500017 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 000000000..a396d0f89 --- /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 000000000..8e46de3f3 --- /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 000000000..c51aa823b --- /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 000000000..ad9a93a7c --- /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 000000000..ad9a93a7c --- /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 000000000..ad9a93a7c --- /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 0d16304bf..98a046412 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 e2dfaec76..989d5315e 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 000000000..916a775fd --- /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 a60288c29..6fcd1c33d 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 5d3299d89..d7e61deeb 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 989d5315e..185cc9481 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 98a046412..b92e6178c 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 185cc9481..3a1882958 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 000000000..e9eb10f8f --- /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 6fcd1c33d..4c0f23729 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 a7ab0442d..6d76f5cd9 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 b92e6178c..0ab076f88 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 921f1dfd3..489c76969 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 8f0f7b024..574b5fa70 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 3719f9e4d..ee69af2e7 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 000000000..d41e7ac0b --- /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 88027d12e..4cd7009ab 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 c6c032b9a..b32288b28 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 937fdcdc9..3d6d85313 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 06406013d..67c339da8 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 cb351acc6..25452ce78 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 305b4f870..49db81f52 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 516475bd2..05de15a9a 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 3fd500017..c6b6952e1 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 25ad8c865..fb824ae59 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 000000000..66392b09f --- /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 000000000..61c7d29f1 --- /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 000000000..79499ba96 --- /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 000000000..8ece37915 --- /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 000979558..c41392dee 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 fbdccb6d7..da7e212c9 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 3d6d85313..be0784540 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 67c339da8..5c9868be2 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`