Skip to content

Commit

Permalink
Add external access to stacktrace APIs for Unit Testing (#58082)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryzngard committed Jan 27, 2022
1 parent 1037b82 commit c805b93
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;

namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api
{
internal interface IUnitTestingStackTraceServiceAccessor : IWorkspaceService
{
Task<ImmutableArray<UnitTestingParsedFrameWrapper>> TryParseAsync(string input, Workspace workspace, CancellationToken cancellationToken);
Task<UnitTestingDefinitionItemWrapper?> TryFindMethodDefinitionAsync(Workspace workspace, UnitTestingParsedFrameWrapper parsedFrame, CancellationToken cancellationToken);
(Document? document, int lineNumber) GetDocumentAndLine(Workspace workspace, UnitTestingParsedFrameWrapper parsedFrame);
Task<bool> TryNavigateToAsync(Workspace workspace, UnitTestingDefinitionItemWrapper definitionItem, bool showInPreviewTab, bool activateTab, CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api
{
internal readonly struct UnitTestingDefinitionItemWrapper
{
internal FindUsages.DefinitionItem UnderlyingObject { get; }

public UnitTestingDefinitionItemWrapper(FindUsages.DefinitionItem definition)
{
UnderlyingObject = definition;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.StackTraceExplorer;

namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api
{
internal readonly struct UnitTestingParsedFrameWrapper
{
internal ParsedFrame UnderlyingObject { get; }

public UnitTestingParsedFrameWrapper(ParsedFrame parsedFrame)
{
UnderlyingObject = parsedFrame;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.StackTraceExplorer;

namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting
{
internal class UnitTestingStackTraceServiceAccessor : IUnitTestingStackTraceServiceAccessor
{
private readonly IStackTraceExplorerService _stackTraceExplorerService;

[Obsolete(MefConstruction.FactoryMethodMessage, error: true)]
public UnitTestingStackTraceServiceAccessor(
IStackTraceExplorerService stackTraceExplorerService)
{
_stackTraceExplorerService = stackTraceExplorerService;
}

public (Document? document, int lineNumber) GetDocumentAndLine(Workspace workspace, UnitTestingParsedFrameWrapper parsedFrame)
=> _stackTraceExplorerService.GetDocumentAndLine(workspace.CurrentSolution, parsedFrame.UnderlyingObject);

public async Task<UnitTestingDefinitionItemWrapper?> TryFindMethodDefinitionAsync(Workspace workspace, UnitTestingParsedFrameWrapper parsedFrame, CancellationToken cancellationToken)
{
var definition = await _stackTraceExplorerService.TryFindDefinitionAsync(workspace.CurrentSolution, parsedFrame.UnderlyingObject, StackFrameSymbolPart.Method, cancellationToken).ConfigureAwait(false);
return definition is null
? null
: new UnitTestingDefinitionItemWrapper(definition);
}

public async Task<ImmutableArray<UnitTestingParsedFrameWrapper>> TryParseAsync(string input, Workspace workspace, CancellationToken cancellationToken)
{
var result = await StackTraceAnalyzer.AnalyzeAsync(input, cancellationToken).ConfigureAwait(false);
return result.ParsedFrames.SelectAsArray(p => new UnitTestingParsedFrameWrapper(p));
}

public Task<bool> TryNavigateToAsync(Workspace workspace, UnitTestingDefinitionItemWrapper definitionItem, bool showInPreviewTab, bool activateTab, CancellationToken cancellationToken)
=> definitionItem.UnderlyingObject.TryNavigateToAsync(workspace, showInPreviewTab, activateTab, cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Composition;
using Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.StackTraceExplorer;

namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting
{
[ExportWorkspaceServiceFactory(typeof(IUnitTestingStackTraceServiceAccessor))]
[Shared]

internal class UnitTestingStackTraceServiceAccessorFactory : IWorkspaceServiceFactory
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public UnitTestingStackTraceServiceAccessorFactory()
{
}

[Obsolete(MefConstruction.FactoryMethodMessage, error: true)]
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{
var stackTraceExplorerService = workspaceServices.GetRequiredService<IStackTraceExplorerService>();
return new UnitTestingStackTraceServiceAccessor(stackTraceExplorerService);
}
}
}

0 comments on commit c805b93

Please sign in to comment.