Prevent Razor Core from running in non-core scenarios.

- Also added tests.

#1776
This commit is contained in:
N. Taylor Mullen 2017-11-16 13:16:36 -08:00
parent fa2d79296a
commit 4f7aab7720
3 changed files with 81 additions and 5 deletions

View File

@ -16,6 +16,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
[Export(typeof(TextBufferProjectService))] [Export(typeof(TextBufferProjectService))]
internal class DefaultTextBufferProjectService : TextBufferProjectService internal class DefaultTextBufferProjectService : TextBufferProjectService
{ {
private const string DotNetCoreCapability = "(CSharp|VB)&CPS";
private readonly RunningDocumentTable _documentTable; private readonly RunningDocumentTable _documentTable;
private readonly ITextDocumentFactoryService _documentFactory; private readonly ITextDocumentFactoryService _documentFactory;
@ -79,7 +81,20 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
throw new ArgumentNullException(nameof(hierarchy)); throw new ArgumentNullException(nameof(hierarchy));
} }
return hierarchy.IsCapabilityMatch("DotNetCoreWeb"); try
{
return hierarchy.IsCapabilityMatch(DotNetCoreCapability);
}
catch (NotSupportedException)
{
// IsCapabilityMatch throws a NotSupportedException if it can't create a BooleanSymbolExpressionEvaluator COM object
}
catch (ObjectDisposedException)
{
// IsCapabilityMatch throws an ObjectDisposedException if the underlying hierarchy has been disposed.
}
return false;
} }
} }
} }

View File

@ -8,6 +8,8 @@ using System.Diagnostics;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor;
using Microsoft.VisualStudio.Editor.Razor; using Microsoft.VisualStudio.Editor.Razor;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Utilities; using Microsoft.VisualStudio.Utilities;
@ -20,14 +22,21 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
internal class RazorTextViewConnectionListener : IWpfTextViewConnectionListener internal class RazorTextViewConnectionListener : IWpfTextViewConnectionListener
{ {
private readonly ForegroundDispatcher _foregroundDispatcher; private readonly ForegroundDispatcher _foregroundDispatcher;
private readonly TextBufferProjectService _projectService;
private readonly RazorEditorFactoryService _editorFactoryService; private readonly RazorEditorFactoryService _editorFactoryService;
private readonly Workspace _workspace; private readonly Workspace _workspace;
[ImportingConstructor] [ImportingConstructor]
public RazorTextViewConnectionListener( public RazorTextViewConnectionListener(
TextBufferProjectService projectService,
RazorEditorFactoryService editorFactoryService, RazorEditorFactoryService editorFactoryService,
[Import(typeof(VisualStudioWorkspace))] Workspace workspace) [Import(typeof(VisualStudioWorkspace))] Workspace workspace)
{ {
if (projectService == null)
{
throw new ArgumentNullException(nameof(projectService));
}
if (editorFactoryService == null) if (editorFactoryService == null)
{ {
throw new ArgumentNullException(nameof(editorFactoryService)); throw new ArgumentNullException(nameof(editorFactoryService));
@ -38,6 +47,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
throw new ArgumentNullException(nameof(workspace)); throw new ArgumentNullException(nameof(workspace));
} }
_projectService = projectService;
_editorFactoryService = editorFactoryService; _editorFactoryService = editorFactoryService;
_workspace = workspace; _workspace = workspace;
@ -47,6 +57,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
// This is only for testing. We want to avoid using the actual Roslyn GetService methods in unit tests. // This is only for testing. We want to avoid using the actual Roslyn GetService methods in unit tests.
internal RazorTextViewConnectionListener( internal RazorTextViewConnectionListener(
ForegroundDispatcher foregroundDispatcher, ForegroundDispatcher foregroundDispatcher,
TextBufferProjectService projectService,
RazorEditorFactoryService editorFactoryService, RazorEditorFactoryService editorFactoryService,
[Import(typeof(VisualStudioWorkspace))] Workspace workspace) [Import(typeof(VisualStudioWorkspace))] Workspace workspace)
{ {
@ -55,6 +66,11 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
throw new ArgumentNullException(nameof(foregroundDispatcher)); throw new ArgumentNullException(nameof(foregroundDispatcher));
} }
if (projectService == null)
{
throw new ArgumentNullException(nameof(projectService));
}
if (editorFactoryService == null) if (editorFactoryService == null)
{ {
throw new ArgumentNullException(nameof(editorFactoryService)); throw new ArgumentNullException(nameof(editorFactoryService));
@ -66,6 +82,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
} }
_foregroundDispatcher = foregroundDispatcher; _foregroundDispatcher = foregroundDispatcher;
_projectService = projectService;
_editorFactoryService = editorFactoryService; _editorFactoryService = editorFactoryService;
_workspace = workspace; _workspace = workspace;
} }
@ -94,6 +111,12 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
continue; continue;
} }
var hierarchy = _projectService.GetHierarchy(textBuffer);
if (!_projectService.IsSupportedProject(hierarchy))
{
return;
}
if (!_editorFactoryService.TryGetDocumentTracker(textBuffer, out var documentTracker) || if (!_editorFactoryService.TryGetDocumentTracker(textBuffer, out var documentTracker) ||
!(documentTracker is DefaultVisualStudioDocumentTracker tracker)) !(documentTracker is DefaultVisualStudioDocumentTracker tracker))
{ {

View File

@ -34,12 +34,32 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
private IContentType NonRazorContentType { get; } = Mock.Of<IContentType>(c => c.IsOfType(It.IsAny<string>()) == false); private IContentType NonRazorContentType { get; } = Mock.Of<IContentType>(c => c.IsOfType(It.IsAny<string>()) == false);
private TextBufferProjectService SupportedProjectService { get; } = Mock.Of<TextBufferProjectService>(s => s.IsSupportedProject(It.IsAny<IVsHierarchy>()) == true);
private TextBufferProjectService UnsupportedProjectService { get; } = Mock.Of<TextBufferProjectService>(s => s.IsSupportedProject(It.IsAny<IVsHierarchy>()) == false);
[ForegroundFact]
public void SubjectBuffersConnected_ForNonRazorCoreProject_DoesNothing()
{
// Arrange
var editorFactoryService = new Mock<RazorEditorFactoryService>(MockBehavior.Strict);
var factory = new RazorTextViewConnectionListener(Dispatcher, UnsupportedProjectService, editorFactoryService.Object, Workspace);
var textView = Mock.Of<IWpfTextView>();
var buffers = new Collection<ITextBuffer>()
{
Mock.Of<ITextBuffer>(b => b.ContentType == RazorContentType && b.Properties == new PropertyCollection()),
};
// Act & Assert
factory.SubjectBuffersConnected(textView, ConnectionReason.BufferGraphChange, buffers);
}
[ForegroundFact] [ForegroundFact]
public void SubjectBuffersConnected_ForNonRazorTextBuffer_DoesNothing() public void SubjectBuffersConnected_ForNonRazorTextBuffer_DoesNothing()
{ {
// Arrange // Arrange
var editorFactoryService = new Mock<RazorEditorFactoryService>(MockBehavior.Strict); var editorFactoryService = new Mock<RazorEditorFactoryService>(MockBehavior.Strict);
var factory = new RazorTextViewConnectionListener(Dispatcher, editorFactoryService.Object, Workspace); var factory = new RazorTextViewConnectionListener(Dispatcher, SupportedProjectService, editorFactoryService.Object, Workspace);
var textView = Mock.Of<IWpfTextView>(); var textView = Mock.Of<IWpfTextView>();
var buffers = new Collection<ITextBuffer>() var buffers = new Collection<ITextBuffer>()
{ {
@ -61,7 +81,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
}; };
VisualStudioDocumentTracker documentTracker = new DefaultVisualStudioDocumentTracker("AFile", ProjectManager, ProjectService, EditorSettingsManager, Workspace, buffers[0]); VisualStudioDocumentTracker documentTracker = new DefaultVisualStudioDocumentTracker("AFile", ProjectManager, ProjectService, EditorSettingsManager, Workspace, buffers[0]);
var editorFactoryService = Mock.Of<RazorEditorFactoryService>(factoryService => factoryService.TryGetDocumentTracker(It.IsAny<ITextBuffer>(), out documentTracker) == true); var editorFactoryService = Mock.Of<RazorEditorFactoryService>(factoryService => factoryService.TryGetDocumentTracker(It.IsAny<ITextBuffer>(), out documentTracker) == true);
var textViewListener = new RazorTextViewConnectionListener(Dispatcher, editorFactoryService, Workspace); var textViewListener = new RazorTextViewConnectionListener(Dispatcher, SupportedProjectService, editorFactoryService, Workspace);
// Act // Act
textViewListener.SubjectBuffersConnected(textView, ConnectionReason.BufferGraphChange, buffers); textViewListener.SubjectBuffersConnected(textView, ConnectionReason.BufferGraphChange, buffers);
@ -93,7 +113,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
tracker.AddTextView(textView1); tracker.AddTextView(textView1);
tracker.AddTextView(textView2); tracker.AddTextView(textView2);
buffers[1].Properties.AddProperty(typeof(VisualStudioDocumentTracker), tracker); buffers[1].Properties.AddProperty(typeof(VisualStudioDocumentTracker), tracker);
var textViewListener = new RazorTextViewConnectionListener(Dispatcher, Mock.Of<RazorEditorFactoryService>(), Workspace); var textViewListener = new RazorTextViewConnectionListener(Dispatcher, SupportedProjectService, Mock.Of<RazorEditorFactoryService>(), Workspace);
// Act // Act
textViewListener.SubjectBuffersDisconnected(textView2, ConnectionReason.BufferGraphChange, buffers); textViewListener.SubjectBuffersDisconnected(textView2, ConnectionReason.BufferGraphChange, buffers);
@ -106,11 +126,29 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Editor
Assert.Collection(tracker.TextViews, v => Assert.Same(v, textView1)); Assert.Collection(tracker.TextViews, v => Assert.Same(v, textView1));
} }
[ForegroundFact]
public void SubjectBuffersDisconnected_FoNonRazorCoreProject_DoesNothing()
{
// Arrange
var textViewListener = new RazorTextViewConnectionListener(Dispatcher, UnsupportedProjectService, Mock.Of<RazorEditorFactoryService>(), Workspace);
var textView = Mock.Of<IWpfTextView>();
var buffers = new Collection<ITextBuffer>()
{
Mock.Of<ITextBuffer>(b => b.ContentType == RazorContentType && b.Properties == new PropertyCollection()),
};
// Act
textViewListener.SubjectBuffersDisconnected(textView, ConnectionReason.BufferGraphChange, buffers);
// Assert
Assert.False(buffers[0].Properties.ContainsProperty(typeof(VisualStudioDocumentTracker)));
}
[ForegroundFact] [ForegroundFact]
public void SubjectBuffersDisconnected_ForAnyTextBufferWithoutTracker_DoesNothing() public void SubjectBuffersDisconnected_ForAnyTextBufferWithoutTracker_DoesNothing()
{ {
// Arrange // Arrange
var textViewListener = new RazorTextViewConnectionListener(Dispatcher, Mock.Of<RazorEditorFactoryService>(), Workspace); var textViewListener = new RazorTextViewConnectionListener(Dispatcher, SupportedProjectService, Mock.Of<RazorEditorFactoryService>(), Workspace);
var textView = Mock.Of<IWpfTextView>(); var textView = Mock.Of<IWpfTextView>();