Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.

**Espressif-IDE Product Information:**
Espressif > Product Information (Copy content from the console and attach as a file)

**Eclipse Error log:**
Window > Show View > Other > Search for "Error Log" (Attach as a file)

Please attach the error log as described here https://github.com/espressif/idf-eclipse-plugin#error-log
**Bug Report**
Please attach the bug report zip file generated. The file is generated in the workspace root directory.
Espressif > Generate Bug Report
1 change: 1 addition & 0 deletions bundles/com.espressif.idf.core/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Automatic-Module-Name: com.espressif.idf.core
Bundle-ActivationPolicy: lazy
Export-Package: com.espressif.idf.core,
com.espressif.idf.core.actions,
com.espressif.idf.core.bug,
com.espressif.idf.core.build,
com.espressif.idf.core.configparser,
com.espressif.idf.core.configparser.vo,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/*******************************************************************************
* Copyright 2025 Espressif Systems (Shanghai) PTE LTD.
* All rights reserved. Use is subject to license terms.
*******************************************************************************/
package com.espressif.idf.core.bug;

import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;

import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Platform;

import com.espressif.idf.core.logging.Logger;
import com.espressif.idf.core.util.FileUtil;
import com.espressif.idf.core.util.StringUtil;

/**
* This class generates a bug report zip file containing:
* 1. Installed tools information
* 2. Product information
* 3. Basic system information (OS, Arch, Memory)
* 4. IDE metadata logs
* 5. eim logs (if available)
*
* The generated zip file is named with a timestamp and stored in the workspace directory.
* @author Ali Azam Rana
*
*/
public class BugReportGenerator
{
private static final String bugReportDirectoryPrefix = "bug_report_"; //$NON-NLS-1$
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the naming convention for a final static field is all uppercase letters with underscores separating words.

private String installedToolsCommandOutput;
private String productInformationCommandOutput;
private File bugReportDirectory;

private enum ByteUnit
{
B("B"), //$NON-NLS-1$
KB("KB"), //$NON-NLS-1$
MB("MB"), //$NON-NLS-1$
GB("GB"), //$NON-NLS-1$
TB("TB"), //$NON-NLS-1$
PB("PB"); //$NON-NLS-1$

final String label;

ByteUnit(String label)
{
this.label = label;
}

ByteUnit next()
{
int i = ordinal();
return i < PB.ordinal() ? values()[i + 1] : PB;
}
}

public BugReportGenerator(String installedToolsCommandOutput, String productInformationCommandOutput)
{
this.installedToolsCommandOutput = installedToolsCommandOutput;
this.productInformationCommandOutput = productInformationCommandOutput;
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")); //$NON-NLS-1$
bugReportDirectory = getWorkspaceDirectory().resolve(bugReportDirectoryPrefix + timestamp + File.separator)
.toFile();
}

private File getEimLogPath()
{
String eimPath = StringUtil.EMPTY;
switch (Platform.getOS())
{
case Platform.OS_WIN32:
eimPath = System.getenv("APPDATA"); //$NON-NLS-1$
if (!StringUtil.isEmpty(eimPath))
{
eimPath = eimPath + "\\Local\\eim\\logs"; //$NON-NLS-1$
}
break;
Comment on lines 103 to 109
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Windows EIM logs path is incorrect.

APPDATA points to Roaming; use LOCALAPPDATA.

-        case Platform.OS_WIN32:
-            eimPath = System.getenv("APPDATA"); //$NON-NLS-1$
+        case Platform.OS_WIN32:
+            eimPath = System.getenv("LOCALAPPDATA"); //$NON-NLS-1$
             if (!StringUtil.isEmpty(eimPath))
             {
                 eimPath = eimPath + "\\Local\\eim\\logs"; //$NON-NLS-1$
             }

Also consider simply: LOCALAPPDATA + "\eim\logs".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case Platform.OS_WIN32:
eimPath = System.getenv("APPDATA"); //$NON-NLS-1$
if (!StringUtil.isEmpty(eimPath))
{
eimPath = eimPath + "\\Local\\eim\\logs"; //$NON-NLS-1$
}
break;
case Platform.OS_WIN32:
eimPath = System.getenv("LOCALAPPDATA"); //$NON-NLS-1$
if (!StringUtil.isEmpty(eimPath))
{
eimPath = eimPath + "\\Local\\eim\\logs"; //$NON-NLS-1$
}
break;
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/bug/BugReportGenerator.java
around lines 81 to 87, the code uses APPDATA (Roaming) for the EIM logs path;
change it to use the LOCALAPPDATA environment variable instead and construct the
path directly (e.g. LOCALAPPDATA + "\\eim\\logs"). Ensure you null/empty-check
the LOCALAPPDATA value before concatenation (using StringUtil.isEmpty) and only
set eimPath when LOCALAPPDATA is available; do not use APPDATA for this path.

case Platform.OS_MACOSX:
eimPath = System.getProperty("user.home"); //$NON-NLS-1$
if (!StringUtil.isEmpty(eimPath))
{
eimPath = eimPath + "/Library/Application Support/eim/logs"; //$NON-NLS-1$
}
break;
case Platform.OS_LINUX:
eimPath = System.getProperty("user.home"); //$NON-NLS-1$
if (!StringUtil.isEmpty(eimPath))
{
eimPath = eimPath + "/.local/share/.eim/logs"; //$NON-NLS-1$
}
break;
default:
break;
}

return new File(eimPath);
}
Comment on lines +128 to +129
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Prevent catastrophic copy when EIM path is missing.

getEimLogPath() returns new File("") on empty, which resolves to the CWD; copyDirectory would then copy the whole working dir. Return null when unresolved and guard the copy.

-        return new File(eimPath);
+        if (StringUtil.isEmpty(eimPath)) {
+            return null;
+        }
+        return new File(eimPath);
-        File eimLogPath = getEimLogPath();
-        File eimLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "eim_logs"); //$NON-NLS-1$ )
-        FileUtil.copyDirectory(eimLogPath, eimLogDir);
+        File eimLogPath = getEimLogPath();
+        if (eimLogPath != null && eimLogPath.exists() && eimLogPath.isDirectory()) {
+            File eimLogDir = new File(bugReportDirectory, "eim_logs"); //$NON-NLS-1$
+            FileUtil.copyDirectory(eimLogPath, eimLogDir);
+        }

Also applies to: 279-282

🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/bug/BugReportGenerator.java
around lines 112-113 (and likewise around 279-282), getEimLogPath() currently
returns new File("") when the EIM path is empty which resolves to the CWD and
can cause copyDirectory to copy the whole working directory; change
getEimLogPath() to return null when the path is empty/unresolved and update the
callers to guard before copying (skip the copy and log a warning or handle
absence) so copyDirectory is only invoked with a non-null, valid directory File.


private Path getWorkspaceDirectory()
{
IWorkspace workspace = ResourcesPlugin.getWorkspace();
File workspaceRoot = workspace.getRoot().getLocation().toFile();
return workspaceRoot.toPath();
}

private File getIdeMetadataLogsFile()
{
File metadataDir = getWorkspaceDirectory().resolve(".metadata").toFile(); //$NON-NLS-1$
return metadataDir;
}

private File createBasicSystemInfoFile() throws IOException
{
String osName = System.getProperty("os.name", "Unknown"); //$NON-NLS-1$ //$NON-NLS-2$
String osVersion = System.getProperty("os.version", "Unknown"); //$NON-NLS-1$ //$NON-NLS-2$
String arch = System.getProperty("os.arch", "Unknown"); //$NON-NLS-1$//$NON-NLS-2$

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can use a variable here for "Unknown"

long freePhys = -1L;
long totalPhys = -1L;
try
{
com.sun.management.OperatingSystemMXBean osBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory
.getOperatingSystemMXBean();
freePhys = osBean.getFreeMemorySize();
totalPhys = osBean.getTotalMemorySize();
}
Comment on lines +204 to +208
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Compile error: wrong com.sun.management.OperatingSystemMXBean methods.

Use getFreePhysicalMemorySize()/getTotalPhysicalMemorySize().

-            freePhys = osBean.getFreeMemorySize();
-            totalPhys = osBean.getTotalMemorySize();
+            freePhys = osBean.getFreePhysicalMemorySize();
+            totalPhys = osBean.getTotalPhysicalMemorySize();
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/bug/BugReportGenerator.java
around lines 132 to 136, the code calls non-existent methods
getFreeMemorySize()/getTotalMemorySize() on
com.sun.management.OperatingSystemMXBean; replace those calls with the correct
methods getFreePhysicalMemorySize() and getTotalPhysicalMemorySize()
respectively so the code compiles and returns physical memory values.

catch (Throwable t)
{
// jdk.management module not present or different VM; leave values as -1.
}

StringBuilder sb = new StringBuilder();
sb.append("Basic System Info").append(System.lineSeparator()); //$NON-NLS-1$
sb.append("==================").append(System.lineSeparator()); //$NON-NLS-1$
sb.append("Generated: ").append(LocalDateTime.now()).append(System.lineSeparator()); //$NON-NLS-1$
sb.append("OS : ").append(osName).append(" ").append(osVersion).append(System.lineSeparator()); //$NON-NLS-1$ //$NON-NLS-2$
sb.append("Arch : ").append(arch).append(System.lineSeparator()); //$NON-NLS-1$
if (totalPhys >= 0 && freePhys >= 0)
{
long used = totalPhys - freePhys;
sb.append("Memory :").append(System.lineSeparator()); //$NON-NLS-1$
sb.append(" Total : ").append(humanBytes(totalPhys)).append(" (").append(totalPhys) //$NON-NLS-1$ //$NON-NLS-2$
.append(" bytes)").append(System.lineSeparator()); //$NON-NLS-1$
sb.append(" Available : ").append(humanBytes(freePhys)).append(" (").append(freePhys).append(" bytes)") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
.append(System.lineSeparator());
sb.append(" In Use : ").append(humanBytes(used)).append(" (").append(used).append(" bytes)") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
.append(System.lineSeparator());
}
else
{
sb.append("Memory : Unavailable (OS-level physical memory query unsupported on this JVM)") //$NON-NLS-1$
.append(System.lineSeparator());
}

// Use your existing helper that writes content to a temp file with the given name.
// This will create a file named exactly "basic_system_info".
return FileUtil.createFileWithContentsInDirectory("basic_system_info", sb.toString(), //$NON-NLS-1$
bugReportDirectory.getAbsolutePath());
}

private static String humanBytes(long bytes)
{
double v = (double) bytes;
ByteUnit unit = ByteUnit.B;
while (v >= 1024.0 && unit != ByteUnit.PB)
{
v /= 1024.0;
unit = unit.next();
}
return String.format(Locale.ROOT, "%.2f %s", v, unit.label); //$NON-NLS-1$
}

/**
* Generates a bug report zip and also returns the path of the generated zip file.
*
* @return
*/
public String generateBugReport()
{
if (!bugReportDirectory.exists())
{
bugReportDirectory.mkdirs();
}

try
{
File installedToolsFile = FileUtil.createFileWithContentsInDirectory("installed_tools.txt", //$NON-NLS-1$
installedToolsCommandOutput, bugReportDirectory.getAbsolutePath());
File productInfoFile = FileUtil.createFileWithContentsInDirectory("product_information.txt", //$NON-NLS-1$
productInformationCommandOutput, bugReportDirectory.getAbsolutePath());
File basicSysInfoFile = createBasicSystemInfoFile();
Comment on lines 267 to 271
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Null-safe file writes for command outputs.

Avoid NPE if either output is null.

-            File installedToolsFile = FileUtil.createFileWithContentsInDirectory("installed_tools.txt", //$NON-NLS-1$
-                    installedToolsCommandOutput, bugReportDirectory.getAbsolutePath());
-            File productInfoFile = FileUtil.createFileWithContentsInDirectory("product_information.txt", //$NON-NLS-1$
-                    productInformationCommandOutput, bugReportDirectory.getAbsolutePath());
+            String installedToolsOut = installedToolsCommandOutput == null ? StringUtil.EMPTY : installedToolsCommandOutput;
+            String productInfoOut = productInformationCommandOutput == null ? StringUtil.EMPTY : productInformationCommandOutput;
+            File installedToolsFile = FileUtil.createFileWithContentsInDirectory("installed_tools.txt", //$NON-NLS-1$
+                    installedToolsOut, bugReportDirectory.getAbsolutePath());
+            File productInfoFile = FileUtil.createFileWithContentsInDirectory("product_information.txt", //$NON-NLS-1$
+                    productInfoOut, bugReportDirectory.getAbsolutePath());
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try
{
File installedToolsFile = FileUtil.createFileWithContentsInDirectory("installed_tools.txt", //$NON-NLS-1$
installedToolsCommandOutput, bugReportDirectory.getAbsolutePath());
File productInfoFile = FileUtil.createFileWithContentsInDirectory("product_information.txt", //$NON-NLS-1$
productInformationCommandOutput, bugReportDirectory.getAbsolutePath());
File basicSysInfoFile = createBasicSystemInfoFile();
try
{
// Null-safe command outputs to avoid passing null into the file-creation utility
String installedToolsOut = installedToolsCommandOutput == null
? StringUtil.EMPTY
: installedToolsCommandOutput;
String productInfoOut = productInformationCommandOutput == null
? StringUtil.EMPTY
: productInformationCommandOutput;
File installedToolsFile = FileUtil.createFileWithContentsInDirectory(
"installed_tools.txt", //$NON-NLS-1$
installedToolsOut,
bugReportDirectory.getAbsolutePath());
File productInfoFile = FileUtil.createFileWithContentsInDirectory(
"product_information.txt", //$NON-NLS-1$
productInfoOut,
bugReportDirectory.getAbsolutePath());
File basicSysInfoFile = createBasicSystemInfoFile();
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/bug/BugReportGenerator.java
around lines 254 to 260, the code calls
FileUtil.createFileWithContentsInDirectory using installedToolsCommandOutput and
productInformationCommandOutput which can be null and cause an NPE; fix by
ensuring null-safe values before calling the method (e.g., replace nulls with
empty strings or only create the file when the output is non-null). Concretely,
compute safe strings like String installedTools = installedToolsCommandOutput ==
null ? "" : installedToolsCommandOutput and String productInfo =
productInformationCommandOutput == null ? "" : productInformationCommandOutput,
then pass those safe values to createFileWithContentsInDirectory (or skip file
creation when you prefer) so no NPE occurs.


List<File> filesToZip = new LinkedList<>();
filesToZip.add(installedToolsFile);
filesToZip.add(productInfoFile);
filesToZip.add(basicSysInfoFile);

File metadataLogsFile = getIdeMetadataLogsFile();
File ideLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "ide_metadata_logs"); //$NON-NLS-1$ )
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix stray ) causing compilation errors.

There’s an extra closing parenthesis after the $NON-NLS-1$ comment.

- File ideLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "ide_metadata_logs"); //$NON-NLS-1$ )
+ File ideLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "ide_metadata_logs"); //$NON-NLS-1$
- File eimLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "eim_logs"); //$NON-NLS-1$ )
+ File eimLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "eim_logs"); //$NON-NLS-1$

Also applies to: 292-292

🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/bug/BugReportGenerator.java
around lines 279 and 292, there are stray closing parentheses immediately after
the //$NON-NLS-1$ comments causing compilation errors; remove the extra ')' at
both locations so the File constructor calls end with ); (i.e., ensure the
comment is outside the parentheses and the method call is properly closed).

if (!ideLogDir.exists())
{
ideLogDir.mkdirs();
}

FileUtil.copyDirectory(metadataLogsFile, ideLogDir);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

PII risk: copying entire workspace .metadata.

Workspace .metadata can contain sensitive data. Limit to logs (e.g., .metadata/.log) or a curated subset.

-        File metadataLogsFile = getIdeMetadataLogsFile();
-        File ideLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "ide_metadata_logs"); //$NON-NLS-1$ )
-        if (!ideLogDir.exists())
-        {
-            ideLogDir.mkdirs();
-        }
-
-        FileUtil.copyDirectory(metadataLogsFile, ideLogDir);
+        File ideLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "ide_metadata_logs"); //$NON-NLS-1$
+        if (!ideLogDir.exists()) {
+            ideLogDir.mkdirs();
+        }
+        // Copy only the workspace .log file to reduce PII exposure
+        File workspaceMeta = getIdeMetadataLogsFile();
+        File workspaceLog = new File(workspaceMeta, ".log"); //$NON-NLS-1$
+        if (workspaceLog.exists()) {
+            java.nio.file.Files.copy(
+                workspaceLog.toPath(),
+                new File(ideLogDir, "workspace.log").toPath(),
+                java.nio.file.StandardCopyOption.REPLACE_EXISTING);
+        }

If more logs are needed, whitelist specific subfolders/files.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
File metadataLogsFile = getIdeMetadataLogsFile();
File ideLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "ide_metadata_logs"); //$NON-NLS-1$ )
if (!ideLogDir.exists())
{
ideLogDir.mkdirs();
}
FileUtil.copyDirectory(metadataLogsFile, ideLogDir);
File ideLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "ide_metadata_logs"); //$NON-NLS-1$
if (!ideLogDir.exists()) {
ideLogDir.mkdirs();
}
// Copy only the workspace .log file to reduce PII exposure
File workspaceMeta = getIdeMetadataLogsFile();
File workspaceLog = new File(workspaceMeta, ".log"); //$NON-NLS-1$
if (workspaceLog.exists()) {
java.nio.file.Files.copy(
workspaceLog.toPath(),
new File(ideLogDir, "workspace.log").toPath(),
java.nio.file.StandardCopyOption.REPLACE_EXISTING);
}
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/bug/BugReportGenerator.java
around lines 208-216, the code currently copies the entire workspace .metadata
which may include PII; instead, restrict what is copied by whitelisting only
specific log files/subfolders (e.g., .metadata/.log and any approved subfolders)
or by copying a curated list of filenames. Change the logic to create the
ide_metadata_logs directory, then iterate a small whitelist (or patterns like
"*.log") and copy each allowed file/subfolder individually (using
FileUtil.copyFile/FileUtil.copyDirectory per item), and add null/exists checks
and clear comments documenting the whitelist; do not copy the whole metadata
directory.

File eimLogPath = getEimLogPath();
File eimLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "eim_logs"); //$NON-NLS-1$ )
FileUtil.copyDirectory(eimLogPath, eimLogDir);

Comment on lines 290 to 297
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Guard optional EIM logs copy.

Skip copy when source doesn’t exist to avoid noisy errors.

-        File eimLogPath = getEimLogPath();
-        File eimLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "eim_logs"); //$NON-NLS-1$ )
-        FileUtil.copyDirectory(eimLogPath, eimLogDir);
+        File eimLogPath = getEimLogPath();
+        if (eimLogPath.exists()) {
+            File eimLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "eim_logs"); //$NON-NLS-1$
+            FileUtil.copyDirectory(eimLogPath, eimLogDir);
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
File eimLogPath = getEimLogPath();
File eimLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "eim_logs"); //$NON-NLS-1$ )
FileUtil.copyDirectory(eimLogPath, eimLogDir);
File eimLogPath = getEimLogPath();
if (eimLogPath.exists()) {
File eimLogDir = new File(bugReportDirectory.getAbsolutePath() + File.separator + "eim_logs"); //$NON-NLS-1$
FileUtil.copyDirectory(eimLogPath, eimLogDir);
}
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/bug/BugReportGenerator.java
around lines 217 to 220, the code unconditionally attempts to copy EIM logs
which may not exist; update it to guard the copy by checking that
getEimLogPath() returned a non-null File that exists (and is a directory/file as
appropriate) before calling FileUtil.copyDirectory, and if the source does not
exist simply skip the copy (optionally log a debug/info message) to avoid noisy
errors.

// Zip the bug report directory
FileUtil.zipDirectory(bugReportDirectory, bugReportDirectory.getAbsolutePath() + ".zip"); //$NON-NLS-1$
}
catch (IOException e)
{
Logger.log(e);
}
return bugReportDirectory.getAbsolutePath() + ".zip"; //$NON-NLS-1$
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*******************************************************************************
* Copyright 2025 Espressif Systems (Shanghai) PTE LTD.
* All rights reserved. Use is subject to license terms.
*******************************************************************************/
package com.espressif.idf.core.bug;

import java.awt.Desktop;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
* Opens the default web browser to create a new issue on the GitHub repository.
*
* @author Ali Azam Rana
*/
public class GithubIssueOpener
{
private static final String issueUrlBase = "https://github.com/espressif/idf-eclipse-plugin/issues/new"; //$NON-NLS-1$

public static void openNewIssue()
throws Exception
{
String q = "&template=" + enc("bug_report.md"); // e.g. "bug_report.md" //$NON-NLS-1$ //$NON-NLS-2$
URI uri = new URI(issueUrlBase + "?" + q); //$NON-NLS-1$
Desktop.getDesktop().browse(uri);
}
Comment on lines +20 to +28
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Guard Desktop.browse for headless/unsupported environments.

Avoid throwing on systems without a desktop or browse action.

-        Desktop.getDesktop().browse(uri);
+        if (!Desktop.isDesktopSupported() || !Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
+            throw new IllegalStateException("Desktop browse is not supported on this system"); //$NON-NLS-1$
+        }
+        Desktop.getDesktop().browse(uri);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private static final String issueUrlBase = "https://github.com/espressif/idf-eclipse-plugin/issues/new"; //$NON-NLS-1$
public static void openNewIssue()
throws Exception
{
String q = "&template=" + enc("bug_report.md"); // e.g. "bug_report.md" //$NON-NLS-1$ //$NON-NLS-2$
URI uri = new URI(issueUrlBase + "?" + q); //$NON-NLS-1$
Desktop.getDesktop().browse(uri);
}
private static final String issueUrlBase = "https://github.com/espressif/idf-eclipse-plugin/issues/new"; //$NON-NLS-1$
public static void openNewIssue()
throws Exception
{
String q = "&template=" + enc("bug_report.md"); // e.g. "bug_report.md" //$NON-NLS-1$ //$NON-NLS-2$
URI uri = new URI(issueUrlBase + "?" + q); //$NON-NLS-1$
if (!Desktop.isDesktopSupported() || !Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
throw new IllegalStateException("Desktop browse is not supported on this system"); //$NON-NLS-1$
}
Desktop.getDesktop().browse(uri);
}
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/bug/GithubIssueOpener.java
around lines 20-28, the code calls Desktop.getDesktop().browse(...) unguarded
which will throw on headless or unsupported environments; change it to first
check Desktop.isDesktopSupported() and
Desktop.getDesktop().isSupported(Desktop.Action.BROWSE) and only call browse
when both are true, otherwise handle gracefully (e.g., log a clear message and
return or open an alternative fallback like showing the URL to the user) so the
method does not throw on systems without a desktop/browse action.


private static String enc(String s) throws UnsupportedEncodingException
{
return URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
}
}
Loading
Loading