-
-
Notifications
You must be signed in to change notification settings - Fork 30
Update: add autofixing to test-case-property-ordering. (fixes #31) #32
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
Changes from 4 commits
237e612
5ee1c38
542d268
8cdb6d5
850e5c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,7 @@ module.exports = { | |
category: 'Tests', | ||
recommended: false, | ||
}, | ||
fixable: null, // or "code" or "whitespace" | ||
fixable: 'code', | ||
schema: [{ | ||
type: 'array', | ||
elements: { type: 'string' }, | ||
|
@@ -31,29 +31,59 @@ module.exports = { | |
// ---------------------------------------------------------------------- | ||
const message = 'The properties of a test case should be placed in a consistent order: [{{order}}].'; | ||
const order = context.options[0] || ['code', 'output', 'options', 'parserOptions', 'errors']; | ||
const sourceCode = context.getSourceCode(); | ||
|
||
return { | ||
Program (ast) { | ||
utils.getTestInfo(context, ast).forEach(testRun => { | ||
[testRun.valid, testRun.invalid].forEach(tests => { | ||
(tests || []).forEach(test => { | ||
const keys = (test.properties || []).map(utils.getKeyName); | ||
const properties = test.properties || []; | ||
const keyNames = properties.map(utils.getKeyName); | ||
|
||
for (let i = 0, lastChecked; i < keys.length; i++) { | ||
const current = order.indexOf(keys[i]); | ||
for (let i = 0, lastChecked; i < keyNames.length; i++) { | ||
const current = order.indexOf(keyNames[i]); | ||
|
||
// current < lastChecked to catch unordered; | ||
// and lastChecked === -1 to catch extra properties before. | ||
if (current > -1 && (current < lastChecked || lastChecked === -1)) { | ||
let orderMsg = order.filter(item => keys.indexOf(item) > -1); | ||
let orderMsg = order.filter(item => keyNames.indexOf(item) > -1); | ||
orderMsg = orderMsg.concat( | ||
lastChecked === -1 ? keys.filter(item => order.indexOf(item) === -1) : [] | ||
lastChecked === -1 ? keyNames.filter(item => order.indexOf(item) === -1) : [] | ||
); | ||
|
||
context.report({ | ||
node: test.properties[i], | ||
node: properties[i], | ||
message, | ||
data: { order: orderMsg.join(', ') }, | ||
fix (fixer) { | ||
const source = sourceCode.getText(); | ||
const last = properties[properties.length - 1]; | ||
// end loc to replace(including whitespaces). | ||
const finalEnd = sourceCode.getTokenAfter(last, token => token.value === '}' && token.type === 'Punctuator').range[0]; | ||
// reorder the properties and put in result array. | ||
const result = []; | ||
for (let j = 0; j < keyNames.length; j++) { | ||
const insertedIndex = orderMsg.indexOf(keyNames[j]); | ||
const propertyCode = sourceCode.getText(properties[j]); | ||
const propertyStart = properties[j].range[1]; | ||
const propertyEnd = j < properties.length - 1 ? properties[j + 1].range[0] : finalEnd; | ||
let trailing = source.slice(propertyStart, propertyEnd); | ||
|
||
// for last property, should check & add trailling commas. | ||
if (j === properties.length - 1 && sourceCode.getTokenAfter(last).value !== ',') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of having a special case for trailing commas, would it work to just set const finalEnd = sourceCode.getTokenAfter(last); |
||
trailing = ', ' + trailing; | ||
} | ||
result[insertedIndex] = propertyCode + trailing; | ||
} | ||
|
||
const start = properties[0].range[0]; | ||
|
||
return fixer.replaceTextRange( | ||
[start, finalEnd], | ||
result.join('') | ||
); | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be possible to use the new feature in ESLint 4.1.0 where you can return an array of autofixes? That way, this autofix would be very simple, because it wouldn't be necessary to deal with whitespace or trailing commas: fix(fixer) {
return orderMsg.map((key, index) => {
const propertyToInsert = test.properties[keyNames.indexOf(key)];
return fixer.replaceText(test.properties[index], sourceCode.getText(propertyToInsert));
});
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. awesome!!! |
||
}); | ||
} | ||
lastChecked = current; | ||
|
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 these variable names are confusing because
propertyStart
andpropertyEnd
describe the boundaries of the whitespace after the property, not the property itself. MaybewhitespaceStart
andwhitespaceEnd
would be better.