Skip to content

Commit

Permalink
Fix jsx-closing-bracket-location fixer (fixes #573)
Browse files Browse the repository at this point in the history
  • Loading branch information
yannickcr committed Apr 25, 2016
1 parent 075864c commit c624783
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 12 deletions.
34 changes: 22 additions & 12 deletions lib/rules/jsx-closing-bracket-location.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,25 +142,35 @@ module.exports = function(context) {
};
}

var lastAttributeEndPos;
var lastAttributeStartPos;
/**
* Get an unique ID for a given JSXOpeningElement
*
* @param {ASTNode} node The AST node being checked.
* @returns {String} Unique ID (based on its range)
*/
function getOpeningElementId(node) {
return node.range.join(':');
}

var lastAttributeNode = {};

return {
JSXAttribute: function(node) {
lastAttributeEndPos = node.end;
lastAttributeStartPos = node.start;
lastAttributeNode[getOpeningElementId(node.parent)] = node;
},

JSXSpreadAttribute: function(node) {
lastAttributeNode[getOpeningElementId(node.parent)] = node;
},

'JSXOpeningElement:exit': function(node) {
var cachedLastAttributeEndPos = lastAttributeEndPos;
var cachedLastAttributeStartPos = lastAttributeStartPos;
var attributeNode = lastAttributeNode[getOpeningElementId(node)];
var cachedLastAttributeEndPos = attributeNode ? attributeNode.end : null;
var cachedLastAttributeStartPos = attributeNode ? attributeNode.start : null;
var expectedNextLine;
var tokens = getTokensLocations(node);
var expectedLocation = getExpectedLocation(tokens);

lastAttributeStartPos = null;
lastAttributeEndPos = null;

if (hasCorrectLocation(tokens, expectedLocation)) {
return;
}
Expand Down Expand Up @@ -188,8 +198,8 @@ module.exports = function(context) {
return fixer.replaceTextRange([cachedLastAttributeEndPos, node.end],
(expectedNextLine ? '\n' : '') + closingTag);
}
return fixer.replaceTextRange([node.name.loc.end.column + 1, node.end],
(expectedNextLine ? '\n' : '') + closingTag);
return fixer.replaceTextRange([node.name.range[1], node.end],
(expectedNextLine ? '\n' : ' ') + closingTag);
case 'after-props':
return fixer.replaceTextRange([cachedLastAttributeEndPos, node.end],
(expectedNextLine ? '\n' : '') + closingTag);
Expand All @@ -198,7 +208,7 @@ module.exports = function(context) {
return fixer.replaceTextRange([cachedLastAttributeEndPos, node.end],
'\n' + spaces.join(' ') + closingTag);
case 'tag-aligned':
var tagSpaces = new Array(node.start);
var tagSpaces = new Array(+correctColumn + 1);
return fixer.replaceTextRange([cachedLastAttributeEndPos, node.end],
'\n' + tagSpaces.join(' ') + closingTag);
case 'line-aligned':
Expand Down
103 changes: 103 additions & 0 deletions tests/lib/rules/jsx-closing-bracket-location.js
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,11 @@ ruleTester.run('jsx-closing-bracket-location', rule, {
' foo',
' ></App>'
].join('\n'),
output: [
'<App',
' foo',
'></App>'
].join('\n'),
options: [{location: 'tag-aligned'}],
parserOptions: parserOptions,
errors: [{
Expand All @@ -577,6 +582,11 @@ ruleTester.run('jsx-closing-bracket-location', rule, {
' foo',
' ></App>'
].join('\n'),
output: [
'<App',
' foo',
'></App>'
].join('\n'),
options: [{location: 'line-aligned'}],
parserOptions: parserOptions,
errors: [{
Expand All @@ -593,6 +603,15 @@ ruleTester.run('jsx-closing-bracket-location', rule, {
' />',
'</Provider>'
].join('\n'),
output: [
'<Provider ',
' store',
'>',
' <App ',
' foo',
' />',
'</Provider>'
].join('\n'),
options: [{selfClosing: 'props-aligned'}],
parserOptions: parserOptions,
errors: [{
Expand All @@ -610,6 +629,15 @@ ruleTester.run('jsx-closing-bracket-location', rule, {
' />', // <--
'</Provider>'
].join('\n'),
output: [
'<Provider',
' store',
' >',
' <App ',
' foo',
' />',
'</Provider>'
].join('\n'),
options: [{nonEmpty: 'props-aligned'}],
parserOptions: parserOptions,
errors: [{
Expand All @@ -625,6 +653,14 @@ ruleTester.run('jsx-closing-bracket-location', rule, {
' foo />',
'</Provider>'
].join('\n'),
output: [
'<Provider ',
' store',
'>',
' <App',
' foo />',
'</Provider>'
].join('\n'),
options: [{selfClosing: 'after-props'}],
parserOptions: parserOptions,
errors: [{
Expand All @@ -641,6 +677,14 @@ ruleTester.run('jsx-closing-bracket-location', rule, {
' />', // <--
'</Provider>'
].join('\n'),
output: [
'<Provider ',
' store>',
' <App ',
' foo',
' />', // <--
'</Provider>'
].join('\n'),
options: [{nonEmpty: 'after-props'}],
parserOptions: parserOptions,
errors: [{
Expand Down Expand Up @@ -688,5 +732,64 @@ ruleTester.run('jsx-closing-bracket-location', rule, {
line: 3,
column: 9
}]
}, {
code: [
'var x = (',
' <div',
' className="MyComponent"',
' {...props} />',
')'
].join('\n'),
output: [
'var x = (',
' <div',
' className="MyComponent"',
' {...props}',
' />',
')'
].join('\n'),
options: [{location: 'line-aligned'}],
parserOptions: parserOptions,
errors: [{
message: messageWithDetails(MESSAGE_LINE_ALIGNED, 3, true),
line: 4,
column: 16
}]
}, {
code: [
'var x = (',
' <Something',
' content={<Foo />} />',
')'
].join('\n'),
output: [
'var x = (',
' <Something',
' content={<Foo />}',
' />',
')'
].join('\n'),
options: [{location: 'line-aligned'}],
parserOptions: parserOptions,
errors: [{
message: messageWithDetails(MESSAGE_LINE_ALIGNED, 3, true),
line: 3,
column: 23
}]
}, {
code: [
'var x = (',
' <Something ',
' />',
')'
].join('\n'),
output: [
'var x = (',
' <Something />',
')'
].join('\n'),
options: [{location: 'line-aligned'}],
parserOptions: parserOptions,
errors: [MESSAGE_AFTER_TAG]
}]
});

0 comments on commit c624783

Please sign in to comment.