Skip to content

Commit ada06d2

Browse files
committed
Only monitor individual configuration paths, rather than the whole workspace, in Visual Studio
1 parent 87f6e7a commit ada06d2

File tree

4 files changed

+61
-36
lines changed

4 files changed

+61
-36
lines changed

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,13 @@ public static void AddDocumentManagementServices(this IServiceCollection service
210210
services.AddSingleton<IProjectConfigurationFileChangeListener, ProjectConfigurationStateSynchronizer>();
211211
services.AddSingleton<IRazorFileChangeListener, RazorFileSynchronizer>();
212212

213-
// File Change detectors
214-
services.AddSingleton<IFileChangeDetector, ProjectConfigurationFileChangeDetector>();
213+
// If we're not monitoring the whole workspace folder for configuration changes, then we don't actually need the the file change
214+
// detector wired up via DI, as the razor/monitorProjectConfigurationFilePath endpoint will directly construct one. This means
215+
// it can be a little simpler, and doesn't need to worry about which folders it's told to listen to.
216+
if (featureOptions.MonitorWorkspaceFolderForConfigurationFiles)
217+
{
218+
services.AddSingleton<IFileChangeDetector, ProjectConfigurationFileChangeDetector>();
219+
}
215220
services.AddSingleton<IFileChangeDetector, RazorFileChangeDetector>();
216221

217222
// Document processed listeners

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/MonitorProjectConfigurationFilePathEndpoint.cs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -84,28 +84,31 @@ public async Task HandleNotificationAsync(MonitorProjectConfigurationFilePathPar
8484
}
8585

8686
var configurationDirectory = Path.GetDirectoryName(request.ConfigurationFilePath);
87-
var normalizedConfigurationDirectory = FilePathNormalizer.NormalizeDirectory(configurationDirectory);
88-
var workspaceDirectory = _workspaceDirectoryPathResolver.Resolve();
89-
var normalizedWorkspaceDirectory = FilePathNormalizer.NormalizeDirectory(workspaceDirectory);
90-
9187
Assumes.NotNull(configurationDirectory);
9288

9389
var previousMonitorExists = _outputPathMonitors.TryGetValue(request.ProjectKeyId, out var entry);
9490

95-
if (normalizedConfigurationDirectory.StartsWith(normalizedWorkspaceDirectory, FilePathComparison.Instance))
91+
if (_options.MonitorWorkspaceFolderForConfigurationFiles)
9692
{
97-
if (previousMonitorExists)
98-
{
99-
_logger.LogInformation("Configuration directory changed from external directory -> internal directory for project '{0}, terminating existing monitor'.", request.ProjectKeyId);
100-
RemoveMonitor(request.ProjectKeyId);
101-
}
102-
else
93+
var normalizedConfigurationDirectory = FilePathNormalizer.NormalizeDirectory(configurationDirectory);
94+
var workspaceDirectory = _workspaceDirectoryPathResolver.Resolve();
95+
var normalizedWorkspaceDirectory = FilePathNormalizer.NormalizeDirectory(workspaceDirectory);
96+
97+
if (normalizedConfigurationDirectory.StartsWith(normalizedWorkspaceDirectory, FilePathComparison.Instance))
10398
{
104-
_logger.LogInformation("No custom configuration directory required. The workspace directory is sufficient for '{0}'.", request.ProjectKeyId);
99+
if (previousMonitorExists)
100+
{
101+
_logger.LogInformation("Configuration directory changed from external directory -> internal directory for project '{0}, terminating existing monitor'.", request.ProjectKeyId);
102+
RemoveMonitor(request.ProjectKeyId);
103+
}
104+
else
105+
{
106+
_logger.LogInformation("No custom configuration directory required. The workspace directory is sufficient for '{0}'.", request.ProjectKeyId);
107+
}
108+
109+
// Configuration directory is already in the workspace directory. We already monitor everything in the workspace directory.
110+
return;
105111
}
106-
107-
// Configuration directory is already in the workspace directory. We already monitor everything in the workspace directory.
108-
return;
109112
}
110113

111114
if (previousMonitorExists)

src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/MonitorProjectConfigurationFilePathEndpointTest.cs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem;
1212
using Microsoft.AspNetCore.Razor.Test.Common;
1313
using Microsoft.CodeAnalysis.Razor;
14+
using Microsoft.CodeAnalysis.Razor.Workspaces;
1415
using Microsoft.Extensions.Logging;
1516
using Moq;
1617
using Xunit;
@@ -135,6 +136,32 @@ public async Task Handle_InWorkspaceDirectory_Noops()
135136
Assert.Equal(0, detector.StartCount);
136137
}
137138

139+
[Fact]
140+
public async Task Handle_InWorkspaceDirectory_MonitorsIfLanguageFeatureOptionSet()
141+
{
142+
// Arrange
143+
var detector = new TestFileChangeDetector();
144+
var configurationFileEndpoint = new TestMonitorProjectConfigurationFilePathEndpoint(
145+
() => detector,
146+
LegacyDispatcher,
147+
_directoryPathResolver,
148+
Enumerable.Empty<IProjectConfigurationFileChangeListener>(),
149+
LoggerFactory,
150+
options: new TestLanguageServerFeatureOptions(monitorWorkspaceFolderForConfigurationFiles: false));
151+
var startRequest = new MonitorProjectConfigurationFilePathParams()
152+
{
153+
ProjectKeyId = TestProjectKey.Create("C:/dir/obj").Id,
154+
ConfigurationFilePath = "C:/dir/obj/Debug/project.razor.bin",
155+
};
156+
var requestContext = CreateRazorRequestContext(documentContext: null);
157+
158+
// Act
159+
await configurationFileEndpoint.HandleNotificationAsync(startRequest, requestContext, DisposalToken);
160+
161+
// Assert
162+
Assert.Equal(1, detector.StartCount);
163+
}
164+
138165
[Fact]
139166
public async Task Handle_DuplicateMonitors_Noops()
140167
{
@@ -323,31 +350,18 @@ private class TestMonitorProjectConfigurationFilePathEndpoint : MonitorProjectCo
323350
{
324351
private readonly Func<IFileChangeDetector> _fileChangeDetectorFactory;
325352

326-
public TestMonitorProjectConfigurationFilePathEndpoint(
327-
ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher,
328-
WorkspaceDirectoryPathResolver workspaceDirectoryPathResolver,
329-
IEnumerable<IProjectConfigurationFileChangeListener> listeners,
330-
ILoggerFactory loggerFactory)
331-
: this(
332-
fileChangeDetectorFactory: null,
333-
projectSnapshotManagerDispatcher,
334-
workspaceDirectoryPathResolver,
335-
listeners,
336-
loggerFactory)
337-
{
338-
}
339-
340353
public TestMonitorProjectConfigurationFilePathEndpoint(
341354
Func<IFileChangeDetector> fileChangeDetectorFactory,
342355
ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher,
343356
WorkspaceDirectoryPathResolver workspaceDirectoryPathResolver,
344357
IEnumerable<IProjectConfigurationFileChangeListener> listeners,
345-
ILoggerFactory loggerFactory)
358+
ILoggerFactory loggerFactory,
359+
LanguageServerFeatureOptions? options = null)
346360
: base(
347361
projectSnapshotManagerDispatcher,
348362
workspaceDirectoryPathResolver,
349363
listeners,
350-
TestLanguageServerFeatureOptions.Instance,
364+
options ?? TestLanguageServerFeatureOptions.Instance,
351365
loggerFactory)
352366
{
353367
_fileChangeDetectorFactory = fileChangeDetectorFactory ?? (() => Mock.Of<IFileChangeDetector>(MockBehavior.Strict));

src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test.Common/TestLanguageServerFeatureOptions.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ internal class TestLanguageServerFeatureOptions : LanguageServerFeatureOptions
99
{
1010
public static readonly LanguageServerFeatureOptions Instance = new TestLanguageServerFeatureOptions();
1111

12-
private bool _includeProjectKeyInGeneratedFilePath;
12+
private readonly bool _includeProjectKeyInGeneratedFilePath;
13+
private readonly bool _monitorWorkspaceFolderForConfigurationFiles;
1314

1415
public TestLanguageServerFeatureOptions(
15-
bool includeProjectKeyInGeneratedFilePath = false)
16+
bool includeProjectKeyInGeneratedFilePath = false,
17+
bool monitorWorkspaceFolderForConfigurationFiles = true)
1618
{
1719
_includeProjectKeyInGeneratedFilePath = includeProjectKeyInGeneratedFilePath;
20+
_monitorWorkspaceFolderForConfigurationFiles = monitorWorkspaceFolderForConfigurationFiles;
1821
}
1922

2023
public override bool SupportsFileManipulation => false;
@@ -41,5 +44,5 @@ public TestLanguageServerFeatureOptions(
4144

4245
public override bool IncludeProjectKeyInGeneratedFilePath => _includeProjectKeyInGeneratedFilePath;
4346

44-
public override bool MonitorWorkspaceFolderForConfigurationFiles => true;
47+
public override bool MonitorWorkspaceFolderForConfigurationFiles => _monitorWorkspaceFolderForConfigurationFiles;
4548
}

0 commit comments

Comments
 (0)