From 3e0feb53d1fd2a79960e081b2c1d28948dbf8853 Mon Sep 17 00:00:00 2001 From: Stella <100439259+StellaHuang95@users.noreply.github.com> Date: Wed, 12 Feb 2025 16:22:38 -0800 Subject: [PATCH] Address feedback from Diagnostics Hub team (#8170) * Add a MefComponent asset to the profiling vsix * load package from shell (#8169) --------- Co-authored-by: Adam Yoblick --- .../Profiling/CommandArgumentBuilder.cs | 21 ++++++++---- .../IPythonProfilerCommandService.cs | 4 ++- .../Profiling/PythonProfilerCommandService.cs | 33 ++++++++++++++++--- .../Profiling/Profiling/UserInputDialog.cs | 3 +- .../Profiling/PythonProfilingPackage.cs | 1 + .../Profiling/source.extension.vsixmanifest | 1 + 6 files changed, 49 insertions(+), 14 deletions(-) diff --git a/Python/Product/Profiling/Profiling/CommandArgumentBuilder.cs b/Python/Product/Profiling/Profiling/CommandArgumentBuilder.cs index 98cb7a8daa..3e34a7cd6c 100644 --- a/Python/Product/Profiling/Profiling/CommandArgumentBuilder.cs +++ b/Python/Product/Profiling/Profiling/CommandArgumentBuilder.cs @@ -30,13 +30,12 @@ internal class CommandArgumentBuilder { /// /// Constructs a based on the provided profiling target. /// - public PythonProfilingCommandArgs BuildCommandArgsFromTarget(ProfilingTarget target) { + public PythonProfilingCommandArgs BuildCommandArgsFromTarget(ProfilingTarget target, PythonProfilingPackage pythonProfilingPackage) { if (target == null) { return null; } try { - var pythonProfilingPackage = PythonProfilingPackage.Instance; var joinableTaskFactory = pythonProfilingPackage.JoinableTaskFactory; PythonProfilingCommandArgs command = null; @@ -48,7 +47,7 @@ public PythonProfilingCommandArgs BuildCommandArgsFromTarget(ProfilingTarget tar var explorer = await pythonProfilingPackage.ShowPerformanceExplorerAsync(); var session = explorer.Sessions.AddTarget(target, name, save); - command = SelectBuilder(target, session); + command = SelectBuilder(target, session, pythonProfilingPackage); }); @@ -62,20 +61,28 @@ public PythonProfilingCommandArgs BuildCommandArgsFromTarget(ProfilingTarget tar /// /// Select the appropriate builder based on the provided profiling target. /// - private PythonProfilingCommandArgs SelectBuilder(ProfilingTarget target, SessionNode session) { + private PythonProfilingCommandArgs SelectBuilder(ProfilingTarget target, SessionNode session, PythonProfilingPackage pythonProfilingPackage) { var projectTarget = target.ProjectTarget; var standaloneTarget = target.StandaloneTarget; if (projectTarget != null) { - return BuildProjectCommandArgs(projectTarget, session); + return BuildProjectCommandArgs(projectTarget, session, pythonProfilingPackage); } else if (standaloneTarget != null) { return BuildStandaloneCommandArgs(standaloneTarget, session); } return null; } - private PythonProfilingCommandArgs BuildProjectCommandArgs(ProjectTarget projectTarget, SessionNode session) { - var solution = PythonProfilingPackage.Instance.Solution; + private PythonProfilingCommandArgs BuildProjectCommandArgs(ProjectTarget projectTarget, SessionNode session, PythonProfilingPackage pythonProfilingPackage) { + if (pythonProfilingPackage == null) { + return null; + } + + var solution = pythonProfilingPackage.Solution; + if (solution == null) { + return null; + } + var project = solution.EnumerateLoadedPythonProjects() .SingleOrDefault(p => p.GetProjectIDGuidProperty() == projectTarget.TargetProject); diff --git a/Python/Product/Profiling/Profiling/IPythonProfilerCommandService.cs b/Python/Product/Profiling/Profiling/IPythonProfilerCommandService.cs index 2ba6c929bb..c8cf9bbc5a 100644 --- a/Python/Product/Profiling/Profiling/IPythonProfilerCommandService.cs +++ b/Python/Product/Profiling/Profiling/IPythonProfilerCommandService.cs @@ -14,6 +14,8 @@ // See the Apache Version 2.0 License for specific language governing // permissions and limitations under the License. +using System.Threading.Tasks; + namespace Microsoft.PythonTools.Profiling { /// @@ -23,6 +25,6 @@ public interface IPythonProfilerCommandService { /// /// Collects user input via a dialog and converts it into a . /// - IPythonProfilingCommandArgs GetCommandArgsFromUserInput(); + Task GetCommandArgsFromUserInput(); } } diff --git a/Python/Product/Profiling/Profiling/PythonProfilerCommandService.cs b/Python/Product/Profiling/Profiling/PythonProfilerCommandService.cs index 08e910f83b..da2b124262 100644 --- a/Python/Product/Profiling/Profiling/PythonProfilerCommandService.cs +++ b/Python/Product/Profiling/Profiling/PythonProfilerCommandService.cs @@ -18,7 +18,11 @@ namespace Microsoft.PythonTools.Profiling { using System; using System.ComponentModel.Composition; using System.Diagnostics; + using System.Threading.Tasks; using System.Windows; + using Microsoft.VisualStudio.Shell; + using Microsoft.VisualStudio.Shell.Interop; + using Microsoft.VisualStudio.Threading; /// /// Implements a service to collect user input for profiling and convert to a . @@ -39,14 +43,18 @@ public PythonProfilerCommandService() { /// /// A object based on user input, or null if canceled. /// - public IPythonProfilingCommandArgs GetCommandArgsFromUserInput() { + public async Task GetCommandArgsFromUserInput() { try { - var pythonProfilingPackage = PythonProfilingPackage.Instance; + var pythonProfilingPackage = await GetPythonProfilingPackageAsync(); + if (pythonProfilingPackage == null) { + return null; + + } var targetView = new ProfilingTargetView(pythonProfilingPackage); - if (_userInputDialog.ShowDialog(targetView)) { + if (_userInputDialog.ShowDialog(targetView, pythonProfilingPackage)) { var target = targetView.GetTarget(); - return _commandArgumentBuilder.BuildCommandArgsFromTarget(target); + return _commandArgumentBuilder.BuildCommandArgsFromTarget(target, pythonProfilingPackage); } } catch (Exception ex) { Debug.Fail($"Error displaying user input dialog: {ex.Message}"); @@ -55,5 +63,22 @@ public IPythonProfilingCommandArgs GetCommandArgsFromUserInput() { return null; } + + private async Task GetPythonProfilingPackageAsync() { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + + var shell = await ServiceProvider.GetGlobalServiceAsync(typeof(SVsShell)) as IVsShell; + if (shell != null) { + var packageGuid = typeof(PythonProfilingPackage).GUID; + int hr = shell.LoadPackage(ref packageGuid, out var packageObj); + + Debug.WriteLine($"LoadPackage result: {hr}"); // Log HRESULT result + + if (packageObj != null) { + return packageObj as PythonProfilingPackage; + } + } + return null; + } } } diff --git a/Python/Product/Profiling/Profiling/UserInputDialog.cs b/Python/Product/Profiling/Profiling/UserInputDialog.cs index 59022d1ebb..500aa28a00 100644 --- a/Python/Product/Profiling/Profiling/UserInputDialog.cs +++ b/Python/Product/Profiling/Profiling/UserInputDialog.cs @@ -16,8 +16,7 @@ namespace Microsoft.PythonTools.Profiling { internal class UserInputDialog { - public bool ShowDialog(ProfilingTargetView targetView) { - var pythonProfilingPackage = PythonProfilingPackage.Instance; + public bool ShowDialog(ProfilingTargetView targetView, PythonProfilingPackage pythonProfilingPackage) { var dialog = new LaunchProfiling(pythonProfilingPackage, targetView); return dialog.ShowModal() ?? false; } diff --git a/Python/Product/Profiling/PythonProfilingPackage.cs b/Python/Product/Profiling/PythonProfilingPackage.cs index 6b862e260f..1e7a847db5 100644 --- a/Python/Product/Profiling/PythonProfilingPackage.cs +++ b/Python/Product/Profiling/PythonProfilingPackage.cs @@ -62,6 +62,7 @@ namespace Microsoft.PythonTools.Profiling { NameResourceID = 105, DefaultName = "PythonPerfSession")] [ProvideAutomationObject("PythonProfiling")] + [ProvideService(typeof(PythonProfilingPackage), IsAsyncQueryable = true)] internal sealed class PythonProfilingPackage : AsyncPackage { internal static PythonProfilingPackage Instance; private static ProfiledProcess _profilingProcess; // process currently being profiled diff --git a/Python/Product/Profiling/source.extension.vsixmanifest b/Python/Product/Profiling/source.extension.vsixmanifest index 3ef0b1b873..661737dc88 100644 --- a/Python/Product/Profiling/source.extension.vsixmanifest +++ b/Python/Product/Profiling/source.extension.vsixmanifest @@ -23,5 +23,6 @@ + \ No newline at end of file