Skip to content

Commit

Permalink
Merge pull request #1120 from sharwell/export-provider
Browse files Browse the repository at this point in the history
Create export provider asynchronously
  • Loading branch information
sharwell authored Sep 26, 2023
2 parents 6535e67 + c5d471a commit 5f6ffda
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/Microsoft.CodeAnalysis.Testing/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

<When Condition="'$(Language)' == 'C#'">
<PropertyGroup>
<LangVersion>9</LangVersion>
<LangVersion>10</LangVersion>
</PropertyGroup>
</When>
</Choose>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
Expand All @@ -32,25 +33,8 @@ namespace Microsoft.CodeAnalysis.Testing
public abstract class AnalyzerTest<TVerifier>
where TVerifier : IVerifier, new()
{
private static readonly Lazy<IExportProviderFactory> ExportProviderFactory;
private static readonly ConditionalWeakTable<Diagnostic, object> NonLocalDiagnostics = new ConditionalWeakTable<Diagnostic, object>();

static AnalyzerTest()
{
ExportProviderFactory = new Lazy<IExportProviderFactory>(
() =>
{
var discovery = new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true);
var parts = Task.Run(() => discovery.CreatePartsAsync(MefHostServices.DefaultAssemblies)).GetAwaiter().GetResult();
var catalog = ComposableCatalog.Create(Resolver.DefaultInstance).AddParts(parts).WithDocumentTextDifferencingService();
var configuration = CompositionConfiguration.Create(catalog);
var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration);
return runtimeComposition.CreateExportProviderFactory();
},
LazyThreadSafetyMode.ExecutionAndPublication);
}

/// <summary>
/// Gets the default verifier for the test.
/// </summary>
Expand Down Expand Up @@ -1587,7 +1571,7 @@ protected virtual async Task<Solution> CreateSolutionAsync(ProjectId projectId,
var parseOptions = CreateParseOptions()
.WithDocumentationMode(projectState.DocumentationMode);

var workspace = CreateWorkspace();
var workspace = await CreateWorkspaceAsync().ConfigureAwait(false);
foreach (var transform in OptionsTransforms)
{
workspace.Options = transform(workspace.Options);
Expand Down Expand Up @@ -1660,16 +1644,27 @@ protected virtual Project ApplyCompilationOptions(Project project)
return solution.GetProject(project.Id);
}

[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete($"Use {nameof(CreateWorkspaceAsync)} instead. https://github.com/dotnet/roslyn-sdk/pull/1120", error: true)]
public Workspace CreateWorkspace()
=> throw new NotSupportedException();

[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete($"Use {nameof(CreateWorkspaceImplAsync)} instead. https://github.com/dotnet/roslyn-sdk/pull/1120", error: true)]
protected virtual Workspace CreateWorkspaceImpl()
=> throw new NotSupportedException();

public async Task<Workspace> CreateWorkspaceAsync()
{
var workspace = CreateWorkspaceImpl();
var workspace = await CreateWorkspaceImplAsync().ConfigureAwait(false);
_workspaces.Add(workspace);
return workspace;
}

protected virtual Workspace CreateWorkspaceImpl()
protected virtual async Task<Workspace> CreateWorkspaceImplAsync()
{
var exportProvider = ExportProviderFactory.Value.CreateExportProvider();
var exportProviderFactory = await ExportProviderFactory.GetOrCreateExportProviderFactoryAsync().ConfigureAwait(false);
var exportProvider = exportProviderFactory.CreateExportProvider();
var host = MefHostServices.Create(exportProvider.AsCompositionContext());
return new AdhocWorkspace(host);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// 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.Threading.Tasks;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.VisualStudio.Composition;

namespace Microsoft.CodeAnalysis.Testing
{
internal static class ExportProviderFactory
{
private static readonly object s_lock = new();
private static Task<IExportProviderFactory>? s_exportProviderFactory;

public static Task<IExportProviderFactory> GetOrCreateExportProviderFactoryAsync()
{
if (s_exportProviderFactory is { } exportProviderFactory)
{
return exportProviderFactory;
}

lock (s_lock)
{
s_exportProviderFactory ??= Task.Run(CreateExportProviderFactorySlowAsync);
return s_exportProviderFactory;
}

static async Task<IExportProviderFactory> CreateExportProviderFactorySlowAsync()
{
var discovery = new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true);
var parts = await discovery.CreatePartsAsync(MefHostServices.DefaultAssemblies).ConfigureAwait(false);
var catalog = ComposableCatalog.Create(Resolver.DefaultInstance).AddParts(parts).WithDocumentTextDifferencingService();

var configuration = CompositionConfiguration.Create(catalog);
var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration);
return runtimeComposition.CreateExportProviderFactory();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.CompilerDiagnostics.get -
Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.CompilerDiagnostics.set -> void
Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.CreateProjectAsync(Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState primaryProject, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState> additionalProjects, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Project>
Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.CreateWorkspace() -> Microsoft.CodeAnalysis.Workspace
Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.CreateWorkspaceAsync() -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Workspace>
Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.DiagnosticVerifier.get -> System.Action<Microsoft.CodeAnalysis.Diagnostic, Microsoft.CodeAnalysis.Testing.DiagnosticResult, Microsoft.CodeAnalysis.Testing.IVerifier>
Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.DiagnosticVerifier.set -> void
Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.DisabledDiagnostics.get -> System.Collections.Generic.List<string>
Expand Down Expand Up @@ -350,6 +351,7 @@ virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.CreateCompilation
virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.CreateProjectImplAsync(Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState primaryProject, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState> additionalProjects, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Project>
virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.CreateSolutionAsync(Microsoft.CodeAnalysis.ProjectId projectId, Microsoft.CodeAnalysis.Testing.Model.EvaluatedProjectState projectState, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Solution>
virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.CreateWorkspaceImpl() -> Microsoft.CodeAnalysis.Workspace
virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.CreateWorkspaceImplAsync() -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Workspace>
virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.DefaultFilePath.get -> string
virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.DefaultFilePathPrefix.get -> string
virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.DefaultTestProjectName.get -> string
Expand Down

0 comments on commit 5f6ffda

Please sign in to comment.