Skip to content

Commit

Permalink
Use newer free-threaded language service API
Browse files Browse the repository at this point in the history
Fixes #353

Roslyn recently implemented a free-threaded version of this API, meaning we no longer need to switch to the UI thread before calling it.

This commit bumps the package version, removes the thread switch and calls the new API.
  • Loading branch information
drewnoakes committed Feb 22, 2021
1 parent 8226af9 commit 7a7f781
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 34 deletions.
19 changes: 9 additions & 10 deletions build/import/Packages.targets
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

<!-- Toolset -->
<PackageReference Update="Nerdbank.Streams" Version="2.6.81" />
<PackageReference Update="System.IO.Pipelines" Version="5.0.0-rc.2.20475.5" />
<PackageReference Update="System.IO.Pipelines" Version="5.0.1" />
<PackageReference Update="RoslynTools.RepoToolset" Version="$(RoslynToolsRepoToolsetVersion)" />
<PackageReference Update="RoslynTools.ModifyVsixManifest" Version="$(RoslynToolsModifyVsixManifestVersion)" />
<PackageReference Update="RoslynTools.SignTool" Version="$(RoslynToolsSignToolVersion)" />
Expand Down Expand Up @@ -47,8 +47,8 @@
<PackageReference Update="Microsoft.VisualStudio.Designer.Interfaces" Version="1.1.4323" />
<PackageReference Update="Microsoft.VisualStudio.ImageCatalog" Version="16.9.30701-preview-2-30710-200" />
<PackageReference Update="Microsoft.VisualStudio.ManagedInterfaces" Version="8.0.50728" />
<PackageReference Update="Microsoft.VisualStudio.RpcContracts" Version="16.8.5-alpha" />
<PackageReference Update="Microsoft.VisualStudio.Telemetry" Version="16.3.59" />
<PackageReference Update="Microsoft.VisualStudio.RpcContracts" Version="16.9.67" />
<PackageReference Update="Microsoft.VisualStudio.Telemetry" Version="16.3.104" />
<PackageReference Update="Microsoft.VisualStudio.Settings.15.0" Version="16.8.30406.155-pre" />
<PackageReference Update="Microsoft.VisualStudio.Setup.Configuration.Interop" Version="2.3.2262-g94fae01e" />
<PackageReference Update="Microsoft.VisualStudio.SDK.EmbedInteropTypes" Version="15.0.34" />
Expand All @@ -66,10 +66,10 @@
<PackageReference Update="Microsoft.VisualStudio.Shell.Interop.15.8.DesignTime" Version="16.8.30406.65" />
<PackageReference Update="Microsoft.VisualStudio.Shell.Interop.16.6.DesignTime" Version="16.8.30406.65-pre" />
<PackageReference Update="Microsoft.VisualStudio.TemplateWizardInterface" Version="16.8.30403.137-pre" />
<PackageReference Update="Microsoft.VisualStudio.Threading" Version="16.8.55" />
<PackageReference Update="Microsoft.VisualStudio.Threading.Analyzers" Version="16.8.55" />
<PackageReference Update="Microsoft.VisualStudio.Utilities" Version="16.8.30406.65-pre" />
<PackageReference Update="Microsoft.VisualStudio.Validation" Version="16.8.33" />
<PackageReference Update="Microsoft.VisualStudio.Threading" Version="16.9.51" />
<PackageReference Update="Microsoft.VisualStudio.Threading.Analyzers" Version="16.9.51" />
<PackageReference Update="Microsoft.VisualStudio.Utilities" Version="16.9.31019.194" />
<PackageReference Update="Microsoft.VisualStudio.Validation" Version="16.9.32" />
<PackageReference Update="Microsoft.VisualStudio.VSHelp" Version="16.0.28321-alpha" />
<PackageReference Update="Microsoft.VisualStudio.WCFReference.Interop" Version="9.1.26606-alpha" />
<PackageReference Update="Microsoft.VisualStudio.Workspace.VSIntegration" Version="16.7.47-preview-0001" />
Expand All @@ -87,7 +87,6 @@
<PackageReference Update="EnvDTE" Version="16.8.30523.219" />
<PackageReference Update="EnvDTE80" Version="16.8.30523.219" />
<PackageReference Update="EnvDTE90" Version="16.8.30523.219" />
<PackageReference Update="StreamJsonRpc" Version="2.6.41-alpha" />

<!-- Avoid double-writes, can remove when https://github.com/NuGet/Home/issues/8343 is fixed -->
<PackageReference Include="VSSDK.DTE" Version="7.0.4" ExcludeAssets="All" />
Expand All @@ -99,8 +98,8 @@
<PackageReference Update="Microsoft.VisualStudio.ProjectSystem.Query" Version="16.9.183-pre" />

<!-- Roslyn -->
<PackageReference Update="Microsoft.VisualStudio.LanguageServices" Version="3.9.0-3.20603.6" />
<PackageReference Update="Microsoft.CodeAnalysis" Version="3.9.0-3.20603.6" />
<PackageReference Update="Microsoft.VisualStudio.LanguageServices" Version="3.10.0-2.21121.14" />
<PackageReference Update="Microsoft.CodeAnalysis" Version="3.10.0-2.21121.14" />
<PackageReference Update="Microsoft.VisualStudio.IntegrationTest.Utilities" Version="2.6.0-beta1-62113-02" />
<PackageReference Update="Microsoft.CSharp" Version="4.7.0" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,17 @@ public Task InitializeAsync(IAsyncServiceProvider asyncServiceProvider)

public override void Write(string message)
{
if (Debugger.IsLogging())
if (System.Diagnostics.Debugger.IsLogging())
{
Debugger.Log(0, null, message);
System.Diagnostics.Debugger.Log(0, null, message);
}
}

public override void WriteLine(string message)
{
if (Debugger.IsLogging())
if (System.Diagnostics.Debugger.IsLogging())
{
Debugger.Log(0, null, message + Environment.NewLine);
System.Diagnostics.Debugger.Log(0, null, message + Environment.NewLine);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.LanguageServices.ProjectSystem;
using Microsoft.VisualStudio.ProjectSystem.Properties;
Expand All @@ -17,20 +18,17 @@ namespace Microsoft.VisualStudio.ProjectSystem.LanguageServices
internal partial class WorkspaceProjectContextProvider : IWorkspaceProjectContextProvider
{
private readonly UnconfiguredProject _project;
private readonly IProjectThreadingService _threadingService;
private readonly IProjectFaultHandlerService _faultHandlerService;
private readonly ISafeProjectGuidService _projectGuidService;
private readonly Lazy<IWorkspaceProjectContextFactory> _workspaceProjectContextFactory;

[ImportingConstructor]
public WorkspaceProjectContextProvider(UnconfiguredProject project,
IProjectThreadingService threadingService,
ISafeProjectGuidService projectGuidService,
IProjectFaultHandlerService faultHandlerService,
Lazy<IWorkspaceProjectContextFactory> workspaceProjectContextFactory) // From Roslyn, so lazy
{
_project = project;
_threadingService = threadingService;
_faultHandlerService = faultHandlerService;
_workspaceProjectContextFactory = workspaceProjectContextFactory;
_projectGuidService = projectGuidService;
Expand Down Expand Up @@ -69,19 +67,17 @@ public async Task ReleaseProjectContextAsync(IWorkspaceProjectContextAccessor ac

private async Task<IWorkspaceProjectContext?> CreateProjectContextHandlingFaultAsync(ProjectContextInitData data, object? hostObject)
{
// TODO: https://github.com/dotnet/project-system/issues/353.
await _threadingService.SwitchToUIThread();

try
{
// Call into Roslyn to init language service for this project
IWorkspaceProjectContext context = _workspaceProjectContextFactory.Value.CreateProjectContext(
IWorkspaceProjectContext context = await _workspaceProjectContextFactory.Value.CreateProjectContextAsync(
data.LanguageName,
data.WorkspaceProjectContextId,
data.ProjectFilePath,
data.ProjectGuid,
hostObject,
data.BinOutputPath);
data.BinOutputPath,
CancellationToken.None);

context.LastDesignTimeBuildSucceeded = false; // By default, turn off diagnostics until the first design time build succeeds for this project.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// 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.md file in the project root for more information.

using System;
using System.Threading;
using System.Threading.Tasks;
using Moq;

namespace Microsoft.VisualStudio.LanguageServices.ProjectSystem
Expand All @@ -12,12 +14,12 @@ public static IWorkspaceProjectContextFactory Create()
return Mock.Of<IWorkspaceProjectContextFactory>();
}

public static IWorkspaceProjectContextFactory ImplementCreateProjectContext(Func<string, string, string, Guid, object, string, IWorkspaceProjectContext?> action)
public static IWorkspaceProjectContextFactory ImplementCreateProjectContextAsync(Func<string, string, string, Guid, object, string, CancellationToken, Task<IWorkspaceProjectContext>> action)
{
var mock = new Mock<IWorkspaceProjectContextFactory>();

mock.Setup(c => c.CreateProjectContext(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Guid>(), It.IsAny<object>(), It.IsAny<string>()))
.Returns(action!);
mock.Setup(c => c.CreateProjectContextAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Guid>(), It.IsAny<object>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(action);

return mock.Object;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public async Task CreateProjectContextAsync_WhenEmptyOrMissingMSBuildProperties_
var snapshot = IProjectRuleSnapshotFactory.FromJson(json);

int callCount = 0;
var workspaceProjectContextFactory = IWorkspaceProjectContextFactoryFactory.ImplementCreateProjectContext((_, _, _, _, _, _) => { callCount++; return null; });
var workspaceProjectContextFactory = IWorkspaceProjectContextFactoryFactory.ImplementCreateProjectContextAsync(delegate { callCount++; return Task.FromResult<IWorkspaceProjectContext>(null!); });
var provider = CreateInstance(workspaceProjectContextFactory: workspaceProjectContextFactory, projectRuleSnapshot: snapshot);

var project = ConfiguredProjectFactory.ImplementProjectConfiguration("Debug|AnyCPU");
Expand All @@ -106,7 +106,7 @@ public async Task CreateProjectContextAsync_UniquelyIdentifiesContext(string con
var projectGuidService = ISafeProjectGuidServiceFactory.ImplementGetProjectGuidAsync(new Guid(guid));

string? result = null;
var workspaceProjectContextFactory = IWorkspaceProjectContextFactoryFactory.ImplementCreateProjectContext((_, id, _, _, _, _) => { result = id; return null; });
var workspaceProjectContextFactory = IWorkspaceProjectContextFactoryFactory.ImplementCreateProjectContextAsync((_, id, _, _, _, _, _) => { result = id; return Task.FromResult<IWorkspaceProjectContext>(null!); });
var provider = CreateInstance(workspaceProjectContextFactory: workspaceProjectContextFactory, projectGuidService: projectGuidService);

var project = ConfiguredProjectFactory.ImplementProjectConfiguration(configuration);
Expand All @@ -128,14 +128,14 @@ public async Task CreateProjectContextAsync_PassesThroughDataToCreateProjectCont
string? languageNameResult = null, projectFilePathResult = null, binOutputPathResult = null;
Guid? projectGuidResult = null;
object? hierarchyResult = null;
var workspaceProjectContextFactory = IWorkspaceProjectContextFactoryFactory.ImplementCreateProjectContext((languageName, _, projectFilePath, guid, hierarchy, binOutputPath) =>
var workspaceProjectContextFactory = IWorkspaceProjectContextFactoryFactory.ImplementCreateProjectContextAsync((languageName, _, projectFilePath, guid, hierarchy, binOutputPath, _) =>
{
languageNameResult = languageName;
projectFilePathResult = projectFilePath;
projectGuidResult = guid;
hierarchyResult = hierarchy;
binOutputPathResult = binOutputPath;
return null;
return Task.FromResult<IWorkspaceProjectContext>(null!);
});

var provider = CreateInstance(project: unconfiguredProject, workspaceProjectContextFactory: workspaceProjectContextFactory, projectGuidService: projectGuidService);
Expand All @@ -154,7 +154,7 @@ public async Task CreateProjectContextAsync_PassesThroughDataToCreateProjectCont
public async Task CreateProjectContextAsync_ReturnsContextWithLastDesignTimeBuildSucceededSetToFalse()
{
var context = IWorkspaceProjectContextMockFactory.Create();
var workspaceProjectContextFactory = IWorkspaceProjectContextFactoryFactory.ImplementCreateProjectContext((_, _, _, _, _, _) => context);
var workspaceProjectContextFactory = IWorkspaceProjectContextFactoryFactory.ImplementCreateProjectContextAsync((_, _, _, _, _, _, _) => Task.FromResult(context));
var provider = CreateInstance(workspaceProjectContextFactory: workspaceProjectContextFactory);

var project = ConfiguredProjectFactory.ImplementProjectConfiguration("Debug|AnyCPU");
Expand All @@ -168,7 +168,7 @@ public async Task CreateProjectContextAsync_ReturnsContextWithLastDesignTimeBuil
[Fact]
public async Task CreateProjectContextAsync_WhenCreateProjectContextThrows_ReturnsNull()
{
var workspaceProjectContextFactory = IWorkspaceProjectContextFactoryFactory.ImplementCreateProjectContext((_, _, _, _, _, _) => { throw new Exception(); });
var workspaceProjectContextFactory = IWorkspaceProjectContextFactoryFactory.ImplementCreateProjectContextAsync((_, _, _, _, _, _, _) => { throw new(); });
var provider = CreateInstance(workspaceProjectContextFactory: workspaceProjectContextFactory);

var project = ConfiguredProjectFactory.ImplementProjectConfiguration("Debug|AnyCPU");
Expand Down Expand Up @@ -203,7 +203,7 @@ public async Task ReleaseProjectContextAsync_WhenContextThrows_SwallowsException
await provider.ReleaseProjectContextAsync(accessor);
}

private static WorkspaceProjectContextProvider CreateInstance(UnconfiguredProject? project = null, IProjectThreadingService? threadingService = null, IWorkspaceProjectContextFactory? workspaceProjectContextFactory = null, ISafeProjectGuidService? projectGuidService = null, IProjectRuleSnapshot? projectRuleSnapshot = null)
private static WorkspaceProjectContextProvider CreateInstance(UnconfiguredProject? project = null, IWorkspaceProjectContextFactory? workspaceProjectContextFactory = null, ISafeProjectGuidService? projectGuidService = null, IProjectRuleSnapshot? projectRuleSnapshot = null)
{
projectRuleSnapshot ??= IProjectRuleSnapshotFactory.FromJson(
@"{
Expand All @@ -216,11 +216,10 @@ private static WorkspaceProjectContextProvider CreateInstance(UnconfiguredProjec

var projectFaultService = IProjectFaultHandlerServiceFactory.Create();
project ??= UnconfiguredProjectFactory.Create();
threadingService ??= IProjectThreadingServiceFactory.Create();
workspaceProjectContextFactory ??= IWorkspaceProjectContextFactoryFactory.Create();
projectGuidService ??= ISafeProjectGuidServiceFactory.ImplementGetProjectGuidAsync(Guid.NewGuid());

var mock = new Mock<WorkspaceProjectContextProvider>(project, threadingService, projectGuidService, projectFaultService, workspaceProjectContextFactory.AsLazy());
var mock = new Mock<WorkspaceProjectContextProvider>(project, projectGuidService, projectFaultService, workspaceProjectContextFactory.AsLazy());
mock.Protected().Setup<Task<IProjectRuleSnapshot>>("GetLatestSnapshotAsync", ItExpr.IsAny<ConfiguredProject>())
.ReturnsAsync(projectRuleSnapshot);

Expand Down

0 comments on commit 7a7f781

Please sign in to comment.