Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
// 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;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using Microsoft.CodeAnalysis.Editor;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.VisualStudio.Composition;
Expand All @@ -25,10 +29,15 @@ internal class CSharpLanguageServerClient : AbstractLanguageServerClient
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CSharpLanguageServerClient(
IThreadingContext threadingContext,
VisualStudioWorkspace workspace,
IEnumerable<Lazy<IOptionPersister>> lazyOptions,
LanguageServerClientEventListener eventListener,
IAsynchronousOperationListenerProvider listenerProvider)
: base(workspace,
: base(
threadingContext,
workspace,
lazyOptions,
eventListener,
listenerProvider,
languageServerName: WellKnownServiceHubServices.CSharpLanguageServer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,18 @@
using Microsoft.CodeAnalysis.Host;
using System.Composition;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Options;
using System.Linq;
using Microsoft.CodeAnalysis.Experiments;

namespace Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService
{
internal abstract class AbstractLanguageServerClient : ILanguageClient
{
private readonly IThreadingContext _threadingContext;
private readonly Workspace _workspace;
private readonly IEnumerable<Lazy<IOptionPersister>> _lazyOptions;
private readonly LanguageServerClientEventListener _eventListener;
private readonly IAsynchronousOperationListener _asyncListener;

Expand Down Expand Up @@ -55,13 +61,17 @@ internal abstract class AbstractLanguageServerClient : ILanguageClient
#pragma warning restore CS0067 // event never used

public AbstractLanguageServerClient(
IThreadingContext threadingContext,
Workspace workspace,
IEnumerable<Lazy<IOptionPersister>> lazyOptions,
LanguageServerClientEventListener eventListener,
IAsynchronousOperationListenerProvider listenerProvider,
string languageServerName,
string serviceHubClientName)
{
_threadingContext = threadingContext;
_workspace = workspace;
_lazyOptions = lazyOptions;
_eventListener = eventListener;
_asyncListener = listenerProvider.GetListener(FeatureAttribute.FindReferences);

Expand Down Expand Up @@ -103,6 +113,9 @@ public Task OnLoadedAsync()
// set up event stream so that we start LSP server once Roslyn is loaded
_eventListener.WorkspaceStarted.ContinueWith(async _ =>
{
// initialize things on UI thread
await InitializeOnUIAsync().ConfigureAwait(false);

// this might get called before solution is fully loaded and before file is opened.
// we delay our OOP start until then, but user might do vsstart before that. so we make sure we start OOP if
// it is not running yet. multiple start is no-op
Expand All @@ -122,6 +135,24 @@ public Task OnLoadedAsync()
}, TaskScheduler.Default).CompletesAsyncOperation(token);

return Task.CompletedTask;

async Task InitializeOnUIAsync()
{
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync();

// this doesn't attempt to solve our JTF and some services being not free-thread issue here, but
// try to fix this particular deadlock issue only. we already have long discussion on
// how we need to deal with JTF, Roslyn service requirements and VS services reality conflicting
// each others. architectural fix should come from the result of that discussion.

// Ensure the options persisters are loaded since we have to fetch options from the shell
_lazyOptions.Select(o => o.Value);

// experimentation service unfortunately uses JTF to jump to UI thread in certain cases
// which can cause deadlock if 2 parties try to enable OOP from BG and then FG before
// experimentation service tries to jump to UI thread.
var experimentationService = _workspace.Services.GetService<IExperimentationService>();
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,7 @@ private void SetRemoteHostBitness()
var x64 = _workspace.Options.GetOption(RemoteHostOptions.OOP64Bit);
if (!x64)
{
x64 = _workspace.Services.GetService<IExperimentationService>().IsExperimentEnabled(
WellKnownExperimentNames.RoslynOOP64bit);
x64 = _workspace.Services.GetService<IExperimentationService>().IsExperimentEnabled(WellKnownExperimentNames.RoslynOOP64bit);
}

// log OOP bitness
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

Imports System.ComponentModel.Composition
Imports Microsoft.CodeAnalysis.Editor
Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Remote
Imports Microsoft.CodeAnalysis.Shared.TestHooks
Imports Microsoft.VisualStudio.LanguageServer.Client
Expand All @@ -23,10 +25,14 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.LanguageClient

<ImportingConstructor>
<Obsolete(MefConstruction.ImportingConstructorMessage, True)>
Public Sub New(workspace As VisualStudioWorkspace,
Public Sub New(threadingContext As IThreadingContext,
workspace As VisualStudioWorkspace,
lazyOptions As IEnumerable(Of Lazy(Of IOptionPersister)),
eventListener As LanguageServerClientEventListener,
listenerProvider As IAsynchronousOperationListenerProvider)
MyBase.New(workspace,
MyBase.New(threadingContext,
workspace,
lazyOptions,
eventListener,
listenerProvider,
languageServerName:=WellKnownServiceHubServices.VisualBasicLanguageServer,
Expand Down