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 8686318fe23ab517b34b42a7a208ab1055f74840..e83bc805c0053c15ac4f86e8e90bf2a46c55185e 100644
--- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj
+++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj
@@ -70,6 +70,9 @@
ProjectOptionsTests.fs
+
+ StructureTests.fs
+
FSharp.Core.optdata
PreserveNewest
diff --git a/src/fsharp/vs/ServiceStructure.fs b/src/fsharp/vs/ServiceStructure.fs
index 35e3d2383e4b5ccfcb84e44a9882705fbdbda778..ffe2461d95948fc3fd97abe366b7f46d73ac6dc8 100644
--- a/src/fsharp/vs/ServiceStructure.fs
+++ b/src/fsharp/vs/ServiceStructure.fs
@@ -228,8 +228,7 @@ module Structure =
| SynExpr.DotIndexedGet (e,_,_,_)
| SynExpr.DotIndexedSet (e,_,_,_,_,_) -> parseExpr e
| SynExpr.New (_,_,expr,r) ->
- let collapse = Range.endToEnd expr.Range r
- rcheck Scope.New Collapse.Below r collapse
+ rcheck Scope.New Collapse.Below r expr.Range
parseExpr expr
| SynExpr.YieldOrReturn (_,e,r) ->
rcheck Scope.YieldOrReturn Collapse.Below r r
diff --git a/tests/service/StructureTests.fs b/tests/service/StructureTests.fs
index 6e80a66bba227a231602c99e4d277873a4bd9218..cbfc937a384f3ddc61ea89bdc9fd36e2bb9fb7ef 100644
--- a/tests/service/StructureTests.fs
+++ b/tests/service/StructureTests.fs
@@ -9,15 +9,18 @@ module Tests.Service.StructureTests
open System.IO
open NUnit.Framework
+open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.SourceCodeServices
+open Microsoft.FSharp.Compiler.SourceCodeServices.Structure
open FSharp.Compiler.Service.Tests.Common
open System.Text
let fileName = Path.Combine (__SOURCE_DIRECTORY__, __SOURCE_FILE__)
type Line = int
type Col = int
+type Range = Line * Col * Line * Col
-let (=>) (source: string) (expectedRanges: (Line * Col * Line * Col) list) =
+let (=>) (source: string) (expectedRanges: (Range * Range) list) =
let lines =
use reader = new StringReader(source)
[| let line = ref (reader.ReadLine())
@@ -35,14 +38,17 @@ let (=>) (source: string) (expectedRanges: (Line * Col * Line * Col) list) =
sb.AppendLine (sprintf "%A" r) |> ignore
sprintf "%O ]" sb
+ let getRange (r: range) = (r.StartLine, r.StartColumn, r.EndLine, r.EndColumn)
+
let ast = parseSourceCode(fileName, 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 r -> r.Range.StartLine, r.Range.StartColumn, r.Range.EndLine, r.Range.EndColumn)
+ |> Seq.map (fun sr -> getRange sr.Range, getRange sr.CollapseRange)
|> Seq.sort
|> List.ofSeq
let expected = List.sort expectedRanges
@@ -54,7 +60,7 @@ let (=>) (source: string) (expectedRanges: (Line * Col * Line * Col) list) =
reraise()
[]
-let ``empty file``() = "" => [ (1, 0, 2, 0) ]
+let ``empty file``() = "" => [ (1, 0, 2, 0), (1, 0, 2, 0) ]
[]
let ``nested module``() =
@@ -62,8 +68,8 @@ let ``nested module``() =
module MyModule =
()
"""
- => [ (1, 0, 4, 0)
- (2, 0, 3, 6) ]
+ => [ (1, 0, 4, 0), (1, 0, 4, 0)
+ (2, 0, 3, 6), (2, 15, 3, 6) ]
[]
let ``module with multiline function``() =
@@ -72,10 +78,10 @@ module MyModule =
let foo() =
foo()
"""
- => [ (1, 0, 5, 0)
- (2, 0, 4, 13)
- (3, 4, 4, 13)
- (3, 8, 4, 13) ]
+ => [ (1, 0, 5, 0), (1, 0, 5, 0)
+ (2, 0, 4, 13), (2, 15, 4, 13)
+ (3, 4, 4, 13), (3, 13, 4, 13)
+ (3, 8, 4, 13), (3, 13, 4, 13) ]
[]
let ``DU``() =
@@ -85,9 +91,9 @@ type Color =
| Green
| Blue
"""
- => [ (1, 0, 6, 0)
- (2, 5, 5, 10)
- (3, 4, 5, 10) ]
+ => [ (1, 0, 6, 0), (1, 0, 6, 0)
+ (2, 5, 5, 10), (2, 11, 5, 10)
+ (3, 4, 5, 10), (3, 4, 5, 10) ]
[]
let ``DU with interface``() =
@@ -101,12 +107,12 @@ type Color =
member __.Dispose() =
(docEventListener :> IDisposable).Dispose()
"""
- => [ (1, 0, 10, 0)
- (2, 5, 9, 55)
- (3, 4, 5, 10)
- (7, 4, 9, 55)
- (8, 15, 9, 55)
- (8, 15, 9, 55) ]
+ => [ (1, 0, 10, 0), (1, 0, 10, 0)
+ (2, 5, 9, 55), (2, 11, 9, 55)
+ (3, 4, 5, 10), (3, 4, 5, 10)
+ (7, 4, 9, 55), (7, 25, 9, 55)
+ (8, 15, 9, 55), (8, 27, 9, 55)
+ (8, 15, 9, 55), (8, 27, 9, 55) ]
[]
let ``record with interface``() =
@@ -122,13 +128,13 @@ type Color =
(docEventListener :> IDisposable).Dispose()
"""
=>
- [ (1, 0, 11, 0)
- (2, 5, 10, 55)
- (3, 4, 4, 14)
- (3, 6, 4, 13)
- (8, 4, 10, 55)
- (9, 15, 10, 55)
- (9, 15, 10, 55) ]
+ [ (1, 0, 11, 0), (1, 0, 11, 0)
+ (2, 5, 10, 55), (2, 11, 10, 55)
+ (3, 4, 4, 14), (3, 4, 4, 14)
+ (3, 6, 4, 13), (3, 6, 4, 13)
+ (8, 4, 10, 55), (8, 25, 10, 55)
+ (9, 15, 10, 55), (9, 27, 10, 55)
+ (9, 15, 10, 55), (9, 27, 10, 55) ]
[]
let ``type with a do block``() =
@@ -141,10 +147,10 @@ type Color() = // 2
foo()
() // 8
"""
- => [ (1, 0, 9, 0)
- (2, 5, 8, 10)
- (3, 8, 4, 10)
- (6, 4, 8, 10) ]
+ => [ (1, 0, 9, 0), (1, 0, 9, 0)
+ (2, 5, 8, 10), (2, 11, 8, 10)
+ (3, 8, 4, 10), (3, 13, 4, 10)
+ (6, 4, 8, 10), (6, 6, 8, 10) ]
[]
let ``complex outlining test``() =
@@ -176,21 +182,21 @@ module MyModule = // 2
member __.Dispose() =
(docEventListener :> IDisposable).Dispose()
"""
- => [ (1, 0, 28, 0)
- (2, 0, 27, 63)
- (4, 4, 5, 10)
- (4, 8, 5, 10)
- (7, 9, 15, 59)
- (8, 8, 11, 9)
- (13, 8, 15, 59)
- (14, 19, 15, 59)
- (14, 19, 15, 59)
- (17, 4, 27, 63)
- (19, 13, 27, 63)
- (20, 12, 23, 13)
- (25, 12, 27, 63)
- (26, 23, 27, 63)
- (26, 23, 27, 63) ]
+ => [ (1, 0, 28, 0), (1, 0, 28, 0)
+ (2, 0, 27, 63), (2, 15, 27, 63)
+ (4, 4, 5, 10), (4, 13, 5, 10)
+ (4, 8, 5, 10), (4, 13, 5, 10)
+ (7, 9, 15, 59), (7, 15, 15, 59)
+ (8, 8, 11, 9), (8, 8, 11, 9)
+ (13, 8, 15, 59), (13, 29, 15, 59)
+ (14, 19, 15, 59), (14, 31, 15, 59)
+ (14, 19, 15, 59), (14, 31, 15, 59)
+ (17, 4, 27, 63), (17, 24, 27, 63)
+ (19, 13, 27, 63), (19, 25, 27, 63)
+ (20, 12, 23, 13), (20, 12, 23, 13)
+ (25, 12, 27, 63), (25, 33, 27, 63)
+ (26, 23, 27, 63), (26, 35, 27, 63)
+ (26, 23, 27, 63), (26, 35, 27, 63) ]
[]
@@ -222,14 +228,14 @@ open H
open G
open H
"""
- => [ (1, 0, 26, 6)
- (2, 5, 3, 6)
- (5, 0, 19, 17)
- (8, 9, 9, 10)
- (11, 4, 14, 17)
- (16, 4, 19, 17)
- (17, 13, 18, 14)
- (21, 5, 26, 6) ]
+ => [ (1, 0, 26, 6), (1, 0, 26, 6)
+ (2, 5, 3, 6), (2, 5, 3, 6)
+ (5, 0, 19, 17), (5, 8, 19, 17)
+ (8, 9, 9, 10), (8, 9, 9, 10)
+ (11, 4, 14, 17), (11, 12, 14, 17)
+ (16, 4, 19, 17), (16, 12, 19, 17)
+ (17, 13, 18, 14), (17, 13, 18, 14)
+ (21, 5, 26, 6), (21, 5, 26, 6) ]
[]
let ``hash directives``() =
@@ -257,9 +263,9 @@ let x = 1
"c"
#r "d"
"""
- => [ (1, 0, 23, 6)
- (2, 3, 8, 6)
- (11, 3, 23, 6) ]
+ => [ (1, 0, 23, 6), (1, 0, 23, 6)
+ (2, 3, 8, 6), (2, 3, 8, 6)
+ (11, 3, 23, 6), (11, 3, 23, 6) ]
[]
let ``nested let bindings``() =
@@ -271,11 +277,11 @@ let f x = // 2
() // 6
x // 7
"""
- => [ (1, 0, 8, 0)
- (2, 0, 7, 5)
- (2, 4, 7, 5)
- (3, 8, 6, 10)
- (4, 12, 5, 14) ]
+ => [ (1, 0, 8, 0), (1, 0, 8, 0)
+ (2, 0, 7, 5), (2, 7, 7, 5)
+ (2, 4, 7, 5), (2, 7, 7, 5)
+ (3, 8, 6, 10), (3, 11, 6, 10)
+ (4, 12, 5, 14), (4, 13, 5, 14) ]
[]
let ``match``() =
@@ -290,11 +296,11 @@ match None with // 2
let x = () // 9
() // 10
"""
- => [ (1, 0, 11, 0)
- (2, 0, 10, 10)
- (6, 4, 10, 10)
- (6, 4, 10, 10)
- (9, 8, 10, 10) ]
+ => [ (1, 0, 11, 0), (1, 0, 11, 0)
+ (2, 0, 10, 10), (2, 15, 10, 10)
+ (6, 4, 10, 10), (5, 6, 10, 10)
+ (6, 4, 10, 10), (6, 19, 10, 10)
+ (9, 8, 10, 10), (8, 10, 10, 10) ]
[]
let ``computation expressions``() =
@@ -307,11 +313,11 @@ seq { // 2
yield () } // 7
} // 8
"""
- => [ (1, 0, 8, 1)
- (2, 0, 8, 1)
- (4, 8, 5, 10)
- (6, 4, 7, 18)
- (6, 11, 7, 18) ]
+ => [ (1, 0, 8, 1), (1, 0, 8, 1)
+ (2, 0, 8, 1), (2, 5, 8, 0)
+ (4, 8, 5, 10), (4, 11, 5, 10)
+ (6, 4, 7, 18), (6, 4, 7, 18)
+ (6, 11, 7, 18), (6, 16, 7, 17) ]
[]
let ``list``() =
@@ -320,10 +326,10 @@ let _ =
[ 1; 2
3 ]
"""
- => [ (1, 0, 5, 0)
- (2, 0, 4, 9)
- (2, 4, 4, 9)
- (3, 4, 4, 9) ]
+ => [ (1, 0, 5, 0), (1, 0, 5, 0)
+ (2, 0, 4, 9), (2, 5, 4, 9)
+ (2, 4, 4, 9), (2, 5, 4, 9)
+ (3, 4, 4, 9), (3, 5, 4, 8) ]
[]
let ``object expressions``() =
@@ -332,10 +338,10 @@ let _ =
{ new System.IDisposable with
member __.Dispose() = () }
"""
- => [ (1, 0, 5, 0)
- (2, 0, 4, 34)
- (2, 4, 4, 34)
- (3, 4, 4, 34) ]
+ => [ (1, 0, 5, 0), (1, 0, 5, 0)
+ (2, 0, 4, 34), (2, 5, 4, 34)
+ (2, 4, 4, 34), (2, 5, 4, 34)
+ (3, 4, 4, 34), (3, 28, 4, 34) ]
[]
let ``try - with``() =
@@ -348,13 +354,13 @@ with _ -> // 5
() // 7
() // 8
"""
- => [ (1, 0, 9, 0)
- (2, 0, 5, 0)
- (2, 0, 8, 6)
- (3, 8, 4, 10)
- (5, 0, 8, 6)
- (6, 4, 8, 6)
- (6, 8, 7, 10) ]
+ => [ (1, 0, 9, 0), (1, 0, 9, 0)
+ (2, 0, 5, 0), (2, 3, 5, 0)
+ (2, 0, 8, 6), (2, 3, 8, 6)
+ (3, 8, 4, 10), (3, 11, 4, 10)
+ (5, 0, 8, 6), (5, 4, 8, 6)
+ (6, 4, 8, 6), (5, 6, 8, 6)
+ (6, 8, 7, 10), (6, 11, 7, 10) ]
[]
let ``try - finally``() =
@@ -367,11 +373,11 @@ finally // 5
() // 7
() // 8
"""
- => [ (1, 0, 9, 0)
- (2, 0, 8, 6)
- (3, 8, 4, 10)
- (5, 0, 8, 6)
- (6, 8, 7, 10) ]
+ => [ (1, 0, 9, 0), (1, 0, 9, 0)
+ (2, 0, 8, 6), (2, 3, 8, 6)
+ (3, 8, 4, 10), (3, 11, 4, 10)
+ (5, 0, 8, 6), (5, 7, 8, 6)
+ (6, 8, 7, 10), (6, 11, 7, 10) ]
[]
let ``if - then - else``() =
@@ -385,11 +391,11 @@ else
()
()
"""
- => [ (1, 0, 10, 0)
- (2, 0, 9, 6)
- (2, 8, 5, 6)
- (3, 8, 4, 10)
- (7, 8, 8, 10) ]
+ => [ (1, 0, 10, 0), (1, 0, 10, 0)
+ (2, 0, 9, 6), (2, 7, 9, 6)
+ (2, 8, 5, 6), (2, 12, 5, 6)
+ (3, 8, 4, 10), (3, 11, 4, 10)
+ (7, 8, 8, 10), (7, 11, 8, 10) ]
[]
let ``code quotation``() =
@@ -398,8 +404,8 @@ let ``code quotation``() =
"code"
@>
"""
- => [ 1, 0, 4, 10
- 2, 0, 4, 10 ]
+ => [ (1, 0, 4, 10), (1, 0, 4, 10)
+ (2, 0, 4, 10), (2, 2, 4, 8) ]
[]
let ``raw code quotation``() =
@@ -408,8 +414,8 @@ let ``raw code quotation``() =
"code"
@@>
"""
- => [ (1, 0, 4, 11)
- (2, 0, 4, 11) ]
+ => [ (1, 0, 4, 11), (1, 0, 4, 11)
+ (2, 0, 4, 11), (2, 3, 4, 8) ]
[]
let ``match lambda aka function``() =
@@ -418,9 +424,9 @@ function
| 0 -> ()
()
"""
- => [ (1, 0, 5, 0)
- (2, 0, 4, 10)
- (3, 8, 4, 10) ]
+ => [ (1, 0, 5, 0), (1, 0, 5, 0)
+ (2, 0, 4, 10), (2, 8, 4, 10)
+ (3, 8, 4, 10), (3, 3, 4, 10) ]
[]
let ``match guarded clause``() =
@@ -430,11 +436,11 @@ let matchwith num =
| 0 -> ()
()
"""
- => [ (1, 0, 6, 0)
- (2, 0, 5, 13)
- (2, 4, 5, 13)
- (3, 4, 5, 13)
- (4, 11, 5, 13) ]
+ => [ (1, 0, 6, 0), (1, 0, 6, 0)
+ (2, 0, 5, 13), (2, 17, 5, 13)
+ (2, 4, 5, 13), (2, 17, 5, 13)
+ (3, 4, 5, 13), (3, 18, 5, 13)
+ (4, 11, 5, 13), (4, 7, 5, 13) ]
[]
let ``for loop``() =
@@ -443,8 +449,8 @@ for x = 100 downto 10 do
()
()
"""
- => [ (1, 0, 5, 0)
- (2, 0, 4, 6) ]
+ => [ (1, 0, 5, 0), (1, 0, 5, 0)
+ (2, 0, 4, 6), (2, 0, 4, 6) ]
[]
let ``for each``() =
@@ -453,9 +459,9 @@ for x in 0 .. 100 ->
()
()
"""
- => [ (1, 0, 5, 0)
- (2, 0, 4, 14)
- (2, 18, 4, 14) ]
+ => [ (1, 0, 5, 0), (1, 0, 5, 0)
+ (2, 0, 4, 14), (2, 0, 4, 14)
+ (2, 18, 4, 14), (2, 18, 4, 14) ]
[]
let ``tuple``() =
@@ -464,8 +470,8 @@ let ``tuple``() =
, 322
, 123123 )
"""
- => [ (1, 0, 4, 10)
- (2, 2, 4, 8) ]
+ => [ (1, 0, 4, 10), (1, 0, 4, 10)
+ (2, 2, 4, 8), (2, 2, 4, 8) ]
[]
let ``do!``() =
@@ -474,8 +480,8 @@ do!
printfn "allo"
printfn "allo"
"""
- => [(1, 0, 5, 0)
- (2, 0, 4, 18)]
+ => [(1, 0, 5, 0), (1, 0, 5, 0)
+ (2, 0, 4, 18), (2, 3, 4, 18)]
[]
let ``cexpr yield yield!``() =
@@ -489,11 +495,11 @@ cexpr{
}
}
"""
- => [1, 0, 9, 5
- 2, 0, 9, 5
- 3, 4, 8, 17
- 4, 8, 8, 17
- 5, 20, 7, 26]
+ => [(1, 0, 9, 5), (1, 0, 9, 5)
+ (2, 0, 9, 5), (2, 6, 9, 4)
+ (3, 4, 8, 17), (3, 4, 8, 17)
+ (4, 8, 8, 17), (4, 14, 8, 16)
+ (5, 20, 7, 26), (5, 20, 7, 26)]
[]
let ``XML doc comments``() =
@@ -511,12 +517,12 @@ module M =
/// Single line comment
let f x = x
"""
- => [ (1, 0, 14, 0)
- (2, 0, 3, 10)
- (4, 0, 13, 15)
- (5, 4, 6, 14)
- (7, 9, 11, 19)
- (8, 8, 10, 18) ]
+ => [ (1, 0, 14, 0), (1, 0, 14, 0)
+ (2, 0, 3, 10), (2, 0, 3, 10)
+ (4, 0, 13, 15), (4, 8, 13, 15)
+ (5, 4, 6, 14), (5, 4, 6, 14)
+ (7, 9, 11, 19), (7, 11, 11, 19)
+ (8, 8, 10, 18), (8, 8, 10, 18) ]
[]
let ``regular comments``() =
@@ -534,12 +540,12 @@ module M =
// Single line comment
let f x = x
"""
- => [ (1, 0, 14, 0)
- (2, 0, 3, 9)
- (4, 0, 13, 15)
- (5, 4, 6, 13)
- (7, 9, 11, 19)
- (8, 8, 10, 17) ]
+ => [ (1, 0, 14, 0), (1, 0, 14, 0)
+ (2, 0, 3, 9), (2, 0, 3, 9)
+ (4, 0, 13, 15), (4, 8, 13, 15)
+ (5, 4, 6, 13), (5, 4, 6, 13)
+ (7, 9, 11, 19), (7, 11, 11, 19)
+ (8, 8, 10, 17), (8, 8, 10, 17) ]
[]
let ``XML doc and regular comments in one block``() =
@@ -554,7 +560,23 @@ let ``XML doc and regular comments in one block``() =
/// Line 8
/// Line 9
"""
- => [ (1, 0, 11, 0)
- (2, 0, 3, 9)
- (4, 0, 5, 10)
- (7, 0, 10, 10) ]
\ No newline at end of file
+ => [ (1, 0, 11, 0), (1, 0, 11, 0)
+ (2, 0, 3, 9), (2, 0, 3, 9)
+ (4, 0, 5, 10), (4, 0, 5, 10)
+ (7, 0, 10, 10), (7, 0, 10, 10) ]
+
+[]
+let ``constructor call``() =
+ """
+module M =
+ let s =
+ new System.String(
+ 'c',
+ 1)
+"""
+ => [ (1, 0, 7, 0), (1, 0, 7, 0)
+ (2, 0, 6, 14), (2, 8, 6, 14)
+ (3, 4, 6, 14), (3, 9, 6, 14)
+ (3, 8, 6, 14), (3, 9, 6, 14)
+ (4, 8, 6, 14), (4, 25, 6, 14)
+ (5, 12, 6, 13), (5, 12, 6, 13) ]