提交 f6cea7c3 编写于 作者: L latkin

Merge branch 'master' into fsharp4

Conflicts:
	src/fsharp/FSharp.Core/array.fs
	src/fsharp/FSharp.Core/seq.fs
...@@ -9,6 +9,14 @@ open System ...@@ -9,6 +9,14 @@ open System
open FSharp.Core.Unittests.LibraryTestFx open FSharp.Core.Unittests.LibraryTestFx
open NUnit.Framework open NUnit.Framework
module LeakUtils =
// when testing for liveness, the things that we want to observe must always be created in
// a nested function call to avoid the GC (possibly) treating them as roots past the last use in the block.
// We also need something non trivial to disuade the compiler from inlining in Release builds.
type ToRun<'a>(f : unit -> 'a) =
member this.Invoke() = f()
let run (toRun : ToRun<'a>) = toRun.Invoke()
// --------------------------------------------------- // ---------------------------------------------------
...@@ -191,6 +199,41 @@ type AsyncModule() = ...@@ -191,6 +199,41 @@ type AsyncModule() =
for _i = 1 to 50 do test() for _i = 1 to 50 do test()
[<Test>]
member this.``Async.AwaitWaitHandle does not leak memory`` () =
// This test checks that AwaitWaitHandle does not leak continuations (described in #131),
// We only test the worst case - when the AwaitWaitHandle is already set.
use manualResetEvent = new System.Threading.ManualResetEvent(true)
let tryToLeak() =
let resource =
LeakUtils.ToRun (fun () ->
let resource = obj()
let work =
async {
let! _ = Async.AwaitWaitHandle manualResetEvent
GC.KeepAlive(resource)
return ()
}
work |> Async.RunSynchronously |> ignore
WeakReference(resource))
|> LeakUtils.run
Assert.IsTrue(resource.IsAlive)
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
Assert.IsFalse(resource.IsAlive)
// The leak hangs on a race condition which is really hard to trigger in F# 3.0, hence the 100000 runs...
for _ in 1..100 do tryToLeak()
[<Test>] [<Test>]
member this.``AwaitWaitHandle.DisposedWaitHandle2``() = member this.``AwaitWaitHandle.DisposedWaitHandle2``() =
let wh = new System.Threading.ManualResetEvent(false) let wh = new System.Threading.ManualResetEvent(false)
......
...@@ -12,7 +12,6 @@ namespace Microsoft.FSharp.Collections ...@@ -12,7 +12,6 @@ namespace Microsoft.FSharp.Collections
open Microsoft.FSharp.Core.Operators open Microsoft.FSharp.Core.Operators
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
open Microsoft.FSharp.Core.SR open Microsoft.FSharp.Core.SR
open Microsoft.FSharp.Core.LanguagePrimitives.ErrorStrings
#if FX_NO_ICLONEABLE #if FX_NO_ICLONEABLE
open Microsoft.FSharp.Core.ICloneableExtensions open Microsoft.FSharp.Core.ICloneableExtensions
#else #else
...@@ -36,7 +35,7 @@ namespace Microsoft.FSharp.Collections ...@@ -36,7 +35,7 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("Last")>] [<CompiledName("Last")>]
let inline last (array : 'T[]) = let inline last (array : 'T[]) =
checkNonNull "array" array checkNonNull "array" array
if array.Length = 0 then invalidArg "array" InputArrayEmptyString if array.Length = 0 then invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString
array.[array.Length-1] array.[array.Length-1]
[<CompiledName("TryLast")>] [<CompiledName("TryLast")>]
...@@ -205,7 +204,7 @@ namespace Microsoft.FSharp.Collections ...@@ -205,7 +204,7 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("Head")>] [<CompiledName("Head")>]
let head (array : 'T[]) = let head (array : 'T[]) =
checkNonNull "array" array checkNonNull "array" array
if array.Length = 0 then invalidArg "array" InputArrayEmptyString else array.[0] if array.Length = 0 then invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString else array.[0]
[<CompiledName("Copy")>] [<CompiledName("Copy")>]
let copy (array: 'T[]) = let copy (array: 'T[]) =
...@@ -719,18 +718,20 @@ namespace Microsoft.FSharp.Collections ...@@ -719,18 +718,20 @@ namespace Microsoft.FSharp.Collections
let reduce f (array : _[]) = let reduce f (array : _[]) =
checkNonNull "array" array checkNonNull "array" array
let len = array.Length let len = array.Length
if len = 0 then invalidArg "array" InputArrayEmptyString else if len = 0 then
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString
let mutable res = array.[0] else
for i = 1 to len - 1 do let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
res <- f.Invoke(res,array.[i]) let mutable res = array.[0]
res for i = 1 to len - 1 do
res <- f.Invoke(res,array.[i])
res
[<CompiledName("ReduceBack")>] [<CompiledName("ReduceBack")>]
let reduceBack f (array : _[]) = let reduceBack f (array : _[]) =
checkNonNull "array" array checkNonNull "array" array
let len = array.Length let len = array.Length
if len = 0 then invalidArg "array" InputArrayEmptyString if len = 0 then invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString
else foldSubRight f array 0 (len - 2) array.[len - 1] else foldSubRight f array 0 (len - 2) array.[len - 1]
[<CompiledName("SortInPlaceWith")>] [<CompiledName("SortInPlaceWith")>]
...@@ -843,7 +844,7 @@ namespace Microsoft.FSharp.Collections ...@@ -843,7 +844,7 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("Min")>] [<CompiledName("Min")>]
let inline min (array:_[]) = let inline min (array:_[]) =
checkNonNull "array" array checkNonNull "array" array
if array.Length = 0 then invalidArg "array" InputArrayEmptyString if array.Length = 0 then invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString
let mutable acc = array.[0] let mutable acc = array.[0]
for i = 1 to array.Length - 1 do for i = 1 to array.Length - 1 do
let curr = array.[i] let curr = array.[i]
...@@ -854,7 +855,7 @@ namespace Microsoft.FSharp.Collections ...@@ -854,7 +855,7 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("MinBy")>] [<CompiledName("MinBy")>]
let inline minBy f (array:_[]) = let inline minBy f (array:_[]) =
checkNonNull "array" array checkNonNull "array" array
if array.Length = 0 then invalidArg "array" InputArrayEmptyString if array.Length = 0 then invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString
let mutable accv = array.[0] let mutable accv = array.[0]
let mutable acc = f accv let mutable acc = f accv
for i = 1 to array.Length - 1 do for i = 1 to array.Length - 1 do
...@@ -868,7 +869,7 @@ namespace Microsoft.FSharp.Collections ...@@ -868,7 +869,7 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("Max")>] [<CompiledName("Max")>]
let inline max (array:_[]) = let inline max (array:_[]) =
checkNonNull "array" array checkNonNull "array" array
if array.Length = 0 then invalidArg "array" InputArrayEmptyString if array.Length = 0 then invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString
let mutable acc = array.[0] let mutable acc = array.[0]
for i = 1 to array.Length - 1 do for i = 1 to array.Length - 1 do
let curr = array.[i] let curr = array.[i]
...@@ -879,7 +880,7 @@ namespace Microsoft.FSharp.Collections ...@@ -879,7 +880,7 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("MaxBy")>] [<CompiledName("MaxBy")>]
let inline maxBy f (array:_[]) = let inline maxBy f (array:_[]) =
checkNonNull "array" array checkNonNull "array" array
if array.Length = 0 then invalidArg "array" InputArrayEmptyString if array.Length = 0 then invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString
let mutable accv = array.[0] let mutable accv = array.[0]
let mutable acc = f accv let mutable acc = f accv
for i = 1 to array.Length - 1 do for i = 1 to array.Length - 1 do
......
...@@ -1671,29 +1671,34 @@ namespace Microsoft.FSharp.Control ...@@ -1671,29 +1671,34 @@ namespace Microsoft.FSharp.Control
Action<obj>(fun _ -> Action<obj>(fun _ ->
if latch.Enter() then if latch.Enter() then
// if we got here - then we need to unregister RegisteredWaitHandle + trigger cancellation // if we got here - then we need to unregister RegisteredWaitHandle + trigger cancellation
// entrance to TP callback is protected by latch - so savedCont will never be called // entrance to TP callback is protected by latch - so savedCont will never be called
match !rwh with lock rwh (fun () ->
| None -> () match !rwh with
| Some rwh -> rwh.Unregister(null) |> ignore | None -> ()
| Some rwh -> rwh.Unregister(null) |> ignore)
Async.Start (async { do (aux.ccont (OperationCanceledException()) |> unfake) })) Async.Start (async { do (aux.ccont (OperationCanceledException()) |> unfake) }))
and registration : CancellationTokenRegistration= aux.token.Register(cancelHandler, null) and registration : CancellationTokenRegistration = aux.token.Register(cancelHandler, null)
let savedCont = args.cont let savedCont = args.cont
try try
rwh := Some(ThreadPool.RegisterWaitForSingleObject lock rwh (fun () ->
(waitObject=waitHandle, rwh := Some(ThreadPool.RegisterWaitForSingleObject
callBack=WaitOrTimerCallback(fun _ timeOut -> (waitObject=waitHandle,
if latch.Enter() then callBack=WaitOrTimerCallback(fun _ timeOut ->
rwh := None if latch.Enter() then
registration.Dispose() lock rwh (fun () -> rwh.Value.Value.Unregister(null) |> ignore)
aux.trampolineHolder.Protect (fun () -> savedCont (not timeOut)) |> unfake), rwh := None
state=null, registration.Dispose()
millisecondsTimeOutInterval=millisecondsTimeout, aux.trampolineHolder.Protect (fun () -> savedCont (not timeOut)) |> unfake),
executeOnlyOnce=true)); state=null,
FakeUnit millisecondsTimeOutInterval=millisecondsTimeout,
executeOnlyOnce=true));
FakeUnit)
with _ -> with _ ->
if latch.Enter() then reraise() // reraise exception only if we successfully enter the latch (no other continuations were called) if latch.Enter() then
registration.Dispose()
reraise() // reraise exception only if we successfully enter the latch (no other continuations were called)
else FakeUnit else FakeUnit
) )
#endif #endif
......
...@@ -4,7 +4,6 @@ namespace Microsoft.FSharp.Primitives.Basics ...@@ -4,7 +4,6 @@ namespace Microsoft.FSharp.Primitives.Basics
open Microsoft.FSharp.Core open Microsoft.FSharp.Core
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
open Microsoft.FSharp.Core.LanguagePrimitives.ErrorStrings
open Microsoft.FSharp.Collections open Microsoft.FSharp.Collections
open Microsoft.FSharp.Core.Operators open Microsoft.FSharp.Core.Operators
open System.Diagnostics.CodeAnalysis open System.Diagnostics.CodeAnalysis
...@@ -327,7 +326,7 @@ module internal List = ...@@ -327,7 +326,7 @@ module internal List =
let init count f = let init count f =
if count < 0 then invalidArg "count" InputMustBeNonNegativeString if count < 0 then invalidArg "count" LanguagePrimitives.ErrorStrings.InputMustBeNonNegativeString
if count = 0 then [] if count = 0 then []
else else
let res = freshConsNoTail (f 0) let res = freshConsNoTail (f 0)
...@@ -344,7 +343,7 @@ module internal List = ...@@ -344,7 +343,7 @@ module internal List =
takeFreshConsTail cons2 (n - 1) xs takeFreshConsTail cons2 (n - 1) xs
let take n l = let take n l =
if n < 0 then invalidArg "count" InputMustBeNonNegativeString if n < 0 then invalidArg "count" LanguagePrimitives.ErrorStrings.InputMustBeNonNegativeString
if n = 0 then [] else if n = 0 then [] else
match l with match l with
| [] -> raise <| System.InvalidOperationException (SR.GetString(SR.notEnoughElements)) | [] -> raise <| System.InvalidOperationException (SR.GetString(SR.notEnoughElements))
...@@ -714,7 +713,7 @@ module internal Array = ...@@ -714,7 +713,7 @@ module internal Array =
(# "newarr !0" type ('T) count : 'T array #) (# "newarr !0" type ('T) count : 'T array #)
let inline init (count:int) (f: int -> 'T) = let inline init (count:int) (f: int -> 'T) =
if count < 0 then invalidArg "count" InputMustBeNonNegativeString if count < 0 then invalidArg "count" LanguagePrimitives.ErrorStrings.InputMustBeNonNegativeString
let arr = (zeroCreateUnchecked count : 'T array) let arr = (zeroCreateUnchecked count : 'T array)
for i = 0 to count - 1 do for i = 0 to count - 1 do
arr.[i] <- f i arr.[i] <- f i
...@@ -883,4 +882,4 @@ module internal Array = ...@@ -883,4 +882,4 @@ module internal Array =
res.[i] <- array.[startIndex+i] res.[i] <- array.[startIndex+i]
else else
Array.Copy(array, startIndex, res, 0, count) Array.Copy(array, startIndex, res, 0, count)
res res
\ No newline at end of file
...@@ -656,17 +656,17 @@ namespace Microsoft.FSharp.Core ...@@ -656,17 +656,17 @@ namespace Microsoft.FSharp.Core
module LanguagePrimitives = module LanguagePrimitives =
[<Sealed>]
module (* internal *) ErrorStrings = type (* internal *) ErrorStrings =
// inline functions cannot call GetString, so we must make these bits public // inline functions cannot call GetString, so we must make these bits public
let AddressOpNotFirstClassString = SR.GetString(SR.addressOpNotFirstClass) static member AddressOpNotFirstClassString with get () = SR.GetString(SR.addressOpNotFirstClass)
let NoNegateMinValueString = SR.GetString(SR.noNegateMinValue) static member NoNegateMinValueString with get () = SR.GetString(SR.noNegateMinValue)
// needs to be public to be visible from inline function 'average' and others // needs to be public to be visible from inline function 'average' and others
let InputSequenceEmptyString = SR.GetString(SR.inputSequenceEmpty) static member InputSequenceEmptyString with get () = SR.GetString(SR.inputSequenceEmpty)
// needs to be public to be visible from inline function 'average' and others // needs to be public to be visible from inline function 'average' and others
let InputArrayEmptyString = SR.GetString(SR.arrayWasEmpty) static member InputArrayEmptyString with get () = SR.GetString(SR.arrayWasEmpty)
// needs to be public to be visible from inline function 'average' and others // needs to be public to be visible from inline function 'average' and others
let InputMustBeNonNegativeString = SR.GetString(SR.inputMustBeNonNegative) static member InputMustBeNonNegativeString with get () = SR.GetString(SR.inputMustBeNonNegative)
[<CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")>] // nested module OK [<CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")>] // nested module OK
module IntrinsicOperators = module IntrinsicOperators =
......
...@@ -1015,22 +1015,23 @@ namespace Microsoft.FSharp.Core ...@@ -1015,22 +1015,23 @@ namespace Microsoft.FSharp.Core
val inline DivideByInt< ^T > : x:^T -> y:int -> ^T when ^T : (static member DivideByInt : ^T * int -> ^T) val inline DivideByInt< ^T > : x:^T -> y:int -> ^T when ^T : (static member DivideByInt : ^T * int -> ^T)
/// <summary>For internal use only</summary> /// <summary>For internal use only</summary>
module (* internal *) ErrorStrings = [<Sealed>]
type (* internal *) ErrorStrings =
[<CompilerMessage("This value is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>] [<CompilerMessage("This value is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>]
val InputSequenceEmptyString : string static member InputSequenceEmptyString : string with get
[<CompilerMessage("This value is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>] [<CompilerMessage("This value is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>]
val InputArrayEmptyString : string static member InputArrayEmptyString : string with get
[<CompilerMessage("This value is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>] [<CompilerMessage("This value is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>]
val AddressOpNotFirstClassString : string static member AddressOpNotFirstClassString : string with get
[<CompilerMessage("This value is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>] [<CompilerMessage("This value is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>]
val NoNegateMinValueString : string static member NoNegateMinValueString : string with get
[<CompilerMessage("This value is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>] [<CompilerMessage("This value is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>]
val InputMustBeNonNegativeString : string static member InputMustBeNonNegativeString : string with get
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
......
...@@ -849,7 +849,6 @@ namespace Microsoft.FSharp.Collections ...@@ -849,7 +849,6 @@ namespace Microsoft.FSharp.Collections
open System.Collections.Generic open System.Collections.Generic
open Microsoft.FSharp.Core open Microsoft.FSharp.Core
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
open Microsoft.FSharp.Core.LanguagePrimitives.ErrorStrings
open Microsoft.FSharp.Core.Operators open Microsoft.FSharp.Core.Operators
open Microsoft.FSharp.Core.CompilerServices open Microsoft.FSharp.Core.CompilerServices
open Microsoft.FSharp.Control open Microsoft.FSharp.Control
...@@ -1161,7 +1160,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1161,7 +1160,7 @@ namespace Microsoft.FSharp.Collections
let reduce f (source : seq<'T>) = let reduce f (source : seq<'T>) =
checkNonNull "source" source checkNonNull "source" source
use e = source.GetEnumerator() use e = source.GetEnumerator()
if not (e.MoveNext()) then invalidArg "source" InputSequenceEmptyString; if not (e.MoveNext()) then invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString;
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
let mutable state = e.Current let mutable state = e.Current
while e.MoveNext() do while e.MoveNext() do
...@@ -1265,7 +1264,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1265,7 +1264,7 @@ namespace Microsoft.FSharp.Collections
checkNonNull "source" source checkNonNull "source" source
let arr = toArray source let arr = toArray source
match arr.Length with match arr.Length with
| 0 -> invalidArg "source" InputSequenceEmptyString | 0 -> invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
| len -> | len ->
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f) let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
foldArraySubRight f arr 0 (len - 2) arr.[len - 1] foldArraySubRight f arr 0 (len - 2) arr.[len - 1]
...@@ -1564,7 +1563,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1564,7 +1563,7 @@ namespace Microsoft.FSharp.Collections
acc <- Checked.(+) acc e.Current acc <- Checked.(+) acc e.Current
count <- count + 1 count <- count + 1
if count = 0 then if count = 0 then
invalidArg "source" InputSequenceEmptyString invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
LanguagePrimitives.DivideByInt< (^a) > acc count LanguagePrimitives.DivideByInt< (^a) > acc count
[<CompiledName("AverageBy")>] [<CompiledName("AverageBy")>]
...@@ -1577,7 +1576,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1577,7 +1576,7 @@ namespace Microsoft.FSharp.Collections
acc <- Checked.(+) acc (f e.Current) acc <- Checked.(+) acc (f e.Current)
count <- count + 1 count <- count + 1
if count = 0 then if count = 0 then
invalidArg "source" InputSequenceEmptyString; invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString;
LanguagePrimitives.DivideByInt< (^U) > acc count LanguagePrimitives.DivideByInt< (^U) > acc count
[<CompiledName("Min")>] [<CompiledName("Min")>]
...@@ -1585,7 +1584,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1585,7 +1584,7 @@ namespace Microsoft.FSharp.Collections
checkNonNull "source" source checkNonNull "source" source
use e = source.GetEnumerator() use e = source.GetEnumerator()
if not (e.MoveNext()) then if not (e.MoveNext()) then
invalidArg "source" InputSequenceEmptyString; invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString;
let mutable acc = e.Current let mutable acc = e.Current
while e.MoveNext() do while e.MoveNext() do
let curr = e.Current let curr = e.Current
...@@ -1598,7 +1597,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1598,7 +1597,7 @@ namespace Microsoft.FSharp.Collections
checkNonNull "source" source checkNonNull "source" source
use e = source.GetEnumerator() use e = source.GetEnumerator()
if not (e.MoveNext()) then if not (e.MoveNext()) then
invalidArg "source" InputSequenceEmptyString; invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString;
let first = e.Current let first = e.Current
let mutable acc = f first let mutable acc = f first
let mutable accv = first let mutable accv = first
...@@ -1632,7 +1631,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1632,7 +1631,7 @@ namespace Microsoft.FSharp.Collections
checkNonNull "source" source checkNonNull "source" source
use e = source.GetEnumerator() use e = source.GetEnumerator()
if not (e.MoveNext()) then if not (e.MoveNext()) then
invalidArg "source" InputSequenceEmptyString; invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString;
let mutable acc = e.Current let mutable acc = e.Current
while e.MoveNext() do while e.MoveNext() do
let curr = e.Current let curr = e.Current
...@@ -1645,7 +1644,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1645,7 +1644,7 @@ namespace Microsoft.FSharp.Collections
checkNonNull "source" source checkNonNull "source" source
use e = source.GetEnumerator() use e = source.GetEnumerator()
if not (e.MoveNext()) then if not (e.MoveNext()) then
invalidArg "source" InputSequenceEmptyString; invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString;
let first = e.Current let first = e.Current
let mutable acc = f first let mutable acc = f first
let mutable accv = first let mutable accv = first
...@@ -1735,7 +1734,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1735,7 +1734,7 @@ namespace Microsoft.FSharp.Collections
checkNonNull "source" source checkNonNull "source" source
use e = source.GetEnumerator() use e = source.GetEnumerator()
if (e.MoveNext()) then e.Current if (e.MoveNext()) then e.Current
else invalidArg "source" InputSequenceEmptyString else invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
[<CompiledName("TryHead")>] [<CompiledName("TryHead")>]
let tryHead (source : seq<_>) = let tryHead (source : seq<_>) =
...@@ -1762,7 +1761,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1762,7 +1761,7 @@ namespace Microsoft.FSharp.Collections
while (e.MoveNext()) do res <- e.Current while (e.MoveNext()) do res <- e.Current
res res
else else
invalidArg "source" InputSequenceEmptyString invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
[<CompiledName("TryLast")>] [<CompiledName("TryLast")>]
let tryLast (source : seq<_>) = let tryLast (source : seq<_>) =
...@@ -1786,7 +1785,7 @@ namespace Microsoft.FSharp.Collections ...@@ -1786,7 +1785,7 @@ namespace Microsoft.FSharp.Collections
else else
v v
else else
invalidArg "source" InputSequenceEmptyString invalidArg "source" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
[<CompiledName("Reverse")>] [<CompiledName("Reverse")>]
let rev source = let rev source =
......
...@@ -508,12 +508,14 @@ module MembersTest = ...@@ -508,12 +508,14 @@ module MembersTest =
let s = 2.0f<kg> let s = 2.0f<kg>
let d = 2.0M<kg> let d = 2.0M<kg>
#if !NetCore
let tmpCulture = System.Threading.Thread.CurrentThread.CurrentCulture let tmpCulture = System.Threading.Thread.CurrentThread.CurrentCulture
System.Threading.Thread.CurrentThread.CurrentCulture <- System.Globalization.CultureInfo("en-US") System.Threading.Thread.CurrentThread.CurrentCulture <- System.Globalization.CultureInfo("en-US")
test "f" (f.ToString().Equals("2")) test "f" (f.ToString().Equals("2"))
test "s" (s.ToString().Equals("2")) test "s" (s.ToString().Equals("2"))
test "d" (d.ToString().Equals("2.0")) test "d" (d.ToString().Equals("2.0"))
System.Threading.Thread.CurrentThread.CurrentCulture <- tmpCulture System.Threading.Thread.CurrentThread.CurrentCulture <- tmpCulture
#endif
let fc = (f :> System.IComparable<float<kg>>).CompareTo(f+f) let fc = (f :> System.IComparable<float<kg>>).CompareTo(f+f)
let sc = (s :> System.IComparable<float32<kg>>).CompareTo(s+s) let sc = (s :> System.IComparable<float32<kg>>).CompareTo(s+s)
......
...@@ -85,6 +85,7 @@ type internal ServiceProvider(getService:Type->obj) = ...@@ -85,6 +85,7 @@ type internal ServiceProvider(getService:Type->obj) =
member sp.TextManager:IVsTextManager = downcast (getService (typeof<SVsTextManager>)) member sp.TextManager:IVsTextManager = downcast (getService (typeof<SVsTextManager>))
member sp.Rdt:IVsRunningDocumentTable = downcast (getService (typeof<SVsRunningDocumentTable>)) member sp.Rdt:IVsRunningDocumentTable = downcast (getService (typeof<SVsRunningDocumentTable>))
member sp.XmlService:IVsXMLMemberIndexService = downcast (getService (typeof<SVsXMLMemberIndexService>)) member sp.XmlService:IVsXMLMemberIndexService = downcast (getService (typeof<SVsXMLMemberIndexService>))
member sp.DTE:EnvDTE.DTE = downcast (getService (typeof<SDTE>))
static member Stub = ServiceProvider(fun _t->raise (Error.UseOfUnitializedServiceProvider)) static member Stub = ServiceProvider(fun _t->raise (Error.UseOfUnitializedServiceProvider))
/// Isolate VsTextManager as much as possible to ease transition into new editor architecture /// Isolate VsTextManager as much as possible to ease transition into new editor architecture
......
...@@ -6,6 +6,9 @@ open System ...@@ -6,6 +6,9 @@ open System
open System.Text open System.Text
open System.Collections.Generic open System.Collections.Generic
open Internal.Utilities.Collections open Internal.Utilities.Collections
open Microsoft.VisualStudio
open EnvDTE
open EnvDTE80
open Microsoft.VisualStudio.Shell.Interop open Microsoft.VisualStudio.Shell.Interop
open Microsoft.FSharp.Compiler.SourceCodeServices open Microsoft.FSharp.Compiler.SourceCodeServices
...@@ -27,9 +30,14 @@ module internal XmlDocumentation = ...@@ -27,9 +30,14 @@ module internal XmlDocumentation =
else xml else xml
/// Provide Xml Documentation /// Provide Xml Documentation
type Provider(xmlIndexService:IVsXMLMemberIndexService) = type Provider(xmlIndexService:IVsXMLMemberIndexService, dte: DTE) =
/// Index of assembly name to xml member index. /// Index of assembly name to xml member index.
let mutable xmlCache = new AgedLookup<string,IVsXMLMemberIndex>(10,areSame=(fun (x,y) -> x = y)) let mutable xmlCache = new AgedLookup<string,IVsXMLMemberIndex>(10,areSame=(fun (x,y) -> x = y))
let events = dte.Events :?> Events2
let solutionEvents = events.SolutionEvents
do solutionEvents.add_AfterClosing(fun () ->
xmlCache.Clear())
let HasTrailingEndOfLine(sb:StringBuilder) = let HasTrailingEndOfLine(sb:StringBuilder) =
if sb.Length = 0 then true if sb.Length = 0 then true
...@@ -188,7 +196,7 @@ module internal XmlDocumentation = ...@@ -188,7 +196,7 @@ module internal XmlDocumentation =
with e-> with e->
Assert.Exception(e) Assert.Exception(e)
reraise() reraise()
/// Append an XmlCommnet to the segment. /// Append an XmlCommnet to the segment.
let AppendXmlComment(documentationProvider:IdealDocumentationProvider, segment:StringBuilder, xml, showExceptions, showParameters, paramName) = let AppendXmlComment(documentationProvider:IdealDocumentationProvider, segment:StringBuilder, xml, showExceptions, showParameters, paramName) =
match xml with match xml with
......
...@@ -5,12 +5,12 @@ open System ...@@ -5,12 +5,12 @@ open System
open System.Text open System.Text
open Microsoft.VisualStudio.Shell.Interop open Microsoft.VisualStudio.Shell.Interop
open Microsoft.FSharp.Compiler.SourceCodeServices open Microsoft.FSharp.Compiler.SourceCodeServices
open EnvDTE
module internal XmlDocumentation = module internal XmlDocumentation =
type Provider = type Provider =
interface IdealDocumentationProvider interface IdealDocumentationProvider
new : xmlIndexService:IVsXMLMemberIndexService -> Provider new : xmlIndexService:IVsXMLMemberIndexService * dte: DTE -> Provider
/// Build a data tip text string with xml comments injected. /// Build a data tip text string with xml comments injected.
val BuildDataTipText : IdealDocumentationProvider * DataTipText -> string val BuildDataTipText : IdealDocumentationProvider * DataTipText -> string
......
...@@ -1593,7 +1593,7 @@ and [<Guid(FSharpConstants.languageServiceGuidString)>] ...@@ -1593,7 +1593,7 @@ and [<Guid(FSharpConstants.languageServiceGuidString)>]
Source.CreateSource(fls, buffer, fls.GetColorizer(buffer), fileChangeEx) Source.CreateSource(fls, buffer, fls.GetColorizer(buffer), fileChangeEx)
ls.Initialize ls.Initialize
(sp, (sp,
(XmlDocumentation.Provider(sp.XmlService) :> IdealDocumentationProvider), (XmlDocumentation.Provider(sp.XmlService, sp.DTE) :> IdealDocumentationProvider),
(preferences :> LanguagePreferences), (preferences :> LanguagePreferences),
enableStandaloneFileIntellisense, enableStandaloneFileIntellisense,
createSource) createSource)
...@@ -2113,4 +2113,4 @@ type FSharpPackage() as self = ...@@ -2113,4 +2113,4 @@ type FSharpPackage() as self =
override x.Terminate() = () override x.Terminate() = ()
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册