diff --git a/src/EditorFeatures/Test/MinimalTestExportProvider.cs b/src/EditorFeatures/Test/MinimalTestExportProvider.cs index 249b788a80f80060de79f1613a0661d179127213..9816ff3b3cbae6583d33a28d937e1af67b324f63 100644 --- a/src/EditorFeatures/Test/MinimalTestExportProvider.cs +++ b/src/EditorFeatures/Test/MinimalTestExportProvider.cs @@ -4,11 +4,9 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Shared.Options; using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities; -using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Shared.Options; using Microsoft.CodeAnalysis.SolutionCrawler; using Microsoft.VisualStudio.Composition; @@ -19,7 +17,7 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests { public static class MinimalTestExportProvider { - private static readonly PartDiscovery s_partDiscovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(Resolver.DefaultInstance), new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true)); + private static readonly PartDiscovery s_partDiscovery = CreatePartDiscovery(Resolver.DefaultInstance); private static readonly Lazy s_lazyLanguageNeutralCatalog = new Lazy(() => CreateAssemblyCatalog(GetVisualStudioAssemblies()).WithParts(CreateAssemblyCatalog(GetLanguageNeutralTypes().Select(t => t.Assembly).Distinct()))); public static ComposableCatalog LanguageNeutralCatalog @@ -103,22 +101,44 @@ public static ComposableCatalog CreateAssemblyCatalog(Assembly assembly) return CreateAssemblyCatalog(SpecializedCollections.SingletonEnumerable(assembly)); } - public static ComposableCatalog CreateAssemblyCatalog(IEnumerable assemblies) + public static ComposableCatalog CreateAssemblyCatalog(IEnumerable assemblies, Resolver resolver = null) { + var discovery = resolver == null ? s_partDiscovery : CreatePartDiscovery(resolver); + // If we run CreatePartsAsync on the test thread we may deadlock since it'll schedule stuff back // on the thread. - var parts = Task.Run(async () => await s_partDiscovery.CreatePartsAsync(assemblies).ConfigureAwait(false)).Result; + var parts = Task.Run(async () => await discovery.CreatePartsAsync(assemblies).ConfigureAwait(false)).Result; - return ComposableCatalog.Create(Resolver.DefaultInstance).AddParts(parts); + return ComposableCatalog.Create(resolver ?? Resolver.DefaultInstance).AddParts(parts); } - public static ComposableCatalog CreateTypeCatalog(IEnumerable types) + public static ComposableCatalog CreateTypeCatalog(IEnumerable types, Resolver resolver = null) { + var discovery = resolver == null ? s_partDiscovery : CreatePartDiscovery(resolver); + // If we run CreatePartsAsync on the test thread we may deadlock since it'll schedule stuff back // on the thread. - var parts = Task.Run(async () => await s_partDiscovery.CreatePartsAsync(types).ConfigureAwait(false)).Result; + var parts = Task.Run(async () => await discovery.CreatePartsAsync(types).ConfigureAwait(false)).Result; + + return ComposableCatalog.Create(resolver ?? Resolver.DefaultInstance).AddParts(parts); + } + + public static Resolver CreateResolver() + { + // simple assembly loader is stateless, so okay to share + return new Resolver(SimpleAssemblyLoader.Instance); + } - return ComposableCatalog.Create(Resolver.DefaultInstance).AddParts(parts); + public static PartDiscovery CreatePartDiscovery(Resolver resolver) + { + return PartDiscovery.Combine(new AttributedPartDiscoveryV1(resolver), new AttributedPartDiscovery(resolver, isNonPublicSupported: true)); + } + + public static ExportProvider CreateExportProvider(ComposableCatalog catalog) + { + var configuration = CompositionConfiguration.Create(catalog.WithDesktopSupport().WithCompositionService()); + var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration); + return runtimeComposition.CreateExportProviderFactory().CreateExportProvider(); } public static ComposableCatalog WithParts(this ComposableCatalog @this, ComposableCatalog catalog) @@ -141,11 +161,25 @@ public static ComposableCatalog WithPart(this ComposableCatalog catalog, Type t) return catalog.WithParts(CreateTypeCatalog(SpecializedCollections.SingletonEnumerable(t))); } - public static ExportProvider CreateExportProvider(ComposableCatalog catalog) + private class SimpleAssemblyLoader : IAssemblyLoader { - var configuration = CompositionConfiguration.Create(catalog.WithDesktopSupport().WithCompositionService()); - var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration); - return runtimeComposition.CreateExportProviderFactory().CreateExportProvider(); + public static readonly IAssemblyLoader Instance = new SimpleAssemblyLoader(); + + public Assembly LoadAssembly(AssemblyName assemblyName) + { + return Assembly.Load(assemblyName); + } + + public Assembly LoadAssembly(string assemblyFullName, string codeBasePath) + { + var assemblyName = new AssemblyName(assemblyFullName); + if (!string.IsNullOrEmpty(codeBasePath)) + { + assemblyName.CodeBase = codeBasePath; + } + + return this.LoadAssembly(assemblyName); + } } } } diff --git a/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs b/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs index c6c87432d0e4da964a441df63b65547ec8d99640..9edfc31ac5645e0886045e3824af357eb6ad7642 100644 --- a/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs +++ b/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs @@ -25,7 +25,7 @@ public class WorkCoordinatorTests [WpfFact] public void RegisterService() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var registrationService = new SolutionCrawlerRegistrationService( SpecializedCollections.EmptyEnumerable>(), @@ -40,7 +40,7 @@ public void RegisterService() [WpfFact, WorkItem(747226)] public async Task SolutionAdded_Simple() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solutionId = SolutionId.CreateNewId(); var projectId = ProjectId.CreateNewId(); @@ -63,7 +63,7 @@ public async Task SolutionAdded_Simple() [WpfFact] public async Task SolutionAdded_Complex() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); @@ -75,7 +75,7 @@ public async Task SolutionAdded_Complex() [WpfFact] public async Task Solution_Remove() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -89,7 +89,7 @@ public async Task Solution_Remove() [WpfFact] public async Task Solution_Clear() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -103,7 +103,7 @@ public async Task Solution_Clear() [WpfFact] public async Task Solution_Reload() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -117,7 +117,7 @@ public async Task Solution_Reload() [WpfFact] public async Task Solution_Change() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solutionInfo = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solutionInfo); @@ -137,7 +137,7 @@ public async Task Solution_Change() [WpfFact] public async Task Project_Add() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -160,7 +160,7 @@ public async Task Project_Add() [WpfFact] public async Task Project_Remove() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -177,7 +177,7 @@ public async Task Project_Remove() [WpfFact] public async Task Project_Change() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solutionInfo = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solutionInfo); @@ -196,7 +196,7 @@ public async Task Project_Change() [WpfFact] public async Task Project_AssemblyName_Change() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solutionInfo = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solutionInfo); @@ -213,7 +213,7 @@ public async Task Project_AssemblyName_Change() [WpfFact] public async Task Project_AnalyzerOptions_Change() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solutionInfo = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solutionInfo); @@ -230,7 +230,7 @@ public async Task Project_AnalyzerOptions_Change() [WpfFact] public async Task Project_Reload() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -245,7 +245,7 @@ public async Task Project_Reload() [WpfFact] public async Task Document_Add() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -263,7 +263,7 @@ public async Task Document_Add() [WpfFact] public async Task Document_Remove() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -282,7 +282,7 @@ public async Task Document_Remove() [WpfFact] public async Task Document_Reload() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -298,7 +298,7 @@ public async Task Document_Reload() [WpfFact] public async Task Document_Reanalyze() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -331,7 +331,7 @@ public async Task Document_Reanalyze() [WorkItem(670335)] public async Task Document_Change() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -348,7 +348,7 @@ public async Task Document_Change() [WpfFact] public async Task Document_AdditionalFileChange() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -376,7 +376,7 @@ public async Task Document_AdditionalFileChange() [WorkItem(670335)] public async Task Document_Cancellation() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -406,7 +406,7 @@ public async Task Document_Cancellation() [WorkItem(670335)] public async Task Document_Cancellation_MultipleTimes() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -440,7 +440,7 @@ public async Task Document_Cancellation_MultipleTimes() [WorkItem(670335)] public async Task Document_InvocationReasons() { - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { var solution = GetInitialSolutionInfo(workspace); workspace.OnSolutionAdded(solution); @@ -700,7 +700,7 @@ public async Task SemanticChange_Propagation() { var solution = GetInitialSolutionInfoWithP2P(); - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { workspace.OnSolutionAdded(solution); await WaitWaiterAsync(workspace.ExportProvider).ConfigureAwait(true); @@ -727,7 +727,7 @@ public async Task ProgressReporterTest() { var solution = GetInitialSolutionInfoWithP2P(); - using (var workspace = new WorkCoordinatorWorkspace(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), SolutionCrawler)) + using (var workspace = new WorkCoordinatorWorkspace(SolutionCrawler)) { await WaitWaiterAsync(workspace.ExportProvider).ConfigureAwait(true); @@ -941,8 +941,8 @@ private class WorkCoordinatorWorkspace : TestWorkspace private readonly IAsynchronousOperationWaiter _workspaceWaiter; private readonly IAsynchronousOperationWaiter _solutionCrawlerWaiter; - public WorkCoordinatorWorkspace(ExportProvider exportProvider, string workspaceKind = null, bool disablePartialSolutions = true) - : base(exportProvider, workspaceKind, disablePartialSolutions) + public WorkCoordinatorWorkspace(string workspaceKind = null, bool disablePartialSolutions = true) + : base(TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic(), workspaceKind, disablePartialSolutions) { _workspaceWaiter = GetListeners(ExportProvider).First(l => l.Metadata.FeatureName == FeatureAttribute.Workspace).Value as IAsynchronousOperationWaiter; _solutionCrawlerWaiter = GetListeners(ExportProvider).First(l => l.Metadata.FeatureName == FeatureAttribute.SolutionCrawler).Value as IAsynchronousOperationWaiter; @@ -955,9 +955,8 @@ protected override void Dispose(bool finalize) { base.Dispose(finalize); - // Bug https://github.com/dotnet/roslyn/issues/5915 - // Assert.False(_workspaceWaiter.HasPendingWork); - // Assert.False(_solutionCrawlerWaiter.HasPendingWork); + Assert.False(_workspaceWaiter.HasPendingWork); + Assert.False(_solutionCrawlerWaiter.HasPendingWork); } } diff --git a/src/EditorFeatures/Test/TestExportProvider.cs b/src/EditorFeatures/Test/TestExportProvider.cs index 375244f4402e96067545ae373dbf8ff4b00fef6c..364011ea08d57c399d070dee2c8c5f9702b8e0da 100644 --- a/src/EditorFeatures/Test/TestExportProvider.cs +++ b/src/EditorFeatures/Test/TestExportProvider.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Formatting; @@ -30,7 +29,7 @@ public static ComposableCatalog EntireAssemblyCatalogWithCSharpAndVisualBasic { if (t_lazyEntireAssemblyCatalogWithCSharpAndVisualBasic == null) { - t_lazyEntireAssemblyCatalogWithCSharpAndVisualBasic = new Lazy(() => MinimalTestExportProvider.CreateAssemblyCatalog(GetNeutralAndCSharpAndVisualBasicTypes().Select(t => t.Assembly).Distinct().Concat(MinimalTestExportProvider.GetVisualStudioAssemblies()))); + t_lazyEntireAssemblyCatalogWithCSharpAndVisualBasic = new Lazy(() => CreateAssemblyCatalogWithCSharpAndVisualBasic()); } return t_lazyEntireAssemblyCatalogWithCSharpAndVisualBasic.Value; @@ -125,9 +124,24 @@ private static Type[] GetNeutralAndCSharpAndVisualBasicTypes() .ToArray(); } + /// + /// Create fresh ExportProvider that doesnt share anything with others. + /// test can use this export provider to create all new MEF components not shared with others. + /// public static ExportProvider CreateExportProviderWithCSharpAndVisualBasic() { - return MinimalTestExportProvider.CreateExportProvider(EntireAssemblyCatalogWithCSharpAndVisualBasic); + return MinimalTestExportProvider.CreateExportProvider(CreateAssemblyCatalogWithCSharpAndVisualBasic()); + } + + /// + /// Create fresh ComposableCatalog that doesnt share anything with others. + /// everything under this catalog should have been created from scratch that doesnt share anything with others. + /// + public static ComposableCatalog CreateAssemblyCatalogWithCSharpAndVisualBasic() + { + return MinimalTestExportProvider.CreateAssemblyCatalog( + GetNeutralAndCSharpAndVisualBasicTypes().Select(t => t.Assembly).Distinct().Concat(MinimalTestExportProvider.GetVisualStudioAssemblies()), + MinimalTestExportProvider.CreateResolver()); } } }