Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use .NET 8.0 assemblies for coverlet.core and remove Newtonsoft.Json #1733

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
vstest 17.8 version
NuGetFrameworksVersion is defined here https://github.com/microsoft/vstest/blob/9a0c41811637edf4afe0e265e08fdd1cb18109ed/eng/Versions.props#L94C1-L94C1
-->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="NuGet.Frameworks" Version="$(NugetPackageVersion)" />
<PackageVersion Include="NuGet.Packaging" Version="$(NugetPackageVersion)" />
<PackageVersion Include="NuGet.Versioning" Version="$(NugetPackageVersion)" />
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ Coverlet supports only SDK-style projects https://docs.microsoft.com/en-us/visua
```bash
dotnet add package coverlet.collector
```

N.B. You **MUST** add package only to test projects and if you create xunit test projects (`dotnet new xunit`) you'll find the reference already present in `csproj` file because Coverlet is the default coverage tool for every .NET Core and >= .NET 6 applications, you've only to update to last version if needed. Do not add `coverlet.collector` and `coverlet.msbuild` package in a test project.
> [!NOTE]
> You **MUST** add package only to test projects and if you create xunit test projects (`dotnet new xunit`) you will find the reference already present in `csproj` file because Coverlet is the default coverage tool for every .NET Core and >= *.NET 8* applications, you've only to update to last version if needed. Add `coverlet.collector` *OR* `coverlet.msbuild` package in a test project.

### Usage (coverlet.collector)

Expand All @@ -61,11 +61,11 @@ See [documentation](Documentation/VSTestIntegration.md) for advanced usage.

#### Requirements (coverlet.collector)

* _You need to be running .NET 6.0 SDK v6.0.316 or newer_
* _You need to reference version 17.5.0 and above of Microsoft.NET.Test.Sdk_
* _You need to be running .NET 8.0 SDK v8.0.112 or newer_
* _You need to reference version 17.12.0 and above of Microsoft.NET.Test.Sdk_

```xml
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
```

### MSBuild Integration (suffers of possible [known issue](https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/KnownIssues.md#1-vstest-stops-process-execution-earlydotnet-test))
Expand Down Expand Up @@ -120,7 +120,7 @@ See [documentation](Documentation/GlobalTool.md) for advanced usage.

.NET global tools rely on a .NET Core runtime installed on your machine https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools#what-could-go-wrong

.NET Coverlet global tool requires _.NET Core 2.2 and above_
.NET Coverlet global tool requires _.NET 8.0 or above_

## How It Works

Expand Down
25 changes: 17 additions & 8 deletions src/coverlet.core/Coverage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text.Json;
using System.Text.Json.Nodes;
using Coverlet.Core.Abstractions;
using Coverlet.Core.Helpers;
using Coverlet.Core.Instrumentation;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Coverlet.Core
{
Expand Down Expand Up @@ -60,6 +60,14 @@ internal class Coverage

public string Identifier { get; }

readonly JsonSerializerOptions _options = new()
{
PropertyNameCaseInsensitive = true,
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
IncludeFields = true,
WriteIndented = true
};

public Coverage(string moduleOrDirectory,
CoverageParameters parameters,
ILogger logger,
Expand Down Expand Up @@ -313,7 +321,7 @@ public CoverageResult GetCoverageResult()
{
_logger.LogInformation($"MergeWith: '{_parameters.MergeWith}'.");
string json = _fileSystem.ReadAllText(_parameters.MergeWith);
coverageResult.Merge(JsonConvert.DeserializeObject<Modules>(json));
coverageResult.Merge(JsonSerializer.Deserialize<Modules>(json, _options));
}
else
{
Expand Down Expand Up @@ -366,8 +374,8 @@ private void CalculateCoverage()
var documents = result.Documents.Values.ToList();
if (_parameters.UseSourceLink && result.SourceLink != null)
{
JToken jObject = JObject.Parse(result.SourceLink)["documents"];
Dictionary<string, string> sourceLinkDocuments = JsonConvert.DeserializeObject<Dictionary<string, string>>(jObject.ToString());
JsonNode jObject = JsonNode.Parse(result.SourceLink)["documents"];
Dictionary<string, string> sourceLinkDocuments = JsonSerializer.Deserialize<Dictionary<string, string>>(jObject.ToString());
foreach (Document document in documents)
{
document.Path = GetSourceLinkUrl(sourceLinkDocuments, document.Path);
Expand Down Expand Up @@ -480,9 +488,9 @@ internal string GetSourceLinkUrl(Dictionary<string, string> sourceLinkDocuments,
{
string key = sourceLinkDocument.Key;
if (Path.GetFileName(key) != "*") continue;

#pragma warning disable IDE0057
IReadOnlyList<SourceRootMapping> rootMapping = _sourceRootTranslator.ResolvePathRoot(key.Substring(0, key.Length - 1));

#pragma warning restore IDE0057
foreach (string keyMapping in rootMapping is null ? [key] : new List<string>(rootMapping.Select(m => m.OriginalPath)))
{
string directoryDocument = Path.GetDirectoryName(document);
Expand All @@ -494,8 +502,9 @@ internal string GetSourceLinkUrl(Dictionary<string, string> sourceLinkDocuments,
{
if (!directoryDocument.StartsWith(sourceLinkRoot + Path.DirectorySeparatorChar))
continue;

#pragma warning disable IDE0057
relativePath = directoryDocument.Substring(sourceLinkRoot.Length + 1);
#pragma warning restore IDE0057
}

if (relativePathOfBestMatch.Length == 0)
Expand Down
2 changes: 2 additions & 0 deletions src/coverlet.core/CoverageResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Coverlet.Core.Enums;
using Coverlet.Core.Instrumentation;

Expand All @@ -22,6 +23,7 @@ internal class Branches : List<BranchInfo> { }

internal class Method
{
[JsonConstructor]
internal Method()
{
Lines = [];
Expand Down
8 changes: 0 additions & 8 deletions src/coverlet.core/Exceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,17 @@

namespace Coverlet.Core.Exceptions
{
[Serializable]
public class CoverletException : Exception
{
public CoverletException() { }
public CoverletException(string message) : base(message) { }
public CoverletException(string message, System.Exception inner) : base(message, inner) { }
protected CoverletException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}

[Serializable]
internal class CecilAssemblyResolutionException : CoverletException
{
public CecilAssemblyResolutionException() { }
public CecilAssemblyResolutionException(string message) : base(message) { }
public CecilAssemblyResolutionException(string message, System.Exception inner) : base(message, inner) { }
protected CecilAssemblyResolutionException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}
6 changes: 5 additions & 1 deletion src/coverlet.core/Helpers/InstrumentationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -415,17 +415,21 @@ private static string GetIncludeModuleKeysForValidFilters(char escapeSymbol, str
}

private static string CreateRegexExcludePattern(IEnumerable<string> filters, char escapeSymbol)
//only look for module filters here, types will be filtered out when instrumenting
//only look for module filters here, types will be filtered out when instrumenting
#pragma warning disable IDE0057 // Use range operator
=> CreateRegexPattern(filters, escapeSymbol, filter => filter.Substring(filter.IndexOf(']') + 1) == "*");
#pragma warning restore IDE0057 // Use range operator

private static string CreateRegexIncludePattern(IEnumerable<string> filters, char escapeSymbol) =>
CreateRegexPattern(filters, escapeSymbol);

private static string CreateRegexPattern(IEnumerable<string> filters, char escapeSymbol, Func<string, bool> filterPredicate = null)
{
IEnumerable<string> filteredFilters = filterPredicate != null ? filters.Where(filterPredicate) : filters;
#pragma warning disable IDE0057 // Use range operator
IEnumerable<string> regexPatterns = filteredFilters.Select(x =>
$"{escapeSymbol}{WildcardToRegex(x.Substring(1, x.IndexOf(']') - 1)).Trim('^', '$')}{escapeSymbol}");
#pragma warning restore IDE0057 // Use range operator
return string.Join("|", regexPatterns);
}

Expand Down
27 changes: 15 additions & 12 deletions src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using Coverlet.Core.Abstractions;
using Coverlet.Core.Exceptions;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.DependencyModel.Resolution;
using Mono.Cecil;
using Newtonsoft.Json.Linq;
using NuGet.Versioning;

namespace Coverlet.Core.Instrumentation
Expand Down Expand Up @@ -296,29 +296,32 @@ public RuntimeConfigurationReader(string runtimeConfigFile)
{
string jsonString = File.ReadAllText(_runtimeConfigFile);

var jsonLoadSettings = new JsonLoadSettings()
var documentOptions = new JsonDocumentOptions
{
CommentHandling = CommentHandling.Ignore
CommentHandling = JsonCommentHandling.Skip
};

var configuration = JObject.Parse(jsonString, jsonLoadSettings);
using var configuration = JsonDocument.Parse(jsonString, documentOptions);

JToken rootElement = configuration.Root;
JToken runtimeOptionsElement = rootElement["runtimeOptions"];
JsonElement rootElement = configuration.RootElement;
JsonElement runtimeOptionsElement = rootElement.GetProperty("runtimeOptions");

if (runtimeOptionsElement?["framework"] != null)
if (runtimeOptionsElement.TryGetProperty("framework", out JsonElement frameworkElement))
{
return [(runtimeOptionsElement["framework"]["name"]?.Value<string>(), runtimeOptionsElement["framework"]["version"]?.Value<string>())];
return new List<(string, string)>
{
(runtimeOptionsElement.GetProperty("framework").GetProperty("name").GetString(), runtimeOptionsElement.GetProperty("framework").GetProperty("version").GetString())
};
}

if (runtimeOptionsElement?["frameworks"] != null)
if (runtimeOptionsElement.TryGetProperty("frameworks", out JsonElement frameworksElement))
{
return runtimeOptionsElement["frameworks"].Select(x => (x["name"]?.Value<string>(), x["version"]?.Value<string>())).ToList();
return frameworksElement.EnumerateArray().Select(x => (x.GetProperty("name").GetString(), x.GetProperty("version").GetString())).ToList();
}

if (runtimeOptionsElement?["includedFrameworks"] != null)
if (runtimeOptionsElement.TryGetProperty("includedFrameworks", out JsonElement runtimeoptionselement))
{
return runtimeOptionsElement["includedFrameworks"].Select(x => (x["name"]?.Value<string>(), x["version"]?.Value<string>())).ToList();
return runtimeoptionselement.EnumerateArray().Select(x => (x.GetProperty("name").GetString(), x.GetProperty("version").GetString())).ToList();
}

throw new InvalidOperationException($"Unable to read runtime configuration from {_runtimeConfigFile}.");
Expand Down
11 changes: 9 additions & 2 deletions src/coverlet.core/Reporters/JsonReporter.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright (c) Toni Solarin-Sodara
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Text.Encodings.Web;
using System.Text.Json;
using Coverlet.Core.Abstractions;
using Newtonsoft.Json;

namespace Coverlet.Core.Reporters
{
Expand All @@ -16,7 +17,13 @@ internal class JsonReporter : IReporter

public string Report(CoverageResult result, ISourceRootTranslator _)
{
return JsonConvert.SerializeObject(result.Modules, Formatting.Indented);
var options = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
IncludeFields = true,
WriteIndented = true,
};
return JsonSerializer.Serialize(result.Modules, options);
}
}
}
27 changes: 16 additions & 11 deletions src/coverlet.core/coverlet.core.csproj
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn);IDE0057</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="6.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyModel" VersionOverride="6.0.2" />
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" VersionOverride="6.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" VersionOverride="6.0.2" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
<PackageReference Include="Microsoft.Extensions.DependencyModel" />
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Mono.Cecil" />
<PackageReference Include="NuGet.Versioning" />
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="System.Text.Json" VersionOverride="6.0.11" />
<PackageReference Include="System.Text.Json" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' != 'netstandard2.0'">
<PackageReference Include="System.Reflection.Metadata" />
<PackageReference Include="System.Collections.Immutable" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="System.Reflection.Metadata" VersionOverride="$(SystemReflectionMetadataVersion)" />
<PackageReference Include="System.Collections.Immutable" VersionOverride="$(SystemCollectionsImmutableVersion)" />
<PackageReference Include="System.Buffers" />
<PackageReference Include="System.Memory" />
<PackageReference Include="System.Threading.Tasks.Extensions" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion src/coverlet.msbuild.tasks/coverlet.msbuild.targets
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<PropertyGroup>
<_CoverletSdkNETCoreSdkVersion>$(NETCoreSdkVersion)</_CoverletSdkNETCoreSdkVersion>
<_CoverletSdkNETCoreSdkVersion Condition="$(_CoverletSdkNETCoreSdkVersion.Contains('-'))">$(_CoverletSdkNETCoreSdkVersion.Split('-')[0])</_CoverletSdkNETCoreSdkVersion>
<_CoverletSdkMinVersionWithDependencyTarget>6.0.100</_CoverletSdkMinVersionWithDependencyTarget>
<_CoverletSdkMinVersionWithDependencyTarget>8.0.100</_CoverletSdkMinVersionWithDependencyTarget>
<_CoverletSourceRootTargetName>CoverletGetPathMap</_CoverletSourceRootTargetName>
<_CoverletSourceRootTargetName Condition="'$([System.Version]::Parse($(_CoverletSdkNETCoreSdkVersion)).CompareTo($([System.Version]::Parse($(_CoverletSdkMinVersionWithDependencyTarget)))))' &gt;= '0' ">InitializeSourceRootMappedPaths</_CoverletSourceRootTargetName>
</PropertyGroup>
Expand Down
Loading