-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: multiple stack trace annotations
- Loading branch information
Showing
4 changed files
with
119 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
|
||
namespace GitHub.VsTest.Logger; | ||
|
||
internal record class StackTraceInfo | ||
{ | ||
public string Frame { get; set; } = ""; | ||
public string Type { get; set; } = ""; | ||
public string Method { get; set; } = ""; | ||
public string ParameterList { get; set; } = ""; | ||
public IEnumerable<KeyValuePair<string, string>> Parameters { get; set; } = new Dictionary<string, string>(StringComparer.Ordinal); | ||
public string File { get; set; } = ""; | ||
public string Line { get; set; } = ""; | ||
} | ||
|
||
internal partial class StackTraceParser | ||
{ | ||
private readonly string _workspacePath; | ||
|
||
/// <summary>ctor</summary> | ||
/// <param name="workspacePath">Full path to the current dir / workspace folder</param> | ||
public StackTraceParser(string workspacePath) => _workspacePath = workspacePath; | ||
|
||
public static IEnumerable<StackTraceInfo> Parse(string stackTrace) | ||
=> Parse(stackTrace, (f, t, m, pl, ps, fn, ln) => new StackTraceInfo { | ||
Frame = f, | ||
Type = t, | ||
Method = m, | ||
ParameterList = pl, | ||
Parameters = ps, | ||
File = fn, | ||
Line = ln, | ||
}); | ||
|
||
private static readonly StringComparison _pathStringComparison = | ||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) | ||
? StringComparison.OrdinalIgnoreCase | ||
: StringComparison.Ordinal; | ||
|
||
|
||
/// <summary> Returns first parsed stack traces with relative file path </summary> | ||
public IEnumerable<StackTraceInfo> ParseAndNormalize(string stackTrace) | ||
{ | ||
var directorySeparators = new char[]{'/', '\\'}; | ||
foreach (var st in Parse(stackTrace)) | ||
{ | ||
// won't work on old msbuilds (requires netstandard2.1, but we are already there, so) | ||
if (!string.IsNullOrWhiteSpace(st.File)) | ||
{ | ||
// file in stacktraces must use full paths, so we can check it before make them relative | ||
// to exclude files out from our workspace | ||
if (st.File.StartsWith(_workspacePath, _pathStringComparison)) | ||
st.File = Path.GetRelativePath(_workspacePath, st.File).Trim(directorySeparators); | ||
// normalize paths to use '/' as directory separators | ||
st.File = st.File.Replace('\\', '/'); | ||
} | ||
yield return st; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
|
||
namespace GitHub.VsTest.Logger.UnitTests; | ||
public class StackTraceParserTests | ||
{ | ||
[Fact] | ||
public void ParseAndNormalize_Should_Return_RelativePath() | ||
{ | ||
const string stackTrace = @"System.Collections.Generic.KeyNotFoundException : Unable to find price for ServiceId=1, Quantity=1 | ||
at SomeCompany.SomeNamespace.Tests.AccountTests.BillForService_Works_ForPlatformServices() in /__NOT_FROM_WORKSPACE__/src/tests/Domain.Tests/AccountTests.cs:line 87 | ||
at SomeCompany.SomeNamespace.Plan.GetPriceTier(Service service, Int64 quantity) in /src/src/Domain/Plan.cs:line 31 | ||
at SomeCompany.SomeNamespace.BillingPeriod.BillForPlatformService(PriceList priceList, ServiceRecord serviceRecord)+MoveNext() in /src/src/Domain/BillingPeriod.cs:line 71 | ||
at SomeCompany.SomeNamespace.Tests.AccountTests.BillForService_Works_ForPlatformServices() in /__NOT_FROM_WORKSPACE__/src/tests/Domain.Tests/AccountTests.cs:line 87 | ||
at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items) | ||
at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source) | ||
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source) | ||
at SomeCompany.SomeNamespace.Account.BillForService(PriceList priceList, BillingPeriod period, ServiceRecord serviceRecord) in /src/src/Domain/Account.cs:line 79 | ||
at SomeCompany.SomeNamespace.Tests.AccountTests.BillForService_Works_ForPlatformServices() in /src/tests/Domain.Tests/AccountTests.cs:line 87 | ||
"; | ||
var parser = new StackTraceParser(workspacePath: "/src"); | ||
var result = parser.ParseAndNormalize(stackTrace); | ||
|
||
var outFromWorkspace = result.FirstOrDefault(); | ||
var projectFile = result.FirstOrDefault(x => x.File.StartsWith("src/", StringComparison.Ordinal)); | ||
|
||
Assert.Equal("/__NOT_FROM_WORKSPACE__/src/tests/Domain.Tests/AccountTests.cs", outFromWorkspace?.File); | ||
Assert.Equal("src/Domain/Plan.cs", projectFile?.File); | ||
} | ||
} |