diff --git a/AltCover.Engine/Visitor.fs b/AltCover.Engine/Visitor.fs index d3f8db69e..3be3b8739 100644 --- a/AltCover.Engine/Visitor.fs +++ b/AltCover.Engine/Visitor.fs @@ -807,7 +807,13 @@ module internal Visitor = let methods = ct.Methods let candidates = - methods + (methods.Concat( + ct.DeclaringType // Hope we don't have to generalise this + |> Option.ofObj + |> Option.filter (fun _ -> ct.Name.StartsWith("<", StringComparison.Ordinal)) + |> Option.map (fun c -> c.Methods |> Seq.toList) + |> Option.defaultValue [] + )) |> Seq.filter (fun mx -> (mx.Name = stripped) && mx.HasBody) |> Seq.toList @@ -816,28 +822,45 @@ module internal Visitor = | _ -> let tag = "<" + stripped + ">" + let sibs = + ct.DeclaringType // Hope we don't have to generalise this + |> Option.ofObj + |> Option.map + (fun c -> + c.NestedTypes + |> Seq.filter + (fun t -> t.Name.IndexOf(tag, StringComparison.Ordinal) >= 0) + |> Seq.collect (fun t -> t.Methods) + |> Seq.filter (fun m -> m.HasBody)) + |> Option.defaultValue ([] |> Seq.ofList) + + let peers = + methods + |> Seq.filter + (fun mx -> + (mx.Name.IndexOf(tag, StringComparison.Ordinal) + >= 0) + && mx.HasBody) + + let children = + ct.NestedTypes + |> Seq.filter (fun tx -> tx.Name.StartsWith("<", StringComparison.Ordinal)) + |> Seq.collect (fun tx -> tx.Methods) + |> Seq.filter + (fun mx -> + mx.HasBody + && (mx.Name.IndexOf(tag, StringComparison.Ordinal) + >= 0 + || mx.DeclaringType.Name.IndexOf(tag, StringComparison.Ordinal) + >= 0)) + candidates - .Concat( - methods - |> Seq.filter - (fun mx -> - (mx.Name.IndexOf(tag, StringComparison.Ordinal) - >= 0) - && mx.HasBody) - ) - .Concat( - ct.NestedTypes - |> Seq.filter (fun tx -> tx.Name.StartsWith("<", StringComparison.Ordinal)) - |> Seq.collect (fun tx -> tx.Methods) - |> Seq.filter - (fun mx -> - mx.HasBody - && (mx.Name.IndexOf(tag, StringComparison.Ordinal) - >= 0 - || mx.DeclaringType.Name.IndexOf(tag, StringComparison.Ordinal) - >= 0)) - ) - |> Seq.tryFind predicate + .Concat(sibs) + .Concat(peers) + .Concat(children) + |> Seq.filter predicate + |> Seq.sortBy (fun mx -> mx.DeclaringType.FullName.Split('/').Length) // strive upwards + |> Seq.tryHead let internal sameType (target: TypeReference) (candidate: TypeReference) = if target = candidate then @@ -904,7 +927,7 @@ module internal Visitor = let internal methodCallsMethod (t: MethodReference) (m: MethodDefinition) = m.Body.Instructions - |> Seq.filter (fun i -> i.OpCode = OpCodes.Call) + |> Seq.filter (fun i -> i.OpCode.FlowControl = FlowControl.Call) |> Seq.exists (fun i -> let tn = (i.Operand :?> MethodReference) @@ -941,7 +964,14 @@ module internal Visitor = let index = (indexOfMatchingClosingAngleBracket mname) - 1 - cSharpContainingMethod mname t index (methodCallsMethod m) + cSharpContainingMethod + mname + t + index + (fun mx -> + (mx.FullName <> m.FullName) + && (methodCallsMethod m mx)) + else let n = t.Name @@ -1013,7 +1043,8 @@ module internal Visitor = then None else - containingMethod x + let next = containingMethod x + next )) (Some m) |> Seq.toList diff --git a/AltCover.Tests/Tests.fs b/AltCover.Tests/Tests.fs index bbe66dedf..d74d1d392 100644 --- a/AltCover.Tests/Tests.fs +++ b/AltCover.Tests/Tests.fs @@ -1621,94 +1621,143 @@ module AltCoverTests = use def = Mono.Cecil.AssemblyDefinition.ReadAssembly(sample3) + // ProgramDatabase.readSymbols def + let methods = def.MainModule.GetAllTypes() |> Seq.collect (fun t -> t.Methods) - |> Seq.sortBy (fun m -> m.FullName) + |> Seq.sortBy (fun m -> m.DeclaringType.FullName + "::" + m.Name) |> Seq.toList + //methods + //|> Seq.iter (fun m -> printf "%A::%A " m.DeclaringType.FullName m.Name + // m.DebugInformation.SequencePoints + // |> Seq.iter (fun s -> printf "%A " s.StartLine) + // printfn ".") + let containing = methods |> Seq.map Visitor.I.containingMethod let result = containing |> Seq.map (fun (mo: MethodDefinition option) -> mo |> Option.map id) + |> Seq.toList + + //let problem = Visitor.I.containingMethod methods.[68] let expected = - [ Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // K Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.Generic.IEnumerator.get_Current() - Some "get_ValuesWorks" // K Sample5.RecursiveSyntheticInvocation`2/d__4::System.Collections.Generic.IEnumerator.get_Current() - None // K Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.get_Item(T) - Some "F2" // System.Boolean Sample5.Class1/d__1::MoveNext() - Some "G2" // System.Boolean Sample5.Class1/Inner/d__2`1::MoveNext() - Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Boolean Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::MoveNext() - Some "get_ValuesWorks" // System.Boolean Sample5.RecursiveSyntheticInvocation`2/d__4::MoveNext() - None // System.Boolean Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.ContainsKey(T) - None // System.Boolean Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.TryGetValue(T,K&) - None // System.Collections.Generic.IEnumerable`1 Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.get_Values() - None // System.Collections.Generic.IEnumerable`1 Sample5.RecursiveSyntheticInvocation`2::get_ValuesWorks() - None // System.Collections.Generic.IEnumerable`1 Sample5.Class1::F2(System.String) - None // System.Collections.Generic.IEnumerable`1 Sample5.Class1/Inner::G2(T) - None // System.Collections.Generic.IEnumerable`1 Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.get_Keys() - Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Collections.Generic.IEnumerator`1 Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.Generic.IEnumerable.GetEnumerator() - Some "get_ValuesWorks" // System.Collections.Generic.IEnumerator`1 Sample5.RecursiveSyntheticInvocation`2/d__4::System.Collections.Generic.IEnumerable.GetEnumerator() - None // System.Collections.Generic.IEnumerator`1> Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IEnumerable>.GetEnumerator() - Some "F2" // System.Collections.Generic.IEnumerator`1 Sample5.Class1/d__1::System.Collections.Generic.IEnumerable.GetEnumerator() - Some "G2" // System.Collections.Generic.IEnumerator`1 Sample5.Class1/Inner/d__2`1::System.Collections.Generic.IEnumerable.GetEnumerator() - Some "F2" // System.Collections.IEnumerator Sample5.Class1/d__1::System.Collections.IEnumerable.GetEnumerator() - Some "G2" // System.Collections.IEnumerator Sample5.Class1/Inner/d__2`1::System.Collections.IEnumerable.GetEnumerator() - Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Collections.IEnumerator Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.IEnumerable.GetEnumerator() - Some "get_ValuesWorks" // System.Collections.IEnumerator Sample5.RecursiveSyntheticInvocation`2/d__4::System.Collections.IEnumerable.GetEnumerator() - None // System.Collections.IEnumerator Sample5.RecursiveSyntheticInvocation`2::System.Collections.IEnumerable.GetEnumerator() - Some "F1" // System.Int32 Sample5.Class1/<>c::b__0_0(System.Char) - Some "F1" // System.Int32 Sample5.Class1/<>c__DisplayClass0_0::b__2(System.Char) - Some "F2" // System.Int32 Sample5.Class1/d__1::System.Collections.Generic.IEnumerator.get_Current() - Some "G1" // System.Int32 Sample5.Class1/Inner/<>c::b__0_0(System.Char) - Some "G1" // System.Int32 Sample5.Class1/Inner/<>c__DisplayClass0_0::b__3(System.Char) - Some "b__3" // System.Int32 Sample5.Class1/Inner::g__Interior|0_2(System.Int32,System.Int32) - Some "g__Interior|0_2" // System.Int32 Sample5.Class1/Inner::g__Recursive|0_4(System.Int32) - None // System.Int32 Sample5.Class1/Inner::G1(System.String) // g1 - Some "F1" // System.Int32 Sample5.Class1::g__Interior|0_1(System.Int32,System.Int32) - Some "F1" // System.Int32 Sample5.Class1::g__Recursive|0_3(System.Int32) - None // System.Int32 Sample5.Class1::F1(System.String) - None // System.Int32 Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyCollection>.get_Count() - Some "F2" // System.Object Sample5.Class1/d__1::System.Collections.IEnumerator.get_Current() - Some "G2" // System.Object Sample5.Class1/Inner/d__2`1::System.Collections.IEnumerator.get_Current() - Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Object Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.IEnumerator.get_Current() - Some "get_ValuesWorks" // System.Object Sample5.RecursiveSyntheticInvocation`2/d__4::System.Collections.IEnumerator.get_Current() - None // System.Threading.Tasks.Task`1 Sample5.Class1/Inner::G3(System.String) // g3 - None // System.Threading.Tasks.Task`1 Sample5.Class1::F3(System.String) - None // System.Void Sample5.Class1/<>c::.cctor() + [ None // System.Void Sample5.Class1/<>c::.cctor() None // System.Void Sample5.Class1/<>c::.ctor() + Some "F1" // System.Int32 Sample5.Class1/<>c::b__0_0(System.Char) None // System.Void Sample5.Class1/<>c__DisplayClass0_0::.ctor() + Some "F1" // System.Int32 Sample5.Class1/<>c__DisplayClass0_0::b__2(System.Char) Some "F2" // System.Void Sample5.Class1/d__1::.ctor(System.Int32) + Some "F2" // System.Boolean Sample5.Class1/d__1::MoveNext() + Some "F2" // System.Collections.Generic.IEnumerator`1 Sample5.Class1/d__1::System.Collections.Generic.IEnumerable.GetEnumerator() + Some "F2" // System.Int32 Sample5.Class1/d__1::System.Collections.Generic.IEnumerator.get_Current() + Some "F2" // System.Collections.IEnumerator Sample5.Class1/d__1::System.Collections.IEnumerable.GetEnumerator() Some "F2" // System.Void Sample5.Class1/d__1::System.Collections.IEnumerator.Reset() + Some "F2" // System.Object Sample5.Class1/d__1::System.Collections.IEnumerator.get_Current() Some "F2" // System.Void Sample5.Class1/d__1::System.IDisposable.Dispose() Some "F3" // System.Void Sample5.Class1/d__2::.ctor() Some "F3" // System.Void Sample5.Class1/d__2::MoveNext() Some "F3" // System.Void Sample5.Class1/d__2::SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine) None // System.Void Sample5.Class1/Inner/<>c::.cctor() None // System.Void Sample5.Class1/Inner/<>c::.ctor() + Some "G1" // System.Int32 Sample5.Class1/Inner/<>c::b__0_0(System.Char) None // System.Void Sample5.Class1/Inner/<>c__DisplayClass0_0::.ctor() + Some "G1" // System.Int32 Sample5.Class1/Inner/<>c__DisplayClass0_0::b__3(System.Char) Some "G2" // System.Void Sample5.Class1/Inner/d__2`1::.ctor(System.Int32) + Some "G2" // System.Boolean Sample5.Class1/Inner/d__2`1::MoveNext() + Some "G2" // System.Collections.Generic.IEnumerator`1 Sample5.Class1/Inner/d__2`1::System.Collections.Generic.IEnumerable.GetEnumerator() + Some "G2" // T Sample5.Class1/Inner/d__2`1::System.Collections.Generic.IEnumerator.get_Current() + Some "G2" // System.Collections.IEnumerator Sample5.Class1/Inner/d__2`1::System.Collections.IEnumerable.GetEnumerator() Some "G2" // System.Void Sample5.Class1/Inner/d__2`1::System.Collections.IEnumerator.Reset() + Some "G2" // System.Object Sample5.Class1/Inner/d__2`1::System.Collections.IEnumerator.get_Current() Some "G2" // System.Void Sample5.Class1/Inner/d__2`1::System.IDisposable.Dispose() Some "G3" // System.Void Sample5.Class1/Inner/d__4::.ctor() Some "G3" // System.Void Sample5.Class1/Inner/d__4::MoveNext() Some "G3" // System.Void Sample5.Class1/Inner/d__4::SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine) None // System.Void Sample5.Class1/Inner::.ctor() + Some "g__Recursive|0_4" // T[] Sample5.Class1/Inner::g__InteriorToArray|0_1(T) + Some "b__3" // System.Int32 Sample5.Class1/Inner::g__Interior|0_2(System.Int32,System.Int32) + Some "g__Interior|0_2" // System.Int32 Sample5.Class1/Inner::g__Recursive|0_4(System.Int32) + None // System.Int32 Sample5.Class1/Inner::G1(System.String) None // System.Void Sample5.Class1/Inner::G1(System.Int32) + None // System.Collections.Generic.IEnumerable`1 Sample5.Class1/Inner::G2(T) None // System.Void Sample5.Class1/Inner::G2(System.Int32) + None // System.Threading.Tasks.Task`1 Sample5.Class1/Inner::G3(System.String) None // System.Void Sample5.Class1/Inner::G3(System.Int32) None // System.Void Sample5.Class1::.ctor() + Some "F1" // System.Int32 Sample5.Class1::g__Interior|0_1(System.Int32,System.Int32) + Some "F1" // System.Int32 Sample5.Class1::g__Recursive|0_3(System.Int32) + None // System.Int32 Sample5.Class1::F1(System.String) + None // System.Collections.Generic.IEnumerable`1 Sample5.Class1::F2(System.String) + None // System.Threading.Tasks.Task`1 Sample5.Class1::F3(System.String) + Some "g__InnerAsync3|0" // System.Void Sample5.Issue135/<>c__DisplayClass2_0/<g__InnerAsync3|0>d::.ctor() + Some "g__InnerAsync3|0" // System.Void Sample5.Issue135/<>c__DisplayClass2_0/<g__InnerAsync3|0>d::MoveNext() + Some "g__InnerAsync3|0" // System.Void Sample5.Issue135/<>c__DisplayClass2_0/<g__InnerAsync3|0>d::SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine) + None // System.Void Sample5.Issue135/<>c__DisplayClass2_0::.ctor() + Some "OuterAsync2" // System.Threading.Tasks.Task Sample5.Issue135/<>c__DisplayClass2_0::g__InnerAsync3|0(System.Object) <== "is" InnerAsync + Some "g__InnerAsync5|0" // System.Void Sample5.Issue135/<>c__DisplayClass3_0/<g__InnerAsync5|0>d::.ctor() + Some "g__InnerAsync5|0" // System.Void Sample5.Issue135/<>c__DisplayClass3_0/<g__InnerAsync5|0>d::MoveNext() + Some "g__InnerAsync5|0" // System.Void Sample5.Issue135/<>c__DisplayClass3_0/<g__InnerAsync5|0>d::SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine) + None // System.Void Sample5.Issue135/<>c__DisplayClass3_0::.ctor() + Some "OuterSynch4" // System.Threading.Tasks.Task Sample5.Issue135/<>c__DisplayClass3_0::g__InnerAsync5|0(System.Object) + Some "OuterAsync2" // System.Void Sample5.Issue135/d__2::.ctor() + Some "OuterAsync2" // System.Void Sample5.Issue135/d__2::MoveNext() + Some "OuterAsync2" // System.Void Sample5.Issue135/d__2::SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine) + None // System.Void Sample5.Issue135::.ctor(System.Object) + None // System.Threading.Tasks.Task Sample5.Issue135::OuterAsync2(System.Object) + None // System.Void Sample5.Issue135::OuterSynch4(System.Object) + Some "g__InnerAsync3|0" // System.Void Sample5.Issue135Complex/<>c__DisplayClass5_0`1/<g__InnerAsync3|0>d::.ctor() + Some "g__InnerAsync3|0" // System.Void Sample5.Issue135Complex/<>c__DisplayClass5_0`1/<g__InnerAsync3|0>d::MoveNext() + Some "g__InnerAsync3|0" // System.Void Sample5.Issue135Complex/<>c__DisplayClass5_0`1/<g__InnerAsync3|0>d::SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine) + None // System.Void Sample5.Issue135Complex/<>c__DisplayClass5_0`1::.ctor() + Some "MoveNext" // System.Threading.Tasks.Task Sample5.Issue135Complex/<>c__DisplayClass5_0`1::g__InnerAsync3|0(T) + Some "g__InnerAsync5|0" // System.Void Sample5.Issue135Complex/<>c__DisplayClass6_0`1/<g__InnerAsync5|0>d::.ctor() + Some "g__InnerAsync5|0" // System.Void Sample5.Issue135Complex/<>c__DisplayClass6_0`1/<g__InnerAsync5|0>d::MoveNext() + Some "g__InnerAsync5|0" // System.Void Sample5.Issue135Complex/<>c__DisplayClass6_0`1/<g__InnerAsync5|0>d::SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine) + None // System.Void Sample5.Issue135Complex/<>c__DisplayClass6_0`1::.ctor() + Some "OuterSynch4" // System.Threading.Tasks.Task Sample5.Issue135Complex/<>c__DisplayClass6_0`1::g__InnerAsync5|0(T) + Some "OuterAsync2" // System.Void Sample5.Issue135Complex/d__5`1::.ctor() + Some "OuterAsync2" // System.Void Sample5.Issue135Complex/d__5`1::MoveNext() + Some "OuterAsync2" // System.Void Sample5.Issue135Complex/d__5`1::SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine) + None // System.Void Sample5.Issue135Complex::.ctor(System.Object) + None // System.Void Sample5.Issue135Complex::OuterAsync2() + None // System.String Sample5.Issue135Complex::OuterAsync2(System.Object) + None // System.String Sample5.Issue135Complex::OuterAsync2(T,U) + None // System.Threading.Tasks.Task Sample5.Issue135Complex::OuterAsync2(T) + None // System.Void Sample5.Issue135Complex::OuterSynch4(T) + None // System.Void Sample5.Issue135Complex::OuterSynch4() + None // System.String Sample5.Issue135Complex::OuterSynch4(System.Object) + None // System.String Sample5.Issue135Complex::OuterSynch4(T,U) Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Void Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::.ctor(System.Int32) + Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Boolean Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::MoveNext() + Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Collections.Generic.IEnumerator`1 Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.Generic.IEnumerable.GetEnumerator() + Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // K Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.Generic.IEnumerator.get_Current() + Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Collections.IEnumerator Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.IEnumerable.GetEnumerator() Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Void Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.IEnumerator.Reset() + Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Object Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.Collections.IEnumerator.get_Current() Some "System.Collections.Generic.IReadOnlyDictionary.get_Values" // System.Void Sample5.RecursiveSyntheticInvocation`2/-get_Values>d__2::System.IDisposable.Dispose() Some "get_ValuesWorks" // System.Void Sample5.RecursiveSyntheticInvocation`2/d__4::.ctor(System.Int32) + Some "get_ValuesWorks" // System.Boolean Sample5.RecursiveSyntheticInvocation`2/d__4::MoveNext() + Some "get_ValuesWorks" // System.Collections.Generic.IEnumerator`1 Sample5.RecursiveSyntheticInvocation`2/d__4::System.Collections.Generic.IEnumerable.GetEnumerator() + Some "get_ValuesWorks" // K Sample5.RecursiveSyntheticInvocation`2/d__4::System.Collections.Generic.IEnumerator.get_Current() + Some "get_ValuesWorks" // System.Collections.IEnumerator Sample5.RecursiveSyntheticInvocation`2/d__4::System.Collections.IEnumerable.GetEnumerator() Some "get_ValuesWorks" // System.Void Sample5.RecursiveSyntheticInvocation`2/d__4::System.Collections.IEnumerator.Reset() + Some "get_ValuesWorks" // System.Object Sample5.RecursiveSyntheticInvocation`2/d__4::System.Collections.IEnumerator.get_Current() Some "get_ValuesWorks" // System.Void Sample5.RecursiveSyntheticInvocation`2/d__4::System.IDisposable.Dispose() None // System.Void Sample5.RecursiveSyntheticInvocation`2::.ctor() - Some "G2" // T Sample5.Class1/Inner/d__2`1::System.Collections.Generic.IEnumerator.get_Current() - Some "g__Recursive|0_4" ] // T[] Sample5.Class1/Inner::g__InteriorToArray|0_1(T) + None // System.Collections.Generic.IEnumerator`1> Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IEnumerable>.GetEnumerator() + None // System.Int32 Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyCollection>.get_Count() + None // System.Boolean Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.ContainsKey(T) + None // System.Boolean Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.TryGetValue(T,K&) + None // K Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.get_Item(T) + None // System.Collections.Generic.IEnumerable`1 Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.get_Keys() + None // System.Collections.Generic.IEnumerable`1 Sample5.RecursiveSyntheticInvocation`2::System.Collections.Generic.IReadOnlyDictionary.get_Values() + None // System.Collections.IEnumerator Sample5.RecursiveSyntheticInvocation`2::System.Collections.IEnumerable.GetEnumerator() + None ] // System.Collections.Generic.IEnumerable`1 Sample5.RecursiveSyntheticInvocation`2::get_ValuesWorks() // methods |> Seq.iter (fun x -> printfn "%A" x.FullName) // Assert.That (result, Is.EquivalentTo expected) @@ -1732,7 +1781,6 @@ module AltCoverTests = )) result - |> Seq.toList |> List.zip expected |> List.iteri (fun i (x, y) -> @@ -1741,8 +1789,17 @@ module AltCoverTests = x |> Is.EqualTo, sprintf "%A %A %d" x (y |> Option.map toFullName) i )) + // Disambiguation checks - let g3 = methods.[40] + // System.Threading.Tasks.Task Sample5.Issue135/<>c__DisplayClass2_0::g__InnerAsync3|0(System.Object) + // => System.Void Sample5.Issue135/d__2::MoveNext() + Assert.That( + result.[68].Value, + Is.EqualTo methods.[75], + "The outer move-next was wanted" + ) + + let g3 = methods.[40] // "System.Threading.Tasks.Task`1 Sample5.Class1/Inner::G3(System.String)" Assert.That( methods @@ -1752,7 +1809,7 @@ module AltCoverTests = Is.EquivalentTo [ g3; g3; g3 ] ) - let g1 = methods.[31] + let g1 = methods.[36] // "System.Int32 Sample5.Class1/Inner::G1(System.String)" Assert.That( methods diff --git a/Samples/Sample5/Class1a.cs b/Samples/Sample5/Class1a.cs index e03626934..4498ab6a5 100644 --- a/Samples/Sample5/Class1a.cs +++ b/Samples/Sample5/Class1a.cs @@ -151,4 +151,125 @@ IEnumerable IReadOnlyDictionary.Keys bool IReadOnlyDictionary.TryGetValue(T key, out K value) => throw new NotImplementedException(); } + + [ExcludeFromCodeCoverage] + public class Issue135 + { + private object field; + + public Issue135(object o) + { // whole span is "Sample5.Issue135"::".ctor" + field = o; + } + +#pragma warning disable CS1998 +#pragma warning disable CS4014 + + internal async Task OuterAsync2(T data) + { // span less inner function is "Sample5.Issue135/d__2"::"MoveNext" + [ExcludeFromCodeCoverage] + async Task InnerAsync3(T aux) + { // whole span is "Sample5.Issue135/<>c__DisplayClass2_0/<g__InnerAsync3|0>d"::"MoveNext + Console.WriteLine("{0} | {1} || {2}", field, data, aux); + InnerAsync3((T)field); + InnerAsync3(data); + OuterAsync2(data); + } + + InnerAsync3((T)field); + } // Unless stated, all other methods have no sequence points + + internal void OuterSynch4(T data) + { + async Task InnerAsync5(T aux) + { + Console.WriteLine("{0} |{1} || {2}", field, data, aux); + InnerAsync5((T)field); + InnerAsync5(data); + OuterSynch4(data); + } + + InnerAsync5((T)field); + } +} + +#pragma warning restore CS4014 +#pragma warning restore CS1998 + + + [ExcludeFromCodeCoverage] + public class Issue135Complex + { + private object field; + + public Issue135Complex(object o) + { // whole span is "Sample5.Issue135"::".ctor" + field = o; + } + +#pragma warning disable CS1998 +#pragma warning disable CS4014 + public void OuterAsync2() + { + Console.WriteLine("Simple async"); + } + + public string OuterAsync2(object o) + { + return o.ToString(); + } + + public string OuterAsync2(T a, U b) + { + return a.ToString() + b.ToString(); + } + + + internal async Task OuterAsync2(T data) + { // span less inner function is "Sample5.Issue135/d__2"::"MoveNext" + [ExcludeFromCodeCoverage] + async Task InnerAsync3(T aux) + { // whole span is "Sample5.Issue135/<>c__DisplayClass2_0/<g__InnerAsync3|0>d"::"MoveNext + Console.WriteLine("{0} | {1} || {2}", field, data, aux); + InnerAsync3((T)field); + InnerAsync3(data); + OuterAsync2(data); + } + + InnerAsync3((T)field); + } // Unless stated, all other methods have no sequence points + + internal void OuterSynch4(T data) + { + async Task InnerAsync5(T aux) + { + Console.WriteLine("{0} |{1} || {2}", field, data, aux); + InnerAsync5((T)field); + InnerAsync5(data); + OuterSynch4(data); + } + + InnerAsync5((T)field); + } + + public void OuterSynch4() + { + Console.WriteLine("Simple synch"); + } + + public string OuterSynch4(object o) + { + return o.ToString(); + } + + public string OuterSynch4(T a, U b) + { + return a.ToString() + b.ToString(); + } + +} + +#pragma warning restore CS4014 +#pragma warning restore CS1998 + } \ No newline at end of file diff --git a/Samples/Sample5/Sample5.csproj b/Samples/Sample5/Sample5.csproj index 7958cb02b..04fe6abf4 100644 --- a/Samples/Sample5/Sample5.csproj +++ b/Samples/Sample5/Sample5.csproj @@ -3,6 +3,7 @@ netstandard2.0;net472 Sample5 + 9.0