Skip to content

Commit 5fe03dc

Browse files
committed
Make IFileSystem a real, non-obsolete, DIed service
1 parent 78bafeb commit 5fe03dc

File tree

8 files changed

+93
-94
lines changed

8 files changed

+93
-94
lines changed

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DirectoryHelper.cs

Lines changed: 11 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Linq;
88
using Microsoft.CodeAnalysis.Razor;
99
using Microsoft.CodeAnalysis.Razor.Logging;
10+
using Microsoft.CodeAnalysis.Razor.Workspaces;
1011

1112
namespace Microsoft.AspNetCore.Razor.LanguageServer;
1213

@@ -26,33 +27,9 @@ internal static IEnumerable<string> GetFilteredFiles(
2627
string workspaceDirectory,
2728
string searchPattern,
2829
IReadOnlyCollection<string> ignoredDirectories,
29-
#pragma warning disable CS0618 // Type or member is obsolete
30-
IFileSystem? fileSystem = null,
31-
#pragma warning restore CS0618 // Type or member is obsolete
32-
ILogger? logger = null)
30+
IFileSystem fileSystem,
31+
ILogger logger)
3332
{
34-
if (workspaceDirectory is null)
35-
{
36-
throw new ArgumentNullException(nameof(workspaceDirectory));
37-
}
38-
39-
if (searchPattern is null)
40-
{
41-
throw new ArgumentNullException(nameof(searchPattern));
42-
}
43-
44-
if (ignoredDirectories is null || ignoredDirectories.Count == 0)
45-
{
46-
throw new ArgumentNullException(nameof(ignoredDirectories));
47-
}
48-
49-
if (fileSystem is null)
50-
{
51-
#pragma warning disable CS0618 // Type or member is obsolete
52-
fileSystem = new DefaultFileSystem();
53-
#pragma warning restore CS0618 // Type or member is obsolete
54-
}
55-
5633
IEnumerable<string> files;
5734
try
5835
{
@@ -62,21 +39,21 @@ internal static IEnumerable<string> GetFilteredFiles(
6239
{
6340
// The filesystem may have deleted the directory between us finding it and searching for files in it.
6441
// This can also happen if the directory is too long for windows.
65-
files = Array.Empty<string>();
42+
files = [];
6643
}
6744
catch (UnauthorizedAccessException ex)
6845
{
69-
logger?.LogWarning($"UnauthorizedAccess: {ex.Message}");
46+
logger.LogWarning($"UnauthorizedAccess: {ex.Message}");
7047
yield break;
7148
}
7249
catch (PathTooLongException ex)
7350
{
74-
logger?.LogWarning($"PathTooLong: {ex.Message}");
51+
logger.LogWarning($"PathTooLong: {ex.Message}");
7552
yield break;
7653
}
7754
catch (IOException ex)
7855
{
79-
logger?.LogWarning($"IOException: {ex.Message}");
56+
logger.LogWarning($"IOException: {ex.Message}");
8057
yield break;
8158
}
8259

@@ -94,21 +71,21 @@ internal static IEnumerable<string> GetFilteredFiles(
9471
{
9572
// The filesystem may have deleted the directory between us finding it and searching for directories in it.
9673
// This can also happen if the directory is too long for windows.
97-
directories = Array.Empty<string>();
74+
directories = [];
9875
}
9976
catch (UnauthorizedAccessException ex)
10077
{
101-
logger?.LogWarning($"UnauthorizedAccess: {ex.Message}");
78+
logger.LogWarning($"UnauthorizedAccess: {ex.Message}");
10279
yield break;
10380
}
10481
catch (PathTooLongException ex)
10582
{
106-
logger?.LogWarning($"PathTooLong: {ex.Message}");
83+
logger.LogWarning($"PathTooLong: {ex.Message}");
10784
yield break;
10885
}
10986
catch (IOException ex)
11087
{
111-
logger?.LogWarning($"IOException: {ex.Message}");
88+
logger.LogWarning($"IOException: {ex.Message}");
11289
yield break;
11390
}
11491

@@ -124,26 +101,4 @@ internal static IEnumerable<string> GetFilteredFiles(
124101
}
125102
}
126103
}
127-
128-
[Obsolete("This only exists to enable testing, do not use it outside of tests for this class")]
129-
internal interface IFileSystem
130-
{
131-
public IEnumerable<string> GetFiles(string workspaceDirectory, string searchPattern, SearchOption searchOption);
132-
133-
public IEnumerable<string> GetDirectories(string workspaceDirectory);
134-
}
135-
136-
[Obsolete("This only exists to enable testing, do not use it outside of tests for this class")]
137-
private class DefaultFileSystem : IFileSystem
138-
{
139-
public IEnumerable<string> GetFiles(string workspaceDirectory, string searchPattern, SearchOption searchOption)
140-
{
141-
return Directory.GetFiles(workspaceDirectory, searchPattern, searchOption);
142-
}
143-
144-
public IEnumerable<string> GetDirectories(string workspaceDirectory)
145-
{
146-
return Directory.GetDirectories(workspaceDirectory);
147-
}
148-
}
149104
}

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorFileChangeDetector.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
using Microsoft.AspNetCore.Razor.PooledObjects;
1414
using Microsoft.AspNetCore.Razor.Utilities;
1515
using Microsoft.CodeAnalysis.Razor;
16+
using Microsoft.CodeAnalysis.Razor.Logging;
17+
using Microsoft.CodeAnalysis.Razor.Workspaces;
1618
using Microsoft.VisualStudio.Threading;
1719

1820
namespace Microsoft.AspNetCore.Razor.LanguageServer;
@@ -30,13 +32,15 @@ internal partial class RazorFileChangeDetector : IFileChangeDetector, IDisposabl
3032
private readonly Dictionary<string, (RazorFileChangeKind kind, int index)> _filePathToChangeMap;
3133
private readonly HashSet<int> _indicesToSkip;
3234
private readonly List<FileSystemWatcher> _watchers;
35+
private readonly IFileSystem _fileSystem;
36+
private readonly ILogger _logger;
3337

34-
public RazorFileChangeDetector(IEnumerable<IRazorFileChangeListener> listeners)
35-
: this(listeners, s_delay)
38+
public RazorFileChangeDetector(IEnumerable<IRazorFileChangeListener> listeners, IFileSystem fileSystem, ILoggerFactory loggerFactory)
39+
: this(listeners, fileSystem, loggerFactory, s_delay)
3640
{
3741
}
3842

39-
protected RazorFileChangeDetector(IEnumerable<IRazorFileChangeListener> listeners, TimeSpan delay)
43+
protected RazorFileChangeDetector(IEnumerable<IRazorFileChangeListener> listeners, IFileSystem fileSystem, ILoggerFactory loggerFactory, TimeSpan delay)
4044
{
4145
_listeners = listeners.ToImmutableArray();
4246

@@ -45,6 +49,8 @@ protected RazorFileChangeDetector(IEnumerable<IRazorFileChangeListener> listener
4549
_filePathToChangeMap = new(FilePathComparer.Instance);
4650
_indicesToSkip = [];
4751
_watchers = new List<FileSystemWatcher>(s_razorFileExtensions.Length);
52+
_fileSystem = fileSystem;
53+
_logger = loggerFactory.GetOrCreateLogger<RazorFileChangeDetector>();
4854
}
4955

5056
public void Dispose()
@@ -218,7 +224,7 @@ protected virtual ImmutableArray<string> GetExistingRazorFiles(string workspaceD
218224

219225
foreach (var extension in s_razorFileExtensions)
220226
{
221-
var existingFiles = DirectoryHelper.GetFilteredFiles(workspaceDirectory, "*" + extension, s_ignoredDirectories);
227+
var existingFiles = DirectoryHelper.GetFilteredFiles(workspaceDirectory, "*" + extension, s_ignoredDirectories, _fileSystem, _logger);
222228
result.AddRange(existingFiles);
223229
}
224230

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ protected override ILspServices ConstructLspServices()
123123
services.AddSingleton(featureOptions);
124124

125125
services.AddSingleton<IFilePathService, LSPFilePathService>();
126+
services.AddSingleton<IFileSystem, FileSystem>();
126127

127128
services.AddLifeCycleServices(this, _clientConnection, _lspServerActivationTracker);
128129

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT license. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
using System.IO;
6+
7+
namespace Microsoft.CodeAnalysis.Razor.Workspaces;
8+
9+
internal class FileSystem : IFileSystem
10+
{
11+
public IEnumerable<string> GetFiles(string workspaceDirectory, string searchPattern, SearchOption searchOption)
12+
{
13+
return Directory.GetFiles(workspaceDirectory, searchPattern, searchOption);
14+
}
15+
16+
public IEnumerable<string> GetDirectories(string workspaceDirectory)
17+
{
18+
return Directory.GetDirectories(workspaceDirectory);
19+
}
20+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT license. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
using System.IO;
6+
7+
namespace Microsoft.CodeAnalysis.Razor.Workspaces;
8+
9+
internal interface IFileSystem
10+
{
11+
public IEnumerable<string> GetFiles(string workspaceDirectory, string searchPattern, SearchOption searchOption);
12+
13+
public IEnumerable<string> GetDirectories(string workspaceDirectory);
14+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT license. See License.txt in the project root for license information.
3+
4+
using System.Composition;
5+
using Microsoft.CodeAnalysis.Razor.Workspaces;
6+
7+
namespace Microsoft.CodeAnalysis.Remote.Razor;
8+
9+
[Export(typeof(IFileSystem)), Shared]
10+
internal class RemoteFileSystem : FileSystem
11+
{
12+
}

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

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT license. See License.txt in the project root for license information.
33

4-
#nullable disable
5-
6-
using System;
74
using System.Collections.Generic;
85
using System.IO;
96
using System.Linq;
107
using Microsoft.AspNetCore.Razor.LanguageServer.Completion;
8+
using Microsoft.CodeAnalysis.Razor.Workspaces;
119
using Xunit;
1210
using Xunit.Abstractions;
13-
using static Microsoft.AspNetCore.Razor.LanguageServer.DirectoryHelper;
1411

1512
namespace Microsoft.AspNetCore.Razor.LanguageServer.Test;
1613

@@ -26,24 +23,22 @@ public void GetFilteredFiles_FindsFiles()
2623
var workspaceDirectory = Path.Combine("LowerDirectory");
2724
var searchPattern = "project.razor.bin";
2825
var ignoredDirectories = new[] { "node_modules" };
29-
var fileResults = new Dictionary<string, IEnumerable<string>>() {
30-
{ "HigherDirectory", new []{ firstProjectRazorJson } },
31-
{ "RealDirectory", new []{ secondProjectRazorJson } },
32-
{ "LongDirectory", new[]{ "LONGPATH", "LONGPATH\\project.razor.bin" } },
26+
var fileResults = new Dictionary<string, string[]?>() {
27+
{ "HigherDirectory", [firstProjectRazorJson] },
28+
{ "RealDirectory", [secondProjectRazorJson] },
29+
{ "LongDirectory", ["LONGPATH", "LONGPATH\\project.razor.bin"] },
3330
{ "node_modules", null },
3431
};
35-
var directoryResults = new Dictionary<string, IEnumerable<string>>() {
36-
{ "LowerDirectory", new[]{ "HigherDirectory" } },
37-
{ "HigherDirectory", new[]{ "node_modules", "RealDirectory", "FakeDirectory", "LongDirectory" } },
32+
var directoryResults = new Dictionary<string, string[]?>() {
33+
{ "LowerDirectory", ["HigherDirectory"] },
34+
{ "HigherDirectory", ["node_modules", "RealDirectory", "FakeDirectory", "LongDirectory"] },
3835
{ "node_modules", null },
3936
};
4037

41-
#pragma warning disable CS0612 // Type or member is obsolete
4238
var fileSystem = new TestFileSystem(fileResults, directoryResults);
43-
#pragma warning restore CS0612 // Type or member is obsolete
4439

4540
// Act
46-
var files = DirectoryHelper.GetFilteredFiles(workspaceDirectory, searchPattern, ignoredDirectories, fileSystem);
41+
var files = DirectoryHelper.GetFilteredFiles(workspaceDirectory, searchPattern, ignoredDirectories, fileSystem, Logger);
4742

4843
// Assert
4944
Assert.Collection(files,
@@ -52,23 +47,13 @@ public void GetFilteredFiles_FindsFiles()
5247
);
5348
}
5449

55-
[Obsolete]
56-
private class TestFileSystem : IFileSystem
50+
private class TestFileSystem(
51+
Dictionary<string, string[]?> fileResults,
52+
Dictionary<string, string[]?> directoryResults) : IFileSystem
5753
{
58-
private readonly IDictionary<string, IEnumerable<string>> _fileResults;
59-
private readonly IDictionary<string, IEnumerable<string>> _directoryResults;
60-
61-
public TestFileSystem(
62-
IDictionary<string, IEnumerable<string>> fileResults,
63-
IDictionary<string, IEnumerable<string>> directoryResults)
64-
{
65-
_fileResults = fileResults;
66-
_directoryResults = directoryResults;
67-
}
68-
6954
public IEnumerable<string> GetDirectories(string workspaceDirectory)
7055
{
71-
var success = _directoryResults.TryGetValue(workspaceDirectory, out var results);
56+
var success = directoryResults.TryGetValue(workspaceDirectory, out var results);
7257
if (success)
7358
{
7459
if (results is null)
@@ -91,7 +76,7 @@ public IEnumerable<string> GetDirectories(string workspaceDirectory)
9176

9277
public IEnumerable<string> GetFiles(string workspaceDirectory, string searchPattern, SearchOption searchOption)
9378
{
94-
var success = _fileResults.TryGetValue(workspaceDirectory, out var results);
79+
var success = fileResults.TryGetValue(workspaceDirectory, out var results);
9580
if (success)
9681
{
9782
if (results is null)

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
using Microsoft.AspNetCore.Razor.LanguageServer.Common;
1010
using Microsoft.AspNetCore.Razor.Test.Common;
1111
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
12+
using Microsoft.CodeAnalysis.Razor.Logging;
13+
using Microsoft.CodeAnalysis.Razor.Workspaces;
1214
using Moq;
1315
using Xunit;
1416
using Xunit.Abstractions;
@@ -38,7 +40,8 @@ public async Task StartAsync_NotifiesListenersOfExistingRazorFiles()
3840
ImmutableArray<string> existingRazorFiles = ["c:/path/to/index.razor", "c:/other/path/_Host.cshtml"];
3941
using var detector = new InitializationSkippingRazorFileChangeDetector(
4042
[listenerMock1.Object, listenerMock2.Object],
41-
existingRazorFiles);
43+
existingRazorFiles,
44+
LoggerFactory);
4245

4346
// Act
4447
await detector.StartAsync("/some/workspacedirectory", DisposalToken);
@@ -79,7 +82,7 @@ internal async Task TestNotificationBehavior((string, RazorFileChangeKind)[] wor
7982
.Returns(Task.CompletedTask)
8083
.Callback((string filePath, RazorFileChangeKind kind, CancellationToken _) => actual.Add((filePath, kind)));
8184

82-
using var detector = new TestRazorFileChangeDetector([listenerMock.Object], TimeSpan.FromMilliseconds(1));
85+
using var detector = new TestRazorFileChangeDetector([listenerMock.Object], TimeSpan.FromMilliseconds(1), LoggerFactory);
8386
var detectorAccessor = detector.GetTestAccessor();
8487

8588
detectorAccessor.AddWork(work);
@@ -114,14 +117,17 @@ public static TheoryData NotificationBehaviorData
114117

115118
private class TestRazorFileChangeDetector(
116119
IEnumerable<IRazorFileChangeListener> listeners,
117-
TimeSpan delay)
118-
: RazorFileChangeDetector(listeners, delay)
120+
TimeSpan delay,
121+
ILoggerFactory loggerFactory)
122+
: RazorFileChangeDetector(listeners, new FileSystem(), loggerFactory, delay)
119123
{
120124
}
121125

122126
private class InitializationSkippingRazorFileChangeDetector(
123127
IEnumerable<IRazorFileChangeListener> listeners,
124-
ImmutableArray<string> existingProjectFiles) : RazorFileChangeDetector(listeners)
128+
ImmutableArray<string> existingProjectFiles,
129+
ILoggerFactory loggerFactory)
130+
: RazorFileChangeDetector(listeners, new FileSystem(), loggerFactory)
125131
{
126132
private readonly ImmutableArray<string> _existingProjectFiles = existingProjectFiles;
127133

0 commit comments

Comments
 (0)