66'use strict' ;
77
88const propName = require ( 'jsx-ast-utils/propName' ) ;
9+ //const astUtils = require(".node_modules\eslint\lib\rules\utils\ast-utils.js");
910const includes = require ( 'array-includes' ) ;
1011const docsUrl = require ( '../util/docsUrl' ) ;
1112const jsxUtil = require ( '../util/jsx' ) ;
@@ -28,7 +29,7 @@ const messages = {
2829 listIsEmpty : 'A customized reserved first list must not be empty' ,
2930 listReservedPropsFirst : 'Reserved props must be listed before all other props' ,
3031 listCallbacksLast : 'Callbacks must be listed after all other props' ,
31- listShorthandFirst : 'Shorthand props must be listed before all other props' ,
32+ listShorthandFirst : 'S horthand props must be listed before all other props' ,
3233 listShorthandLast : 'Shorthand props must be listed after all other props' ,
3334 listMultilineFirst : 'Multiline props must be listed before all other props' ,
3435 listMultilineLast : 'Multiline props must be listed after all other props' ,
@@ -46,6 +47,12 @@ function isReservedPropName(name, list) {
4647 return list . indexOf ( name ) >= 0 ;
4748}
4849
50+ function sorttoend ( node ) {
51+ if ( attributemap . get ( node ) && attributemap . get ( node ) [ 1 ] ) {
52+ return true
53+ }
54+ }
55+
4956function contextCompare ( a , b , options ) {
5057 let aProp = propName ( a ) ;
5158 let bProp = propName ( b ) ;
@@ -98,6 +105,17 @@ function contextCompare(a, b, options) {
98105 return 0 ;
99106 }
100107
108+ if ( options . commentbetween ) {
109+ const asorttoend = sorttoend ( a ) ;
110+ const bsorttoend = sorttoend ( b ) ;
111+ if ( asorttoend && ! bsorttoend ) {
112+ return 1 ;
113+ }
114+ if ( ! asorttoend && bsorttoend ) {
115+ return - 1 ;
116+ }
117+ }
118+
101119 const actualLocale = options . locale === 'auto' ? undefined : options . locale ;
102120
103121 if ( options . ignoreCase ) {
@@ -120,24 +138,67 @@ function contextCompare(a, b, options) {
120138 * @param {Array<JSXSpreadAttribute|JSXAttribute> } attributes
121139 * @return {Array<Array<JSXAttribute>> }
122140 */
123- function getGroupsOfSortableAttributes ( attributes ) {
141+
142+ const attributemap = new WeakMap ( )
143+ // attributemap = [endrange, true||false if comment inbetween nodes exists, it needs to be sorted to end ]
144+ function getGroupsOfSortableAttributes ( attributes , context ) {
124145 const sortableAttributeGroups = [ ] ;
146+ const sourceCode = context . getSourceCode ( ) ;
147+
125148 let groupCount = 0 ;
126149 for ( let i = 0 ; i < attributes . length ; i ++ ) {
150+ const attribute = attributes [ i ] ;
151+ const nextattribute = attributes [ i + 1 ] ;
152+ const attributeline = attribute . loc . start . line ;
153+ const comment = sourceCode . getCommentsAfter ( attribute ) ;
127154 const lastAttr = attributes [ i - 1 ] ;
155+ function addtoSortableAttributeGroups ( ) { sortableAttributeGroups [ groupCount - 1 ] . push ( attribute ) } ;
128156 // If we have no groups or if the last attribute was JSXSpreadAttribute
129157 // then we start a new group. Append attributes to the group until we
130158 // come across another JSXSpreadAttribute or exhaust the array.
131159 if (
132160 ! lastAttr
133161 || ( lastAttr . type === 'JSXSpreadAttribute'
134- && attributes [ i ] . type !== 'JSXSpreadAttribute' )
162+ && attribute . type !== 'JSXSpreadAttribute' )
135163 ) {
136164 groupCount += 1 ;
137165 sortableAttributeGroups [ groupCount - 1 ] = [ ] ;
138166 }
139- if ( attributes [ i ] . type !== 'JSXSpreadAttribute' ) {
140- sortableAttributeGroups [ groupCount - 1 ] . push ( attributes [ i ] ) ;
167+ if ( attribute . type !== 'JSXSpreadAttribute' ) {
168+ if ( comment . length > 0 ) {
169+ const commentline = comment [ 0 ] . loc . start . line
170+ if ( attributeline + 1 == commentline && comment . length == 1 && nextattribute ) {
171+ attributemap . set ( attribute , [ nextattribute . range [ 1 ] , true ] )
172+ addtoSortableAttributeGroups ( )
173+ i ++
174+ continue
175+ }
176+ if ( attributeline == commentline && comment . length == 1 ) {
177+ if ( comment [ 0 ] . type == 'Block' ) {
178+ attributemap . set ( attribute , [ nextattribute . range [ 1 ] , true ] )
179+ addtoSortableAttributeGroups ( )
180+ i ++
181+ continue
182+ }
183+ attributemap . set ( attribute , [ comment [ 0 ] . range [ 1 ] , false ] )
184+ addtoSortableAttributeGroups ( )
185+ }
186+ if ( comment . length > 1 ) {
187+ if ( attributeline + 1 == comment [ 1 ] . loc . start . line && nextattribute ) {
188+ const commentnextattribute = sourceCode . getCommentsAfter ( nextattribute ) ;
189+ attributemap . set ( attribute , [ nextattribute . range [ 1 ] , true ] )
190+ if ( commentnextattribute . length == 1 && nextattribute . loc . start . line == commentnextattribute [ 0 ] . loc . start . line ) {
191+ attributemap . set ( attribute , [ commentnextattribute [ 0 ] . range [ 1 ] , true ] )
192+ }
193+ addtoSortableAttributeGroups ( )
194+ i ++
195+ continue
196+ }
197+ }
198+ } else {
199+ attributemap . set ( attribute , [ attribute . range [ 1 ] , false ] )
200+ addtoSortableAttributeGroups ( )
201+ }
141202 }
142203 }
143204 return sortableAttributeGroups ;
@@ -155,6 +216,7 @@ const generateFixerFunction = (node, context, reservedList) => {
155216 const noSortAlphabetically = configuration . noSortAlphabetically || false ;
156217 const reservedFirst = configuration . reservedFirst || false ;
157218 const locale = configuration . locale || 'auto' ;
219+ const commentbetween = configuration . commentbetween || true ;
158220
159221 // Sort props according to the context. Only supports ignoreCase.
160222 // Since we cannot safely move JSXSpreadAttribute (due to potential variable overrides),
@@ -169,23 +231,24 @@ const generateFixerFunction = (node, context, reservedList) => {
169231 reservedFirst,
170232 reservedList,
171233 locale,
234+ commentbetween,
172235 } ;
173- const sortableAttributeGroups = getGroupsOfSortableAttributes ( attributes ) ;
236+ const sortableAttributeGroups = getGroupsOfSortableAttributes ( attributes , context ) ;
174237 const sortedAttributeGroups = sortableAttributeGroups
175238 . slice ( 0 )
176- . map ( ( group ) => group . slice ( 0 ) . sort ( ( a , b ) => contextCompare ( a , b , options ) ) ) ;
239+ . map ( ( group ) => group . slice ( 0 ) . sort ( ( a , b ) => contextCompare ( a , b , options ) ) ) ;
177240
178241 return function fixFunction ( fixer ) {
179242 const fixers = [ ] ;
180243 let source = sourceCode . getText ( ) ;
181244
182- // Replace each unsorted attribute with the sorted one.
183245 sortableAttributeGroups . forEach ( ( sortableGroup , ii ) => {
184246 sortableGroup . forEach ( ( attr , jj ) => {
185247 const sortedAttr = sortedAttributeGroups [ ii ] [ jj ] ;
186- const sortedAttrText = sourceCode . getText ( sortedAttr ) ;
248+ const sortedAttrText = source . substring ( sortedAttr . range [ 0 ] , attributemap . get ( sortedAttr ) [ 0 ] )
249+ const attrrangeEnd = attributemap . get ( attr ) [ 0 ]
187250 fixers . push ( {
188- range : [ attr . range [ 0 ] , attr . range [ 1 ] ] ,
251+ range : [ attr . range [ 0 ] , attrrangeEnd ] ,
189252 text : sortedAttrText ,
190253 } ) ;
191254 } ) ;
@@ -194,7 +257,7 @@ const generateFixerFunction = (node, context, reservedList) => {
194257 fixers . sort ( ( a , b ) => b . range [ 0 ] - a . range [ 0 ] ) ;
195258
196259 const rangeStart = fixers [ fixers . length - 1 ] . range [ 0 ] ;
197- const rangeEnd = fixers [ 0 ] . range [ 1 ] ;
260+ const rangeEnd = fixers [ 0 ] . range [ 1 ] ;
198261
199262 fixers . forEach ( ( fix ) => {
200263 source = `${ source . substr ( 0 , fix . range [ 0 ] ) } ${ fix . text } ${ source . substr ( fix . range [ 1 ] ) } ` ;
@@ -262,10 +325,11 @@ function reportNodeAttribute(nodeAttribute, errorType, node, context, reservedLi
262325 errors . push ( errorType ) ;
263326
264327 reportedNodeAttributes . set ( nodeAttribute , errors ) ;
265-
328+
266329 report ( context , messages [ errorType ] , errorType , {
267330 node : nodeAttribute . name ,
268331 fix : generateFixerFunction ( node , context , reservedList ) ,
332+
269333 } ) ;
270334}
271335
0 commit comments