Skip to content

Commit e72a219

Browse files
committed
Replaced WorkspaceFileSystemWrapper with Get-Content and Get-ChildItem
1 parent e4b2fc4 commit e72a219

File tree

10 files changed

+105
-443
lines changed

10 files changed

+105
-443
lines changed

src/PowerShellEditorServices/Services/TextDocument/Handlers/DidChangeWatchedFilesHandler.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public Task<Unit> Handle(DidChangeWatchedFilesParams request, CancellationToken
100100
string fileContents;
101101
try
102102
{
103-
fileContents = WorkspaceService.ReadFileContents(change.Uri);
103+
fileContents = _workspaceService.ReadFileContents(change.Uri);
104104
}
105105
catch
106106
{

src/PowerShellEditorServices/Services/Workspace/WorkspaceFileSystemWrapper.cs

-363
This file was deleted.

src/PowerShellEditorServices/Services/Workspace/WorkspaceService.cs

+87-50
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
using System.Collections.Generic;
77
using System.IO;
88
using System.Linq;
9+
using System.Management.Automation;
910
using System.Security;
1011
using System.Text;
11-
using Microsoft.Extensions.FileSystemGlobbing;
12+
using System.Threading;
1213
using Microsoft.Extensions.Logging;
14+
using Microsoft.PowerShell.EditorServices.Services.PowerShell;
1315
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
14-
using Microsoft.PowerShell.EditorServices.Services.Workspace;
1516
using Microsoft.PowerShell.EditorServices.Utility;
1617
using OmniSharp.Extensions.LanguageServer.Protocol;
1718
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
@@ -84,20 +85,23 @@ internal class WorkspaceService
8485
/// </summary>
8586
public bool FollowSymlinks { get; set; }
8687

88+
private readonly IInternalPowerShellExecutionService executionService;
89+
8790
#endregion
8891

8992
#region Constructors
9093

9194
/// <summary>
9295
/// Creates a new instance of the Workspace class.
9396
/// </summary>
94-
public WorkspaceService(ILoggerFactory factory)
97+
public WorkspaceService(ILoggerFactory factory, IInternalPowerShellExecutionService executionService)
9598
{
9699
powerShellVersion = VersionUtils.PSVersion;
97100
logger = factory.CreateLogger<WorkspaceService>();
98101
WorkspaceFolders = new List<WorkspaceFolder>();
99102
ExcludeFilesGlob = new List<string>();
100103
FollowSymlinks = true;
104+
this.executionService = executionService;
101105
}
102106

103107
#endregion
@@ -139,19 +143,9 @@ public ScriptFile GetFile(DocumentUri documentUri)
139143
// Make sure the file isn't already loaded into the workspace
140144
if (!workspaceFiles.TryGetValue(keyName, out ScriptFile scriptFile))
141145
{
142-
// This method allows FileNotFoundException to bubble up
143-
// if the file isn't found.
144-
using (StreamReader streamReader = OpenStreamReader(documentUri))
145-
{
146-
scriptFile =
147-
new ScriptFile(
148-
documentUri,
149-
streamReader,
150-
powerShellVersion);
151-
152-
workspaceFiles[keyName] = scriptFile;
153-
}
154-
146+
string fileContent = ReadFileContents(documentUri);
147+
scriptFile = new ScriptFile(documentUri, fileContent, powerShellVersion);
148+
workspaceFiles[keyName] = scriptFile;
155149
logger.LogDebug("Opened file on disk: " + documentUri.ToString());
156150
}
157151

@@ -348,7 +342,6 @@ public IEnumerable<string> EnumeratePSFiles()
348342
ignoreReparsePoints: !FollowSymlinks
349343
);
350344
}
351-
352345
/// <summary>
353346
/// Enumerate all the PowerShell (ps1, psm1, psd1) files in the workspace folders in a
354347
/// recursive manner. Falls back to initial working directory if there are no workspace folders.
@@ -360,33 +353,22 @@ public IEnumerable<string> EnumeratePSFiles(
360353
int maxDepth,
361354
bool ignoreReparsePoints)
362355
{
363-
Matcher matcher = new();
364-
foreach (string pattern in includeGlobs) { matcher.AddInclude(pattern); }
365-
foreach (string pattern in excludeGlobs) { matcher.AddExclude(pattern); }
356+
PSCommand psCommand = new();
357+
psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Get-ChildItem")
358+
.AddParameter("Path", WorkspacePaths)
359+
.AddParameter("File")
360+
.AddParameter("Recurse")
361+
.AddParameter("ErrorAction", "SilentlyContinue")
362+
.AddParameter("Force")
363+
.AddParameter("Include", includeGlobs.Concat(VersionUtils.IsNetCore ? s_psFileExtensionsCoreFramework : s_psFileExtensionsFullFramework))
364+
.AddParameter("Exclude", excludeGlobs)
365+
.AddParameter("Depth", maxDepth)
366+
.AddParameter("FollowSymlink", !ignoreReparsePoints)
367+
.AddCommand("Select-Object")
368+
.AddParameter("ExpandObject", "FullName");
369+
IEnumerable<string> results = executionService.ExecutePSCommandAsync<string>(psCommand, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult();
370+
return results;
366371

367-
foreach (string rootPath in WorkspacePaths)
368-
{
369-
if (!Directory.Exists(rootPath))
370-
{
371-
continue;
372-
}
373-
374-
WorkspaceFileSystemWrapperFactory fsFactory = new(
375-
rootPath,
376-
maxDepth,
377-
VersionUtils.IsNetCore ? s_psFileExtensionsCoreFramework : s_psFileExtensionsFullFramework,
378-
ignoreReparsePoints,
379-
logger);
380-
381-
PatternMatchingResult fileMatchResult = matcher.Execute(fsFactory.RootDirectory);
382-
foreach (FilePatternMatch item in fileMatchResult.Files)
383-
{
384-
// item.Path always contains forward slashes in paths when it should be backslashes on Windows.
385-
// Since we're returning strings here, it's important to use the correct directory separator.
386-
string path = VersionUtils.IsWindows ? item.Path.Replace('/', Path.DirectorySeparatorChar) : item.Path;
387-
yield return Path.Combine(rootPath, path);
388-
}
389-
}
390372
}
391373

392374
#endregion
@@ -403,10 +385,57 @@ internal static StreamReader OpenStreamReader(DocumentUri uri)
403385
return new StreamReader(fileStream, new UTF8Encoding(), detectEncodingFromByteOrderMarks: true);
404386
}
405387

406-
internal static string ReadFileContents(DocumentUri uri)
388+
internal string ReadFileContents(DocumentUri uri)
407389
{
408-
using StreamReader reader = OpenStreamReader(uri);
409-
return reader.ReadToEnd();
390+
PSCommand psCommand = new();
391+
string pspath;
392+
if (uri.Scheme == Uri.UriSchemeFile)
393+
{
394+
pspath = uri.ToUri().LocalPath;
395+
}
396+
else
397+
{
398+
string PSProvider = uri.Authority;
399+
string path = uri.Path;
400+
pspath = $"{PSProvider}::{path}";
401+
}
402+
/* uri - "file:///c:/Users/dkattan/source/repos/immybot-ref/submodules/PowerShellEditorServices/test/PowerShellEditorServices.Test.Shared/Completion/CompletionExamples.psm1"
403+
* Authority = ""
404+
* Fragment = ""
405+
* Path = "/C:/Users/dkattan/source/repos/immybot-ref/submodules/PowerShellEditorServices/test/PowerShellEditorServices.Test.Shared/Completion/CompletionExamples.psm1"
406+
* Query = ""
407+
* Scheme = "file"
408+
* PSPath - "Microsoft.PowerShell.Core\FileSystem::C:\Users\dkattan\source\repos\immybot-ref\submodules\PowerShellEditorServices\test\PowerShellEditorServices.Test.Shared\Completion\CompletionExamples.psm1"
409+
*
410+
* Suggested Format:
411+
* Authority = "Microsoft.PowerShell.Core\FileSystem"
412+
* Scheme = "PSProvider"
413+
* Path = "/C:/Users/dkattan/source/repos/immybot-ref/submodules/PowerShellEditorServices/test/PowerShellEditorServices.Test.Shared/Completion/CompletionExamples.psm1"
414+
* Result -> "PSProvider://Microsoft.PowerShell.Core/FileSystem::C:/Users/dkattan/source/repos/immybot-ref/submodules/PowerShellEditorServices/test/PowerShellEditorServices.Test.Shared/Completion/CompletionExamples.psm1"
415+
*
416+
* Suggested Format 2:
417+
* Authority = ""
418+
* Scheme = "FileSystem"
419+
* Path = "/C:/Users/dkattan/source/repos/immybot-ref/submodules/PowerShellEditorServices/test/PowerShellEditorServices.Test.Shared/Completion/CompletionExamples.psm1"
420+
* Result "FileSystem://c:/Users/dkattan/source/repos/immybot-ref/submodules/PowerShellEditorServices/test/PowerShellEditorServices.Test.Shared/Completion/CompletionExamples.psm1"
421+
422+
*/
423+
psCommand.AddCommand("Get-Content")
424+
.AddParameter("LiteralPath", pspath)
425+
.AddParameter("Raw", true)
426+
.AddParameter("ErrorAction", ActionPreference.Stop);
427+
try
428+
{
429+
IEnumerable<string> result = executionService.ExecutePSCommandAsync<string>(psCommand, CancellationToken.None, new PowerShell.Execution.PowerShellExecutionOptions()
430+
{
431+
ThrowOnError = true
432+
}).ConfigureAwait(false).GetAwaiter().GetResult();
433+
return result.FirstOrDefault();
434+
}
435+
catch (ActionPreferenceStopException ex) when (ex.ErrorRecord.CategoryInfo.Category == ErrorCategory.ObjectNotFound && ex.ErrorRecord.TargetObject is string[] missingFiles && missingFiles.Count() == 1)
436+
{
437+
throw new FileNotFoundException(ex.ErrorRecord.ToString(), missingFiles.First(), ex.ErrorRecord.Exception);
438+
}
410439
}
411440

412441
internal string ResolveWorkspacePath(string path) => ResolveRelativeScriptPath(InitialWorkingDirectory, path);
@@ -429,10 +458,18 @@ internal string ResolveRelativeScriptPath(string baseFilePath, string relativePa
429458
// Get the directory of the original script file, combine it
430459
// with the given path and then resolve the absolute file path.
431460
combinedPath =
432-
Path.GetFullPath(
433-
Path.Combine(
434-
baseFilePath,
435-
relativePath));
461+
Path.GetFullPath(
462+
Path.Combine(
463+
baseFilePath,
464+
relativePath));
465+
466+
PSCommand psCommand = new();
467+
psCommand.AddCommand("Resolve-Path")
468+
.AddParameter("Relative", true)
469+
.AddParameter("Path", relativePath)
470+
.AddParameter("RelativeBasePath", baseFilePath);
471+
IEnumerable<string> result = executionService.ExecutePSCommandAsync<string>(psCommand, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult();
472+
combinedPath = result.FirstOrDefault();
436473
}
437474
catch (NotSupportedException e)
438475
{

test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public DebugServiceTests()
7070
debugService.DebuggerStopped += OnDebuggerStopped;
7171

7272
// Load the test debug files.
73-
workspace = new WorkspaceService(NullLoggerFactory.Instance);
73+
workspace = new WorkspaceService(NullLoggerFactory.Instance, PsesHostFactory.Create(NullLoggerFactory.Instance));
7474
debugScriptFile = GetDebugScript("DebugTest.ps1");
7575
oddPathScriptFile = GetDebugScript("Debug' W&ith $Params [Test].ps1");
7676
variableScriptFile = GetDebugScript("VariableTest.ps1");

test/PowerShellEditorServices.Test/Language/CompletionHandlerTests.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public class CompletionHandlerTests : IDisposable
3030
public CompletionHandlerTests()
3131
{
3232
psesHost = PsesHostFactory.Create(NullLoggerFactory.Instance);
33-
workspace = new WorkspaceService(NullLoggerFactory.Instance);
33+
workspace = new WorkspaceService(NullLoggerFactory.Instance, psesHost);
3434
completionHandler = new PsesCompletionHandler(NullLoggerFactory.Instance, psesHost, psesHost, workspace);
3535
}
3636

@@ -42,12 +42,12 @@ public void Dispose()
4242
GC.SuppressFinalize(this);
4343
}
4444

45-
private ScriptFile GetScriptFile(ScriptRegion scriptRegion) => workspace.GetFile(TestUtilities.GetSharedPath(scriptRegion.File));
45+
private async Task<ScriptFile> GetScriptFile(ScriptRegion scriptRegion) => workspace.GetFile(TestUtilities.GetSharedPath(scriptRegion.File));
4646

47-
private Task<CompletionResults> GetCompletionResultsAsync(ScriptRegion scriptRegion)
47+
private async Task<CompletionResults> GetCompletionResultsAsync(ScriptRegion scriptRegion)
4848
{
49-
return completionHandler.GetCompletionsInFileAsync(
50-
GetScriptFile(scriptRegion),
49+
return await completionHandler.GetCompletionsInFileAsync(
50+
await GetScriptFile(scriptRegion),
5151
scriptRegion.StartLineNumber,
5252
scriptRegion.StartColumnNumber,
5353
CancellationToken.None);

test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public class SymbolsServiceTests : IDisposable
4040
public SymbolsServiceTests()
4141
{
4242
psesHost = PsesHostFactory.Create(NullLoggerFactory.Instance);
43-
workspace = new WorkspaceService(NullLoggerFactory.Instance);
43+
workspace = new WorkspaceService(NullLoggerFactory.Instance, psesHost);
4444
workspace.WorkspaceFolders.Add(new WorkspaceFolder
4545
{
4646
Uri = DocumentUri.FromFileSystemPath(TestUtilities.GetSharedPath("References"))

test/PowerShellEditorServices.Test/Services/Symbols/AstOperationsTests.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.PowerShell.EditorServices.Services;
88
using Microsoft.PowerShell.EditorServices.Services.Symbols;
99
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
10+
using Microsoft.PowerShell.EditorServices.Test;
1011
using Microsoft.PowerShell.EditorServices.Test.Shared;
1112
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
1213
using Xunit;
@@ -20,7 +21,7 @@ public class AstOperationsTests
2021

2122
public AstOperationsTests()
2223
{
23-
WorkspaceService workspace = new(NullLoggerFactory.Instance);
24+
WorkspaceService workspace = new(NullLoggerFactory.Instance, PsesHostFactory.Create(NullLoggerFactory.Instance));
2425
scriptFile = workspace.GetFile(TestUtilities.GetSharedPath("References/FunctionReference.ps1"));
2526
}
2627

test/PowerShellEditorServices.Test/Services/Symbols/PSScriptAnalyzerTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace PowerShellEditorServices.Test.Services.Symbols
1515
[Trait("Category", "PSScriptAnalyzer")]
1616
public class PSScriptAnalyzerTests
1717
{
18-
private readonly WorkspaceService workspaceService = new(NullLoggerFactory.Instance);
18+
private readonly WorkspaceService workspaceService = new(NullLoggerFactory.Instance, PsesHostFactory.Create(NullLoggerFactory.Instance));
1919
private readonly AnalysisService analysisService;
2020
private const string script = "function Do-Work {}";
2121

test/PowerShellEditorServices.Test/Session/WorkspaceTests.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Microsoft.PowerShell.EditorServices.Utility;
1313
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
1414
using OmniSharp.Extensions.LanguageServer.Protocol;
15+
using Microsoft.PowerShell.EditorServices.Test;
1516

1617
namespace PowerShellEditorServices.Test.Session
1718
{
@@ -39,7 +40,7 @@ public void CanResolveWorkspaceRelativePath()
3940
ScriptFile testPathOutside = CreateScriptFile("c:/Test/PeerPath/FilePath.ps1");
4041
ScriptFile testPathAnotherDrive = CreateScriptFile("z:/TryAndFindMe/FilePath.ps1");
4142

42-
WorkspaceService workspace = new(NullLoggerFactory.Instance);
43+
WorkspaceService workspace = new(NullLoggerFactory.Instance, PsesHostFactory.Create(NullLoggerFactory.Instance));
4344

4445
// Test with zero workspace folders
4546
Assert.Equal(
@@ -77,7 +78,7 @@ public void CanResolveWorkspaceRelativePath()
7778

7879
internal static WorkspaceService FixturesWorkspace()
7980
{
80-
return new WorkspaceService(NullLoggerFactory.Instance)
81+
return new WorkspaceService(NullLoggerFactory.Instance, PsesHostFactory.Create(NullLoggerFactory.Instance))
8182
{
8283
WorkspaceFolders =
8384
{

test/PowerShellEditorServices.Test/packages.lock.json

+4-18
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,6 @@
1111
"Microsoft.CodeCoverage": "17.8.0"
1212
}
1313
},
14-
"Microsoft.NETFramework.ReferenceAssemblies": {
15-
"type": "Direct",
16-
"requested": "[1.0.3, )",
17-
"resolved": "1.0.3",
18-
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
19-
"dependencies": {
20-
"Microsoft.NETFramework.ReferenceAssemblies.net462": "1.0.3"
21-
}
22-
},
2314
"Microsoft.PowerShell.5.ReferenceAssemblies": {
2415
"type": "Direct",
2516
"requested": "[1.1.0, )",
@@ -183,11 +174,6 @@
183174
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
184175
}
185176
},
186-
"Microsoft.NETFramework.ReferenceAssemblies.net462": {
187-
"type": "Transitive",
188-
"resolved": "1.0.3",
189-
"contentHash": "IzAV30z22ESCeQfxP29oVf4qEo8fBGXLXSU6oacv/9Iqe6PzgHDKCaWfwMBak7bSJQM0F5boXWoZS+kChztRIQ=="
190-
},
191177
"Microsoft.TestPlatform.ObjectModel": {
192178
"type": "Transitive",
193179
"resolved": "17.8.0",
@@ -550,7 +536,7 @@
550536
"Microsoft.PowerShell.EditorServices.Test.Shared": {
551537
"type": "Project",
552538
"dependencies": {
553-
"Microsoft.PowerShell.EditorServices": "[3.16.0, )"
539+
"Microsoft.PowerShell.EditorServices": "[3.17.0, )"
554540
}
555541
}
556542
},
@@ -1691,7 +1677,7 @@
16911677
"Microsoft.PowerShell.EditorServices.Test.Shared": {
16921678
"type": "Project",
16931679
"dependencies": {
1694-
"Microsoft.PowerShell.EditorServices": "[3.16.0, )"
1680+
"Microsoft.PowerShell.EditorServices": "[3.17.0, )"
16951681
}
16961682
}
16971683
},
@@ -2820,7 +2806,7 @@
28202806
"Microsoft.PowerShell.EditorServices.Test.Shared": {
28212807
"type": "Project",
28222808
"dependencies": {
2823-
"Microsoft.PowerShell.EditorServices": "[3.16.0, )"
2809+
"Microsoft.PowerShell.EditorServices": "[3.17.0, )"
28242810
}
28252811
}
28262812
},
@@ -3948,7 +3934,7 @@
39483934
"Microsoft.PowerShell.EditorServices.Test.Shared": {
39493935
"type": "Project",
39503936
"dependencies": {
3951-
"Microsoft.PowerShell.EditorServices": "[3.16.0, )"
3937+
"Microsoft.PowerShell.EditorServices": "[3.17.0, )"
39523938
}
39533939
}
39543940
}

0 commit comments

Comments
 (0)