diff --git a/FineCodeCoverage/FineCodeCoverage.csproj b/FineCodeCoverage/FineCodeCoverage.csproj index cff6100b..18975232 100644 --- a/FineCodeCoverage/FineCodeCoverage.csproj +++ b/FineCodeCoverage/FineCodeCoverage.csproj @@ -170,6 +170,7 @@ + @@ -228,6 +229,7 @@ Resources\LICENSE true + true diff --git a/FineCodeCoverage/Output/ClearUICommand.cs b/FineCodeCoverage/Output/ClearUICommand.cs new file mode 100644 index 00000000..a2fb644b --- /dev/null +++ b/FineCodeCoverage/Output/ClearUICommand.cs @@ -0,0 +1,83 @@ +using System; +using System.ComponentModel.Design; +using System.Globalization; +using System.Threading; +using System.Threading.Tasks; +using FineCodeCoverage.Engine; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Task = System.Threading.Tasks.Task; + +namespace FineCodeCoverage.Output +{ + /// + /// Command handler + /// + internal sealed class ClearUICommand + { + /// + /// Command ID. + /// + public const int CommandId = 256; + + /// + /// Command menu group (command set GUID). + /// + public static readonly Guid CommandSet = new Guid("d58a999f-4a1b-42df-839a-cb31a0a4fed7"); + + private readonly IFCCEngine fccEngine; + + /// + /// 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 ClearUICommand(OleMenuCommandService commandService, IFCCEngine fccEngine) + { + this.fccEngine = fccEngine; + 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 ClearUICommand Instance + { + get; + private set; + } + + /// + /// Initializes the singleton instance of the command. + /// + /// Owner package, not null. + public static async Task InitializeAsync(AsyncPackage package, IFCCEngine fccEngine) + { + // Switch to the main thread - the call to AddCommand in ClearUICommand's constructor requires + // the UI thread. + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken); + + OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService; + Instance = new ClearUICommand(commandService, fccEngine); + } + + /// + /// 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 void Execute(object sender, EventArgs e) + { + ThreadHelper.ThrowIfNotOnUIThread(); + fccEngine.ClearUI(); + } + + } +} diff --git a/FineCodeCoverage/Output/OutputToolWindowPackage.cs b/FineCodeCoverage/Output/OutputToolWindowPackage.cs index 7bc98ace..f6ca424f 100644 --- a/FineCodeCoverage/Output/OutputToolWindowPackage.cs +++ b/FineCodeCoverage/Output/OutputToolWindowPackage.cs @@ -75,6 +75,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke componentModel = sp.GetService(typeof(Microsoft.VisualStudio.ComponentModelHost.SComponentModel)) as Microsoft.VisualStudio.ComponentModelHost.IComponentModel; Assumes.Present(componentModel); await OutputToolWindowCommand.InitializeAsync(this); + await ClearUICommand.InitializeAsync(this, componentModel.GetService()); } protected override System.Threading.Tasks.Task InitializeToolWindowAsync(Type toolWindowType, int id, CancellationToken cancellationToken) diff --git a/FineCodeCoverage/Output/OutputToolWindowPackage.vsct b/FineCodeCoverage/Output/OutputToolWindowPackage.vsct index d38388f2..947a60d8 100644 --- a/FineCodeCoverage/Output/OutputToolWindowPackage.vsct +++ b/FineCodeCoverage/Output/OutputToolWindowPackage.vsct @@ -15,10 +15,10 @@ defining some of the constants that we will use inside the file. --> - + - + @@ -43,12 +43,19 @@ DynamicVisibility If you do not want an image next to your command, remove the Icon node /> --> + @@ -58,8 +65,14 @@ bitmap strip containing the bitmaps and then there are the numeric ids of the elements used inside a button definition. An important aspect of this declaration is that the element id must be the actual index (1-based) of the bitmap inside the bitmap strip. --> - + + + + + + + @@ -71,7 +84,16 @@ - + + + + + + + + + + diff --git a/FineCodeCoverage/Output/OutputToolWindowPackage1.cs b/FineCodeCoverage/Output/OutputToolWindowPackage1.cs index ac62adb5..e377eb08 100644 --- a/FineCodeCoverage/Output/OutputToolWindowPackage1.cs +++ b/FineCodeCoverage/Output/OutputToolWindowPackage1.cs @@ -20,6 +20,12 @@ internal sealed partial class PackageGuids public const string guidImagesString = "297e101c-4afa-47b1-b382-087cfb4618b0"; public static Guid guidImages = new Guid(guidImagesString); + + public const string guidOutputToolWindowPackageCmdSet1String = "d58a999f-4a1b-42df-839a-cb31a0a4fed7"; + public static Guid guidOutputToolWindowPackageCmdSet1 = new Guid(guidOutputToolWindowPackageCmdSet1String); + + public const string guidImages1String = "8252a6d7-bcf3-4518-ae22-ad20ef8d4b63"; + public static Guid guidImages1 = new Guid(guidImages1String); } /// /// Helper class that encapsulates all CommandIDs uses across VS Package. @@ -28,5 +34,7 @@ internal sealed partial class PackageIds { public const int OutputToolWindowCommandId = 0x0100; public const int bmpPic1 = 0x0001; + public const int MyMenuGroup = 0x1020; + public const int cmdidClearUICommand = 0x0100; } } \ No newline at end of file diff --git a/FineCodeCoverage/Output/Resources/ClearUICommand.png b/FineCodeCoverage/Output/Resources/ClearUICommand.png new file mode 100644 index 00000000..7c8a4d2b Binary files /dev/null and b/FineCodeCoverage/Output/Resources/ClearUICommand.png differ diff --git a/README.md b/README.md index b351945a..54c64c8b 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ Introduction Fine Code Coverage works by reacting to the visual studio test explorer, providing coverage from each test project containing tests that you have selected to run. This coverage is presented as a single unified report as well as coloured margins alongside your code. +This coverage is not dynamic and represents the coverage obtained from the last time you executed tests. +When the coverage becomes outdated, you can click the 'FCC Clear UI' button in Tools or run coverage again. + The coverage is provided by either [OpenCover](https://github.com/OpenCover/opencover) for old style projects and [Coverlet](https://github.com/coverlet-coverage/coverlet) for new style sdk projects. FCC provides an abstraction over both so that it is possible to ignore the differences between the two but there are circumstances where it is important to be aware of cover tool that will be run. This is most apparent when Coverlet is used, please read on for the specifics.