diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index d10ec4cb..02e5cdbe 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "dotnet-reportgenerator-globaltool": { - "version": "5.1.18", + "version": "5.1.21", "commands": [ "reportgenerator" ] @@ -33,7 +33,7 @@ ] }, "nbgv": { - "version": "3.5.119", + "version": "3.6.133", "commands": [ "nbgv" ] diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aab25756..ae61a3b9 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.202' + dotnet-version: '7.0.302' - 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.202' + dotnet-version: '7.0.302' - name: Tools run: dotnet tool restore - name: Setup diff --git a/AltCover.Api.Tests/FSApiTests.fs b/AltCover.Api.Tests/FSApiTests.fs index 49d30279..516a42d9 100644 --- a/AltCover.Api.Tests/FSApiTests.fs +++ b/AltCover.Api.Tests/FSApiTests.fs @@ -1283,9 +1283,9 @@ module FSApiTests = let combined2 = DotNet.CLIOptions.Many [ a2; force; fail; summary ] - test <@ combined.ForceDelete @> - test <@ combined.FailFast @> - test <@ combined.ShowSummary = "R" @> + test <@ combined2.ForceDelete @> + test <@ combined2.FailFast @> + test <@ combined2.ShowSummary = "R" @> test <@ diff --git a/AltCover.Engine/CecilEx.fs b/AltCover.Engine/CecilEx.fs index 948fb8b9..b43e5f37 100644 --- a/AltCover.Engine/CecilEx.fs +++ b/AltCover.Engine/CecilEx.fs @@ -130,7 +130,6 @@ type internal AssemblyResolver() as self = "dotnet|shared" .Replace('|', Path.DirectorySeparatorChar) - let sources = [ AssemblyConstants.packageEnv [ Environment.GetEnvironmentVariable "ProgramFiles" @@ -180,140 +179,6 @@ type internal AssemblyResolver() as self = [] module internal CecilExtension = - let internal scopesSeen = - System.Collections.Generic.HashSet() - - let internal safeOffset (point: InstructionOffset) = - if point.IsEndOfMethod then - None - else - Some point.Offset - - // workround for old MCS + Cecil 0.11.4 - let pruneLocalScopes (m: MethodDefinition) = - scopesSeen.Clear() - - let rec pruneScope (scope: ScopeDebugInformation) = - let novel = scopesSeen.Add scope - - if novel then - let scopes = scope.Scopes // non-null by construction - - scopes - |> Seq.filter (fun subScope -> - let repeat = - subScope - |> Option.ofObj - |> Option.map pruneScope - |> Option.defaultValue true - - repeat || subScope.Start.IsEndOfMethod) - |> Seq.toList - |> List.iter (scopes.Remove >> ignore) - - not novel - - m.DebugInformation.Scope - |> Option.ofObj - |> Option.map pruneScope - |> ignore - - // address issue 135 - let internal isResolvedProp = - typeof - .GetProperty( - "IsResolved", - System.Reflection.BindingFlags.Instance - ||| System.Reflection.BindingFlags.NonPublic - ) - - let etypeField = - typeof - .GetField( - "etype", - System.Reflection.BindingFlags.Instance - ||| System.Reflection.BindingFlags.NonPublic - ) - - let internal offsetTable = - System.Collections.Generic.SortedDictionary() - - let unresolved (point: InstructionOffset) = - isResolvedProp.GetValue(point) :?> bool |> not - - let checkScopeConstants (m: MethodDefinition) = - scopesSeen - |> Seq.iter (fun scope -> - let sus = - scope.Constants - |> Seq.filter (fun c -> - (isNull c.Value) - && match etypeField.GetValue(c.ConstantType) :?> byte with - | 0x14uy // ElementType.Array - | 0x1duy // ElementType.SzArray - | 0x12uy // ElementType.Class - | 0x1cuy // ElementType.Object - | 0x00uy // ElementType.None - | 0x13uy // ElementType.Var - | 0x1euy // ElementType.MVar - | 0x0euy -> // ElementType.String - false - | _ -> not c.ConstantType.IsPrimitive) - |> Seq.toList - - sus - |> Seq.iter (fun c -> - scope.Constants.Remove c |> ignore - - sprintf "Null Constant %s elided in method %s" c.Name m.FullName - |> Output.verbose)) - - let prepareLocalScopes (m: MethodDefinition) = - offsetTable.Clear() - scopesSeen.Clear() - - let size = - m.Body.Instructions - |> Seq.fold - (fun _ i -> - offsetTable.Add(i.Offset, i) - i.Offset + i.GetSize()) - 0 - - let resolvePoint (point: InstructionOffset) = - point - |> safeOffset - |> Option.map (fun offset -> - let o = Math.Max(offset, 0) - let ok, i = offsetTable.TryGetValue(o) - - if ok then - InstructionOffset(i) - else - offsetTable.Keys - |> Seq.filter (fun kk -> o < size && kk <= o) - |> Seq.tryLast - |> Option.map (fun k -> InstructionOffset(offsetTable.[k])) - |> Option.defaultValue (InstructionOffset())) - |> Option.defaultValue (InstructionOffset()) - - let rec resolveScope (scope: ScopeDebugInformation) = - if scope.IsNotNull then - if scopesSeen.Add scope then - scope.Scopes // non-null by construction - |> Seq.iter resolveScope - - if unresolved scope.Start then - scope.Start <- resolvePoint scope.Start - - if unresolved scope.End then - scope.End <- resolvePoint scope.End - - m.DebugInformation.Scope |> resolveScope - - checkScopeConstants m - - pruneLocalScopes m // Adjust the IL for exception handling // param name="handler">The exception handler diff --git a/AltCover.Engine/Filter.fs b/AltCover.Engine/Filter.fs index 301d360f..2ba7e086 100644 --- a/AltCover.Engine/Filter.fs +++ b/AltCover.Engine/Filter.fs @@ -283,8 +283,13 @@ module internal Filter = || fullName == typeof.FullName))) + [] let internal isFSharpAutoProperty (m: MethodDefinition) = let body = m.Body.Instructions + let fullName = m.DeclaringType.FullName + let name = m.Name if m.IsSetter then body @@ -292,10 +297,8 @@ module internal Filter = |> Option.map (fun i -> let f = i.Operand :?> FieldReference - (f.DeclaringType.FullName - == m.DeclaringType.FullName) - && m.Name.Replace("set_", String.Empty) + "@" - == f.Name) + (f.DeclaringType.FullName == fullName) + && name.Replace("set_", String.Empty) + "@" == f.Name) |> Option.defaultValue false else if m.IsGetter then body @@ -303,10 +306,8 @@ module internal Filter = |> Option.map (fun i -> let f = i.Operand :?> FieldReference - (f.DeclaringType.FullName - == m.DeclaringType.FullName) - && m.Name.Replace("get_", String.Empty) + "@" - == f.Name) + (f.DeclaringType.FullName == fullName) + && name.Replace("get_", String.Empty) + "@" == f.Name) |> Option.defaultValue false else false diff --git a/AltCover.Engine/Instrument.fs b/AltCover.Engine/Instrument.fs index e22b9f32..e7473c7d 100644 --- a/AltCover.Engine/Instrument.fs +++ b/AltCover.Engine/Instrument.fs @@ -363,8 +363,7 @@ module internal Instrument = let head = initialBody |> Seq.head worker.InsertBefore(head, value (worker)) worker.InsertBefore(head, worker.Create(OpCodes.Ret)) - initialBody |> Seq.iter worker.Remove - pruneLocalScopes pathGetterDef) + initialBody |> Seq.iter worker.Remove) [ ("get_Timer", // set the timer interval in ticks CoverageParameters.interval ()) ] @@ -385,8 +384,7 @@ module internal Instrument = worker.InsertBefore(head, worker.Create(OpCodes.Ldc_I4, value)) worker.InsertBefore(head, worker.Create(OpCodes.Conv_I8)) worker.InsertBefore(head, worker.Create(OpCodes.Ret)) - initialBody |> Seq.iter worker.Remove - pruneLocalScopes pathGetterDef)) + initialBody |> Seq.iter worker.Remove)) [ let mt = m.Method - if mt.HasBody then - prepareLocalScopes mt - let body = mt.Body { state with @@ -1046,8 +1041,6 @@ module internal Instrument = body.SimplifyMacros() // changes "long" conditional operators to their short representation where possible body.OptimizeMacros() - // purge dodgy scope data - state.MethodBody.Method |> pruneLocalScopes doTrack state m @@ -1333,8 +1326,6 @@ module internal Instrument = bulkInsertBefore worker head store true |> ignore - pruneLocalScopes getterDef - let recorderFileName = (extractName state.RecordingAssembly) + ".dll" diff --git a/AltCover.Engine/Json.fs b/AltCover.Engine/Json.fs index bdfede6a..19cdd7ba 100644 --- a/AltCover.Engine/Json.fs +++ b/AltCover.Engine/Json.fs @@ -97,6 +97,9 @@ module internal Json = else m0 + [] let internal maybeAssembly path = Some path |> Option.filter File.Exists diff --git a/AltCover.Engine/LCov.fs b/AltCover.Engine/LCov.fs index 95c58b40..9de2c00c 100644 --- a/AltCover.Engine/LCov.fs +++ b/AltCover.Engine/LCov.fs @@ -427,7 +427,7 @@ FN:4,(anonymous_0) vc.ToString(CultureInfo.InvariantCulture) writer.WriteLine("DA:" + sl + "," + vcs) - (f + 1, h + if vcs == "0" then 0 else 1)) + (f + 1, h + (if vcs == "0" then 0 else 1))) (0, 0) // At the end of a section, there is a summary about how many lines were // found and how many were actually instrumented: diff --git a/AltCover.Engine/NativeJson.fs b/AltCover.Engine/NativeJson.fs index 3d0adf80..34e2d7b9 100644 --- a/AltCover.Engine/NativeJson.fs +++ b/AltCover.Engine/NativeJson.fs @@ -20,9 +20,9 @@ open Manatee.Json module #if GUI || RUNNER - internal + internal #endif - NativeJson = + NativeJson = type internal TimeStamp = string diff --git a/AltCover.Engine/Runner.fs b/AltCover.Engine/Runner.fs index 3f5297e4..d673d155 100644 --- a/AltCover.Engine/Runner.fs +++ b/AltCover.Engine/Runner.fs @@ -163,6 +163,9 @@ type internal Threshold = module internal Runner = + let internal defaultSummary = + [ "?"; "?"; "?"; "?"; "?"; "?" ] + let mutable internal recordingDirectory: Option = None @@ -466,6 +469,9 @@ module internal Runner = [] + [] let private makeOpenCoverSummary (report: XDocument) (summary: XElement) = let l = @@ -536,7 +542,7 @@ module internal Runner = report.Root.Elements("Summary".X) |> Seq.tryHead |> Option.map (makeOpenCoverSummary report) - |> Option.defaultValue [] + |> Option.defaultValue defaultSummary [ [] //(result, 0uy, String.Empty) + | Unknown -> defaultSummary | XML report -> report |> match format with | ReportFormat.NCover -> nCoverSummary | _ -> openCoverSummary - | JSON jtext -> jsonSummary jtext // (result, 0uy, String.Empty) // TODO + | JSON jtext -> jsonSummary jtext let best = (result, 0uy, String.Empty) diff --git a/AltCover.Tests/Expecto.fs b/AltCover.Tests/Expecto.fs index 45d2e8ba..f21f56f5 100644 --- a/AltCover.Tests/Expecto.fs +++ b/AltCover.Tests/Expecto.fs @@ -209,6 +209,8 @@ module ExpectoTestManifest = "Runner.SimpleJsonShouldGeneratePlausibleSummary" Tests.AltCoverRunnerTests.ComplexJsonShouldGeneratePlausibleSummary, "Runner.ComplexJsonShouldGeneratePlausibleSummary" + Tests.AltCoverRunnerTests.UnknownGeneratesExpectedSummary, + "Runner.UnknownGeneratesExpectedSummary" Tests.AltCoverRunnerTests.EmptyNCoverGeneratesExpectedSummary, "Runner.EmptyNCoverGeneratesExpectedSummary" Tests.AltCoverRunnerTests.EmptyNCoverGeneratesExpectedTCSummary, diff --git a/AltCover.Tests/Runner.Tests.fs b/AltCover.Tests/Runner.Tests.fs index 224cc66f..d6008418 100644 --- a/AltCover.Tests/Runner.Tests.fs +++ b/AltCover.Tests/Runner.Tests.fs @@ -4166,6 +4166,49 @@ module AltCoverRunnerTests = | (0L, []) -> () // | _ -> Assert.Fail(sprintf "%A" result) + [] + let UnknownGeneratesExpectedSummary () = + let resetInfo () = Output.info <- ignore + resetInfo () + Output.info "info" + Runner.init () + let report = XDocument() + let builder = System.Text.StringBuilder() + Runner.summary.Clear() |> ignore + + try + lock Runner.summaryFormat (fun () -> + Runner.summaryFormat <- Default + + Runner.threshold <- + Some + { Statements = 25uy + Branches = 0uy + Methods = 0uy + Crap = 0uy + AltMethods = 0uy + AltCrap = 0uy } + + let task = Collect() + Output.info <- (fun s -> builder.Append(s).Append("|") |> ignore) + + let r = + Runner.I.standardSummary DocumentType.Unknown ReportFormat.NCover 0 + + Assert.That(r, Is.EqualTo(0, 0, String.Empty)) + + Assert.That(builder.ToString(), Is.EqualTo String.Empty) + + let collected = + task.Summary + .Replace("\r", String.Empty) + .Replace("\n", "|") + + Assert.That(collected, Is.EqualTo String.Empty)) + finally + resetInfo () + + [] let EmptyNCoverGeneratesExpectedSummary () = let resetInfo () = Output.info <- ignore diff --git a/AltCover.Tests/Tests2.fs b/AltCover.Tests/Tests2.fs index fe97da6e..61ec91f2 100644 --- a/AltCover.Tests/Tests2.fs +++ b/AltCover.Tests/Tests2.fs @@ -851,28 +851,15 @@ module AltCoverTests2 = writer.SymbolWriterProvider <- Mono.Cecil.Cil.EmbeddedPortablePdbWriterProvider() writer.WriteSymbols <- true - let save = Output.verbose - let b = System.Text.StringBuilder() - - Output.verbose <- b.AppendLine >> ignore - let def = ``module``.MainModule.GetTypes() |> Seq.collect (fun t -> t.Methods) |> Seq.find (fun m -> m.Name.Equals("MakeConst")) - prepareLocalScopes def - Output.verbose <- save - - test - <@ - b.ToString() = "Null Constant thing elided in method System.Void NullConst.Program::MakeConst()" - + Environment.NewLine - @> - use sink = File.Open(outputdll, FileMode.Create, FileAccess.ReadWrite) + // should not throw ``module``.Write(sink, writer) [] @@ -907,11 +894,12 @@ module AltCoverTests2 = "Scope.Start.IsEndOfMethod" ) - Assert.True( + Assert.That( pathGetterDef.DebugInformation.Scope.Scopes |> Seq.exists (fun subscope -> subscope.Start.IsEndOfMethod), + Is.False, "subscope.Start.IsEndOfMethod" - ) // this one needs the home-built Sample31 + ) // big test -- if we can write w/o crashing when the previous asserts are removed let output = Path.GetTempFileName() @@ -925,10 +913,7 @@ module AltCoverTests2 = use sink = File.Open(outputdll, FileMode.Create, FileAccess.ReadWrite) - Assert.Throws(fun () -> ``module``.Write(sink, writer)) - |> ignore - - pruneLocalScopes pathGetterDef + // should not throw ``module``.Write(sink, writer) Assert.That( @@ -937,11 +922,6 @@ module AltCoverTests2 = "pruned Scope.Start.IsEndOfMethod" ) - Assert.True( - pathGetterDef.DebugInformation.Scope.Scopes - |> Seq.isEmpty, - "pruned subscope.Start.IsEndOfMethod" - ) (* was IL_0000: ldarg.0 IL_0001: ldfld bool Sample31.Class3/Class4::'k__BackingField' @@ -994,42 +974,16 @@ has been prefixed with Ldc_I4_1 (1 byte) rescope.Scopes.Add rescope - let save = Output.verbose - let b = System.Text.StringBuilder() + Assert.True(InstructionOffset().IsEndOfMethod, "End should go to none") - Output.verbose <- b.AppendLine >> ignore - - prepareLocalScopes pathGetterDef - - Assert.True( - InstructionOffset() |> safeOffset |> Option.isNone, - "End should go to none" - ) - - // prune 1 recursion and 2 at end - Assert.That(rescope.Scopes |> Seq.length, Is.EqualTo 4) + // prune 1 recursion and 2 at end => 3 + Assert.That(rescope.Scopes |> Seq.length, Is.EqualTo(4 + 3)) test <@ start.Offset = 0 @> test <@ start.Next.Offset = 1 @> test <@ start.Next.Next.Offset = 2 @> test <@ start.Next.Next.Next.Offset = 7 @> - let expected = - [ Some start.Offset - Some start.Next.Next.Offset - Some finish.Offset - Some finish.Offset ] - - let result = - rescope.Scopes - |> Seq.map (fun s -> safeOffset s.Start) - |> Seq.toList - - test <@ result = expected @> - test <@ b.ToString() = String.Empty @> - - Output.verbose <- save - [] let ShouldWriteMonoAssemblyOK () = try diff --git a/AltCover.Toolkit/OpenCover.fs b/AltCover.Toolkit/OpenCover.fs index 5485559a..a117174e 100644 --- a/AltCover.Toolkit/OpenCover.fs +++ b/AltCover.Toolkit/OpenCover.fs @@ -165,6 +165,15 @@ module OpenCover = XAttribute(XName.Get "maxCrapScore", 0) ) + [] + [] + [] let internal fixFormatMethod (m: XElement) (file: AssemblyDefinition) = // visited attribute let a = m.Attributes() |> Seq.toList @@ -1252,6 +1261,6 @@ coverlet on Tests.AltCoverRunnerTests/PostprocessShouldRestoreDegenerateOpenCove "PreferStringComparisonOverrideRule", Scope = "member", Target = - "AltCover.OpenCover/Pipe #4 stage #1 at line 746@747::Invoke(System.Tuple`2,System.Xml.Linq.XElement)", + "AltCover.OpenCover/Pipe #4 stage #1 at line 755@756::Invoke(System.Tuple`2,System.Xml.Linq.XElement)", Justification = "Compiler Generated")>] () \ No newline at end of file diff --git a/AltCover.UICommon/CoverageFile.fs b/AltCover.UICommon/CoverageFile.fs index ccb52897..778d7e27 100644 --- a/AltCover.UICommon/CoverageFile.fs +++ b/AltCover.UICommon/CoverageFile.fs @@ -344,7 +344,7 @@ module Extensions = "PreferStringComparisonOverrideRule", Scope = "member", Target = - "AltCover.Transformer/transformFromCobertura@94-2::Invoke(System.Xml.Linq.XElement)", + "AltCover.Transformer/transformFromCobertura@94-1::Invoke(System.Xml.Linq.XElement)", Justification = "Override not in netstandard2.0")>] [] +[] () \ No newline at end of file diff --git a/AltCover.sln b/AltCover.sln index 008c7e3e..ff877763 100644 --- a/AltCover.sln +++ b/AltCover.sln @@ -70,6 +70,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Items", "Build Items" Build\SelfTest.snk = Build\SelfTest.snk Build\setup.fs = Build\setup.fs Build\targets.fs = Build\targets.fs + version.json = version.json EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documents", "Documents", "{EE49FA56-4B6F-4C55-8D24-7E834274D7FE}" diff --git a/Build/targets.fs b/Build/targets.fs index 96994a60..0bf2b21a 100644 --- a/Build/targets.fs +++ b/Build/targets.fs @@ -1232,6 +1232,8 @@ module Targets = let standardRules = [ "-Microsoft.Design#CA1020" // small namespaces + "-Microsoft.Naming#CA1702" // compound naming pedantry + "-Microsoft.Naming#CA1704" // spelling pedantry "-Microsoft.Usage#CA2243" ] // :AttributeStringLiteralsShouldParseCorrectly" let minimalRules = @@ -2328,6 +2330,7 @@ module Targets = StrongNameKey = TypeSafe.FilePath signingKey SingleVisit = TypeSafe.Set InPlace = TypeSafe.Clear + //CallContext = TypeSafe.Context [ TypeSafe.TimeItem 3uy ] Save = TypeSafe.Clear } |> filter ) @@ -4058,10 +4061,10 @@ module Targets = |> Seq.toList let auxVFiles = - [ (!! "./_Binaries/AltCover.Visualizer/Release+AnyCPU/netcoreapp2.1/*.xml") ] + [ (!! "./AltCover.Visualizer/DotnetToolSettings.xml") ] |> Seq.concat - |> Seq.map (fun x -> - (x, Some("tools/netcoreapp2.1/any/" + Path.GetFileName x), None)) + |> Seq.map (fun x -> // Avalonia + (x, Some("tools/net5.0/any/" + Path.GetFileName x), None)) |> Seq.toList let auxFiles = @@ -4134,7 +4137,7 @@ module Targets = "altcover.global") (List.concat - [ vizFiles "tools/netcoreapp2.1/any" + [ vizFiles "tools/net5.0/any" // Avalonia [ (Path.getFullName "Build/README.visualizer.md", Some "", None) (Path.getFullName "./_Binaries/README.visualizer.html", Some "", None) ] auxVFiles @@ -5813,7 +5816,8 @@ module Targets = "MSBuildTest", "true" "AltCoverTag", "MSBuildTest_" "AltCoverPath", unpack.Replace('\\', '/') - "DebugSymbols", "True" ] }) + "DebugSymbols", "True" + "Fake2738Workround", "True" ] }) "./Samples/Sample4/Sample4LongForm.fsproj") let Cake2Test = diff --git a/Directory.Packages.props b/Directory.Packages.props index 2200ba4a..591de72d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,9 +4,9 @@ - - - + + + @@ -17,18 +17,18 @@ - - + + - - - + + + - + @@ -40,37 +40,37 @@ - - + + - + - + - + - + - + - + - + - + diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 1363c3e5..9753d4f9 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -3,7 +3,18 @@ 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 21) +# (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 +* Supports net8.0 preview 4 +* Updated to Cecil 11.5, removing the need for workrounds for issues noted at 11.4 +* Other dependency updates. + +# 8.6.48 (Habu series release 21a) +* [BUGFIX] Correctly package the visualizer for net5.0, as well as building it against the later platform + +# 8.6.45 (Habu series release 21) * [BUGFIX] Issue #179 - Improve and strengthen the heuristic for locating dependent assemblies, prossibly slightly speeding the look-up in the process by eliminating potentially duplicated effort. # 8.6.40 (Habu series release 20) diff --git a/global.json b/global.json index 8a477346..df1081c3 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "7.0.202", + "version": "7.0.302", "rollForward": "latestMinor" } } \ No newline at end of file diff --git a/nupkg/build/netstandard2.0/AltCover.targets b/nupkg/build/netstandard2.0/AltCover.targets index 49793bdc..fb281e20 100644 --- a/nupkg/build/netstandard2.0/AltCover.targets +++ b/nupkg/build/netstandard2.0/AltCover.targets @@ -198,7 +198,6 @@ Foreground $(TargetDir) $(AltCoverInstrumentedDirectory)_$(ProjectName) - true - -