@@ -20,6 +20,8 @@ module.exports = {
20
20
url : docsUrl ( 'sort-prop-types' )
21
21
} ,
22
22
23
+ fixable : 'code' ,
24
+
23
25
schema : [ {
24
26
type : 'object' ,
25
27
properties : {
@@ -71,6 +73,46 @@ module.exports = {
71
73
) ;
72
74
}
73
75
76
+ function getShapeProperties ( node ) {
77
+ return node . arguments && node . arguments [ 0 ] && node . arguments [ 0 ] . properties ;
78
+ }
79
+
80
+ function sorter ( a , b ) {
81
+ let aKey = getKey ( a ) ;
82
+ let bKey = getKey ( b ) ;
83
+ if ( requiredFirst ) {
84
+ if ( isRequiredProp ( a ) && ! isRequiredProp ( b ) ) {
85
+ return - 1 ;
86
+ }
87
+ if ( ! isRequiredProp ( a ) && isRequiredProp ( b ) ) {
88
+ return 1 ;
89
+ }
90
+ }
91
+
92
+ if ( callbacksLast ) {
93
+ if ( isCallbackPropName ( aKey ) && ! isCallbackPropName ( bKey ) ) {
94
+ return 1 ;
95
+ }
96
+ if ( ! isCallbackPropName ( aKey ) && isCallbackPropName ( bKey ) ) {
97
+ return - 1 ;
98
+ }
99
+ }
100
+
101
+ if ( ignoreCase ) {
102
+ aKey = aKey . toLowerCase ( ) ;
103
+ bKey = bKey . toLowerCase ( ) ;
104
+ }
105
+
106
+ if ( aKey < bKey ) {
107
+ return - 1 ;
108
+ }
109
+ if ( aKey > bKey ) {
110
+ return 1 ;
111
+ }
112
+ return 0 ;
113
+ }
114
+
115
+
74
116
/**
75
117
* Checks if propTypes declarations are sorted
76
118
* @param {Array } declarations The array of AST nodes being checked.
@@ -83,6 +125,48 @@ module.exports = {
83
125
return ;
84
126
}
85
127
128
+ function fix ( fixer ) {
129
+ function sortInSource ( allNodes , source ) {
130
+ const originalSource = source ;
131
+ const nodeGroups = allNodes . reduce ( ( acc , curr ) => {
132
+ if ( curr . type === 'ExperimentalSpreadProperty' || curr . type === 'SpreadElement' ) {
133
+ acc . push ( [ ] ) ;
134
+ } else {
135
+ acc [ acc . length - 1 ] . push ( curr ) ;
136
+ }
137
+ return acc ;
138
+ } , [ [ ] ] ) ;
139
+
140
+ nodeGroups . forEach ( nodes => {
141
+ const sortedAttributes = nodes . slice ( ) . sort ( sorter ) ;
142
+
143
+ for ( let i = nodes . length - 1 ; i >= 0 ; i -- ) {
144
+ const sortedAttr = sortedAttributes [ i ] ;
145
+ const attr = nodes [ i ] ;
146
+ let sortedAttrText = sourceCode . getText ( sortedAttr ) ;
147
+ if ( sortShapeProp && isShapeProp ( sortedAttr . value ) ) {
148
+ const shape = getShapeProperties ( sortedAttr . value ) ;
149
+ if ( shape ) {
150
+ const attrSource = sortInSource (
151
+ shape ,
152
+ originalSource
153
+ ) ;
154
+ sortedAttrText = attrSource . slice ( sortedAttr . range [ 0 ] , sortedAttr . range [ 1 ] ) ;
155
+ }
156
+ }
157
+ source = `${ source . slice ( 0 , attr . range [ 0 ] ) } ${ sortedAttrText } ${ source . slice ( attr . range [ 1 ] ) } ` ;
158
+ }
159
+ } ) ;
160
+ return source ;
161
+ }
162
+
163
+ const source = sortInSource ( declarations , context . getSourceCode ( ) . getText ( ) ) ;
164
+
165
+ const rangeStart = declarations [ 0 ] . range [ 0 ] ;
166
+ const rangeEnd = declarations [ declarations . length - 1 ] . range [ 1 ] ;
167
+ return fixer . replaceTextRange ( [ rangeStart , rangeEnd ] , source . slice ( rangeStart , rangeEnd ) ) ;
168
+ }
169
+
86
170
declarations . reduce ( ( prev , curr , idx , decls ) => {
87
171
if ( curr . type === 'ExperimentalSpreadProperty' || curr . type === 'SpreadElement' ) {
88
172
return decls [ idx + 1 ] ;
@@ -109,7 +193,8 @@ module.exports = {
109
193
// Encountered a non-required prop after a required prop
110
194
context . report ( {
111
195
node : curr ,
112
- message : 'Required prop types must be listed before all other prop types'
196
+ message : 'Required prop types must be listed before all other prop types' ,
197
+ fix
113
198
} ) ;
114
199
return curr ;
115
200
}
@@ -124,7 +209,8 @@ module.exports = {
124
209
// Encountered a non-callback prop after a callback prop
125
210
context . report ( {
126
211
node : prev ,
127
- message : 'Callback prop types must be listed after all other prop types'
212
+ message : 'Callback prop types must be listed after all other prop types' ,
213
+ fix
128
214
} ) ;
129
215
return prev ;
130
216
}
@@ -133,7 +219,8 @@ module.exports = {
133
219
if ( currentPropName < prevPropName ) {
134
220
context . report ( {
135
221
node : curr ,
136
- message : 'Prop types declarations should be sorted alphabetically'
222
+ message : 'Prop types declarations should be sorted alphabetically' ,
223
+ fix
137
224
} ) ;
138
225
return prev ;
139
226
}
@@ -166,7 +253,7 @@ module.exports = {
166
253
167
254
return {
168
255
CallExpression : function ( node ) {
169
- if ( ! sortShapeProp || ! isShapeProp ( node ) || ( ! node . arguments && ! node . arguments [ 0 ] ) ) {
256
+ if ( ! sortShapeProp || ! isShapeProp ( node ) || ! ( node . arguments && node . arguments [ 0 ] ) ) {
170
257
return ;
171
258
}
172
259
checkSorted ( node . arguments [ 0 ] . properties ) ;
0 commit comments