121 lines
4.4 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|