From ab0fc65148de33e7ca27703223495cd55049f2f0 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sat, 24 Nov 2018 22:31:44 +0200 Subject: [PATCH 1/5] Dive into types in type test expressions in AST visitor --- src/fsharp/service/ServiceParseTreeWalk.fs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/fsharp/service/ServiceParseTreeWalk.fs b/src/fsharp/service/ServiceParseTreeWalk.fs index 660528e03ee..14e08c9b2de 100755 --- a/src/fsharp/service/ServiceParseTreeWalk.fs +++ b/src/fsharp/service/ServiceParseTreeWalk.fs @@ -456,9 +456,12 @@ module public AstTraversal = dive synExpr2 synExpr2.Range traverseSynExpr dive synExpr3 synExpr3.Range traverseSynExpr] |> pick expr - | SynExpr.TypeTest(synExpr, _synType, _range) -> traverseSynExpr synExpr - | SynExpr.Upcast(synExpr, _synType, _range) -> traverseSynExpr synExpr - | SynExpr.Downcast(synExpr, _synType, _range) -> traverseSynExpr synExpr + | SynExpr.TypeTest(synExpr, synType, _range) + | SynExpr.Upcast(synExpr, synType, _range) + | SynExpr.Downcast(synExpr, synType, _range) -> + [dive synExpr synExpr.Range traverseSynExpr + dive synType synType.Range traverseSynType] + |> pick expr | SynExpr.InferredUpcast(synExpr, _range) -> traverseSynExpr synExpr | SynExpr.InferredDowncast(synExpr, _range) -> traverseSynExpr synExpr | SynExpr.Null(_range) -> None From 1130a5597dbbb44e00a9ac5935dd9c5a304501ee Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 11 Dec 2018 23:24:37 +0300 Subject: [PATCH 2/5] Add test --- .../FSharp.Compiler.Service.Tests.fsproj | 3 +++ tests/service/Common.fs | 17 ++++++------ tests/service/InteractiveCheckerTests.fs | 6 +---- tests/service/StructureTests.fs | 26 ++++++++----------- tests/service/TreeVisitorTests.fs | 22 ++++++++++++++++ .../UnitTests/VisualFSharp.UnitTests.fsproj | 3 +++ 6 files changed, 49 insertions(+), 28 deletions(-) create mode 100644 tests/service/TreeVisitorTests.fs diff --git a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 8d09c3a26f1..b8371a5e479 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -69,6 +69,9 @@ Program.fs + + TreeVisitorTests.fs + diff --git a/tests/service/Common.fs b/tests/service/Common.fs index 07c2484e70a..6999e97a2b2 100644 --- a/tests/service/Common.fs +++ b/tests/service/Common.fs @@ -195,17 +195,18 @@ let parseAndCheckScript (file, input) = | FSharpCheckFileAnswer.Succeeded(res) -> parseResult, res | res -> failwithf "Parsing did not finish... (%A)" res -let parseSourceCode (name: string, code: string) = - let location = Path.Combine(Path.GetTempPath(),"test"+string(hash (name, code))) - try Directory.CreateDirectory(location) |> ignore with _ -> () +let parseSource (source: string) = + let location = Path.GetTempFileName() + let filePath = Path.Combine(location, ".fs") + let dllPath = Path.Combine(location, ".dll") - let projPath = Path.Combine(location, name + ".fsproj") - let filePath = Path.Combine(location, name + ".fs") - let dllPath = Path.Combine(location, name + ".dll") let args = mkProjectCommandLineArgs(dllPath, [filePath]) let options, errors = checker.GetParsingOptionsFromCommandLineArgs(List.ofArray args) - let parseResults = checker.ParseFile(filePath, code, options) |> Async.RunSynchronously - parseResults.ParseTree + let parseResults = checker.ParseFile(filePath, source, options) |> Async.RunSynchronously + + match parseResults.ParseTree with + | Some parseTree -> parseTree + | None -> failwithf "Expected there to be a parse tree for source:\n%s" source /// Extract range info let tups (m:Range.range) = (m.StartLine, m.StartColumn), (m.EndLine, m.EndColumn) diff --git a/tests/service/InteractiveCheckerTests.fs b/tests/service/InteractiveCheckerTests.fs index fba9adcb639..136505b6dd2 100644 --- a/tests/service/InteractiveCheckerTests.fs +++ b/tests/service/InteractiveCheckerTests.fs @@ -54,11 +54,7 @@ let internal identsAndRanges (input: Ast.ParsedInput) = | Ast.ParsedInput.SigFile _ -> [] let internal parseAndExtractRanges code = - let file = "Test" - let result = parseSourceCode (file, code) - match result with - | Some tree -> tree |> identsAndRanges - | None -> failwith "fail to parse..." + parseSource code |> identsAndRanges let input = """ diff --git a/tests/service/StructureTests.fs b/tests/service/StructureTests.fs index d87c3c18e78..7b353bcdb2e 100644 --- a/tests/service/StructureTests.fs +++ b/tests/service/StructureTests.fs @@ -40,23 +40,19 @@ let (=>) (source: string) (expectedRanges: (Range * Range) list) = let getRange (r: range) = (r.StartLine, r.StartColumn, r.EndLine, r.EndColumn) - let ast = parseSourceCode(fileName, source) - + let tree = parseSource source try - match ast with - | Some tree -> - let actual = - Structure.getOutliningRanges lines tree - |> Seq.filter (fun sr -> sr.Range.StartLine <> sr.Range.EndLine) - |> Seq.map (fun sr -> getRange sr.Range, getRange sr.CollapseRange) - |> Seq.sort - |> List.ofSeq - let expected = List.sort expectedRanges - if actual <> expected then - failwithf "Expected %s, but was %s" (formatList expected) (formatList actual) - | None -> failwithf "Expected there to be a parse tree for source:\n%s" source + let actual = + Structure.getOutliningRanges lines tree + |> Seq.filter (fun sr -> sr.Range.StartLine <> sr.Range.EndLine) + |> Seq.map (fun sr -> getRange sr.Range, getRange sr.CollapseRange) + |> Seq.sort + |> List.ofSeq + let expected = List.sort expectedRanges + if actual <> expected then + failwithf "Expected %s, but was %s" (formatList expected) (formatList actual) with _ -> - printfn "AST:\n%+A" ast + printfn "AST:\n%+A" tree reraise() [] diff --git a/tests/service/TreeVisitorTests.fs b/tests/service/TreeVisitorTests.fs new file mode 100644 index 00000000000..3003619a7a4 --- /dev/null +++ b/tests/service/TreeVisitorTests.fs @@ -0,0 +1,22 @@ +module Tests.Service.TreeVisitorTests + +open FSharp.Compiler.Service.Tests.Common +open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.SourceCodeServices.AstTraversal +open NUnit.Framework + +[] +let ``Visit type`` () = + let visitor = + { new AstVisitorBase<_>() with + member x.VisitExpr(_, _, defaultTraverse, expr) = defaultTraverse expr + member x.VisitType(_, _) = Some () } + + let source = "123 :? int" + let parseTree = parseSource source + + Traverse(mkPos 1 11, parseTree, visitor) + |> Option.defaultWith (fun _ -> failwith "Did not visit type") + + Traverse(mkPos 1 3, parseTree, visitor) + |> Option.map (fun _ -> failwith "Should not visit type") |> ignore diff --git a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj index 27b6d0224e3..2ef7eccb6e9 100644 --- a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj +++ b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj @@ -107,6 +107,9 @@ CompilerService\UnusedOpensTests.fs + + CompilerService\TreeVisitorTests.fs + Roslyn\SyntacticColorizationServiceTests.fs From 11fe286b5e575a396ff8742b69e78f832e022cae Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 12 Dec 2018 16:15:44 +0300 Subject: [PATCH 3/5] Update VisualFSharp test --- tests/service/ServiceUntypedParseTests.fs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/service/ServiceUntypedParseTests.fs b/tests/service/ServiceUntypedParseTests.fs index d47acf69de2..ccda4f5bac4 100644 --- a/tests/service/ServiceUntypedParseTests.fs +++ b/tests/service/ServiceUntypedParseTests.fs @@ -40,14 +40,12 @@ let private (=>) (source: string) (expected: CompletionContext option) = match markerPos with | None -> failwithf "Marker '%s' was not found in the source code" Marker | Some markerPos -> - match parseSourceCode("C:\\test.fs", source) with - | None -> failwith "No parse tree" - | Some parseTree -> - let actual = UntypedParseImpl.TryGetCompletionContext(markerPos, parseTree, lines.[Line.toZ markerPos.Line]) - try Assert.AreEqual(expected, actual) - with e -> - printfn "ParseTree: %A" parseTree - reraise() + let parseTree = parseSource source + let actual = UntypedParseImpl.TryGetCompletionContext(markerPos, parseTree, lines.[Line.toZ markerPos.Line]) + try Assert.AreEqual(expected, actual) + with e -> + printfn "ParseTree: %A" parseTree + reraise() module AttributeCompletion = [] From 46b55bb066be186d6ba0d5f076ed49b569377506 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 12 Dec 2018 16:26:42 +0300 Subject: [PATCH 4/5] Update fsproj --- .../FSharp.Compiler.Service.Tests.fsproj | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index b8371a5e479..ed1eda7dd31 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -66,12 +66,15 @@ TokenizerTests.fs - - Program.fs + + ServiceUntypedParseTests.fs TreeVisitorTests.fs + + Program.fs + From 861e99da1e4e5af3ece063792ad1fa4168c8c7de Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 12 Dec 2018 16:38:54 +0300 Subject: [PATCH 5/5] Cleanup test --- tests/service/TreeVisitorTests.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/service/TreeVisitorTests.fs b/tests/service/TreeVisitorTests.fs index 3003619a7a4..e81d140011e 100644 --- a/tests/service/TreeVisitorTests.fs +++ b/tests/service/TreeVisitorTests.fs @@ -6,7 +6,7 @@ open Microsoft.FSharp.Compiler.SourceCodeServices.AstTraversal open NUnit.Framework [] -let ``Visit type`` () = +let ``Visit type test`` () = let visitor = { new AstVisitorBase<_>() with member x.VisitExpr(_, _, defaultTraverse, expr) = defaultTraverse expr @@ -19,4 +19,4 @@ let ``Visit type`` () = |> Option.defaultWith (fun _ -> failwith "Did not visit type") Traverse(mkPos 1 3, parseTree, visitor) - |> Option.map (fun _ -> failwith "Should not visit type") |> ignore + |> Option.iter (fun _ -> failwith "Should not visit type")