// Before
type Foo = Promise<
<span class="pl-k">|</span> { ok<span class="pl-k">:</span> <span class="pl-c1">true</span>, bar<span class="pl-k">:</span> string, baz<span class="pl-k">:</span> SomeOtherLongType }
<span class="pl-k">|</span> { ok<span class="pl-k">:</span> <span class="pl-c1">false</span>, bar<span class="pl-k">:</span> SomeOtherLongType }
>;
// After
type Foo = Promise<
{ ok: true, bar: string, baz: SomeOtherLongType } |
{ ok: false, bar: SomeOtherLongType }
>;
Do not put parens for single argument with end of line comment (#1518)
The detection code for whether an arrow function should be written without parenthesis just checked if there was a comment, but instead we only want comments that are inline like (/* comment */ num)
, not end of line comments.
// Before
KEYPAD_NUMBERS.map((num) => ( // Buttons 0-9
<div />
));
KEYPAD_NUMBERS.map(num => ( // Buttons 0-9
<div />
));
Do not indent nested ternaries (#1822)
This avoids making it seems like it is indented by 4 characters instead of two. The downside is that if the condition is multi-line it's not going to be properly aligned, but I feel it's a better trade-offs. If you are doing nested ternaries, you usually have small conditions.
// Before
aaaaaaaaaaaaaaa
? bbbbbbbbbbbbbbbbbb
: ccccccccccccccc
? ddddddddddddddd
: eeeeeeeeeeeeeee ? fffffffffffffff : gggggggggggggggg;
// After
aaaaaaaaaaaaaaa
? bbbbbbbbbbbbbbbbbb
: ccccccccccccccc
? ddddddddddddddd
: eeeeeeeeeeeeeee ? fffffffffffffff : gggggggggggggggg;
Inline chained conditionals inside of jsx attribute (#1519)
We don't need to use the indentation to disambiguate another block as nothing can come after.
// Before
<div
src={
!isEnabled &&
diffUpdateMessageInput != null &&
this.state.isUpdateMessageEmpty
}
/>;
// After
<div
src={
!isEnabled &&
diffUpdateMessageInput != null &&
this.state.isUpdateMessageEmpty
}
/>;
Unescape unnecessarily escaped characters in strings (#1575) by @josephfrazier
We are already trying to cleanup strings in various ways, this is another small addition that's going to remove \
that are not needed.
// Before
a = 'hol\a';
// After
a = 'hola';
Fix boolean for empty objects (#1590) by @dmitrika
We want to inline objects inside of a boolean expression as it looks weird to have {
on its own line. But it turns out that it leads to weird behaviors for empty objects. So we keep them on their own line if they are empty.
const x = firstItemWithAVeryLongNameThatKeepsGoing ||
secondItemWithALongNameAsWell || {};
// After
const x =
firstItemWithAVeryLongNameThatKeepsGoing ||
secondItemWithALongNameAsWell ||
{};
Remove Parens from SequenceExpressions in ForStatements (#1597) by @k15a
It is common to assign multiple values inside of a for loop, now we don't add parenthesis anymore.
// Before
for ((i = 0), (len = arr.length); i < len; i++) {
// After
for (i = 0, len = arr.length; i < len; i++) {
Do not inline arrow when argument has a leading comment (#1660)
If you put block comments inside of arrow functions, we no longer mess everything up!
// Before
export const bem = block => /**
* @param {String} [element] - the BEM Element within that block; if undefined, selects the block itself.
*/
element => /**
* @param {?String} [modifier] - the BEM Modifier for the Block or Element; if undefined, selects the Block or Element unmodified.
*/
modifier =>
// After
export const bem = block =>
/
* @param {String} [element] - the BEM Element within that block; if undefined, selects the block itself.
*/
element =>
/
* @param {?String} [modifier] - the BEM Modifier for the Block or Element; if undefined, selects the Block or Element unmodified.
*/
modifier =>
Fix last comments of imports (#1677)
Another place where we have to do special logic for comments!
// Before
import {
ExecutionResult,
DocumentNode,
/* tslint:disable */
SelectionSetNode,
} /* tslint:enable */ from 'graphql';
// After
import {
DocumentNode,
/* tslint:disable /
SelectionSetNode,
/ tslint:enable */
} from 'graphql';
Handle comments in member chain (#1686, #1691)
We handled some placements before and kept adding places where they could appear, now we switch to a more general approach. Hopefully those issues shouldn't crop up in the future anymore.
// Before
const configModel = this.baseConfigurationService.getCache().consolidated // global/default values (do NOT modify)
.merge(this.cachedWorkspaceConfig);
// After
const configModel = this.baseConfigurationService
.getCache()
.consolidated // global/default values (do NOT modify)
.merge(this.cachedWorkspaceConfig);
Use expandLast for nested arrow functions (#1720)
// Before
f(action => next =>
next(action));
// After
f(action => next =>
next(action),
);
Put JSX comments inside of the parenthesis (#1712)
This mostly affects Facebook engineers where we automatically add $FlowFixMe
when pushing a new version of flow. Now it no longer messes up those comments.
// Before
const aDiv = /* $FlowFixMe */
(
<div className="foo">
Foo bar
</div>
);
// After
const aDiv = (
/* $FlowFixMe */
<div className="foo">
Foo bar
</div>
);
Force \n for multiple variable declarations (#1723)
This one has been very often requested. We used to only break multiple variable declarations if the line was > 80 columns. Now we do it regardless if there's at least one with an assignment.
// Before
var numberValue1 = 1, numberValue2 = 2;
// After
var numberValue1 = 1,
numberValue2 = 2;
Inline | null and | void (#1734)
The expanded version of flow union looks good when they are many objects but if it's used for nullability, the it looks very weird. We're now inlining | null
and | void
.
// Before
interface RelayProps {
articles:
| Array<
| {
__id: string,
}
| null
>
| null
}
// After
interface RelayProps {
articles: Array<{
__id: string,
} | null> | null,
}
Break on implements instead of extends (#1730)
We no longer break on extends
. This should make classes with extends that can break look less wonky.
// Before
class MyContractSelectionWidget
extends React.Component<
void,
MyContractSelectionWidgetPropsType,
void
> {
method() {}
}
// After
class MyContractSelectionWidget extends React.Component<
void,
MyContractSelectionWidgetPropsType,
void
> {
method() {}
}
Inline single import (#1729)
The same way we don't break long require
calls, we no longer break import
statements if there is only a single thing being imported.
// Before
import somethingSuperLongsomethingSuperLong
from "somethingSuperLongsomethingSuperLongsomethingSuperLong";
// After
import somethingSuperLongsomethingSuperLong from "somethingSuperLongsomethingSuperLongsomethingSuperLong";
Add the ability for SequenceExpression to break (#1749)
Did you know that if none of your code were statements, you could use ()
instead of {}
and ,
instead of ;
? Now you do. Some people exploit this fact when returning things from arrow functions. This is not recommended but it's easy to support in prettier so might as well Β―_(γ)_/Β―
// Before
const f = (argument1, argument2, argument3) =>
(doSomethingWithArgument(argument1), doSomethingWithArgument(
argument2
), argument1);
// After
const f = (argument1, argument2, argument3) => (
doSomethingWithArgument(argument1),
doSomethingWithArgument(argument2),
argument1
);
Don't force line break in empty loop bodies (#1815)
Loops with empty body no longer have their {}
split into two lines.
// Before
while (true) {
}
// After
while (true) {}
Preserve empty lines between switch cases with comments (#1708)
// Before
switch (true) {
case true:
// Good luck getting here
case false:
}
// After
switch (true) {
case true:
// Good luck getting here
case false:
}
Correctness
We used to find where to put comments by traversing the AST using the definition from ast-types. This occasionally caused issues when some field wasn't declared, we wouldn't find the node and either print comments in an incorrect location or throw an error. It turns out that we don't need to keep this mapping and can just traverse the objects and if a node has a type
field, then it's a node.
// Before
Error: did not recognize object of type "ObjectTypeSpreadProperty"
// After
type X = {...Y//};
type X = {//...Y};
If you were adding invisible characters inside of JSX text, we would replace them by regular spaces. I don't know why anyone would ever want to do that, but now we print it back as is!
We used to have some pretty complicated (and not working well) code to handle comments inside of template literals. We introduced a really nice solution for JSX {}
expressions. The idea is to introduce a boundary before the end of the }
and if we still have unprinted comments, then flush them all at once, put a \n and print the }
. We are now using this logic for template literals :)
// Before
`${0} // comment`;
// After
</span><span class="pl-s1"><span class="pl-pse">${</span></span></span> <span class="pl-s"><span class="pl-s1"><span class="pl-c1">0</span></span></span> <span class="pl-s"><span class="pl-s1"><span class="pl-c"><span class="pl-c">//</span> comment</span></span></span> <span class="pl-s"><span class="pl-s1"><span class="pl-pse">}</span></span><span class="pl-pds">
;
We don't have an automated way to put parenthesis, we instead specify all the possible combinations of nodes and when they should or shouldn't have parenthesis. So there's likely a long tail of unusual combinations that are still remaining. In this case, we made await
handling a lot more robust by both adding parenthesis where they are needed and removing them when they are not.
// Before
(await spellcheck) && spellcheck.setChecking(false);
new A((await x));
// After
await (spellcheck && spellcheck.setChecking(false));
new A(await x);
Preserve getter/setter info on flow ObjectTypeProperty (#1585) by @josephfrazier
Another long tail option that we haven't got right!
// Before
type T = { method: () => void };
// After
type T = { get method(): void }
Add parenthesis for single arg types with generics (#1814)
Another case of sneaky parenthesis that we didn't properly add!
// Before
type ExtractType = <A>B<C> => D
// After
type ExtractType = <A>(B<C>) => D
We want prettier to be able to parse all the JavaScript out there. For babylon parser, we have to chose whether a file is using strict mode or not. We opted in to use strict mode by default as most files parse that way. But if you have octal literals like 0775
, it would not even parse. Now if it fails to parse in strict mode, we're going to try again in non-strict. We also allow return
outside of a function as it's valid in node files.
// Before
SyntaxError
// After
return 0775;
CLI
Allow --write
to be used with --list-different
(#1633)
This is useful to combine the two if you are writing a commit hook to tell the user what actually changed in a single command.
Ignore node_modules when running prettier from CLI (#1683) by @thymikee
It's very easy to run prettier over the node_modules/
folder by mistake which is something you almost never want to. So now we disable it by default and add a --with-node-modules
option if you really want to.
Traverse dot files for glob (#1844) by @jhgg
We enabled the option to go through .dotfiles in the glob parsing library we are using. This means that writing *
will now catch .eslintrc
.
Not sure how things should work exactly?
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot π΄