Add `ProjectPathProvider` abstract for document tracker creation.
- First iteration of live share replaced the document tracker factory entirely; however, this will be prone to breaking changes in the future when me make changes to document tracker to not rely on a file path. To pre-emptively prevent breaking changes I added a project path provider that can be overridden in the live share case. Note that one big difference here between old and new is that instead of being a MEF service implementation for the project path resolution we're bringing that to the Workspace service level. - Added tests to validate the two flows of the default project path provider.
This commit is contained in:
parent
9a249ffcc1
commit
95d41507fc
|
|
@ -0,0 +1,41 @@
|
||||||
|
// 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 Microsoft.VisualStudio.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
|
{
|
||||||
|
internal class DefaultProjectPathProvider : ProjectPathProvider
|
||||||
|
{
|
||||||
|
private readonly TextBufferProjectService _projectService;
|
||||||
|
|
||||||
|
public DefaultProjectPathProvider(TextBufferProjectService projectService)
|
||||||
|
{
|
||||||
|
if (projectService == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(projectService));
|
||||||
|
}
|
||||||
|
|
||||||
|
_projectService = projectService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TryGetProjectPath(ITextBuffer textBuffer, out string filePath)
|
||||||
|
{
|
||||||
|
if (textBuffer == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(textBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
var project = _projectService.GetHostProject(textBuffer);
|
||||||
|
if (project == null)
|
||||||
|
{
|
||||||
|
filePath = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath = _projectService.GetProjectPath(project);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// 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 Microsoft.CodeAnalysis.Host;
|
||||||
|
using Microsoft.CodeAnalysis.Host.Mef;
|
||||||
|
using Microsoft.CodeAnalysis.Razor;
|
||||||
|
|
||||||
|
namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
|
{
|
||||||
|
[System.Composition.Shared]
|
||||||
|
[ExportWorkspaceService(typeof(ProjectPathProvider), ServiceLayer.Default)]
|
||||||
|
internal class DefaultProjectPathProviderFactory : IWorkspaceServiceFactory
|
||||||
|
{
|
||||||
|
private readonly TextBufferProjectService _projectService;
|
||||||
|
|
||||||
|
[ImportingConstructor]
|
||||||
|
public DefaultProjectPathProviderFactory(TextBufferProjectService projectService)
|
||||||
|
{
|
||||||
|
if (projectService == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(projectService));
|
||||||
|
}
|
||||||
|
|
||||||
|
_projectService = projectService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
|
||||||
|
{
|
||||||
|
if (workspaceServices == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(workspaceServices));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DefaultProjectPathProvider(_projectService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,8 +13,8 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
{
|
{
|
||||||
internal class DefaultVisualStudioDocumentTrackerFactory : VisualStudioDocumentTrackerFactory
|
internal class DefaultVisualStudioDocumentTrackerFactory : VisualStudioDocumentTrackerFactory
|
||||||
{
|
{
|
||||||
private readonly TextBufferProjectService _projectService;
|
|
||||||
private readonly ITextDocumentFactoryService _textDocumentFactory;
|
private readonly ITextDocumentFactoryService _textDocumentFactory;
|
||||||
|
private readonly ProjectPathProvider _projectPathProvider;
|
||||||
private readonly Workspace _workspace;
|
private readonly Workspace _workspace;
|
||||||
private readonly ImportDocumentManager _importDocumentManager;
|
private readonly ImportDocumentManager _importDocumentManager;
|
||||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
ForegroundDispatcher foregroundDispatcher,
|
ForegroundDispatcher foregroundDispatcher,
|
||||||
ProjectSnapshotManager projectManager,
|
ProjectSnapshotManager projectManager,
|
||||||
WorkspaceEditorSettings workspaceEditorSettings,
|
WorkspaceEditorSettings workspaceEditorSettings,
|
||||||
TextBufferProjectService projectService,
|
ProjectPathProvider projectPathProvider,
|
||||||
ITextDocumentFactoryService textDocumentFactory,
|
ITextDocumentFactoryService textDocumentFactory,
|
||||||
ImportDocumentManager importDocumentManager,
|
ImportDocumentManager importDocumentManager,
|
||||||
Workspace workspace)
|
Workspace workspace)
|
||||||
|
|
@ -45,9 +45,9 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
throw new ArgumentNullException(nameof(workspaceEditorSettings));
|
throw new ArgumentNullException(nameof(workspaceEditorSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (projectService == null)
|
if (projectPathProvider == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(projectService));
|
throw new ArgumentNullException(nameof(projectPathProvider));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textDocumentFactory == null)
|
if (textDocumentFactory == null)
|
||||||
|
|
@ -68,7 +68,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
_foregroundDispatcher = foregroundDispatcher;
|
_foregroundDispatcher = foregroundDispatcher;
|
||||||
_projectManager = projectManager;
|
_projectManager = projectManager;
|
||||||
_workspaceEditorSettings = workspaceEditorSettings;
|
_workspaceEditorSettings = workspaceEditorSettings;
|
||||||
_projectService = projectService;
|
_projectPathProvider = projectPathProvider;
|
||||||
_textDocumentFactory = textDocumentFactory;
|
_textDocumentFactory = textDocumentFactory;
|
||||||
_importDocumentManager = importDocumentManager;
|
_importDocumentManager = importDocumentManager;
|
||||||
_workspace = workspace;
|
_workspace = workspace;
|
||||||
|
|
@ -87,16 +87,12 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var filePath = textDocument.FilePath;
|
if (!_projectPathProvider.TryGetProjectPath(textBuffer, out var projectPath))
|
||||||
var project = _projectService.GetHostProject(textBuffer);
|
|
||||||
if (project == null)
|
|
||||||
{
|
{
|
||||||
Debug.Fail("Text buffer should belong to a project.");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectPath = _projectService.GetProjectPath(project);
|
var filePath = textDocument.FilePath;
|
||||||
|
|
||||||
var tracker = new DefaultVisualStudioDocumentTracker(_foregroundDispatcher, filePath, projectPath, _projectManager, _workspaceEditorSettings, _workspace, textBuffer, _importDocumentManager);
|
var tracker = new DefaultVisualStudioDocumentTracker(_foregroundDispatcher, filePath, projectPath, _projectManager, _workspaceEditorSettings, _workspace, textBuffer, _importDocumentManager);
|
||||||
|
|
||||||
return tracker;
|
return tracker;
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,11 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
internal class DefaultVisualStudioDocumentTrackerFactoryFactory : ILanguageServiceFactory
|
internal class DefaultVisualStudioDocumentTrackerFactoryFactory : ILanguageServiceFactory
|
||||||
{
|
{
|
||||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||||
private readonly TextBufferProjectService _projectService;
|
|
||||||
private readonly ITextDocumentFactoryService _textDocumentFactory;
|
private readonly ITextDocumentFactoryService _textDocumentFactory;
|
||||||
|
|
||||||
[ImportingConstructor]
|
[ImportingConstructor]
|
||||||
public DefaultVisualStudioDocumentTrackerFactoryFactory(
|
public DefaultVisualStudioDocumentTrackerFactoryFactory(
|
||||||
ForegroundDispatcher foregroundDispatcher,
|
ForegroundDispatcher foregroundDispatcher,
|
||||||
TextBufferProjectService projectService,
|
|
||||||
ITextDocumentFactoryService textDocumentFactory)
|
ITextDocumentFactoryService textDocumentFactory)
|
||||||
{
|
{
|
||||||
if (foregroundDispatcher == null)
|
if (foregroundDispatcher == null)
|
||||||
|
|
@ -31,18 +29,12 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (projectService == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(projectService));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (textDocumentFactory == null)
|
if (textDocumentFactory == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(textDocumentFactory));
|
throw new ArgumentNullException(nameof(textDocumentFactory));
|
||||||
}
|
}
|
||||||
|
|
||||||
_foregroundDispatcher = foregroundDispatcher;
|
_foregroundDispatcher = foregroundDispatcher;
|
||||||
_projectService = projectService;
|
|
||||||
_textDocumentFactory = textDocumentFactory;
|
_textDocumentFactory = textDocumentFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,11 +49,13 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
var workspaceEditorSettings = languageServices.GetRequiredService<WorkspaceEditorSettings>();
|
var workspaceEditorSettings = languageServices.GetRequiredService<WorkspaceEditorSettings>();
|
||||||
var importDocumentManager = languageServices.GetRequiredService<ImportDocumentManager>();
|
var importDocumentManager = languageServices.GetRequiredService<ImportDocumentManager>();
|
||||||
|
|
||||||
|
var projectPathProvider = languageServices.WorkspaceServices.GetRequiredService<ProjectPathProvider>();
|
||||||
|
|
||||||
return new DefaultVisualStudioDocumentTrackerFactory(
|
return new DefaultVisualStudioDocumentTrackerFactory(
|
||||||
_foregroundDispatcher,
|
_foregroundDispatcher,
|
||||||
projectManager,
|
projectManager,
|
||||||
workspaceEditorSettings,
|
workspaceEditorSettings,
|
||||||
_projectService,
|
projectPathProvider,
|
||||||
_textDocumentFactory,
|
_textDocumentFactory,
|
||||||
importDocumentManager,
|
importDocumentManager,
|
||||||
languageServices.WorkspaceServices.Workspace);
|
languageServices.WorkspaceServices.Workspace);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// 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 Microsoft.CodeAnalysis.Host;
|
||||||
|
using Microsoft.VisualStudio.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
|
{
|
||||||
|
internal abstract class ProjectPathProvider : IWorkspaceService
|
||||||
|
{
|
||||||
|
public abstract bool TryGetProjectPath(ITextBuffer textBuffer, out string filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
// 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 Microsoft.VisualStudio.Text;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.VisualStudio.Editor.Razor
|
||||||
|
{
|
||||||
|
public class DefaultProjectPathProviderTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void TryGetProjectPath_ReturnsFalseIfNoProject()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var projectPathProvider = new DefaultProjectPathProvider(Mock.Of<TextBufferProjectService>());
|
||||||
|
var textBuffer = Mock.Of<ITextBuffer>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = projectPathProvider.TryGetProjectPath(textBuffer, out var filePath);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(result);
|
||||||
|
Assert.Null(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetProjectPath_ReturnsTrueIfProject()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expectedProjectPath = "/my/project/path.csproj";
|
||||||
|
var projectService = new Mock<TextBufferProjectService>();
|
||||||
|
projectService.Setup(service => service.GetHostProject(It.IsAny<ITextBuffer>()))
|
||||||
|
.Returns(new object());
|
||||||
|
projectService.Setup(service => service.GetProjectPath(It.IsAny<object>()))
|
||||||
|
.Returns(expectedProjectPath);
|
||||||
|
var projectPathProvider = new DefaultProjectPathProvider(projectService.Object);
|
||||||
|
var textBuffer = Mock.Of<ITextBuffer>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = projectPathProvider.TryGetProjectPath(textBuffer, out var filePath);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.Equal(expectedProjectPath, filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue