Skip to content
3 changes: 2 additions & 1 deletion src/coverlet.collector/DataCollection/CoverageWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
6 changes: 6 additions & 0 deletions src/coverlet.collector/DataCollection/CoverletSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ internal class CoverletSettings
/// </summary>
public bool DeterministicReport { get; set; }

/// <summary>
/// Instruments modules even if the sources from the PDBs can't be resolved.
/// </summary>
public bool InstrumentModulesWithoutLocalSources { get; set; }

public override string ToString()
{
var builder = new StringBuilder();
Expand All @@ -98,6 +103,7 @@ public override string ToString()
builder.AppendFormat("SkipAutoProps: '{0}'", SkipAutoProps);
builder.AppendFormat("DoesNotReturnAttributes: '{0}'", string.Join(",", DoesNotReturnAttributes ?? Enumerable.Empty<string>()));
builder.AppendFormat("DeterministicReport: '{0}'", DeterministicReport);
builder.AppendFormat("InstrumentModulesWithoutLocalSources: '{0}'", InstrumentModulesWithoutLocalSources);

return builder.ToString();
}
Expand Down
13 changes: 13 additions & 0 deletions src/coverlet.collector/DataCollection/CoverletSettingsParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public CoverletSettings Parse(XmlElement configurationElement, IEnumerable<strin
coverletSettings.SkipAutoProps = ParseSkipAutoProps(configurationElement);
coverletSettings.DoesNotReturnAttributes = ParseDoesNotReturnAttributes(configurationElement);
coverletSettings.DeterministicReport = ParseDeterministicReport(configurationElement);
coverletSettings.InstrumentModulesWithoutLocalSources = ParseInstrumentModulesWithoutLocalSources(configurationElement);
}

coverletSettings.ReportFormats = ParseReportFormats(configurationElement);
Expand Down Expand Up @@ -211,6 +212,18 @@ private static bool ParseDeterministicReport(XmlElement configurationElement)
return deterministicReport;
}

/// <summary>
/// Parse InstrumentModulesWithoutLocalSources flag
/// </summary>
/// <param name="configurationElement">Configuration element</param>
/// <returns>InstrumentModulesWithoutLocalSources flag</returns>
private static bool ParseInstrumentModulesWithoutLocalSources(XmlElement configurationElement)
{
XmlElement instrumentModulesWithoutLocalSourcesElement = configurationElement[CoverletConstants.InstrumentModulesWithoutLocalSources];
bool.TryParse(instrumentModulesWithoutLocalSourcesElement?.InnerText, out bool instrumentModulesWithoutLocalSources);
return instrumentModulesWithoutLocalSources;
}

/// <summary>
/// Parse include test assembly flag
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/coverlet.collector/Utilities/CoverletConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
}
4 changes: 3 additions & 1 deletion src/coverlet.console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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(() =>
{
Expand Down Expand Up @@ -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<ISourceRootTranslator>();
Expand Down
2 changes: 2 additions & 0 deletions src/coverlet.core/Coverage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/coverlet.core/Instrumentation/Instrumenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
3 changes: 0 additions & 3 deletions src/coverlet.core/Reporters/CoberturaReporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,6 @@ private static string GetRelativePathFromBase(IEnumerable<string> 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;
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/coverlet.msbuild.tasks/InstrumentationTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class InstrumentationTask : BaseTask

public bool DeterministicReport { get; set; }

public bool InstrumentModulesWithoutLocalSources { get; set; }

[Output]
public ITaskItem InstrumenterState { get; set; }

Expand Down Expand Up @@ -99,6 +101,7 @@ public override bool Execute()
UseSourceLink = UseSourceLink,
SkipAutoProps = SkipAutoProps,
DeterministicReport = DeterministicReport,
InstrumentModulesWithoutLocalSources = InstrumentModulesWithoutLocalSources,
DoesNotReturnAttributes = DoesNotReturnAttribute?.Split(',')
};

Expand Down