Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions src/Compiler/Utilities/range.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type FileIndex = int32
[<AutoOpen>]
module PosImpl =
[<Literal>]
let columnBitCount = 20
let columnBitCount = 22

[<Literal>]
let lineBitCount = 31
Expand Down Expand Up @@ -83,13 +83,13 @@ type NotedSourceConstruct =
[<AutoOpen>]
module RangeImpl =
[<Literal>]
let fileIndexBitCount = 24
let fileIndexBitCount = 20

[<Literal>]
let startColumnBitCount = columnBitCount // 20
let startColumnBitCount = columnBitCount // 22

[<Literal>]
let endColumnBitCount = columnBitCount // 20
let endColumnBitCount = columnBitCount // 22

[<Literal>]
let startLineBitCount = lineBitCount // 31
Expand All @@ -107,10 +107,10 @@ module RangeImpl =
let fileIndexShift = 0

[<Literal>]
let startColumnShift = 24
let startColumnShift = 20

[<Literal>]
let endColumnShift = 44
let endColumnShift = 42

[<Literal>]
let startLineShift = 0
Expand All @@ -126,15 +126,15 @@ module RangeImpl =

[<Literal>]
let fileIndexMask =
0b0000000000000000000000000000000000000000111111111111111111111111L
0b0000000000000000000000000000000000000000000011111111111111111111L

[<Literal>]
let startColumnMask =
0b0000000000000000000011111111111111111111000000000000000000000000L
0b0000000000000000000000111111111111111111111100000000000000000000L

[<Literal>]
let endColumnMask =
0b1111111111111111111100000000000000000000000000000000000000000000L
0b1111111111111111111111000000000000000000000000000000000000000000L

[<Literal>]
let startLineMask =
Expand Down Expand Up @@ -277,18 +277,19 @@ type Range(code1: int64, code2: int64) =

new(fIdx, b: pos, e: pos) = range (fIdx, b.Line, b.Column, e.Line, e.Column)

member _.StartLine = int32 ((code2 &&& startLineMask) >>> startLineShift)
member _.StartLine = int32 (uint64 (code2 &&& startLineMask) >>> startLineShift)

member _.StartColumn = int32 ((code1 &&& startColumnMask) >>> startColumnShift)
member _.StartColumn = int32 (uint64 (code1 &&& startColumnMask) >>> startColumnShift)

member m.EndLine = int32 ((code2 &&& heightMask) >>> heightShift) + m.StartLine
member m.EndLine = int32 (uint64 (code2 &&& heightMask) >>> heightShift) + m.StartLine

member _.EndColumn = int32 ((code1 &&& endColumnMask) >>> endColumnShift)
member _.EndColumn = int32 (uint64 (code1 &&& endColumnMask) >>> endColumnShift)

member _.IsSynthetic = int32 ((code2 &&& isSyntheticMask) >>> isSyntheticShift) <> 0
member _.IsSynthetic =
int32 (uint64 (code2 &&& isSyntheticMask) >>> isSyntheticShift) <> 0

member _.NotedSourceConstruct =
match int32 ((code2 &&& debugPointKindMask) >>> debugPointKindShift) with
match int32 (uint64 (code2 &&& debugPointKindMask) >>> debugPointKindShift) with
| 1 -> NotedSourceConstruct.While
| 2 -> NotedSourceConstruct.For
| 3 -> NotedSourceConstruct.Try
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

namespace FSharp.Compiler.ComponentTests.CompilerService

open Xunit
open System
open FSharp.Test.Compiler

module RangeModule =

let useValidateRoundTripTemplate (insertedTestCase: string) =
let exceptionMessage = """raise (new Exception($"Error round tripping '{label}': expected: '{expected}' actual: '{actual}'\n arguments: startline '{startline}' startcolumn '{startcolumn}' endline '{endline}' endcolumn '{endcolumn}\n Range Object: {r.ToString()}\n Range Properties: r.StartLine '{r.StartLine}' r.StartColumn '{r.StartColumn}' r.EndLine '{r.EndLine}' r.EndColumn '{r.EndColumn}'\n"))"""
FSharp $"""
open System
open FSharp.Compiler.Text
open Range
open Position

let getRangeWithFileName filename startline startcolumn endline endcolumn =
mkRange filename (mkPos startline startcolumn) (mkPos endline endcolumn)

// Get a range object given start and end columns and lines
let getRange startline startcolumn endline endcolumn =
getRangeWithFileName "DefaultTestFileName" startline startcolumn endline endcolumn

// If the range object sets the values to a value different to what is passed in then validRangeValuesUnchanged throws
// Exceptions at runtime indicate failure
let validRangeValuesUnchanged startline startcolumn endline endcolumn =
let r = getRange startline startcolumn endline endcolumn
let validateRoundTrip label expected actual =
if expected <> actual then {exceptionMessage}

validateRoundTrip "StartColumn" startcolumn r.StartColumn
validateRoundTrip "EndColumn" endcolumn r.EndColumn

validateRoundTrip "StartLine" startline r.StartLine
validateRoundTrip "EndLine" endline r.EndLine


let MaximumColumnValue = 4194303
let MaximumStartLineValue = 2147483647
let MaximumEndLineValue = 134217727
{insertedTestCase}
"""

[<Fact>]
let ``Validate valid Smoke test Min and Max values stored in Range`` () =
useValidateRoundTripTemplate """
validRangeValuesUnchanged 0 0 MaximumEndLineValue MaximumColumnValue
"""
|> withReferenceFSharpCompilerService
|> asExe
|> compileAndRun
|> shouldSucceed


[<Fact>]
let ``Validate valid EndColumn values are unchanged by storing in Range`` () =
useValidateRoundTripTemplate """
validRangeValuesUnchanged 0 0 0 MaximumColumnValue
"""
|> withReferenceFSharpCompilerService
|> asExe
|> compileAndRun
|> shouldSucceed


[<Fact>]
let ``Validate valid EndLine values are unchanged by storing in Range`` () =
useValidateRoundTripTemplate """
validRangeValuesUnchanged 0 0 MaximumEndLineValue 0
"""
|> withReferenceFSharpCompilerService
|> asExe
|> compileAndRun
|> shouldSucceed


[<Fact>]
let ``Validate valid StartColumn values are unchanged by storing in Range`` () =
useValidateRoundTripTemplate """
// Start Column only
validRangeValuesUnchanged 0 MaximumColumnValue 0 0
"""
|> withReferenceFSharpCompilerService
|> asExe
|> compileAndRun
|> shouldSucceed


[<Fact>]
let ``Validate valid StartLine values are unchanged by storing in Range`` () =
useValidateRoundTripTemplate """
validRangeValuesUnchanged (MaximumStartLineValue - MaximumEndLineValue) 0 MaximumStartLineValue 0
"""
|> withReferenceFSharpCompilerService
|> asExe
|> compileAndRun
|> shouldSucceed
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@
<Compile Include="CompilerOptions\fsc\reflectionfree.fs" />
<Compile Include="CompilerOptions\fsc\refonlyrefout.fs" />
<Compile Include="CompilerOptions\fsc\sourceFiles.fs" />
<Compile Include="CompilerService\RangeModule.fs" />
<Compile Include="Debugger\PortablePdbs.fs" />
<Compile Include="Diagnostics\async.fs" />
<Compile Include="Diagnostics\General.fs" />
Expand Down
6 changes: 6 additions & 0 deletions tests/FSharp.Test.Utilities/Compiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,12 @@ module rec Compiler =
| CS src -> CS { src with Name = Some name }
| IL _ -> failwith "IL Compilation cannot be named."

let withReferenceFSharpCompilerService (cUnit: CompilationUnit) : CompilationUnit =
// Compute the location of the FSharp.Compiler.Service dll that matches the target framework used to build this test assembly
let compilerServiceAssemblyLocation =
typeof<FSharp.Compiler.Text.Range>.Assembly.Location
withOptionsHelper [ $"-r:{compilerServiceAssemblyLocation}" ] "withReferenceFSharpCompilerService is only supported for F#" cUnit

let withReferences (references: CompilationUnit list) (cUnit: CompilationUnit) : CompilationUnit =
match cUnit with
| FS fs -> FS { fs with References = fs.References @ references }
Expand Down