Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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: 1 addition & 0 deletions Documentation/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

-Fix F# projects with `unkown` source [#1145](https://github.com/coverlet-coverage/coverlet/issues/1145)
-Fix partially covered throw statement [#1144](https://github.com/coverlet-coverage/coverlet/pull/1144)
-Fix coverage threshold not failing when no coverage [#1115](https://github.com/coverlet-coverage/coverlet/pull/1115)
-Fix partially covered `await foreach` statement [#1107](https://github.com/coverlet-coverage/coverlet/pull/1107) by https://github.com/alexthornton1
Expand Down
7 changes: 7 additions & 0 deletions coverlet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{9A8B19D4
test\Directory.Build.targets = test\Directory.Build.targets
EndProjectSection
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "coverlet.tests.projectsample.fsharp", "test\coverlet.tests.projectsample.fsharp\coverlet.tests.projectsample.fsharp.fsproj", "{1CBF6966-2A67-4D2C-8598-D174B83072F4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -115,6 +117,10 @@ Global
{F8199E19-FA9A-4559-9101-CAD7028121B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8199E19-FA9A-4559-9101-CAD7028121B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8199E19-FA9A-4559-9101-CAD7028121B4}.Release|Any CPU.Build.0 = Release|Any CPU
{1CBF6966-2A67-4D2C-8598-D174B83072F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1CBF6966-2A67-4D2C-8598-D174B83072F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1CBF6966-2A67-4D2C-8598-D174B83072F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1CBF6966-2A67-4D2C-8598-D174B83072F4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -135,6 +141,7 @@ Global
{5FF404AD-7C0B-465A-A1E9-558CDC642B0C} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134}
{F8199E19-FA9A-4559-9101-CAD7028121B4} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134}
{9A8B19D4-4A24-4217-AEFE-159B68F029A1} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134}
{1CBF6966-2A67-4D2C-8598-D174B83072F4} = {2FEBDE1B-83E3-445B-B9F8-5644B0E0E134}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9CA57C02-97B0-4C38-A027-EA61E8741F10}
Expand Down
20 changes: 15 additions & 5 deletions src/coverlet.core/Helpers/InstrumentationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,13 @@ public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNot
{
Document document = metadataReader.GetDocument(docHandle);
string docName = _sourceRootTranslator.ResolveFilePath(metadataReader.GetString(document.Name));

Guid languageGuid = metadataReader.GetGuid(document.Language);
// We verify all docs and return false if not all are present in local
// We could have false negative if doc is not a source
// Btw check for all possible extension could be weak approach
// We exlude from the check the autogenerated source file(i.e. source generators)
if (!_fileSystem.Exists(docName) && !docName.EndsWith(".g.cs"))
// We exclude from the check the autogenerated source file(i.e. source generators)
// We exclude special F# construct https://github.com/coverlet-coverage/coverlet/issues/1145
if (!_fileSystem.Exists(docName) && !docName.EndsWith(".g.cs") && !IsUnknownModuleInFSharpAssembly(languageGuid, docName))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic could be extracted into a method, since it is identical with the logic in PortablePdbHasLocalSource. This helps if we need to add even more exceptions, e.g. for the null documents in VB (#1073).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, done.

{
firstNotFoundDocument = docName;
return false;
Expand Down Expand Up @@ -165,16 +166,18 @@ public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDoc
_logger.LogWarning($"{nameof(BadImageFormatException)} during MetadataReaderProvider.FromPortablePdbStream in InstrumentationHelper.PortablePdbHasLocalSource, unable to check if module has got local source.");
return true;
}

foreach (DocumentHandle docHandle in metadataReader.Documents)
{
Document document = metadataReader.GetDocument(docHandle);
string docName = _sourceRootTranslator.ResolveFilePath(metadataReader.GetString(document.Name));

Guid languageGuid = metadataReader.GetGuid(document.Language);
// We verify all docs and return false if not all are present in local
// We could have false negative if doc is not a source
// Btw check for all possible extension could be weak approach
// We exlude from the check the autogenerated source file(i.e. source generators)
if (!_fileSystem.Exists(docName) && !docName.EndsWith(".g.cs"))
// We exclude special F# construct https://github.com/coverlet-coverage/coverlet/issues/1145
if (!_fileSystem.Exists(docName) && !docName.EndsWith(".g.cs") && !IsUnknownModuleInFSharpAssembly(languageGuid, docName))
{
firstNotFoundDocument = docName;
return false;
Expand Down Expand Up @@ -443,5 +446,12 @@ private bool IsAssembly(string filePath)
return false;
}
}

private bool IsUnknownModuleInFSharpAssembly(Guid languageGuid, string docName)
{
// https://github.com/dotnet/runtime/blob/main/docs/design/specs/PortablePdb-Metadata.md#document-table-0x30
return languageGuid.Equals(new Guid("ab4f38c9-b6e6-43ba-be3b-58080b2ccce3"))
&& docName.EndsWith("unknown");
}
}
}
18 changes: 18 additions & 0 deletions test/coverlet.core.tests/Instrumentation/InstrumenterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,24 @@ public void TestInstrument_MissingModule()
loggerMock.Verify(l => l.LogWarning(It.IsAny<string>()));
}

[Fact]
public void CanInstrumentFSharpAssemblyWithAnonymousRecord()
{
var loggerMock = new Mock<ILogger>();

string sample = Directory.GetFiles(Directory.GetCurrentDirectory(), "coverlet.tests.projectsample.fsharp.dll").First();
InstrumentationHelper instrumentationHelper =
new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), new FileSystem(), new Mock<ILogger>().Object,
new SourceRootTranslator(sample, new Mock<ILogger>().Object, new FileSystem()));

var instrumenter = new Instrumenter(sample, "_coverlet_tests_projectsample_fsharp", new CoverageParameters(), loggerMock.Object, instrumentationHelper,
new FileSystem(), new SourceRootTranslator(sample, loggerMock.Object, new FileSystem()), new CecilSymbolHelper());

Assert.True(instrumentationHelper.HasPdb(sample, out bool embedded));
Assert.False(embedded);
Assert.True(instrumenter.CanInstrument());
}

[Theory]
[InlineData("NotAMatch", new string[] { }, false)]
[InlineData("ExcludeFromCoverageAttribute", new string[] { }, true)]
Expand Down
1 change: 1 addition & 0 deletions test/coverlet.core.tests/coverlet.core.tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<ProjectReference Include="$(RepoRoot)src\coverlet.msbuild.tasks\coverlet.msbuild.tasks.csproj" />
<ProjectReference Include="$(RepoRoot)test\coverlet.tests.projectsample.empty\coverlet.tests.projectsample.empty.csproj" />
<ProjectReference Include="$(RepoRoot)test\coverlet.tests.projectsample.excludedbyattribute\coverlet.tests.projectsample.excludedbyattribute.csproj" />
<ProjectReference Include="$(RepoRoot)test\coverlet.tests.projectsample.fsharp\coverlet.tests.projectsample.fsharp.fsproj" />
<ProjectReference Include="$(RepoRoot)test\coverlet.core.tests.samples.netstandard\coverlet.core.tests.samples.netstandard.csproj" />
<ProjectReference Include="$(RepoRoot)test\coverlet.tests.xunit.extensions\coverlet.tests.xunit.extensions.csproj" />
</ItemGroup>
Expand Down
4 changes: 4 additions & 0 deletions test/coverlet.tests.projectsample.fsharp/Library.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace coverlet.tests.projectsample.fsharp

module TestModule =
type Type1 = Option1 | Option2 of {| x: string |}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<Compile Include="Library.fs" />
</ItemGroup>

</Project>