Skip to content

Commit 29617f8

Browse files
committed
Add workspace path information to psEditor.Workspace API
This change adds a new Path property to the EditorWorkspace class which gets exposed through to the psEditor API. This is useful for extension authors who want to perform operations based on the workspace path. Resolves #236.
1 parent 56a0ebd commit 29617f8

File tree

8 files changed

+123
-1
lines changed

8 files changed

+123
-1
lines changed

src/PowerShellEditorServices.Protocol/Server/LanguageServerEditorOperations.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using Microsoft.PowerShell.EditorServices.Protocol.LanguageServer;
88
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
99
using System.Threading.Tasks;
10-
using System;
1110

1211
namespace Microsoft.PowerShell.EditorServices.Protocol.Server
1312
{
@@ -111,6 +110,16 @@ public Task OpenFile(string filePath)
111110
true);
112111
}
113112

113+
public string GetWorkspacePath()
114+
{
115+
return this.editorSession.Workspace.WorkspacePath;
116+
}
117+
118+
public string GetWorkspaceRelativePath(string filePath)
119+
{
120+
return this.editorSession.Workspace.GetRelativePath(filePath);
121+
}
122+
114123
public Task ShowInformationMessage(string message)
115124
{
116125
return

src/PowerShellEditorServices/Extensions/EditorWorkspace.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ public class EditorWorkspace
1717

1818
#endregion
1919

20+
#region Properties
21+
22+
/// <summary>
23+
/// Gets the current workspace path if there is one or null otherwise.
24+
/// </summary>
25+
public string Path
26+
{
27+
get { return this.editorOperations.GetWorkspacePath(); }
28+
}
29+
30+
#endregion
31+
2032
#region Constructors
2133

2234
internal EditorWorkspace(IEditorOperations editorOperations)

src/PowerShellEditorServices/Extensions/FileContext.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ public string Path
3232
get { return this.scriptFile.FilePath; }
3333
}
3434

35+
/// <summary>
36+
/// Gets the workspace-relative path of the file.
37+
/// </summary>
38+
public string WorkspacePath
39+
{
40+
get
41+
{
42+
return
43+
this.editorOperations.GetWorkspaceRelativePath(
44+
this.scriptFile.FilePath);
45+
}
46+
}
47+
3548
/// <summary>
3649
/// Gets the parsed abstract syntax tree for the file.
3750
/// </summary>

src/PowerShellEditorServices/Extensions/IEditorOperations.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ public interface IEditorOperations
2020
/// <returns>A new EditorContext object.</returns>
2121
Task<EditorContext> GetEditorContext();
2222

23+
/// <summary>
24+
/// Gets the path to the editor's active workspace.
25+
/// </summary>
26+
/// <returns>The workspace path or null if there isn't one.</returns>
27+
string GetWorkspacePath();
28+
29+
/// <summary>
30+
/// Resolves the given file path relative to the current workspace path.
31+
/// </summary>
32+
/// <param name="filePath">The file path to be resolved.</param>
33+
/// <returns>The resolved file path.</returns>
34+
string GetWorkspaceRelativePath(string filePath);
35+
2336
/// <summary>
2437
/// Causes a file to be opened in the editor. If the file is
2538
/// already open, the editor must switch to the file.

src/PowerShellEditorServices/Workspace/Workspace.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,32 @@ public ScriptFile[] ExpandScriptReferences(ScriptFile scriptFile)
176176
return expandedReferences.ToArray();
177177
}
178178

179+
/// <summary>
180+
/// Gets the workspace-relative path of the given file path.
181+
/// </summary>
182+
/// <param name="filePath">The original full file path.</param>
183+
/// <returns>A relative file path</returns>
184+
public string GetRelativePath(string filePath)
185+
{
186+
string resolvedPath = filePath;
187+
188+
if (!IsPathInMemory(filePath) && !string.IsNullOrEmpty(this.WorkspacePath))
189+
{
190+
Uri workspaceUri = new Uri(this.WorkspacePath);
191+
Uri fileUri = new Uri(filePath);
192+
193+
resolvedPath = workspaceUri.MakeRelativeUri(fileUri).ToString();
194+
195+
// Convert the directory separators if necessary
196+
if (System.IO.Path.DirectorySeparatorChar == '\\')
197+
{
198+
resolvedPath = resolvedPath.Replace('/', '\\');
199+
}
200+
}
201+
202+
return resolvedPath;
203+
}
204+
179205
#endregion
180206

181207
#region Private Methods

test/PowerShellEditorServices.Test/Extensions/ExtensionServiceTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,16 @@ await this.extensionEventQueue.EnqueueAsync(
168168

169169
public class TestEditorOperations : IEditorOperations
170170
{
171+
public string GetWorkspacePath()
172+
{
173+
throw new NotImplementedException();
174+
}
175+
176+
public string GetWorkspaceRelativePath(string filePath)
177+
{
178+
throw new NotImplementedException();
179+
}
180+
171181
public Task OpenFile(string filePath)
172182
{
173183
throw new NotImplementedException();

test/PowerShellEditorServices.Test/PowerShellEditorServices.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
<Compile Include="Console\ConsoleServiceTests.cs" />
7474
<Compile Include="Console\ChoicePromptHandlerTests.cs" />
7575
<Compile Include="Session\ScriptFileTests.cs" />
76+
<Compile Include="Session\WorkspaceTests.cs" />
7677
<Compile Include="Utility\AsyncDebouncerTests.cs" />
7778
<Compile Include="Utility\AsyncLockTests.cs" />
7879
<Compile Include="Utility\AsyncQueueTests.cs" />
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
using Microsoft.PowerShell.EditorServices;
7+
using System;
8+
using System.IO;
9+
using System.Linq;
10+
using Xunit;
11+
12+
namespace Microsoft.PowerShell.EditorServices.Test.Session
13+
{
14+
public class WorkspaceTests
15+
{
16+
private static readonly Version PowerShellVersion = new Version("5.0");
17+
18+
[Fact]
19+
public void CanResolveWorkspaceRelativePath()
20+
{
21+
string workspacePath = @"c:\Test\Workspace\";
22+
string testPathInside = @"c:\Test\Workspace\SubFolder\FilePath.ps1";
23+
string testPathOutside = @"c:\Test\PeerPath\FilePath.ps1";
24+
string testPathAnotherDrive = @"z:\TryAndFindMe\FilePath.ps1";
25+
26+
Workspace workspace = new Workspace(PowerShellVersion);
27+
28+
// Test without a workspace path
29+
Assert.Equal(testPathOutside, workspace.GetRelativePath(testPathOutside));
30+
31+
// Test with a workspace path
32+
workspace.WorkspacePath = workspacePath;
33+
Assert.Equal(@"SubFolder\FilePath.ps1", workspace.GetRelativePath(testPathInside));
34+
Assert.Equal(@"..\PeerPath\FilePath.ps1", workspace.GetRelativePath(testPathOutside));
35+
Assert.Equal(testPathAnotherDrive, workspace.GetRelativePath(testPathAnotherDrive));
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)