From d3b2d620f8e28fda09d639a660b6197a25068f75 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sat, 28 Mar 2020 00:30:46 +0300 Subject: [PATCH 1/3] Initial ranges collection --- .../FSharp.Compiler.Service.Tests.fsproj | 5 +- .../FSharp.Compiler.Service.fsproj | 3 + src/fsharp/NameResolution.fs | 25 ++- src/fsharp/NameResolution.fsi | 13 +- src/fsharp/RangeScopedCollection.fs | 53 ++++++ src/fsharp/TypeChecker.fs | 1 + src/fsharp/range.fs | 3 + src/fsharp/range.fsi | 2 + src/fsharp/service/FSharpCheckerResults.fs | 34 ++-- tests/service/RangeScopedCollectionTests.fs | 156 ++++++++++++++++++ 10 files changed, 271 insertions(+), 24 deletions(-) create mode 100644 src/fsharp/RangeScopedCollection.fs create mode 100644 tests/service/RangeScopedCollectionTests.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 a070bb8cdac..e2cabf402e8 100644 --- a/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -1,4 +1,4 @@ - + @@ -19,6 +19,9 @@ Common.fs + + RangeScopedCollectionTests.fs + AssemblyReaderShim.fs diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index ba7364151aa..22076780654 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -187,6 +187,9 @@ ErrorLogging/range.fs + + ErrorLogging/RangeScopedCollection.fs + ErrorLogging/ErrorLogger.fs diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 9f20947b91a..ffc77eead5e 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -4,6 +4,7 @@ /// Name environment and name resolution module internal FSharp.Compiler.NameResolution +open System open System.Collections.Generic open Internal.Utilities @@ -1451,6 +1452,7 @@ type ITypecheckResultsSink = abstract NotifyMethodGroupNameResolution : pos * item: Item * itemMethodGroup: Item * TyparInst * ItemOccurence * NameResolutionEnv * AccessorDomain * range * replace: bool -> unit abstract NotifyFormatSpecifierLocation: range * int -> unit abstract NotifyOpenDeclaration: OpenDeclaration -> unit + abstract CreateScope: range -> IDisposable abstract CurrentSourceText: ISourceText option abstract FormatStringCheckContext: FormatStringCheckContext option @@ -1671,14 +1673,26 @@ type CapturedNameResolution(i: Item, tpinst, io: ItemOccurence, nre: NameResolut member this.DebugToString() = sprintf "%A: %+A" (this.Pos.Line, this.Pos.Column) i + interface IRangeOwner with + member this.Range = m + + +type CapturedExpressionType = + | CET of ty: TType * nenv: NameResolutionEnv * ad: AccessorDomain * m: range + + interface IRangeOwner with + member this.Range = + let (CET (m = range)) = this in range + + /// Represents container for all name resolutions that were met so far when typechecking some particular file type TcResolutions (capturedEnvs: ResizeArray, - capturedExprTypes: ResizeArray, + capturedExprTypes: RangeScopedCollection, capturedNameResolutions: ResizeArray, capturedMethodGroupResolutions: ResizeArray) = - static let empty = TcResolutions(ResizeArray 0, ResizeArray 0, ResizeArray 0, ResizeArray 0) + static let empty = TcResolutions(ResizeArray 0, RangeScopedCollection (), ResizeArray 0, ResizeArray 0) member this.CapturedEnvs = capturedEnvs member this.CapturedExpressionTypings = capturedExprTypes @@ -1727,7 +1741,7 @@ type TcSymbolUses(g, capturedNameResolutions: ResizeArray() - let capturedExprTypings = ResizeArray<_>() + let capturedExprTypings = RangeScopedCollection() let capturedNameResolutions = ResizeArray() let capturedMethodGroupResolutions = ResizeArray() let capturedOpenDeclarations = ResizeArray() @@ -1807,7 +1821,7 @@ type TcResultsSinkImpl(g, ?sourceText: ISourceText) = member sink.NotifyExprHasType(ty, nenv, ad, m) = if allowedRange m then - capturedExprTypings.Add((ty, nenv, ad, m)) + capturedExprTypings.AddItem(CET(ty, nenv, ad, m)) member sink.NotifyNameResolution(endPos, item, tpinst, occurenceType, nenv, ad, m, replace) = if allowedRange m then @@ -1830,6 +1844,9 @@ type TcResultsSinkImpl(g, ?sourceText: ISourceText) = member sink.NotifyOpenDeclaration openDeclaration = capturedOpenDeclarations.Add openDeclaration + member sink.CreateScope m = + capturedExprTypings.CreateScope(m) + member sink.CurrentSourceText = sourceText member sink.FormatStringCheckContext = formatStringCheckContext.Value diff --git a/src/fsharp/NameResolution.fsi b/src/fsharp/NameResolution.fsi index ea1bf05c8b1..2e8ce203647 100755 --- a/src/fsharp/NameResolution.fsi +++ b/src/fsharp/NameResolution.fsi @@ -2,6 +2,7 @@ module internal FSharp.Compiler.NameResolution +open System open FSharp.Compiler open FSharp.Compiler.AccessibilityLogic open FSharp.Compiler.AbstractSyntax @@ -325,6 +326,14 @@ type internal CapturedNameResolution = /// The starting and ending position member Range : range + interface IRangeOwner + + +type CapturedExpressionType = + | CET of ty: TType * nenv: NameResolutionEnv * ad: AccessorDomain * m: range + interface IRangeOwner + + [] type internal TcResolutions = @@ -334,7 +343,7 @@ type internal TcResolutions = /// Information of exact types found for expressions, that can be to the left of a dot. /// typ - the inferred type for an expression - member CapturedExpressionTypings : ResizeArray + member CapturedExpressionTypings : RangeScopedCollection /// Exact name resolutions member CapturedNameResolutions : ResizeArray @@ -419,6 +428,8 @@ type ITypecheckResultsSink = /// Record that an open declaration occured in a given scope range abstract NotifyOpenDeclaration : OpenDeclaration -> unit + abstract CreateScope: range -> IDisposable + /// Get the current source abstract CurrentSourceText : ISourceText option diff --git a/src/fsharp/RangeScopedCollection.fs b/src/fsharp/RangeScopedCollection.fs new file mode 100644 index 00000000000..4a34f186e2a --- /dev/null +++ b/src/fsharp/RangeScopedCollection.fs @@ -0,0 +1,53 @@ +namespace FSharp.Compiler + +open System +open System.Collections.Generic +open FSharp.Compiler.Range + +type IRangeOwner = + abstract Range: range + +type Disposable() = + static member val Empty: IDisposable = new Disposable() :> _ + + interface IDisposable with + member _.Dispose() = () + +type RangeScopedCollection<'T when 'T :> IRangeOwner>() as this = + let mutable currentScope = this + + member val Items = ResizeArray<'T>() + member val NestedScopes = ResizeArray>() + + member _.AddItem(item: 'T) = + currentScope.Items.Add(item) + + member _.CreateScope(m: range) = + let newScope = RangeScopedCollection() + currentScope.NestedScopes.Add(m, newScope) + + let parentScope = currentScope + currentScope <- newScope + + { new IDisposable with + member x.Dispose() = + // todo: remove scopes without items + currentScope <- parentScope } + + +[] +module RangeScopedCollection = + let itemsByEndPos (endPos: pos) (rsc: RangeScopedCollection<_>): IList<_> = + let rec loop (result: ResizeArray<_>) endPos (rsc: RangeScopedCollection<_>) = + for item in rsc.Items do + if rangeEndsAtPos endPos item.Range then + result.Add(item) + + for range, scope in rsc.NestedScopes do + if rangeContainsPos range endPos then + loop result endPos scope + + let result = ResizeArray() + loop result endPos rsc + + result :> _ diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 541d15b982b..5afd1b237fd 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -1883,6 +1883,7 @@ let MakeAndPublishSimpleValsForMergedScope cenv env m (names: NameMap<_>) = member this.NotifyExprHasType(_, _, _, _) = assert false // no expr typings in MakeAndPublishSimpleVals member this.NotifyFormatSpecifierLocation(_, _) = () member this.NotifyOpenDeclaration(_) = () + member this.CreateScope _ = Disposable.Empty member this.CurrentSourceText = None member this.FormatStringCheckContext = None } diff --git a/src/fsharp/range.fs b/src/fsharp/range.fs index ccdea8979bb..83cda4a121a 100755 --- a/src/fsharp/range.fs +++ b/src/fsharp/range.fs @@ -330,6 +330,9 @@ let rangeContainsPos (m1:range) p = let rangeBeforePos (m1:range) p = posGeq p m1.End +let rangeEndsAtPos (pos: pos) (m: range) = + m.EndLine = pos.Line && m.EndColumn = pos.Column + let rangeN filename line = mkRange filename (mkPos line 0) (mkPos line 0) let pos0 = mkPos 1 0 diff --git a/src/fsharp/range.fsi b/src/fsharp/range.fsi index 172ad32c103..35f1bc9ea3b 100755 --- a/src/fsharp/range.fsi +++ b/src/fsharp/range.fsi @@ -140,6 +140,8 @@ val rangeContainsPos : range -> pos -> bool /// Test to see if a range occurs fully before a position val rangeBeforePos : range -> pos -> bool +val rangeEndsAtPos: pos: pos -> m: range -> bool + /// Make a dummy range for a file val rangeN : string -> int -> range diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 15cb154cf69..ea96dead486 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -359,26 +359,24 @@ type internal TypeCheckInfo | Some (denv, m, items) -> let items = List.map ItemWithNoInst items ReturnItemsOfType items g denv m TypeNameResolutionFlag.ResolveTypeNamesToTypeRefs hasTextChangedSinceLastTypecheck - - /// finds captured typing for the given position - let GetExprTypingForPosition(endOfExprPos) = - let quals = - sResolutions.CapturedExpressionTypings - |> Seq.filter (fun (ty,nenv,_,m) -> - // We only want expression types that end at the particular position in the file we are looking at. - posEq m.End endOfExprPos && - - // Get rid of function types. True, given a 2-arg curried function "f x y", it is legal to do "(f x).GetType()", - // but you almost never want to do this in practice, and we choose not to offer up any intellisense for - // F# function types. - not (isFunTy nenv.DisplayEnv.g ty)) + + /// Get captured expression types ending at the particular position. + let GetExprTypingForPosition (endOfExprPos: pos) = + let quals = + sResolutions.CapturedExpressionTypings + |> RangeScopedCollection.itemsByEndPos endOfExprPos + |> Seq.filter (fun (CET(ty,nenv,_,_)) -> + // Get rid of function types. True, given a 2-arg curried function "f x y", it is legal to do "(f x).GetType()", + // but you almost never want to do this in practice, and we choose not to offer up any intellisense for + // F# function types. + not (isFunTy nenv.DisplayEnv.g ty)) |> Seq.toArray let thereWereSomeQuals = not (Array.isEmpty quals) // filter out errors let quals = quals - |> Array.filter (fun (ty,nenv,_,_) -> + |> Array.filter (fun (CET(ty,nenv,_,_)) -> let denv = nenv.DisplayEnv not (isTyparTy denv.g ty && (destTyparTy denv.g ty).IsFromError)) thereWereSomeQuals, quals @@ -391,11 +389,11 @@ type internal TypeCheckInfo match quals with | [||] -> None | quals -> - quals |> Array.tryFind (fun (_,_,_,rq) -> + quals |> Array.tryFind (fun (CET(_,_,_,rq)) -> ignore(r) // for breakpoint posEq r.Start rq.Start) match bestQual with - | Some (ty,nenv,ad,m) when isRecdTy nenv.DisplayEnv.g ty -> + | Some (CET(ty,nenv,ad,m)) when isRecdTy nenv.DisplayEnv.g ty -> let items = NameResolution.ResolveRecordOrClassFieldsOfType ncenv m ad ty false Some (items, nenv.DisplayEnv, m) | _ -> None @@ -426,7 +424,7 @@ type internal TypeCheckInfo // If not, then the stale typecheck info does not have a capturedExpressionTyping for this exact expression, and the // user can wait for typechecking to catch up and second-chance intellisense to give the right result. let qual = - quals |> Array.tryFind (fun (_,_,_,r) -> + quals |> Array.tryFind (fun (CET(_,_,_,r)) -> ignore(r) // for breakpoint posEq exprRange.Start r.Start) qual, false @@ -439,7 +437,7 @@ type internal TypeCheckInfo match bestQual with | Some bestQual -> - let (ty,nenv,ad,m) = bestQual + let (CET(ty,nenv,ad,m)) = bestQual let items = ResolveCompletionsInType ncenv nenv (ResolveCompletionTargets.All(ConstraintSolver.IsApplicableMethApprox g amap m)) m ad false ty let items = items |> List.map ItemWithNoInst let items = items |> RemoveDuplicateItems g diff --git a/tests/service/RangeScopedCollectionTests.fs b/tests/service/RangeScopedCollectionTests.fs new file mode 100644 index 00000000000..0b4aad67bb2 --- /dev/null +++ b/tests/service/RangeScopedCollectionTests.fs @@ -0,0 +1,156 @@ +module FSharp.Compiler.Service.Tests.RangeScopedCollectionTest + +open System.IO +open FSharp.Compiler +open FSharp.Compiler.Range +open FsUnit +open NUnit.Framework + +type NumberedItems() = + let mutable itemsCount = 0 + + member val RequestedRangeNumbers = ResizeArray() + + member x.Create(m: range) = + itemsCount <- itemsCount + 1 + NumberedItem(itemsCount, m, x) + + member x.Create() = + x.Create(rangeStartup) + +and NumberedItem(number: int, m: range, items) = + member val Number = number + + override x.ToString() = + x.Number.ToString() + ": " + m.ToShortString() + + interface IRangeOwner with + member x.Range = + items.RequestedRangeNumbers.Add(number) + m + + +type RangeScopedCollection<'T when 'T :> IRangeOwner> with + member x.WithScope(m, f) = + use scope = x.CreateScope(m) + f () + + member x.WithScope(f) = + x.WithScope(rangeStartup, f) + + +let mkRange s e = + mkRange unknownFileName s e + +let mkSimplePos c = + mkPos 0 c + +let mkSimpleRange (s, e) = + let s = mkSimplePos s + let e = mkSimplePos e + mkRange s e + + +[] +let ``Filter - End pos 01`` () = + let expectedPos = mkSimplePos 3 + let expectedRange = mkRange expectedPos expectedPos + + let nestedScopeRange = mkSimpleRange (1, 5) + let innerNestedScopeRange = mkSimpleRange (1, 2) + let otherNestedScopeRange = mkSimpleRange (4, 5) + + let items = NumberedItems() + let rsc = RangeScopedCollection<_>() + + rsc.AddItem(items.Create(expectedRange)) + rsc.AddItem(items.Create()) + + rsc.WithScope(nestedScopeRange, fun _ -> + rsc.AddItem(items.Create()) + rsc.AddItem(items.Create(expectedRange)) + + rsc.WithScope(innerNestedScopeRange, fun _ -> + rsc.AddItem(items.Create(innerNestedScopeRange)))) + + rsc.WithScope(otherNestedScopeRange, fun _ -> + rsc.AddItem(items.Create(otherNestedScopeRange))) + + rsc.AddItem(items.Create(expectedRange)) + + RangeScopedCollection.itemsByEndPos expectedPos rsc + |> Seq.map (fun o -> o.Number) + |> Array.ofSeq + |> shouldEqual [| 1; 7; 4 |] + + items.RequestedRangeNumbers + |> Array.ofSeq + |> shouldEqual [| 1; 2; 7; 3; 4 |] + + +let dumpCollection (rsc: RangeScopedCollection<_>) = + let writer = new StringWriter() + + let rec loop indent (rsc: RangeScopedCollection<_>) = + for item in rsc.Items do + writer.WriteLine(indent + item.ToString()) + + for range, rsc in rsc.NestedScopes do + writer.WriteLine() + writer.WriteLine(indent + "Nested scope: " + range.ToShortString()) + loop (indent + " ") rsc + + loop "" rsc + writer.ToString() + +let (|Trim|) (s: string) = + s.Trim() + +let assertDumpEquals rsc (Trim expected) = + let (Trim dump) = dumpCollection rsc + dump |> shouldEqual expected + + +[] +let ``Scopes 01`` () = + let items = NumberedItems() + let rsc = RangeScopedCollection<_>() + + rsc.AddItem(items.Create()) + rsc.WithScope(fun _ -> + rsc.AddItem(items.Create())) + rsc.AddItem(items.Create()) + + assertDumpEquals rsc """ +1: (1,0--1,0) +3: (1,0--1,0) + +Nested scope: (1,0--1,0) + 2: (1,0--1,0) +""" + + +[] +let ``Scopes 02 - Nested`` () = + let items = NumberedItems() + let rsc = RangeScopedCollection<_>() + + rsc.AddItem(items.Create()) + rsc.WithScope(fun _ -> + rsc.AddItem(items.Create()) + rsc.WithScope(fun _ -> + rsc.AddItem(items.Create())) + rsc.AddItem(items.Create())) + rsc.AddItem(items.Create()) + + assertDumpEquals rsc """ +1: (1,0--1,0) +5: (1,0--1,0) + +Nested scope: (1,0--1,0) + 2: (1,0--1,0) + 4: (1,0--1,0) + + Nested scope: (1,0--1,0) + 3: (1,0--1,0) +""" From 81d51c1f0a74d020b0ee0e689d90d70e11a2cbe8 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sat, 28 Mar 2020 17:46:44 +0300 Subject: [PATCH 2/3] Create some top level nested scopes in type checker --- src/absil/illib.fs | 2 + src/fsharp/NameResolution.fs | 5 ++ src/fsharp/NameResolution.fsi | 2 + src/fsharp/RangeScopedCollection.fs | 70 +++++++++++++++++---- src/fsharp/TypeChecker.fs | 4 +- tests/service/RangeScopedCollectionTests.fs | 17 +++-- 6 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/absil/illib.fs b/src/absil/illib.fs index 33e0566a6c2..e3899c86e7b 100644 --- a/src/absil/illib.fs +++ b/src/absil/illib.fs @@ -935,6 +935,8 @@ type EventuallyBuilder() = member x.TryWith(e, handler) = Eventually.tryWith e handler + member x.Using(resource, e) = Eventually.tryFinally (e resource) (fun () -> (resource :> IDisposable).Dispose()) + member x.TryFinally(e, compensation) = Eventually.tryFinally e compensation member x.Delay f = Eventually.delay f diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index ffc77eead5e..57e2f53eeb6 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -1904,6 +1904,11 @@ let CallOpenDeclarationSink (sink: TcResultsSink) (openDeclaration: OpenDeclarat | None -> () | Some sink -> sink.NotifyOpenDeclaration openDeclaration +let CreateScope (sink: TcResultsSink) (m: range) = + match sink.CurrentSink with + | None -> Disposable.Empty + | Some sink -> sink.CreateScope(m) + //------------------------------------------------------------------------- // Check inferability of type parameters in resolved items. //------------------------------------------------------------------------- diff --git a/src/fsharp/NameResolution.fsi b/src/fsharp/NameResolution.fsi index 2e8ce203647..05fedde272e 100755 --- a/src/fsharp/NameResolution.fsi +++ b/src/fsharp/NameResolution.fsi @@ -494,6 +494,8 @@ val internal CallExprHasTypeSink : TcResultsSink -> range * NameResolutio /// Report an open declaration val internal CallOpenDeclarationSink : TcResultsSink -> OpenDeclaration -> unit +val internal CreateScope: TcResultsSink -> range -> IDisposable + /// Get all the available properties of a type (both intrinsic and extension) val internal AllPropInfosOfTypeInScope : ResultCollectionSettings -> InfoReader -> NameResolutionEnv -> string option -> AccessorDomain -> FindMemberFlag -> range -> TType -> PropInfo list diff --git a/src/fsharp/RangeScopedCollection.fs b/src/fsharp/RangeScopedCollection.fs index 4a34f186e2a..c5ec97e2461 100644 --- a/src/fsharp/RangeScopedCollection.fs +++ b/src/fsharp/RangeScopedCollection.fs @@ -13,18 +13,65 @@ type Disposable() = interface IDisposable with member _.Dispose() = () -type RangeScopedCollection<'T when 'T :> IRangeOwner>() as this = - let mutable currentScope = this +type ScopeData<'T when 'T :> IRangeOwner>() = member val Items = ResizeArray<'T>() - member val NestedScopes = ResizeArray>() + member val NestedScopes = ResizeArray>() + +and RangedScope<'T when 'T :> IRangeOwner> = + private + | Global of ScopeData<'T> + | Nested of range * ScopeData<'T> + + member private scope.Data = + match scope with + | Global data + | Nested (_, data) -> data + + member scope.NestedScopes = + scope.Data.NestedScopes + + member scope.Items = + scope.Data.Items + + member scope.Range = + match scope with + | Global _ -> None + | Nested (scopeRange, _) -> Some scopeRange + + member scope.Contains(m: range) = + match scope with + | Global _ -> true + | Nested (scopeRange, _) -> rangeContainsRange scopeRange m + + member scope.Contains(p: pos) = + match scope with + | Global _ -> true + | Nested (scopeRange, _) -> rangeContainsPos scopeRange p + + member x.CreateNestedScope(m: range) = + match x with + | Global _ -> () + | Nested (currentScopeRange, _) -> + assert rangeContainsRange currentScopeRange m + + let scope = Nested(m, ScopeData()) + x.NestedScopes.Add(scope) + + scope + + static member CreateGlobalScope<'T>() = + RangedScope.Global(ScopeData<'T>()) + +type RangeScopedCollection<'T when 'T :> IRangeOwner>() = + let globalScope = RangedScope.CreateGlobalScope() + let mutable currentScope = globalScope member _.AddItem(item: 'T) = currentScope.Items.Add(item) member _.CreateScope(m: range) = - let newScope = RangeScopedCollection() - currentScope.NestedScopes.Add(m, newScope) + let newScope = currentScope.CreateNestedScope(m) let parentScope = currentScope currentScope <- newScope @@ -34,20 +81,21 @@ type RangeScopedCollection<'T when 'T :> IRangeOwner>() as this = // todo: remove scopes without items currentScope <- parentScope } + member x.GlobalScope = globalScope [] module RangeScopedCollection = let itemsByEndPos (endPos: pos) (rsc: RangeScopedCollection<_>): IList<_> = - let rec loop (result: ResizeArray<_>) endPos (rsc: RangeScopedCollection<_>) = - for item in rsc.Items do + let rec loop (result: ResizeArray<_>) endPos (scope: RangedScope<_>) = + for item in scope.Items do if rangeEndsAtPos endPos item.Range then result.Add(item) - for range, scope in rsc.NestedScopes do - if rangeContainsPos range endPos then - loop result endPos scope + for scope in scope.NestedScopes do + if scope.Contains(endPos) then + loop result endPos scope let result = ResizeArray() - loop result endPos rsc + loop result endPos rsc.GlobalScope result :> _ diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 5afd1b237fd..89ab9921ef2 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -17510,8 +17510,10 @@ let rec TcModuleOrNamespaceElementNonMutRec (cenv: cenv) parent typeNames scopem //printfn "----------\nCHECKING, e = %+A\n------------------\n" e try - match ElimModuleDoBinding synDecl with + let synDecl = ElimModuleDoBinding synDecl + use _ = CreateScope cenv.tcSink synDecl.Range + match synDecl with | SynModuleDecl.ModuleAbbrev (id, p, m) -> let env = MutRecBindingChecking.TcModuleAbbrevDecl cenv scopem env (id, p, m) return ((fun e -> e), []), env, env diff --git a/tests/service/RangeScopedCollectionTests.fs b/tests/service/RangeScopedCollectionTests.fs index 0b4aad67bb2..88e3436e8c7 100644 --- a/tests/service/RangeScopedCollectionTests.fs +++ b/tests/service/RangeScopedCollectionTests.fs @@ -91,16 +91,21 @@ let ``Filter - End pos 01`` () = let dumpCollection (rsc: RangeScopedCollection<_>) = let writer = new StringWriter() - let rec loop indent (rsc: RangeScopedCollection<_>) = - for item in rsc.Items do + let rec loop indent (scope: RangedScope<_>) = + for item in scope.Items do writer.WriteLine(indent + item.ToString()) - for range, rsc in rsc.NestedScopes do + for nestedScope in scope.NestedScopes do + let scopeRangeString = + nestedScope.Range + |> Option.map (fun m -> m.ToShortString()) + |> Option.defaultWith (fun _ -> failwithf "Expecting nested scope") + writer.WriteLine() - writer.WriteLine(indent + "Nested scope: " + range.ToShortString()) - loop (indent + " ") rsc + writer.WriteLine(indent + "Nested scope: " + scopeRangeString) + loop (indent + " ") nestedScope - loop "" rsc + loop "" rsc.GlobalScope writer.ToString() let (|Trim|) (s: string) = From 2889d081e54afc4116b184cd34648404290a2a62 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sat, 28 Mar 2020 17:51:17 +0300 Subject: [PATCH 3/3] Add new file to FCP fsproj --- .../FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index f8ee4764fdc..cce46945208 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -174,6 +174,9 @@ ErrorLogging\range.fs + + ErrorLogging\RangeScopedCollection.fs + ErrorLogging\ErrorLogger.fs