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
43 changes: 22 additions & 21 deletions src/VisualStudio/Core/Def/LanguageService/AbstractPackage`2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ protected override void RegisterInitializeAsyncWork(PackageLoadTasks packageInit
base.RegisterInitializeAsyncWork(packageInitializationTasks);

packageInitializationTasks.AddTask(isMainThreadTask: true, task: PackageInitializationMainThreadAsync);
packageInitializationTasks.AddTask(isMainThreadTask: false, task: PackageInitializationBackgroundThreadAsync);
}

private async Task PackageInitializationMainThreadAsync(PackageLoadTasks packageInitializationTasks, CancellationToken cancellationToken)
Expand All @@ -59,33 +58,35 @@ private async Task PackageInitializationMainThreadAsync(PackageLoadTasks package
RegisterEditorFactory(editorFactory);
}

// Misc workspace has to be up and running by the time our package is usable so that it can track running
// doc events and appropriately map files to/from it and other relevant workspaces (like the
// metadata-as-source workspace).
var miscellaneousFilesWorkspace = this.ComponentModel.GetService<MiscellaneousFilesWorkspace>();

// awaiting an IVsTask guarantees to return on the captured context
await shell.LoadPackageAsync(Guids.RoslynPackageId);
}

private Task PackageInitializationBackgroundThreadAsync(PackageLoadTasks packageInitializationTasks, CancellationToken cancellationToken)
{
RegisterLanguageService(typeof(TLanguageService), async cancellationToken =>
{
// Ensure we're on the BG when creating the language service.
await TaskScheduler.Default;

// Create the language service, tell it to set itself up, then store it in a field
// so we can notify it that it's time to clean up.
_languageService = CreateLanguageService();
await _languageService.SetupAsync(cancellationToken).ConfigureAwait(false);
packageInitializationTasks.AddTask(
isMainThreadTask: false,
task: (PackageLoadTasks packageInitializationTasks, CancellationToken cancellationToken) =>
{
RegisterLanguageService(typeof(TLanguageService), async cancellationToken =>
{
// Ensure we're on the BG when creating the language service.
await TaskScheduler.Default;

return _languageService.ComAggregate!;
});
// Create the language service, tell it to set itself up, then store it in a field
// so we can notify it that it's time to clean up.
_languageService = CreateLanguageService();
await _languageService.SetupAsync(cancellationToken).ConfigureAwait(false);

// Misc workspace has to be up and running by the time our package is usable so that it can track running
// doc events and appropriately map files to/from it and other relevant workspaces (like the
// metadata-as-source workspace).
var miscellaneousFilesWorkspace = this.ComponentModel.GetService<MiscellaneousFilesWorkspace>();
return _languageService.ComAggregate!;
});

RegisterMiscellaneousFilesWorkspaceInformation(miscellaneousFilesWorkspace);
RegisterMiscellaneousFilesWorkspaceInformation(miscellaneousFilesWorkspace);

return Task.CompletedTask;
return Task.CompletedTask;
});
}

protected override void RegisterOnAfterPackageLoadedAsyncWork(PackageLoadTasks afterPackageLoadedTasks)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IOpenText
private readonly IThreadingContext _threadingContext;
private readonly IVsService<IVsTextManager> _textManagerService;
private readonly OpenTextBufferProvider _openTextBufferProvider;
private readonly Lazy<IMetadataAsSourceFileService> _fileTrackingMetadataAsSourceService;
private readonly IMetadataAsSourceFileService _fileTrackingMetadataAsSourceService;

private readonly ConcurrentDictionary<Guid, LanguageInformation> _languageInformationByLanguageGuid = [];

Expand All @@ -47,24 +47,24 @@ internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IOpenText
/// </summary>
private readonly Dictionary<string, (ProjectId projectId, SourceTextContainer textContainer)> _monikersToProjectIdAndContainer = [];

private readonly Lazy<ImmutableArray<MetadataReference>> _metadataReferences;
private readonly ImmutableArray<MetadataReference> _metadataReferences;

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public MiscellaneousFilesWorkspace(
IThreadingContext threadingContext,
IVsService<SVsTextManager, IVsTextManager> textManagerService,
OpenTextBufferProvider openTextBufferProvider,
Lazy<IMetadataAsSourceFileService> fileTrackingMetadataAsSourceService,
Composition.ExportProvider exportProvider)
: base(VisualStudioMefHostServices.Create(exportProvider), WorkspaceKind.MiscellaneousFiles)
IMetadataAsSourceFileService fileTrackingMetadataAsSourceService,
VisualStudioWorkspace visualStudioWorkspace)
: base(visualStudioWorkspace.Services.HostServices, WorkspaceKind.MiscellaneousFiles)
{
_threadingContext = threadingContext;
_textManagerService = textManagerService;
_openTextBufferProvider = openTextBufferProvider;
_fileTrackingMetadataAsSourceService = fileTrackingMetadataAsSourceService;

_metadataReferences = new(() => [.. CreateMetadataReferences()]);
_metadataReferences = [.. CreateMetadataReferences()];

_openTextBufferProvider.AddListener(this);
}
Expand Down Expand Up @@ -122,10 +122,6 @@ public void RegisterLanguage(Guid languageGuid, string languageName, string scri

private IEnumerable<MetadataReference> CreateMetadataReferences()
{
// VisualStudioMetadataReferenceManager construction requires the main thread
// TODO: Determine if main thread affinity can be removed: https://github.com/dotnet/roslyn/issues/77791
_threadingContext.ThrowIfNotOnUIThread();

var manager = this.Services.GetService<VisualStudioMetadataReferenceManager>();
var searchPaths = VisualStudioMetadataReferenceManager.GetReferencePaths();

Expand Down Expand Up @@ -265,7 +261,7 @@ private void AttachToDocument(string moniker, ITextBuffer textBuffer)
{
_threadingContext.ThrowIfNotOnUIThread();

if (_fileTrackingMetadataAsSourceService.Value.TryAddDocumentToWorkspace(moniker, textBuffer.AsTextContainer(), out var _))
if (_fileTrackingMetadataAsSourceService.TryAddDocumentToWorkspace(moniker, textBuffer.AsTextContainer(), out var _))
{
// We already added it, so we will keep it excluded from the misc files workspace
return;
Expand All @@ -286,24 +282,20 @@ private void AttachToDocument(string moniker, ITextBuffer textBuffer)
/// </summary>
private ProjectInfo CreateProjectInfoForDocument(string filePath)
{
// Potential calculation of _metadataReferences requires being on the main thread
// TODO: Determine if main thread affinity can be removed: https://github.com/dotnet/roslyn/issues/77791
_threadingContext.ThrowIfNotOnUIThread();

// This should always succeed since we only got here if we already confirmed the moniker is acceptable
var languageInformation = TryGetLanguageInformation(filePath);
Contract.ThrowIfNull(languageInformation);

var checksumAlgorithm = SourceHashAlgorithms.Default;
var fileLoader = new WorkspaceFileTextLoader(Services.SolutionServices, filePath, defaultEncoding: null);
return MiscellaneousFileUtilities.CreateMiscellaneousProjectInfoForDocument(
this, filePath, fileLoader, languageInformation, checksumAlgorithm, Services.SolutionServices, _metadataReferences.Value);
this, filePath, fileLoader, languageInformation, checksumAlgorithm, Services.SolutionServices, _metadataReferences);
}

private void DetachFromDocument(string moniker)
{
_threadingContext.ThrowIfNotOnUIThread();
if (_fileTrackingMetadataAsSourceService.Value.TryRemoveDocumentFromWorkspace(moniker))
if (_fileTrackingMetadataAsSourceService.TryRemoveDocumentFromWorkspace(moniker))
{
return;
}
Expand Down
Loading