using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System;
using System.ComponentModel.Design;
using Task = System.Threading.Tasks.Task;
using PortingAssistantVSExtensionClient.Models;
using EnvDTE;
using EnvDTE80;
using PortingAssistantVSExtensionClient.Utils;
using System.Collections.Generic;
using PortingAssistantVSExtensionClient.Options;
using Microsoft.VisualStudio.PlatformUI;
using PortingAssistantVSExtensionClient.Dialogs;
using PortingAssistantVSExtensionClient.Common;
using System.Threading;
using System.IO;
namespace PortingAssistantVSExtensionClient.Commands
{
///
/// Command handler
///
internal sealed class ProjectPortingCommand
{
///
/// Command ID.
///
public const int CommandId = PackageIds.cmdidProjectPortingCommand;
///
/// 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 ProjectPortingCommand(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 ProjectPortingCommand Instance
{
get;
private set;
}
private string selectedProjectName = "";
///
/// 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 ProjectPortingCommand's constructor requires
// the UI thread.
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
Instance = new ProjectPortingCommand(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;
string SelectedProjectPath = SolutionUtils.GetSelectedProjectPath();
selectedProjectName = Path.GetFileName(SelectedProjectPath);
if (!UserSettings.Instance.SolutionAssessed)
{
NotificationUtils.ShowInfoMessageBox(this.package, "Please run a full assessment before porting", "");
return;
}
if (string.IsNullOrEmpty(SelectedProjectPath))
{
NotificationUtils.ShowInfoMessageBox(this.package, "Please select or open a project", "Porting a project");
return;
}
if (UserSettings.Instance.TargetFramework.Equals(TargetFrameworkType.NO_SELECTION))
{
if (!SelectTargetDialog.EnsureExecute()) return;
}
if (!PortingDialog.EnsureExecute(selectedProjectName)) return;
string SolutionFile = await CommandsCommon.GetSolutionPathAsync();
CommandsCommon.EnableAllCommand(false);
string pipeName = Guid.NewGuid().ToString();
CommandsCommon.RunPortingAsync(SolutionFile, new List { SelectedProjectPath }, pipeName, selectedProjectName);
PipeUtils.StartListenerConnection(pipeName, GetPortingCompletionTasks(this.package, selectedProjectName, UserSettings.Instance.TargetFramework));
}
catch (Exception ex)
{
NotificationUtils.ShowErrorMessageBox(this.package, $"Porting failed for {selectedProjectName} due to {ex.Message}", "Porting failed");
CommandsCommon.EnableAllCommand(true);
}
}
public Func GetPortingCompletionTasks(AsyncPackage package, string selectedProject, string targetFramework)
{
async Task CompletionTask()
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
try
{
var successfulMessage = $"The project 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 {selectedProject} due to {ex.Message}",
"Porting failed");
}
finally
{
CommandsCommon.EnableAllCommand(true);
}
}
return CompletionTask;
}
}
}