Skip to content
Closed
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
35 changes: 26 additions & 9 deletions src/Compiler/Utilities/range.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ open System
open System.IO
open System.Collections.Concurrent
open System.Collections.Generic
open System.Text
open Microsoft.FSharp.Core.Printf
open Internal.Utilities.Library
open Internal.Utilities.Library.Extras.Bits
Expand Down Expand Up @@ -258,6 +259,13 @@ module FileIndex =
let startupFileName = "startup"
let commandLineArgsFileName = "commandLineArgs"

let mutable internal testSource: string option = None

let internal setTestSource source =
testSource <- Some source
{ new IDisposable with
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we maybe make the source accessible from this object? So that we can pass it to parseTestSource directly in the tests. That would make the test code a bit clearer and if we ever need to change how we store this we wouldn't need to change the tests.

member this.Dispose() = testSource <- None }

[<Struct; CustomEquality; NoComparison>]
[<System.Diagnostics.DebuggerDisplay("({StartLine},{StartColumn}-{EndLine},{EndColumn}) {ShortFileName} -> {DebugCode}")>]
type Range(code1: int64, code2: int64) =
Expand Down Expand Up @@ -342,6 +350,22 @@ type Range(code1: int64, code2: int64) =
member _.Code2 = code2

member m.DebugCode =
let getRangeSubstring (m: range) (stream: Stream) =
let endCol = m.EndColumn - 1
let startCol = m.StartColumn - 1

stream.ReadLines()
|> Seq.skip (m.StartLine - 1)
|> Seq.take (m.EndLine - m.StartLine + 1)
|> String.concat "\n"
|> fun s -> s.Substring(startCol + 1, s.LastIndexOf("\n", StringComparison.Ordinal) + 1 - startCol + endCol)

match testSource with
| Some source ->
use stream = new MemoryStream(Encoding.UTF8.GetBytes(source + "\n"))
getRangeSubstring m stream
| _ ->

let name = m.FileName

if
Expand All @@ -351,21 +375,14 @@ type Range(code1: int64, code2: int64) =
then
name
else

try
let endCol = m.EndColumn - 1
let startCol = m.StartColumn - 1

if FileSystem.IsInvalidPathShim m.FileName then
"path invalid: " + m.FileName
elif not (FileSystem.FileExistsShim m.FileName) then
"non existing file: " + m.FileName
else
FileSystem.OpenFileForReadShim(m.FileName).ReadLines()
|> Seq.skip (m.StartLine - 1)
|> Seq.take (m.EndLine - m.StartLine + 1)
|> String.concat "\n"
|> fun s -> s.Substring(startCol + 1, s.LastIndexOf("\n", StringComparison.Ordinal) + 1 - startCol + endCol)
use stream = FileSystem.OpenFileForReadShim(m.FileName)
getRangeSubstring m stream
with e ->
e.ToString()

Expand Down
4 changes: 4 additions & 0 deletions src/Compiler/Utilities/range.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// The Range and Pos types form part of the public API of FSharp.Compiler.Service
namespace FSharp.Compiler.Text

open System
open System.Collections.Generic

/// An index into a global tables of filenames
Expand Down Expand Up @@ -183,6 +184,9 @@ module internal FileIndex =

val startupFileName: string

val mutable internal testSource: string option
val internal setTestSource: string -> IDisposable

module Range =

/// Ordering on positions
Expand Down
16 changes: 15 additions & 1 deletion tests/service/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,24 @@ let getParseAndCheckResultsPreview (source: string) =
let getParseAndCheckResults50 (source: string) =
parseAndCheckScript50("Test.fsx", source)

let parseTestSource () =
match FileIndex.testSource with
| None -> failwith "Test source is not set"
| Some source ->

let path = "Test.fsx"

let options =
{ FSharpParsingOptions.Default with
IsExe = true
SourceFiles = [| path |] }

let parseFileResults = checker.ParseFile(path, SourceText.ofString source, options) |> Async.RunSynchronously
parseFileResults.ParseTree

let getParseAndCheckResults70 (source: string) =
parseAndCheckScript70("Test.fsx", source)


let inline dumpDiagnostics (results: FSharpCheckFileResults) =
results.Diagnostics
|> Array.map (fun e ->
Expand Down
52 changes: 26 additions & 26 deletions tests/service/ParserTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ open NUnit.Framework

[<Test>]
let ``Interface impl - No members`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
type T =
interface I with
member x.P2 = ()

let x = ()
"""
match getSingleModuleMemberDecls parseResults with
match parseTestSource () |> getSingleModuleMemberDecls with
| [ SynModuleDecl.Types ([ SynTypeDefn (typeRepr = SynTypeDefnRepr.ObjectModel (members = [ _; _ ])) ], _)
SynModuleDecl.Let _ ] -> ()
| _ -> failwith "Unexpected tree"


[<Test>]
let ``Union case 01 - of`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
type U1 =
| A of

Expand All @@ -39,7 +39,7 @@ let x = ()
cases |> List.map (fun (SynUnionCase (ident = SynIdent(ident,_))) -> ident.idText) |> Some
| _ -> None

match getSingleModuleMemberDecls parseResults with
match parseTestSource () |> getSingleModuleMemberDecls with
| [ SynModuleDecl.Types ([ UnionWithCases ["A"]], _)
SynModuleDecl.Types ([ UnionWithCases ["B"; "C"] ], _)
SynModuleDecl.Let _ ] -> ()
Expand All @@ -48,72 +48,72 @@ let x = ()

[<Test>]
let ``Match clause 01`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
match () with
| x
"""
match getSingleExprInModule parseResults with
match parseTestSource () |> getSingleExprInModule with
| SynExpr.Match (clauses=[ SynMatchClause (resultExpr=SynExpr.ArbitraryAfterError _) ]) -> ()
| _ -> failwith "Unexpected tree"


[<Test>]
let ``Match clause 02 - When`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
match () with
| x when true
"""

match getSingleExprInModule parseResults with
match parseTestSource () |> getSingleExprInModule with
| SynExpr.Match (clauses=[ SynMatchClause (resultExpr=SynExpr.ArbitraryAfterError _) ]) -> ()
| _ -> failwith "Unexpected tree"

[<Test>]
let ``Match clause 03 - When`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
match () with
| x when true
| _ -> ()
"""

match getSingleExprInModule parseResults with
match parseTestSource () |> getSingleExprInModule with
| SynExpr.Match (clauses=[ SynMatchClause (resultExpr=SynExpr.ArbitraryAfterError _); _ ]) -> ()
| _ -> failwith "Unexpected tree"

[<Test>]
let ``Match clause 04 - Or pat`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
match () with
| x
| _ -> ()
"""

match getSingleExprInModule parseResults with
match parseTestSource () |> getSingleExprInModule with
| SynExpr.Match (clauses=[ SynMatchClause (pat=SynPat.Or _;resultExpr=SynExpr.Const _) ]) -> ()
| _ -> failwith "Unexpected tree"

[<Test>]
let ``Match clause 05 - Missing body`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
match () with
| x ->
| _ -> ()
"""

match getSingleExprInModule parseResults with
match parseTestSource () |> getSingleExprInModule with
| SynExpr.Match (clauses=[ SynMatchClause (resultExpr=SynExpr.ArbitraryAfterError _)
SynMatchClause (resultExpr=SynExpr.Const _) ]) -> ()
| _ -> failwith "Unexpected tree"

[<Test>]
let ``Match clause 06`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
match () with
| (x
| y -> ()
"""

match getSingleExprInModule parseResults with
match parseTestSource () |> getSingleExprInModule with
| SynExpr.Match (clauses=[ SynMatchClause (pat=pat) ]) ->
match pat with
| SynPat.FromParseError (SynPat.Paren (SynPat.Or (SynPat.Named _, SynPat.Named _, _, _), _), _) -> ()
Expand All @@ -122,13 +122,13 @@ match () with

[<Test>]
let ``Match clause 07`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
match () with
| (x,
| y -> ()
"""

match getSingleExprInModule parseResults with
match parseTestSource () |> getSingleExprInModule with
| SynExpr.Match (clauses=[ SynMatchClause (pat=pat) ]) ->
match pat with
| SynPat.Paren(SynPat.Or(SynPat.Tuple(elementPats = [SynPat.Named _; SynPat.Wild _]), SynPat.Named _, _, _), _) -> ()
Expand All @@ -137,24 +137,24 @@ match () with

[<Test>]
let ``Match clause 08 - Range`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
match () with
| a
b
"""
match getSingleModuleMemberDecls parseResults with
match parseTestSource () |> getSingleModuleMemberDecls with
| [ SynModuleDecl.Expr (expr=(SynExpr.Match _ as m)); SynModuleDecl.Expr (expr=(SynExpr.Ident _ as i)) ] ->
Assert.True(Position.posLt m.Range.End i.Range.Start)
| _ -> failwith "Unexpected tree"


[<Test>]
let ``Let - Parameter - Paren 01`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
let f (x
"""

match getSingleDeclInModule parseResults with
match parseTestSource () |> getSingleDeclInModule with
| SynModuleDecl.Let (_, [ SynBinding (headPat = headPat) ], _) ->
match headPat with
| SynPat.LongIdent (argPats=SynArgPats.Pats [ SynPat.FromParseError (SynPat.Paren (SynPat.Named _, _), _) ]) -> ()
Expand All @@ -163,11 +163,11 @@ let f (x

[<Test>]
let ``Let - Parameter - Paren 02 - Tuple`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
let f (x, y
"""

match getSingleDeclInModule parseResults with
match parseTestSource () |> getSingleDeclInModule with
| SynModuleDecl.Let (_, [ SynBinding (headPat = headPat) ], _) ->
match headPat with
| SynPat.LongIdent (argPats=SynArgPats.Pats [ SynPat.FromParseError (SynPat.Paren (SynPat.Tuple _, _), _) ]) -> ()
Expand All @@ -176,11 +176,11 @@ let f (x, y

[<Test>]
let ``Let - Parameter - Paren 03 - Tuple`` () =
let parseResults = getParseResults """
use _ = FileIndex.setTestSource """
let f (x,
"""

match getSingleDeclInModule parseResults with
match parseTestSource () |> getSingleDeclInModule with
| SynModuleDecl.Let (_, [ SynBinding (headPat = SynPat.LongIdent (argPats = SynArgPats.Pats [ pat ])) ], _) ->
match pat with
| SynPat.FromParseError (SynPat.Paren (SynPat.Tuple(elementPats = [SynPat.Named _; SynPat.Wild _]), _), _) -> ()
Expand Down