diff --git a/src/Compiler/Utilities/range.fs b/src/Compiler/Utilities/range.fs index bbd6a9f0673..f81d32d8324 100755 --- a/src/Compiler/Utilities/range.fs +++ b/src/Compiler/Utilities/range.fs @@ -18,7 +18,7 @@ type FileIndex = int32 [] module PosImpl = [] - let columnBitCount = 20 + let columnBitCount = 22 [] let lineBitCount = 31 @@ -83,13 +83,13 @@ type NotedSourceConstruct = [] module RangeImpl = [] - let fileIndexBitCount = 24 + let fileIndexBitCount = 20 [] - let startColumnBitCount = columnBitCount // 20 + let startColumnBitCount = columnBitCount // 22 [] - let endColumnBitCount = columnBitCount // 20 + let endColumnBitCount = columnBitCount // 22 [] let startLineBitCount = lineBitCount // 31 @@ -107,10 +107,10 @@ module RangeImpl = let fileIndexShift = 0 [] - let startColumnShift = 24 + let startColumnShift = 20 [] - let endColumnShift = 44 + let endColumnShift = 42 [] let startLineShift = 0 @@ -126,15 +126,15 @@ module RangeImpl = [] let fileIndexMask = - 0b0000000000000000000000000000000000000000111111111111111111111111L + 0b0000000000000000000000000000000000000000000011111111111111111111L [] let startColumnMask = - 0b0000000000000000000011111111111111111111000000000000000000000000L + 0b0000000000000000000000111111111111111111111100000000000000000000L [] let endColumnMask = - 0b1111111111111111111100000000000000000000000000000000000000000000L + 0b1111111111111111111111000000000000000000000000000000000000000000L [] let startLineMask = @@ -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 diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/RangeModule.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/RangeModule.fs new file mode 100644 index 00000000000..61aa5af53d6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/RangeModule.fs @@ -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} +""" + + [] + let ``Validate valid Smoke test Min and Max values stored in Range`` () = + useValidateRoundTripTemplate """ +validRangeValuesUnchanged 0 0 MaximumEndLineValue MaximumColumnValue +""" + |> withReferenceFSharpCompilerService + |> asExe + |> compileAndRun + |> shouldSucceed + + + [] + let ``Validate valid EndColumn values are unchanged by storing in Range`` () = + useValidateRoundTripTemplate """ +validRangeValuesUnchanged 0 0 0 MaximumColumnValue +""" + |> withReferenceFSharpCompilerService + |> asExe + |> compileAndRun + |> shouldSucceed + + + [] + let ``Validate valid EndLine values are unchanged by storing in Range`` () = + useValidateRoundTripTemplate """ +validRangeValuesUnchanged 0 0 MaximumEndLineValue 0 +""" + |> withReferenceFSharpCompilerService + |> asExe + |> compileAndRun + |> shouldSucceed + + + [] + let ``Validate valid StartColumn values are unchanged by storing in Range`` () = + useValidateRoundTripTemplate """ +// Start Column only +validRangeValuesUnchanged 0 MaximumColumnValue 0 0 +""" + |> withReferenceFSharpCompilerService + |> asExe + |> compileAndRun + |> shouldSucceed + + + [] + let ``Validate valid StartLine values are unchanged by storing in Range`` () = + useValidateRoundTripTemplate """ +validRangeValuesUnchanged (MaximumStartLineValue - MaximumEndLineValue) 0 MaximumStartLineValue 0 +""" + |> withReferenceFSharpCompilerService + |> asExe + |> compileAndRun + |> shouldSucceed diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 756dbbce130..d7c1166d0ff 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -204,6 +204,7 @@ + diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index ca4065f6b14..eb74fb14c34 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -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.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 }