@@ -313,169 +313,175 @@ let parseFormatStringInternal
313
313
and parseSpecifier acc ( i , fragLine , fragCol ) fragments =
314
314
let startFragCol = fragCol
315
315
let fragCol = fragCol+ 1
316
- let i = i+ 1
317
- if i >= len then failwith ( FSComp.SR.forMissingFormatSpecifier())
318
- let info = newInfo()
319
-
320
- let oldI = i
321
- let posi , i = Parsing.position fmt i
322
- let fragCol = fragCol + i - oldI
323
-
324
- let oldI = i
325
- let i = Parsing.flags info fmt i
326
- let fragCol = fragCol + i - oldI
327
-
328
- let oldI = i
329
- let widthArg ,( widthValue , ( precisionArg , i )) = Parsing.widthAndPrecision info fmt i
330
- let fragCol = fragCol + i - oldI
331
-
332
- if i >= len then failwith ( FSComp.SR.forBadPrecision())
333
-
334
- let acc = if precisionArg then ( Option.map ((+) 1 ) posi, g.int_ ty) :: acc else acc
335
-
336
- let acc = if widthArg then ( Option.map ((+) 1 ) posi, g.int_ ty) :: acc else acc
337
-
338
- let checkOtherFlags c =
339
- if info.precision then failwith ( FSComp.SR.forFormatDoesntSupportPrecision( c.ToString()))
340
- if info.addZeros then failwith ( FSComp.SR.forDoesNotSupportZeroFlag( c.ToString()))
341
- match info.numPrefixIfPos with
342
- | Some n -> failwith ( FSComp.SR.forDoesNotSupportPrefixFlag( c.ToString(), n.ToString()))
343
- | None -> ()
344
-
345
- let skipPossibleInterpolationHole pos = Parsing.skipPossibleInterpolationHole isInterpolated isFormattableString fmt pos
346
-
347
- // Implicitly typed holes in interpolated strings are translated to '... %P(...)...' in the
348
- // type checker. They should always have '(...)' after for format string.
349
- let requireAndSkipInterpolationHoleFormat i =
350
- if i < len && fmt[ i] = '(' then
351
- let i2 = fmt.IndexOf( " )" , i+ 1 )
352
- if i2 = - 1 then
353
- failwith ( FSComp.SR.forFormatInvalidForInterpolated3())
354
- else
355
- let dotnetAlignment = match widthValue with None -> " " | Some w -> " ," + ( if info.leftJustify then " -" else " " ) + string w
356
- let dotnetNumberFormat = match fmt[ i+ 1 .. i2-1 ] with " " -> " " | s -> " :" + s
357
- appendToDotnetFormatString ( " {" + string dotnetFormatStringInterpolationHoleCount + dotnetAlignment + dotnetNumberFormat + " }" )
358
- dotnetFormatStringInterpolationHoleCount <- dotnetFormatStringInterpolationHoleCount + 1
359
- i2+ 1
360
- else
361
- failwith ( FSComp.SR.forFormatInvalidForInterpolated3())
362
-
363
- let collectSpecifierLocation fragLine fragCol numStdArgs =
316
+ if fmt[ i..( i+ 1 )] = " %%" then
364
317
match context with
365
318
| Some _ ->
366
- let numArgsForSpecifier =
367
- numStdArgs + ( if widthArg then 1 else 0 ) + ( if precisionArg then 1 else 0 )
368
319
specifierLocations.Add(
369
320
( Range.mkFileIndexRange m.FileIndex
370
321
( Position.mkPos fragLine startFragCol)
371
- ( Position.mkPos fragLine ( fragCol + 1 ))), numArgsForSpecifier )
322
+ ( Position.mkPos fragLine ( fragCol + 1 ))), 0 )
372
323
| None -> ()
373
-
374
- let ch = fmt[ i]
375
- match ch with
376
- | '%' ->
377
- collectSpecifierLocation fragLine fragCol 0
378
324
appendToDotnetFormatString " %"
379
- parseLoop acc ( i+ 1 , fragLine, fragCol+ 1 ) fragments
380
-
381
- | 'd' | 'i' | 'u' | 'B' | 'o' | 'x' | 'X' ->
382
- if ch = 'B' then DiagnosticsLogger.checkLanguageFeatureError g.langVersion Features.LanguageFeature.PrintfBinaryFormat m
383
- if info.precision then failwith ( FSComp.SR.forFormatDoesntSupportPrecision( ch.ToString()))
384
- collectSpecifierLocation fragLine fragCol 1
385
- let i = skipPossibleInterpolationHole ( i+ 1 )
386
- parseLoop (( posi, mkFlexibleIntFormatTypar g m) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
387
-
388
- | 'l' | 'L' ->
389
- if info.precision then failwith ( FSComp.SR.forFormatDoesntSupportPrecision( ch.ToString()))
390
- let fragCol = fragCol+ 1
325
+ parseLoop acc ( i+ 2 , fragLine, fragCol+ 1 ) fragments
326
+ else
391
327
let i = i+ 1
328
+ if i >= len then failwith ( FSComp.SR.forMissingFormatSpecifier())
329
+ let info = newInfo()
330
+
331
+ let oldI = i
332
+ let posi , i = Parsing.position fmt i
333
+ let fragCol = fragCol + i - oldI
334
+
335
+ let oldI = i
336
+ let i = Parsing.flags info fmt i
337
+ let fragCol = fragCol + i - oldI
338
+
339
+ let oldI = i
340
+ let widthArg ,( widthValue , ( precisionArg , i )) = Parsing.widthAndPrecision info fmt i
341
+ let fragCol = fragCol + i - oldI
342
+
343
+ if i >= len then failwith ( FSComp.SR.forBadPrecision())
344
+
345
+ let acc = if precisionArg then ( Option.map ((+) 1 ) posi, g.int_ ty) :: acc else acc
346
+
347
+ let acc = if widthArg then ( Option.map ((+) 1 ) posi, g.int_ ty) :: acc else acc
348
+
349
+ let checkOtherFlags c =
350
+ if info.precision then failwith ( FSComp.SR.forFormatDoesntSupportPrecision( c.ToString()))
351
+ if info.addZeros then failwith ( FSComp.SR.forDoesNotSupportZeroFlag( c.ToString()))
352
+ match info.numPrefixIfPos with
353
+ | Some n -> failwith ( FSComp.SR.forDoesNotSupportPrefixFlag( c.ToString(), n.ToString()))
354
+ | None -> ()
355
+
356
+ let skipPossibleInterpolationHole pos = Parsing.skipPossibleInterpolationHole isInterpolated isFormattableString fmt pos
357
+
358
+ // Implicitly typed holes in interpolated strings are translated to '... %P(...)...' in the
359
+ // type checker. They should always have '(...)' after for format string.
360
+ let requireAndSkipInterpolationHoleFormat i =
361
+ if i < len && fmt[ i] = '(' then
362
+ let i2 = fmt.IndexOf( " )" , i+ 1 )
363
+ if i2 = - 1 then
364
+ failwith ( FSComp.SR.forFormatInvalidForInterpolated3())
365
+ else
366
+ let dotnetAlignment = match widthValue with None -> " " | Some w -> " ," + ( if info.leftJustify then " -" else " " ) + string w
367
+ let dotnetNumberFormat = match fmt[ i+ 1 .. i2-1 ] with " " -> " " | s -> " :" + s
368
+ appendToDotnetFormatString ( " {" + string dotnetFormatStringInterpolationHoleCount + dotnetAlignment + dotnetNumberFormat + " }" )
369
+ dotnetFormatStringInterpolationHoleCount <- dotnetFormatStringInterpolationHoleCount + 1
370
+ i2+ 1
371
+ else
372
+ failwith ( FSComp.SR.forFormatInvalidForInterpolated3())
392
373
393
- // "bad format specifier ... In F# code you can use %d, %x, %o or %u instead ..."
394
- if i >= len then
395
- failwith ( FSComp.SR.forBadFormatSpecifier())
396
- // Always error for %l and %Lx
397
- failwith ( FSComp.SR.forLIsUnnecessary())
398
- match fmt[ i] with
399
- | 'd' | 'i' | 'o' | 'u' | 'x' | 'X' ->
374
+ let collectSpecifierLocation fragLine fragCol numStdArgs =
375
+ match context with
376
+ | Some _ ->
377
+ let numArgsForSpecifier =
378
+ numStdArgs + ( if widthArg then 1 else 0 ) + ( if precisionArg then 1 else 0 )
379
+ specifierLocations.Add(
380
+ ( Range.mkFileIndexRange m.FileIndex
381
+ ( Position.mkPos fragLine startFragCol)
382
+ ( Position.mkPos fragLine ( fragCol + 1 ))), numArgsForSpecifier)
383
+ | None -> ()
384
+
385
+ let ch = fmt[ i]
386
+ match ch with
387
+ | 'd' | 'i' | 'u' | 'B' | 'o' | 'x' | 'X' ->
388
+ if ch = 'B' then DiagnosticsLogger.checkLanguageFeatureError g.langVersion Features.LanguageFeature.PrintfBinaryFormat m
389
+ if info.precision then failwith ( FSComp.SR.forFormatDoesntSupportPrecision( ch.ToString()))
400
390
collectSpecifierLocation fragLine fragCol 1
401
391
let i = skipPossibleInterpolationHole ( i+ 1 )
402
- parseLoop (( posi, mkFlexibleIntFormatTypar g m) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
403
- | _ -> failwith ( FSComp.SR.forBadFormatSpecifier())
404
-
405
- | 'h' | 'H' ->
406
- failwith ( FSComp.SR.forHIsUnnecessary())
407
-
408
- | 'M' ->
409
- collectSpecifierLocation fragLine fragCol 1
410
- let i = skipPossibleInterpolationHole ( i+ 1 )
411
- parseLoop (( posi, mkFlexibleDecimalFormatTypar g m) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
412
-
413
- | 'f' | 'F' | 'e' | 'E' | 'g' | 'G' ->
414
- collectSpecifierLocation fragLine fragCol 1
415
- let i = skipPossibleInterpolationHole ( i+ 1 )
416
- parseLoop (( posi, mkFlexibleFloatFormatTypar g m) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
417
-
418
- | 'b' ->
419
- checkOtherFlags ch
420
- collectSpecifierLocation fragLine fragCol 1
421
- let i = skipPossibleInterpolationHole ( i+ 1 )
422
- parseLoop (( posi, g.bool_ ty) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
423
-
424
- | 'c' ->
425
- checkOtherFlags ch
426
- collectSpecifierLocation fragLine fragCol 1
427
- let i = skipPossibleInterpolationHole ( i+ 1 )
428
- parseLoop (( posi, g.char_ ty) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
429
-
430
- | 's' ->
431
- checkOtherFlags ch
432
- collectSpecifierLocation fragLine fragCol 1
433
- let i = skipPossibleInterpolationHole ( i+ 1 )
434
- parseLoop (( posi, g.string_ ty) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
435
-
436
- | 'O' ->
437
- checkOtherFlags ch
438
- collectSpecifierLocation fragLine fragCol 1
439
- let i = skipPossibleInterpolationHole ( i+ 1 )
440
- parseLoop (( posi, NewInferenceType g) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
441
-
442
- // residue of hole "...{n}..." in interpolated strings become %P(...)
443
- | 'P' when isInterpolated ->
444
- checkOtherFlags ch
445
- let i = requireAndSkipInterpolationHoleFormat ( i+ 1 )
446
- // Note, the fragCol doesn't advance at all as these are magically inserted.
447
- parseLoop (( posi, NewInferenceType g) :: acc) ( i, fragLine, startFragCol) fragments
448
-
449
- | 'A' ->
450
- if g.useReflectionFreeCodeGen then
451
- failwith ( FSComp.SR.forPercentAInReflectionFreeCode())
452
-
453
- match info.numPrefixIfPos with
454
- | None // %A has BindingFlags=Public, %+A has BindingFlags=Public | NonPublic
455
- | Some '+' ->
392
+ parseLoop (( posi, mkFlexibleIntFormatTypar g m) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
393
+
394
+ | 'l' | 'L' ->
395
+ if info.precision then failwith ( FSComp.SR.forFormatDoesntSupportPrecision( ch.ToString()))
396
+ let fragCol = fragCol+ 1
397
+ let i = i+ 1
398
+
399
+ // "bad format specifier ... In F# code you can use %d, %x, %o or %u instead ..."
400
+ if i >= len then
401
+ failwith ( FSComp.SR.forBadFormatSpecifier())
402
+ // Always error for %l and %Lx
403
+ failwith ( FSComp.SR.forLIsUnnecessary())
404
+ match fmt[ i] with
405
+ | 'd' | 'i' | 'o' | 'u' | 'x' | 'X' ->
406
+ collectSpecifierLocation fragLine fragCol 1
407
+ let i = skipPossibleInterpolationHole ( i+ 1 )
408
+ parseLoop (( posi, mkFlexibleIntFormatTypar g m) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
409
+ | _ -> failwith ( FSComp.SR.forBadFormatSpecifier())
410
+
411
+ | 'h' | 'H' ->
412
+ failwith ( FSComp.SR.forHIsUnnecessary())
413
+
414
+ | 'M' ->
456
415
collectSpecifierLocation fragLine fragCol 1
457
416
let i = skipPossibleInterpolationHole ( i+ 1 )
417
+ parseLoop (( posi, mkFlexibleDecimalFormatTypar g m) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
418
+
419
+ | 'f' | 'F' | 'e' | 'E' | 'g' | 'G' ->
420
+ collectSpecifierLocation fragLine fragCol 1
421
+ let i = skipPossibleInterpolationHole ( i+ 1 )
422
+ parseLoop (( posi, mkFlexibleFloatFormatTypar g m) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
423
+
424
+ | 'b' ->
425
+ checkOtherFlags ch
426
+ collectSpecifierLocation fragLine fragCol 1
427
+ let i = skipPossibleInterpolationHole ( i+ 1 )
428
+ parseLoop (( posi, g.bool_ ty) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
429
+
430
+ | 'c' ->
431
+ checkOtherFlags ch
432
+ collectSpecifierLocation fragLine fragCol 1
433
+ let i = skipPossibleInterpolationHole ( i+ 1 )
434
+ parseLoop (( posi, g.char_ ty) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
435
+
436
+ | 's' ->
437
+ checkOtherFlags ch
438
+ collectSpecifierLocation fragLine fragCol 1
439
+ let i = skipPossibleInterpolationHole ( i+ 1 )
440
+ parseLoop (( posi, g.string_ ty) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
441
+
442
+ | 'O' ->
443
+ checkOtherFlags ch
444
+ collectSpecifierLocation fragLine fragCol 1
445
+ let i = skipPossibleInterpolationHole ( i+ 1 )
446
+ parseLoop (( posi, NewInferenceType g) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
447
+
448
+ // residue of hole "...{n}..." in interpolated strings become %P(...)
449
+ | 'P' when isInterpolated ->
450
+ checkOtherFlags ch
451
+ let i = requireAndSkipInterpolationHoleFormat ( i+ 1 )
452
+ // Note, the fragCol doesn't advance at all as these are magically inserted.
453
+ parseLoop (( posi, NewInferenceType g) :: acc) ( i, fragLine, startFragCol) fragments
454
+
455
+ | 'A' ->
456
+ if g.useReflectionFreeCodeGen then
457
+ failwith ( FSComp.SR.forPercentAInReflectionFreeCode())
458
+
459
+ match info.numPrefixIfPos with
460
+ | None // %A has BindingFlags=Public, %+A has BindingFlags=Public | NonPublic
461
+ | Some '+' ->
462
+ collectSpecifierLocation fragLine fragCol 1
463
+ let i = skipPossibleInterpolationHole ( i+ 1 )
464
+ let aTy = NewInferenceType g
465
+ percentATys.Add( aTy)
466
+ parseLoop (( posi, aTy) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
467
+ | Some n ->
468
+ failwith ( FSComp.SR.forDoesNotSupportPrefixFlag( ch.ToString(), n.ToString()))
469
+
470
+ | 'a' ->
471
+ checkOtherFlags ch
458
472
let aTy = NewInferenceType g
459
- percentATys.Add( aTy)
460
- parseLoop (( posi, aTy) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
461
- | Some n ->
462
- failwith ( FSComp.SR.forDoesNotSupportPrefixFlag( ch.ToString(), n.ToString()))
463
-
464
- | 'a' ->
465
- checkOtherFlags ch
466
- let aTy = NewInferenceType g
467
- let fTy = mkFunTy g printerArgTy ( mkFunTy g aTy printerResidueTy)
468
- collectSpecifierLocation fragLine fragCol 2
469
- let i = skipPossibleInterpolationHole ( i+ 1 )
470
- parseLoop (( Option.map ((+) 1 ) posi, aTy) :: ( posi, fTy) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
471
-
472
- | 't' ->
473
- checkOtherFlags ch
474
- collectSpecifierLocation fragLine fragCol 1
475
- let i = skipPossibleInterpolationHole ( i+ 1 )
476
- parseLoop (( posi, mkFunTy g printerArgTy printerResidueTy) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
477
-
478
- | c -> failwith ( FSComp.SR.forBadFormatSpecifierGeneral( String.make 1 c))
473
+ let fTy = mkFunTy g printerArgTy ( mkFunTy g aTy printerResidueTy)
474
+ collectSpecifierLocation fragLine fragCol 2
475
+ let i = skipPossibleInterpolationHole ( i+ 1 )
476
+ parseLoop (( Option.map ((+) 1 ) posi, aTy) :: ( posi, fTy) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
477
+
478
+ | 't' ->
479
+ checkOtherFlags ch
480
+ collectSpecifierLocation fragLine fragCol 1
481
+ let i = skipPossibleInterpolationHole ( i+ 1 )
482
+ parseLoop (( posi, mkFunTy g printerArgTy printerResidueTy) :: acc) ( i, fragLine, fragCol+ 1 ) fragments
483
+
484
+ | c -> failwith ( FSComp.SR.forBadFormatSpecifierGeneral( String.make 1 c))
479
485
480
486
let results = parseLoop [] ( 0 , 0 , m.StartColumn) fragments
481
487
results, Seq.toList specifierLocations, dotnetFormatString.ToString(), percentATys.ToArray()
0 commit comments