Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix up extension API #2053

Merged
merged 4 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/PowerShellEditorServices/Extensions/EditorRequests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ internal class ExtensionCommandRemovedNotification
internal class GetEditorContextRequest
{ }

internal enum EditorCommandResponse
internal enum EditorOperationResponse
{
Unsupported,
OK
Completed,
Failed
}

internal class InsertTextRequest
Expand Down
3 changes: 0 additions & 3 deletions src/PowerShellEditorServices/Extensions/EditorWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ internal EditorWindow(IEditorOperations editorOperations)
#endregion

#region Public Methods
#pragma warning disable VSTHRD002 // These are public APIs that use async internal methods.

/// <summary>
/// Shows an informational message to the user.
/// </summary>
Expand Down Expand Up @@ -72,7 +70,6 @@ internal EditorWindow(IEditorOperations editorOperations)
/// <param name="timeout">A timeout in milliseconds for how long the message should remain visible.</param>
public void SetStatusBarMessage(string message, int timeout) => editorOperations.SetStatusBarMessageAsync(message, timeout).Wait();

#pragma warning restore VSTHRD002
#endregion
}
}
44 changes: 37 additions & 7 deletions src/PowerShellEditorServices/Extensions/EditorWorkspace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@ public sealed class EditorWorkspace
#region Properties

/// <summary>
/// Gets the current workspace path if there is one for the open editor or null otherwise.
/// Gets the server's initial working directory, since the extension API doesn't have a
/// multi-root workspace concept.
/// </summary>
public string Path => editorOperations.GetWorkspacePath();

/// <summary>
/// Get all the workspace folders' paths.
/// </summary>
public string[] Paths => editorOperations.GetWorkspacePaths();

#endregion

#region Constructors
Expand All @@ -31,30 +37,54 @@ public sealed class EditorWorkspace
#endregion

#region Public Methods
#pragma warning disable VSTHRD002 // These are public APIs that use async internal methods.
// TODO: Consider returning bool instead of void to indicate success?

/// <summary>
/// Creates a new file in the editor.
/// </summary>
public void NewFile() => editorOperations.NewFileAsync(string.Empty).Wait();

/// <summary>
/// Creates a new file in the editor
/// Creates a new file in the editor.
/// </summary>
public void NewFile() => editorOperations.NewFileAsync().Wait();
/// <param name="content">The content to place in the new file.</param>
andyleejordan marked this conversation as resolved.
Show resolved Hide resolved
public void NewFile(string content) => editorOperations.NewFileAsync(content).Wait();

/// <summary>
/// Opens a file in the workspace. If the file is already open
/// Opens a file in the workspace. If the file is already open
/// its buffer will be made active.
/// </summary>
/// <param name="filePath">The path to the file to be opened.</param>
public void OpenFile(string filePath) => editorOperations.OpenFileAsync(filePath).Wait();

/// <summary>
/// Opens a file in the workspace. If the file is already open
/// Opens a file in the workspace. If the file is already open
/// its buffer will be made active.
/// You can specify whether the file opens as a preview or as a durable editor.
/// </summary>
/// <param name="filePath">The path to the file to be opened.</param>
/// <param name="preview">Determines wether the file is opened as a preview or as a durable editor.</param>
public void OpenFile(string filePath, bool preview) => editorOperations.OpenFileAsync(filePath, preview).Wait();

#pragma warning restore VSTHRD002
/// <summary>
/// Closes a file in the workspace.
/// </summary>
/// <param name="filePath">The path to the file to be closed.</param>
public void CloseFile(string filePath) => editorOperations.CloseFileAsync(filePath).Wait();

/// <summary>
/// Saves an open file in the workspace.
/// </summary>
/// <param name="filePath">The path to the file to be saved.</param>
public void SaveFile(string filePath) => editorOperations.SaveFileAsync(filePath).Wait();

/// <summary>
/// Saves a file with a new name AKA a copy.
/// </summary>
/// <param name="oldFilePath">The file to copy.</param>
/// <param name="newFilePath">The file to create.</param>
public void SaveFile(string oldFilePath, string newFilePath) => editorOperations.SaveFileAsync(oldFilePath, newFilePath).Wait();

#endregion
}
}
3 changes: 1 addition & 2 deletions src/PowerShellEditorServices/Extensions/FileContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ public sealed class FileContext
/// <summary>
/// Gets the workspace-relative path of the file.
/// </summary>
public string WorkspacePath => editorOperations.GetWorkspaceRelativePath(
scriptFile.FilePath);
public string WorkspacePath => editorOperations.GetWorkspaceRelativePath(scriptFile);

#endregion

Expand Down
21 changes: 17 additions & 4 deletions src/PowerShellEditorServices/Extensions/IEditorOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,37 @@ internal interface IEditorOperations
Task<EditorContext> GetEditorContextAsync();

/// <summary>
/// Gets the path to the editor's active workspace.
/// Gets the server's initial working directory, since the extension API doesn't have a
/// multi-root workspace concept.
/// </summary>
/// <returns>The workspace path or null if there isn't one.</returns>
/// <returns>The server's initial working directory.</returns>
string GetWorkspacePath();

/// <summary>
/// Get all the workspace folders' paths.
/// </summary>
/// <returns></returns>
string[] GetWorkspacePaths();

/// <summary>
/// Resolves the given file path relative to the current workspace path.
/// </summary>
/// <param name="filePath">The file path to be resolved.</param>
/// <returns>The resolved file path.</returns>
string GetWorkspaceRelativePath(string filePath);
string GetWorkspaceRelativePath(ScriptFile scriptFile);

/// <summary>
/// Causes a new untitled file to be created in the editor.
/// </summary>
/// <returns>A task that can be awaited for completion.</returns>
Task NewFileAsync();

/// <summary>
/// Causes a new untitled file to be created in the editor.
/// </summary>
/// <param name="content">The content to insert into the new file.</param>
andyleejordan marked this conversation as resolved.
Show resolved Hide resolved
/// <returns>A task that can be awaited for completion.</returns>
Task NewFileAsync(string content);

/// <summary>
/// Causes a file to be opened in the editor. If the file is
/// already open, the editor must switch to the file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,16 @@
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.PowerShell.EditorServices.Services.Extension
{
internal class EditorOperationsService : IEditorOperations
{
private const bool DefaultPreviewSetting = true;

private readonly PsesInternalHost _psesHost;
private readonly WorkspaceService _workspaceService;

private readonly ILanguageServerFacade _languageServer;

public EditorOperationsService(
Expand Down Expand Up @@ -72,7 +70,7 @@ public async Task InsertTextAsync(string filePath, string text, BufferRange inse
Character = insertRange.End.Column - 1
}
}
}).ReturningVoid(CancellationToken.None).ConfigureAwait(false);
}).Returning<EditorOperationResponse>(CancellationToken.None).ConfigureAwait(false);
}

public async Task SetSelectionAsync(BufferRange selectionRange)
Expand All @@ -98,7 +96,7 @@ public async Task SetSelectionAsync(BufferRange selectionRange)
Character = selectionRange.End.Column - 1
}
}
}).ReturningVoid(CancellationToken.None).ConfigureAwait(false);
}).Returning<EditorOperationResponse>(CancellationToken.None).ConfigureAwait(false);
}

public EditorContext ConvertClientEditorContext(
Expand All @@ -123,15 +121,17 @@ public EditorContext ConvertClientEditorContext(
clientContext.CurrentFileLanguage);
}

public async Task NewFileAsync()
public async Task NewFileAsync() => await NewFileAsync(string.Empty).ConfigureAwait(false);

public async Task NewFileAsync(string content)
{
if (!TestHasLanguageServer())
{
return;
}

await _languageServer.SendRequest<string>("editor/newFile", null)
.ReturningVoid(CancellationToken.None)
await _languageServer.SendRequest("editor/newFile", content)
.Returning<EditorOperationResponse>(CancellationToken.None)
.ConfigureAwait(false);
}

Expand All @@ -145,8 +145,8 @@ public async Task OpenFileAsync(string filePath)
await _languageServer.SendRequest("editor/openFile", new OpenFileDetails
{
FilePath = filePath,
Preview = DefaultPreviewSetting
}).ReturningVoid(CancellationToken.None).ConfigureAwait(false);
Preview = true
}).Returning<EditorOperationResponse>(CancellationToken.None).ConfigureAwait(false);
}

public async Task OpenFileAsync(string filePath, bool preview)
Expand All @@ -160,7 +160,7 @@ public async Task OpenFileAsync(string filePath, bool preview)
{
FilePath = filePath,
Preview = preview
}).ReturningVoid(CancellationToken.None).ConfigureAwait(false);
}).Returning<EditorOperationResponse>(CancellationToken.None).ConfigureAwait(false);
}

public async Task CloseFileAsync(string filePath)
Expand All @@ -171,7 +171,7 @@ public async Task CloseFileAsync(string filePath)
}

await _languageServer.SendRequest("editor/closeFile", filePath)
.ReturningVoid(CancellationToken.None)
.Returning<EditorOperationResponse>(CancellationToken.None)
.ConfigureAwait(false);
}

Expand All @@ -188,14 +188,16 @@ public async Task SaveFileAsync(string currentPath, string newSavePath)
{
FilePath = currentPath,
NewPath = newSavePath
}).ReturningVoid(CancellationToken.None).ConfigureAwait(false);
}).Returning<EditorOperationResponse>(CancellationToken.None).ConfigureAwait(false);
}

// TODO: This should get the current editor's context and use it to determine which
// workspace it's in.
// NOTE: This name is now outdated since we don't have a way to distinguish one workspace
// from another for the extension API.
public string GetWorkspacePath() => _workspaceService.InitialWorkingDirectory;

public string GetWorkspaceRelativePath(string filePath) => _workspaceService.GetRelativePath(filePath);
public string[] GetWorkspacePaths() => _workspaceService.WorkspacePaths.ToArray();

public string GetWorkspaceRelativePath(ScriptFile scriptFile) => _workspaceService.GetRelativePath(scriptFile);

public async Task ShowInformationMessageAsync(string message)
{
Expand All @@ -205,7 +207,7 @@ public async Task ShowInformationMessageAsync(string message)
}

await _languageServer.SendRequest("editor/showInformationMessage", message)
.ReturningVoid(CancellationToken.None)
.Returning<EditorOperationResponse>(CancellationToken.None)
.ConfigureAwait(false);
}

Expand All @@ -217,7 +219,7 @@ public async Task ShowErrorMessageAsync(string message)
}

await _languageServer.SendRequest("editor/showErrorMessage", message)
.ReturningVoid(CancellationToken.None)
.Returning<EditorOperationResponse>(CancellationToken.None)
.ConfigureAwait(false);
}

Expand All @@ -229,7 +231,7 @@ public async Task ShowWarningMessageAsync(string message)
}

await _languageServer.SendRequest("editor/showWarningMessage", message)
.ReturningVoid(CancellationToken.None)
.Returning<EditorOperationResponse>(CancellationToken.None)
.ConfigureAwait(false);
}

Expand All @@ -244,7 +246,7 @@ public async Task SetStatusBarMessageAsync(string message, int? timeout)
{
Message = message,
Timeout = timeout
}).ReturningVoid(CancellationToken.None).ConfigureAwait(false);
}).Returning<EditorOperationResponse>(CancellationToken.None).ConfigureAwait(false);
}

public void ClearTerminal()
Expand All @@ -267,7 +269,7 @@ private bool TestHasLanguageServer(bool warnUser = true)
if (warnUser)
{
_psesHost.UI.WriteWarningLine(
"Editor operations are not supported in temporary consoles. Re-run the command in the main PowerShell Intergrated Console.");
"Editor operations are not supported in temporary consoles. Re-run the command in the main Extension Terminal.");
}

return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public async Task<CommentHelpRequestResult> Handle(CommentHelpRequestParams requ
{
// check if the previous character is `<` because it invalidates
// the param block the follows it.
IList<string> lines = ScriptFile.GetLinesInternal(funcText);
IList<string> lines = ScriptFile.GetLines(funcText);
int relativeTriggerLine0b = triggerLine - funcExtent.StartLineNumber;
if (relativeTriggerLine0b > 0 && lines[relativeTriggerLine0b].IndexOf("<", StringComparison.OrdinalIgnoreCase) > -1)
{
Expand All @@ -68,7 +68,7 @@ public async Task<CommentHelpRequestResult> Handle(CommentHelpRequestParams requ
return result;
}

List<string> helpLines = ScriptFile.GetLinesInternal(helpText);
List<string> helpLines = ScriptFile.GetLines(helpText);

if (helpLocation?.Equals("before", StringComparison.OrdinalIgnoreCase) == false)
{
Expand Down
18 changes: 2 additions & 16 deletions src/PowerShellEditorServices/Services/TextDocument/ScriptFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,6 @@ internal sealed class ScriptFile

#region Properties

/// <summary>
/// Gets a unique string that identifies this file. At this time,
/// this property returns a normalized version of the value stored
/// in the FilePath property.
/// </summary>
public string Id => FilePath.ToLower();

/// <summary>
/// Gets the path at which this file resides.
/// </summary>
Expand Down Expand Up @@ -173,14 +166,7 @@ internal ScriptFile(
/// </summary>
/// <param name="text">Input string to be split up into lines.</param>
/// <returns>The lines in the string.</returns>
internal static IList<string> GetLines(string text) => GetLinesInternal(text);

/// <summary>
/// Get the lines in a string.
/// </summary>
/// <param name="text">Input string to be split up into lines.</param>
/// <returns>The lines in the string.</returns>
internal static List<string> GetLinesInternal(string text)
internal static List<string> GetLines(string text)
{
if (text == null)
{
Expand Down Expand Up @@ -520,7 +506,7 @@ internal void SetFileContents(string fileContents)
{
// Split the file contents into lines and trim
// any carriage returns from the strings.
FileLines = GetLinesInternal(fileContents);
FileLines = GetLines(fileContents);

// Parse the contents to get syntax tree and errors
ParseFileContents();
Expand Down
Loading