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
Update: support multiple fixes in a report (fixes #7348) #8101
Conversation
@mysticatea, thanks for your PR! By analyzing the history of the files in this pull request, we identified @alberto, @nzakas and @vitorbal to be potential reviewers. |
LGTM |
2 similar comments
LGTM |
LGTM |
I will try to explain more details about this PR. The purpose of this PR is that it supports multiple fix objects per report, as keeping no breaking change. context.report({
node,
message,
fix(fixer) {
return [
fixer.insertTextBefore(node, "("),
fixer.insertTextAfter(node, ")")
];
}
}) There are changes in For example: /* eslint arrow-body-style: error */
const foo = () => {
return {a: 1}
} In this case, [ { "range": [ 56, 69 ], "text": "" },
{ "range": [ 69, 69 ], "text": "(" },
{ "range": [ 75, 75 ], "text": ")" },
{ "range": [ 75, 77 ], "text": "" } ] Then { "range": [ 56, 77 ], "text": "({a: 1})" } After that, it does existing autofix process if
[
{
"filePath":"C:\\Users\\t-nagashima.AD\\Documents\\GitHub\\eslint\\test.js",
"messages":[
{
"ruleId":"arrow-body-style",
"severity":2,
"message":"Unexpected block statement surrounding arrow body.",
"line":3,
"column":19,
"nodeType":"ArrowFunctionExpression",
"source":"const foo = () => {",
"fix":{
"range":[
56,
77
],
"text":"({a: 1})"
}
}
],
"errorCount":1,
"warningCount":0,
"source":"/* eslint arrow-body-style: error */\n\nconst foo = () => {\n return {a: 1}\n}\n"
}
] I want to investigate the way of no-merging and overlap detection improvement after this PR. (maybe it makes a breaking change) |
91963e5
to
d376127
Compare
LGTM |
d376127
to
6c64259
Compare
LGTM |
LGTM 👍 as always nicely done @mysticatea ... |
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 as far as I can tell, although I would love to be able to call keep
on a larger range than my fix in order to fix #8026.
@@ -61,6 +62,71 @@ const PASSTHROUGHS = [ | |||
//------------------------------------------------------------------------------ | |||
|
|||
/** | |||
* Compares items in a fixes array by range. | |||
* @param {Fix} a The first message. | |||
* @param {Fix} b The second message. |
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.
Should be "The first fix" and "The second fix"
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.
Oops, it's my copy/paste mistake. Thank you!
lib/rule-context.js
Outdated
let lastPos = start; | ||
|
||
for (const fix of fixes) { | ||
assert(fix.range[0] >= lastPos, "Fix objects must not be overlapped in a report."); |
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.
Requiring the ranges to be disjoint could make fixer.keep
a lot less useful, I think. In #8067 for the no-else-return
/no-useless-return
fix (#8026), I intentionally want to keep all of an outer node (the function containing the fix) while modifying something inside of it.
With this API, I guess what I'd do is compute fixStart
and fixEnd
and yield that fix, then yield keepRange(functionStart, fixStart)
and keepRange(fixEnd, functionEnd)
. That isn't so bad, I suppose, but seems a lot more clunky than saying "preserve the function and replace this text within the function".
One possible solution, if we're ok with it being a little magical, is to allow fixes to be completely contained within other fixes and always use the most specific one. Or maybe the fixes could be applied in order in a reasonable way, with later ones taking precedence.
(Although I recognize that there's maybe some disagreement about whether keep
should be used that way in my use case anyway.)
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.
Honestly, I think it's rare case if we need locking the outer node.
In no-else-return
case, it needs locking only the previous if
block.
In no-useless-return
case, it needs locking only after the return
statement.
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.
That makes sense, I can see how the fixes for no-else-return
and no-useless-return
would work in that case. (I'm still a little unsure about how to properly reason about the implementation of no-useless-return
, but it certainly seems easy and correct to call keepRange
from the end of the fix to the end of the function.)
I think locking the outer node can be nice because it's safer and makes the rule simpler, but I can see the argument that it's usually not necessary. And if the long-term plan is to allow a distinction between "fixing" and "locking" operations, then I think it shouldn't be hard to allow the two types to overlap, which would address my concerns there.
* @param {SourceCode} sourceCode The source code object to get the text between fixes. | ||
* @returns {void} | ||
*/ | ||
function mergeFixes(fixes, sourceCode) { |
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.
Worth noting that mergeFixes
could be made an internal utility instead of a public API if there's any controversy around this API addition.
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.
As public API, this is simple enhancement; the fix
functions support for an iterable object as their return value.
There are 2 topics here.
- To not modify comments, this feature would be helpful.
- To avoid autofix conflict, this feature would be helpful.
As I mentioned in this post, currently we have a pain to remain comments. The purpose of the fix
functions is "to modify code", but we have to focus on "to not modify code" mainly in order to not remove comments. This enhancement would resolve the problem. I think this is valuable for plugin ecosystem as well.
In addition, we can address locked ranges in the same mechanism.
In fact, this is the 1st step of my plan.
Because the report of linting has fix
properties which have a fix object, this PR is merging the multiple fixes before it makes the report for now. I have to avoid a breaking change about the fix
property (the shape of the report also are public API).
However, I have a plan (though it's not accepted yet) to change the fix
property to fixes
property that has an array of fix objects, so this mergeFixes
function would be removed in future. It implies that fixing process can distinguish between fixing ranges and locking ranges. I expect it to allow us smarter conflict check.
6c64259
to
0c18661
Compare
LGTM |
I updated this PR; now we can use |
@mysticatea I will support this enhancement with one change request. I really would like to avoid generators in our code base. While I understand that they can be very helpful, but I feel like majority of JS community doesn't really understand them and they significantly increasing bar of entry. I would like to avoid both generators and |
Thank you, @ilyavolodin ! Hmm, though I don't think generators make hurdles. |
Marking this accepted as we have the support and @mysticatea will champion. |
Technically, I think we would need TSC consensus for this because it's a core change. I like the general idea of allowing multiple fixes, but I'm not sure we should add |
I'm sorry for late. I will get the time to work on this within this week end.
|
0c18661
to
d25c542
Compare
LGTM |
d25c542
to
5dba973
Compare
I think the autofixing and (I'm also planning to review this PR later, assuming it's not going into the release today.) |
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 mostly looks good but I think there is a bug if a fix range contains -1
as an index.
lib/rule-context.js
Outdated
for (const fix of fixes) { | ||
assert(fix.range[0] >= lastPos, "Fix objects must not be overlapped in a report."); | ||
|
||
text += originalText.slice(lastPos, fix.range[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.
Some fix ranges, like unicode-bom
, use -1
as the start to indicate that the fix should replace the BOM. I think that will cause a bug here because .slice(-1)
will take the last character in the string.
LGTM |
LGTM |
Thank you for the review.
|
lib/rule-context.js
Outdated
|
||
for (const fix of fixes) { | ||
assert(fix.range[0] >= lastPos, "Fix objects must not be overlapped in a report."); | ||
assert(fix.range[0] >= lastPos || fix.range[0] < 0, "Fix objects must not be overlapped in a report."); |
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 this fail to detect a conflict if two fixes have ranges [-1, 0]
and [-1, 5]
? It seems like the assertion will always pass for fixes that start at -1
.
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.
Good catch.
LGTM |
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.
LGTM, thanks!
lib/rule-context.js
Outdated
@@ -92,18 +92,18 @@ function mergeFixes(fixes, sourceCode) { | |||
const start = fixes[0].range[0]; | |||
const end = fixes[fixes.length - 1].range[1]; | |||
let text = ""; | |||
let lastPos = Math.max(0, start); | |||
let lastPos = Number.MIN_SAFE_INTEGER; |
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.
Maybe it would be better to use -Infinity
in case someone uses extremely small numbers in fix ranges for whatever reason, but I think it's probably fine -- files usually don't have 253 BOMs. 😄
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.
Yeah 😄
I expect that integer variables are faster by compiler optimization.
1817: Update eslint to the latest version 🚀 r=jniles ## Version **4.1.0** of [eslint](https://github.com/eslint/eslint) just got published. <table> <tr> <th align=left> Dependency </td> <td> eslint </td> </tr> <tr> <th align=left> Current Version </td> <td> 3.19.0 </td> </tr> <tr> <th align=left> Type </td> <td> devDependency </td> </tr> </table> The version **4.1.0** is **not covered** by your **current version range**. Without accepting this pull request your project will work just like it did before. There might be a bunch of new features, fixes and perf improvements that the maintainers worked on for you though. I recommend you look into these changes and try to get onto the latest version of eslint. Given that you have a decent test suite, a passing build is a strong indicator that you can take advantage of these changes by merging the proposed change into your project. Otherwise this branch is a great starting point for you to work on the update. --- <details> <summary>Release Notes</summary> <strong>v4.1.0</strong> <ul> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/e8f1362ab640c883a5d296e951308fab22073e7f" class="commit-link"><tt>e8f1362</tt></a> Docs: Remove wrong descriptions in <code>padded-block</code> rule (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8783" class="issue-link js-issue-link" data-url="eslint/eslint#8783" data-id="237771100" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8783</a>) (Plusb Preco)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/291a78302c1d5d402c6582b3f4cc836e61fde787" class="commit-link"><tt>291a783</tt></a> Update: <code>enforceForArrowConditionals</code> to <code>no-extra-parens</code> (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/6196" class="issue-link js-issue-link" data-url="eslint/eslint#6196" data-id="155067290" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#6196</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8439" class="issue-link js-issue-link" data-url="eslint/eslint#8439" data-id="220697521" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8439</a>) (Evilebot Tnawi)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/a21dd32c46f95bc232a67929c224824692f94b70" class="commit-link"><tt>a21dd32</tt></a> New: Add <code>overrides</code>/<code>files</code> options for glob-based config (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/3611" class="issue-link js-issue-link" data-url="eslint/eslint#3611" data-id="104053558" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#3611</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8081" class="issue-link js-issue-link" data-url="eslint/eslint#8081" data-id="207675247" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8081</a>) (Sylvan Mably)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/879688ce96f80aa0692f732759c6f67a0c36c4c3" class="commit-link"><tt>879688c</tt></a> Update: Add ignoreComments option to no-trailing-spaces (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8061" class="issue-link js-issue-link" data-url="eslint/eslint#8061" data-id="206865549" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8061</a>) (Jake Roussel)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/b58ae2e6d6bd4662b549ca5c0472943055a74df8" class="commit-link"><tt>b58ae2e</tt></a> Chore: Only instantiate fileEntryCache when cache flage set (perf) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8763" class="issue-link js-issue-link" data-url="eslint/eslint#8763" data-id="236756225" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8763</a>) (Gyandeep Singh)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/98512881f1fc2417011247931fa089d987ee8cc6" class="commit-link"><tt>9851288</tt></a> Update: fix indent errors on multiline destructure (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8729" class="issue-link js-issue-link" data-url="eslint/eslint#8729" data-id="235733166" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8729</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8756" class="issue-link js-issue-link" data-url="eslint/eslint#8756" data-id="236673913" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8756</a>) (Victor Hom)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/3608f06c2a412587c2d05dec0297803b25f3e630" class="commit-link"><tt>3608f06</tt></a> Docs: Increase visibility of code of conduct (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8758" class="issue-link js-issue-link" data-url="eslint/eslint#8758" data-id="236687424" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8758</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8764" class="issue-link js-issue-link" data-url="eslint/eslint#8764" data-id="236758243" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8764</a>) (Kai Cataldo)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/673a58bc8420075ba698cee6762e17322a5263c3" class="commit-link"><tt>673a58b</tt></a> Update: support multiple fixes in a report (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/7348" class="issue-link js-issue-link" data-url="eslint/eslint#7348" data-id="182620143" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#7348</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8101" class="issue-link js-issue-link" data-url="eslint/eslint#8101" data-id="208681921" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8101</a>) (Toru Nagashima)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/7a1bc3893ab55d0ab16ccf4b7a62c85329ab4007" class="commit-link"><tt>7a1bc38</tt></a> Fix: don't pass default parserOptions to custom parsers (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8744" class="issue-link js-issue-link" data-url="eslint/eslint#8744" data-id="236336414" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8744</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8745" class="issue-link js-issue-link" data-url="eslint/eslint#8745" data-id="236373829" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8745</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/c5b405280409698d14b62cbf3c87b7cf6cf71391" class="commit-link"><tt>c5b4052</tt></a> Chore: enable computed-property-spacing on ESLint codebase (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8760" class="issue-link js-issue-link" data-url="eslint/eslint#8760" data-id="236699991" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8760</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/3419f6446e205d79d9db77f6c176b9167d1fd8a7" class="commit-link"><tt>3419f64</tt></a> Docs: describe how to use formatters on the formatter demo page (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8754" class="issue-link js-issue-link" data-url="eslint/eslint#8754" data-id="236645523" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8754</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/a3ff8f21106cf8eca55978d4b3e053973f5e1bf2" class="commit-link"><tt>a3ff8f2</tt></a> Chore: combine tests in tests/lib/eslint.js and tests/lib/linter.js (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8746" class="issue-link js-issue-link" data-url="eslint/eslint#8746" data-id="236375849" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8746</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/b7cc1e6fe995d52e581fcb2b1a44e37a18680e90" class="commit-link"><tt>b7cc1e6</tt></a> Fix: Space-infix-ops should ignore type annotations in TypeScript (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8341" class="issue-link js-issue-link" data-url="eslint/eslint#8341" data-id="217102387" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8341</a>) (Reyad Attiyat)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/46e73eea69abc2ba80bb1397c6779b8789dbd385" class="commit-link"><tt>46e73ee</tt></a> Fix: eslint --init installs wrong dependencies of popular styles (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/7338" class="issue-link js-issue-link" data-url="eslint/eslint#7338" data-id="182134634" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#7338</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8713" class="issue-link js-issue-link" data-url="eslint/eslint#8713" data-id="235217725" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8713</a>) (Toru Nagashima)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/a82361b65699653761436a2e9acc7f485c827ca0" class="commit-link"><tt>a82361b</tt></a> Chore: Prevent package-lock.json files from being created (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8742" class="issue-link js-issue-link" data-url="eslint/eslint#8742" data-id="236292937" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8742</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8747" class="issue-link js-issue-link" data-url="eslint/eslint#8747" data-id="236397701" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8747</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/5f81a68a3904a559764872e3f0c7453865a6c6dc" class="commit-link"><tt>5f81a68</tt></a> New: Add eslintIgnore support to package.json (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8458" class="issue-link js-issue-link" data-url="eslint/eslint#8458" data-id="221689525" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8458</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8690" class="issue-link js-issue-link" data-url="eslint/eslint#8690" data-id="233757916" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8690</a>) (Victor Hom)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/b5a70b4e8c20dc1ea3e31137706fc20da339f379" class="commit-link"><tt>b5a70b4</tt></a> Update: fix multiline binary operator/parentheses indentation (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8719" class="issue-link js-issue-link" data-url="eslint/eslint#8719" data-id="235421314" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8719</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/ab8b0167bdaf3b8851eab3fbc2769f2bdd71677b" class="commit-link"><tt>ab8b016</tt></a> Update: fix MemberExpression indentation with "off" option (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8721" class="issue-link js-issue-link" data-url="eslint/eslint#8721" data-id="235434741" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8721</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8724" class="issue-link js-issue-link" data-url="eslint/eslint#8724" data-id="235459105" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8724</a>) (Teddy Katz)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/eb5d12c15a32084907f1c58bcbec721b5008495d" class="commit-link"><tt>eb5d12c</tt></a> Update: Add Fixer method to Linter API (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8631" class="issue-link js-issue-link" data-url="eslint/eslint#8631" data-id="230242473" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8631</a>) (Gyandeep Singh)</li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/26a2daab311c8c59942c52f436d380a195db2bd4" class="commit-link"><tt>26a2daa</tt></a> Chore: Cache fs reads in ignored-paths (fixes <a href="https://urls.greenkeeper.io/eslint/eslint/issues/8363" class="issue-link js-issue-link" data-url="eslint/eslint#8363" data-id="218136776" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8363</a>) (<a href="https://urls.greenkeeper.io/eslint/eslint/pull/8706" class="issue-link js-issue-link" data-url="eslint/eslint#8706" data-id="235004396" data-error-text="Failed to load issue title" data-permission-text="Issue title is private">#8706</a>) (Victor Hom)</li> </ul> </details> <details> <summary>Commits</summary> <p>The new version differs by 141 commits.</p> <ul> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/7d9e3beeb58c1ee71d53dfcfd3e3b0721dd79b46"><code>7d9e3be</code></a> <code>4.1.0</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/e727b7bdfcfb0564aabd713b32364e6f4afcfeec"><code>e727b7b</code></a> <code>Build: changelog update for 4.1.0</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/e8f1362ab640c883a5d296e951308fab22073e7f"><code>e8f1362</code></a> <code>Docs: Remove wrong descriptions in <code>padded-block</code> rule (#8783)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/291a78302c1d5d402c6582b3f4cc836e61fde787"><code>291a783</code></a> <code>Update: <code>enforceForArrowConditionals</code> to <code>no-extra-parens</code> (fixes #6196) (#8439)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/a21dd32c46f95bc232a67929c224824692f94b70"><code>a21dd32</code></a> <code>New: Add <code>overrides</code>/<code>files</code> options for glob-based config (fixes #3611) (#8081)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/879688ce96f80aa0692f732759c6f67a0c36c4c3"><code>879688c</code></a> <code>Update: Add ignoreComments option to no-trailing-spaces (#8061)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/b58ae2e6d6bd4662b549ca5c0472943055a74df8"><code>b58ae2e</code></a> <code>Chore: Only instantiate fileEntryCache when cache flage set (perf) (#8763)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/98512881f1fc2417011247931fa089d987ee8cc6"><code>9851288</code></a> <code>Update: fix indent errors on multiline destructure (fixes #8729) (#8756)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/3608f06c2a412587c2d05dec0297803b25f3e630"><code>3608f06</code></a> <code>Docs: Increase visibility of code of conduct (fixes #8758) (#8764)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/673a58bc8420075ba698cee6762e17322a5263c3"><code>673a58b</code></a> <code>Update: support multiple fixes in a report (fixes #7348) (#8101)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/7a1bc3893ab55d0ab16ccf4b7a62c85329ab4007"><code>7a1bc38</code></a> <code>Fix: don't pass default parserOptions to custom parsers (fixes #8744) (#8745)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/c5b405280409698d14b62cbf3c87b7cf6cf71391"><code>c5b4052</code></a> <code>Chore: enable computed-property-spacing on ESLint codebase (#8760)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/3419f6446e205d79d9db77f6c176b9167d1fd8a7"><code>3419f64</code></a> <code>Docs: describe how to use formatters on the formatter demo page (#8754)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/a3ff8f21106cf8eca55978d4b3e053973f5e1bf2"><code>a3ff8f2</code></a> <code>Chore: combine tests in tests/lib/eslint.js and tests/lib/linter.js (#8746)</code></li> <li><a href="https://urls.greenkeeper.io/eslint/eslint/commit/b7cc1e6fe995d52e581fcb2b1a44e37a18680e90"><code>b7cc1e6</code></a> <code>Fix: Space-infix-ops should ignore type annotations in TypeScript (#8341)</code></li> </ul> <p>There are 141 commits in total.</p> <p>See the <a href="https://urls.greenkeeper.io/eslint/eslint/compare/421aab44a9c167c82210bed52f68cf990b7edbea...7d9e3beeb58c1ee71d53dfcfd3e3b0721dd79b46">full diff</a></p> </details> <details> <summary>Not sure how things should work exactly?</summary> There is a collection of [frequently asked questions](https://greenkeeper.io/faq.html) and of course you may always [ask my humans](https://github.com/greenkeeperio/greenkeeper/issues/new). </details> --- Your [Greenkeeper](https://greenkeeper.io) Bot 🌴
What is the purpose of this pull request? (put an "X" next to item)
[X] Add something to the core
Fixes #7348.
What changes did you make? (Give an overview)
This PR adds the ability to handle multiple fixes for each report. The
fix
methods can return an iterable object, includes arrays.Those fixes are merged to one internally, so this does not change about the result of ESLint; each message has one
fix
property as same as the current behavior. This is not a breaking change.Pros:
fix
functions.Cons:
This PR includes 2 examples.
One is about
arrow-body-style
. The rule had a super complexfix
function.Before:
After:
.
I think the "After" is more readable. Because "Before" had to focus on the operation of the text which we want to not change mainly. On the other hand, "After" focuses on the operation of the text (token) that we want to change mainly. I think this is a huge difference.
Another one is
semi
. This is an example about to control conflictions of autofix.After:
In addition, This PR adds some APIs.
sourceCode.commentsExistBetween(left, right)
returnstrue
if comments exist between theleft
and theright
. Otherwise it returnsfalse
. Since we frequently use this check to avoid removing comments by autofix, it would be useful.fixer.keep(nodeOrToken)
andfixer.keepRange(range)
returns a fix object which does not change code. Those would allow us to control conflictions of autofix, utilizing the mechanism that overlapped fixes are not applied at the same time.Is there anything you'd like reviewers to focus on?
Direction. The original issue is not accepted yet, but I want to advance this feature. Currently, we have to focus on the text which we want to not change to keep comments when we implement autofix. This feature would allow us to focus on the text which we want to change.
I'm a champion for this.