Skip to content

Commit e9fb52d

Browse files
committed
Revert "[Fix] jsx-indent with tabs (fixes jsx-eslint#1057)"
This reverts commit 6e5f688. Conflicts: lib/rules/jsx-indent.js tests/lib/rules/jsx-indent.js
1 parent 5b75162 commit e9fb52d

File tree

3 files changed

+86
-289
lines changed

3 files changed

+86
-289
lines changed

docs/rules/jsx-indent.md

-62
Original file line numberDiff line numberDiff line change
@@ -77,68 +77,6 @@ The following patterns are not warnings:
7777
</App>
7878
```
7979

80-
#### indentLogicalExpressions
81-
82-
```js
83-
...
84-
"react/jsx-indent": [<enabled>, 'tab'|<number>, {indentLogicalExpressions: true}]
85-
...
86-
```
87-
88-
By default this is set to false. When enabled, an additional indentation is required when the JSX is the right of a LogicalExpression
89-
90-
The following patterns are considered warnings:
91-
92-
```jsx
93-
// 2 spaces indentation with indentLogicalExpressions as false
94-
// [2, 2, {indentLogicalExpressions: false}]
95-
<App>
96-
{
97-
condition &&
98-
<Container>
99-
<Child></Child>
100-
</Container>
101-
}
102-
</App>
103-
104-
// 2 spaces indentation with indentLogicalExpressions as true
105-
// [2, 2, {indentLogicalExpressions: true}]
106-
<App>
107-
{
108-
condition &&
109-
<Container>
110-
<Child></Child>
111-
</Container>
112-
}
113-
</App>
114-
```
115-
116-
The following patterns are not warnings:
117-
118-
```jsx
119-
// 2 spaces indentation with indentLogicalExpressions as true
120-
// [2, 2, {indentLogicalExpressions: true}]
121-
<App>
122-
{
123-
condition &&
124-
<Container>
125-
<Child></Child>
126-
</Container>
127-
}
128-
</App>
129-
130-
// 2 spaces indentation with indentLogicalExpressions as false
131-
// [2, 2, {indentLogicalExpressions: false}]
132-
<App>
133-
{
134-
condition &&
135-
<Container>
136-
<Child></Child>
137-
</Container>
138-
}
139-
</App>
140-
```
141-
14280
## When not to use
14381

14482
If you are not using JSX then you can disable this rule.

lib/rules/jsx-indent.js

+60-150
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,6 @@ module.exports = {
4646
}, {
4747
type: 'integer'
4848
}]
49-
}, {
50-
type: 'object',
51-
properties: {
52-
indentLogicalExpressions: {
53-
type: 'boolean'
54-
}
55-
},
56-
additionalProperties: false
5749
}]
5850
},
5951

@@ -64,7 +56,6 @@ module.exports = {
6456
var extraColumnStart = 0;
6557
var indentType = 'space';
6658
var indentSize = 4;
67-
var indentLogicalExpressions = false;
6859

6960
var sourceCode = context.getSourceCode();
7061

@@ -76,25 +67,24 @@ module.exports = {
7667
indentSize = context.options[0];
7768
indentType = 'space';
7869
}
79-
if (context.options[1]) {
80-
indentLogicalExpressions = context.options[1].indentLogicalExpressions || false;
81-
}
8270
}
8371

8472
var indentChar = indentType === 'space' ? ' ' : '\t';
8573

8674
/**
8775
* Responsible for fixing the indentation issue fix
88-
* @param {Boolean} rangeToReplace is used to specify the range
89-
* to replace with the correct indentation.
76+
* @param {ASTNode} node Node violating the indent rule
9077
* @param {Number} needed Expected indentation character count
9178
* @returns {Function} function to be executed by the fixer
9279
* @private
9380
*/
94-
function getFixerFunction(rangeToReplace, needed) {
81+
function getFixerFunction(node, needed) {
9582
return function(fixer) {
9683
var indent = Array(needed + 1).join(indentChar);
97-
return fixer.replaceTextRange(rangeToReplace, indent);
84+
return fixer.replaceTextRange(
85+
[node.start - node.loc.start.column, node.start],
86+
indent
87+
);
9888
};
9989
}
10090

@@ -103,38 +93,46 @@ module.exports = {
10393
* @param {ASTNode} node Node violating the indent rule
10494
* @param {Number} needed Expected indentation character count
10595
* @param {Number} gotten Indentation character count in the actual node/code
106-
* @param {Array} rangeToReplace is used in the fixer.
107-
* Defaults to the indent of the start of the node
108-
* @param {Object} loc Error line and column location (defaults to node.loc
96+
* @param {Object} loc Error line and column location
10997
*/
110-
function report(node, needed, gotten, rangeToReplace, loc) {
98+
function report(node, needed, gotten, loc) {
11199
var msgContext = {
112100
needed: needed,
113101
type: indentType,
114102
characters: needed === 1 ? 'character' : 'characters',
115103
gotten: gotten
116104
};
117-
rangeToReplace = rangeToReplace || [node.start - node.loc.start.column, node.start];
118105

119-
context.report({
120-
node: node,
121-
loc: loc || node.loc,
122-
message: MESSAGE,
123-
data: msgContext,
124-
fix: getFixerFunction(rangeToReplace, needed)
125-
});
106+
if (loc) {
107+
context.report({
108+
node: node,
109+
loc: loc,
110+
message: MESSAGE,
111+
data: msgContext,
112+
fix: getFixerFunction(node, needed)
113+
});
114+
} else {
115+
context.report({
116+
node: node,
117+
message: MESSAGE,
118+
data: msgContext,
119+
fix: getFixerFunction(node, needed)
120+
});
121+
}
126122
}
127123

128124
/**
129-
* Get the indentation (of the proper indentType) that exists in the source
130-
* @param {String} src the source string
131-
* @param {Boolean} byLastLine whether the line checked should be the last
132-
* Defaults to the first line
133-
* @param {Boolean} excludeCommas whether to skip commas in the check
134-
* Defaults to false
135-
* @return {Number} the indentation of the indentType that exists on the line
125+
* Get node indent
126+
* @param {ASTNode} node Node to examine
127+
* @param {Boolean} byLastLine get indent of node's last line
128+
* @param {Boolean} excludeCommas skip comma on start of line
129+
* @return {Number} Indent
136130
*/
137-
function getIndentFromString(src, byLastLine, excludeCommas) {
131+
function getNodeIndent(node, byLastLine, excludeCommas) {
132+
byLastLine = byLastLine || false;
133+
excludeCommas = excludeCommas || false;
134+
135+
var src = sourceCode.getText(node, node.loc.start.column + extraColumnStart);
138136
var lines = src.split('\n');
139137
if (byLastLine) {
140138
src = lines[lines.length - 1];
@@ -156,24 +154,7 @@ module.exports = {
156154
}
157155

158156
/**
159-
* Get node indent
160-
* @param {ASTNode} node Node to examine
161-
* @param {Boolean} byLastLine get indent of node's last line
162-
* @param {Boolean} excludeCommas skip comma on start of line
163-
* @return {Number} Indent
164-
*/
165-
function getNodeIndent(node, byLastLine, excludeCommas) {
166-
byLastLine = byLastLine || false;
167-
excludeCommas = excludeCommas || false;
168-
169-
var src = sourceCode.getText(node, node.loc.start.column + extraColumnStart);
170-
171-
return getIndentFromString(src, byLastLine, excludeCommas);
172-
}
173-
174-
/**
175-
* Checks if the node is the first in its own start line. By default it looks by start line.
176-
* One exception is closing tags with preceeding whitespace
157+
* Checks node is the first in its own start line. By default it looks by start line.
177158
* @param {ASTNode} node The node to check
178159
* @return {Boolean} true if its the first in the its start line
179160
*/
@@ -184,9 +165,8 @@ module.exports = {
184165
} while (token.type === 'JSXText' && /^\s*$/.test(token.value));
185166
var startLine = node.loc.start.line;
186167
var endLine = token ? token.loc.end.line : -1;
187-
var whitespaceOnly = token ? /\n\s*$/.test(token.value) : false;
188168

189-
return startLine !== endLine || whitespaceOnly;
169+
return startLine !== endLine;
190170
}
191171

192172
/**
@@ -238,83 +218,41 @@ module.exports = {
238218
}
239219
}
240220

241-
/**
242-
* Checks the end of the tag (>) to determine whether it's on its own line
243-
* If so, it verifies the indentation is correct and reports if it is not
244-
* @param {ASTNode} node The node to check
245-
* @param {Number} startIndent The indentation of the start of the tag
246-
*/
247-
function checkTagEndIndent(node, startIndent) {
248-
var source = sourceCode.getText(node);
249-
var isTagEndOnOwnLine = /\n\s*\/?>$/.exec(source);
250-
if (isTagEndOnOwnLine) {
251-
var endIndent = getIndentFromString(source, true, false);
252-
if (endIndent !== startIndent) {
253-
var rangeToReplace = [node.end - node.loc.end.column, node.end - 1];
254-
report(node, startIndent, endIndent, rangeToReplace);
255-
}
256-
}
257-
}
258-
259-
/**
260-
* Gets what the JSXOpeningElement's indentation should be
261-
* @param {ASTNode} node The JSXOpeningElement
262-
* @return {Number} the number of indentation characters it should have
263-
*/
264-
function getOpeningElementIndent(node) {
265-
var prevToken = sourceCode.getTokenBefore(node);
266-
if (!prevToken) {
267-
return 0;
268-
}
269-
if (prevToken.type === 'JSXText' || prevToken.type === 'Punctuator' && prevToken.value === ',') {
270-
// Use the parent in a list or an array
271-
prevToken = sourceCode.getNodeByRangeIndex(prevToken.start);
272-
prevToken = prevToken.type === 'Literal' ? prevToken.parent : prevToken;
273-
} else if (prevToken.type === 'Punctuator' && prevToken.value === ':') {
274-
// Use the first non-punctuator token in a conditional expression
275-
do {
276-
prevToken = sourceCode.getTokenBefore(prevToken);
277-
} while (prevToken.type === 'Punctuator');
278-
prevToken = sourceCode.getNodeByRangeIndex(prevToken.range[0]);
279-
280-
while (prevToken.parent && prevToken.parent.type !== 'ConditionalExpression') {
281-
prevToken = prevToken.parent;
282-
}
283-
}
284-
prevToken = prevToken.type === 'JSXExpressionContainer' ? prevToken.expression : prevToken;
285-
286-
var parentElementIndent = getNodeIndent(prevToken);
287-
if (prevToken.type === 'JSXElement' && (!prevToken.parent || prevToken.parent.type !== 'LogicalExpression')) {
288-
parentElementIndent = getOpeningElementIndent(prevToken.openingElement);
289-
}
290-
291-
if (isRightInLogicalExp(node) && indentLogicalExpressions) {
292-
parentElementIndent += indentSize;
293-
}
294-
295-
var indent = (
296-
prevToken.loc.start.line === node.loc.start.line ||
297-
isRightInLogicalExp(node) ||
298-
isAlternateInConditionalExp(node)
299-
) ? 0 : indentSize;
300-
return parentElementIndent + indent;
301-
}
302-
303221
return {
304222
JSXOpeningElement: function(node) {
305223
var prevToken = sourceCode.getTokenBefore(node);
306224
if (!prevToken) {
307225
return;
308226
}
309-
var startIndent = getOpeningElementIndent(node);
310-
checkNodesIndent(node, startIndent);
311-
checkTagEndIndent(node, startIndent);
227+
// Use the parent in a list or an array
228+
if (prevToken.type === 'JSXText' || prevToken.type === 'Punctuator' && prevToken.value === ',') {
229+
prevToken = sourceCode.getNodeByRangeIndex(prevToken.start);
230+
prevToken = prevToken.type === 'Literal' ? prevToken.parent : prevToken;
231+
// Use the first non-punctuator token in a conditional expression
232+
} else if (prevToken.type === 'Punctuator' && prevToken.value === ':') {
233+
do {
234+
prevToken = sourceCode.getTokenBefore(prevToken);
235+
} while (prevToken.type === 'Punctuator');
236+
prevToken = sourceCode.getNodeByRangeIndex(prevToken.range[0]);
237+
while (prevToken.parent && prevToken.parent.type !== 'ConditionalExpression') {
238+
prevToken = prevToken.parent;
239+
}
240+
}
241+
prevToken = prevToken.type === 'JSXExpressionContainer' ? prevToken.expression : prevToken;
242+
243+
var parentElementIndent = getNodeIndent(prevToken);
244+
var indent = (
245+
prevToken.loc.start.line === node.loc.start.line ||
246+
isRightInLogicalExp(node) ||
247+
isAlternateInConditionalExp(node)
248+
) ? 0 : indentSize;
249+
checkNodesIndent(node, parentElementIndent + indent);
312250
},
313251
JSXClosingElement: function(node) {
314252
if (!node.parent) {
315253
return;
316254
}
317-
var peerElementIndent = getOpeningElementIndent(node.parent.openingElement);
255+
var peerElementIndent = getNodeIndent(node.parent.openingElement);
318256
checkNodesIndent(node, peerElementIndent);
319257
},
320258
JSXExpressionContainer: function(node) {
@@ -323,34 +261,6 @@ module.exports = {
323261
}
324262
var parentNodeIndent = getNodeIndent(node.parent);
325263
checkNodesIndent(node, parentNodeIndent + indentSize);
326-
},
327-
Literal: function(node) {
328-
if (!node.parent || node.parent.type !== 'JSXElement' || node.loc.start.line === node.parent.loc.start.line) {
329-
return;
330-
}
331-
var parentElementIndent = getOpeningElementIndent(node.parent.openingElement);
332-
var expectedIndent = parentElementIndent + indentSize;
333-
var source = sourceCode.getText(node);
334-
var lines = source.split('\n');
335-
var currentIndex = 0;
336-
lines.forEach(function(line, lineNumber) {
337-
if (line.trim()) {
338-
var lineIndent = getIndentFromString(line);
339-
if (lineIndent !== expectedIndent) {
340-
var lineStart = source.indexOf(line, currentIndex);
341-
var lineIndentStart = line.search(/\S/);
342-
var lineIndentEnd = lineStart + lineIndentStart;
343-
var rangeToReplace = [node.start + lineStart, node.start + lineIndentEnd];
344-
var locLine = lineNumber + node.loc.start.line;
345-
var loc = {
346-
start: {line: locLine, column: lineIndentStart},
347-
end: {line: locLine, column: lineIndentEnd}
348-
};
349-
report(node, expectedIndent, lineIndent, rangeToReplace, loc);
350-
}
351-
}
352-
currentIndex += line.length;
353-
});
354264
}
355265
};
356266

0 commit comments

Comments
 (0)