using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using PortingAssistantVSExtensionClient.Common;
using PortingAssistantVSExtensionClient.Dialogs;
using PortingAssistantVSExtensionClient.Models;
using PortingAssistantVSExtensionClient.Options;
using PortingAssistantVSExtensionClient.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.IO;
using Task = System.Threading.Tasks.Task;
namespace PortingAssistantVSExtensionClient.Commands
{
///
/// Command handler
///
internal sealed class SolutionPortingCommand
{
///
/// Command ID.
///
public const int CommandId = PackageIds.cmdidSolutionPortingCommand;
///
/// Command menu group (command set GUID).
///
public static readonly Guid CommandSet = new Guid(PackageGuids.guidPortingAssistantVSExtensionClientPackageCmdSetString);
///
/// VS Package that provides this command, not null.
///
private readonly AsyncPackage package;
///
/// Initializes a new instance of the class.
/// Adds our command handlers for menu (commands must exist in the command table file)
///
/// Owner package, not null.
/// Command service to add command to, not null.
private SolutionPortingCommand(AsyncPackage package, OleMenuCommandService commandService)
{
this.package = package ?? throw new ArgumentNullException(nameof(package));
commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
var menuCommandID = new CommandID(CommandSet, CommandId);
var menuItem = new MenuCommand(this.Execute, menuCommandID);
commandService.AddCommand(menuItem);
}
///
/// Gets the instance of the command.
///
public static SolutionPortingCommand Instance
{
get;
private set;
}
private string solutionName = "";
///
/// Gets the service provider from the owner package.
///
private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
{
get
{
return this.package;
}
}
///
/// Initializes the singleton instance of the command.
///
/// Owner package, not null.
public static async Task InitializeAsync(AsyncPackage package)
{
// Switch to the main thread - the call to AddCommand in SolutionPortingCommand's constructor requires
// the UI thread.
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
Instance = new SolutionPortingCommand(package, commandService);
}
///
/// This function is the callback used to execute the command when the menu item is clicked.
/// See the constructor to see how the menu item is associated with this function using
/// OleMenuCommandService service and MenuCommand class.
///
/// Event sender.
/// Event args.
private async void Execute(object sender, EventArgs e)
{
try
{
if (!await CommandsCommon.CheckLanguageServerStatusAsync())
{
NotificationUtils.ShowInfoMessageBox(PAGlobalService.Instance.Package, "Porting Assistant cannot be activated. Please open any .cs/.vb file if its not already opened.", "Porting Assistant can not be activated.");
return;
}
if (!CommandsCommon.SetupPage()) return;
if (!UserSettings.Instance.SolutionAssessed)
{
NotificationUtils.ShowInfoMessageBox(this.package, "Please run a full assessment before porting", "");
return;
}
if (UserSettings.Instance.TargetFramework.Equals(TargetFrameworkType.NO_SELECTION))
{
if (!SelectTargetDialog.EnsureExecute()) return;
}
string SolutionFile = await CommandsCommon.GetSolutionPathAsync();
solutionName = Path.GetFileName(SolutionFile);
var ProjectFiles = SolutionUtils.GetProjectPath(SolutionFile);
if (!PortingDialog.EnsureExecute(solutionName)) return;
CommandsCommon.EnableAllCommand(false);
string pipeName = Guid.NewGuid().ToString();
CommandsCommon.RunPortingAsync(SolutionFile, ProjectFiles, pipeName, solutionName);
PipeUtils.StartListenerConnection(pipeName, GetSolutionCompletionTasks(this.package, solutionName, UserSettings.Instance.TargetFramework));
}
catch (Exception ex)
{
NotificationUtils.ShowErrorMessageBox(this.package, $"Porting failed for {solutionName} due to {ex.Message}", "Porting failed");
CommandsCommon.EnableAllCommand(true);
}
}
public Func GetSolutionCompletionTasks(AsyncPackage package, string solutionName, string targetFramework)
{
async Task CompletionTask()
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
try
{
var successfulMessage = $"The solution has been ported to {targetFramework}" + (UserSettings.Instance.ApplyPortAction ? $".{Environment.NewLine}Code changes have been applied" : "");
NotificationUtils.ShowInfoMessageBox(package, successfulMessage, "Porting successful");
await NotificationUtils.ShowInfoBarAsync(package, successfulMessage);
await NotificationUtils.UseStatusBarProgressAsync(2, 2, successfulMessage);
}
catch (Exception ex)
{
NotificationUtils.ShowErrorMessageBox(package, $"Porting failed for {solutionName} due to {ex.Message}", "Porting failed");
}
finally
{
CommandsCommon.EnableAllCommand(true);
}
}
return CompletionTask;
}
}
}