From afe0f3eabd0bb4d4b5e20df4a4a4ab1d1b4dcc21 Mon Sep 17 00:00:00 2001 From: Viacheslav Lozinskyi Date: Mon, 23 Mar 2020 23:21:58 +0200 Subject: [PATCH] Output window for visualization of OpenCppCoverage results is significantly improved. --- .../CoverageRateBuilder.cs | 19 +++++++++++++++++++ VSPackage/CoverageRunner.cs | 12 ++++++------ .../CoverageTree/CoverageTreeController.cs | 3 +++ VSPackage/CoverageTree/CoverageTreeManager.cs | 8 ++++---- VSPackage/ErrorHandler.cs | 13 +++++++------ VSPackage/OpenCppCoverageCmdLine.cs | 3 ++- VSPackage/OpenCppCoveragePackage.cs | 10 +++++----- VSPackage/OpenCppCoverageRunner.cs | 7 +++---- VSPackage/OutputWindowWriter.cs | 8 ++++---- VSPackage/ProjectBuilder.cs | 11 ++++------- VSPackage/Settings/SettingsStorage.cs | 7 +++++-- .../Settings/StartUpProjectSettingsBuilder.cs | 3 ++- .../Settings/UI/MainSettingController.cs | 1 + VSPackage/TemporaryFile.cs | 3 ++- VSPackage/VSPackage.csproj | 3 --- VSPackage/source.extension.vsixmanifest | 2 +- 16 files changed, 68 insertions(+), 45 deletions(-) diff --git a/VSPackage/CoverageRateBuilder/CoverageRateBuilder.cs b/VSPackage/CoverageRateBuilder/CoverageRateBuilder.cs index 530c376..2cdde5c 100644 --- a/VSPackage/CoverageRateBuilder/CoverageRateBuilder.cs +++ b/VSPackage/CoverageRateBuilder/CoverageRateBuilder.cs @@ -37,6 +37,7 @@ public CoverageRate Build(CoverageResult result) foreach (var protoFile in protoModule.FilesList) module.AddChild(BuildFileCoverage(protoFile)); coverageRate.AddChild(module); + Update(module); } return coverageRate; @@ -52,5 +53,23 @@ FileCoverage BuildFileCoverage(ProtoBuff.FileCoverage protoFile) lines.Select(l => new LineCoverage( (int)l.LineNumber, l.HasBeenExecuted)).ToList()); } + + private static void Update(ModuleCoverage module) + { + OutputWindowWriter.WriteLine("PROJECT: \"" + module.Name + "\"\u0004 // " + GetProgress(module.CoverLineCount, module.TotalLineCount)); + foreach (FileCoverage current in module.Children) + { + OutputWindowWriter.WriteLine(" FILE: \"" + current.Path + "\" // " + GetProgress(current.CoverLineCount, current.TotalLineCount)); + } + } + + private static string GetProgress(int current, int total) + { + if (total > 0) + { + return ((current * 100) / total).ToString() + "%"; + } + return "100%"; + } } } diff --git a/VSPackage/CoverageRunner.cs b/VSPackage/CoverageRunner.cs index 9bfc833..a6519a0 100644 --- a/VSPackage/CoverageRunner.cs +++ b/VSPackage/CoverageRunner.cs @@ -94,7 +94,6 @@ public void RunCoverageOnStartupProject(MainSettings settings) void RunCoverage(MainSettings settings) { outputWindowWriter.ActivatePane(); - outputWindowWriter.WriteLine("Start computing code coverage..."); if (!File.Exists(settings.BasicSettings.ProgramToRun)) { @@ -109,9 +108,10 @@ void RunCoverage(MainSettings settings) AddBinaryOutput(settings.ImportExportSettings, coveragePath); onCoverageFinished = openCppCoverageRunner.RunCodeCoverageAsync(settings); } - catch (Exception) + catch (Exception e) { coveragePath.Dispose(); + OutputWindowWriter.WriteLine("ERROR: " + e.Message); throw; } @@ -148,12 +148,12 @@ void OnCoverageRateBuilt(CoverageRate coverageRate, string coveragePath) { if (coverageRate == null) { - outputWindowWriter.WriteLine("The execution of the previous line failed." + - " Please execute the previous line in a promt" + - " command to have more information about the issue."); + OutputWindowWriter.WriteLine("ERROR: The execution of the previous line failed."); + OutputWindowWriter.WriteLine(" Please execute the previous line in a promt command to have more information about the issue."); throw new VSPackageException("Cannot generate coverage. See output pane for more information"); } - outputWindowWriter.WriteLine("Coverage written in " + coveragePath); + OutputWindowWriter.WriteLine("COVERAGE: Computing finished\u0006"); + OutputWindowWriter.WriteLine(" Result written in \"" + coveragePath + "\""); coverageTreeManager.ShowTreeCoverage(this.dte, this.coverageViewManager, coverageRate); this.coverageViewManager.CoverageRate = coverageRate; diff --git a/VSPackage/CoverageTree/CoverageTreeController.cs b/VSPackage/CoverageTree/CoverageTreeController.cs index e47c33f..80c0d73 100644 --- a/VSPackage/CoverageTree/CoverageTreeController.cs +++ b/VSPackage/CoverageTree/CoverageTreeController.cs @@ -74,7 +74,10 @@ public SharpTreeNode Current if (fileCoverage != null) { if (this.dte == null) + { + //outputWindowWriter.WriteLine("ERROR: UpdateCoverageRate should be call first."); throw new InvalidOperationException("UpdateCoverageRate should be call first."); + } this.dte.ItemOperations.OpenFile(fileCoverage.Path, Constants.vsViewKindCode); } } diff --git a/VSPackage/CoverageTree/CoverageTreeManager.cs b/VSPackage/CoverageTree/CoverageTreeManager.cs index 6a718ef..d1d632a 100644 --- a/VSPackage/CoverageTree/CoverageTreeManager.cs +++ b/VSPackage/CoverageTree/CoverageTreeManager.cs @@ -50,11 +50,11 @@ public void ShowTreeCoverage() //--------------------------------------------------------------------- void ShowTreeCoverage(Action action) { - var window = this.windowFinder.FindToolWindow(); + //var window = this.windowFinder.FindToolWindow(); - action(window); - var frame = (IVsWindowFrame)window.Frame; - Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(frame.Show()); + //action(window); + //var frame = (IVsWindowFrame)window.Frame; + //Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(frame.Show()); } } } diff --git a/VSPackage/ErrorHandler.cs b/VSPackage/ErrorHandler.cs index 88f7ce3..db12853 100644 --- a/VSPackage/ErrorHandler.cs +++ b/VSPackage/ErrorHandler.cs @@ -38,18 +38,19 @@ public async Task ExecuteAsync(Func action) { await action(); } - catch (VSPackageException exception) + catch (VSPackageException e) { if (OutputWriter != null) - OutputWriter.WriteLine(exception.Message); - ShowMessage(exception.Message); + OutputWindowWriter.WriteLine("ERROR: " + e.Message); + ShowMessage(e.Message); } - catch (Exception exception) + catch (Exception e) { - if (OutputWriter != null && OutputWriter.WriteLine(exception.ToString())) + if (OutputWriter != null && OutputWindowWriter.WriteLine("ERROR: " + e.ToString())) ShowMessage("Unknow error. Please see the output console for more information."); else - ShowMessage(exception.ToString()); + ShowMessage(e.ToString()); + OutputWindowWriter.WriteLine("ERROR: " + e.Message); } } diff --git a/VSPackage/OpenCppCoverageCmdLine.cs b/VSPackage/OpenCppCoverageCmdLine.cs index e00305a..5845dd8 100644 --- a/VSPackage/OpenCppCoverageCmdLine.cs +++ b/VSPackage/OpenCppCoverageCmdLine.cs @@ -155,9 +155,10 @@ void AppendMiscellaneousSettings( foreach (var line in lines) writer.WriteLine(line); } - catch (FileNotFoundException) + catch (FileNotFoundException e) { string message = $"Cannot find the config file defined in Miscellanous tab: {settings.OptionalConfigFile}"; + OutputWindowWriter.WriteLine("ERROR: " + e.Message); throw new VSPackageException(message); } } diff --git a/VSPackage/OpenCppCoveragePackage.cs b/VSPackage/OpenCppCoveragePackage.cs index 61a2e93..28c44b9 100644 --- a/VSPackage/OpenCppCoveragePackage.cs +++ b/VSPackage/OpenCppCoveragePackage.cs @@ -44,11 +44,11 @@ namespace OpenCppCoverage.VSPackage [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // This attribute is needed to let the shell know that this package exposes some menus. [ProvideMenuResource("Menus.ctmenu", 1)] - [ProvideToolWindow(typeof(CoverageTreeToolWindow), - Style = Microsoft.VisualStudio.Shell.VsDockStyle.Tabbed, - MultiInstances = false, - Transient = true, - Window = Microsoft.VisualStudio.Shell.Interop.ToolWindowGuids.Outputwindow)] + //[ProvideToolWindow(typeof(CoverageTreeToolWindow), + // Style = Microsoft.VisualStudio.Shell.VsDockStyle.Tabbed, + // MultiInstances = false, + // Transient = true, + // Window = Microsoft.VisualStudio.Shell.Interop.ToolWindowGuids.Outputwindow)] [ProvideToolWindow(typeof(SettingToolWindow), Style = Microsoft.VisualStudio.Shell.VsDockStyle.Float, MultiInstances = false, diff --git a/VSPackage/OpenCppCoverageRunner.cs b/VSPackage/OpenCppCoverageRunner.cs index 2fc8513..b038fd2 100644 --- a/VSPackage/OpenCppCoverageRunner.cs +++ b/VSPackage/OpenCppCoverageRunner.cs @@ -18,7 +18,6 @@ using System; using System.Diagnostics; using System.IO; -using System.Runtime.InteropServices; using System.Threading.Tasks; namespace OpenCppCoverage.VSPackage @@ -44,9 +43,9 @@ public Task RunCodeCoverageAsync(MainSettings settings) var fileName = GetOpenCppCoveragePath(basicSettings.ProgramToRun); var arguments = this.openCppCoverageCmdLine.Build(settings); - this.outputWindowWriter.WriteLine("Run:"); - this.outputWindowWriter.WriteLine(string.Format(@"""{0}"" {1}", - fileName, arguments)); + OutputWindowWriter.WriteLine("COVERAGE: Computing started\u0006"); + OutputWindowWriter.WriteLine(" File name = " + fileName); + OutputWindowWriter.WriteLine(" Arguments = " + arguments); // Run in a new thread to not block UI thread. return Task.Run(() => diff --git a/VSPackage/OutputWindowWriter.cs b/VSPackage/OutputWindowWriter.cs index 458fa84..aef752f 100644 --- a/VSPackage/OutputWindowWriter.cs +++ b/VSPackage/OutputWindowWriter.cs @@ -46,16 +46,16 @@ public OutputWindowWriter(DTE2 dte, IVsOutputWindow outputWindow) //--------------------------------------------------------------------- public void ActivatePane() { - outputWindowPane_.Activate(); + //outputWindowPane_.Activate(); } //--------------------------------------------------------------------- - public bool WriteLine(string message) + public static bool WriteLine(string message) { return Microsoft.VisualStudio.ErrorHandler.Succeeded(outputWindowPane_.OutputString(message + "\n")); } - - readonly IVsOutputWindowPane outputWindowPane_; + + private static IVsOutputWindowPane outputWindowPane_ = null; public readonly static Guid OpenCppCoverageOutputPaneGuid = new Guid("CB47C727-5E45-467B-A4CD-4A025986A8A0"); } } diff --git a/VSPackage/ProjectBuilder.cs b/VSPackage/ProjectBuilder.cs index dd65949..8df93ff 100644 --- a/VSPackage/ProjectBuilder.cs +++ b/VSPackage/ProjectBuilder.cs @@ -50,10 +50,6 @@ public void Build( // buildEvents need to be a member to avoid a garbage collector issue. this.buildEvents.OnBuildProjConfigDone += buildHandler; - - this.outputWindowWriter.WriteLine( - "Start building " + projectName - + " " + solutionConfigurationName); var output = dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput); if (output != null) @@ -67,9 +63,10 @@ public void Build( } catch (COMException e) { - throw new VSPackageException( - string.Format("Error when building {0} with configuration {1}: {2}", - projectName, solutionConfigurationName, e.Message)); + OutputWindowWriter.WriteLine("ERROR: " + e.Message); + OutputWindowWriter.WriteLine(" Project = " + projectName); + OutputWindowWriter.WriteLine(" Configuration = " + solutionConfigurationName); + throw; } } diff --git a/VSPackage/Settings/SettingsStorage.cs b/VSPackage/Settings/SettingsStorage.cs index d78caee..5e3c89d 100644 --- a/VSPackage/Settings/SettingsStorage.cs +++ b/VSPackage/Settings/SettingsStorage.cs @@ -53,12 +53,14 @@ public UserInterfaceSettings TryLoad(string optionalProjectPath, string optional { json = File.ReadAllText(configPath); } - catch (FileNotFoundException) + catch (FileNotFoundException e) { + OutputWindowWriter.WriteLine("ERROR: " + e.Message); return null; } - catch (DirectoryNotFoundException) + catch (DirectoryNotFoundException e) { + OutputWindowWriter.WriteLine("ERROR: " + e.Message); return null; } @@ -70,6 +72,7 @@ public UserInterfaceSettings TryLoad(string optionalProjectPath, string optional { var error = string.Format( $"Error when deserializing {configPath} : {e.Message}\nRemoving {configPath} should fix this issue."); + OutputWindowWriter.WriteLine("ERROR: " + e.Message); throw new VSPackageException(error); } } diff --git a/VSPackage/Settings/StartUpProjectSettingsBuilder.cs b/VSPackage/Settings/StartUpProjectSettingsBuilder.cs index 1de4882..e23844c 100644 --- a/VSPackage/Settings/StartUpProjectSettingsBuilder.cs +++ b/VSPackage/Settings/StartUpProjectSettingsBuilder.cs @@ -166,9 +166,10 @@ List CreateExtendedProjectsFor(Project project) if (projectObject != null && projectObject.Kind == "VCProject") projects.Add(new ExtendedProject(project, new DynamicVCProject(projectObject))); } - catch (RuntimeBinderException) + catch (RuntimeBinderException e) { // Nothing because not a VCProject + OutputWindowWriter.WriteLine("ERROR: " + e.Message); } } diff --git a/VSPackage/Settings/UI/MainSettingController.cs b/VSPackage/Settings/UI/MainSettingController.cs index a8aa9d8..32490fe 100644 --- a/VSPackage/Settings/UI/MainSettingController.cs +++ b/VSPackage/Settings/UI/MainSettingController.cs @@ -152,6 +152,7 @@ public TabItem SelectedTab catch (Exception e) { this.CommandLineText = e.Message; + OutputWindowWriter.WriteLine("ERROR: " + e.Message); } } } diff --git a/VSPackage/TemporaryFile.cs b/VSPackage/TemporaryFile.cs index 4be7d97..b008892 100644 --- a/VSPackage/TemporaryFile.cs +++ b/VSPackage/TemporaryFile.cs @@ -39,8 +39,9 @@ public void Dispose() { File.Delete(this.Path); } - catch (FileNotFoundException) + catch (FileNotFoundException e) { + OutputWindowWriter.WriteLine("ERROR: " + e.Message); } } } diff --git a/VSPackage/VSPackage.csproj b/VSPackage/VSPackage.csproj index 57ff6a7..0100862 100644 --- a/VSPackage/VSPackage.csproj +++ b/VSPackage/VSPackage.csproj @@ -277,9 +277,6 @@ true PreserveNewest - - true - true diff --git a/VSPackage/source.extension.vsixmanifest b/VSPackage/source.extension.vsixmanifest index 8a3d997..f1d2316 100644 --- a/VSPackage/source.extension.vsixmanifest +++ b/VSPackage/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + OpenCppCoverage Plugin Visual Studio plugin for OpenCppCoverage to compute code coverage for C++ application. https://github.com/OpenCppCoverage/OpenCppCoveragePlugin