@@ -12,6 +12,20 @@ const astUtil = require('../util/ast');
1212const docsUrl = require ( '../util/docsUrl' ) ;
1313const lifecycleMethods = require ( '../util/lifecycleMethods' ) ;
1414
15+ function getText ( node ) {
16+ const params = node . value . params . map ( ( p ) => p . name ) ;
17+
18+ if ( node . type === 'Property' ) {
19+ return `: function(${ params . join ( ', ' ) } ) ` ;
20+ }
21+
22+ if ( node . type === 'ClassProperty' || node . type === 'PropertyDefinition' ) {
23+ return `(${ params . join ( ', ' ) } ) ` ;
24+ }
25+
26+ return null ;
27+ }
28+
1529module . exports = {
1630 meta : {
1731 docs : {
@@ -25,20 +39,6 @@ module.exports = {
2539 } ,
2640
2741 create : Components . detect ( ( context , components , utils ) => {
28- function getText ( node ) {
29- const params = node . value . params . map ( ( p ) => p . name ) ;
30-
31- if ( node . type === 'Property' ) {
32- return `: function(${ params . join ( ', ' ) } ) ` ;
33- }
34-
35- if ( node . type === 'ClassProperty' || node . type === 'PropertyDefinition' ) {
36- return `(${ params . join ( ', ' ) } ) ` ;
37- }
38-
39- return null ;
40- }
41-
4242 /**
4343 * @param {Array } properties list of component properties
4444 */
@@ -57,16 +57,63 @@ module.exports = {
5757 ) . indexOf ( propertyName ) > - 1 ;
5858
5959 if ( nodeType === 'ArrowFunctionExpression' && isLifecycleMethod ) {
60- const range = [ node . key . range [ 1 ] , node . value . body . range [ 0 ] ] ;
61- const text = getText ( node ) ;
60+ const body = node . value . body ;
61+ const isBlockBody = body . type === 'BlockStatement' ;
62+ const sourceCode = context . getSourceCode ( ) ;
63+
64+ let nextComment = [ ] ;
65+ let previousComment = [ ] ;
66+ let bodyRange ;
67+ if ( ! isBlockBody ) {
68+ const previousToken = sourceCode . getTokenBefore ( body ) ;
69+
70+ if ( sourceCode . getCommentsBefore ) {
71+ // eslint >=4.x
72+ previousComment = sourceCode . getCommentsBefore ( body ) ;
73+ } else {
74+ // eslint 3.x
75+ const potentialComment = sourceCode . getTokenBefore ( body , { includeComments : true } ) ;
76+ previousComment = previousToken === potentialComment ? [ ] : [ potentialComment ] ;
77+ }
78+
79+ if ( sourceCode . getCommentsAfter ) {
80+ // eslint >=4.x
81+ nextComment = sourceCode . getCommentsAfter ( body ) ;
82+ } else {
83+ // eslint 3.x
84+ const potentialComment = sourceCode . getTokenAfter ( body , { includeComments : true } ) ;
85+ const nextToken = sourceCode . getTokenAfter ( body ) ;
86+ nextComment = nextToken === potentialComment ? [ ] : [ potentialComment ] ;
87+ }
88+ bodyRange = [
89+ ( previousComment . length > 0 ? previousComment [ 0 ] : body ) . range [ 0 ] ,
90+ ( nextComment . length > 0 ? nextComment [ nextComment . length - 1 ] : body ) . range [ 1 ] ,
91+ ] ;
92+ }
93+ const headRange = [
94+ node . key . range [ 1 ] ,
95+ ( previousComment . length > 0 ? previousComment [ 0 ] : body ) . range [ 0 ] ,
96+ ] ;
6297
6398 context . report ( {
6499 node,
65100 message : '{{propertyName}} is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' ,
66101 data : {
67102 propertyName,
68103 } ,
69- fix : ( fixer ) => fixer . replaceTextRange ( range , text ) ,
104+ fix ( fixer ) {
105+ if ( ! sourceCode . getCommentsAfter ) {
106+ // eslint 3.x
107+ return isBlockBody && fixer . replaceTextRange ( headRange , getText ( node ) ) ;
108+ }
109+ return [ ] . concat (
110+ fixer . replaceTextRange ( headRange , getText ( node ) ) ,
111+ isBlockBody ? [ ] : fixer . replaceTextRange (
112+ bodyRange ,
113+ `{ return ${ previousComment . map ( ( x ) => sourceCode . getText ( x ) ) . join ( '' ) } ${ sourceCode . getText ( body ) } ${ nextComment . map ( ( x ) => sourceCode . getText ( x ) ) . join ( '' ) } ; }`
114+ )
115+ ) ;
116+ } ,
70117 } ) ;
71118 }
72119 } ) ;
0 commit comments