// 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); } } }