@@ -152,7 +152,8 @@ export let findCodeActionsInDiagnosticsMessage = ({
152
152
let codeActionEtractors = [
153
153
simpleTypeMismatches ,
154
154
didYouMeanAction ,
155
- addUndefinedRecordFields ,
155
+ addUndefinedRecordFieldsV10 ,
156
+ addUndefinedRecordFieldsV11 ,
156
157
simpleConversion ,
157
158
applyUncurried ,
158
159
simpleAddMissingCases ,
@@ -310,11 +311,107 @@ let wrapInSome: codeActionExtractor = ({
310
311
return false ;
311
312
} ;
312
313
314
+ let handleUndefinedRecordFieldsAction = ( {
315
+ recordFieldNames,
316
+ codeActions,
317
+ file,
318
+ range,
319
+ diagnostic,
320
+ } : {
321
+ recordFieldNames : string [ ] ;
322
+ codeActions : filesCodeActions ;
323
+ file : string ;
324
+ range : p . Range ;
325
+ diagnostic : p . Diagnostic ;
326
+ } ) => {
327
+ if ( recordFieldNames != null ) {
328
+ codeActions [ file ] = codeActions [ file ] || [ ] ;
329
+
330
+ // The formatter outputs trailing commas automatically if the record
331
+ // definition is on multiple lines, and no trailing comma if it's on a
332
+ // single line. We need to adapt to this so we don't accidentally
333
+ // insert an invalid comma.
334
+ let multilineRecordDefinitionBody = range . start . line !== range . end . line ;
335
+
336
+ // Let's build up the text we're going to insert.
337
+ let newText = "" ;
338
+
339
+ if ( multilineRecordDefinitionBody ) {
340
+ // If it's a multiline body, we know it looks like this:
341
+ // ```
342
+ // let someRecord = {
343
+ // atLeastOneExistingField: string,
344
+ // }
345
+ // ```
346
+ // We can figure out the formatting from the range the code action
347
+ // gives us. We'll insert to the direct left of the ending brace.
348
+
349
+ // The end char is the closing brace, and it's always going to be 2
350
+ // characters back from the record fields.
351
+ let paddingCharacters = multilineRecordDefinitionBody
352
+ ? range . end . character + 2
353
+ : 0 ;
354
+ let paddingContentRecordField = Array . from ( {
355
+ length : paddingCharacters ,
356
+ } ) . join ( " " ) ;
357
+ let paddingContentEndBrace = Array . from ( {
358
+ length : range . end . character ,
359
+ } ) . join ( " " ) ;
360
+
361
+ recordFieldNames . forEach ( ( fieldName , index ) => {
362
+ if ( index === 0 ) {
363
+ // This adds spacing from the ending brace up to the equivalent
364
+ // of the last record field name, needed for the first inserted
365
+ // record field name.
366
+ newText += " " ;
367
+ } else {
368
+ // The rest of the new record field names will start from a new
369
+ // line, so they need left padding all the way to the same level
370
+ // as the rest of the record fields.
371
+ newText += paddingContentRecordField ;
372
+ }
373
+
374
+ newText += `${ fieldName } : failwith("TODO"),\n` ;
375
+ } ) ;
376
+
377
+ // Let's put the end brace back where it was (we still have it to the direct right of us).
378
+ newText += `${ paddingContentEndBrace } ` ;
379
+ } else {
380
+ // A single line record definition body is a bit easier - we'll just add the new fields on the same line.
381
+ newText += ", " ;
382
+ newText += recordFieldNames
383
+ . map ( ( fieldName ) => `${ fieldName } : failwith("TODO")` )
384
+ . join ( ", " ) ;
385
+ }
386
+
387
+ let codeAction : p . CodeAction = {
388
+ title : `Add missing record fields` ,
389
+ edit : {
390
+ changes : {
391
+ [ file ] : insertBeforeEndingChar ( range , newText ) ,
392
+ } ,
393
+ } ,
394
+ diagnostics : [ diagnostic ] ,
395
+ kind : p . CodeActionKind . QuickFix ,
396
+ isPreferred : true ,
397
+ } ;
398
+
399
+ codeActions [ file ] . push ( {
400
+ range,
401
+ codeAction,
402
+ } ) ;
403
+
404
+ return true ;
405
+ }
406
+
407
+ return false ;
408
+ } ;
409
+
313
410
// This action handles when the compiler errors on certain fields of a record
314
411
// being undefined. We then offers an action that inserts all of the record
315
412
// fields, with an `assert false` dummy value. `assert false` is so applying the
316
413
// code action actually compiles.
317
- let addUndefinedRecordFields : codeActionExtractor = ( {
414
+ let addUndefinedRecordFieldsV10 : codeActionExtractor = ( {
318
415
array,
319
416
codeActions,
320
417
diagnostic,
@@ -335,85 +432,53 @@ let addUndefinedRecordFields: codeActionExtractor = ({
335
432
recordFieldNames . push ( ...line . trim ( ) . split ( " " ) ) ;
336
433
} ) ;
337
434
338
- if ( recordFieldNames != null ) {
339
- codeActions [ file ] = codeActions [ file ] || [ ] ;
435
+ return handleUndefinedRecordFieldsAction ( {
436
+ recordFieldNames,
437
+ codeActions,
438
+ diagnostic,
439
+ file,
440
+ range,
441
+ } ) ;
442
+ }
340
443
341
- // The formatter outputs trailing commas automatically if the record
342
- // definition is on multiple lines, and no trailing comma if it's on a
343
- // single line. We need to adapt to this so we don't accidentally
344
- // insert an invalid comma.
345
- let multilineRecordDefinitionBody = range . start . line !== range . end . line ;
346
-
347
- // Let's build up the text we're going to insert.
348
- let newText = "" ;
349
-
350
- if ( multilineRecordDefinitionBody ) {
351
- // If it's a multiline body, we know it looks like this:
352
- // ```
353
- // let someRecord = {
354
- // atLeastOneExistingField: string,
355
- // }
356
- // ```
357
- // We can figure out the formatting from the range the code action
358
- // gives us. We'll insert to the direct left of the ending brace.
359
-
360
- // The end char is the closing brace, and it's always going to be 2
361
- // characters back from the record fields.
362
- let paddingCharacters = multilineRecordDefinitionBody
363
- ? range . end . character + 2
364
- : 0 ;
365
- let paddingContentRecordField = Array . from ( {
366
- length : paddingCharacters ,
367
- } ) . join ( " " ) ;
368
- let paddingContentEndBrace = Array . from ( {
369
- length : range . end . character ,
370
- } ) . join ( " " ) ;
371
-
372
- recordFieldNames . forEach ( ( fieldName , index ) => {
373
- if ( index === 0 ) {
374
- // This adds spacing from the ending brace up to the equivalent
375
- // of the last record field name, needed for the first inserted
376
- // record field name.
377
- newText += " " ;
378
- } else {
379
- // The rest of the new record field names will start from a new
380
- // line, so they need left padding all the way to the same level
381
- // as the rest of the record fields.
382
- newText += paddingContentRecordField ;
383
- }
384
-
385
- newText += `${ fieldName } : assert false,\n` ;
386
- } ) ;
444
+ return false ;
445
+ } ;
387
446
388
- // Let's put the end brace back where it was (we still have it to the direct right of us).
389
- newText += `${ paddingContentEndBrace } ` ;
390
- } else {
391
- // A single line record definition body is a bit easier - we'll just add the new fields on the same line.
392
- newText += ", " ;
393
- newText += recordFieldNames
394
- . map ( ( fieldName ) => `${ fieldName } : assert false` )
395
- . join ( ", " ) ;
396
- }
447
+ let addUndefinedRecordFieldsV11 : codeActionExtractor = ( {
448
+ array,
449
+ codeActions,
450
+ diagnostic,
451
+ file,
452
+ index,
453
+ line,
454
+ range,
455
+ } ) => {
456
+ if ( line . startsWith ( "Some required record fields are missing:" ) ) {
457
+ let recordFieldNames = line
458
+ . trim ( )
459
+ . split ( "Some required record fields are missing: " ) [ 1 ]
460
+ ?. split ( " " ) ;
397
461
398
- let codeAction : p . CodeAction = {
399
- title : `Add missing record fields` ,
400
- edit : {
401
- changes : {
402
- [ file ] : insertBeforeEndingChar ( range , newText ) ,
403
- } ,
404
- } ,
405
- diagnostics : [ diagnostic ] ,
406
- kind : p . CodeActionKind . QuickFix ,
407
- isPreferred : true ,
408
- } ;
462
+ // This collects the rest of the fields if fields are printed on
463
+ // multiple lines.
464
+ let stop = false ;
465
+ array . slice ( index + 1 ) . forEach ( ( line ) => {
466
+ if ( stop ) return ;
409
467
410
- codeActions [ file ] . push ( {
411
- range,
412
- codeAction,
413
- } ) ;
468
+ recordFieldNames . push ( ...line . trim ( ) . split ( "." ) [ 0 ] . split ( " " ) ) ;
414
469
415
- return true ;
416
- }
470
+ if ( line . includes ( "." ) ) {
471
+ stop = true ;
472
+ }
473
+ } ) ;
474
+
475
+ return handleUndefinedRecordFieldsAction ( {
476
+ recordFieldNames,
477
+ codeActions,
478
+ diagnostic,
479
+ file,
480
+ range,
481
+ } ) ;
417
482
}
418
483
419
484
return false ;
0 commit comments