diff --git a/SharedProject/Core/Model/CoverageProject.cs b/SharedProject/Core/Model/CoverageProject.cs index 144286fa..2ee58364 100644 --- a/SharedProject/Core/Model/CoverageProject.cs +++ b/SharedProject/Core/Model/CoverageProject.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Task = System.Threading.Tasks.Task; using System.Xml.Linq; using System.Xml.XPath; using EnvDTE; @@ -355,7 +356,7 @@ public XElement ProjectFileXElement public bool Is64Bit { get; set; } public string RunSettingsFile { get; set; } - public async System.Threading.Tasks.Task StepAsync(string stepName, Func action) + public async Task StepAsync(string stepName, Func action) { if (HasFailed) { @@ -380,7 +381,7 @@ public async System.Threading.Tasks.Task StepAsync(string stepName, Func PrepareForCoverageAsync() + public async Task PrepareForCoverageAsync() { EnsureDirectories(); CleanFCCDirectory(); @@ -389,7 +390,7 @@ public async System.Threading.Tasks.Task referencedProjects = await GetReferencedProjectsAsync(); SetExcludedReferencedProjects(referencedProjects); diff --git a/SharedProject/Core/ReportGenerator/ReportGeneratorUtil.cs b/SharedProject/Core/ReportGenerator/ReportGeneratorUtil.cs index e53cfc88..12d442c2 100644 --- a/SharedProject/Core/ReportGenerator/ReportGeneratorUtil.cs +++ b/SharedProject/Core/ReportGenerator/ReportGeneratorUtil.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Task = System.Threading.Tasks.Task; using System.Windows; using ExCSS; using FineCodeCoverage.Core.Utilities; @@ -25,8 +26,8 @@ interface IReportGeneratorUtil string ProcessUnifiedHtml(string htmlForProcessing,string reportOutputFolder); Task GenerateAsync(IEnumerable coverOutputFiles,string reportOutputFolder, bool throwError = false); string BlankReport(bool withHistory); - System.Threading.Tasks.Task LogCoverageProcessAsync(string message); - System.Threading.Tasks.Task EndOfCoverageRunAsync(); + Task LogCoverageProcessAsync(string message); + Task EndOfCoverageRunAsync(); } internal class ReportGeneratorResult @@ -124,12 +125,12 @@ IEventAggregator eventAggregator scriptManager.ShowFCCOutputPaneEvent += ScriptManager_ShowFCCOutputPaneEvent; } - private async void ScriptManager_ShowFCCOutputPaneEvent(object sender, EventArgs e) + private void ScriptManager_ShowFCCOutputPaneEvent(object sender, EventArgs e) { - await showFCCOutputPane.ShowAsync(); + _ = ThreadHelper.JoinableTaskFactory.RunAsync(() => showFCCOutputPane.ShowAsync()); } - private void ScriptManager_ClearFCCWindowLogsEvent(object sender, EventArgs e) + private void ScriptManager_ClearFCCWindowLogsEvent(object sender, EventArgs e) { logs.Clear(); } @@ -1686,14 +1687,14 @@ public string BlankReport(bool withHistory) return ProcessUnifiedHtml(resourceProvider.ReadResource("dummyReportToProcess.html"),null); } - public async System.Threading.Tasks.Task LogCoverageProcessAsync(string message) + public async Task LogCoverageProcessAsync(string message) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); eventAggregator.SendMessage(new InvokeScriptMessage(CoverageLogJSFunctionName, message)); logs.Add(message); } - public async System.Threading.Tasks.Task EndOfCoverageRunAsync() + public async Task EndOfCoverageRunAsync() { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); eventAggregator.SendMessage(new InvokeScriptMessage(ShowFCCWorkingJSFunctionName, false)); diff --git a/SharedProject/Impl/CoverageColorProvider.cs b/SharedProject/Impl/CoverageColorProvider.cs index 749407c3..18b6f9d9 100644 --- a/SharedProject/Impl/CoverageColorProvider.cs +++ b/SharedProject/Impl/CoverageColorProvider.cs @@ -102,29 +102,33 @@ private void UpdateFromFontsAndColorsIfNecessary() private void UpdateColoursFromFontsAndColors() { - ThreadHelper.ThrowIfNotOnUIThread(); - var success = fontAndColorStorage.OpenCategory(ref categoryWithCoverage, storeFlags); - if (success == VSConstants.S_OK) + ThreadHelper.JoinableTaskFactory.Run(async () => { - CoverageTouchedArea = GetColor("Coverage Touched Area"); - CoverageNotTouchedArea = GetColor("Coverage Not Touched Area"); - CoveragePartiallyTouchedArea = GetColor("Coverage Partially Touched Area"); - } - fontAndColorStorage.CloseCategory(); - //throw ? - requiresFromFontsAndColours = false; - } - - private System.Windows.Media.Color GetColor(string displayName) - { - ThreadHelper.ThrowIfNotOnUIThread(); - var touchAreaInfo = new ColorableItemInfo[1]; - var getItemSuccess = fontAndColorStorage.GetItem(displayName, touchAreaInfo); - if (getItemSuccess == VSConstants.S_OK) - { - return ParseColor(touchAreaInfo[0].crBackground); - } - throw new Exception("Failed to get color"); + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + var success = fontAndColorStorage.OpenCategory(ref categoryWithCoverage, storeFlags); + if (success == VSConstants.S_OK) + { + // https://github.com/microsoft/vs-threading/issues/993 + System.Windows.Media.Color GetColor(string displayName) + { + var touchAreaInfo = new ColorableItemInfo[1]; + var getItemSuccess = fontAndColorStorage.GetItem(displayName, touchAreaInfo); + if (getItemSuccess == VSConstants.S_OK) + { + return ParseColor(touchAreaInfo[0].crBackground); + } + throw new Exception("Failed to get color"); + } + + CoverageTouchedArea = GetColor("Coverage Touched Area"); + CoverageNotTouchedArea = GetColor("Coverage Not Touched Area"); + CoveragePartiallyTouchedArea = GetColor("Coverage Partially Touched Area"); + } + fontAndColorStorage.CloseCategory(); + //throw ? + requiresFromFontsAndColours = false; + }); + } private System.Windows.Media.Color ParseColor(uint color) @@ -133,7 +137,6 @@ private System.Windows.Media.Color ParseColor(uint color) return System.Windows.Media.Color.FromArgb(dcolor.A, dcolor.R, dcolor.G, dcolor.B); } - } } \ No newline at end of file diff --git a/SharedProject/Impl/Logger.cs b/SharedProject/Impl/Logger.cs index 0f2b6af4..ea319ca8 100644 --- a/SharedProject/Impl/Logger.cs +++ b/SharedProject/Impl/Logger.cs @@ -2,18 +2,18 @@ using System.Linq; using FineCodeCoverage; using System.Diagnostics; -using Microsoft.VisualStudio; using System.Collections.Generic; using Microsoft.VisualStudio.Shell; using System.Diagnostics.CodeAnalysis; using Microsoft.VisualStudio.Shell.Interop; using System.ComponentModel.Composition; using Microsoft; -using EnvDTE; +using Task = System.Threading.Tasks.Task; +using EnvDTE80; interface IShowFCCOutputPane { - System.Threading.Tasks.Task ShowAsync(); + Task ShowAsync(); } [Export(typeof(IShowFCCOutputPane))] [Export(typeof(ILogger))] @@ -21,7 +21,7 @@ public class Logger : ILogger, IShowFCCOutputPane { private IVsOutputWindowPane _pane; private IVsOutputWindow _outputWindow; - private DTE dte; + private DTE2 dte; private readonly IServiceProvider _serviceProvider; private Guid fccPaneGuid = Guid.Parse("3B3C775A-0050-445D-9022-0230957805B2"); @@ -35,33 +35,27 @@ IServiceProvider serviceProvider staticLogger = this; } - IVsOutputWindowPane CreatePane(Guid paneGuid, string title, - bool visible, bool clearWithSolution) - { - - ThreadHelper.ThrowIfNotOnUIThread(); - _outputWindow = (IVsOutputWindow)_serviceProvider.GetService(typeof(SVsOutputWindow)); - Assumes.Present(_outputWindow); - dte = (EnvDTE.DTE)_serviceProvider.GetService(typeof(EnvDTE.DTE)); - Assumes.Present(dte); - - // Create a new pane. - _outputWindow.CreatePane( - ref paneGuid, - title, - Convert.ToInt32(visible), - Convert.ToInt32(clearWithSolution)); - - // Retrieve the new pane. - _outputWindow.GetPane(ref paneGuid, out IVsOutputWindowPane pane); - return pane; - } - private void SetPane() { - ThreadHelper.ThrowIfNotOnUIThread(); - // do not clear with solution otherwise will not get initialize methods - _pane = CreatePane(fccPaneGuid, "FCC", true, false); + ThreadHelper.JoinableTaskFactory.Run(async () => + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + _outputWindow = (IVsOutputWindow)_serviceProvider.GetService(typeof(SVsOutputWindow)); + Assumes.Present(_outputWindow); + dte = (DTE2)_serviceProvider.GetService(typeof(EnvDTE.DTE)); + Assumes.Present(dte); + + // Create a new pane. + _outputWindow.CreatePane( + ref fccPaneGuid, + "FCC", + Convert.ToInt32(true), + Convert.ToInt32(false)); // do not clear with solution otherwise will not get initialize methods + + // Retrieve the new pane. + _outputWindow.GetPane(ref fccPaneGuid, out IVsOutputWindowPane pane); + _pane = pane; + }); } [SuppressMessage("Usage", "VSTHRD102:Implement internal logic asynchronously")] @@ -154,7 +148,7 @@ public void LogWithoutTitle(IEnumerable message) LogImpl(message.ToArray(), false); } - public async System.Threading.Tasks.Task ShowAsync() + public async Task ShowAsync() { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); diff --git a/SharedProject/Impl/TestContainerDiscovery/PackageInitializer.cs b/SharedProject/Impl/TestContainerDiscovery/PackageInitializer.cs index 4d7c0d26..b3f93e39 100644 --- a/SharedProject/Impl/TestContainerDiscovery/PackageInitializer.cs +++ b/SharedProject/Impl/TestContainerDiscovery/PackageInitializer.cs @@ -41,12 +41,12 @@ public void Initialize() if (File.Exists(outputWindowInitializedFile)) { - OutputToolWindowCommand.Instance.FindToolWindow(); + await OutputToolWindowCommand.Instance.FindToolWindowAsync(); } else { // for first time users, the window is automatically docked - OutputToolWindowCommand.Instance.ShowToolWindow(); + await OutputToolWindowCommand.Instance.ShowToolWindowAsync(); File.WriteAllText(outputWindowInitializedFile, string.Empty); } } diff --git a/SharedProject/Options/AppOptions.cs b/SharedProject/Options/AppOptions.cs index 65ad9b6a..cd998dd5 100644 --- a/SharedProject/Options/AppOptions.cs +++ b/SharedProject/Options/AppOptions.cs @@ -175,7 +175,6 @@ You can also ignore additional attributes by adding to this list (short name or [Description("Set to true to hide classes, namespaces and assemblies that are fully covered.")] public bool HideFullyCovered { get; set; } - [SuppressMessage("Usage", "VSTHRD010:Invoke single-threaded types on Main thread")] public override void SaveSettingsToStorage() { AppOptionsStorageProvider.SaveSettingsToStorage(this); diff --git a/SharedProject/Options/AppOptionsProvider.cs b/SharedProject/Options/AppOptionsProvider.cs index 4542ea99..58c6a549 100644 --- a/SharedProject/Options/AppOptionsProvider.cs +++ b/SharedProject/Options/AppOptionsProvider.cs @@ -35,16 +35,21 @@ public IAppOptions Get() return options; } - [SuppressMessage("Usage", "VSTHRD010:Invoke single-threaded types on Main thread")] private WritableSettingsStore EnsureStore() { - var settingsManager = new ShellSettingsManager(ServiceProvider.GlobalProvider); - var settingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); - - if (!settingsStore.CollectionExists(Vsix.Code)) + WritableSettingsStore settingsStore = null; + ThreadHelper.JoinableTaskFactory.Run(async () => { - settingsStore.CreateCollection(Vsix.Code); - } + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + var settingsManager = new ShellSettingsManager(ServiceProvider.GlobalProvider); + settingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); + + if (!settingsStore.CollectionExists(Vsix.Code)) + { + settingsStore.CreateCollection(Vsix.Code); + } + }); + return settingsStore; } @@ -53,7 +58,6 @@ private PropertyInfo[] ReflectProperties() return AppOptionsType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance); } - [SuppressMessage("Usage", "VSTHRD010:Invoke single-threaded types on Main thread")] public void LoadSettingsFromStorage(AppOptions instance) { var settingsStore = EnsureStore(); @@ -85,7 +89,7 @@ public void LoadSettingsFromStorage(AppOptions instance) } } } - [SuppressMessage("Usage", "VSTHRD010:Invoke single-threaded types on Main thread")] + public void SaveSettingsToStorage(AppOptions appOptions) { var settingsStore = EnsureStore(); diff --git a/SharedProject/Output/OutputToolWindowCommand.cs b/SharedProject/Output/OutputToolWindowCommand.cs index 669e3ead..5b560e43 100644 --- a/SharedProject/Output/OutputToolWindowCommand.cs +++ b/SharedProject/Output/OutputToolWindowCommand.cs @@ -1,6 +1,7 @@ using System; using System.ComponentModel.Design; using Microsoft.VisualStudio.Shell; +using System.Threading.Tasks; using Task = System.Threading.Tasks.Task; namespace FineCodeCoverage.Output @@ -82,39 +83,29 @@ public static async Task InitializeAsync(AsyncPackage package) /// The event args. public void Execute(object sender, EventArgs e) { - ShowToolWindow(); + _ = ThreadHelper.JoinableTaskFactory.RunAsync(ShowToolWindowAsync); } - public ToolWindowPane ShowToolWindow() + public async Task ShowToolWindowAsync() { - ToolWindowPane window = null; + ToolWindowPane window = await package.ShowToolWindowAsync(typeof(OutputToolWindow), 0, true, package.DisposalToken); - package.JoinableTaskFactory.RunAsync(async delegate + if ((null == window) || (null == window.Frame)) { - window = await package.ShowToolWindowAsync(typeof(OutputToolWindow), 0, true, package.DisposalToken); - - if ((null == window) || (null == window.Frame)) - { - throw new NotSupportedException($"Cannot create '{Vsix.Name}' output window"); - } - }); + throw new NotSupportedException($"Cannot create '{Vsix.Name}' output window"); + } return window; } - public ToolWindowPane FindToolWindow() + public async Task FindToolWindowAsync() { - ToolWindowPane window = null; + ToolWindowPane window = await package.FindToolWindowAsync(typeof(OutputToolWindow), 0, true, package.DisposalToken); - package.JoinableTaskFactory.RunAsync(async delegate + if ((null == window) || (null == window.Frame)) { - window = await package.FindToolWindowAsync(typeof(OutputToolWindow), 0, true, package.DisposalToken); - - if ((null == window) || (null == window.Frame)) - { - throw new NotSupportedException($"Cannot create '{Vsix.Name}' output window"); - } - }); + throw new NotSupportedException($"Cannot create '{Vsix.Name}' output window"); + } return window; } diff --git a/SharedProject/Output/OutputToolWindowPackage.cs b/SharedProject/Output/OutputToolWindowPackage.cs index c3d285d2..9218dfca 100644 --- a/SharedProject/Output/OutputToolWindowPackage.cs +++ b/SharedProject/Output/OutputToolWindowPackage.cs @@ -5,6 +5,7 @@ using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis; using System.ComponentModel.Composition; +using System.Threading.Tasks; using Task = System.Threading.Tasks.Task; using Microsoft.VisualStudio.Shell.Interop; using EnvDTE80; @@ -91,9 +92,9 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke await ClearUICommand.InitializeAsync(this, componentModel.GetService()); } - protected override System.Threading.Tasks.Task InitializeToolWindowAsync(Type toolWindowType, int id, CancellationToken cancellationToken) + protected override Task InitializeToolWindowAsync(Type toolWindowType, int id, CancellationToken cancellationToken) { - return System.Threading.Tasks.Task.FromResult(GetOutputToolWindowContext()); + return Task.FromResult(GetOutputToolWindowContext()); } public override IVsAsyncToolWindowFactory GetAsyncToolWindowFactory(Guid toolWindowType) {