Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a276808

Browse files
authored
Parser: Capture multiple block separators (#18899)
1 parent 369eac4 commit a276808

38 files changed

+174
-104
lines changed

docs/release-notes/.FSharp.Compiler.Service/10.0.100.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* Use `errorR` instead of `error` in `CheckDeclarations.fs` when possible. ([PR #18645](https://github.com/dotnet/fsharp/pull/18645))
3131
* Parser: Capture named fields block separators. ([PR #18857](https://github.com/dotnet/fsharp/pull/18857))
3232
* Type checker: use inner expr range in upcast constraints errors ([PR #18850](https://github.com/dotnet/fsharp/pull/18850))
33+
* Parser: Capture multiple block separators ([PR #18899](https://github.com/dotnet/fsharp/pull/18899))
3334

3435
### Breaking Changes
3536

src/Compiler/Checking/CheckRecordSyntaxHelpers.fs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,14 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid
9090
let totalRange (origId: Ident) (id: Ident) =
9191
withStartEnd origId.idRange.End id.idRange.Start origId.idRange
9292

93-
let rangeOfBlockSeparator (id: Ident) =
94-
let idEnd = id.idRange.End
95-
let blockSeparatorStartCol = idEnd.Column
96-
let blockSeparatorEndCol = blockSeparatorStartCol + 4
97-
let blockSeparatorStartPos = mkPos idEnd.Line blockSeparatorStartCol
98-
let blockSeparatorEndPos = mkPos idEnd.Line blockSeparatorEndCol
99-
100-
withStartEnd blockSeparatorStartPos blockSeparatorEndPos id.idRange
101-
10293
match withExpr with
103-
| SynExpr.Ident origId, (sepRange, _) ->
104-
let lid, rng = upToId sepRange id (origId :: ids)
105-
Some(SynExpr.LongIdent(false, LongIdentWithDots(lid, rng), None, totalRange origId id), (rangeOfBlockSeparator id, None))
94+
| SynExpr.Ident origId, (blockSep: BlockSeparator) ->
95+
let lid, rng = upToId blockSep.Range id (origId :: ids)
96+
97+
Some(
98+
SynExpr.LongIdent(false, LongIdentWithDots(lid, rng), None, totalRange origId id),
99+
BlockSeparator.Offside(blockSep.Range, None)
100+
)
106101
| _ -> None
107102

108103
let rec synExprRecd copyInfo (outerFieldId: Ident) innerFields exprBeingAssigned =

src/Compiler/Checking/CheckRecordSyntaxHelpers.fsi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ open FSharp.Compiler.TypedTree
1010
val GroupUpdatesToNestedFields:
1111
fields: ((Ident list * Ident) * SynExpr option) list -> ((Ident list * Ident) * SynExpr option) list
1212

13-
val TransformAstForNestedUpdates<'a> :
13+
val TransformAstForNestedUpdates:
1414
cenv: TcFileState ->
1515
env: TcEnv ->
1616
overallTy: TType ->
1717
lid: LongIdent ->
1818
exprBeingAssigned: SynExpr ->
19-
withExpr: SynExpr * (range * 'a) ->
19+
withExpr: SynExpr * BlockSeparator ->
2020
(Ident list * Ident) * SynExpr option
2121

2222
val BindOriginalRecdExpr:

src/Compiler/Checking/Expressions/CheckExpressions.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7757,7 +7757,7 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, m
77577757

77587758
match withExprOpt, synLongId.LongIdent, exprBeingAssigned with
77597759
| _, [ id ], _ -> ([], id), exprBeingAssigned
7760-
| Some withExpr, lid, Some exprBeingAssigned -> TransformAstForNestedUpdates cenv env overallTy lid exprBeingAssigned withExpr
7760+
| Some (origExpr, blockSep), lid, Some exprBeingAssigned -> TransformAstForNestedUpdates cenv env overallTy lid exprBeingAssigned (origExpr, blockSep)
77617761
| _ -> List.frontAndBack synLongId.LongIdent, exprBeingAssigned)
77627762

77637763
let flds = if hasOrigExpr then GroupUpdatesToNestedFields flds else flds

src/Compiler/Service/ServiceParseTreeWalk.fs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -445,12 +445,12 @@ module SyntaxTraversal =
445445
| SynExpr.AnonRecd(copyInfo = copyOpt; recordFields = fields) ->
446446
[
447447
match copyOpt with
448-
| Some(expr, (withRange, _)) ->
448+
| Some(expr, blockSep) ->
449449
yield dive expr expr.Range traverseSynExpr
450450

451451
yield
452-
dive () withRange (fun () ->
453-
if posGeq pos withRange.End then
452+
dive () blockSep.Range (fun () ->
453+
if posGeq pos blockSep.Range.End then
454454
// special case: caret is after WITH
455455
// { x with $ }
456456
visitor.VisitRecordField(path, Some expr, None)
@@ -498,24 +498,24 @@ module SyntaxTraversal =
498498
traverseSynExpr expr)
499499

500500
match sepOpt with
501-
| Some(sep, scPosOpt) ->
501+
| Some blockSep ->
502502
yield
503-
dive () sep (fun () ->
503+
dive () blockSep.Range (fun () ->
504504
// special case: caret is below 'inherit' + one or more fields are already defined
505505
// inherit A()
506506
// $
507507
// field1 = 5
508-
diveIntoSeparator inheritRange.StartColumn scPosOpt None)
508+
diveIntoSeparator inheritRange.StartColumn blockSep.Position None)
509509
| None -> ()
510510
| _ -> ()
511511

512512
match copyOpt with
513-
| Some(expr, (withRange, _)) ->
513+
| Some(expr, blockSep) ->
514514
yield dive expr expr.Range traverseSynExpr
515515

516516
yield
517-
dive () withRange (fun () ->
518-
if posGeq pos withRange.End then
517+
dive () blockSep.Range (fun () ->
518+
if posGeq pos blockSep.Range.End then
519519
// special case: caret is after WITH
520520
// { x with $ }
521521
visitor.VisitRecordField(path, Some expr, None)
@@ -556,14 +556,14 @@ module SyntaxTraversal =
556556
| None -> ()
557557

558558
match sepOpt with
559-
| Some(sep, scPosOpt) ->
559+
| Some blockSep ->
560560
yield
561-
dive () sep (fun () ->
561+
dive () blockSep.Range (fun () ->
562562
// special case: caret is between field bindings
563563
// field1 = 5
564564
// $
565565
// field2 = 5
566-
diveIntoSeparator offsideColumn scPosOpt copyOpt)
566+
diveIntoSeparator offsideColumn blockSep.Position copyOpt)
567567
| _ -> ()
568568

569569
]

src/Compiler/SyntaxTree/SyntaxTree.fs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,23 @@ type DebugPointAtBinding =
306306

307307
type SeqExprOnly = SeqExprOnly of bool
308308

309-
type BlockSeparator = range * pos option
309+
[<NoEquality; NoComparison; RequireQualifiedAccess>]
310+
type BlockSeparator =
311+
| Semicolon of range: range * position: pos option
312+
| Comma of range: range * position: pos option
313+
| Offside of range: range * position: pos option
314+
315+
member this.Range =
316+
match this with
317+
| Semicolon(range = m)
318+
| Comma(range = m)
319+
| Offside(range = m) -> m
320+
321+
member this.Position =
322+
match this with
323+
| Semicolon(position = p)
324+
| Comma(position = p)
325+
| Offside(position = p) -> p
310326

311327
type RecordFieldName = SynLongIdent * bool
312328

src/Compiler/SyntaxTree/SyntaxTree.fsi

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,26 @@ type SeqExprOnly =
354354
/// Indicates if a for loop is 'for x in e1 -> e2', only valid in sequence expressions
355355
| SeqExprOnly of bool
356356

357-
/// Represents the location of the separator block + optional position
358-
/// of the semicolon (used for tooling support)
359-
type BlockSeparator = range * pos option
357+
/// Represents the location of the separator block and optional position of the semicolon (used for tooling support)
358+
[<NoEquality; NoComparison; RequireQualifiedAccess>]
359+
type BlockSeparator =
360+
/// A separator consisting of a semicolon ';'
361+
/// range is the range of the semicolon
362+
/// position is the position of the semicolon (if available)
363+
| Semicolon of range: range * position: pos option
364+
/// A separator consisting of a comma ','
365+
/// range is the range of the comma
366+
/// position is the position of the comma (if available)
367+
| Comma of range: range * position: pos option
368+
369+
// A separator consisting of a newline
370+
/// range is the range of the newline
371+
/// position is the position of the newline (if available)
372+
| Offside of range: range * position: pos option
373+
374+
member Range: range
375+
376+
member Position: pos option
360377

361378
/// Represents a record field name plus a flag indicating if given record field name is syntactically
362379
/// correct and can be used in name resolution.

src/Compiler/pars.fsy

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5709,7 +5709,7 @@ recdExprCore:
57095709
| appExpr
57105710
{ let mExpr = rhs parseState 1
57115711
reportParseErrorAt mExpr (FSComp.SR.parsFieldBinding ())
5712-
Some($1, (mExpr.EndRange, None)), [] }
5712+
Some($1, BlockSeparator.Offside(mExpr.EndRange, None)), [] }
57135713

57145714
/*
57155715
handles cases when identifier can start from the underscore
@@ -5743,15 +5743,15 @@ recdExprCore:
57435743
| appExpr WITH recdBinding recdExprBindings opt_seps_block
57445744
{ let l = List.rev $4
57455745
let l = rebindRanges $3 l $5
5746-
(Some($1, (rhs parseState 2, None)), l) }
5746+
(Some($1, BlockSeparator.Offside(rhs parseState 2, None)), l) }
57475747

57485748
| appExpr OWITH opt_seps_block OEND
5749-
{ (Some($1, (rhs parseState 2, None)), []) }
5749+
{ (Some($1, BlockSeparator.Offside(rhs parseState 2, None)), []) }
57505750

57515751
| appExpr OWITH recdBinding recdExprBindings opt_seps_block OEND
57525752
{ let l = List.rev $4
57535753
let l = rebindRanges $3 l $5
5754-
(Some($1, (rhs parseState 2, None)), l) }
5754+
(Some($1, BlockSeparator.Offside(rhs parseState 2, None)), l) }
57555755

57565756
opt_seps_block:
57575757
| seps_block
@@ -5762,17 +5762,17 @@ opt_seps_block:
57625762

57635763
seps_block:
57645764
| OBLOCKSEP
5765-
{ (rhs parseState 1), None }
5765+
{ BlockSeparator.Offside((rhs parseState 1), None) }
57665766

57675767
| SEMICOLON
57685768
{ let m = (rhs parseState 1)
5769-
m, Some m.End }
5769+
BlockSeparator.Semicolon(m, Some m.End) }
57705770

57715771
| SEMICOLON OBLOCKSEP
5772-
{ (rhs2 parseState 1 2), Some (rhs parseState 1).End }
5772+
{ BlockSeparator.Semicolon((rhs2 parseState 1 2), Some (rhs parseState 1).End) }
57735773

57745774
| OBLOCKSEP SEMICOLON
5775-
{ (rhs2 parseState 1 2), Some (rhs parseState 2).End }
5775+
{ BlockSeparator.Semicolon((rhs2 parseState 1 2), Some (rhs parseState 2).End) }
57765776

57775777

57785778
/* identifier can start from the underscore */

0 commit comments

Comments
 (0)