@@ -12,6 +12,20 @@ const astUtil = require('../util/ast');
12
12
const docsUrl = require ( '../util/docsUrl' ) ;
13
13
const lifecycleMethods = require ( '../util/lifecycleMethods' ) ;
14
14
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
+
15
29
module . exports = {
16
30
meta : {
17
31
docs : {
@@ -25,20 +39,6 @@ module.exports = {
25
39
} ,
26
40
27
41
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
-
42
42
/**
43
43
* @param {Array } properties list of component properties
44
44
*/
@@ -57,16 +57,63 @@ module.exports = {
57
57
) . indexOf ( propertyName ) > - 1 ;
58
58
59
59
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
+ ] ;
62
97
63
98
context . report ( {
64
99
node,
65
100
message : '{{propertyName}} is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' ,
66
101
data : {
67
102
propertyName,
68
103
} ,
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
+ } ,
70
117
} ) ;
71
118
}
72
119
} ) ;
0 commit comments