Skip to content

Commit

Permalink
fix: extend the autofix range in comma-dangle to ensure the last elem…
Browse files Browse the repository at this point in the history
…ent (#15669)

Fixes #15660
  • Loading branch information
mdjermanovic committed Mar 4, 2022
1 parent edb12e5 commit c178ce7
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 4 deletions.
28 changes: 24 additions & 4 deletions lib/rules/comma-dangle.js
Expand Up @@ -243,8 +243,18 @@ module.exports = {
node: lastItem,
loc: trailingToken.loc,
messageId: "unexpected",
fix(fixer) {
return fixer.remove(trailingToken);
*fix(fixer) {
yield fixer.remove(trailingToken);

/*
* Extend the range of the fix to include surrounding tokens to ensure
* that the element after which the comma is removed stays _last_.
* This intentionally makes conflicts in fix ranges with rules that may be
* adding or removing elements in the same autofix pass.
* https://github.com/eslint/eslint/issues/15660
*/
yield fixer.insertTextBefore(sourceCode.getTokenBefore(trailingToken), "");
yield fixer.insertTextAfter(sourceCode.getTokenAfter(trailingToken), "");
}
});
}
Expand Down Expand Up @@ -282,8 +292,18 @@ module.exports = {
end: astUtils.getNextLocation(sourceCode, trailingToken.loc.end)
},
messageId: "missing",
fix(fixer) {
return fixer.insertTextAfter(trailingToken, ",");
*fix(fixer) {
yield fixer.insertTextAfter(trailingToken, ",");

/*
* Extend the range of the fix to include surrounding tokens to ensure
* that the element after which the comma is inserted stays _last_.
* This intentionally makes conflicts in fix ranges with rules that may be
* adding or removing elements in the same autofix pass.
* https://github.com/eslint/eslint/issues/15660
*/
yield fixer.insertTextBefore(trailingToken, "");
yield fixer.insertTextAfter(sourceCode.getTokenAfter(trailingToken), "");
}
});
}
Expand Down
84 changes: 84 additions & 0 deletions tests/lib/rules/comma-dangle.js
Expand Up @@ -10,6 +10,7 @@
//------------------------------------------------------------------------------

const path = require("path"),
{ unIndent } = require("../../_utils"),
rule = require("../../../lib/rules/comma-dangle"),
{ RuleTester } = require("../../../lib/rule-tester");

Expand All @@ -35,6 +36,29 @@ function parser(name) {

const ruleTester = new RuleTester();

ruleTester.defineRule("add-named-import", {
meta: {
fixable: "code"
},
create(context) {
return {
ImportDeclaration(node) {
const sourceCode = context.getSourceCode();
const closingBrace = sourceCode.getLastToken(node, token => token.value === "}");
const addComma = sourceCode.getTokenBefore(closingBrace).value !== ",";

context.report({
message: "Add I18nManager.",
node,
fix(fixer) {
return fixer.insertTextBefore(closingBrace, `${addComma ? "," : ""}I18nManager`);
}
});
}
};
}
});

ruleTester.run("comma-dangle", rule, {
valid: [
"var foo = { bar: 'baz' }",
Expand Down Expand Up @@ -1766,6 +1790,66 @@ let d = 0;export {d,};
output: "foo(a)",
parserOptions: { ecmaVersion: 8 },
errors: [{ messageId: "unexpected" }]
},

// https://github.com/eslint/eslint/issues/15660
{
code: unIndent`
/*eslint add-named-import:1*/
import {
StyleSheet,
View,
TextInput,
ImageBackground,
Image,
TouchableOpacity,
SafeAreaView
} from 'react-native';
`,
output: unIndent`
/*eslint add-named-import:1*/
import {
StyleSheet,
View,
TextInput,
ImageBackground,
Image,
TouchableOpacity,
SafeAreaView,
} from 'react-native';
`,
options: [{ imports: "always-multiline" }],
parserOptions: { ecmaVersion: 6, sourceType: "module" },
errors: 2
},
{
code: unIndent`
/*eslint add-named-import:1*/
import {
StyleSheet,
View,
TextInput,
ImageBackground,
Image,
TouchableOpacity,
SafeAreaView,
} from 'react-native';
`,
output: unIndent`
/*eslint add-named-import:1*/
import {
StyleSheet,
View,
TextInput,
ImageBackground,
Image,
TouchableOpacity,
SafeAreaView
} from 'react-native';
`,
options: [{ imports: "never" }],
parserOptions: { ecmaVersion: 6, sourceType: "module" },
errors: 2
}
]
});

0 comments on commit c178ce7

Please sign in to comment.