Skip to content

Commit 196538d

Browse files
Pass the MSBuild default assemblies
1 parent 645b0ad commit 196538d

2 files changed

Lines changed: 29 additions & 28 deletions

File tree

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using System;
2+
using System.Collections.Immutable;
3+
using System.Reflection;
24
using System.Threading.Tasks;
35
using ICSharpCode.CodeConverter.Util.FromRoslynSdk;
46
using Microsoft.CodeAnalysis;
57
using Microsoft.CodeAnalysis.Host;
68
using Microsoft.CodeAnalysis.Host.Mef;
79
using Microsoft.VisualStudio.Composition;
10+
using Microsoft.VisualStudio.Threading;
811

912
namespace ICSharpCode.CodeConverter.Shared
1013
{
@@ -15,43 +18,38 @@ namespace ICSharpCode.CodeConverter.Shared
1518
public static class ThreadSafeWorkspaceHelper
1619
{
1720
/// <summary>
18-
/// Use this in all workspace creation
21+
/// Empty solution in an adhoc workspace
1922
/// </summary>
20-
public static HostServices HostServices {
21-
get {
22-
var exportProvider = ExportProviderFactory.Value.CreateExportProvider();
23-
return MefHostServices.Create(exportProvider.AsCompositionContext());
24-
}
25-
}
23+
public static Solution EmptyAdhocSolution => _emptyAdhocSolution.GetAwaiter().GetResult();
2624

2725
/// <summary>
28-
/// Empty solution in an adhoc workspace
26+
/// Use this in all workspace creation
2927
/// </summary>
30-
public static Solution EmptyAdhocSolution => LazyAdhocSolution.Value;
31-
32-
private static readonly Lazy<IExportProviderFactory> ExportProviderFactory = new Lazy<IExportProviderFactory>(CreateExportProviderFactory);
33-
34-
private static IExportProviderFactory CreateExportProviderFactory()
28+
public static async Task<HostServices> CreateHostServicesAsync(ImmutableArray<Assembly> assemblies)
3529
{
36-
#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits - Consider making a joinable task factory available so we can use AsyncLazy
37-
return Task.Run(async () => await CreateExportProviderFactoryAsync()).GetAwaiter().GetResult();
38-
#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits
30+
var exportProvider = await CreateExportProviderFactoryAsync(assemblies);
31+
return MefHostServices.Create(exportProvider.CreateExportProvider().AsCompositionContext());
3932
}
4033

41-
private static async Task<IExportProviderFactory> CreateExportProviderFactoryAsync()
34+
private static async Task<IExportProviderFactory> CreateExportProviderFactoryAsync(ImmutableArray<Assembly> assemblies)
4235
{
4336
var discovery = new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true);
44-
var parts = await discovery.CreatePartsAsync(MefHostServices.DefaultAssemblies);
37+
var parts = await discovery.CreatePartsAsync(assemblies);
4538
var catalog = ComposableCatalog.Create(Resolver.DefaultInstance).AddParts(parts);
4639

4740
var configuration = CompositionConfiguration.Create(catalog);
4841
var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration);
4942
return runtimeComposition.CreateExportProviderFactory();
5043
}
5144

52-
private static Lazy<Solution> LazyAdhocSolution = new Lazy<Solution>(() => {
53-
return new AdhocWorkspace(HostServices).CurrentSolution;
54-
});
45+
/// <summary>
46+
/// Empty solution in an adhoc workspace
47+
/// </summary>
48+
private static Task<Solution> _emptyAdhocSolution =
49+
Task.Run(async () => {
50+
var hostServices = await CreateHostServicesAsync(MefHostServices.DefaultAssemblies);
51+
return new AdhocWorkspace(hostServices).CurrentSolution;
52+
});
5553

5654
}
5755
}

CommandLine/CodeConv.Shared/MSBuildWorkspaceConverter.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using Microsoft.VisualStudio.Threading;
1919
using CodeConv.Shared.Util;
2020
using System.ComponentModel.DataAnnotations;
21+
using Microsoft.CodeAnalysis.Host.Mef;
2122

2223
namespace ICSharpCode.CodeConverter.CommandLine
2324
{
@@ -26,7 +27,7 @@ public sealed class MSBuildWorkspaceConverter : IDisposable
2627
private readonly bool _bestEffortConversion;
2728
private readonly string _solutionFilePath;
2829
private readonly Dictionary<string, string> _buildProps;
29-
private readonly Lazy<MSBuildWorkspace> _workspace; //Cached to avoid NullRef from OptionsService when initialized concurrently (e.g. in our tests)
30+
private readonly AsyncLazy<MSBuildWorkspace> _workspace; //Cached to avoid NullRef from OptionsService when initialized concurrently (e.g. in our tests)
3031
private AsyncLazy<Solution>? _cachedSolution; //Cached for performance of tests
3132
private readonly bool _isNetCore;
3233

@@ -38,7 +39,7 @@ public MSBuildWorkspaceConverter(string solutionFilePath, bool isNetCore, bool b
3839
_buildProps.TryAdd("Platform", "AnyCPU");
3940
_solutionFilePath = solutionFilePath;
4041
_isNetCore = isNetCore;
41-
_workspace = new Lazy<MSBuildWorkspace>(() => CreateWorkspace(_buildProps));
42+
_workspace = new AsyncLazy<MSBuildWorkspace>(() => CreateWorkspaceAsync(_buildProps));
4243
}
4344

4445
public async IAsyncEnumerable<ConversionResult> ConvertProjectsWhereAsync(Func<Project, bool> shouldConvertProject, Language? targetLanguage, IProgress<ConversionProgress> progress, [EnumeratorCancellation] CancellationToken token)
@@ -70,7 +71,7 @@ private async Task<Solution> GetSolutionAsync(string projectOrSolutionFile, IPro
7071
progress.Report($"Running dotnet restore on {projectOrSolutionFile}");
7172
await RestorePackagesForSolutionAsync(projectOrSolutionFile);
7273

73-
var workspace = _workspace.Value;
74+
var workspace = await _workspace.GetValueAsync();
7475
var solution = string.Equals(Path.GetExtension(projectOrSolutionFile), ".sln", StringComparison.OrdinalIgnoreCase) ? await workspace.OpenSolutionAsync(projectOrSolutionFile)
7576
: (await workspace.OpenProjectAsync(projectOrSolutionFile)).Solution;
7677

@@ -95,7 +96,7 @@ private async Task<Solution> GetSolutionAsync(string projectOrSolutionFile, IPro
9596
private async Task<string> GetCompilationErrorsAsync(
9697
IEnumerable<Project> projectsToConvert)
9798
{
98-
var workspaceErrors = _workspace.Value.Diagnostics.GetErrorString();
99+
var workspaceErrors = (await _workspace.GetValueAsync()).Diagnostics.GetErrorString();
99100
var errors = await projectsToConvert.ParallelSelectAwait(async x => {
100101
var c = await x.GetCompilationAsync() ?? throw new InvalidOperationException($"Compilation could not be created for {x.Language}");
101102
return new[] { CompilationWarnings.WarningsForCompilation(c, c.AssemblyName) };
@@ -110,7 +111,7 @@ private static async Task RestorePackagesForSolutionAsync(string solutionFile)
110111
if (restoreExitCode != 0) throw new ValidationException("dotnet restore had a non-zero exit code.");
111112
}
112113

113-
private static MSBuildWorkspace CreateWorkspace(Dictionary<string, string> buildProps)
114+
private static async Task<MSBuildWorkspace> CreateWorkspaceAsync(Dictionary<string, string> buildProps)
114115
{
115116
if (MSBuildLocator.CanRegister) {
116117
var instances = MSBuildLocator.QueryVisualStudioInstances().ToArray();
@@ -119,12 +120,14 @@ private static MSBuildWorkspace CreateWorkspace(Dictionary<string, string> build
119120
MSBuildLocator.RegisterInstance(instance);
120121
AppDomain.CurrentDomain.UseVersionAgnosticAssemblyResolution();
121122
}
122-
return MSBuildWorkspace.Create(buildProps, ThreadSafeWorkspaceHelper.HostServices);
123+
124+
var hostServices = await ThreadSafeWorkspaceHelper.CreateHostServicesAsync(MSBuildMefHostServices.DefaultAssemblies);
125+
return MSBuildWorkspace.Create(buildProps, hostServices);
123126
}
124127

125128
public void Dispose()
126129
{
127-
if (_workspace.IsValueCreated) _workspace.Value.Dispose();
130+
if (_workspace.IsValueCreated) _workspace.GetValueAsync().Dispose();
128131
}
129132
}
130133
}

0 commit comments

Comments
 (0)