// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.PowerShell.EditorServices.Extensions.Services;
using Microsoft.PowerShell.EditorServices.Services.Extension;
namespace Microsoft.PowerShell.EditorServices.Extensions
{
///
/// Extension class to access the editor API with.
/// This is done so that the async/ALC APIs aren't exposed to PowerShell, where they're likely only to cause problems.
///
public static class EditorObjectExtensions
{
///
/// Get the provider of extension services for .NET extension tooling.
///
/// The editor object ($psEditor).
/// The extension services provider.
public static EditorExtensionServiceProvider GetExtensionServiceProvider(this EditorObject editorObject) => editorObject.Api;
}
///
/// Provides the entry point of the extensibility API, inserted into
/// the PowerShell session as the "$psEditor" variable.
///
public class EditorObject
{
private static readonly TaskCompletionSource s_editorObjectReady = new();
///
/// A reference to the editor object instance. Only valid when completes.
///
public static EditorObject Instance { get; private set; }
///
/// A task that completes when the editor object static instance has been set.
///
public static Task EditorObjectReady => s_editorObjectReady.Task;
#region Private Fields
private readonly ExtensionService _extensionService;
private readonly IEditorOperations _editorOperations;
private readonly Lazy _apiLazy;
#endregion
#region Properties
internal EditorExtensionServiceProvider Api => _apiLazy.Value;
///
/// Gets the version of PowerShell Editor Services.
///
public Version EditorServicesVersion => GetType().GetTypeInfo().Assembly.GetName().Version;
///
/// Gets the workspace interface for the editor API.
///
public EditorWorkspace Workspace { get; }
///
/// Gets the window interface for the editor API.
///
public EditorWindow Window { get; }
#endregion
///
/// Creates a new instance of the EditorObject class.
///
/// The service provider?
/// An ExtensionService which handles command registration.
/// An IEditorOperations implementation which handles operations in the host editor.
internal EditorObject(
IServiceProvider serviceProvider,
ExtensionService extensionService,
IEditorOperations editorOperations)
{
_extensionService = extensionService;
_editorOperations = editorOperations;
// Create API area objects
Workspace = new EditorWorkspace(_editorOperations);
Window = new EditorWindow(_editorOperations);
// Create this lazily so that dependency injection does not have a circular call dependency
_apiLazy = new Lazy(() => new EditorExtensionServiceProvider(serviceProvider));
}
///
/// Registers a new command in the editor.
///
/// The EditorCommand to be registered.
/// True if the command is newly registered, false if the command already exists.
public bool RegisterCommand(EditorCommand editorCommand) => _extensionService.RegisterCommand(editorCommand);
///
/// Unregisters an existing EditorCommand based on its registered name.
///
/// The name of the command to be unregistered.
public void UnregisterCommand(string commandName) => _extensionService.UnregisterCommand(commandName);
///
/// Returns all registered EditorCommands.
///
/// An Array of all registered EditorCommands.
public EditorCommand[] GetCommands() => _extensionService.GetCommands();
///
/// Gets the EditorContext which contains the state of the editor
/// at the time this method is invoked.
///
/// A instance of the EditorContext class.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")]
public EditorContext GetEditorContext() => _editorOperations.GetEditorContextAsync().Result;
internal void SetAsStaticInstance()
{
Instance = this;
s_editorObjectReady.TrySetResult(true);
}
}
}