-
-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merge with eslint-plugin-prettify #21
Conversation
This code is originally from zertosh/eslint-plugin-prettify@2fb5dfb. It's has been adjusted to conform to the existing ESLint style.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! This generally looks good, I just have a few small suggestions/questions.
} | ||
// Register ourselves as a plugin to avoid `node_modules` trickery. | ||
const Plugins = require('eslint/lib/config/plugins'); | ||
Plugins.define('prettier', require('.')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this approach is going to break after eslint/eslint#8465 is merged, which is likely to happen in ESLint 4. (The change makes Plugins
an ES6 class rather than a global mutable object, to prevent unrelated modules from conflicting with each other if they both happen to be using eslint in the same process.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh thanks for the heads up! Modifying the node_modules
after an install causes yarn issues :/
QQ: We also use this approach at fb because you can't use a path as a plugin. I understand the module resolution complications of supporting relative paths, but would the ESLint team be open to accepting a PR for absolute paths to a plugin?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's an accepted issue for it at eslint/eslint#6237, but when I looked into it a little while ago it seemed like it could introduce problems even when absolute paths are used. Basically, if I load eslint-plugin-foo
with a relative path, and I'm also using a shareable config that references something else called eslint-plugin-foo
in node_modules
(e.g. another version of the plugin), it wouldn't be possible to configure rules from both plugins independently.
Feel free to comment on that thread if you have any ideas for how to handle that, though.
Hmm, I hadn't realized modifying node_modules
breaks yarn. Maybe we should keep Plugins
somehow until we have a better way to refer to plugins by path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I hadn't realized modifying node_modules breaks yarn
It causes yarn check
to fail. Also, it'll break a new yarn feature I'll be upstreaming soon: "watchman-based check". Basically, you get instant (sub ~100ms) full node_modules
verification, which lets use put yarn
in front of every js script w/o having to worry about stale modules.
|
||
## Migrating to 2.0.0 | ||
- A string with a pragma that triggers this rule. By default, this rule applies to all files. However, if you set a pragma (this option), only files with that pragma in the heading docblock will be checked. All pragmas must start with `@`. Example: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, it seems like it would be better to get this functionality by using normal eslint
directive comments, e.g.
/* eslint prettier: ["error", "fb"] */
Is there a reason to have a special pragma for the rule?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tbh, this is a facebookism. We need a to tell our language-agnostic infra that these files conform to a formatter (we use @format
). This helps the merge drivers to reconcile changes, and helps other enforcement tooling maintain order. So even if eslint-plugin-prettier
didn't understand pragmas, we'd still have to mark these with @format
.
eslint-plugin-prettier.js
Outdated
ret += '\u23ce'; // Return Symbol | ||
break; | ||
case '\t': | ||
ret += '\u21b9'; // Left Arrow To Bar Over Right Arrow To Bar |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Maybe this would be more readable if you used the symbols themselves in the code rather than their escape codes. For example:
switch (str[i]) {
case ' ':
ret += '·'; // Middle Dot, \u00b7
break;
case '\n':
ret += '⏎'; // Return Symbol, \u23ce
case '\t':
ret += '↹'; // Left Arrow To Bar Over Right Arrow To Bar, \u21b9
}
That way, if someone sees a symbol in the output, it's easier to tell where in the code the symbol is coming from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
eslint-plugin-prettier.js
Outdated
// and another's beginning does not have line endings (i.e. issues that occur | ||
// on contiguous lines). | ||
|
||
const source = context.getSource(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think context.getSource()
is deprecated -- there doesn't seem to be any documentation for it, and it's in the list of deprecated passthroughs here. Can you replace it with context.getSourceCode().text
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
eslint-plugin-prettier.js
Outdated
*/ | ||
function reportInsert(context, offset, text) { | ||
const pos = getLocFromIndex(context, offset); | ||
const range = [null, offset]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure null
is documented as a valid value in a fix range. Can you replace this with [offset, offset]
or something like that instead?
(Admittedly, the design of insertTextAfterRange
does make the first value in the range useless, but I don't want this to break if ESLint starts validating ranges later on by asserting that both values are numbers.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
eslint-plugin-prettier.js
Outdated
if (pragma) { | ||
// The pragma is only valid if it is found in a block comment at the | ||
// very start of the file. | ||
const firstComment = context.getAllComments()[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think context.getAllComments()
is also deprecated. Can you use context.getSourceCode().getAllComments()
instead?
Also, starting in ESLint 4, shebang comments will be included in the result of sourceCode.getAllComments
(see the migration guide). Shebang comments need to be placed at the start of a file, so maybe it would be better to filter them here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
code: sections[1], | ||
output: sections[2], | ||
options: eval(sections[3]), // eslint-disable-line no-eval | ||
errors: eval(sections[4]) // eslint-disable-line no-eval |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to use JSON.parse
here instead? It seems like there's no reason to execute array literals as code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSON formatting is too restrictive: Quoting keys, and using double quotes for strings. RuleTester's output is not JSON, so copy/pasting expected output would've required re-formatting. If it's all the same to you, I'd like to keep the eval
until it becomes a problem.
test/prettier.js
Outdated
{ code: `/** @format */\n'';\n`, options: ['fb', '@format'] } | ||
], | ||
invalid: [ | ||
'01', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't a strong objection, but I have doubts about whether putting the invalid cases in separate files actually improves debuggability. If a single test case is failing, it seems like it would be easier to search for the corresponding code within a single file rather than opening/closing a bunch of test files to try to find the right one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, it's actually more about easily looking at a fixture file and easily converting line & column in the test vs the message. It's also very convenient to be able to quickly focus on a few tests by commenting out.
test/prettier.js
Outdated
@@ -0,0 +1,92 @@ | |||
#!/usr/bin/env node | |||
/* eslint-disable node/shebang */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this file executable? RuleTester
uses mocha internally, so it seems like this would throw an error if it was just run with node
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It works actually, you just don't get pretty output if there's an error. But I'll remove it since that's an odd use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, TIL.
eslint-plugin-prettier.js
Outdated
// Prettier is expensive to load, so only load it if needed. | ||
prettier = require('prettier'); | ||
} | ||
const source = context.getSource(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think context.getSource()
is deprecated -- there doesn't seem to be any documentation for it, and it's in the list of deprecated passthroughs here. Can you replace it with context.getSourceCode().text
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this 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, @not-an-aardvark do you have any concerns left merging this in?
I enabled "Rebase and merge" to preserve the commits on this PR. If it all looks good, then I can merge and publish. |
By the way, I've been using this script to autogenerate changelogs and git tags, in case we want to keep using it. (It requires a few additional devDependencies that |
neat script @not-an-aardvark! I just used it and pushed the results :) I'll check it into the repo & add some release instructions. Mind doing an npm release and/or adding me as a collaborator? |
Will do. Are you |
@not-an-aardvark, yup! Thanks! |
Thanks for confirming. I'm on mobile right now but I'll add you sometime in the next few hours. |
Added you to the npm package. |
Summary: `eslint-plugin-prettify` merged into `eslint-plugin-prettier` (prettier/eslint-plugin-prettier#21) Reviewed By: matthewwithanm Differential Revision: D5080518 fbshipit-source-id: 05d568daaa44b189f82ea912b5d1fdedae07f367
As discussed in #17, eslint-plugin-prettify will merge into eslint-plugin-prettier. eslint-plugin-prettify diffs the original code against the prettier output, and reports fine grained issues, instead of invalidating the entire file.
This PR ports the code at zertosh/eslint-plugin-prettify@2fb5dfb, and adjusts it to conform to @not-an-aardvark's pre-existing code style. A few notes:
"fb"
- which sets preferred "Facebook style" (see the README).@format
if you used the magic"fb"
config. In this port, that's no longer the case (as requested by @kittens).no-styles
, which added a preprocessor that stripped style rules from the final result. That's not included in this PR, it'll be added in a followup PR.