41
41
42
42
export const FlowSeverity = {
43
43
Error : 'error' ,
44
- Warning : 'warning' ,
44
+ Warning : 'warning'
45
45
} ;
46
46
47
47
type Pos = {
@@ -54,42 +54,47 @@ type Loc = {
54
54
end : Pos
55
55
} ;
56
56
57
- // Adapted from https://github.com/facebook/flow/blob/master/tsrc/flowResult.js
58
57
type FlowPos = {
59
58
line : number ,
60
59
column : number ,
61
60
offset : number
62
61
} ;
63
62
64
63
type FlowLoc = {
65
- source : ? string ,
64
+ source : string ,
66
65
start : FlowPos ,
67
66
end : FlowPos ,
68
67
type : 'SourceFile' | 'LibFile'
69
68
} ;
70
69
71
- type FlowMessage = {
72
- path : string ,
73
- descr : string ,
74
- type : 'Blame' | 'Comment' ,
75
- line : number ,
76
- endline : number ,
77
- loc ?: ?FlowLoc
70
+ type FlowSimpleMessage = {
71
+ kind : 'Code' | 'Text' ,
72
+ text : string
78
73
} ;
79
74
80
- type FlowError = {
81
- message : Array < FlowMessage > ,
82
- level ? : string ,
83
- operation ?: FlowMessage ,
84
- extra ?: Array < {
85
- message : Array < FlowMessage >
86
- } >
75
+ opaque type FlowReferenceID = string ;
76
+
77
+ type FlowReferenceMessage = {
78
+ kind : 'Reference' ,
79
+ referenceId : FlowReferenceID ,
80
+ message : FlowSimpleMessage [ ]
87
81
} ;
88
82
89
- function mainLocOfError ( error : FlowError ) : ?FlowLoc {
90
- const { operation, message } = error ;
91
- return ( operation && operation . loc ) || message [ 0 ] . loc ;
92
- }
83
+ type FlowMarkupMessage = FlowSimpleMessage | FlowReferenceMessage ;
84
+
85
+ type FlowReferenceLocs = {
86
+ [ referenceId : FlowReferenceID ] : FlowLoc
87
+ } ;
88
+
89
+ type FlowError = {
90
+ kind : 'infer' | 'lint' ,
91
+ level : 'error' | 'warning' ,
92
+ classic : boolean ,
93
+ primaryLoc : FlowLoc ,
94
+ rootLoc : FlowLoc | null ,
95
+ messageMarkup : FlowMarkupMessage [ ] ,
96
+ referenceLocs : FlowReferenceLocs
97
+ } ;
93
98
94
99
function fatalError ( message ) {
95
100
return [
@@ -102,39 +107,49 @@ function fatalError(message) {
102
107
}
103
108
104
109
function formatSeePath (
105
- message : FlowMessage ,
110
+ loc : FlowLoc ,
106
111
root : string ,
107
112
flowVersion : string
108
- ) {
109
- return message . loc && message . loc . type === 'LibFile'
113
+ ) : string {
114
+ return loc . type === 'LibFile'
110
115
? `https://github.com/facebook/flow/blob/v${ flowVersion } /lib/${ pathModule . basename (
111
- message . path
112
- ) } #L${ message . line } `
113
- : `.${ slash ( message . path . replace ( root , '' ) ) } :${ message . line } ` ;
116
+ loc . source
117
+ ) } #L${ loc . start . line } `
118
+ : `.${ slash ( loc . source . replace ( root , '' ) ) } :${ loc . start . line } ` ;
119
+ }
120
+
121
+ function formatMessage ( message : FlowSimpleMessage ) : string {
122
+ switch ( message . kind ) {
123
+ case 'Code' :
124
+ return `\`${ message . text } \`` ;
125
+ case 'Text' :
126
+ default : // In case new kinds are added in later Flow versions
127
+ return message . text ;
128
+ }
114
129
}
115
130
116
- function formatMessage (
117
- message : FlowMessage ,
118
- extras : FlowMessage [ ] ,
131
+ function formatMarkupMessage (
132
+ markupMessage : FlowMarkupMessage ,
133
+ errorLoc : FlowLoc ,
134
+ referenceLocs : FlowReferenceLocs ,
119
135
root : string ,
120
136
flowVersion : string ,
121
137
lineOffset : number
122
- ) {
123
- return message . descr . replace ( / ( \[ \d + \] ) / g, ( matchedStr , extraDescr ) => {
124
- const extraMessage = extras . find ( extra => extra . descr === extraDescr ) ;
138
+ ) : string {
139
+ if ( markupMessage . kind !== 'Reference' ) {
140
+ return formatMessage ( markupMessage ) ;
141
+ }
125
142
126
- if ( extraMessage === undefined ) {
127
- return matchedStr ;
128
- }
143
+ let messageStr = markupMessage . message . map ( formatMessage ) . join ( '' ) ;
144
+ const referenceLoc = referenceLocs [ markupMessage . referenceId ] ;
129
145
130
- if ( extraMessage . path !== message . path ) {
131
- return ` (see ${ formatSeePath ( extraMessage , root , flowVersion ) } )` ;
132
- }
146
+ if ( referenceLoc . source !== errorLoc . source ) {
147
+ messageStr += ` (see ${ formatSeePath ( referenceLoc , root , flowVersion ) } )` ;
148
+ } else if ( referenceLoc . start . line !== errorLoc . start . line ) {
149
+ messageStr += ` (see line ${ referenceLoc . start . line + lineOffset } )` ;
150
+ }
133
151
134
- return extraMessage . line === message . line
135
- ? '' // Avoid adding the "see line" message if it's on the same line
136
- : ` (see line ${ lineOffset + extraMessage . line } )` ;
137
- } ) ;
152
+ return messageStr ;
138
153
}
139
154
140
155
function getFlowBin ( ) {
@@ -157,15 +172,16 @@ function spawnFlow(
157
172
input : string ,
158
173
root : string ,
159
174
stopOnExit : boolean ,
160
- filepath : string
175
+ filepath : string ,
176
+ extraOptions ?: string [ ] = [ ]
161
177
) : string | boolean {
162
178
if ( ! input ) {
163
179
return true ;
164
180
}
165
181
166
182
const child = childProcess . spawnSync (
167
183
getFlowBin ( ) ,
168
- [ mode , '--json' , `--root=${ root } ` , filepath ] ,
184
+ [ mode , '--json' , `--root=${ root } ` , filepath , ... extraOptions ] ,
169
185
{
170
186
input,
171
187
encoding : 'utf-8'
@@ -207,7 +223,14 @@ export function collect(
207
223
filepath : string ,
208
224
programOffset : { line : number , column : number }
209
225
) : CollectOutput | boolean {
210
- const stdout = spawnFlow ( 'check-contents' , stdin , root , stopOnExit , filepath ) ;
226
+ const stdout = spawnFlow (
227
+ 'check-contents' ,
228
+ stdin ,
229
+ root ,
230
+ stopOnExit ,
231
+ filepath ,
232
+ [ '--json-version=2' ]
233
+ ) ;
211
234
212
235
if ( typeof stdout !== 'string' ) {
213
236
return stdout ;
@@ -229,71 +252,52 @@ export function collect(
229
252
: fatalError ( 'Flow returned invalid json' ) ;
230
253
}
231
254
232
- const fullFilepath = pathModule . resolve ( root , filepath ) ;
233
-
234
- // Loop through errors in the file
235
- const output = json . errors
236
- // Temporarily hide the 'inconsistent use of library definitions' issue
237
- . filter ( ( error : FlowError ) => {
238
- const mainLoc = mainLocOfError ( error ) ;
239
- const mainFile = mainLoc && mainLoc . source ;
240
- return (
241
- mainFile &&
242
- error . message [ 0 ] . descr &&
243
- ! error . message [ 0 ] . descr . includes ( 'inconsistent use of' ) &&
244
- pathModule . resolve ( root , mainFile ) === fullFilepath
245
- ) ;
246
- } )
247
- . map ( ( error : FlowError ) => {
248
- const { extra, level, message : [ messageObject ] } = error ;
249
- let message ;
250
-
251
- if ( extra !== undefined && extra . length > 0 ) {
252
- const extras = extra . map ( extraObj => extraObj . message [ 0 ] ) ; // Normalize extras
253
- message = formatMessage (
254
- messageObject ,
255
- extras ,
255
+ const output = json . errors . map ( ( error : FlowError ) => {
256
+ const { level, messageMarkup, primaryLoc : loc , referenceLocs } = error ;
257
+
258
+ const message = messageMarkup
259
+ . map ( markupMessage =>
260
+ formatMarkupMessage (
261
+ markupMessage ,
262
+ loc ,
263
+ referenceLocs ,
256
264
root ,
257
265
json . flowVersion ,
258
266
programOffset . line
259
- ) ;
260
- } else {
261
- message = messageObject . descr ;
267
+ )
268
+ )
269
+ . join ( '' ) ;
270
+
271
+ const newLoc = {
272
+ start : {
273
+ line : loc . start . line + programOffset . line ,
274
+ column :
275
+ loc . start . line === 0
276
+ ? loc . start . column + programOffset . column
277
+ : loc . start . column ,
278
+ offset : loc . start . offset
279
+ } ,
280
+ end : {
281
+ line : loc . end . line + programOffset . line ,
282
+ column :
283
+ loc . end . line === 0
284
+ ? loc . end . column + programOffset . column
285
+ : loc . end . column ,
286
+ offset : loc . end . offset
262
287
}
288
+ } ;
263
289
264
- const defaultPos = { line : 1 , column : 1 , offset : 0 } ;
265
- const loc = messageObject . loc || { start : defaultPos , end : defaultPos } ;
266
-
267
- const newLoc = {
268
- start : {
269
- line : loc . start . line + programOffset . line ,
270
- column :
271
- loc . start . line === 0
272
- ? loc . start . column + programOffset . column
273
- : loc . start . column ,
274
- offset : loc . start . offset
275
- } ,
276
- end : {
277
- line : loc . end . line + programOffset . line ,
278
- column :
279
- loc . end . line === 0
280
- ? loc . end . column + programOffset . column
281
- : loc . end . column ,
282
- offset : loc . end . offset
283
- }
284
- } ;
285
-
286
- return {
287
- ...( process . env . DEBUG_FLOWTYPE_ERRRORS === 'true' ? json : { } ) ,
288
- type : determineRuleType ( message ) ,
289
- level : level || FlowSeverity . Error ,
290
- message,
291
- path : messageObject . path ,
292
- start : newLoc . start . line ,
293
- end : newLoc . end . line ,
294
- loc : newLoc
295
- } ;
296
- } ) ;
290
+ return {
291
+ ...( process . env . DEBUG_FLOWTYPE_ERRRORS === 'true' ? json : { } ) ,
292
+ type : determineRuleType ( message ) ,
293
+ level : level || FlowSeverity . Error ,
294
+ message,
295
+ path : loc . source ,
296
+ start : newLoc . start . line ,
297
+ end : newLoc . end . line ,
298
+ loc : newLoc
299
+ } ;
300
+ } ) ;
297
301
298
302
return output ;
299
303
}
0 commit comments