diff --git a/src/Compiler/Utilities/range.fs b/src/Compiler/Utilities/range.fs index 6bf20edfc00..0a91bb1a2c3 100755 --- a/src/Compiler/Utilities/range.fs +++ b/src/Compiler/Utilities/range.fs @@ -492,6 +492,20 @@ module Range = else m + let withStartEnd (startPos: Position) (endPos: Position) (r: range) = range (r.FileIndex, startPos, endPos) + + let withStart (startPos: Position) (r: range) = range (r.FileIndex, startPos, r.End) + + let withEnd (endPos: Position) (r: range) = range (r.FileIndex, r.Start, endPos) + + let shiftStart (lineDelta: int) (columnDelta: int) (r: range) = + let shiftedStart = mkPos (r.Start.Line + lineDelta) (r.StartColumn + columnDelta) + range (r.FileIndex, shiftedStart, r.End) + + let shiftEnd (lineDelta: int) (columnDelta: int) (r: range) = + let shiftedEnd = mkPos (r.End.Line + lineDelta) (r.EndColumn + columnDelta) + range (r.FileIndex, r.Start, shiftedEnd) + let rangeContainsRange (m1: range) (m2: range) = m1.FileIndex = m2.FileIndex && posGeq m2.Start m1.Start && posGeq m1.End m2.End diff --git a/src/Compiler/Utilities/range.fsi b/src/Compiler/Utilities/range.fsi index 100c57fb67e..7b422fcd307 100755 --- a/src/Compiler/Utilities/range.fsi +++ b/src/Compiler/Utilities/range.fsi @@ -211,6 +211,21 @@ module Range = /// Union two ranges, taking their first occurring start position and last occurring end position val unionRanges: range -> range -> range + + // Create a new range with the given start and end positions + val withStartEnd: Position -> Position -> range -> range + + // Create a new range with the given start position + val withStart: Position -> range -> range + + // Create a new range with the given end position + val withEnd: Position -> range -> range + + // Create a new range with the start position shifted by the given deltas + val shiftStart: int -> int -> range -> range + + // Create a new range with the end position shifted by the given deltas + val shiftEnd: int -> int -> range -> range /// Test to see if one range contains another range val rangeContainsRange: range -> range -> bool diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index d22e79fd15d..18e50749469 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -603,7 +603,7 @@ fileModuleSpec: | [] -> ParsedSigFileFragment.AnonModule($1, m) | _ -> let lastDeclRange = List.tryLast $1 |> Option.map (fun decl -> decl.Range) |> Option.defaultValue (rhs parseState 1) - let m = mkRange lastDeclRange.FileName (lhs parseState).Start lastDeclRange.End + let m = withStart (lhs parseState).Start lastDeclRange xml.MarkAsInvalid() let trivia: SynModuleOrNamespaceSigTrivia = match mNamespaceOpt with @@ -1159,7 +1159,7 @@ fileModuleImpl: | [], None -> ParsedImplFileFragment.AnonModule($1, m) | _ -> let lastDeclRange = List.tryLast $1 |> Option.map (fun decl -> decl.Range) |> Option.defaultValue (rhs parseState 1) - let m = mkRange lastDeclRange.FileName (lhs parseState).Start lastDeclRange.End + let m = withStart (lhs parseState).Start lastDeclRange xml.MarkAsInvalid() let trivia: SynModuleOrNamespaceTrivia = match mNamespaceOpt with @@ -4927,18 +4927,18 @@ atomicExprQualification: | GLOBAL { (fun e mLhs mDot -> reportParseErrorAt (rhs parseState 3) (FSComp.SR.nrGlobalUsedOnlyAsFirstName()) - let fixedLhsm = mkRange mLhs.FileName mLhs.Start mDot.End // previous mLhs is wrong after 'recover' + let fixedLhsm = withEnd mDot.End mLhs // previous mLhs is wrong after 'recover' mkSynDotMissing mDot fixedLhsm e) } | /* empty */ { (fun e mLhs mDot -> reportParseErrorAt mDot (FSComp.SR.parsMissingQualificationAfterDot()) - let fixedLhsm = mkRange mLhs.FileName mLhs.Start mDot.End // previous mLhs is wrong after 'recover' + let fixedLhsm = withEnd mDot.End mLhs // previous mLhs is wrong after 'recover' mkSynDotMissing mDot fixedLhsm e) } | recover { (fun e mLhs mDot -> reportParseErrorAt mDot (FSComp.SR.parsMissingQualificationAfterDot()) - let fixedLhsm = mkRange mLhs.FileName mLhs.Start mDot.End // previous mLhs is wrong after 'recover' + let fixedLhsm = withEnd mDot.End mLhs // previous mLhs is wrong after 'recover' // Include 'e' in the returned expression but throw it away mkSynDotMissing mDot fixedLhsm e) } | LPAREN COLON_COLON rparen DOT INT32 @@ -5883,7 +5883,7 @@ appTypeConPower: { if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator()) if $2 = "^-" then let afterMinus = (rhs parseState 2).EndRange - let beforeMinus = mkRange afterMinus.FileName (mkPos afterMinus.EndLine (afterMinus.EndColumn - 1)) afterMinus.End + let beforeMinus = shiftStart 0 -1 afterMinus let m = unionRanges beforeMinus (rhs parseState 3) // include MINUS in Negate range SynType.MeasurePower($1, SynRationalConst.Negate($3, m), lhs parseState) else SynType.MeasurePower($1, $3, lhs parseState) } @@ -6044,7 +6044,7 @@ powerType: { if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator()) if $2 = "^-" then let afterMinus = (rhs parseState 2).EndRange - let beforeMinus = mkRange afterMinus.FileName (mkPos afterMinus.EndLine (afterMinus.EndColumn - 1)) afterMinus.End + let beforeMinus = shiftStart 0 -1 afterMinus let m = unionRanges beforeMinus (rhs parseState 3) // include MINUS in Negate range SynType.MeasurePower($1, SynRationalConst.Negate($3, m), lhs parseState) else SynType.MeasurePower($1, $3, lhs parseState) } @@ -6270,7 +6270,7 @@ measureTypePower: if $2 = "^-" then let mOp = rhs parseState 2 let afterMinus = mOp.EndRange - let beforeMinus = mkRange afterMinus.FileName (mkPos afterMinus.EndLine (afterMinus.EndColumn - 1)) afterMinus.End + let beforeMinus = shiftStart 0 -1 afterMinus let mNegate = unionRanges beforeMinus (rhs parseState 3) // include MINUS in Negate range let mCaret = unionRanges mOp.StartRange mNegate.StartRange SynMeasure.Power($1, mCaret, SynRationalConst.Negate($3, mNegate), lhs parseState) diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index 7f07a0f1123..6a555b4aed0 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -10039,8 +10039,13 @@ FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range range0 FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range rangeCmdArgs FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range rangeN(System.String, Int32) FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range rangeStartup +FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range shiftEnd(Int32, Int32, FSharp.Compiler.Text.Range) +FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range shiftStart(Int32, Int32, FSharp.Compiler.Text.Range) FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range trimRangeToLine(FSharp.Compiler.Text.Range) FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range unionRanges(FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range) +FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range withEnd(FSharp.Compiler.Text.Position, FSharp.Compiler.Text.Range) +FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range withStart(FSharp.Compiler.Text.Position, FSharp.Compiler.Text.Range) +FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range withStartEnd(FSharp.Compiler.Text.Position, FSharp.Compiler.Text.Position, FSharp.Compiler.Text.Range) FSharp.Compiler.Text.RangeModule: System.Collections.Generic.IComparer`1[FSharp.Compiler.Text.Position] get_posOrder() FSharp.Compiler.Text.RangeModule: System.Collections.Generic.IComparer`1[FSharp.Compiler.Text.Position] posOrder FSharp.Compiler.Text.RangeModule: System.Collections.Generic.IComparer`1[FSharp.Compiler.Text.Range] get_rangeOrder() diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index 7f07a0f1123..6a555b4aed0 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -10039,8 +10039,13 @@ FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range range0 FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range rangeCmdArgs FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range rangeN(System.String, Int32) FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range rangeStartup +FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range shiftEnd(Int32, Int32, FSharp.Compiler.Text.Range) +FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range shiftStart(Int32, Int32, FSharp.Compiler.Text.Range) FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range trimRangeToLine(FSharp.Compiler.Text.Range) FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range unionRanges(FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range) +FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range withEnd(FSharp.Compiler.Text.Position, FSharp.Compiler.Text.Range) +FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range withStart(FSharp.Compiler.Text.Position, FSharp.Compiler.Text.Range) +FSharp.Compiler.Text.RangeModule: FSharp.Compiler.Text.Range withStartEnd(FSharp.Compiler.Text.Position, FSharp.Compiler.Text.Position, FSharp.Compiler.Text.Range) FSharp.Compiler.Text.RangeModule: System.Collections.Generic.IComparer`1[FSharp.Compiler.Text.Position] get_posOrder() FSharp.Compiler.Text.RangeModule: System.Collections.Generic.IComparer`1[FSharp.Compiler.Text.Position] posOrder FSharp.Compiler.Text.RangeModule: System.Collections.Generic.IComparer`1[FSharp.Compiler.Text.Range] get_rangeOrder() diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index eb9294585d9..3b83200c1d6 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -97,6 +97,9 @@ PrettyNaming.fs + + RangeTests.fs + Program.fs diff --git a/tests/service/RangeTests.fs b/tests/service/RangeTests.fs new file mode 100644 index 00000000000..2fd9d4c28fa --- /dev/null +++ b/tests/service/RangeTests.fs @@ -0,0 +1,48 @@ +module Tests.Service.RangeTests + +open FSharp.Compiler.Text +open FSharp.Compiler.Text.Position +open FSharp.Compiler.Text.Range +open FsUnit +open NUnit.Framework + +[] +let ``withStartEnd Test`` () = + let z = Range.Zero + let newStart = mkPos 2 4 + let newEnd = mkPos 7 23 + let r = withStartEnd newStart newEnd z + r.Start |> shouldEqual newStart + r.End |> shouldEqual newEnd + +[] +let ``withStart Test`` () = + let z = Range.Zero + let newStart = mkPos 2 4 + let r = withStart newStart z + r.Start |> shouldEqual newStart + +[] +let ``withEnd Test`` () = + let z = Range.Zero + let newEnd = mkPos 2 4 + let r = withEnd newEnd z + r.End |> shouldEqual newEnd + +[] +let ``shiftStart Test`` () = + let z = Range.Zero + let lineDelta = 10 + let columnDelta = 20 + let r = shiftStart lineDelta columnDelta z + r.Start.Column |> shouldEqual (z.StartColumn + columnDelta) + r.Start.Line |> shouldEqual (z.StartLine + lineDelta) + +[] +let ``shiftEnd Test`` () = + let z = Range.Zero + let lineDelta = 10 + let columnDelta = 20 + let r = shiftEnd lineDelta columnDelta z + r.End.Column |> shouldEqual (z.EndColumn + columnDelta) + r.End.Line |> shouldEqual (z.EndLine + lineDelta)