33
44// https://github.com/eslint/eslint/blob/091e52ae1ca408f3e668f394c14d214c9ce806e6/lib/shared/types.js#L11
55// https://github.com/eslint/eslint/blob/82669fa66670a00988db5b1d10fe8f3bf30be84e/lib/shared/config-validator.js#L40
6- function convertSeverity ( s ) {
6+ function convertSeverity ( s ) {
77 if ( s === 0 ) { // off
8- return 'INFO' ;
8+ return 'INFO'
99 } else if ( s === 1 ) {
10- return 'WARNING' ;
10+ return 'WARNING'
1111 } else if ( s === 2 ) {
12- return 'ERROR' ;
12+ return 'ERROR'
1313 }
14- return 'UNKNOWN_SEVERITY' ;
14+ return 'UNKNOWN_SEVERITY'
1515}
1616
17- function isHighSurrogate ( ch ) {
18- return 0xD800 <= ch && ch < 0xDC00 ;
17+ function isHighSurrogate ( ch ) {
18+ return ch >= 0xD800 && ch < 0xDC00
1919}
2020
21- function isLowSurrogate ( ch ) {
22- return 0xDC00 <= ch && ch < 0xE000 ;
21+ function isLowSurrogate ( ch ) {
22+ return ch >= 0xDC00 && ch < 0xE000
2323}
2424
25- function utf8length ( str ) {
26- let length = 0 ;
25+ function utf8length ( str ) {
26+ let length = 0
2727 for ( let i = 0 ; i < str . length ; i ++ ) {
28- const ch = str . charCodeAt ( i ) ;
28+ const ch = str . charCodeAt ( i )
2929 if ( isHighSurrogate ( ch ) ) {
30- i ++ ;
31- length += 4 ;
30+ i ++
31+ length += 4
3232 if ( i >= str . length || ! isLowSurrogate ( str . charCodeAt ( i ) ) ) {
33- throw new Error ( " invalid surrogate character" ) ;
33+ throw new Error ( ' invalid surrogate character' )
3434 }
3535 } else if ( isLowSurrogate ( ch ) ) {
36- throw new Error ( " invalid surrogate character" ) ;
36+ throw new Error ( ' invalid surrogate character' )
3737 } else if ( ch < 0x80 ) {
38- length ++ ;
38+ length ++
3939 } else if ( ch < 0x0800 ) {
40- length += 2 ;
40+ length += 2
4141 } else {
42- length += 3 ;
42+ length += 3
4343 }
4444 }
45- return length ;
45+ return length
4646}
4747
48- function positionFromUTF16CodeUnitOffset ( offset , text ) {
49- const lines = text . split ( '\n' ) ;
50- let lnum = 1 ;
51- let column = 0 ;
52- let lengthSoFar = 0 ;
48+ function positionFromUTF16CodeUnitOffset ( offset , text ) {
49+ const lines = text . split ( '\n' )
50+ let lnum = 1
51+ let column = 0
52+ let lengthSoFar = 0
5353 for ( const line of lines ) {
5454 if ( offset <= lengthSoFar + line . length ) {
55- const lineText = line . slice ( 0 , offset - lengthSoFar ) ;
55+ const lineText = line . slice ( 0 , offset - lengthSoFar )
5656 // +1 because eslint offset is a bit weird and will append text right
5757 // after the offset.
58- column = utf8length ( lineText ) + 1 ;
59- break ;
58+ column = utf8length ( lineText ) + 1
59+ break
6060 }
61- lengthSoFar += line . length + 1 ; // +1 for line-break.
62- lnum ++ ;
61+ lengthSoFar += line . length + 1 // +1 for line-break.
62+ lnum ++
6363 }
64- return { line : lnum , column : column } ;
64+ return { line : lnum , column }
6565}
6666
6767// How to get UTF-8 column from UTF-16 code unit column.
@@ -89,49 +89,64 @@ function positionFromUTF16CodeUnitOffset(offset, text) {
8989// 1. Extract the line text until the column (exclusive): "haya🐶"
9090// 2. Count length of the extracted line text in UTF-8: utf8length("haya🐶") = 8
9191// 3. +1 to the length to get the UTF-8 column: 9
92- function positionFromLineAndUTF16CodeUnitOffsetColumn ( line , column , sourceLines ) {
93- let col = 0 ;
94- if ( sourceLines . length >= line ) {
95- // 1. Extract the line text until the column (exclusive)
96- const lineText = sourceLines [ line - 1 ] . slice ( 0 , column - 1 ) ;
97- // 2&3. Count length of the extracted line text in UTF-8 and +1.
98- col = utf8length ( lineText ) + 1 ;
92+ function positionFromLineAndUTF16CodeUnitOffsetColumn ( line , column , sourceLines ) {
93+ let col = 0
94+ if ( ! sourceLines || ! Array . isArray ( sourceLines ) ) {
95+ console . warn ( '[eslint-formatter-rdjson] sourceLines is missing or invalid:' , { line, column } )
96+ return { line, column : col }
9997 }
100- return { line : line , column : col } ;
98+
99+ if ( sourceLines . length < line ) {
100+ console . warn ( '[eslint-formatter-rdjson] Line number exceeds sourceLines length:' , { line, sourceLines : sourceLines . length } )
101+ return { line, column : col }
102+ }
103+
104+ const sourceLine = sourceLines [ line - 1 ]
105+ if ( ! sourceLine ) {
106+ console . warn ( '[eslint-formatter-rdjson] Source line is undefined:' , { line } )
107+ return { line, column : col }
108+ }
109+
110+ // 1. Extract the line text until the column (exclusive)
111+ const lineText = sourceLine . slice ( 0 , column - 1 )
112+ // 2&3. Count length of the extracted line text in UTF-8 and +1.
113+ col = utf8length ( lineText ) + 1
114+
115+ return { line, column : col }
101116}
102117
103- function commonSuffixLength ( str1 , str2 ) {
104- let i = 0 ;
105- let seenSurrogate = false ;
118+ function commonSuffixLength ( str1 , str2 ) {
119+ let i = 0
120+ let seenSurrogate = false
106121 for ( i = 0 ; i < str1 . length && i < str2 . length ; ++ i ) {
107- const ch1 = str1 . charCodeAt ( str1 . length - ( i + 1 ) ) ;
108- const ch2 = str2 . charCodeAt ( str2 . length - ( i + 1 ) ) ;
122+ const ch1 = str1 . charCodeAt ( str1 . length - ( i + 1 ) )
123+ const ch2 = str2 . charCodeAt ( str2 . length - ( i + 1 ) )
109124 if ( ch1 !== ch2 ) {
110125 if ( seenSurrogate ) {
111126 if ( ! isHighSurrogate ( ch1 ) || ! isHighSurrogate ( ch2 ) ) {
112- throw new Error ( " invalid surrogate character" ) ;
127+ throw new Error ( ' invalid surrogate character' )
113128 }
114129 // i is now between a low surrogate and a high surrogate.
115130 // we need to remove the low surrogate from the common suffix
116131 // to avoid breaking surrogate pairs.
117- i -- ;
132+ i --
118133 }
119- break ;
134+ break
120135 }
121- seenSurrogate = isLowSurrogate ( ch1 ) ;
136+ seenSurrogate = isLowSurrogate ( ch1 )
122137 }
123- return i ;
138+ return i
124139}
125140
126- function buildMinimumSuggestion ( fix , source ) {
127- const l = commonSuffixLength ( fix . text , source . slice ( fix . range [ 0 ] , fix . range [ 1 ] ) ) ;
141+ function buildMinimumSuggestion ( fix , source ) {
142+ const l = commonSuffixLength ( fix . text , source . slice ( fix . range [ 0 ] , fix . range [ 1 ] ) )
128143 return {
129144 range : {
130145 start : positionFromUTF16CodeUnitOffset ( fix . range [ 0 ] , source ) ,
131146 end : positionFromUTF16CodeUnitOffset ( fix . range [ 1 ] - l , source )
132147 } ,
133148 text : fix . text . slice ( 0 , fix . text . length - l )
134- } ;
149+ }
135150}
136151
137152module . exports = function ( results , data ) {
@@ -141,12 +156,12 @@ module.exports = function (results, data) {
141156 url : 'https://eslint.org/'
142157 } ,
143158 diagnostics : [ ]
144- } ;
159+ }
145160
146161 results . forEach ( result => {
147- const filePath = result . filePath ;
148- const source = result . source ;
149- const sourceLines = source ? source . split ( '\n' ) : [ ] ;
162+ const filePath = result . filePath
163+ const source = result . source
164+ const sourceLines = source ? source . split ( '\n' ) : [ ]
150165 result . messages . forEach ( msg => {
151166 const diagnostic = {
152167 message : msg . message ,
@@ -162,19 +177,19 @@ module.exports = function (results, data) {
162177 url : ( data . rulesMeta [ msg . ruleId ] && data . rulesMeta [ msg . ruleId ] . docs ? data . rulesMeta [ msg . ruleId ] . docs . url : '' )
163178 } ,
164179 original_output : JSON . stringify ( msg )
165- } ;
180+ }
166181
167182 // the end of the range is optional
168183 if ( msg . endLine && msg . endColumn ) {
169184 diagnostic . location . range . end = positionFromLineAndUTF16CodeUnitOffsetColumn ( msg . endLine , msg . endColumn , sourceLines )
170185 }
171186
172187 if ( msg . fix ) {
173- diagnostic . suggestions = [ buildMinimumSuggestion ( msg . fix , source ) ] ;
188+ diagnostic . suggestions = [ buildMinimumSuggestion ( msg . fix , source ) ]
174189 }
175190
176- rdjson . diagnostics . push ( diagnostic ) ;
177- } ) ;
178- } ) ;
179- return JSON . stringify ( rdjson ) ;
180- } ;
191+ rdjson . diagnostics . push ( diagnostic )
192+ } )
193+ } )
194+ return JSON . stringify ( rdjson )
195+ }
0 commit comments