diff --git a/src/coverlet.collector/DataCollection/CoverageWrapper.cs b/src/coverlet.collector/DataCollection/CoverageWrapper.cs
index 9018ee387..0f8dc4287 100644
--- a/src/coverlet.collector/DataCollection/CoverageWrapper.cs
+++ b/src/coverlet.collector/DataCollection/CoverageWrapper.cs
@@ -33,7 +33,8 @@ public Coverage CreateCoverage(CoverletSettings settings, ILogger coverletLogger
UseSourceLink = settings.UseSourceLink,
SkipAutoProps = settings.SkipAutoProps,
DoesNotReturnAttributes = settings.DoesNotReturnAttributes,
- DeterministicReport = settings.DeterministicReport
+ DeterministicReport = settings.DeterministicReport,
+ InstrumentModulesWithoutLocalSources = settings.InstrumentModulesWithoutLocalSources
};
return new Coverage(
diff --git a/src/coverlet.collector/DataCollection/CoverletSettings.cs b/src/coverlet.collector/DataCollection/CoverletSettings.cs
index bf04e6326..7a23e0a5e 100644
--- a/src/coverlet.collector/DataCollection/CoverletSettings.cs
+++ b/src/coverlet.collector/DataCollection/CoverletSettings.cs
@@ -81,6 +81,11 @@ internal class CoverletSettings
///
public bool DeterministicReport { get; set; }
+ ///
+ /// Instruments modules even if the sources from the PDBs can't be resolved.
+ ///
+ public bool InstrumentModulesWithoutLocalSources { get; set; }
+
public override string ToString()
{
var builder = new StringBuilder();
@@ -98,6 +103,7 @@ public override string ToString()
builder.AppendFormat("SkipAutoProps: '{0}'", SkipAutoProps);
builder.AppendFormat("DoesNotReturnAttributes: '{0}'", string.Join(",", DoesNotReturnAttributes ?? Enumerable.Empty()));
builder.AppendFormat("DeterministicReport: '{0}'", DeterministicReport);
+ builder.AppendFormat("InstrumentModulesWithoutLocalSources: '{0}'", InstrumentModulesWithoutLocalSources);
return builder.ToString();
}
diff --git a/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs b/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs
index 4440b24d8..b1a77b1dc 100644
--- a/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs
+++ b/src/coverlet.collector/DataCollection/CoverletSettingsParser.cs
@@ -48,6 +48,7 @@ public CoverletSettings Parse(XmlElement configurationElement, IEnumerable
+ /// Parse InstrumentModulesWithoutLocalSources flag
+ ///
+ /// Configuration element
+ /// InstrumentModulesWithoutLocalSources flag
+ private static bool ParseInstrumentModulesWithoutLocalSources(XmlElement configurationElement)
+ {
+ XmlElement instrumentModulesWithoutLocalSourcesElement = configurationElement[CoverletConstants.InstrumentModulesWithoutLocalSources];
+ bool.TryParse(instrumentModulesWithoutLocalSourcesElement?.InnerText, out bool instrumentModulesWithoutLocalSources);
+ return instrumentModulesWithoutLocalSources;
+ }
+
///
/// Parse include test assembly flag
///
diff --git a/src/coverlet.collector/Utilities/CoverletConstants.cs b/src/coverlet.collector/Utilities/CoverletConstants.cs
index 5aff53cfb..a8bd770e7 100644
--- a/src/coverlet.collector/Utilities/CoverletConstants.cs
+++ b/src/coverlet.collector/Utilities/CoverletConstants.cs
@@ -26,5 +26,6 @@ internal static class CoverletConstants
public const string SkipAutoProps = "SkipAutoProps";
public const string DoesNotReturnAttributesElementName = "DoesNotReturnAttribute";
public const string DeterministicReport = "DeterministicReport";
+ public const string InstrumentModulesWithoutLocalSources = "InstrumentModulesWithoutLocalSources";
}
}
diff --git a/src/coverlet.console/Program.cs b/src/coverlet.console/Program.cs
index 25f5f7350..a80f6ff31 100644
--- a/src/coverlet.console/Program.cs
+++ b/src/coverlet.console/Program.cs
@@ -70,6 +70,7 @@ static int Main(string[] args)
CommandOption mergeWith = app.Option("--merge-with", "Path to existing coverage result to merge.", CommandOptionType.SingleValue);
CommandOption useSourceLink = app.Option("--use-source-link", "Specifies whether to use SourceLink URIs in place of file system paths.", CommandOptionType.NoValue);
CommandOption doesNotReturnAttributes = app.Option("--does-not-return-attribute", "Attributes that mark methods that do not return.", CommandOptionType.MultipleValue);
+ CommandOption instrumentModulesWithoutLocalSources = app.Option("--instrument-modules-without-local-sources", "Specifies whether modules should be instrumented even if the sources from the PDBs can't be found locally.", CommandOptionType.NoValue);
app.OnExecute(() =>
{
@@ -97,7 +98,8 @@ static int Main(string[] args)
MergeWith = mergeWith.Value(),
UseSourceLink = useSourceLink.HasValue(),
SkipAutoProps = skipAutoProp.HasValue(),
- DoesNotReturnAttributes = doesNotReturnAttributes.Values.ToArray()
+ DoesNotReturnAttributes = doesNotReturnAttributes.Values.ToArray(),
+ InstrumentModulesWithoutLocalSources = instrumentModulesWithoutLocalSources.HasValue(),
};
ISourceRootTranslator sourceRootTranslator = serviceProvider.GetRequiredService();
diff --git a/src/coverlet.core/Coverage.cs b/src/coverlet.core/Coverage.cs
index 25a415b5b..d0357997e 100644
--- a/src/coverlet.core/Coverage.cs
+++ b/src/coverlet.core/Coverage.cs
@@ -43,6 +43,8 @@ internal class CoverageParameters
public bool SkipAutoProps { get; set; }
[DataMember]
public bool DeterministicReport { get; set; }
+ [DataMember]
+ public bool InstrumentModulesWithoutLocalSources { get; set; }
}
internal class Coverage
diff --git a/src/coverlet.core/Instrumentation/Instrumenter.cs b/src/coverlet.core/Instrumentation/Instrumenter.cs
index 42a1a1835..36d195c50 100644
--- a/src/coverlet.core/Instrumentation/Instrumenter.cs
+++ b/src/coverlet.core/Instrumentation/Instrumenter.cs
@@ -94,6 +94,11 @@ public bool CanInstrument()
{
if (_instrumentationHelper.HasPdb(_module, out bool embeddedPdb))
{
+ if (this._parameters.InstrumentModulesWithoutLocalSources)
+ {
+ return true;
+ }
+
if (embeddedPdb)
{
if (_instrumentationHelper.EmbeddedPortablePdbHasLocalSource(_module, out string firstNotFoundDocument))
diff --git a/src/coverlet.core/Reporters/CoberturaReporter.cs b/src/coverlet.core/Reporters/CoberturaReporter.cs
index 57571df9a..e3d299fda 100644
--- a/src/coverlet.core/Reporters/CoberturaReporter.cs
+++ b/src/coverlet.core/Reporters/CoberturaReporter.cs
@@ -227,9 +227,6 @@ private static string GetRelativePathFromBase(IEnumerable basePaths, str
return path.Substring(basePath.Length);
}
}
-
- Debug.Assert(false, "Unexpected, we should find at least one path starts with one pre-build roots list");
-
return path;
}
}
diff --git a/src/coverlet.msbuild.tasks/InstrumentationTask.cs b/src/coverlet.msbuild.tasks/InstrumentationTask.cs
index 2ec4910da..b43f152d4 100644
--- a/src/coverlet.msbuild.tasks/InstrumentationTask.cs
+++ b/src/coverlet.msbuild.tasks/InstrumentationTask.cs
@@ -47,6 +47,8 @@ public class InstrumentationTask : BaseTask
public bool DeterministicReport { get; set; }
+ public bool InstrumentModulesWithoutLocalSources { get; set; }
+
[Output]
public ITaskItem InstrumenterState { get; set; }
@@ -99,6 +101,7 @@ public override bool Execute()
UseSourceLink = UseSourceLink,
SkipAutoProps = SkipAutoProps,
DeterministicReport = DeterministicReport,
+ InstrumentModulesWithoutLocalSources = InstrumentModulesWithoutLocalSources,
DoesNotReturnAttributes = DoesNotReturnAttribute?.Split(',')
};