From a8217517334e23a42258667af1ebb08b165f8c0d Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Tue, 6 Jun 2023 15:29:40 +0100 Subject: [PATCH 1/7] [skip ci] Update release notes --- ReleaseNotes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 9753d4f9..da156320 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -3,7 +3,9 @@ A. Start with the Quick Start guide : https://github.com/SteveGilham/altcover/wiki/QuickStart-Guide and read the FAQ : https://github.com/SteveGilham/altcover/wiki/FAQ -# (Habu series release 22) +# (Habu series release 23) + +# 8.6.61 (Habu series release 22) * [BUGFIX] prevent possible "The lists had different lengths." exception in the collect phase (Issue 181) * Removes some obsolete code from the `dotnet test` integration * Drop support for Fake 5.23.x From aa6f5b83ee5a69503d314588a9bed8eab4093e43 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Thu, 8 Jun 2023 08:47:07 +0100 Subject: [PATCH 2/7] Simplify/manual linting --- AltCover.Engine/ProgramDatabase.fs | 3 +-- AltCover.Engine/Visitor.fs | 9 ++++----- AltCover.Tests/Tests.fs | 18 ++++++------------ AltCover.Tests/Tests2.fs | 9 +++------ Demo/inspector/Program.fs | 6 ++---- 5 files changed, 16 insertions(+), 29 deletions(-) diff --git a/AltCover.Engine/ProgramDatabase.fs b/AltCover.Engine/ProgramDatabase.fs index 5b324fae..a2f1b828 100644 --- a/AltCover.Engine/ProgramDatabase.fs +++ b/AltCover.Engine/ProgramDatabase.fs @@ -272,8 +272,7 @@ module internal ProgramDatabase = let folder = foldername :: (Seq.toList symbolFolders) - |> Seq.map (I.getSymbolsByFolder filename) - |> Seq.choose id + |> Seq.choose (I.getSymbolsByFolder filename) |> Seq.tryFind (I.symbolMatch tokens) sprintf diff --git a/AltCover.Engine/Visitor.fs b/AltCover.Engine/Visitor.fs index ce689168..88034f77 100644 --- a/AltCover.Engine/Visitor.fs +++ b/AltCover.Engine/Visitor.fs @@ -820,7 +820,7 @@ module internal Visitor = + name CoverageParameters.trackingNames - |> Seq.map (fun n -> + |> Seq.choose (fun n -> if n.Chars(0) = '[' then let stripped = n.Trim([| '['; ']' |]) @@ -844,7 +844,6 @@ module internal Visitor = Some n else None) - |> Seq.choose id |> Seq.tryFind (fun _ -> true) |> Option.map (fun n -> let id = methodNumber + 1 @@ -1649,18 +1648,18 @@ module internal Visitor = "AvoidMessageChainsRule", Scope = "member", Target = - "AltCover.Visitor/I/generated@1380::Invoke(Mono.Cecil.Cil.Instruction)", + "AltCover.Visitor/I/generated@1379::Invoke(Mono.Cecil.Cil.Instruction)", Justification = "No direct call available")>] [,Microsoft.FSharp.Collections.FSharpList`1)", + "AltCover.Visitor/I/start@1229::Invoke(Microsoft.FSharp.Core.FSharpFunc`2,Microsoft.FSharp.Collections.FSharpList`1)", Justification = "Inlined library code")>] [,Microsoft.FSharp.Collections.FSharpList`1)", + "AltCover.Visitor/I/finish@1232::Invoke(Microsoft.FSharp.Core.FSharpFunc`2,Microsoft.FSharp.Collections.FSharpList`1)", Justification = "Inlined library code")>] () \ No newline at end of file diff --git a/AltCover.Tests/Tests.fs b/AltCover.Tests/Tests.fs index 5631b715..c4148d12 100644 --- a/AltCover.Tests/Tests.fs +++ b/AltCover.Tests/Tests.fs @@ -1845,8 +1845,7 @@ module AltCoverTests = Assert.That( methods - |> Seq.map Visitor.I.containingMethod - |> Seq.choose id + |> Seq.choose Visitor.I.containingMethod |> Seq.filter (fun m -> m.Name = "G3"), Is.EquivalentTo [ g3; g3; g3 ] ) @@ -1855,8 +1854,7 @@ module AltCoverTests = Assert.That( methods - |> Seq.map Visitor.I.containingMethod - |> Seq.choose id + |> Seq.choose Visitor.I.containingMethod |> Seq.filter (fun m -> m.Name = "G1"), Is.EquivalentTo [ g1; g1 ] ) @@ -2970,8 +2968,7 @@ module AltCoverTests = let tracks = def.MainModule.GetAllTypes() |> Seq.collect (fun t -> t.Methods) - |> Seq.map (Visitor.I.track) - |> Seq.choose id + |> Seq.choose (Visitor.I.track) |> Seq.toList Assert.That(tracks, Is.EquivalentTo [ (1, "[Test"); (2, "[Test") ]) @@ -3029,8 +3026,7 @@ module AltCoverTests = let tracks = def.MainModule.GetAllTypes() |> Seq.collect (fun t -> t.Methods) - |> Seq.map (Visitor.I.track) - |> Seq.choose id + |> Seq.choose (Visitor.I.track) |> Seq.toList Assert.That( @@ -3069,8 +3065,7 @@ module AltCoverTests = let tracks = def.MainModule.GetAllTypes() |> Seq.collect (fun t -> t.Methods) - |> Seq.map (Visitor.I.track) - |> Seq.choose id + |> Seq.choose (Visitor.I.track) |> Seq.toList Assert.That( @@ -4661,11 +4656,10 @@ module AltCoverTests = Inspection = Inspections.Instrument Track = None DefaultVisitCount = Exemption.None } - |> Seq.map (fun n -> + |> Seq.choose (fun n -> match n with | BranchPoint b -> Some b | _ -> None) - |> Seq.choose id |> Seq.toList // The only overt branching in this function are the 4 match cases // Internal IL conditional branching is a compiler thing from inlining "string" diff --git a/AltCover.Tests/Tests2.fs b/AltCover.Tests/Tests2.fs index 61ec91f2..58168413 100644 --- a/AltCover.Tests/Tests2.fs +++ b/AltCover.Tests/Tests2.fs @@ -2109,11 +2109,10 @@ has been prefixed with Ldc_I4_1 (1 byte) Inspection = Inspections.Instrument Track = None DefaultVisitCount = Exemption.None } - |> Seq.map (fun n -> + |> Seq.choose (fun n -> match n with | BranchPoint b -> Some b | _ -> None) - |> Seq.choose id |> Seq.take 2 // start of a switch |> Seq.toList @@ -2207,11 +2206,10 @@ has been prefixed with Ldc_I4_1 (1 byte) Inspection = Inspections.Instrument Track = None DefaultVisitCount = Exemption.None } - |> Seq.map (fun n -> + |> Seq.choose (fun n -> match n with | BranchPoint b -> Some b | _ -> None) - |> Seq.choose id |> Seq.skip 2 |> Seq.take 2 // first of "switch" |> Seq.toList @@ -2298,11 +2296,10 @@ has been prefixed with Ldc_I4_1 (1 byte) Inspection = Inspections.Instrument Track = None DefaultVisitCount = Exemption.None } - |> Seq.map (fun n -> + |> Seq.choose (fun n -> match n with | BranchPoint b -> Some b | _ -> None) - |> Seq.choose id |> Seq.take 2 // start of a switch |> Seq.toList diff --git a/Demo/inspector/Program.fs b/Demo/inspector/Program.fs index 09959500..85650bc4 100644 --- a/Demo/inspector/Program.fs +++ b/Demo/inspector/Program.fs @@ -91,10 +91,8 @@ let inspect (def: AssemblyDefinition) = [] let main argv = argv - |> Seq.map getFileExists - |> Seq.choose id - |> Seq.map loadInCecil - |> Seq.choose id + |> Seq.choose getFileExists + |> Seq.choose loadInCecil |> Seq.iter inspect 0 // return an integer exit code \ No newline at end of file From 8bc005bb45f0f8892bcf79be65de2faf56ef4856 Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Wed, 14 Jun 2023 12:37:06 +0100 Subject: [PATCH 3/7] new sdk 7.0.304 --- .github/workflows/main.yml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ae61a3b9..e17eee52 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,7 +20,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-dotnet@v3 with: - dotnet-version: '7.0.302' + dotnet-version: '7.0.304' - name: Tools run: dotnet tool restore - name: Setup @@ -51,7 +51,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-dotnet@v3 with: - dotnet-version: '7.0.302' + dotnet-version: '7.0.304' - name: Tools run: dotnet tool restore - name: Setup diff --git a/global.json b/global.json index df1081c3..b516c799 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "7.0.302", + "version": "7.0.304", "rollForward": "latestMinor" } } \ No newline at end of file From c0a8443afa4e7f5c8c8afc7cd6c581bf5840ff3c Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Tue, 4 Jul 2023 08:46:49 +0100 Subject: [PATCH 4/7] Workflow cancellation as per # per https://www.meziantou.net/how-to-cancel-github-workflows-when-pushing-new-commits-on-a-branch.htm --- .github/workflows/main.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e17eee52..66894e06 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,6 +11,17 @@ on: branches: - master +# per https://www.meziantou.net/how-to-cancel-github-workflows-when-pushing-new-commits-on-a-branch.htm +# https://docs.github.com/en/actions/learn-github-actions/expressions +# https://docs.github.com/en/actions/learn-github-actions/contexts#github-context +concurrency: + # github.workflow: name of the workflow + # github.event.pull_request.number || github.ref: pull request number or branch name if not a pull request + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + + # Cancel in-progress runs when a new workflow with the same group name is triggered + cancel-in-progress: true + jobs: windows: runs-on: windows-latest From 886583d6b63ae6f63f2e4ff358573b52b366e25e Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Tue, 4 Jul 2023 08:47:47 +0100 Subject: [PATCH 5/7] For me, one at a time globally should do OK. --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 66894e06..5dd5ab26 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,8 @@ on: concurrency: # github.workflow: name of the workflow # github.event.pull_request.number || github.ref: pull request number or branch name if not a pull request - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + group: ${{ github.workflow }} + #-${{ github.event.pull_request.number || github.ref }} # Cancel in-progress runs when a new workflow with the same group name is triggered cancel-in-progress: true From 5fd86456ac67b0c6299f52280e8ddd9014bed80d Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Mon, 10 Jul 2023 17:06:56 +0100 Subject: [PATCH 6/7] Skip anonymous types with zero code points just like we skip other compiler generated cruft --- AltCover.Engine/Visitor.fs | 32 ++++++++++++++++++++++---------- AltCover.Tests/Tests.fs | 10 ++++++++-- Samples/Sample21/UnitTest1.cs | 16 ++++++++++++++++ 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/AltCover.Engine/Visitor.fs b/AltCover.Engine/Visitor.fs index 88034f77..e30dfa89 100644 --- a/AltCover.Engine/Visitor.fs +++ b/AltCover.Engine/Visitor.fs @@ -284,6 +284,10 @@ module internal CoverageParameters = let mutable internal staticFilter: StaticFilter option = None + let effectiveStaticFilter () = + staticFilter + |> Option.defaultValue StaticFilter.Hidden + let internal showGenerated = ref false let generationFilter = @@ -747,6 +751,15 @@ module internal Visitor = t.Methods |> Seq.exists (fun m -> m.IsAbstract |> not) + [] + let internal stripAnonymous (t: TypeDefinition) = + t.Name.StartsWith("<>f__AnonymousType", StringComparison.Ordinal) + |> not + || CoverageParameters.effectiveStaticFilter () + <> StaticFilter.Hidden + let private visitModule (x: ModuleEntry) (buildSequence: Node -> seq) = zeroPoints () @@ -772,7 +785,8 @@ module internal Visitor = |> Seq.collect (fun x -> x.Module.GetAllTypes() |> Seq.cast - |> Seq.filter stripInterfaces) + |> Seq.filter stripInterfaces + |> Seq.filter stripAnonymous) |> Seq.collect ( (fun t -> let types = @@ -1108,9 +1122,7 @@ module internal Visitor = if significant m then StaticFilter.NoFilter else - match CoverageParameters.staticFilter with - | None -> StaticFilter.Hidden - | Some f -> f + CoverageParameters.effectiveStaticFilter () (m, key)) |> Seq.filter (fun (m, k) -> k <> StaticFilter.Hidden) @@ -1226,10 +1238,10 @@ module internal Visitor = let places = List.concat [ toNext; toJump ] let start = - places |> (boundaryOfList List.minBy) + places |> (boundaryOfList List.minBy) // This line to suppress let finish = - places |> (boundaryOfList List.maxBy) + places |> (boundaryOfList List.maxBy) // This line to suppress let range = Seq.unfold @@ -1376,7 +1388,7 @@ module internal Visitor = // possibly add MoveNext filtering let generated (i: Instruction) = - let before = firstOfSequencePoint dbg i // This line in suppress + let before = firstOfSequencePoint dbg i // This line to suppress let sp = dbg.GetSequencePoint before before.OpCode = OpCodes.Ldloc_0 @@ -1648,18 +1660,18 @@ module internal Visitor = "AvoidMessageChainsRule", Scope = "member", Target = - "AltCover.Visitor/I/generated@1379::Invoke(Mono.Cecil.Cil.Instruction)", + "AltCover.Visitor/I/generated@1391::Invoke(Mono.Cecil.Cil.Instruction)", Justification = "No direct call available")>] [,Microsoft.FSharp.Collections.FSharpList`1)", + "AltCover.Visitor/I/start@1241::Invoke(Microsoft.FSharp.Core.FSharpFunc`2,Microsoft.FSharp.Collections.FSharpList`1)", Justification = "Inlined library code")>] [,Microsoft.FSharp.Collections.FSharpList`1)", + "AltCover.Visitor/I/finish@1244::Invoke(Microsoft.FSharp.Core.FSharpFunc`2,Microsoft.FSharp.Collections.FSharpList`1)", Justification = "Inlined library code")>] () \ No newline at end of file diff --git a/AltCover.Tests/Tests.fs b/AltCover.Tests/Tests.fs index c4148d12..491744b2 100644 --- a/AltCover.Tests/Tests.fs +++ b/AltCover.Tests/Tests.fs @@ -5636,12 +5636,15 @@ module AltCoverTests = test <@ - classes = [ "Sample21.Tests" + classes = [ "Sample21.Product" + "Sample21.Tests" "Sample21.Traditional" ] @> let expectedMethods = - [ "System.String Sample21.Traditional::DoSomething()" + [ "System.String Sample21.Product::Junk(System.String)" + "System.String Sample21.Traditional::DoSomething()" + "System.Void Sample21.Product::.ctor(System.String)" "System.Void Sample21.Tests::.ctor()" "System.Void Sample21.Tests::Setup()" "System.Void Sample21.Tests::Test1()" @@ -5703,6 +5706,7 @@ module AltCoverTests = [ "Sample21.IModern" "Sample21.Modern1" "Sample21.Modern2" + "Sample21.Product" "Sample21.Tests" "Sample21.Traditional" ] @@ -5711,9 +5715,11 @@ module AltCoverTests = let expectedMethods = [ "System.String Sample21.IModern::DoSomething()" "System.String Sample21.Modern2::DoSomething()" + "System.String Sample21.Product::Junk(System.String)" "System.String Sample21.Traditional::DoSomething()" "System.Void Sample21.Modern1::.ctor()" "System.Void Sample21.Modern2::.ctor()" + "System.Void Sample21.Product::.ctor(System.String)" "System.Void Sample21.Tests::.ctor()" "System.Void Sample21.Tests::Setup()" "System.Void Sample21.Tests::Test1()" diff --git a/Samples/Sample21/UnitTest1.cs b/Samples/Sample21/UnitTest1.cs index 5b7ea01e..1737c520 100644 --- a/Samples/Sample21/UnitTest1.cs +++ b/Samples/Sample21/UnitTest1.cs @@ -2,6 +2,22 @@ namespace Sample21 { + public class Product + { + public Product(string name) + { Name = name; } + + public string Name { get; set; } + + public static string Junk(string name) + { + var product = new Product(name); + var bonus = new { note = "You won!" }; + var shipmentWithBonus = new { address = "Somewhere St.", product, bonus }; + return shipmentWithBonus.ToString(); + } + } + public class Tests { [SetUp] From e6a384ff0e947319826bbda16045ba9b62abde8c Mon Sep 17 00:00:00 2001 From: Steve Gilham Date: Mon, 10 Jul 2023 17:10:36 +0100 Subject: [PATCH 7/7] Update release notes --- ReleaseNotes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index da156320..39c02886 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -4,6 +4,8 @@ A. Start with the Quick Start guide : https://github.com/SteveGilham/altcover/wi read the FAQ : https://github.com/SteveGilham/altcover/wiki/FAQ # (Habu series release 23) +* Omit anonymous types from coverage, in the same way as other compiler generated code (auto-properties, equality and related operations on F# distributed unions, etc.) +* Supports net8.0 preview 5 # 8.6.61 (Habu series release 22) * [BUGFIX] prevent possible "The lists had different lengths." exception in the collect phase (Issue 181)