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