Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to new output window API #38653

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 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
8 changes: 5 additions & 3 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
<MicrosoftExtensionsLoggingVersion>2.1.1</MicrosoftExtensionsLoggingVersion>
<MicrosoftIdentityModelClientsActiveDirectoryVersion>3.13.8</MicrosoftIdentityModelClientsActiveDirectoryVersion>
<MicrosoftInternalPerformanceCodeMarkersDesignTimeVersion>15.8.27812-alpha</MicrosoftInternalPerformanceCodeMarkersDesignTimeVersion>
<MicrosoftInternalVisualStudioShellEmbeddable>16.4.29305.180</MicrosoftInternalVisualStudioShellEmbeddable>
<MicrosoftInternalVisualStudioShellInterop140DesignTimeVersion>14.3.25407-alpha</MicrosoftInternalVisualStudioShellInterop140DesignTimeVersion>
<MicrosoftMetadataVisualizerVersion>1.0.0-beta1-63011-01</MicrosoftMetadataVisualizerVersion>
<MicrosoftMSXMLVersion>8.0.0.0-alpha</MicrosoftMSXMLVersion>
Expand Down Expand Up @@ -127,6 +128,7 @@
<MicrosoftVisualStudioProjectSystemVersion>16.2.133-pre</MicrosoftVisualStudioProjectSystemVersion>
<MicrosoftVisualStudioProjectSystemManagedVersion>2.3.6152103</MicrosoftVisualStudioProjectSystemManagedVersion>
<MicrosoftVisualStudioRemoteControlVersion>14.1.10</MicrosoftVisualStudioRemoteControlVersion>
<MicrosoftVisualStudioRpcContracts>16.3.35-alpha</MicrosoftVisualStudioRpcContracts>
<MicrosoftVisualStudioSDKAnalyzersVersion>16.3.2</MicrosoftVisualStudioSDKAnalyzersVersion>
<MicrosoftVisualStudioSetupConfigurationInteropVersion>1.16.30</MicrosoftVisualStudioSetupConfigurationInteropVersion>
<MicrosoftVisualStudioShell150Version>16.0.28226-pre</MicrosoftVisualStudioShell150Version>
Expand Down Expand Up @@ -156,15 +158,15 @@
<MicrosoftVisualStudioThreadingAnalyzersVersion>16.3.13</MicrosoftVisualStudioThreadingAnalyzersVersion>
<MicrosoftVisualStudioThreadingVersion>16.3.13</MicrosoftVisualStudioThreadingVersion>
<MicrosoftVisualStudioUtilitiesVersion>16.3.29212.169</MicrosoftVisualStudioUtilitiesVersion>
<MicrosoftVisualStudioValidationVersion>15.3.23</MicrosoftVisualStudioValidationVersion>
<MicrosoftVisualStudioValidationVersion>15.5.31</MicrosoftVisualStudioValidationVersion>
<MicrosoftVisualStudioVsInteractiveWindowVersion>2.0.0-rc3-61304-01</MicrosoftVisualStudioVsInteractiveWindowVersion>
<MicrosoftWin32PrimitivesVersion>4.3.0</MicrosoftWin32PrimitivesVersion>
<MSBuildStructuredLoggerVersion>2.0.61</MSBuildStructuredLoggerVersion>
<MDbgVersion>0.1.0</MDbgVersion>
<MonoOptionsVersion>4.4.0</MonoOptionsVersion>
<MoqVersion>4.10.1</MoqVersion>
<NerdbankFullDuplexStreamVersion>1.0.1</NerdbankFullDuplexStreamVersion>
<NewtonsoftJsonVersion>12.0.1</NewtonsoftJsonVersion>
<NewtonsoftJsonVersion>12.0.2</NewtonsoftJsonVersion>
<NuGetPackagingVersion>4.9.2</NuGetPackagingVersion>
<NuGetVisualStudioVersion>4.0.0-rc-2048</NuGetVisualStudioVersion>
<NuGetSolutionRestoreManagerInteropVersion>4.8.0</NuGetSolutionRestoreManagerInteropVersion>
Expand All @@ -179,7 +181,7 @@
<RoslynToolsLightUpSystemRuntimeLoaderFixedVersion>4.3.0</RoslynToolsLightUpSystemRuntimeLoaderFixedVersion>
<RoslynMicrosoftVisualStudioExtensionManagerVersion>0.0.4</RoslynMicrosoftVisualStudioExtensionManagerVersion>
<SourceBrowserVersion>1.0.21</SourceBrowserVersion>
<StreamJsonRpcVersion>2.1.55</StreamJsonRpcVersion>
<StreamJsonRpcVersion>2.1.74</StreamJsonRpcVersion>
<SystemBuffersVersion>4.5.0</SystemBuffersVersion>
<SystemCollectionsImmutableVersion>1.5.0</SystemCollectionsImmutableVersion>
<SystemCommandLineExperimentalVersion>0.1.0-alpha-63729-01</SystemCommandLineExperimentalVersion>
Expand Down
1 change: 1 addition & 0 deletions src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
<_Dependency Remove="Microsoft.Build"/>
<_Dependency Remove="Microsoft.Build.Framework"/>
<_Dependency Remove="Microsoft.MSXML"/>
<_Dependency Remove="Microsoft.ServiceHub.Framework" />
<_Dependency Remove="Newtonsoft.Json"/>
<_Dependency Remove="stdole"/>
<_Dependency Remove="StreamJsonRpc"/>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
<PackageReference Include="EnvDTE" Version="$(EnvDTEVersion)" />
<PackageReference Include="EnvDTE80" Version="$(EnvDTE80Version)" />
<PackageReference Include="Microsoft.CodeAnalysis.Elfie" Version="$(MicrosoftCodeAnalysisElfieVersion)" PrivateAssets="all" />
<PackageReference Include="Microsoft.Internal.VisualStudio.Shell.Embeddable" Version="$(MicrosoftInternalVisualStudioShellEmbeddable)" />
<PackageReference Include="Microsoft.ServiceHub.Client" Version="$(MicrosoftServiceHubClientVersion)" />
<PackageReference Include="Microsoft.VisualStudio.Debugger.Engine-implementation" Version="$(MicrosoftVisualStudioDebuggerEngineimplementationVersion)" />
<PackageReference Include="Microsoft.VisualStudio.Debugger.UI.Interfaces" Version="$(MicrosoftVisualStudioDebuggerUIInterfacesVersion)" />
Expand All @@ -186,6 +187,7 @@
<PackageReference Include="Microsoft.VisualStudio.Progression.CodeSchema" Version="$(MicrosoftVisualStudioProgressionCodeSchemaVersion)" />
<PackageReference Include="Microsoft.VisualStudio.Progression.Common" Version="$(MicrosoftVisualStudioProgressionCommonVersion)" />
<PackageReference Include="Microsoft.VisualStudio.Progression.Interfaces" Version="$(MicrosoftVisualStudioProgressionInterfacesVersion)" />
<PackageReference Include="Microsoft.VisualStudio.RpcContracts" Version="$(MicrosoftVisualStudioRpcContracts)" />
<PackageReference Include="Microsoft.VisualStudio.GraphModel" Version="$(MicrosoftVisualStudioGraphModelVersion)" />
<PackageReference Include="Microsoft.VisualStudio.CallHierarchy.Package.Definitions" Version="$(MicrosoftVisualStudioCallHierarchyPackageDefinitionsVersion)" />
<PackageReference Include="Microsoft.VisualStudio.Language.CallHierarchy" Version="$(MicrosoftVisualStudioLanguageCallHierarchyVersion)" />
Expand Down
22 changes: 20 additions & 2 deletions src/VisualStudio/Core/Def/RoslynPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Microsoft.CodeAnalysis.Notification;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Versions;
using Microsoft.ServiceHub.Framework;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.LanguageServices.Experimentation;
using Microsoft.VisualStudio.LanguageServices.Implementation;
Expand All @@ -28,6 +29,7 @@
using Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource;
using Microsoft.VisualStudio.LanguageServices.Telemetry;
using Microsoft.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.RpcContracts.OutputChannel;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.TaskStatusCenter;
Expand All @@ -43,7 +45,6 @@ namespace Microsoft.VisualStudio.LanguageServices.Setup
internal class RoslynPackage : AbstractPackage
{
private VisualStudioWorkspace _workspace;
private WorkspaceFailureOutputPane _outputPane;
private IComponentModel _componentModel;
private RuleSetEventHandler _ruleSetEventHandler;
private IDisposable _solutionEventMonitor;
Expand Down Expand Up @@ -78,7 +79,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
RoslynTelemetrySetup.Initialize(this);

// set workspace output pane
_outputPane = new WorkspaceFailureOutputPane(_componentModel.GetService<IThreadingContext>(), this, _workspace);
await InitializeWorkspaceFailureOutputWindow().ConfigureAwait(true);

InitializeColors();

Expand All @@ -90,6 +91,23 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
TrackBulkFileOperations();
}

private async Task InitializeWorkspaceFailureOutputWindow()
dibarbet marked this conversation as resolved.
Show resolved Hide resolved
{
var threadingContext = _componentModel.GetService<IThreadingContext>();
var brokeredServiceContainer = await this.GetServiceAsync<SVsBrokeredServiceContainer, IBrokeredServiceContainer>().ConfigureAwait(false);
dibarbet marked this conversation as resolved.
Show resolved Hide resolved
Assumes.Present(brokeredServiceContainer);
var serviceBroker = brokeredServiceContainer.GetFullAccessServiceBroker();
var serviceBrokerClient = new ServiceBrokerClient(serviceBroker, threadingContext.JoinableTaskFactory);

#pragma warning disable VSTHRD101 // Avoid unsupported async delegates
dibarbet marked this conversation as resolved.
Show resolved Hide resolved
_workspace.WorkspaceFailed += async (sender, eventArgs) =>
{
using var outputChannelStore = await serviceBrokerClient.GetProxyAsync<IOutputChannelStore>(VisualStudioServices.VS2019_4.OutputChannelStore).ConfigureAwait(false);
await outputChannelStore.Proxy.WriteLineAsync(ServicesVSResources.IntelliSense, eventArgs.Diagnostic.ToString()).ConfigureAwait(false);
};
#pragma warning restore VSTHRD101 // Avoid unsupported async delegates
}

private void InitializeColors()
{
// Use VS color keys in order to support theming.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

using System;
using System.Threading;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Options;
using Microsoft.ServiceHub.Framework;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.RpcContracts.OutputChannel;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

namespace Microsoft.CodeAnalysis.Internal.Log
{
Expand All @@ -19,6 +19,9 @@ internal sealed class OutputWindowLogger : ILogger
{
private readonly Func<FunctionId, bool> _loggingChecker;

private readonly ServiceBrokerClient _serviceBrokerClient;
private readonly IThreadingContext _threadingContext;

public OutputWindowLogger()
: this((Func<FunctionId, bool>)null)
{
Expand All @@ -32,6 +35,18 @@ public OutputWindowLogger(IGlobalOptionService optionService)
public OutputWindowLogger(Func<FunctionId, bool> loggingChecker)
{
_loggingChecker = loggingChecker;

var serviceProvider = ServiceProvider.GlobalProvider;

var componentModel = (IComponentModel)serviceProvider.GetService(typeof(SComponentModel));
Assumes.Present(componentModel);

var brokeredServiceContainer = (IBrokeredServiceContainer)serviceProvider.GetService(typeof(SVsBrokeredServiceContainer));
dibarbet marked this conversation as resolved.
Show resolved Hide resolved
Assumes.Present(brokeredServiceContainer);
var serviceBroker = brokeredServiceContainer.GetFullAccessServiceBroker();

_threadingContext = componentModel.GetService<IThreadingContext>();
_serviceBrokerClient = new ServiceBrokerClient(serviceBroker, _threadingContext.JoinableTaskFactory);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any overhead of creating multiple Clients, or is there some benefit of sharing things?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, I'll defer to Andrew

@AArnott is there any issue with sharing a single service broker client to retrieve various distinct services? Is there any benefit to doing that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A ServiceBrokerClient is totally fine with you requesting several services from it. It's optimized for that. What you shouldn't do is share your ServiceBrokerClient with a lot of users/classes if you can avoid it. The AvailabilityChanged event can get noisy if it's raising events to a lot of listeners for services that aren't related to an individual handler. So basically if you're setting up multiple handlers for that event to inform different classes that all consume from the same ServiceBrokerClient, consider creating a separate ServiceBrokerClient (and each with its own IServiceBroker passed to it) for each of these classes.

}

public bool IsEnabled(FunctionId functionId)
Expand All @@ -41,97 +56,27 @@ public bool IsEnabled(FunctionId functionId)

public void Log(FunctionId functionId, LogMessage logMessage)
{
OutputPane.WriteLine(string.Format("[{0}] {1} - {2}", Thread.CurrentThread.ManagedThreadId, functionId.ToString(), logMessage.GetMessage()));
WriteLine(string.Format("[{0}] {1} - {2}", Thread.CurrentThread.ManagedThreadId, functionId.ToString(), logMessage.GetMessage()));
}

public void LogBlockStart(FunctionId functionId, LogMessage logMessage, int uniquePairId, CancellationToken cancellationToken)
{
OutputPane.WriteLine(string.Format("[{0}] Start({1}) : {2} - {3}", Thread.CurrentThread.ManagedThreadId, uniquePairId, functionId.ToString(), logMessage.GetMessage()));
WriteLine(string.Format("[{0}] Start({1}) : {2} - {3}", Thread.CurrentThread.ManagedThreadId, uniquePairId, functionId.ToString(), logMessage.GetMessage()));
}

public void LogBlockEnd(FunctionId functionId, LogMessage logMessage, int uniquePairId, int delta, CancellationToken cancellationToken)
{
var functionString = functionId.ToString() + (cancellationToken.IsCancellationRequested ? " Canceled" : string.Empty);
OutputPane.WriteLine(string.Format("[{0}] End({1}) : [{2}ms] {3}", Thread.CurrentThread.ManagedThreadId, uniquePairId, delta, functionString));
WriteLine(string.Format("[{0}] End({1}) : [{2}ms] {3}", Thread.CurrentThread.ManagedThreadId, uniquePairId, delta, functionString));
}

private class OutputPane
private void WriteLine(string value)
{
private static readonly Guid s_outputPaneGuid = new Guid("BBAFF416-4AF5-41F2-9F93-91F283E43C3B");

public static readonly OutputPane s_instance = new OutputPane();

private readonly IServiceProvider _serviceProvider;
private readonly IThreadingContext _threadingContext;

public static void WriteLine(string value)
{
s_instance.WriteLineInternal(value);
}

public OutputPane()
{
_serviceProvider = ServiceProvider.GlobalProvider;

var componentModel = (IComponentModel)_serviceProvider.GetService(typeof(SComponentModel));
_threadingContext = componentModel.GetService<IThreadingContext>();
}

private IVsOutputWindowPane _doNotAccessDirectlyOutputPane;

private void WriteLineInternal(string value)
{
var pane = GetPane();
if (pane == null)
{
return;
}

pane.OutputStringThreadSafe(value + Environment.NewLine);
}

private IVsOutputWindowPane GetPane()
_threadingContext.JoinableTaskFactory.RunAsync(async () =>
dibarbet marked this conversation as resolved.
Show resolved Hide resolved
{
if (_doNotAccessDirectlyOutputPane == null)
{
_threadingContext.JoinableTaskFactory.Run(async () =>
{
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync();

if (_doNotAccessDirectlyOutputPane != null)
{
// check whether other one already initialized output window.
// the output API already handle double initialization, so this is just quick bail
// rather than any functional issue
return;
}

var outputWindow = (IVsOutputWindow)_serviceProvider.GetService(typeof(SVsOutputWindow));

// this should bring outout window to the front
_doNotAccessDirectlyOutputPane = CreateOutputPane(outputWindow);
});
}

return _doNotAccessDirectlyOutputPane;
}

private IVsOutputWindowPane CreateOutputPane(IVsOutputWindow outputWindow)
{
_threadingContext.ThrowIfNotOnUIThread();

// Try to get the workspace pane if it has already been registered
var workspacePaneGuid = s_outputPaneGuid;

// If the pane has already been created, CreatePane returns it
if (ErrorHandler.Succeeded(outputWindow.CreatePane(ref workspacePaneGuid, "Roslyn Logger Output", fInitVisible: 1, fClearWithSolution: 1)) &&
ErrorHandler.Succeeded(outputWindow.GetPane(ref workspacePaneGuid, out var pane)))
{
return pane;
}

return null;
}
using var outputChannelStore = await _serviceBrokerClient.GetProxyAsync<IOutputChannelStore>(VisualStudioServices.VS2019_4.OutputChannelStore).ConfigureAwait(false);
await outputChannelStore.Proxy.WriteLineAsync("Roslyn Logger Output", value).ConfigureAwait(false);
});
}
}
}
Loading