aspnetcore/src/Microsoft.VisualStudio.Lang.../DefaultVisualStudioWorkspac...

121 lines
4.4 KiB
C#

// Copyright (c) .NET Foundation. 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.ComponentModel.Composition;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Editor.Razor;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Projection;
namespace Microsoft.VisualStudio.LanguageServices.Razor
{
[System.Composition.Shared]
[Export(typeof(VisualStudioWorkspaceAccessor))]
internal class DefaultVisualStudioWorkspaceAccessor : VisualStudioWorkspaceAccessor
{
private readonly IBufferGraphFactoryService _bufferGraphService;
private readonly TextBufferProjectService _projectService;
private readonly Workspace _defaultWorkspace;
[ImportingConstructor]
public DefaultVisualStudioWorkspaceAccessor(
IBufferGraphFactoryService bufferGraphService,
TextBufferProjectService projectService,
[Import(typeof(VisualStudioWorkspace))] Workspace defaultWorkspace)
{
if (bufferGraphService == null)
{
throw new ArgumentNullException(nameof(bufferGraphService));
}
if (projectService == null)
{
throw new ArgumentNullException(nameof(projectService));
}
if (defaultWorkspace == null)
{
throw new ArgumentNullException(nameof(defaultWorkspace));
}
_bufferGraphService = bufferGraphService;
_projectService = projectService;
_defaultWorkspace = defaultWorkspace;
}
public override Workspace Workspace => _defaultWorkspace;
public override bool TryGetWorkspace(ITextBuffer textBuffer, out Workspace workspace)
{
if (textBuffer == null)
{
throw new ArgumentNullException(nameof(textBuffer));
}
// We do a best effort approach in this method to get the workspace that belongs to the TextBuffer.
// The approaches we take to find the workspace are:
//
// 1. Look for a C# projection buffer associated with the Razor buffer. If we can find one we let
// Roslyn take control of finding the Workspace (projectionBuffer.GetWorkspace()). If not,
// fall back to determining if we can use the default workspace.
// 2. Look to see if this ITextBuffer is associated with a host project. If we find that our Razor
// buffer has a host project, we make the assumption that we should use the default VisualStudioWorkspace.
if (TryGetWorkspaceFromProjectionBuffer(textBuffer, out workspace))
{
return true;
}
if (TryGetWorkspaceFromHostProject(textBuffer, out workspace))
{
return true;
}
workspace = null;
return false;
}
// Internal virtual for testing
internal virtual bool TryGetWorkspaceFromProjectionBuffer(ITextBuffer textBuffer, out Workspace workspace)
{
var graph = _bufferGraphService.CreateBufferGraph(textBuffer);
var projectedCSharpBuffer = graph.GetTextBuffers(buffer => buffer.ContentType.IsOfType("CSharp")).FirstOrDefault();
if (projectedCSharpBuffer == null)
{
workspace = null;
return false;
}
workspace = projectedCSharpBuffer.GetWorkspace();
if (workspace == null)
{
// Couldn't resolve a workspace for the projected csharp buffer.
return false;
}
return true;
}
// Internal virtual for testing
internal virtual bool TryGetWorkspaceFromHostProject(ITextBuffer textBuffer, out Workspace workspace)
{
var project = _projectService.GetHostProject(textBuffer);
if (project == null)
{
// Could not locate a project for the given text buffer.
workspace = null;
return false;
}
// We have a host project, assume default workspace.
workspace = _defaultWorkspace;
return true;
}
}
}