未验证 提交 33bcfd44 编写于 作者: S Sam Harwell 提交者: GitHub

Merge pull request #28957 from sharwell/fix-mef-usage

Fix MEF usage in Navigate To test code
......@@ -12,7 +12,6 @@
using Roslyn.Test.Utilities;
using Xunit;
#pragma warning disable CS0618 // MatchKind is obsolete
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.NavigateTo
{
public class InteractiveNavigateToTests : AbstractNavigateToTests
......@@ -20,7 +19,7 @@ public class InteractiveNavigateToTests : AbstractNavigateToTests
protected override string Language => "csharp";
protected override TestWorkspace CreateWorkspace(string content, ExportProvider exportProvider)
=> TestWorkspace.CreateCSharp(content, parseOptions: Options.Script);
=> TestWorkspace.CreateCSharp(content, parseOptions: Options.Script, exportProvider: exportProvider);
[WpfFact, Trait(Traits.Feature, Traits.Features.NavigateTo)]
public async Task NoItemsForEmptyFile()
......@@ -641,4 +640,3 @@ public async Task TermSplittingTest8()
}
}
}
#pragma warning restore CS0618 // MatchKind is obsolete
......@@ -1021,8 +1021,7 @@ public partial class C
</Workspace>
", exportProvider: TestExportProvider.ExportProviderWithCSharpAndVisualBasic))
{
_provider = new NavigateToItemProvider(
workspace, AsynchronousOperationListenerProvider.NullListener, documentTrackingService: null);
_provider = new NavigateToItemProvider(workspace, AsynchronousOperationListenerProvider.NullListener);
_aggregator = new NavigateToTestAggregator(_provider);
var items = await _aggregator.GetItemsAsync("VisibleMethod");
......
......@@ -24,7 +24,6 @@ private class Searcher
{
private readonly Solution _solution;
private readonly IAsynchronousOperationListener _asyncListener;
private readonly IDocumentTrackingService _documentTrackingService;
private readonly INavigateToItemDisplayFactory _displayFactory;
private readonly INavigateToCallback _callback;
private readonly string _searchPattern;
......@@ -37,7 +36,6 @@ private class Searcher
public Searcher(
Solution solution,
IAsynchronousOperationListener asyncListener,
IDocumentTrackingService documentTrackingService,
INavigateToItemDisplayFactory displayFactory,
INavigateToCallback callback,
string searchPattern,
......@@ -47,7 +45,6 @@ private class Searcher
{
_solution = solution;
_asyncListener = asyncListener;
_documentTrackingService = documentTrackingService;
_displayFactory = displayFactory;
_callback = callback;
_searchPattern = searchPattern;
......@@ -78,7 +75,7 @@ internal async Task SearchAsync()
// If the workspace is tracking documents, use that to prioritize our search
// order. That way we provide results for the documents the user is working
// on faster than the rest of the solution.
var docTrackingService = _documentTrackingService ?? workspace.Services.GetService<IDocumentTrackingService>();
var docTrackingService = workspace.Services.GetService<IDocumentTrackingService>();
if (docTrackingService != null)
{
await SearchProjectsInPriorityOrder(docTrackingService).ConfigureAwait(false);
......
......@@ -18,22 +18,19 @@ internal partial class NavigateToItemProvider : INavigateToItemProvider2
{
private readonly Workspace _workspace;
private readonly IAsynchronousOperationListener _asyncListener;
private readonly IDocumentTrackingService _documentTrackingService;
private readonly INavigateToItemDisplayFactory _displayFactory;
private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
public NavigateToItemProvider(
Workspace workspace,
IAsynchronousOperationListener asyncListener,
IDocumentTrackingService documentTrackingService)
IAsynchronousOperationListener asyncListener)
{
Contract.ThrowIfNull(workspace);
Contract.ThrowIfNull(asyncListener);
_workspace = workspace;
_asyncListener = asyncListener;
_documentTrackingService = documentTrackingService;
_displayFactory = new NavigateToItemDisplayFactory();
}
......@@ -123,7 +120,6 @@ private void StartSearch(INavigateToCallback callback, string searchValue, IImmu
var searcher = new Searcher(
_workspace.CurrentSolution,
_asyncListener,
_documentTrackingService,
_displayFactory,
callback,
searchValue,
......
......@@ -36,8 +36,7 @@ public bool TryCreateNavigateToItemProvider(IServiceProvider serviceProvider, ou
return false;
}
provider = new NavigateToItemProvider(
workspace, _asyncListener, documentTrackingService: null);
provider = new NavigateToItemProvider(workspace, _asyncListener);
return true;
}
}
......
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Media;
......@@ -12,7 +13,8 @@
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Editor.Wpf;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities.RemoteHost;
......@@ -30,6 +32,13 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.NavigateTo
[UseExportProvider]
public abstract class AbstractNavigateToTests
{
private static readonly Lazy<IExportProviderFactory> s_exportProviderFactory =
new Lazy<IExportProviderFactory>(() =>
{
var catalog = TestExportProvider.EntireAssemblyCatalogWithCSharpAndVisualBasic.WithPart(typeof(DocumentTrackingServiceFactory));
return ExportProviderCache.GetOrCreateExportProviderFactory(catalog);
});
protected INavigateToItemProvider _provider;
protected NavigateToTestAggregator _aggregator;
......@@ -58,23 +67,47 @@ public abstract class AbstractNavigateToTests
protected async Task TestAsync(string content, Func<TestWorkspace, Task> body)
{
await TestAsync(content, body, outOfProcess: true);
await TestAsync(content, body, outOfProcess: false);
// Keep track of tested combinations to ensure all expected tests run
var testedCombinations = new HashSet<(bool outOfProcess, Type documentTrackingServiceType)>();
await TestAsync(content, BodyWrapper, outOfProcess: true);
await TestAsync(content, BodyWrapper, outOfProcess: false);
Assert.Contains((true, null), testedCombinations);
Assert.Contains((true, typeof(FirstDocIsVisibleDocumentTrackingService)), testedCombinations);
Assert.Contains((true, typeof(FirstDocIsActiveAndVisibleDocumentTrackingService)), testedCombinations);
Assert.Contains((false, null), testedCombinations);
Assert.Contains((false, typeof(FirstDocIsVisibleDocumentTrackingService)), testedCombinations);
Assert.Contains((false, typeof(FirstDocIsActiveAndVisibleDocumentTrackingService)), testedCombinations);
return;
// Local function
Task BodyWrapper(TestWorkspace workspace)
{
// Track the current test setup
var outOfProcess = workspace.Options.GetOption(RemoteHostOptions.RemoteHostTest);
var documentTrackingServiceType = workspace.Services.GetService<IDocumentTrackingService>()?.GetType();
testedCombinations.Add((outOfProcess, documentTrackingServiceType));
// Run the test itself
return body(workspace);
}
}
internal async Task TestAsync(string content, Func<TestWorkspace, Task> body, bool outOfProcess)
private async Task TestAsync(string content, Func<TestWorkspace, Task> body, bool outOfProcess)
{
await TestAsync(content, body, outOfProcess, null);
await TestAsync(content, body, outOfProcess, w => new FirstDocIsVisibleDocumentTrackingService(w));
await TestAsync(content, body, outOfProcess, w => new FirstDocIsActiveAndVisibleDocumentTrackingService(w));
await TestAsync(content, body, outOfProcess, w => new FirstDocIsVisibleDocumentTrackingService(w.Workspace));
await TestAsync(content, body, outOfProcess, w => new FirstDocIsActiveAndVisibleDocumentTrackingService(w.Workspace));
}
internal async Task TestAsync(
private async Task TestAsync(
string content, Func<TestWorkspace, Task> body, bool outOfProcess,
Func<TestWorkspace, IDocumentTrackingService> createTrackingService)
Func<HostWorkspaceServices, IDocumentTrackingService> createTrackingService)
{
using (var workspace = SetupWorkspace(
content, TestExportProvider.ExportProviderWithCSharpAndVisualBasic, createTrackingService))
using (var workspace = SetupWorkspace(content, createTrackingService))
{
workspace.Options = workspace.Options.WithChangedOption(RemoteHostOptions.RemoteHostTest, outOfProcess);
await body(workspace);
......@@ -82,33 +115,37 @@ internal async Task TestAsync(string content, Func<TestWorkspace, Task> body, bo
}
private protected TestWorkspace SetupWorkspace(
XElement workspaceElement, ExportProvider exportProvider,
Func<TestWorkspace, IDocumentTrackingService> createTrackingService)
XElement workspaceElement,
Func<HostWorkspaceServices, IDocumentTrackingService> createTrackingService)
{
var exportProvider = s_exportProviderFactory.Value.CreateExportProvider();
var documentTrackingServiceFactory = exportProvider.GetExportedValue<DocumentTrackingServiceFactory>();
documentTrackingServiceFactory.FactoryMethod = createTrackingService;
var workspace = TestWorkspace.Create(workspaceElement, exportProvider: exportProvider);
var trackingService = createTrackingService?.Invoke(workspace);
InitializeWorkspace(workspace, trackingService);
InitializeWorkspace(workspace);
return workspace;
}
private protected TestWorkspace SetupWorkspace(
string content, ExportProvider exportProvider,
Func<TestWorkspace, IDocumentTrackingService> createTrackingService)
string content,
Func<HostWorkspaceServices, IDocumentTrackingService> createTrackingService)
{
var exportProvider = s_exportProviderFactory.Value.CreateExportProvider();
var documentTrackingServiceFactory = exportProvider.GetExportedValue<DocumentTrackingServiceFactory>();
documentTrackingServiceFactory.FactoryMethod = createTrackingService;
var workspace = CreateWorkspace(content, exportProvider);
var trackingService = createTrackingService?.Invoke(workspace);
InitializeWorkspace(workspace, trackingService);
InitializeWorkspace(workspace);
return workspace;
}
internal void InitializeWorkspace(
TestWorkspace workspace, IDocumentTrackingService documentTrackingService)
internal void InitializeWorkspace(TestWorkspace workspace)
{
_provider = new NavigateToItemProvider(workspace, AsynchronousOperationListenerProvider.NullListener, documentTrackingService);
_provider = new NavigateToItemProvider(workspace, AsynchronousOperationListenerProvider.NullListener);
_aggregator = new NavigateToTestAggregator(_provider);
}
#pragma warning disable CS0618 // MatchKind is obsolete
protected void VerifyNavigateToResultItems(
List<NavigateToItem> expecteditems, IEnumerable<NavigateToItem> items)
{
......@@ -193,47 +230,69 @@ protected static int CompareNavigateToItems(NavigateToItem a, NavigateToItem b)
result = a.SecondarySort.CompareTo(b.SecondarySort);
return result;
}
#pragma warning restore CS0618 // MatchKind is obsolete
}
#pragma warning disable CS0067
private class FirstDocIsVisibleDocumentTrackingService : IDocumentTrackingService
{
private readonly Workspace _workspace;
public class FirstDocIsVisibleDocumentTrackingService : IDocumentTrackingService
{
private readonly Workspace _workspace;
public FirstDocIsVisibleDocumentTrackingService(Workspace workspace)
{
_workspace = workspace;
}
public FirstDocIsVisibleDocumentTrackingService(Workspace workspace)
{
_workspace = workspace;
public event EventHandler<DocumentId> ActiveDocumentChanged { add { } remove { } }
public event EventHandler<EventArgs> NonRoslynBufferTextChanged { add { } remove { } }
public DocumentId TryGetActiveDocument()
=> null;
public ImmutableArray<DocumentId> GetVisibleDocuments()
=> ImmutableArray.Create(_workspace.CurrentSolution.Projects.First().DocumentIds.First());
}
public event EventHandler<DocumentId> ActiveDocumentChanged;
public event EventHandler<EventArgs> NonRoslynBufferTextChanged;
private class FirstDocIsActiveAndVisibleDocumentTrackingService : IDocumentTrackingService
{
private readonly Workspace _workspace;
public DocumentId TryGetActiveDocument()
=> null;
public FirstDocIsActiveAndVisibleDocumentTrackingService(Workspace workspace)
{
_workspace = workspace;
}
public ImmutableArray<DocumentId> GetVisibleDocuments()
=> ImmutableArray.Create(_workspace.CurrentSolution.Projects.First().DocumentIds.First());
}
public event EventHandler<DocumentId> ActiveDocumentChanged { add { } remove { } }
public event EventHandler<EventArgs> NonRoslynBufferTextChanged { add { } remove { } }
public class FirstDocIsActiveAndVisibleDocumentTrackingService : IDocumentTrackingService
{
private readonly Workspace _workspace;
public DocumentId TryGetActiveDocument()
=> _workspace.CurrentSolution.Projects.First().DocumentIds.First();
public FirstDocIsActiveAndVisibleDocumentTrackingService(Workspace workspace)
{
_workspace = workspace;
public ImmutableArray<DocumentId> GetVisibleDocuments()
=> ImmutableArray.Create(_workspace.CurrentSolution.Projects.First().DocumentIds.First());
}
public event EventHandler<DocumentId> ActiveDocumentChanged;
public event EventHandler<EventArgs> NonRoslynBufferTextChanged;
[Export]
[ExportWorkspaceServiceFactory(typeof(IDocumentTrackingService), ServiceLayer.Host)]
[Shared]
[PartNotDiscoverable]
public sealed class DocumentTrackingServiceFactory : IWorkspaceServiceFactory
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public DocumentTrackingServiceFactory()
{
FactoryMethod = null;
}
public DocumentId TryGetActiveDocument()
=> _workspace.CurrentSolution.Projects.First().DocumentIds.First();
internal Func<HostWorkspaceServices, IDocumentTrackingService> FactoryMethod
{
get;
set;
}
public ImmutableArray<DocumentId> GetVisibleDocuments()
=> ImmutableArray.Create(_workspace.CurrentSolution.Projects.First().DocumentIds.First());
[Obsolete(MefConstruction.FactoryMethodMessage, error: true)]
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{
return FactoryMethod?.Invoke(workspaceServices);
}
}
}
#pragma warning restore
}
......@@ -739,7 +739,7 @@ Public Class Goo
End Class
</Document>
</Project>
</Workspace>, exportProvider:=Nothing, createTrackingService:=Nothing)
</Workspace>, createTrackingService:=Nothing)
Dim item As NavigateToItem = (Await _aggregator.GetItemsAsync("G")).Single()
Dim itemDisplay As INavigateToItemDisplay = item.DisplayFactory.CreateItemDisplay(item)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册