@@ -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