-
Notifications
You must be signed in to change notification settings - Fork 387
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9531 from Erarndt/dev/erarndt/languageServiceThre…
…adSwitch Avoid repeated switches to main thread to check if in command line mode
- Loading branch information
Showing
2 changed files
with
28 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 28 additions & 45 deletions
73
src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/Shell/VSShellServices.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,58 @@ | ||
// 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 Microsoft.VisualStudio.ProjectSystem; | ||
using Microsoft.VisualStudio.ProjectSystem.VS; | ||
using Microsoft.VisualStudio.ProjectSystem.VS.Interop; | ||
using Microsoft.VisualStudio.Shell.Interop; | ||
using Microsoft.VisualStudio.Threading; | ||
|
||
namespace Microsoft.VisualStudio.Shell; | ||
|
||
[Export(typeof(IVsShellServices))] | ||
[AppliesTo(ProjectCapabilities.AlwaysApplicable)] | ||
internal class VSShellServices : IVsShellServices | ||
{ | ||
|
||
private readonly AsyncLazy<(bool IsCommandLineMode, bool IsPopulateSolutionCacheMode)> _initialization; | ||
private readonly Task<bool> _isCommandLine; | ||
private readonly Task<bool> _isPopulateCache; | ||
|
||
[ImportingConstructor] | ||
public VSShellServices( | ||
IVsUIService<SVsShell, IVsShell> vsShellService, | ||
IVsUIService<SVsAppCommandLine, IVsAppCommandLine> commandLineService, | ||
JoinableTaskContext joinableTaskContext) | ||
IVsService<IVsAppId> vsAppId, | ||
IVsService<SVsAppCommandLine, IVsAppCommandLine> commandLine) | ||
{ | ||
_initialization = new( | ||
async () => | ||
{ | ||
// Initialisation must occur on the main thread. | ||
await joinableTaskContext.Factory.SwitchToMainThreadAsync(); | ||
IVsShell? vsShell = vsShellService.Value; | ||
IVsAppCommandLine? commandLine = commandLineService.Value; | ||
bool isCommandLineMode = IsCommandLineMode(); | ||
_isCommandLine = IsCommandLineModeAsync(vsAppId); | ||
_isPopulateCache = IsPopulateSolutionCacheModeAsync(commandLine); | ||
|
||
if (isCommandLineMode) | ||
{ | ||
return (IsCommandLineMode: true, IsPopulateSolutionCacheMode()); | ||
} | ||
return (false, false); | ||
bool IsCommandLineMode() | ||
{ | ||
Assumes.Present(vsShell); | ||
int hr = vsShell.GetProperty((int)__VSSPROPID.VSSPROPID_IsInCommandLineMode, out object result); | ||
static async Task<bool> IsCommandLineModeAsync(IVsService<IVsAppId> vsAppIdService) | ||
{ | ||
IVsAppId? vsAppId = await vsAppIdService.GetValueOrNullAsync(); | ||
if (vsAppId is not null) | ||
{ | ||
const int VSAPROPID_IsInCommandLineMode = (int)Microsoft.Internal.VisualStudio.AppId.Interop.__VSAPROPID10.VSAPROPID_IsInCommandLineMode; | ||
return ErrorHandler.Succeeded(vsAppId.GetProperty(VSAPROPID_IsInCommandLineMode, out object o)) && o is true; | ||
} | ||
|
||
return ErrorHandler.Succeeded(hr) | ||
&& result is bool isCommandLineMode | ||
&& isCommandLineMode; | ||
} | ||
return false; | ||
} | ||
|
||
bool IsPopulateSolutionCacheMode() | ||
{ | ||
if (commandLine is null) | ||
return false; | ||
static async Task<bool> IsPopulateSolutionCacheModeAsync(IVsService<SVsAppCommandLine, IVsAppCommandLine> commandLineService) | ||
{ | ||
IVsAppCommandLine? commandLine = await commandLineService.GetValueOrNullAsync(); | ||
if (commandLine is null) | ||
return false; | ||
|
||
int hr = commandLine.GetOption("populateSolutionCache", out int populateSolutionCache, out string commandValue); | ||
int hr = commandLine.GetOption("populateSolutionCache", out int populateSolutionCache, out string _); | ||
|
||
return ErrorHandler.Succeeded(hr) | ||
&& Convert.ToBoolean(populateSolutionCache); | ||
} | ||
}, | ||
joinableTaskContext.Factory); | ||
return ErrorHandler.Succeeded(hr) | ||
&& Convert.ToBoolean(populateSolutionCache); | ||
} | ||
} | ||
|
||
public async Task<bool> IsCommandLineModeAsync(CancellationToken cancellationToken) | ||
{ | ||
return (await _initialization.GetValueAsync(cancellationToken)).IsCommandLineMode; | ||
return await _isCommandLine; | ||
} | ||
|
||
public async Task<bool> IsPopulateSolutionCacheModeAsync(CancellationToken cancellationToken) | ||
{ | ||
return (await _initialization.GetValueAsync(cancellationToken)).IsPopulateSolutionCacheMode; | ||
return await _isPopulateCache; | ||
} | ||
} |