Skip to content

Commit c805b93

Browse files
author
Andrew Hall
authored
Add external access to stacktrace APIs for Unit Testing (#58082)
1 parent 1037b82 commit c805b93

File tree

5 files changed

+131
-0
lines changed

5 files changed

+131
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Collections.Immutable;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Host;
9+
10+
namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api
11+
{
12+
internal interface IUnitTestingStackTraceServiceAccessor : IWorkspaceService
13+
{
14+
Task<ImmutableArray<UnitTestingParsedFrameWrapper>> TryParseAsync(string input, Workspace workspace, CancellationToken cancellationToken);
15+
Task<UnitTestingDefinitionItemWrapper?> TryFindMethodDefinitionAsync(Workspace workspace, UnitTestingParsedFrameWrapper parsedFrame, CancellationToken cancellationToken);
16+
(Document? document, int lineNumber) GetDocumentAndLine(Workspace workspace, UnitTestingParsedFrameWrapper parsedFrame);
17+
Task<bool> TryNavigateToAsync(Workspace workspace, UnitTestingDefinitionItemWrapper definitionItem, bool showInPreviewTab, bool activateTab, CancellationToken cancellationToken);
18+
}
19+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api
6+
{
7+
internal readonly struct UnitTestingDefinitionItemWrapper
8+
{
9+
internal FindUsages.DefinitionItem UnderlyingObject { get; }
10+
11+
public UnitTestingDefinitionItemWrapper(FindUsages.DefinitionItem definition)
12+
{
13+
UnderlyingObject = definition;
14+
}
15+
}
16+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Microsoft.CodeAnalysis.StackTraceExplorer;
6+
7+
namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api
8+
{
9+
internal readonly struct UnitTestingParsedFrameWrapper
10+
{
11+
internal ParsedFrame UnderlyingObject { get; }
12+
13+
public UnitTestingParsedFrameWrapper(ParsedFrame parsedFrame)
14+
{
15+
UnderlyingObject = parsedFrame;
16+
}
17+
}
18+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Immutable;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
using Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api;
10+
using Microsoft.CodeAnalysis.Host.Mef;
11+
using Microsoft.CodeAnalysis.StackTraceExplorer;
12+
13+
namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting
14+
{
15+
internal class UnitTestingStackTraceServiceAccessor : IUnitTestingStackTraceServiceAccessor
16+
{
17+
private readonly IStackTraceExplorerService _stackTraceExplorerService;
18+
19+
[Obsolete(MefConstruction.FactoryMethodMessage, error: true)]
20+
public UnitTestingStackTraceServiceAccessor(
21+
IStackTraceExplorerService stackTraceExplorerService)
22+
{
23+
_stackTraceExplorerService = stackTraceExplorerService;
24+
}
25+
26+
public (Document? document, int lineNumber) GetDocumentAndLine(Workspace workspace, UnitTestingParsedFrameWrapper parsedFrame)
27+
=> _stackTraceExplorerService.GetDocumentAndLine(workspace.CurrentSolution, parsedFrame.UnderlyingObject);
28+
29+
public async Task<UnitTestingDefinitionItemWrapper?> TryFindMethodDefinitionAsync(Workspace workspace, UnitTestingParsedFrameWrapper parsedFrame, CancellationToken cancellationToken)
30+
{
31+
var definition = await _stackTraceExplorerService.TryFindDefinitionAsync(workspace.CurrentSolution, parsedFrame.UnderlyingObject, StackFrameSymbolPart.Method, cancellationToken).ConfigureAwait(false);
32+
return definition is null
33+
? null
34+
: new UnitTestingDefinitionItemWrapper(definition);
35+
}
36+
37+
public async Task<ImmutableArray<UnitTestingParsedFrameWrapper>> TryParseAsync(string input, Workspace workspace, CancellationToken cancellationToken)
38+
{
39+
var result = await StackTraceAnalyzer.AnalyzeAsync(input, cancellationToken).ConfigureAwait(false);
40+
return result.ParsedFrames.SelectAsArray(p => new UnitTestingParsedFrameWrapper(p));
41+
}
42+
43+
public Task<bool> TryNavigateToAsync(Workspace workspace, UnitTestingDefinitionItemWrapper definitionItem, bool showInPreviewTab, bool activateTab, CancellationToken cancellationToken)
44+
=> definitionItem.UnderlyingObject.TryNavigateToAsync(workspace, showInPreviewTab, activateTab, cancellationToken);
45+
}
46+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Composition;
7+
using Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api;
8+
using Microsoft.CodeAnalysis.Host;
9+
using Microsoft.CodeAnalysis.Host.Mef;
10+
using Microsoft.CodeAnalysis.StackTraceExplorer;
11+
12+
namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting
13+
{
14+
[ExportWorkspaceServiceFactory(typeof(IUnitTestingStackTraceServiceAccessor))]
15+
[Shared]
16+
17+
internal class UnitTestingStackTraceServiceAccessorFactory : IWorkspaceServiceFactory
18+
{
19+
[ImportingConstructor]
20+
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
21+
public UnitTestingStackTraceServiceAccessorFactory()
22+
{
23+
}
24+
25+
[Obsolete(MefConstruction.FactoryMethodMessage, error: true)]
26+
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
27+
{
28+
var stackTraceExplorerService = workspaceServices.GetRequiredService<IStackTraceExplorerService>();
29+
return new UnitTestingStackTraceServiceAccessor(stackTraceExplorerService);
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)