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..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,6 +66,12 @@
TokenizerTests.fs
+
+ ServiceUntypedParseTests.fs
+
+
+ TreeVisitorTests.fs
+
Program.fs
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
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/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 =
[]
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..e81d140011e
--- /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 test`` () =
+ 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.iter (fun _ -> failwith "Should not visit type")
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