Add option to require @prettier or @format pragma#2772
Add option to require @prettier or @format pragma#2772vjeux merged 7 commits intoprettier:masterfrom
Conversation
| * @flow | ||
| * @format | ||
| */ | ||
|
|
There was a problem hiding this comment.
hmm.. the whole thing does work. not sure what happened here...
There was a problem hiding this comment.
What do you mean? Isn't it supposed to be working?
By the way, it doesn't have to be an integration test. It can be written as a normal test. You can create a new folder and tweak the config in jsfmt.spec.js
|
As I mentioned in #2397 (comment), I'm not sure why |
|
cc the eslint-plugin-prettier folks: @not-an-aardvark @zertosh |
|
If we go through with this let's stick with either |
| re = reForPragma[pragma]; | ||
| } else { | ||
| // @pragma surrounded by any amount of whitespace on either or both sides | ||
| re = reForPragma[pragma] = new RegExp(`\\s*@${pragma}\\s*`); |
There was a problem hiding this comment.
Your \s* does absolutely nothing. It matches -- 0 -- or more whitespaces.
There was a problem hiding this comment.
You need to escape pragma, otherwise people can start adding .* to match literally anything.
There was a problem hiding this comment.
It is also worth thinking about if [email protected] should match the @prettier pragma. Perhaps we should check how Flow checks for @flow and do something similar?
| } | ||
|
|
||
| // Cache compiled regexps in the likely case the same pragma is used for many | ||
| // files. |
There was a problem hiding this comment.
No seriously, this is not needed. Creating a dynamic regex isn't going to be a bottleneck.
| // if the user provided a value with `@` in the beginning anyway, strip it off. | ||
| if (value.startsWith("@")) { | ||
| return value.substr(1); | ||
| } |
There was a problem hiding this comment.
Please don't silently drop things. Instead you want to throw an exception with a clear error message.
There was a problem hiding this comment.
Actually, it seems to be confusing so why not require people to add @ in the command line.
--pragma @format
| const value = argv["require-pragma"]; | ||
|
|
||
| if (value === undefined) { | ||
| return value; |
There was a problem hiding this comment.
Can you be explicit and return undefined;, otherwise it's not instantly clear that value is undefined
| Print trailing commas wherever possible when multi-line. Defaults to none. | ||
| --parser <flow|babylon|typescript|postcss|json|graphql> | ||
| Specify which parse to use. Defaults to babylon. | ||
| --require-pragma <none|format|prettier> |
There was a problem hiding this comment.
I would just name it --pragma, it feels weird to have the require- in front.
There was a problem hiding this comment.
Given the fact that we want it to be a boolean, disregard my renaming suggestion.
|
If you address my comments, I'll get it in, thanks for building it! |
|
I somehow skipped @azz comment. I actually really like the idea. What we could do is to hardcode in the future |
|
@azz @mitermayer @vjeux don't you think we should keep this flexible for compatibility with eslint-plugin-prettier's pragma option allowing arbitrary strings? I definitely see the advantage of keeping this to a known value so in the future option-values can be applied. I'm still worried about the existing adoption of eslint-plugin-prettier's arbitrary pragmas though. |
|
Isn't it super easy to migrate from a custom pragma name, though? Just a simple search-and-replace across the entire repo. |
|
I doubt many people used a different pragma, if they are using the pragma at all. |
| re = reForPragma[pragma] = new RegExp(`\\s*@${pragma}\\s*`); | ||
| } | ||
|
|
||
| const firstComment = astComments[0]; |
There was a problem hiding this comment.
Why does it have to be the first comment? There are lots of magic comments you might start your files with:
@prettier@floweslint-disable no-console- licensing stuff
There was a problem hiding this comment.
All the fb magic comments only work if it's the first comment of the file.
There was a problem hiding this comment.
it doesn't need to be the first thing in the comment, but it needs to be a part of the first comment, like in a docblock. You can still have other pragmas and licensing information within that first docblock (see most open source FB projects)
There was a problem hiding this comment.
There are two practical reasons for this:
- We don't need to parse the file, we can just grep until we see */ to find it which helps making it fast.
- We use them to toggle syntax variants, so we can't actually parse the file until we know which variant to use.
We're not doing any of those two right now with prettier but those are two optimizations that would be useful.
There was a problem hiding this comment.
Good, sounds like this has been thought through then. 👍
There was a problem hiding this comment.
Actually, we should probably implement 1), otherwise it's going to throw error for js files that prettier doesn't understand or be super slow for giant generated files where it doesn't need to.
There was a problem hiding this comment.
I played around a little bit with Flow, and this works:
/*
function notCode() {
return 1;
}
*/
// @prettier
// something something @flow side
code;It appears as if @flow can be present anywhere in any comment that comes before all code. Additionally, @flow seems to have to be located at the very beginning of a comment or line, at the very end of a line, or surrounded by whitespace.
9b39c76 to
375f296
Compare
| const config = require("./src/resolve-config"); | ||
|
|
||
| const PRAGMA_RE = /@\bprettier|format\b/; | ||
| const docblock = require("jest-docblock"); |
There was a problem hiding this comment.
My only concern on using jest-docblock for extracting the tags is that it has no documentation or information around it, (https://www.npmjs.com/package/jest-docblock).
If that is a multi-purpose module maybe we should include some documentation around it, otherwise we could either implement our own naive docblock pragma extractor or use other established parser like doctrine.
@cpojer what are your thoughts around it ? is jest-docblock meant to be a private module for jest itself ?
There was a problem hiding this comment.
it's already used to do the pragma extraction in eslint-plugin-prettier :) Also see prettier using jest-validate right below in package.json here.
it's so useful I'd be happy to document its api.
I imagine jest split itself as many packages for this very reason?
There was a problem hiding this comment.
jest-docblock in particular was split out because it was needed in multiple packages inside of jest - an awesome side-effect is that it can be used separately by other projects!
It has no documentation since I was lazy when it was extracted, so a documentation PR would be awesome
There was a problem hiding this comment.
Use it, it's great. No docs necessary, source should be reasonably simple :)
|
jest-docblock is what we use for jest and runs in prod at Facebook so even though it has no documentation, I would trust it. Also, we're pinning a version and it's unlikely to change drastically so we should be good to go. |
|
I'm in favor of a hardcoded pragma; I think it will be better for the community long-term; instead of a user wondering, "what does that mean?" every time they go into a new project, and then realizing, "oh, that's how they configured prettier", a user who has wondered that once will understand what's going on in the next project, when they see the same pragma. Because of that motivation, I'd prefer a single, hardcoded pragma (like what flow does). My preference is for |
375f296 to
d838f18
Compare
|
Facebook entire codebase is using |
|
I also vote for |
I feel like in open source, this is more bad than good; hiding complexity can confuse people. googling " |
|
@suchipi totally agreed, I think that for open source it makes sense to use and promote |
|
Anything I can do to help move this along @vjeux? Apart from maybe moving the integration test to a unit-style snapshot test, I feel like this is in a pretty good spot right now. |
|
Travis says that the tests fail – perhaps you could start by looking at those? |
|
ah yeah, I thought this was due to a few lines not being covered like I saw before, but there's an issue with Node 4 not having |
Fixes prettier#2397. Inspired by `eslint-plugin-prettier` and the discussion in prettier#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
c7bc25e to
556529e
Compare
|
Thanks! |
|
any time @vjeux 🎉 |
Fixes #2397.
Inspired by
eslint-plugin-prettierand 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
argvflag, 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 thetrailingCommasoption.cc @vjeux