Skip to content

Add heuristic to format functional composition more nicely#4431

Merged
suchipi merged 5 commits intoprettier:masterfrom
suchipi:functional_composition
May 8, 2018
Merged

Add heuristic to format functional composition more nicely#4431
suchipi merged 5 commits intoprettier:masterfrom
suchipi:functional_composition

Conversation

@suchipi
Copy link
Copy Markdown
Member

@suchipi suchipi commented May 6, 2018

Based on discussion in #4172, this makes CallExpressions whose callee appears to be a functional composition function always break their arguments.

I added examples for ramda, rxjs, lodash, redux, and a generic "compose/composeFlipped".

Fixes #4172
Fixes #1420

// composeP
// composeK
// flow
// flowRight
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you listed out all the possibilities anyway, perhaps we should make an array with all names and use that instead of a regex?

Copy link
Copy Markdown
Member Author

@suchipi suchipi May 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do


const maybeTrailingComma = shouldPrintComma(options, "all") ? "," : "";

function allArgsBrokenOut() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't create a function, just inline the content in the if

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh nevermind, you're using it below as well

"composeK",
"flow",
"flowRight"
];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are inlining it like this, then please use an object so it doesn't have to do a linear lookup every time.

{
  pipe: true,
  pipeP: true,
  ...
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about a Set?

(Btw, as far as I remember we have lots of such arrays where we do indexOf.)





Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why all the empty lines?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because my editor was prettifying on save so I pasted these into nano 😅 I can remove them


foo(6);


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here


foo(6);


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

@vjeux
Copy link
Copy Markdown
Contributor

vjeux commented May 6, 2018

This issue has more examples. connect would likely be worthy of inclusion for redux.
#1420

composeP: true,
composeK: true,
flow: true,
flowRight: true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add as comments which is coming from which library, so we know in the future where it came from

Also add comments for libraries
Copy link
Copy Markdown
Contributor

@vjeux vjeux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks! It's going to make a lot of people happy :)

@suchipi
Copy link
Copy Markdown
Member Author

suchipi commented May 6, 2018

Thanks for coming up with the good heuristic @vjeux :)

@suchipi suchipi merged commit ed18f9f into prettier:master May 8, 2018
@adrianmcli
Copy link
Copy Markdown

Awesome work all-around. Thanks y'all.

@lipis lipis added this to the 1.13 milestone May 9, 2018
@szkl
Copy link
Copy Markdown

szkl commented Jun 1, 2018

This issue has more examples. connect would likely be worthy of inclusion for redux.
#1420

What about the specified names occurring in different contexts? socket.connect for example.

@suchipi
Copy link
Copy Markdown
Member Author

suchipi commented Jun 1, 2018

I avoided socket.pipe by only matching if there's more than one argument, but it looks like this is mistakenly hitting socket.connect in some cases:

Prettier 1.13.4
Playground link

--parser babylon

Input:

socket.connect(2000, () => {})

Output:

socket.connect(
  2000,
  () => {}
);

We could probably refine this to bail if any of the arguments are number, string, or object literals. Thoughts?

@duailibe
Copy link
Copy Markdown
Collaborator

duailibe commented Jun 1, 2018

@suchipi makes sense. Or whitelist for call expressions, identifiers, (arrow) functions

@suchipi
Copy link
Copy Markdown
Member Author

suchipi commented Jun 1, 2018

I'd rather do an omit list than an allow list because you could have functions as object properties and access them with a member expression.

@princed
Copy link
Copy Markdown
Contributor

princed commented Jun 21, 2018

@suchipi Is there any GH issue on that matter?
We got hit in our own classes with Prettier producing code like this:

this.compose(
  d1,
  d2
);

@suchipi
Copy link
Copy Markdown
Member Author

suchipi commented Jun 21, 2018

@princed I haven't made one yet, if you could make one, I would appreciate it

@princed
Copy link
Copy Markdown
Contributor

princed commented Jun 26, 2018

@suchipi Raised #4751

@lxe
Copy link
Copy Markdown

lxe commented Jul 3, 2018

This is clever actually very nice for most cases, but I don't think that hardcoding function names from arbitrary libraries into a general purpose JS formatter is a good idea. Maybe there's a way to expand the heuristic to allow for configuration or use the argument types somehow?

@suchipi
Copy link
Copy Markdown
Member Author

suchipi commented Jul 3, 2018

@lxe there is some discussion related to that problem space in #4424

@shannonmoeller
Copy link
Copy Markdown
Member

I agree with @lxe. Hate to be a downer, but this change is awful. Adding a hardcoded list of function names to treat specially has just made prettier a React code formatter, not a general-purpose code formatter.

@j-f1
Copy link
Copy Markdown
Member

j-f1 commented Jul 3, 2018

Adding a hardcoded list of function names to treat specially has just made prettier a React code formatter, not a general-purpose code formatter.

None of these changes cause the React APIs to be printed differently. Also, we already do some of this special-casing (for example, never breaking it() calls).

@benlesh
Copy link
Copy Markdown

benlesh commented Jul 20, 2018

Honestly, I think you'll be better off just doing what clang format did and using a trailing comma as the heuristic to decide if you should inline them all or put them each on their own lines:

someThing.whatever(foo, bar, baz, qux);

//vs

somthing.whatever(
  foo, 
  bar,
  baz,
  qux,
)
  1. It's easy to control
  2. It's easy to learn
  3. It's fairly intuitive
  4. It's great for git diffs
  5. You don't have to write crazy logic guesswork algorithms to figure out what to do.

🤷‍♂️

@j-f1
Copy link
Copy Markdown
Member

j-f1 commented Jul 20, 2018

Not all runtimes support trailing commas in functions, though.

@suchipi
Copy link
Copy Markdown
Member Author

suchipi commented Jul 20, 2018

  1. It's easy to control

This is a negative, from my perspective. For me, a big value of prettier is that I can let it "do it's thing" and be hands-off about formatting... at least, mostly. We rely on hinting for multilining object literals and I have to break out of my flow to adjust formatting from time to time because of it. I would rather it didn't let me influence the formatting at all- then I could focus on writing the code and let the formatting be what it is. But the ability to influence the formatting wedges itself into my workflow...

@lock lock bot added the locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting. label Oct 18, 2018
@lock lock bot locked as resolved and limited conversation to collaborators Oct 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting.

Projects

None yet

Development

Successfully merging this pull request may close these issues.