diff --git a/README.md b/README.md index 487ed102f..0cb7e5e20 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ To get a quick understanding about ESP-IDF and Eclipse plugin features check our * [ Device Firmware Upgrade (DFU) through USB ](#deviceFirmwareUpgrade)
* [ GDBStub Debugging ](#gdbStubDebugging)
* [ Core Dump Debugging ](#coreDumpDebugging)
+* [ GCOV Code Coverage and Dump Generation ](#gcovCodeCoverage)
* [ Application Level Tracing ](#appLvlTracing)
* [ ESP-IDF master update](#updateEspIdfMaster)
* [ Partition Table Editor UI for ESP-IDF](#partitionTableEditor)
@@ -581,6 +582,38 @@ This will enable the core dump debugging and whenever you connect a serial monit You can view the registers stack trace and even view the value of variables in stack frame. To exit the debug session simply press stop button. + + +# GCOV Code Coverage and Dump Generation + +The idf eclipse plugin allows you to generate and view the gcov code coverage reports. + +For the purpose of the this documentation please use the example project [gcov](https://github.com/espressif/esp-idf/blob/master/examples/system/gcov/). +You can read about the project more in the project [README.MD](https://github.com/espressif/esp-idf/blob/master/examples/system/gcov/README.md) to learn more about the flags required to enable this. + +After building and flashing the project you can start a normal debug session using the OpenOCD Launch Configuration. Once the debug session starts and the eclipse switches to the debug prespective you will notice two buttons on the IDF Process Console. +![](docs/images/GcovCodeCoverage/gcov-1.png) + +The first button is to generate the instant runtime dump and the second button is to generate the hard coded dump. Based on where your program is you can create a dump. As per the example project the program halts twice for you to generate the hard-coded dump which you can do by pressing the second button. +The instant runtime dump can be generated by pressing the first button after the hard-coded dump is complete. + +After your dumps are generated you can right click on the project and select the following option. +`ESP-IDF: View GCOV Files` + +![](docs/images/GcovCodeCoverage/gcov-2.png) + +This will open a view for you that will show you the dumps that are available for the eclipse to be analyzed. +![](docs/images/GcovCodeCoverage/gcov-3.png) + +You can press the refresh button to update the view to show the latest files and use the select project button to select a different project. +Only one name is shown for both gcno and gcda files and only files that have a matching partner file with gcno or gcda are shown here. + +You can double click on any shown file and you will receive the following dialog. ![](docs/images/GcovCodeCoverage/gcov-4.png). +You can either select to view the coverage for the selected file only or view the whole coverage +Depending upon what you selected you will either be shown the file and also a view that will contain the whole summary for the coverage. +![Summary View](docs/images/GcovCodeCoverage/gcov-5.png) +![File View](docs/images/GcovCodeCoverage/gcov-6.png) + # Device Firmware Upgrade (DFU) through USB diff --git a/README_CN.md b/README_CN.md index e5e477fd6..976174f95 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,4 +1,4 @@ -[![GitHub 发布](https://img.shields.io/github/release/espressif/idf-eclipse-plugin.svg)](https://github.com/espressif/idf-eclipse-plugin/releases/latest) +[![GitHub 发布](https://img.shields.io/github/release/espressif/idf-eclipse-plugin.svg)](https://github.com/espressif/idf-eclipse-plugin/releases/latest) [English](./README.md) @@ -43,6 +43,7 @@ ESP-IDF Eclipse 插件支持 `macOS`、`Window` 和 `Linux` 操作系统。 * [导入一个现有的 Debug 启动配置](#importDebugLaunchConfig)
* [通过 USB 升级设备固件 (DFU)](#deviceFirmwareUpgrade)
* [GDBStub 调试](#gdbStubDebugging)
+* [GCOV Code Coverage and Dump Generation](#gcovCodeCoverage)
* [应用层追踪](#appLvlTracing)
* [ESP-IDF master 分支更新](#updateEspIdfMaster)
* [更改语言](#changeLanguage)
@@ -57,9 +58,9 @@ ESP-IDF Eclipse 插件支持 `macOS`、`Window` 和 `Linux` 操作系统。 IDF Eclipse 插件的运行环境要求如下。 * **Java 11 及以上**:点击这里下载并安装 Java SE -* **Python 3.6 及以上**:点击这里下载并安装 Python -* **Eclipse IDE C/C++ 开发工具 2022-06(2021-06 及以上)**:点击这里下载并安装 Eclipse CDT 安装包 -* **Git**:点击这里获得最新 Git +* **Python 3.6 及以上**:点击这里下载并安装 Python +* **Eclipse IDE C/C++ 开发工具 2022-06(2021-06 及以上)**:点击这里下载并安装 Eclipse CDT 安装包 +* **Git**:点击这里获得最新 Git * **ESP-IDF 4.0 及以上**:点击这里克隆 ESP-IDF 仓库 > **Note:** 请确保系统环境 `PATH` 可以访问 Java、Python 和 Git。 @@ -83,7 +84,7 @@ IDF Eclipse 插件的运行环境要求如下。 * 测试版:https://dl.espressif.com/dl/idf-eclipse-plugin/updates/beta/ * 每日构建版:https://dl.espressif.com/dl/idf-eclipse-plugin/updates/nightly/ * 点击`添加`。 -1. 从列表中选择`Espressif IDF`,并按照提示完成所有安装步骤。 +1. 从列表中选择`Espressif IDF`,并按照提示完成所有安装步骤。 > **Note:** 本文档中的所有截图均来自 `macOS` 操作系统,但安装步骤同时适用于 `Windows`、`Linux` 和 `macOS` 操作系统。 @@ -203,7 +204,7 @@ ESP-IDF 的 `idf.py` 工具可以打包 `make flash` 命令和常用指令。用 # 查看串口输出 -为了查看 Eclipse 的串口输出,我们需要在`ESP-IDF 串口监视器`中配置需要监测的串口。本功能已经集成至`IDF 监视器`。更多详情,请见 这里。 +为了查看 Eclipse 的串口输出,我们需要在`ESP-IDF 串口监视器`中配置需要监测的串口。本功能已经集成至`IDF 监视器`。更多详情,请见 这里。 1. 点击工具栏中的`打开终端`图标。 1. 从终端下拉菜单中选择`ESP-IDF 串口监视器`。 @@ -215,7 +216,7 @@ ESP-IDF 的 `idf.py` 工具可以打包 `make flash` 命令和常用指令。用 ### ESP-IDF 串口监视器设置 -设置 ESP-IDF 串口监视器的字符和行数上限: +设置 ESP-IDF 串口监视器的字符和行数上限: 1. 进入 Eclipse 偏好设置,选择 `乐鑫` 1. 点击 `ESP-IDF 串口监视器设置` 1. 配置 `控制台行宽 (Console Line Width)` 和 `控制台输出上限 (Limit Console Output)` @@ -276,7 +277,7 @@ ESP-IDF Eclipse 插件中还集成了一个 CMake 编辑器,允许用户编辑 # ESP-IDF 终端 -`ESP-IDF 终端`可为用户在 Eclipse 环境中启动一个本地终端窗口。用户可通过`偏好设置`>`C/C++`>`构建`>`环境`配置所有环境变量。本终端窗口的默认工作目录为当前选定的项目或 `IDF_PATH`(如未选定项目)。 +`ESP-IDF 终端`可为用户在 Eclipse 环境中启动一个本地终端窗口。用户可通过`偏好设置`>`C/C++`>`构建`>`环境`配置所有环境变量。本终端窗口的默认工作目录为当前选定的项目或 `IDF_PATH`(如未选定项目)。 终端 PATH 还将同时配置 `esptool`、`espcoredump`、`partition_table` 和 `app_update` 组件路径,允许用户从 ESP-IDF 终端直接进行访问。 @@ -313,7 +314,7 @@ ESP-IDF Eclipse 插件中还集成了一个 CMake 编辑器,允许用户编辑 如上述环境变量未能自动正确配置,请按照以下步骤操作。 -1. 前往`C/C++ 构建`下的`环境`偏好设置页。 +1. 前往`C/C++ 构建`下的`环境`偏好设置页。 1. 再次点击`添加...`,并输入`IDF_PATH`,即 ESP-IDF 的完整安装路径。 1. 按照相同步骤,配置 OPENOCD_SCRIPTS、IDF_PYTHON_ENV_PATH 和 PATH 环境变量 @@ -398,10 +399,10 @@ IDF Eclipse 插件可支持不同语言。如需更改,请按照以下步骤 注意,上述操作仅提供针对插件界面的汉化。如需全部汉化,则请另外安装 Eclipse 汉化包。 -# 故障排除 +# 故障排除 ## 错误日志 -`错误日志`视图可以显示插件记录的所有警告和错误,其底层日志文件 (.log 文件) 保存在工作空间的 .metadata 子目录下。 +`错误日志`视图可以显示插件记录的所有警告和错误,其底层日志文件 (.log 文件) 保存在工作空间的 .metadata 子目录下。 打开`错误日志`视图,请前往`窗口`>`显示视图`>`错误日志`。 @@ -414,7 +415,7 @@ IDF Eclipse 插件可支持不同语言。如需更改,请按照以下步骤 ## 控制台视图日志 `控制台`视图可显示与当前运行或构建有关的所有警告和错误。 -打开`控制台`视图,请前往`窗口`>`显示视图`>`控制台`。 +打开`控制台`视图,请前往`窗口`>`显示视图`>`控制台`。 ![](docs/images/CDT_Build_Console.png) @@ -422,7 +423,7 @@ IDF Eclipse 插件可支持不同语言。如需更改,请按照以下步骤 打开 CDT 全局构建日志,请前往`偏好设置`>`C/C++`>`构建`>`日志` ## 乐鑫 IDF 工具集控制台 -`乐鑫 IDF 工具控制台`为`控制台`视图的组成部分,通常仅在通过 Eclipse 安装 IDF 工具集时使用。 +`乐鑫 IDF 工具控制台`为`控制台`视图的组成部分,通常仅在通过 Eclipse 安装 IDF 工具集时使用。 如您在通过`乐鑫`>`ESP-IDF 工具管理器`>`安装工具`方式安装 IDF 工具集时出现任何问题,即可使用本控制台查看错误报告。 @@ -453,7 +454,7 @@ IDF Eclipse 插件可支持不同语言。如需更改,请按照以下步骤 1. 点击`添加`按钮。 1. 在`添加`仓库对话框中选择`存档`> `com.espressif.idf.update-vxxxxxxx.zip` 文件。 1. 点击`添加`。 -1. 从列表中选择`Espressif IDF`,并按照提示完成所有安装步骤。 +1. 从列表中选择`Espressif IDF`,并按照提示完成所有安装步骤。 1. 重启 Eclipse。 ![](docs/images/zh/1_idffeature_install.png) @@ -549,6 +550,39 @@ IDF Eclipse 插件可支持不同语言。如需更改,请按照以下步骤 1. 点击 `停止`。 + + +# GCOV 代码覆盖率和转储生成 + +借助 ESP-IDF Eclipse 插件,您可以生成和查看 GCOV 代码覆盖率报告。 + +请参考示例项目 [gcov](https://github.com/espressif/esp-idf/blob/master/examples/system/gcov/)来了解这一功能。 +有关启用此功能所需标志的详细信息,请查看该示例的[项目简介](https://github.com/espressif/esp-idf/blob/master/examples/system/gcov/README.md)。 + +构建并烧录项目后,您可以使用 OpenOCD 启动配置开始调试。调试会话开始后,ESP-IDF Eclipse 切换到调试视图,您会在 IDF 进程控制台上看到以下两个按键。 +![](docs/images/GcovCodeCoverage/gcov-1.png) + +第一个按键用于生成即时运行时转储,第二个按键用于生成硬编码转储。根据程序当前状态,您可以选择生成相应的转储。示例项目中的程序会暂停两次,以便您按下第二个按键生成硬编码转储。 +在硬编码转储生成完成后,您可以按下第一个按键生成即时运行时转储。 + +转储生成后,您可以右键单击项目,然后选择以下选项。 +`ESP-IDF: 查看GCOV文件` + +![](docs/images/GcovCodeCoverage/gcov-2.png) + +点击该选项后,会打开一个视图,显示可用于 Eclipse 分析的转储文件。 +![](docs/images/GcovCodeCoverage/gcov-3.png) + +点击刷新按键可更新视图以显示最新的文件,然后使用选择项目按键来选择不同的项目。 +文件名只显示一个名称,同时用于 gcno 和 gcda 文件。同时,只有具有匹配的 gcno 或 gcda 文件的文件才会显示在列表中。 + +双击列表中的任何文件,将显示以下对话框。 +![](docs/images/GcovCodeCoverage/gcov-4.png)。 +您可以选择仅查看所选文件的覆盖率,或查看整个项目的覆盖率。 +根据您的选择,系统会显示相应的信息。 +![摘要视图](docs/images/GcovCodeCoverage/gcov-5.png) +![文件视图](docs/images/GcovCodeCoverage/gcov-6.png) + # 通过 USB 升级设备固件 (DFU) @@ -604,7 +638,7 @@ ESP-IDF 的 [应用层追踪](https://docs.espressif.com/projects/esp-idf/en/lat 开始命令: * 语法:`start [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]` -* 参数: +* 参数: * `outfile`:文件路径(从任一 CPU),格式应满足 `file://path/to/file`。 * `poll_period`:可用追踪数据的轮询周期(单位:毫秒)。如果大于 0,则命令以“非阻塞”模式运行。默认值 1(1 毫秒)。 * `trace_size`:可追踪数据的最大长度限制(单位:字节)。注意,该参数使能后,追踪数据达到配置的长度后则自动停止。默认值 -1(不限制最大长度)。 @@ -661,7 +695,7 @@ ESP-IDF 的 [应用层追踪](https://docs.espressif.com/projects/esp-idf/en/lat 1. 点击 `Details`。 1. 点击左侧 `Summary`。 1. 下滑至页面底部,找到 `Artifacts`。 -1. 下载 `com.espressif.idf.update`,并按照 介绍 进行安装。 # 自定义 IDE 配置 @@ -687,5 +721,5 @@ IDE 支持配置自定义构架目录: | IEP 2.1.2 | Eclipse 2021-06, 2021-03, 2020-12, 2020-09 |Java 11 及以上 | ESP-IDF 工具安装器 (Windows) 2.9| IEP 2.1.2 增加了对 Eclipse 2021-06 的支持| | IEP 2.1.1 | Eclipse 2021-03, 2020-12, 2020-09 | Java 11 及以上 | ESP-IDF 工具安装器 (Windows) 2.8 | ESP-IDF 工具安装器 (Windows) 集成 IEP 2.1.0,需升级至 2.1.1 | IEP 2.1.0 | Eclipse 2021-03, 2020-12, 2020-09 | Java 11 及以上 | ESP-IDF 工具安装器 (Windows) 2.6 beta | IEP 2.1.0 增加了对 Eclipse 2021-03 的支持| -| IEP 2.0.0 | Eclipse 2020-12, 2020-09, 2020-06 | Java 11 及以上 | ESP-IDF 工具安装器 (Windows) 2.6 beta || +| IEP 2.0.0 | Eclipse 2020-12, 2020-09, 2020-06 | Java 11 及以上 | ESP-IDF 工具安装器 (Windows) 2.6 beta || | IEP 1.2.4 | Eclipse 2020-12, 2020-09, 2020-06, 2020-03 | Java 1.8 及以上 | 不支持 | IEP 1.2.4 增加了对 Eclipse 2020-12 的支持| \ No newline at end of file diff --git a/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF b/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF index 5dcffd652..53aa2d2d6 100644 --- a/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF +++ b/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF @@ -25,8 +25,9 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.commands, org.eclipse.jface, org.apache.commons.logging;bundle-version="1.2.0", - org.eclipse.core.variables, - org.eclipse.embedcdt.core;visibility:=reexport + org.eclipse.embedcdt.core;visibility:=reexport, + org.eclipse.linuxtools.gcov.core, + org.eclipse.core.variables Bundle-RequiredExecutionEnvironment: JavaSE-11 Automatic-Module-Name: com.espressif.idf.core Bundle-ActivationPolicy: lazy diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/GcovUtility.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/GcovUtility.java new file mode 100644 index 000000000..7a97c571f --- /dev/null +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/GcovUtility.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright 2023 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ +package com.espressif.idf.core.util; + +import org.eclipse.core.internal.registry.osgi.OSGIUtils; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.ui.PlatformUI; +import org.osgi.framework.Bundle; +import org.osgi.framework.FrameworkUtil; + +import com.espressif.idf.core.logging.Logger; + +/** + * Gcov utility to handle and manage the selected project for view and also used to setup the dialog settings + * + * @author Ali Azam Rana + * + */ +@SuppressWarnings("restriction") +public class GcovUtility +{ + private static IProject selectedProject; + + public static void setSelectedProject(IProject project) + { + selectedProject = project; + } + + public static IProject getSelectedProject() + { + return selectedProject; + } + + public static void clearSelectedProject() + { + selectedProject = null; + } + + public static void setUpDialog(IFile gcFile, String elfFile) + { + try + { + Bundle bundle = OSGIUtils.getDefault().getBundle("org.eclipse.linuxtools.gcov.core"); //$NON-NLS-1$ + Class openGcAction = bundle.loadClass("org.eclipse.linuxtools.internal.gcov.action.OpenGCAction"); //$NON-NLS-1$ + Class openGcDialog = bundle.loadClass("org.eclipse.linuxtools.internal.gcov.dialog.OpenGCDialog"); //$NON-NLS-1$ + IDialogSettings ds = PlatformUI.getDialogSettingsProvider(FrameworkUtil.getBundle(openGcAction)) + .getDialogSettings(); + IDialogSettings defaultMapping = ds.getSection(openGcDialog.getName()); + if (defaultMapping == null) + { + defaultMapping = ds.addNewSection(openGcDialog.getName()); + } + + ds.put(gcFile.getRawLocation().toOSString(), elfFile); + } + catch (Exception e) + { + Logger.log(e); + } + } +} diff --git a/bundles/com.espressif.idf.debug.gdbjtag.openocd/plugin.xml b/bundles/com.espressif.idf.debug.gdbjtag.openocd/plugin.xml index 5d82c459e..975ccf303 100644 --- a/bundles/com.espressif.idf.debug.gdbjtag.openocd/plugin.xml +++ b/bundles/com.espressif.idf.debug.gdbjtag.openocd/plugin.xml @@ -132,6 +132,17 @@ id="com.espressif.idf.ui.appLvlTracing" name="%command.name"> + + + + + diff --git a/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/dsf/Launch.java b/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/dsf/Launch.java index 8749df392..ed846fcb5 100644 --- a/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/dsf/Launch.java +++ b/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/dsf/Launch.java @@ -22,6 +22,7 @@ import org.eclipse.cdt.debug.gdbjtag.core.IGDBJtagConstants; import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor; +import org.eclipse.cdt.dsf.concurrent.DsfExecutor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; @@ -37,7 +38,6 @@ import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.ISourceLocator; -import org.eclipse.debug.internal.core.LaunchConfigurationWorkingCopy; import org.eclipse.embedcdt.debug.gdbjtag.core.dsf.GnuMcuLaunch; import com.espressif.idf.core.util.PortChecker; @@ -74,7 +74,21 @@ public Launch(ILaunchConfiguration launchConfiguration, String mode, ISourceLoca fExecutor = (DefaultDsfExecutor) getDsfExecutor(); fSession = getSession(); } - + + public DsfSession getSession() + { + return super.getSession(); + } + + public DsfServicesTracker getDsfServicesTracker() + { + return fTracker; + } + + public DsfExecutor getDsfExecutor() + { + return super.getDsfExecutor(); + } // ------------------------------------------------------------------------ @Override diff --git a/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/gcov/GcovDumpHandler.java b/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/gcov/GcovDumpHandler.java new file mode 100644 index 000000000..772f48a83 --- /dev/null +++ b/bundles/com.espressif.idf.debug.gdbjtag.openocd/src/com/espressif/idf/debug/gdbjtag/openocd/gcov/GcovDumpHandler.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright 2023 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ +package com.espressif.idf.debug.gdbjtag.openocd.gcov; + +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.DsfExecutor; +import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.IProcesses; +import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext; +import org.eclipse.cdt.dsf.mi.service.command.commands.CLICommand; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; + +import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.core.util.GcovUtility; +import com.espressif.idf.core.util.StringUtil; +import com.espressif.idf.debug.gdbjtag.openocd.dsf.Launch; +import com.espressif.idf.ui.gcov.GcovFileView; + +/** + * The gcov dump handler simply runs and suspends the debug session momentarily to send the dump commands based on which + * button was pressed + * + * @author Ali Azam Rana + * + */ +public class GcovDumpHandler extends AbstractHandler +{ + private static final String INSTANT_ID = "com.espressif.idf.gcov.instant"; + private static final String HARD_CODED_ID = "com.espressif.idf.gcov.hardcoded"; + + private IExecutionDMContext executionDMContext; + private boolean isInstant = false; + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException + { + isInstant = event.getCommand().getId().equals(INSTANT_ID); + ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); + ILaunch[] launches = launchManager.getLaunches(); + ILaunch launchActive = null; + for (ILaunch launch : launches) + { + if (!launch.isTerminated()) + { + launchActive = launch; + break; + } + } + + DsfServicesTracker dsfServicesTracker = ((Launch) launchActive).getDsfServicesTracker(); + ICommandControlService commandControlService = dsfServicesTracker.getService(ICommandControlService.class); + DsfExecutor dsfExecutor = ((Launch) launchActive).getDsfExecutor(); + IRunControl runControl = dsfServicesTracker.getService(IRunControl.class); + ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(commandControlService.getContext(), + ICommandControlDMContext.class); + IProcesses processControl = dsfServicesTracker.getService(IProcesses.class); + processControl.getProcessesBeingDebugged(controlDmc, new DataRequestMonitor(dsfExecutor, null) + { + @Override + protected void handleSuccess() + { + executionDMContext = (IExecutionDMContext) (getData()[0]); + } + }); + final ILaunch finalActiveLaunch = launchActive; + runControl.suspend(executionDMContext, new RequestMonitor(dsfExecutor, null) + { + @Override + protected void handleSuccess() + { + commandControlService.queueCommand(new CLICommand<>(commandControlService.getContext(), + isInstant ? "mon esp gcov dump" : "mon esp gcov"), new ImmediateDataRequestMonitor<>() + { + @Override + protected void handleSuccess() + { + runControl.resume(executionDMContext, new RequestMonitor(dsfExecutor, null)); + ILaunchConfiguration launchConfig = finalActiveLaunch.getLaunchConfiguration(); + Display.getDefault().asyncExec(() -> { + String projectName; + try + { + projectName = launchConfig.getAttribute( + ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, StringUtil.EMPTY); + + if (!projectName.isEmpty()) + { + IProject project = ResourcesPlugin.getWorkspace().getRoot() + .getProject(projectName); + if (project != null && project.exists()) + { + GcovUtility.setSelectedProject(project); + IWorkbenchWindow window = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow(); + if (window != null) + { + IWorkbenchPage page = window.getActivePage(); + if (page != null) + { + try + { + GcovFileView gcovFileView = (GcovFileView) page + .showView(GcovFileView.ID); + page.activate(gcovFileView); + + } + catch (PartInitException e) + { + Logger.log(e); + } + } + } + } + } + } + catch (CoreException e) + { + Logger.log(e); + } + }); + } + + @Override + protected void handleError() + { + Logger.log("Error Occurred while running dump comand resuming debug operation"); + runControl.resume(executionDMContext, new RequestMonitor(dsfExecutor, null)); + } + }); + } + }); + return null; + } +} diff --git a/bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java b/bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java index 7427f69ea..e8baaefc9 100644 --- a/bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java +++ b/bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java @@ -190,7 +190,7 @@ public Process start() throws Exception public boolean dependenciesAreInstalled() { InstallToolsHandler installToolsHandler = new InstallToolsHandler(); - IStatus status = installToolsHandler.handleWebSocketClientInstall(); + IStatus status = installToolsHandler.handlePythonDependenciesInstall(); if (status == null || status.getSeverity() == IStatus.ERROR) { Logger.log(IDFCorePlugin.getPlugin(), IDFCorePlugin.errorStatus("Unable to get the process status.", null)); //$NON-NLS-1$ diff --git a/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF b/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF index 8658b5036..f2a80cacd 100644 --- a/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF +++ b/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF @@ -41,12 +41,14 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.embedcdt.ui, org.eclipse.ltk.ui.refactoring, org.eclipse.ltk.core.refactoring, - org.eclipse.epp.mpc.ui + org.eclipse.epp.mpc.ui, + org.eclipse.core.variables;bundle-version="3.5.100" Automatic-Module-Name: com.espressif.idf.ui Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-11 Export-Package: com.espressif.idf.ui, com.espressif.idf.ui.dialogs, + com.espressif.idf.ui.gcov, com.espressif.idf.ui.handlers, com.espressif.idf.ui.preferences, com.espressif.idf.ui.tracing, diff --git a/bundles/com.espressif.idf.ui/plugin.xml b/bundles/com.espressif.idf.ui/plugin.xml index a288f248c..085ba6d14 100644 --- a/bundles/com.espressif.idf.ui/plugin.xml +++ b/bundles/com.espressif.idf.ui/plugin.xml @@ -428,6 +428,22 @@ + + + + + + + + + @@ -527,6 +544,11 @@ id="com.espressif.idf.ui.nvsEditorCommand" name="%command.name.nvsTableEditor"> + + @@ -713,4 +735,53 @@ type="java.lang.Object"> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/LogMessagesThread.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LogMessagesThread.java similarity index 97% rename from bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/LogMessagesThread.java rename to bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LogMessagesThread.java index 20e25273f..40e47c636 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/LogMessagesThread.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LogMessagesThread.java @@ -2,7 +2,7 @@ * Copyright 2022 Espressif Systems (Shanghai) PTE LTD. All rights reserved. * Use is subject to license terms. *******************************************************************************/ -package com.espressif.idf.ui.tools; +package com.espressif.idf.ui; import java.util.Queue; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/GcovFileView.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/GcovFileView.java new file mode 100644 index 000000000..89d50a209 --- /dev/null +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/GcovFileView.java @@ -0,0 +1,420 @@ +/******************************************************************************* + * Copyright 2023 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ +package com.espressif.idf.ui.gcov; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.Collator; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceVisitor; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.ISelectionService; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.ElementListSelectionDialog; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.part.ViewPart; + +import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.core.util.GcovUtility; +import com.espressif.idf.core.util.IDFUtil; + +/** + * Gcov file view that can be opened by right clicking on the project. It is used to show the gcno/gcda files as one + * unit for the selected project User can launch the eclipse's default gcov viewer by double clicking on the entries + * + * @author Ali Azam Rana + * + */ +public class GcovFileView extends ViewPart implements ISelectionListener +{ + + public static final String ID = "com.espressif.idf.ui.gcov.reportsView"; + + private Table table; + private IProject selectedProject; + + @Override + public void createPartControl(Composite parent) + { + table = new Table(parent, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION); + table.setLinesVisible(true); + table.setHeaderVisible(true); + + String[] titles = { Messages.TableCol_FileName, Messages.TableCol_Path, Messages.TableCol_LastModifiedGCNO, + Messages.TableCol_LastModifiedGCDA, Messages.TableCol_SizeGCNO, Messages.TableCol_SizeGCDA }; + for (int i = 0; i < titles.length; i++) + { + TableColumn column = new TableColumn(table, SWT.NONE); + column.setWidth(180); + column.setText(titles[i]); + column.addSelectionListener(new TableColumnSelectionAdapter(column, i)); + } + + table.addListener(SWT.MouseDoubleClick, new Listener() + { + @Override + public void handleEvent(Event event) + { + Point pt = new Point(event.x, event.y); + TableItem item = table.getItem(pt); + if (item == null) + return; + IFile file = (IFile) item.getData(); + + if (file != null) + { + try + { + GcovUtility.setUpDialog(file, IDFUtil.getELFFilePath(selectedProject).toOSString()); + IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + } + catch (PartInitException e) + { + Logger.log(e); + } + } + } + }); + + // Create Toolbar and Buttons + IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager(); + Action refreshAction = new Action(Messages.GcovFileView_Refresh_Button) + { + public void run() + { + refreshList(); + } + }; + Action selectProjectAction = new Action(Messages.GcovFileView_SelectProject_Button) + { + public void run() + { + openProjectSelectionDialog(); + refreshList(); + } + }; + + mgr.add(refreshAction); + mgr.add(selectProjectAction); + + // Initial population of the list + refreshList(); + } + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) + { + if (!(selection instanceof IStructuredSelection)) + return; + IStructuredSelection ssel = (IStructuredSelection) selection; + Object obj = ssel.getFirstElement(); + if (obj instanceof IProject) + { + setSelectedProject((IProject) obj); + } + } + + private void openProjectSelectionDialog() + { + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + ElementListSelectionDialog dialog = new ElementListSelectionDialog( + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + new org.eclipse.ui.model.WorkbenchLabelProvider()); + dialog.setElements(root.getProjects()); + dialog.setTitle(Messages.Dialog_SelectProject_Title); + + // only continue if the user pressed "OK" + if (dialog.open() != Window.OK) + { + return; + } + + setSelectedProject((IProject) dialog.getFirstResult()); + } + + private void createTableItem(Image image, String fileName, String filePath, String gcnoDate, String gcdaDate, + String gcnoSize, String gcdaSize, Object data) + { + int index = 0; + TableItem item = new TableItem(table, SWT.NONE); + item.setImage(index, image); + item.setText(index++, fileName); + item.setText(index++, filePath); + item.setText(index++, gcnoDate); + item.setText(index++, gcdaDate); + item.setText(index++, gcnoSize); + item.setText(index++, gcdaSize); + + item.setData(data); + } + + private String getFileSize(java.nio.file.Path path) + { + try + { + long size = Files.size(path); + return String.valueOf(size) + " bytes"; //$NON-NLS-1$ + } + catch (Exception e) + { + return Messages.Table_Unknown; + } + } + + private void verifyProjectSelection() + { + if (getSelectedProject() == null) + { + // Get the current selection + ISelectionService selectionService = PlatformUI.getWorkbench().getActiveWorkbenchWindow() + .getSelectionService(); + IStructuredSelection structuredSelection = (IStructuredSelection) selectionService + .getSelection("org.eclipse.ui.navigator.ProjectExplorer"); //$NON-NLS-1$ + + if (structuredSelection != null && !structuredSelection.isEmpty()) + { + Object firstElement = structuredSelection.getFirstElement(); + if (firstElement instanceof IProject) + { + setSelectedProject((IProject) firstElement); + } + } + + // Now we check the GCOV Utility to see if any project was selected + if (getSelectedProject() == null) + { + setSelectedProject(GcovUtility.getSelectedProject()); + } + + // If no project is selected, ask the user to choose one + if (getSelectedProject() == null) + { + openProjectSelectionDialog(); + } + } + } + + private void refreshList() + { + for (TableItem item : table.getItems()) + { + item.dispose(); + } + + verifyProjectSelection(); + + IProject project = getSelectedProject(); + + if (project.exists() && project.isOpen()) + { + try + { + project.accept(new IResourceVisitor() + { + public boolean visit(IResource resource) + { + if (resource instanceof IFile) + { + IFile file = (IFile) resource; + if ("gcno".equals(file.getFileExtension())) //$NON-NLS-1$ + { + String parentDir = file.getParent().getRawLocation().toString(); + String partnerFile = parentDir + "/" //$NON-NLS-1$ + + file.getName().substring(0, file.getName().indexOf(".gcno")) + ".gcda"; //$NON-NLS-1$ //$NON-NLS-2$ + if (Files.exists(Paths.get(partnerFile))) + { + Image image = PlatformUI.getWorkbench().getEditorRegistry() + .getImageDescriptor(file.getName()).createImage(); + // gcno + IFileInfo fileInfo = EFS.getLocalFileSystem().getStore(file.getLocationURI()) + .fetchInfo(); + String dateGcno = DateFormat.getDateTimeInstance() + .format(new Date(fileInfo.getLastModified())); + // gcda + fileInfo = EFS.getLocalFileSystem().getStore(Path.fromOSString(partnerFile)) + .fetchInfo(); + String dateGcda = DateFormat.getDateTimeInstance() + .format(new Date(fileInfo.getLastModified())); + + String gcnoSize = getFileSize(Paths.get(file.getRawLocationURI())); + String gcdaSize = getFileSize(Paths.get(partnerFile)); + + createTableItem(image, file.getName().substring(0, file.getName().indexOf(".gcno")), //$NON-NLS-1$ + file.getParent().getFullPath().toString(), dateGcno, dateGcda, gcnoSize, + gcdaSize, file); + } + } + } + return true; // continue visiting children + } + }); + } + catch (CoreException e) + { + Logger.log(e); + } + } + + } + + @Override + public void setFocus() + { + table.setFocus(); + } + + @Override + public void dispose() + { + getSite().getPage().removeSelectionListener(this); + super.dispose(); + } + + public IProject getSelectedProject() + { + return selectedProject; + } + + public void setSelectedProject(IProject selectedProject) + { + this.selectedProject = selectedProject; + } + + private class TableColumnSelectionAdapter extends SelectionAdapter + { + private TableColumn column; + private int colIndex; + + private class TableRowData + { + public String[] textData; + public Image image; + public Object itemData; + } + + private TableColumnSelectionAdapter(TableColumn column, int colIndex) + { + this.column = column; + this.colIndex = colIndex; + } + + @Override + public void widgetSelected(SelectionEvent e) + { + TableItem[] items = table.getItems(); + Collator collator = Collator.getInstance(Locale.getDefault()); + + // Determine increasing or decreasing order + int direction = table.getSortDirection(); + if (table.getSortColumn() == column) + { + direction = direction == SWT.UP ? SWT.DOWN : SWT.UP; + } + else + { + direction = SWT.DOWN; + } + + // Update sort direction and sort column + table.setSortDirection(direction); + table.setSortColumn(column); + + final int finalDirection = direction; + + // Implement your sorting logic here + Arrays.sort(items, new Comparator() + { + public int compare(TableItem item1, TableItem item2) + { + if (finalDirection == SWT.UP) + { + return collator.compare(item1.getText(colIndex), item2.getText(colIndex)); + } + else + { + return collator.compare(item2.getText(colIndex), item1.getText(colIndex)); + } + } + }); + + // Copy existing item data + List copiedData = createTableDataCopy(items); + + // Remove all items (dispose of TableItem objects) + table.removeAll(); + + // Repopulate the table + populateTable(copiedData); + } + + private List createTableDataCopy(TableItem[] items) + { + List copiedData = new ArrayList<>(); + for (TableItem item : items) + { + TableRowData rowData = new TableRowData(); + rowData.textData = new String[table.getColumnCount()]; + for (int j = 0; j < table.getColumnCount(); j++) + { + rowData.textData[j] = item.getText(j); + } + rowData.image = item.getImage(0); // Assuming image is in the first column + rowData.itemData = item.getData(); + copiedData.add(rowData); + } + + return copiedData; + } + + private void populateTable(List tableRowData) + { + for (TableRowData rowData : tableRowData) + { + TableItem newItem = new TableItem(table, SWT.NONE); + for (int j = 0; j < table.getColumnCount(); j++) + { + newItem.setText(j, rowData.textData[j]); + } + newItem.setImage(0, rowData.image); // Assuming image is in the first column + newItem.setData(rowData.itemData); + } + } + + } +} diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/GcovFileViewCommandHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/GcovFileViewCommandHandler.java new file mode 100644 index 000000000..931bba46f --- /dev/null +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/GcovFileViewCommandHandler.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright 2023 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ +package com.espressif.idf.ui.gcov; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; + +import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.core.util.GcovUtility; +import com.espressif.idf.ui.UIPlugin; + +/** + * Handler for the gcov view menu command + * @author Ali Azam Rana + * + */ +public class GcovFileViewCommandHandler extends AbstractHandler +{ + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException + { + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + { + throw new ExecutionException("Active workbench window cannot be retrieved"); + } + + IWorkbenchPage page = window.getActivePage(); + if (page == null) + { + throw new ExecutionException("Active page cannot be retrieved"); + } + + try + { + GcovUtility.clearSelectedProject(); + page.showView(GcovFileView.ID); + } + catch (PartInitException e) + { + Logger.log(UIPlugin.getDefault(), "Failed to initialize GcovFileView: " + e.getMessage(), e); + } + return null; + } + +} diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/Messages.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/Messages.java new file mode 100644 index 000000000..1733cfb8f --- /dev/null +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/Messages.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright 2023 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ +package com.espressif.idf.ui.gcov; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS +{ + private static final String BUNDLE_NAME = "com.espressif.idf.ui.gcov.messages"; //$NON-NLS-1$ + + public static String TableCol_FileName; + public static String TableCol_Path; + public static String TableCol_LastModifiedGCNO; + public static String TableCol_LastModifiedGCDA; + public static String TableCol_SizeGCNO; + public static String TableCol_SizeGCDA; + public static String Dialog_SelectProject_Title; + public static String Table_Unknown; + public static String GcovFileView_Refresh_Button; + public static String GcovFileView_SelectProject_Button; + + static + { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() + { + } +} diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/messages.properties b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/messages.properties new file mode 100644 index 000000000..3df4934c8 --- /dev/null +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/gcov/messages.properties @@ -0,0 +1,10 @@ +TableCol_FileName=File Name +TableCol_Path=Path +TableCol_LastModifiedGCNO=Last Modified GCNO +TableCol_LastModifiedGCDA=Last Modified GCDA +TableCol_SizeGCNO=Size GCNO +TableCol_SizeGCDA=Size GCDA +Dialog_SelectProject_Title=Select a Project +Table_Unknown=Unknown +GcovFileView_Refresh_Button=Refresh +GcovFileView_SelectProject_Button=Select Project \ No newline at end of file diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java index f5e24de5e..8ec9066bf 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java @@ -574,7 +574,7 @@ public Boolean call() throws Exception runToolsExport(idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.GIT_PATH)); new ESPToolChainManager().configureToolChain(); configEnv(); - handleWebSocketClientInstall(); + handlePipDependenciesInstall(); copyOpenOcdRules(); IDFUtil.updateEspressifPrefPageOpenocdPath(); validateToolsInstall(); @@ -979,7 +979,7 @@ private void runPythonEnvCommand() } } - private void handleWebSocketClientInstall() + private void handlePipDependenciesInstall() { List arguments = new ArrayList(); final String pythonEnvPath = IDFUtil.getIDFPythonEnvPath(); @@ -996,7 +996,8 @@ private void handleWebSocketClientInstall() arguments.add("install"); //$NON-NLS-1$ arguments.add("websocket-client"); //$NON-NLS-1$ - + arguments.add("gcovr"); //$NON-NLS-1$ + ProcessBuilderFactory processRunner = new ProcessBuilderFactory(); try diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallEspIdfPage.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallEspIdfPage.java index 51c3ded89..4129f27f7 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallEspIdfPage.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallEspIdfPage.java @@ -36,9 +36,9 @@ import com.espressif.idf.core.tools.IToolsInstallationWizardConstants; import com.espressif.idf.core.util.IDFUtil; import com.espressif.idf.core.util.StringUtil; +import com.espressif.idf.ui.LogMessagesThread; import com.espressif.idf.ui.UIPlugin; import com.espressif.idf.ui.tools.GitDownloadAndCloneThread; -import com.espressif.idf.ui.tools.LogMessagesThread; import com.espressif.idf.ui.tools.Messages; import com.espressif.idf.ui.tools.wizard.ToolsManagerWizard; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java index fff211bbb..fc4d0759d 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java @@ -54,8 +54,8 @@ import com.espressif.idf.core.tools.vo.VersionDetailsVO; import com.espressif.idf.core.tools.vo.VersionsVO; import com.espressif.idf.core.util.StringUtil; +import com.espressif.idf.ui.LogMessagesThread; import com.espressif.idf.ui.UIPlugin; -import com.espressif.idf.ui.tools.LogMessagesThread; import com.espressif.idf.ui.tools.Messages; import com.espressif.idf.ui.tools.ToolsInstallationHandler; import com.espressif.idf.ui.tools.wizard.ToolsManagerWizardDialog; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java index 58d2617af..bf648c889 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java @@ -96,8 +96,8 @@ protected IStatus run(IProgressMonitor monitor) configEnv(); - monitor.setTaskName(Messages.InstallToolsHandler_InstallingWebscoketMsg); - handleWebSocketClientInstall(); + monitor.setTaskName(Messages.InstallToolsHandler_InstallingPythonDepMsg); + handlePythonDependenciesInstall(); monitor.worked(1); copyOpenOcdRules(); @@ -216,9 +216,10 @@ protected IStatus handleToolsInstallPython(MessageConsoleStream console) return runCommand(arguments, console); } - public IStatus handleWebSocketClientInstall() + public IStatus handlePythonDependenciesInstall() { String websocketClient = "websocket-client"; //$NON-NLS-1$ + String gcovr = "gcovr"; //$NON-NLS-1$ // pip install websocket-client List arguments = new ArrayList(); final String pythonEnvPath = IDFUtil.getIDFPythonEnvPath(); @@ -263,15 +264,16 @@ public IStatus handleWebSocketClientInstall() } String cmdOutput = status.getMessage(); - if (cmdOutput.contains(websocketClient)) + if (cmdOutput.contains(websocketClient) && cmdOutput.contains(gcovr)) { - return IDFCorePlugin.okStatus("websocket-client already installed", null); //$NON-NLS-1$ + return IDFCorePlugin.okStatus("dependencies in pip already installed", null); //$NON-NLS-1$ } // websocket client not installed so installing it now. arguments.remove(arguments.size() - 1); arguments.add("install"); //$NON-NLS-1$ arguments.add(websocketClient); + arguments.add(gcovr); status = processRunner.runInBackground(arguments, org.eclipse.core.runtime.Path.ROOT, environment); if (status == null) diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/Messages.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/Messages.java index 6eee46609..ea54bd591 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/Messages.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/Messages.java @@ -29,7 +29,7 @@ public class Messages extends NLS public static String InstallToolsHandler_ConfiguredCMakeMsg; public static String InstallToolsHandler_ExportingPathsMsg; public static String InstallToolsHandler_InstallingPythonMsg; - public static String InstallToolsHandler_InstallingWebscoketMsg; + public static String InstallToolsHandler_InstallingPythonDepMsg; public static String InstallToolsHandler_InstallingToolsMsg; public static String InstallToolsHandler_ItWilltakeTimeMsg; public static String InstallToolsHandler_ToolsCompleted; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/messages.properties b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/messages.properties index 03336ab14..88842634c 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/messages.properties +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/messages.properties @@ -22,7 +22,7 @@ InstallToolsHandler_ConfiguredBuildEnvVarMsg=Configured CDT Build Environment va InstallToolsHandler_ConfiguredCMakeMsg=Configured CMake toolchain. You can check Preferences > C/C++ > CMake InstallToolsHandler_ExportingPathsMsg=Exporting and processing tools paths InstallToolsHandler_InstallingPythonMsg=Installing Python -InstallToolsHandler_InstallingWebscoketMsg=Installing websocket_client +InstallToolsHandler_InstallingPythonDepMsg=Installing websocket_client and gcovr InstallToolsHandler_InstallingToolsMsg=Installing tools... InstallToolsHandler_ItWilltakeTimeMsg=This can take a while. Please be patient. InstallToolsHandler_ToolsCompleted=Install tools completed. diff --git a/docs/images/GcovCodeCoverage/gcov-1.png b/docs/images/GcovCodeCoverage/gcov-1.png new file mode 100644 index 000000000..821be7962 Binary files /dev/null and b/docs/images/GcovCodeCoverage/gcov-1.png differ diff --git a/docs/images/GcovCodeCoverage/gcov-2.png b/docs/images/GcovCodeCoverage/gcov-2.png new file mode 100644 index 000000000..7d1e1bfbb Binary files /dev/null and b/docs/images/GcovCodeCoverage/gcov-2.png differ diff --git a/docs/images/GcovCodeCoverage/gcov-3.png b/docs/images/GcovCodeCoverage/gcov-3.png new file mode 100644 index 000000000..3586c0620 Binary files /dev/null and b/docs/images/GcovCodeCoverage/gcov-3.png differ diff --git a/docs/images/GcovCodeCoverage/gcov-4.png b/docs/images/GcovCodeCoverage/gcov-4.png new file mode 100644 index 000000000..623089e72 Binary files /dev/null and b/docs/images/GcovCodeCoverage/gcov-4.png differ diff --git a/docs/images/GcovCodeCoverage/gcov-5.png b/docs/images/GcovCodeCoverage/gcov-5.png new file mode 100644 index 000000000..4ca862572 Binary files /dev/null and b/docs/images/GcovCodeCoverage/gcov-5.png differ diff --git a/docs/images/GcovCodeCoverage/gcov-6.png b/docs/images/GcovCodeCoverage/gcov-6.png new file mode 100644 index 000000000..f98afd205 Binary files /dev/null and b/docs/images/GcovCodeCoverage/gcov-6.png differ diff --git a/releng/com.espressif.idf.target/com.espressif.idf.target.target b/releng/com.espressif.idf.target/com.espressif.idf.target.target index 964ef06f2..42fe74a91 100644 --- a/releng/com.espressif.idf.target/com.espressif.idf.target.target +++ b/releng/com.espressif.idf.target/com.espressif.idf.target.target @@ -103,8 +103,8 @@ - - + + @@ -122,5 +122,13 @@ + + + + + + + + \ No newline at end of file