提交 a6ec0f86 编写于 作者: C CyrusNajmabadi

Don't cause VB to load in a C# project and vice-versa.

上级 b280c27c
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Utilities;
using Microsoft.VisualStudio.Shell;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService
{
internal abstract class AbstractPackage : Package
{
protected ForegroundThreadAffinitizedObject ForegroundObject;
protected override void Initialize()
{
base.Initialize();
// Assume that we are being initialized on the UI thread at this point.
var defaultForegroundThreadData = ForegroundThreadData.CreateDefault(
defaultKind: ForegroundThreadDataKind.ForcedByPackageInitialize);
ForegroundThreadAffinitizedObject.CurrentForegroundThreadData = defaultForegroundThreadData;
ForegroundObject = new ForegroundThreadAffinitizedObject(defaultForegroundThreadData);
}
protected void LoadComponentsInUIContextOnceSolutionFullyLoaded()
{
ForegroundObject.AssertIsForeground();
if (KnownUIContexts.SolutionExistsAndFullyLoadedContext.IsActive)
{
// if we are already in the right UI context, load it right away
LoadComponentsInUIContext();
}
else
{
// load them when it is a right context.
KnownUIContexts.SolutionExistsAndFullyLoadedContext.UIContextChanged += OnSolutionExistsAndFullyLoadedContext;
}
}
private void OnSolutionExistsAndFullyLoadedContext(object sender, UIContextChangedEventArgs e)
{
ForegroundObject.AssertIsForeground();
if (e.Activated)
{
// unsubscribe from it
KnownUIContexts.SolutionExistsAndFullyLoadedContext.UIContextChanged -= OnSolutionExistsAndFullyLoadedContext;
// load components
LoadComponentsInUIContext();
}
}
protected abstract void LoadComponentsInUIContext();
}
}
......@@ -4,22 +4,28 @@
using System.Collections.Generic;
using System.ComponentModel.Design;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Packaging;
using Microsoft.CodeAnalysis.SymbolSearch;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.LanguageServices.Packaging;
using Microsoft.VisualStudio.LanguageServices.SymbolSearch;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using static Microsoft.CodeAnalysis.Utilities.ForegroundThreadDataKind;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService
{
internal abstract partial class AbstractPackage<TPackage, TLanguageService> : Package
internal abstract partial class AbstractPackage<TPackage, TLanguageService> : AbstractPackage
where TPackage : AbstractPackage<TPackage, TLanguageService>
where TLanguageService : AbstractLanguageService<TPackage, TLanguageService>
{
private ForegroundThreadAffinitizedObject _foregroundObject;
private TLanguageService _languageService;
private MiscellaneousFilesWorkspace _miscellaneousFilesWorkspace;
private PackageInstallerService _packageInstallerService;
private SymbolSearchService _symbolSearchService;
public VisualStudioWorkspaceImpl Workspace { get; private set; }
protected AbstractPackage()
......@@ -29,10 +35,6 @@ protected AbstractPackage()
protected override void Initialize()
{
base.Initialize();
// Assume that we are being initialized on the UI thread at this point.
var defaultForegroundThreadData = ForegroundThreadData.CreateDefault(defaultKind: ForcedByPackageInitialize);
ForegroundThreadAffinitizedObject.CurrentForegroundThreadData = defaultForegroundThreadData;
_foregroundObject = new ForegroundThreadAffinitizedObject(defaultForegroundThreadData);
foreach (var editorFactory in CreateEditorFactories())
{
......@@ -76,6 +78,21 @@ protected override void Initialize()
// Ensure services that must be created on the UI thread have been.
HACK_AbstractCreateServicesOnUiThread.CreateServicesOnUIThread(ComponentModel, RoslynLanguageName);
LoadComponentsInUIContextOnceSolutionFullyLoaded();
}
protected override void LoadComponentsInUIContext()
{
ForegroundObject.AssertIsForeground();
// Ensure the nuget package services are initialized after we've loaded
// the solution.
_packageInstallerService = Workspace.Services.GetService<IPackageInstallerService>() as PackageInstallerService;
_symbolSearchService = Workspace.Services.GetService<ISymbolSearchService>() as SymbolSearchService;
_packageInstallerService?.Start();
_symbolSearchService?.Start(this.RoslynLanguageName);
}
protected abstract VisualStudioWorkspaceImpl CreateWorkspace();
......@@ -84,7 +101,7 @@ internal IComponentModel ComponentModel
{
get
{
_foregroundObject.AssertIsForeground();
ForegroundObject.AssertIsForeground();
return (IComponentModel)GetService(typeof(SComponentModel));
}
......@@ -108,6 +125,9 @@ protected void RegisterLanguageService(Type t, Func<object> serviceCreator)
protected override void Dispose(bool disposing)
{
_packageInstallerService?.Stop();
_symbolSearchService?.Stop(this.RoslynLanguageName);
if (_miscellaneousFilesWorkspace != null)
{
_miscellaneousFilesWorkspace.StopSolutionCrawler();
......
......@@ -16,6 +16,7 @@
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.LanguageServices.Implementation;
using Microsoft.VisualStudio.LanguageServices.Implementation.Interactive;
using Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService;
using Microsoft.VisualStudio.LanguageServices.Implementation.Library.FindResults;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.RuleSets;
......@@ -34,7 +35,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Setup
[Guid(Guids.RoslynPackageIdString)]
[PackageRegistration(UseManagedResourcesOnly = true)]
[ProvideMenuResource("Menus.ctmenu", version: 13)]
internal class RoslynPackage : Package
internal class RoslynPackage : AbstractPackage
{
private LibraryManager _libraryManager;
private uint _libraryManagerCookie;
......@@ -44,17 +45,10 @@ internal class RoslynPackage : Package
private RuleSetEventHandler _ruleSetEventHandler;
private IDisposable _solutionEventMonitor;
private PackageInstallerService _packageInstallerService;
private SymbolSearchService _symbolSearchService;
protected override void Initialize()
{
base.Initialize();
// Assume that we are being initialized on the UI thread at this point.
ForegroundThreadAffinitizedObject.CurrentForegroundThreadData = ForegroundThreadData.CreateDefault(defaultKind: ForcedByPackageInitialize);
Debug.Assert(ForegroundThreadAffinitizedObject.CurrentForegroundThreadData.Kind != Unknown);
FatalError.Handler = FailFast.OnFatalException;
FatalError.NonFatalHandler = WatsonReporter.Report;
......@@ -85,7 +79,7 @@ protected override void Initialize()
InitializeColors();
// load some services that have to be loaded in UI thread
LoadComponentsInUIContext();
LoadComponentsInUIContextOnceSolutionFullyLoaded();
_solutionEventMonitor = new SolutionEventMonitor(_workspace);
}
......@@ -122,33 +116,7 @@ private void InitializeColors()
CodeAnalysisColors.AccentBarColorKey = EnvironmentColors.FileTabInactiveDocumentBorderEdgeBrushKey;
}
private void LoadComponentsInUIContext()
{
if (KnownUIContexts.SolutionExistsAndFullyLoadedContext.IsActive)
{
// if we are already in the right UI context, load it right away
LoadComponents();
}
else
{
// load them when it is a right context.
KnownUIContexts.SolutionExistsAndFullyLoadedContext.UIContextChanged += OnSolutionExistsAndFullyLoadedContext;
}
}
private void OnSolutionExistsAndFullyLoadedContext(object sender, UIContextChangedEventArgs e)
{
if (e.Activated)
{
// unsubscribe from it
KnownUIContexts.SolutionExistsAndFullyLoadedContext.UIContextChanged -= OnSolutionExistsAndFullyLoadedContext;
// load components
LoadComponents();
}
}
private void LoadComponents()
protected override void LoadComponentsInUIContext()
{
// we need to load it as early as possible since we can have errors from
// package from each language very early
......@@ -167,14 +135,6 @@ private void LoadComponents()
this.ComponentModel.GetService<MiscellaneousFilesWorkspace>();
LoadAnalyzerNodeComponents();
// Ensure the nuget package services are initialized after we've loaded
// the solution.
_packageInstallerService = _workspace.Services.GetService<IPackageInstallerService>() as PackageInstallerService;
_symbolSearchService = _workspace.Services.GetService<ISymbolSearchService>() as SymbolSearchService;
_packageInstallerService?.Start();
_symbolSearchService?.Start();
Task.Run(() => LoadComponentsBackground());
}
......@@ -217,9 +177,6 @@ internal IComponentModel ComponentModel
protected override void Dispose(bool disposing)
{
_packageInstallerService?.Stop();
_symbolSearchService?.Stop();
UnregisterFindResultsLibraryManager();
DisposeVisualStudioDocumentTrackingService();
......
......@@ -70,6 +70,7 @@
<Compile Include="Implementation\Interactive\VisualBasicResetInteractiveMenuCommand.cs" />
<Compile Include="Implementation\Interop\CleanableWeakComHandleTable.cs" />
<Compile Include="Implementation\LanguageService\AbstractLanguageService`2.IVsLanguageBlock.cs" />
<Compile Include="Implementation\LanguageService\AbstractPackage.cs" />
<Compile Include="Implementation\Library\AbstractLibraryService.cs" />
<Compile Include="Implementation\Library\ClassView\AbstractSyncClassViewCommandHandler.cs" />
<Compile Include="Implementation\Library\FindResults\TreeItems\AbstractSourceTreeItem.cs" />
......
......@@ -69,16 +69,19 @@ internal partial class SymbolSearchService
private void LogException(Exception e, string text) => _logService.LogException(e, text);
internal void RegisterLanguage(string languageName)
{
this.AssertIsForeground();
_registeredLanguageNames.Add(languageName);
OnOptionChanged(null, EventArgs.Empty);
}
private void OnOptionChanged(object sender, EventArgs e)
{
var options = _workspace.Options;
if (!options.GetOption(AddImportOptions.SuggestForTypesInReferenceAssemblies, LanguageNames.CSharp) &&
!options.GetOption(AddImportOptions.SuggestForTypesInReferenceAssemblies, LanguageNames.VisualBasic) &&
!options.GetOption(AddImportOptions.SuggestForTypesInNuGetPackages, LanguageNames.CSharp) &&
!options.GetOption(AddImportOptions.SuggestForTypesInNuGetPackages, LanguageNames.VisualBasic))
// If we don't have any add-import features that would use these indices, then
// don't bother creating them.
if (!_registeredLanguageNames.Any(IsRegisteredForLanguage))
{
// If we don't have any add-import features that would use these indices, then
// don't bother creating them.
return;
}
......@@ -96,6 +99,14 @@ private void OnOptionChanged(object sender, EventArgs e)
}
}
private bool IsRegisteredForLanguage(string language)
{
var options = _workspace.Options;
return options.GetOption(AddImportOptions.SuggestForTypesInReferenceAssemblies, language) ||
options.GetOption(AddImportOptions.SuggestForTypesInNuGetPackages, language);
}
// internal for testing purposes.
internal Task UpdateSourceInBackgroundAsync(string source)
{
......
......@@ -41,7 +41,7 @@ internal partial class SymbolSearchService : ForegroundThreadAffinitizedObject,
private ConcurrentDictionary<string, IAddReferenceDatabaseWrapper> _sourceToDatabase =
new ConcurrentDictionary<string, IAddReferenceDatabaseWrapper>();
private bool _started;
private readonly List<string> _registeredLanguageNames = new List<string>();
[ImportingConstructor]
public SymbolSearchService(
......@@ -111,36 +111,44 @@ private static IRemoteControlService CreateRemoteControlService(VSShell.SVsServi
_cancellationToken = _cancellationTokenSource.Token;
}
internal void Start()
internal void Start(string languageName)
{
var options = _workspace.Options;
if (!options.GetOption(ServiceComponentOnOffOptions.SymbolSearch))
_registeredLanguageNames.Add(languageName);
if (_registeredLanguageNames.Count == 1)
{
return;
}
// When the first language registers, start the service.
var options = _workspace.Options;
if (!options.GetOption(ServiceComponentOnOffOptions.SymbolSearch))
{
return;
}
var optionsService = _workspace.Services.GetService<IOptionService>();
optionsService.OptionChanged += OnOptionChanged;
var optionsService = _workspace.Services.GetService<IOptionService>();
optionsService.OptionChanged += OnOptionChanged;
// Start the whole process once we're connected
_installerService.PackageSourcesChanged += OnOptionChanged;
// Start the whole process once we're connected
_installerService.PackageSourcesChanged += OnOptionChanged;
}
// Kick things off.
OnOptionChanged(this, EventArgs.Empty);
_started = true;
}
internal void Stop()
internal void Stop(string languageName)
{
if (!_started)
_registeredLanguageNames.Remove(languageName);
if (_registeredLanguageNames.Count == 0)
{
return;
}
// once there are no more languages registered, we can actually stop this service.
var optionsService = _workspace.Services.GetService<IOptionService>();
optionsService.OptionChanged -= OnOptionChanged;
var optionsService = _workspace.Services.GetService<IOptionService>();
optionsService.OptionChanged -= OnOptionChanged;
_installerService.PackageSourcesChanged -= OnOptionChanged;
// Cancel any existing work.
_cancellationTokenSource.Cancel();
_installerService.PackageSourcesChanged -= OnOptionChanged;
// Cancel any existing work.
_cancellationTokenSource.Cancel();
}
}
public IEnumerable<PackageWithTypeResult> FindPackagesWithType(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册