Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IEP-1334: EIM Integration #1116

Open
wants to merge 41 commits into
base: master
Choose a base branch
from
Open

IEP-1334: EIM Integration #1116

wants to merge 41 commits into from

Conversation

alirana01
Copy link
Collaborator

@alirana01 alirana01 commented Jan 13, 2025

Description

EIM Integration

Fixes # (IEP-1334)

Type of change

Please delete options that are not relevant.

  • New feature (breaking change which adds functionality)
  • This change requires a documentation update

How has this been tested?

All flows relevant to onboarding and ide tools installation must be selected.

Try setting up ide without EIM installed. User should get a message to download and install the EIM and then start the IDE.

Try starting IDE after EIM is installed. The user must be notified that no active ESP-IDF configuration is found and must come towards the ESP-IDF Manager which will now only have option to activate or refresh an installation from the given list that comes from the EIM

Try starting IDE in a workspace with the older version and this should notify the user to export the configuration that must be passed on by the user to EIM for proper handling and creating the eim stable configs.

Test Configuration:

  • ESP-IDF Version: any
  • OS (Windows,Linux and macOS): all

Checklist

  • PR Self Reviewed
  • Applied Code formatting
  • Added Documentation
  • Updated SWTBot Tests
  • Verified on all platforms - Windows,Linux and macOS

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added support for enhanced user notifications related to ESP-IDF tool initialization and configuration.
    • Introduced new user interface messages for handling old configurations and export processes.
    • Enhanced the setup process for development tools within the IDE, improving user interaction.
    • Streamlined the initialization process for IDF tools, focusing on user notifications and error handling.
    • Updated the workflow for building ESP-IDF tools to specify version 5.3.
    • Added new messages related to OpenOCD rules during installation and configuration processes.
    • Added a new interface for managing JSON configurations and improved handling of installed IDF components.
    • Implemented a new class for managing the setup of ESP-IDF tools in the IDE.
  • Bug Fixes

    • Improved error handling for missing ESP-IDF installations and old configuration detection.
    • Enhanced error handling and rollback capabilities in the setup tools management.
  • Documentation

    • Added new localized messages for user guidance during tool setup and configuration.

@alirana01 alirana01 self-assigned this Jan 13, 2025

This comment was marked as outdated.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 17

🧹 Nitpick comments (5)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)

205-237: Clean up commented-out code related to the Remove All functionality

The code block for the removeAllButton has been commented out. If this functionality is no longer needed, consider removing the code entirely to maintain code cleanliness. If it will be used later, add a comment explaining its future use.

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java (1)

1-10: Use a final class instead of an interface for constants

Using an interface to hold constants is an anti-pattern in Java. It's better to use a final class with a private constructor to hold constants. This approach prevents unintended implementation and makes the intent clearer.

Refactor EimConstants to a utility class:

-public interface EimConstants
+public final class EimConstants
 {
-    String EIM_WIN_PATH = "C:\\Espressif\\tools\\esp_ide.json"; //$NON-NLS-1$
+    public static final String EIM_WIN_PATH = "C:\\Espressif\\tools\\esp_ide.json"; //$NON-NLS-1$

-    String EIM_URL = "https://github.com/espressif/idf-im-cli"; //$NON-NLS-1$
+    public static final String EIM_URL = "https://github.com/espressif/idf-im-cli"; //$NON-NLS-1$

-    String EIM_POSIX_PATH = "~/.espressif/tools/eim_idf.json"; //$NON-NLS-1$
+    public static final String EIM_POSIX_PATH = "~/.espressif/tools/eim_idf.json"; //$NON-NLS-1$

+    private EimConstants() {
+        // Prevent instantiation
+    }
 }
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1)

7-14: Add class-level documentation and field validation.

The class would benefit from:

  1. JavaDoc explaining the purpose of this configuration class
  2. Documentation for each field explaining their significance
  3. Null validation in setters

Example implementation:

+/**
+ * Represents the EIM (ESP-IDF Installation Manager) configuration.
+ * This class is used for JSON serialization/deserialization of EIM settings.
+ */
 public class EimJson
 {
 	@Expose
+	/** Path to the Git executable */
 	private String gitPath;
 	@Expose
+	/** Currently selected IDF installation ID */
 	private String idfSelectedId;
 	@Expose
+	/** List of installed IDF versions */
 	private List<IdfInstalled> idfInstalled;
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java (1)

5-18: Add class documentation and field validation.

The class needs:

  1. JavaDoc documentation
  2. Field validation
  3. toString() implementation for debugging
+/**
+ * Represents an installed ESP-IDF instance with its configuration.
+ * This class contains paths and settings for a specific IDF installation.
+ */
 public class IdfInstalled
 {
 	@Expose
+	/** Script to activate this IDF installation */
 	private String activationScript;
 	@Expose
+	/** Unique identifier for this installation */
 	private String id;
 	@Expose
+	/** Path to the IDF tools directory */
 	private String idfToolsPath;
 	@Expose
+	/** Display name of this installation */
 	private String name;
 	@Expose
+	/** Root path of this IDF installation */
 	private String path;
 	@Expose
+	/** Python interpreter path for this installation */
 	private String python;
bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties (1)

22-23: Consider adding documentation links.

To help users better understand the EIM installation process, consider adding a link to the official documentation.

Add documentation link to the message:

-ToolsInitializationEimMissingMsgBoxMessage=ESP-IDF is not found on your system. Please use EIM (Espressif Installation Manager) to install the ESP-IDF on your system to use the IDE. When prompted, click Yes to open the EIM download page in your browser.
+ToolsInitializationEimMissingMsgBoxMessage=ESP-IDF is not found on your system. Please use EIM (Espressif Installation Manager) to install the ESP-IDF on your system to use the IDE. When prompted, click Yes to open the EIM download page in your browser. For more information, visit: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 04b99d1 and bcddd42.

📒 Files selected for processing (10)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (4 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (14 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: build_macos
🔇 Additional comments (3)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (1)

290-290: ⚠️ Potential issue

Correct the method name 'userNotficationToInstallEim'

The method userNotficationToInstallEim() has a typo in its name. 'Notfication' should be 'Notification'.

Apply this diff to fix the method name:

-private void userNotficationToInstallEim()
+private void userNotificationToInstallEim()

Run the following script to find and correct all occurrences of the misspelled method name:

✅ Verification successful

Rename method to fix typo: 'userNotficationToInstallEim' → 'userNotificationToInstallEim'

The method name has a typo that needs to be corrected in two locations in bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java:

  • Method declaration
  • Method invocation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find occurrences of 'userNotficationToInstallEim' in the codebase.

rg 'userNotficationToInstallEim' -t java

Length of output: 282


Script:

#!/bin/bash
# Check for any similar typos in method names or strings
rg -i 'notfication' -t java

Length of output: 269

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java (1)

35-38: Ensure ID uniqueness.

The ID setter should validate the format to ensure uniqueness across installations.

bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java (1)

36-38: LGTM!

The new message constants are properly integrated with the NLS system and follow the existing pattern in the file.

Comment on lines 135 to 112
catch (IOException e)
{
Logger.log(e);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance error handling in the catch block

When catching IOException while obtaining eimJson, consider informing the user or taking corrective action rather than just logging it. This will improve error visibility and user experience.

Comment on lines +276 to +217
String path = StringUtil.EMPTY;
if (Platform.getOS().equals(Platform.OS_WIN32))
{
JSONObject jsonObj = (JSONObject) parser.parse(new FileReader(idf_json_file));
String gitExecutablePath = (String) jsonObj.get(GIT_PATH);
String idfToolsPath = (String) jsonObj.get(IDF_TOOLS_PATH_KEY);
String idfVersionId = (String) jsonObj.get(IDF_VERSIONS_ID);
JSONObject list = (JSONObject) jsonObj.get(IDF_INSTALLED_LIST_KEY);
if (list != null)
{
// selected esp-idf version information
JSONObject selectedIDFInfo = (JSONObject) list.get(idfVersionId);
String idfPath = (String) selectedIDFInfo.get(IDF_PATH);
String pythonExecutablePath = (String) selectedIDFInfo.get(PYTHON_PATH);
IDFToolSet newToolSet = new IDFToolSet();
newToolSet.setIdfLocation(idfPath);
newToolSet.setSystemGitExecutablePath(gitExecutablePath);
newToolSet.setSystemPythonExecutablePath(pythonExecutablePath);
newToolSet.setActive(true);
Preferences prefs = InstanceScope.INSTANCE.getNode(IDFCorePlugin.PLUGIN_ID);
prefs.put(IDFCorePreferenceConstants.IDF_TOOLS_PATH, idfToolsPath);
try
{
prefs.flush();
}
catch (BackingStoreException e)
{
Logger.log(e);
}
ToolsActivationJob toolsActivationJob = new ToolsActivationJob(newToolSet, pythonExecutablePath, gitExecutablePath);
ToolsActivationJobListener toolsActivationJobListener = new ToolsActivationJobListener(ESPIDFMainTablePage.getInstance());
toolsActivationJob.addJobChangeListener(toolsActivationJobListener);
toolsActivationJob.schedule();
}

// save state
Preferences prefs = getPreferences();
prefs.putBoolean(IS_INSTALLER_CONFIG_SET, true);
try
{
prefs.flush();
}
catch (BackingStoreException e)
{
Logger.log(e);
}
IDFUtil.updateEspressifPrefPageOpenocdPath();

path = EimConstants.EIM_WIN_PATH;
}
catch (
IOException
| ParseException e)
else
{
Logger.log(e);
path = EimConstants.EIM_POSIX_PATH;
}

File file = new File(path);
return file.exists();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Expand '~' in POSIX paths to the user's home directory

In the method isEimIdfJsonPresent(), the POSIX path EimConstants.EIM_POSIX_PATH uses '~' to represent the user's home directory. Java's File class does not automatically expand '~', which will result in the file not being found. Use System.getProperty("user.home") to construct the correct path.

Apply this diff to fix the path resolution:

 String path = StringUtil.EMPTY;

 if (Platform.getOS().equals(Platform.OS_WIN32))
 {
     path = EimConstants.EIM_WIN_PATH;
 }
 else
 {
-    path = EimConstants.EIM_POSIX_PATH;
+    String userHome = System.getProperty("user.home");
+    path = userHome + EimConstants.EIM_POSIX_PATH.substring(1); // Remove the '~' character
 }

 File file = new File(path);
 return file.exists();
📝 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
String path = StringUtil.EMPTY;
if (Platform.getOS().equals(Platform.OS_WIN32))
{
JSONObject jsonObj = (JSONObject) parser.parse(new FileReader(idf_json_file));
String gitExecutablePath = (String) jsonObj.get(GIT_PATH);
String idfToolsPath = (String) jsonObj.get(IDF_TOOLS_PATH_KEY);
String idfVersionId = (String) jsonObj.get(IDF_VERSIONS_ID);
JSONObject list = (JSONObject) jsonObj.get(IDF_INSTALLED_LIST_KEY);
if (list != null)
{
// selected esp-idf version information
JSONObject selectedIDFInfo = (JSONObject) list.get(idfVersionId);
String idfPath = (String) selectedIDFInfo.get(IDF_PATH);
String pythonExecutablePath = (String) selectedIDFInfo.get(PYTHON_PATH);
IDFToolSet newToolSet = new IDFToolSet();
newToolSet.setIdfLocation(idfPath);
newToolSet.setSystemGitExecutablePath(gitExecutablePath);
newToolSet.setSystemPythonExecutablePath(pythonExecutablePath);
newToolSet.setActive(true);
Preferences prefs = InstanceScope.INSTANCE.getNode(IDFCorePlugin.PLUGIN_ID);
prefs.put(IDFCorePreferenceConstants.IDF_TOOLS_PATH, idfToolsPath);
try
{
prefs.flush();
}
catch (BackingStoreException e)
{
Logger.log(e);
}
ToolsActivationJob toolsActivationJob = new ToolsActivationJob(newToolSet, pythonExecutablePath, gitExecutablePath);
ToolsActivationJobListener toolsActivationJobListener = new ToolsActivationJobListener(ESPIDFMainTablePage.getInstance());
toolsActivationJob.addJobChangeListener(toolsActivationJobListener);
toolsActivationJob.schedule();
}
// save state
Preferences prefs = getPreferences();
prefs.putBoolean(IS_INSTALLER_CONFIG_SET, true);
try
{
prefs.flush();
}
catch (BackingStoreException e)
{
Logger.log(e);
}
IDFUtil.updateEspressifPrefPageOpenocdPath();
path = EimConstants.EIM_WIN_PATH;
}
catch (
IOException
| ParseException e)
else
{
Logger.log(e);
path = EimConstants.EIM_POSIX_PATH;
}
File file = new File(path);
return file.exists();
}
String path = StringUtil.EMPTY;
if (Platform.getOS().equals(Platform.OS_WIN32))
{
path = EimConstants.EIM_WIN_PATH;
}
else
{
String userHome = System.getProperty("user.home");
path = userHome + EimConstants.EIM_POSIX_PATH.substring(1); // Remove the '~' character
}
File file = new File(path);
return file.exists();
}

Comment on lines 141 to 138
{
// TODO: Installer config flag is not set so we need to start IDF Manager and let user select the IDF for workspace
Display.getDefault().syncExec(()-> {
Shell shell = Display.getDefault().getActiveShell();
MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING| SWT.YES | SWT.NO);
messageBox.setText("No Active ESP-IDF in workspace");
messageBox.setMessage("No active ESP-IDF found in current workspace. Do you want to select the ESP-IDF for current workspace?");

int response = messageBox.open();
if (response == SWT.NO)
if (response == SWT.YES)
{
IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables();
updateEspIdfJsonFile(idf_json_file,
idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.IDF_PATH));
Preferences prefs = getPreferences();
prefs.putBoolean(IS_INSTALLER_CONFIG_SET, true);
IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow();
IDFUtil.closeWelcomePage(activeww);
try
{
prefs.flush();
IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimJson), ESPIDFManagerEditor.EDITOR_ID);
}
catch (BackingStoreException e)
catch (PartInitException e)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure eimJson is not null before using it

In the block where you open the editor with eimJson, ensure that eimJson is not null to prevent a potential NullPointerException.

Apply this diff to add a null check:

 if (!isInstallerConfigSet())
 {
     // ...
     if (response == SWT.YES)
     {
+        if (eimJson != null)
+        {
             IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow();
             IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimJson), ESPIDFManagerEditor.EDITOR_ID);
+        }
+        else
+        {
+            // Handle the case where eimJson is null
+            MessageBox errorMessageBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+            errorMessageBox.setText("Error");
+            errorMessageBox.setMessage("EIM configuration data is unavailable.");
+            errorMessageBox.open();
+        }
     }
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +50 to +43
import com.espressif.idf.core.tools.EimIdfConfiguratinParser;
import com.espressif.idf.core.tools.vo.EimJson;
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

⚠️ Potential issue

Coordinated rename required across core and UI bundles

The typo exists in multiple locations and requires coordinated changes:

  • Core bundle:
    • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java (class definition)
  • UI bundle:
    • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (import and field)
    • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (import and field)

Rename the class from EimIdfConfiguratinParser to EimIdfConfigurationParser and update all references.

🔗 Analysis chain

Correct the spelling of 'Configuratin' to 'Configuration'

There is a misspelling in the class name EimIdfConfiguratinParser and the variable eimIdfConfiguratinParser. Please correct 'Configuratin' to 'Configuration' to maintain consistency and avoid confusion.

Apply this diff to fix the typo:

-import com.espressif.idf.core.tools.EimIdfConfiguratinParser;
+import com.espressif.idf.core.tools.EimIdfConfigurationParser;

...

-private EimIdfConfiguratinParser eimIdfConfiguratinParser;
+private EimIdfConfigurationParser eimIdfConfigurationParser;

Run the following script to find and correct all occurrences of the typo in the codebase:

Also applies to: 87-88

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find and list all occurrences of 'Configuratin' in filenames and code.

# Find files with 'Configuratin' in their names
fd -e java -p 'Configuratin'

# Search code for 'Configuratin'
rg 'Configuratin' -t java

Length of output: 1737

Comment on lines +75 to +86
public static ESPIDFMainTablePage getInstance(EimJson eimJson)
{
if (espidfMainTablePage == null)
{
espidfMainTablePage = new ESPIDFMainTablePage();
}

ESPIDFMainTablePage.eimJson = eimJson;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid using a static eimJson variable to prevent threading issues

The static variable eimJson is being modified in the getInstance(EimJson eimJson) method. This could lead to threading issues if multiple threads access or modify eimJson concurrently. Consider making eimJson an instance variable or ensuring thread safety.

Comment on lines +12 to +13
public class EimIdfConfiguratinParser
{
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 class name typo.

The class name contains a typo: "Configuratin" should be "Configuration".

-public class EimIdfConfiguratinParser
+public class EimIdfConfigurationParser
📝 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
public class EimIdfConfiguratinParser
{
public class EimIdfConfigurationParser
{

Comment on lines +23 to +30
private void load() throws IOException
{
try (FileReader fileReader = new FileReader(
Platform.getOS().equals(Platform.OS_WIN32) ? EimConstants.EIM_WIN_PATH : EimConstants.EIM_POSIX_PATH))
{
eimJson = gson.fromJson(fileReader, EimJson.class);
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve error handling in load() method.

The load method should handle JSON parsing errors and file not found scenarios more gracefully.

 	private void load() throws IOException
 	{
+		File configFile = new File(
+			Platform.getOS().equals(Platform.OS_WIN32) ? 
+				EimConstants.EIM_WIN_PATH : 
+				EimConstants.EIM_POSIX_PATH
+		);
+		
+		if (!configFile.exists()) {
+			throw new FileNotFoundException("EIM configuration file not found: " + configFile.getPath());
+		}
+
 		try (FileReader fileReader = new FileReader(
-				Platform.getOS().equals(Platform.OS_WIN32) ? EimConstants.EIM_WIN_PATH : EimConstants.EIM_POSIX_PATH))
+				configFile))
 		{
 			eimJson = gson.fromJson(fileReader, EimJson.class);
+			if (eimJson == null) {
+				throw new IOException("Failed to parse EIM configuration file");
+			}
+		} catch (JsonSyntaxException e) {
+			throw new IOException("Invalid JSON format in EIM configuration file", e);
 		}
 	}
📝 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 void load() throws IOException
{
try (FileReader fileReader = new FileReader(
Platform.getOS().equals(Platform.OS_WIN32) ? EimConstants.EIM_WIN_PATH : EimConstants.EIM_POSIX_PATH))
{
eimJson = gson.fromJson(fileReader, EimJson.class);
}
}
private void load() throws IOException
{
File configFile = new File(
Platform.getOS().equals(Platform.OS_WIN32) ?
EimConstants.EIM_WIN_PATH :
EimConstants.EIM_POSIX_PATH
);
if (!configFile.exists()) {
throw new FileNotFoundException("EIM configuration file not found: " + configFile.getPath());
}
try (FileReader fileReader = new FileReader(configFile))
{
eimJson = gson.fromJson(fileReader, EimJson.class);
if (eimJson == null) {
throw new IOException("Failed to parse EIM configuration file");
}
} catch (JsonSyntaxException e) {
throw new IOException("Invalid JSON format in EIM configuration file", e);
}
}

Comment on lines +25 to +28
public void setActivationScript(String activationScript)
{
this.activationScript = activationScript;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Validate path parameters.

Path-related setters should validate their input to ensure they contain valid paths.

 	public void setPath(String path)
 	{
+		if (path == null || path.trim().isEmpty()) {
+			throw new IllegalArgumentException("Path cannot be null or empty");
+		}
 		this.path = path;
 	}

 	public void setActivationScript(String activationScript)
 	{
+		if (activationScript == null || activationScript.trim().isEmpty()) {
+			throw new IllegalArgumentException("Activation script path cannot be null or empty");
+		}
 		this.activationScript = activationScript;
 	}

Also applies to: 65-68

Comment on lines +56 to +57
ESPIDFMainTablePage espidfMainTablePage = ESPIDFMainTablePage
.getInstance(((EimEditorInput) getEditorInput()).getEimJson());
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for the editor input cast and EimJson retrieval.

The current implementation assumes the editor input will always be of type EimEditorInput. This could lead to runtime exceptions if a different input type is provided.

Add proper error handling:

-		ESPIDFMainTablePage espidfMainTablePage = ESPIDFMainTablePage
-				.getInstance(((EimEditorInput) getEditorInput()).getEimJson());
+		IEditorInput input = getEditorInput();
+		if (!(input instanceof EimEditorInput)) {
+			throw new IllegalStateException("Expected EimEditorInput but got: " + input.getClass().getName());
+		}
+		EimJson eimJson = ((EimEditorInput) input).getEimJson();
+		if (eimJson == null) {
+			throw new IllegalStateException("EimJson configuration is null");
+		}
+		ESPIDFMainTablePage espidfMainTablePage = ESPIDFMainTablePage.getInstance(eimJson);
📝 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
ESPIDFMainTablePage espidfMainTablePage = ESPIDFMainTablePage
.getInstance(((EimEditorInput) getEditorInput()).getEimJson());
IEditorInput input = getEditorInput();
if (!(input instanceof EimEditorInput)) {
throw new IllegalStateException("Expected EimEditorInput but got: " + input.getClass().getName());
}
EimJson eimJson = ((EimEditorInput) input).getEimJson();
if (eimJson == null) {
throw new IllegalStateException("EimJson configuration is null");
}
ESPIDFMainTablePage espidfMainTablePage = ESPIDFMainTablePage.getInstance(eimJson);

@@ -19,6 +19,8 @@ IDFBuildConfiguration_ParseCommand=Parse Compile Commands File
IncreasePartitionSizeTitle=Low Application Partition Size
IncreasePartitionSizeMessage=Less than 30% of application partition size is free({0} of {1} bytes), would you like to increase it? Please click <a href={2}>here</a> to check more details.
ToolsInitializationDifferentPathMessageBoxTitle=Different IDF path found in the config file
ToolsInitializationEimMissingMsgBoxTitle=ESP-IDF Missing
ToolsInitializationEimMissingMsgBoxMessage=ESP-IDF is not found on your system. Please user EIM to install the ESP-IDF on your system to use the IDE. Click Yes to go to the download page and install EIM.
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 typo and improve message clarity.

The message contains a typo and could be more specific about the user action required.

Fix the typo and improve the message:

-ToolsInitializationEimMissingMsgBoxMessage=ESP-IDF is not found on your system. Please user EIM to install the ESP-IDF on your system to use the IDE. Click Yes to go to the download page and install EIM.
+ToolsInitializationEimMissingMsgBoxMessage=ESP-IDF is not found on your system. Please use EIM (Espressif Installation Manager) to install the ESP-IDF on your system to use the IDE. When prompted, click Yes to open the EIM download page in your browser.
📝 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
ToolsInitializationEimMissingMsgBoxMessage=ESP-IDF is not found on your system. Please user EIM to install the ESP-IDF on your system to use the IDE. Click Yes to go to the download page and install EIM.
ToolsInitializationEimMissingMsgBoxMessage=ESP-IDF is not found on your system. Please use EIM (Espressif Installation Manager) to install the ESP-IDF on your system to use the IDE. When prompted, click Yes to open the EIM download page in your browser.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 16

🔭 Outside diff range comments (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)

Line range hint 517-534: Fix incorrect column index mapping in compare method.

The switch statement's case indices don't match the column order defined in setupColumns(). This will result in incorrect sorting behavior.

Apply this fix:

 switch (propertyIndex) {
 case 0:
-  rc = p1.getName().compareTo(p2.getName());
+  rc = Boolean.compare(
+    ToolsUtility.isIdfInstalledActive(p1),
+    ToolsUtility.isIdfInstalledActive(p2));
   break;
 case 1:
-  rc = p1.getPath().compareTo(p2.getPath());
+  rc = getIdfVersion(p1).compareTo(getIdfVersion(p2));
   break;
 case 2:
-  Boolean p1State = ToolsUtility.isIdfInstalledActive(p1);
-  Boolean p2State = ToolsUtility.isIdfInstalledActive(p2);
-  rc = p1State.compareTo(p2State);
+  rc = p1.getName().compareTo(p2.getName());
+  break;
+case 3:
+  rc = p1.getPath().compareTo(p2.getPath());
   break;
 default:
   break;
🧹 Nitpick comments (8)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)

386-400: Consider extracting the setup tools initialization to a separate method.

The button event handler contains complex initialization logic that could be moved to a dedicated method for better maintainability.

Extract the setup tools initialization:

+private void initializeSetupTools(IdfInstalled idfInstalled, Button button) {
+  IDFConsole idfConsole = new IDFConsole();
+  MessageConsoleStream standardConsoleStream = 
+    idfConsole.getConsoleStream(Messages.IDFToolsHandler_ToolsManagerConsole, null, false, true);
+  MessageConsoleStream errorConsoleStream = 
+    idfConsole.getConsoleStream(Messages.IDFToolsHandler_ToolsManagerConsole, null, true, true);
+  SetupToolsInIde setupToolsInIde = 
+    new SetupToolsInIde(idfInstalled, eimJson, errorConsoleStream, standardConsoleStream);
+  SetupToolsJobListener toolsActivationJobListener = 
+    new SetupToolsJobListener(ESPIDFMainTablePage.this, setupToolsInIde);
+  setupToolsInIde.addJobChangeListener(toolsActivationJobListener);
+  setupToolsInIde.schedule();
+  button.setEnabled(false);
+}

 setActiveButton.addListener(SWT.Selection, e -> {
   Button btn = (Button) e.widget;
-  IDFConsole idfConsole = new IDFConsole();
-  MessageConsoleStream standardConsoleStream = ...
-  MessageConsoleStream errorConsoleStream = ...
-  SetupToolsInIde setupToolsInIde = ...
-  SetupToolsJobListener toolsActivationJobListener = ...
-  setupToolsInIde.addJobChangeListener(toolsActivationJobListener);
-  setupToolsInIde.schedule();
-  btn.setEnabled(false);
+  initializeSetupTools((IdfInstalled) btn.getData(IDF_TOOL_SET_BTN_KEY), btn);
 });
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (5)

38-55: Use try-with-resources to ensure the FileInputStream is properly closed

The FileInputStream should be enclosed in a try-with-resources statement to automatically handle the resource closing, even if an exception occurs. This improves resource management and prevents potential resource leaks.

Apply this refactor:

-public static String getFileChecksum(MessageDigest digest, File file) throws IOException
-{
-	FileInputStream fis = new FileInputStream(file);
-	byte[] byteArray = new byte[1024];
-	int bytesCount = 0;
-	while ((bytesCount = fis.read(byteArray)) != -1)
-	{
-		digest.update(byteArray, 0, bytesCount);
-	}
-	;
-	fis.close();
-	byte[] bytes = digest.digest();
-	StringBuilder sb = new StringBuilder();
-	for (int i = 0; i < bytes.length; i++)
-	{
-		sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
-	}
-	return sb.toString();
-}
+public static String getFileChecksum(MessageDigest digest, File file) throws IOException
+{
+	try (FileInputStream fis = new FileInputStream(file))
+	{
+		byte[] byteArray = new byte[1024];
+		int bytesCount = 0;
+		while ((bytesCount = fis.read(byteArray)) != -1)
+		{
+			digest.update(byteArray, 0, bytesCount);
+		}
+	}
+	byte[] bytes = digest.digest();
+	StringBuilder sb = new StringBuilder();
+	for (int i = 0; i < bytes.length; i++)
+	{
+		sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
+	}
+	return sb.toString();
+}

47-47: Remove unnecessary semicolon

There is an extraneous semicolon after the while loop that is not required and can be removed to clean up the code.

Apply this change:

-	;

58-96: Remove unused parameter 'gitPath' in getIdfVersion method

The parameter gitPath is not utilized within the getIdfVersion method. Removing it will simplify the method signature and avoid confusion.

Apply this change:

-public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath)
+public static String getIdfVersion(IdfInstalled idfInstalled)

Ensure to update any calls to this method accordingly in the codebase.


65-96: Check the exit value of the process to ensure successful execution

After executing the activation script, it's good practice to verify if the process exited successfully. Checking the exit code can help handle errors gracefully and provide better debugging information.

You can enhance the code as follows:

process.waitFor();
+int exitCode = process.exitValue();
+if (exitCode != 0) {
+	Logger.log("Activation script exited with code: " + exitCode);
+	// Handle the error as needed
+}

122-124: Optimize environment variable retrieval

Creating a new IDFEnvironmentVariables instance each time may not be efficient. Consider reusing an existing instance or implementing a singleton pattern if appropriate.

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1)

343-364: Optimize process waiting by using waitFor with a timeout

The current implementation uses a custom loop with Thread.sleep() to wait for the process to complete, which may not be efficient.

Consider using process.waitFor(long timeout, TimeUnit unit) to wait for the process with a specified timeout. This simplifies the code and enhances reliability.

Apply this diff to refactor the code:

  try
  {
      Process process = processRunner.run(arguments, org.eclipse.core.runtime.Path.ROOT, env);
      BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
      String line;
      while ((line = reader.readLine()) != null)
      {
          output.append(line).append(System.lineSeparator());
      }
-     int waitCount = 10;
-     while (process.isAlive() && waitCount > 0)
-     {
-         try
-         {
-             Thread.sleep(300);					
-         }
-         catch (InterruptedException e)
-         {
-             Logger.log(e);
-         }
-         waitCount--;
-     }
-     if (waitCount == 0)
+     boolean finished = process.waitFor(3000, TimeUnit.MILLISECONDS);
+     if (!finished)
      {
          log("Process possibly stuck", IStatus.ERROR); //$NON-NLS-1$
          return Status.CANCEL_STATUS;
      }
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (1)

62-63: Consider using dependency injection

The direct instantiation of EimIdfConfiguratinParser creates tight coupling between UI and core components. Consider using dependency injection to improve modularity and testability.

  1. Define an interface in the core bundle:
public interface IEimConfigurationParser {
    EimJson getEimJson(boolean refresh) throws IOException;
}
  1. Use OSGi services or a dependency injection framework to inject the implementation:
@Inject
private IEimConfigurationParser configurationParser;

Also applies to: 101-104

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bcddd42 and 3c9bf5c.

⛔ Files ignored due to path filters (1)
  • bundles/com.espressif.idf.ui/icons/tools/delete.png is excluded by !**/*.png
📒 Files selected for processing (14)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/Messages.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/messages.properties (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (2 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (3 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFNewToolsWizard.java (2 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java (2 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (2 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (4 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (13 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: build_macos
🔇 Additional comments (14)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)

121-121: LGTM! Message declarations follow established patterns.

The new message declarations for EspIdfManagerNameCol and IDFToolsHandler_ToolsManagerConsole are consistent with the existing naming conventions and properly support the EIM integration UI components.

Also applies to: 133-133

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties (3)

117-117: LGTM! Clear and concise column header.

The message value "Name" for EspIdfManagerNameCol is appropriately simple and follows UI text best practices.


133-134: LGTM! Clear user instruction.

The message for IDFDownloadHandler_DownloadPageMsg provides clear guidance to users about their options.


135-135: LGTM! Consistent console title.

The message for IDFToolsHandler_ToolsManagerConsole follows product naming conventions and clearly identifies the console purpose.

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (2)

68-68: ⚠️ Potential issue

Consider making eimJson an instance variable to prevent threading issues.

The static eimJson variable could lead to race conditions if multiple instances of the plugin are running concurrently.

Convert the static variable to an instance variable:

-private static EimJson eimJson;
+private EimJson eimJson;

Likely invalid or redundant comment.


437-441: ⚠️ Potential issue

Implement the reload functionality.

The reload button's event handler contains commented-out code that needs to be implemented.

Let's verify if the required classes exist in the codebase:

✅ Verification successful

Uncomment the reload functionality implementation

The required classes and methods exist in the codebase. The commented code should be uncommented as it contains the correct implementation using:

  • ToolsActivationJob from com.espressif.idf.ui.tools
  • IDFUtil.getPythonExecutable() and IDFUtil.getGitExecutablePathFromSystem() from com.espressif.idf.core.util
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for ToolsActivationJob class
ast-grep --pattern 'class ToolsActivationJob {
  $$$
}'

# Search for IDFUtil class methods
ast-grep --pattern 'class IDFUtil {
  $$$
  getPythonExecutable() {
    $$$
  }
  $$$
  getGitExecutablePathFromSystem() {
    $$$
  }
  $$$
}'

Length of output: 203


Script:

#!/bin/bash
# Search for ToolsActivationJob and related classes
rg -l "ToolsActivationJob|ToolsActivationJobListener" --type java

# Search for IDFUtil class and its methods
rg "class.*IDFUtil|getPythonExecutable|getGitExecutablePathFromSystem" -A 5 --type java

# Search for similar job patterns in case names changed
rg "class.*Job.*extends.*Job.*activation" -A 5 --type java

Length of output: 10993

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java (1)

15-15: LGTM!

The integration of EimEditorInput and the updated configuration parser enhances the configuration management approach. The implementation is clean and aligns with best practices.

Also applies to: 41-41

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (1)

99-117: Validate activationScriptPath to prevent security risks

Ensure that activationScriptPath is properly validated to prevent command injection or execution of unintended scripts.

Please confirm that activationScriptPath comes from a trusted source or implement validation checks.

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/Messages.java (1)

1-27: Code structure and internationalization setup look good

The Messages class is properly configured for internationalization using NLS.

bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java (1)

55-56: LGTM! Environment variable constant follows conventions.

The new constant ESP_IDF_EIM_ID follows the established naming pattern and is properly documented.

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java (1)

9-9: Ensure POSIX path resolves the user's home directory

The constant EIM_POSIX_PATH uses '~' to represent the user's home directory. This will not be automatically expanded when used with File.

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (3)

37-38: Fix typo in class name and field

The class name and field have a typo: 'Configuratin' should be 'Configuration'.

This issue was previously identified and requires coordinated changes across core and UI bundles. Please refer to the previous review comment for the complete fix.

Also applies to: 62-63


142-156: Fix path handling for POSIX systems

The POSIX path handling doesn't expand the '~' character to the user's home directory.

This issue was previously identified. Please refer to the previous review comment for the complete fix.


106-114: 🛠️ Refactor suggestion

Improve error handling for EIM JSON parsing

The error handling for IOException is insufficient. The error should be propagated to the user since this is a critical initialization step.

Apply this diff to improve error handling:

     try
     {
         eimJson = eimIdfConfiguratinParser.getEimJson(true);
     }
     catch (IOException e)
     {
         Logger.log(e);
+        Display.getDefault().asyncExec(() -> {
+            Shell shell = Display.getDefault().getActiveShell();
+            if (shell == null) {
+                shell = new Shell(Display.getDefault());
+            }
+            MessageBox errorBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+            errorBox.setText("EIM Configuration Error");
+            errorBox.setMessage("Failed to load EIM configuration: " + e.getMessage());
+            errorBox.open();
+            if (shell.isDisposed()) {
+                shell.dispose();
+            }
+        });
     }

Likely invalid or redundant comment.

Comment on lines +211 to +233
public static String getIDFPythonEnvPath(String idfPyEnvPath)
{
idfPyEnvPath = idfPyEnvPath.strip();
if (!StringUtil.isEmpty(idfPyEnvPath))
{

if (Platform.getOS().equals(Platform.OS_WIN32))
{
idfPyEnvPath = idfPyEnvPath + "/" + "Scripts"; //$NON-NLS-1$ //$NON-NLS-2$
}
else
{
idfPyEnvPath = idfPyEnvPath + "/" + "bin"; //$NON-NLS-1$ //$NON-NLS-2$
}
java.nio.file.Path commandPath = findCommand(IDFConstants.PYTHON_CMD, idfPyEnvPath);
if (commandPath != null)
{
return commandPath.toFile().getAbsolutePath();
}
}
return findCommandFromBuildEnvPath(IDFConstants.PYTHON_CMD);

}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add null check and improve error handling.

The new method has potential issues that need to be addressed:

  1. Missing null check could lead to NullPointerException
  2. Silent failure when command path is not found
  3. Platform-dependent path separator usage

Apply this diff to fix the issues:

 public static String getIDFPythonEnvPath(String idfPyEnvPath)
 {
+    if (idfPyEnvPath == null) {
+        Logger.log("idfPyEnvPath is null, falling back to build environment PATH");
+        return findCommandFromBuildEnvPath(IDFConstants.PYTHON_CMD);
+    }
     idfPyEnvPath = idfPyEnvPath.strip();
     if (!StringUtil.isEmpty(idfPyEnvPath))
     {
         if (Platform.getOS().equals(Platform.OS_WIN32))
         {
-            idfPyEnvPath = idfPyEnvPath + "/" + "Scripts"; //$NON-NLS-1$ //$NON-NLS-2$
+            idfPyEnvPath = idfPyEnvPath + File.separator + "Scripts"; //$NON-NLS-1$
         }
         else
         {
-            idfPyEnvPath = idfPyEnvPath + "/" + "bin"; //$NON-NLS-1$ //$NON-NLS-2$
+            idfPyEnvPath = idfPyEnvPath + File.separator + "bin"; //$NON-NLS-1$
         }
         java.nio.file.Path commandPath = findCommand(IDFConstants.PYTHON_CMD, idfPyEnvPath);
         if (commandPath != null)
         {
             return commandPath.toFile().getAbsolutePath();
+        } else {
+            Logger.log("Python command not found in " + idfPyEnvPath + ", falling back to build environment PATH");
         }
     }
     return findCommandFromBuildEnvPath(IDFConstants.PYTHON_CMD);
 }

Committable suggestion skipped: line range outside the PR's diff.


🛠️ Refactor suggestion

Reduce code duplication with the existing getIDFPythonEnvPath() method.

The new method duplicates most of the logic from the existing method. Consider refactoring to share the common code.

Apply this diff to reduce duplication:

+private static String getIDFPythonEnvPathInternal(String idfPyEnvPath) {
+    if (idfPyEnvPath == null) {
+        Logger.log("idfPyEnvPath is null, falling back to build environment PATH");
+        return findCommandFromBuildEnvPath(IDFConstants.PYTHON_CMD);
+    }
+    idfPyEnvPath = idfPyEnvPath.strip();
+    if (!StringUtil.isEmpty(idfPyEnvPath))
+    {
+        if (Platform.getOS().equals(Platform.OS_WIN32))
+        {
+            idfPyEnvPath = idfPyEnvPath + File.separator + "Scripts"; //$NON-NLS-1$
+        }
+        else
+        {
+            idfPyEnvPath = idfPyEnvPath + File.separator + "bin"; //$NON-NLS-1$
+        }
+        java.nio.file.Path commandPath = findCommand(IDFConstants.PYTHON_CMD, idfPyEnvPath);
+        if (commandPath != null)
+        {
+            return commandPath.toFile().getAbsolutePath();
+        }
+        Logger.log("Python command not found in " + idfPyEnvPath + ", falling back to build environment PATH");
+    }
+    return findCommandFromBuildEnvPath(IDFConstants.PYTHON_CMD);
+}

 public static String getIDFPythonEnvPath()
 {
-    String idfPyEnvPath = new IDFEnvironmentVariables().getEnvValue(IDFEnvironmentVariables.IDF_PYTHON_ENV_PATH);
-    idfPyEnvPath = idfPyEnvPath.strip();
-    if (!StringUtil.isEmpty(idfPyEnvPath))
-    {
-        if (Platform.getOS().equals(Platform.OS_WIN32))
-        {
-            idfPyEnvPath = idfPyEnvPath + "/" + "Scripts"; //$NON-NLS-1$ //$NON-NLS-2$
-        }
-        else
-        {
-            idfPyEnvPath = idfPyEnvPath + "/" + "bin"; //$NON-NLS-1$ //$NON-NLS-2$
-        }
-        java.nio.file.Path commandPath = findCommand(IDFConstants.PYTHON_CMD, idfPyEnvPath);
-        if (commandPath != null)
-        {
-            return commandPath.toFile().getAbsolutePath();
-        }
-    }
-    return findCommandFromBuildEnvPath(IDFConstants.PYTHON_CMD);
+    return getIDFPythonEnvPathInternal(
+        new IDFEnvironmentVariables().getEnvValue(IDFEnvironmentVariables.IDF_PYTHON_ENV_PATH)
+    );
 }

 public static String getIDFPythonEnvPath(String idfPyEnvPath)
 {
-    idfPyEnvPath = idfPyEnvPath.strip();
-    if (!StringUtil.isEmpty(idfPyEnvPath))
-    {
-        if (Platform.getOS().equals(Platform.OS_WIN32))
-        {
-            idfPyEnvPath = idfPyEnvPath + "/" + "Scripts"; //$NON-NLS-1$ //$NON-NLS-2$
-        }
-        else
-        {
-            idfPyEnvPath = idfPyEnvPath + "/" + "bin"; //$NON-NLS-1$ //$NON-NLS-2$
-        }
-        java.nio.file.Path commandPath = findCommand(IDFConstants.PYTHON_CMD, idfPyEnvPath);
-        if (commandPath != null)
-        {
-            return commandPath.toFile().getAbsolutePath();
-        }
-    }
-    return findCommandFromBuildEnvPath(IDFConstants.PYTHON_CMD);
+    return getIDFPythonEnvPathInternal(idfPyEnvPath);
 }
📝 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
public static String getIDFPythonEnvPath(String idfPyEnvPath)
{
idfPyEnvPath = idfPyEnvPath.strip();
if (!StringUtil.isEmpty(idfPyEnvPath))
{
if (Platform.getOS().equals(Platform.OS_WIN32))
{
idfPyEnvPath = idfPyEnvPath + "/" + "Scripts"; //$NON-NLS-1$ //$NON-NLS-2$
}
else
{
idfPyEnvPath = idfPyEnvPath + "/" + "bin"; //$NON-NLS-1$ //$NON-NLS-2$
}
java.nio.file.Path commandPath = findCommand(IDFConstants.PYTHON_CMD, idfPyEnvPath);
if (commandPath != null)
{
return commandPath.toFile().getAbsolutePath();
}
}
return findCommandFromBuildEnvPath(IDFConstants.PYTHON_CMD);
}
private static String getIDFPythonEnvPathInternal(String idfPyEnvPath) {
if (idfPyEnvPath == null) {
Logger.log("idfPyEnvPath is null, falling back to build environment PATH");
return findCommandFromBuildEnvPath(IDFConstants.PYTHON_CMD);
}
idfPyEnvPath = idfPyEnvPath.strip();
if (!StringUtil.isEmpty(idfPyEnvPath))
{
if (Platform.getOS().equals(Platform.OS_WIN32))
{
idfPyEnvPath = idfPyEnvPath + File.separator + "Scripts"; //$NON-NLS-1$
}
else
{
idfPyEnvPath = idfPyEnvPath + File.separator + "bin"; //$NON-NLS-1$
}
java.nio.file.Path commandPath = findCommand(IDFConstants.PYTHON_CMD, idfPyEnvPath);
if (commandPath != null)
{
return commandPath.toFile().getAbsolutePath();
}
Logger.log("Python command not found in " + idfPyEnvPath + ", falling back to build environment PATH");
}
return findCommandFromBuildEnvPath(IDFConstants.PYTHON_CMD);
}
public static String getIDFPythonEnvPath()
{
return getIDFPythonEnvPathInternal(
new IDFEnvironmentVariables().getEnvValue(IDFEnvironmentVariables.IDF_PYTHON_ENV_PATH)
);
}
public static String getIDFPythonEnvPath(String idfPyEnvPath)
{
return getIDFPythonEnvPathInternal(idfPyEnvPath);
}

Comment on lines 449 to 461
// Button removeButton = new Button(buttonComposite, SWT.PUSH | SWT.FLAT);
// removeButton.pack();
// removeButton.setData(IDF_TOOL_SET_BTN_KEY, idfInstalled);
// removeButton.setImage(UIPlugin.getImage(REMOVE_ICON));
// removeButton.setToolTipText(Messages.EspIdfManagerDeleteBtnToolTip);
// removeButton.addListener(SWT.Selection, e -> {
// Button btn = (Button) e.widget;
// IdfInstalled selectedToolSet = (IdfInstalled) btn.getData(IDF_TOOL_SET_BTN_KEY);
// performDeleteOperation(selectedToolSet);
// refreshEditorUI();
// });
// removeButton.setSize(cellBounds.width, buttonHeight);
// removeButton.redraw();
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

⚠️ Potential issue

Fix type mismatch before implementing remove functionality

The remove button implementation is commented out, but simply uncommenting won't work. There's a type mismatch:

  • The button stores data of type IdfInstalled
  • The performDeleteOperation method expects IDFToolSet
🔗 Analysis chain

Implement the remove functionality.

The remove button's creation and event handling code is commented out, which means the UI lacks the ability to remove IDF installations.

Let's verify if we can safely uncomment this code:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for REMOVE_ICON constant
rg "REMOVE_ICON.*=.*" -A 1

# Search for performDeleteOperation method implementation
ast-grep --pattern 'performDeleteOperation(IdfInstalled $_) {
  $$$
}'

Length of output: 101


Script:

#!/bin/bash
# Search for any icon-related constants and remove/delete operations
rg -i "remove.*icon|delete.*icon" -g "*.java"

# Search for any method containing delete or remove in the name
ast-grep --pattern 'void $_delete$_($_) {
  $$$
}'

# Search for any method containing delete or remove with different signature
ast-grep --pattern 'boolean $_delete$_($_) {
  $$$
}'

# Look for Messages class and tooltip
rg "EspIdfManagerDeleteBtnToolTip" -g "*.java"

Length of output: 662


Script:

#!/bin/bash
# Search for performDeleteOperation with any signature
rg "performDeleteOperation" -g "*.java" -A 5

# Search for any method containing perform and delete
rg "perform.*delete|delete.*perform" -g "*.java" -A 5

# Get more context around the button implementation
rg -B 10 -A 10 "removeButton.setImage" -g "*.java"

Length of output: 4845


import com.espressif.idf.core.logging.Logger;
import com.espressif.idf.core.tools.IToolsInstallationWizardConstants;
import com.espressif.idf.core.tools.EimIdfConfiguratinParser;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Correct the typo in EimIdfConfiguratinParser.

The class name EimIdfConfiguratinParser appears to have a typographical error. It should be EimIdfConfigurationParser. This typo affects the import statement and its usage in the code.

Apply this diff to correct the class name:

- import com.espressif.idf.core.tools.EimIdfConfiguratinParser;
+ import com.espressif.idf.core.tools.EimIdfConfigurationParser;
- EimIdfConfiguratinParser eimIdfConfiguratinParser = new EimIdfConfiguratinParser();
+ EimIdfConfigurationParser eimIdfConfigurationParser = new EimIdfConfigurationParser();
- IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimIdfConfiguratinParser.getEimJson(true)), ESPIDFManagerEditor.EDITOR_ID);
+ IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimIdfConfigurationParser.getEimJson(true)), ESPIDFManagerEditor.EDITOR_ID);

Also applies to: 39-41

Comment on lines +120 to +93
public static boolean isIdfInstalledActive(IdfInstalled idfInstalled)
{
if (StringUtil.isEmpty(path))
{
Map<String, String> env = IDFUtil.getSystemEnv();
if (env.containsKey(IDFEnvironmentVariables.PATH))
path = env.get(IDFEnvironmentVariables.PATH);
else
path = env.get("Path"); //$NON-NLS-1$
}

SystemExecutableFinder systemExecutableFinder = new SystemExecutableFinder(new ToolsSystemWrapper(path));
return systemExecutableFinder.find(toolName);
IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables();
String espIdfIdEim = idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.ESP_IDF_EIM_ID);
return idfInstalled.getId().equals(espIdfIdEim);
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 potential NullPointerException in isIdfInstalledActive method

If idfInstalled.getId() could be null, calling .equals() on it may lead to a NullPointerException. Use Objects.equals() to safely compare the IDs.

Apply this fix:

-import com.espressif.idf.core.IDFEnvironmentVariables;
+import com.espressif.idf.core.IDFEnvironmentVariables;
+import java.util.Objects;

...

-return idfInstalled.getId().equals(espIdfIdEim);
+return Objects.equals(idfInstalled.getId(), espIdfIdEim);
📝 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
public static boolean isIdfInstalledActive(IdfInstalled idfInstalled)
{
if (StringUtil.isEmpty(path))
{
Map<String, String> env = IDFUtil.getSystemEnv();
if (env.containsKey(IDFEnvironmentVariables.PATH))
path = env.get(IDFEnvironmentVariables.PATH);
else
path = env.get("Path"); //$NON-NLS-1$
}
SystemExecutableFinder systemExecutableFinder = new SystemExecutableFinder(new ToolsSystemWrapper(path));
return systemExecutableFinder.find(toolName);
IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables();
String espIdfIdEim = idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.ESP_IDF_EIM_ID);
return idfInstalled.getId().equals(espIdfIdEim);
import com.espressif.idf.core.IDFEnvironmentVariables;
import java.util.Objects;
public static boolean isIdfInstalledActive(IdfInstalled idfInstalled)
{
IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables();
String espIdfIdEim = idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.ESP_IDF_EIM_ID);
return Objects.equals(idfInstalled.getId(), espIdfIdEim);

Comment on lines 81 to 54
if (line.startsWith("ESP_IDF_VERSION=")) //$NON-NLS-1$
{
espIdfVersion = line.split("=")[1]; //$NON-NLS-1$
break;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid potential ArrayIndexOutOfBoundsException when splitting the version string

When splitting the line to extract espIdfVersion, ensure that the line contains an = character to prevent an ArrayIndexOutOfBoundsException.

Apply this fix:

if (line.startsWith("ESP_IDF_VERSION=")) //$NON-NLS-1$
{
+	if (line.contains("=")) {
		espIdfVersion = line.split("=")[1]; //$NON-NLS-1$
		break;
+	}
}
📝 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
if (line.startsWith("ESP_IDF_VERSION=")) //$NON-NLS-1$
{
espIdfVersion = line.split("=")[1]; //$NON-NLS-1$
break;
}
if (line.startsWith("ESP_IDF_VERSION=")) //$NON-NLS-1$
{
if (line.contains("=")) {
espIdfVersion = line.split("=")[1]; //$NON-NLS-1$
break;
}
}

Comment on lines 342 to 346
ToolsActivationJob toolsActivationJob = new ToolsActivationJob(idfToolSets.get(0), pythonPath, gitPath);
ToolsActivationJobListener toolsActivationJobListener = new ToolsActivationJobListener(espidfMainTablePage);
toolsActivationJob.addJobChangeListener(toolsActivationJobListener);
toolsActivationJob.schedule();
// SetupToolsJobListener toolsActivationJobListener = new SetupToolsJobListener(espidfMainTablePage4);
// toolsActivationJob.addJobChangeListener(toolsActivationJobListener);
// toolsActivationJob.schedule();
}
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Critical: Tools activation must not be disabled

The commented-out code prevents essential IDE setup:

  • Environment variables required for ESP-IDF development won't be configured
  • Toolchains and build targets won't be initialized
  • OpenOCD debugging capabilities on Linux won't be properly set up
  • WebSocket client installation will be skipped
🔗 Analysis chain

Verify the impact of disabling tools activation.

The tools activation process has been disabled by commenting out the listener setup. This could affect the IDE's ability to use the tools after installation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for references to ToolsActivationJob to understand the impact
rg "ToolsActivationJob" -A 5

Length of output: 3960


Script:

#!/bin/bash
# Get the implementation of ToolsActivationJob
cat bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java

Length of output: 7300


public interface EimConstants
{
String EIM_WIN_PATH = "C:\\Espressif\\tools\\esp_ide.json"; //$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.

🛠️ Refactor suggestion

Consider making Windows path configurable.

The hardcoded Windows path C:\\Espressif\\tools\\esp_ide.json might not be suitable for all installations. Consider:

  1. Making it configurable through preferences
  2. Using a relative path to the user's home directory

InstallToolsHandler_OpenOCDRulesCopyWarning=Warning
InstallToolsHandler_OpenOCDRulesCopyWarningMessage=The rules file is already present in the /etc/udev/rules.d/ directory, Do you want to replace the file with the file from OpenOCD directory
InstallToolsHandler_OpenOCDRulesNotCopied=Rules Not Copied to system
InstallToolsHandler_OpenOCDRulesCopyError=Unable to copy rules for OpenOCD to system directory, try running the eclipse with sudo command
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Make error message platform-agnostic.

The error message specifically mentions the sudo command, which is Linux/Unix specific. Consider making it platform-agnostic, such as "try running Eclipse with administrator privileges".

-InstallToolsHandler_OpenOCDRulesCopyError=Unable to copy rules for OpenOCD to system directory, try running the eclipse with sudo command
+InstallToolsHandler_OpenOCDRulesCopyError=Unable to copy rules for OpenOCD to system directory. Please try running Eclipse with administrator privileges
📝 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
InstallToolsHandler_OpenOCDRulesCopyError=Unable to copy rules for OpenOCD to system directory, try running the eclipse with sudo command
InstallToolsHandler_OpenOCDRulesCopyError=Unable to copy rules for OpenOCD to system directory. Please try running Eclipse with administrator privileges

Comment on lines +158 to +247
private void userNotficationToInstallEim()
{
Display.getDefault().asyncExec(()-> {
Shell shell = new Shell(Display.getDefault());
MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.YES | SWT.NO);

messageBox.setText(Messages.ToolsInitializationEimMissingMsgBoxTitle);
messageBox.setMessage(Messages.ToolsInitializationEimMissingMsgBoxMessage);
int response = messageBox.open();
if (response == SWT.YES)
{
Program.launch(EimConstants.EIM_URL);
}
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve shell management and URL handling

Several issues in the notification method:

  1. Shell is created but never disposed
  2. Direct URL launch could be a security concern

Apply this diff to improve the implementation:

     private void userNotficationToInstallEim()
     {
         Display.getDefault().asyncExec(()-> {
-            Shell shell = new Shell(Display.getDefault());
+            Shell shell = Display.getDefault().getActiveShell();
+            if (shell == null) {
+                shell = new Shell(Display.getDefault());
+            }
             MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.YES | SWT.NO);
             
             messageBox.setText(Messages.ToolsInitializationEimMissingMsgBoxTitle);
             messageBox.setMessage(Messages.ToolsInitializationEimMissingMsgBoxMessage);
             int response = messageBox.open();
             if (response == SWT.YES)
             {
-                Program.launch(EimConstants.EIM_URL);
+                // Validate URL before launching
+                String url = EimConstants.EIM_URL;
+                if (url != null && (url.startsWith("https://") || url.startsWith("http://"))) {
+                    Program.launch(url);
+                } else {
+                    Logger.log("Invalid URL format: " + url);
+                    MessageBox errorBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+                    errorBox.setText("Error");
+                    errorBox.setMessage("Invalid URL format");
+                    errorBox.open();
+                }
             }   
+            if (shell.isDisposed()) {
+                shell.dispose();
+            }
         });
     }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 118 to 142
Display.getDefault().syncExec(()-> {
Shell shell = Display.getDefault().getActiveShell();
MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING| SWT.YES | SWT.NO);
messageBox.setText("No Active ESP-IDF in workspace");
messageBox.setMessage("No active ESP-IDF found in current workspace. Do you want to select the ESP-IDF for current workspace?");

int response = messageBox.open();
if (response == SWT.NO)
if (response == SWT.YES)
{
IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables();
updateEspIdfJsonFile(idf_json_file,
idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.IDF_PATH));
Preferences prefs = getPreferences();
prefs.putBoolean(IS_INSTALLER_CONFIG_SET, true);
IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow();
IDFUtil.closeWelcomePage(activeww);
try
{
prefs.flush();
IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimJson), ESPIDFManagerEditor.EDITOR_ID);
}
catch (BackingStoreException e)
catch (PartInitException e)
{
Logger.log(e);
}

return;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ensure proper shell disposal and handle edge cases

The code has several issues:

  1. The shell obtained from Display.getDefault().getActiveShell() might be null if no window is active.
  2. The code runs in syncExec which could cause UI freezes. Consider using asyncExec for better responsiveness.

Apply this diff to improve the implementation:

-      Display.getDefault().syncExec(()-> {
-          Shell shell = Display.getDefault().getActiveShell();
+      Display.getDefault().asyncExec(()-> {
+          Shell shell = Display.getDefault().getActiveShell();
+          if (shell == null) {
+              shell = new Shell(Display.getDefault());
+          }
           MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING| SWT.YES | SWT.NO);
           messageBox.setText("No Active ESP-IDF in workspace");
           messageBox.setMessage("No active ESP-IDF found in current workspace. Do you want to select the ESP-IDF for current workspace?");
           
           int response = messageBox.open();
           if (response == SWT.YES)
           {
               IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow();
+              if (activeww == null) {
+                  Logger.log("No active workbench window found");
+                  return;
+              }
               IDFUtil.closeWelcomePage(activeww);
               try
               {
                   IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimJson), ESPIDFManagerEditor.EDITOR_ID);
               }
               catch (PartInitException e)
               {
                   Logger.log(e);
+                  MessageBox errorBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+                  errorBox.setText("Error");
+                  errorBox.setMessage("Failed to open ESP-IDF Manager: " + e.getMessage());
+                  errorBox.open();
               }
           }
+          if (shell.isDisposed()) {
+              shell.dispose();
+          }
       });

Committable suggestion skipped: line range outside the PR's diff.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java (1)

Integration tests needed for critical EIM functionality

The verification confirms that EIM integration touches several critical paths (tools initialization, project setup, installation) but lacks test coverage. The original architectural advice remains valid and important:

  1. Add integration tests covering the complete EIM installation workflow
  2. Include test cases for EIM configuration parsing
  3. Add tests for EIM-related project setup scenarios
🔗 Analysis chain

Line range hint 40-109: Consider adding integration tests for the EIM workflow.

Since this is part of the EIM integration and modifies the installation tools workflow:

  1. Consider adding integration tests that verify the complete EIM installation flow
  2. Document the new EIM-related configuration options in the plugin's documentation

Let's check for existing test coverage:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Look for test files related to EIM integration
fd -e java -e xml test.*Eim

Length of output: 31


Script:

#!/bin/bash
# Look for test files related to installation tools and EIM
rg -l "class.*Test" | rg -i "install|tools"
rg -l "EimConstants" --type java

Length of output: 599

♻️ Duplicate comments (7)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (3)

66-66: ⚠️ Potential issue

Convert static eimJson to instance variable to prevent threading issues.

The static eimJson variable can lead to race conditions if multiple plugin windows are opened simultaneously.

Convert to instance variable:

-private static EimJson eimJson;
+private EimJson eimJson;

132-139: ⚠️ Potential issue

Improve error handling for configuration parsing.

The catch block only logs the error without proper user feedback or recovery mechanism.

Add error handling and user feedback:

 try {
   eimJson = eimIdfConfiguratinParser.getEimJson(true);
 } catch (IOException e) {
   Logger.log(e);
+  MessageDialog.openError(
+    Display.getDefault().getActiveShell(),
+    "Configuration Error",
+    "Failed to load IDF configuration: " + e.getMessage());
+  return;
 }

405-423: ⚠️ Potential issue

Implement remove functionality for IDF installations.

The remove button implementation is missing, which prevents users from removing unwanted IDF installations.

Let's verify if we can safely implement the remove functionality:

#!/bin/bash
# Search for any existing remove/delete implementation
rg "remove.*idf|delete.*idf" -g "*.java"

# Search for any UI messages related to remove/delete
rg "EspIdfManagerDeleteBtn|EspIdfManagerRemoveBtn" -g "*.java"
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (1)

158-171: 🛠️ Refactor suggestion

Add method documentation and verify URL safety

The method needs documentation and URL validation.

+    /**
+     * Displays a notification dialog prompting the user to install EIM when the
+     * configuration is missing. If the user agrees, opens the EIM download page
+     * in the default browser.
+     */
     private void userNotficationToInstallEim()

     // Verify URL safety
+    if (!EimConstants.EIM_URL.startsWith("https://")) {
+        Logger.log("Unsafe URL protocol detected: " + EimConstants.EIM_URL);
+        return;
+    }

Shell management and disposal issues.

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (2)

253-253: ⚠️ Potential issue

Fix syntax error due to extraneous parenthesis

At line 253, there is an extra closing parenthesis causing a syntax error in the log method call.

Apply this diff to fix the syntax error:

- log("Executing " + arguments.toString(), IStatus.OK); //$NON-NLS-1$)
+ log("Executing " + arguments.toString(), IStatus.OK); //$NON-NLS-1$

171-226: ⚠️ Potential issue

Handle permissions when copying OpenOCD rules on Linux

The method copyOpenOcdRules() attempts to copy OpenOCD rules to /etc/udev/rules.d/60-openocd.rules, which requires root permissions. The current implementation does not handle permission issues that may arise if the application is not running with sufficient privileges. This could lead to an IOException.

Consider adding proper error handling for permission issues and provide guidance to the user on how to proceed if the copy fails due to insufficient permissions. For example, prompt the user to run the application with elevated privileges or provide instructions on how to copy the rules manually.

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (1)

39-41: ⚠️ Potential issue

Prevent potential NullPointerException due to uninitialized setupToolsInIde

In the done method, setupToolsInIde may be null if the default constructor SetupToolsJobListener() is used without initializing setupToolsInIde. This could result in a NullPointerException when setupToolsInIde.rollback() is called.

To resolve this issue, consider adding a null check before calling setupToolsInIde.rollback(), or remove the default constructor if it's unnecessary.

Apply this diff to add a null check:

if (event.getResult().getSeverity() != IStatus.OK)
{
+    if (setupToolsInIde != null)
+    {
        // Rollback all the changes
        setupToolsInIde.rollback();
+    }
+    else
+    {
+        Logger.log("setupToolsInIde is null; rollback cannot be performed.");
+    }
}

Alternatively, if the default constructor is not needed, you can remove it:

- public SetupToolsJobListener()
- {
- }

Also applies to: 55-59

🧹 Nitpick comments (6)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/NewProjectHandlerUtil.java (1)

Line range hint 28-54: Consider enhancing error handling and user experience.

The current implementation could benefit from the following improvements:

  1. Consider combining the validation checks to provide a comprehensive list of issues rather than stopping at the first failure
  2. Add logging for debugging purposes
  3. Consider using a builder pattern for validation checks

Example refactor:

 public static boolean installToolsCheck() {
+    Logger.debug("Checking IDF project prerequisites...");
+    List<String> issues = new ArrayList<>();
+
     String idfPath = IDFUtil.getIDFPath();
     if (StringUtil.isEmpty(idfPath)) {
-        showMessage(Messages.NewProjectHandler_CouldntFindIdfPath);
-        return false;
+        issues.add(Messages.NewProjectHandler_CouldntFindIdfPath);
     }
     
     IEnvironmentVariable pathEnv = new IDFEnvironmentVariables().getEnv(IDFEnvironmentVariables.PATH);
     String path = Optional.ofNullable(pathEnv).map(o -> o.getValue()).orElse(null);
     if (StringUtil.isEmpty(path)) {
-        showMessage(Messages.NewProjectHandler_CouldntFindPath);
-        return false;
+        issues.add(Messages.NewProjectHandler_CouldntFindPath);
     }
     
     boolean isToolsInstalled = scopedPreferenceStore.getBoolean(EimConstants.INSTALL_TOOLS_FLAG, false);
     if (!isToolsInstalled) {
-        showMessage(Messages.NewProjectHandler_CouldntFindTools);
-        return false;
+        issues.add(Messages.NewProjectHandler_CouldntFindTools);
     }
-    return true;
+    
+    if (!issues.isEmpty()) {
+        Logger.debug("Prerequisites check failed: " + String.join(", ", issues));
+        showMessage(String.join("\n", issues));
+        return false;
+    }
+    
+    Logger.debug("All prerequisites satisfied");
+    return true;
 }
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)

37-37: Fix typo in class name EimIdfConfiguratinParser.

The class name contains a typo: "Configuratin" should be "Configuration".

This requires updating the class name in the core package as well.

Also applies to: 67-67, 76-76

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (2)

101-104: Move parser initialization to constructor

Initialize eimIdfConfiguratinParser in the constructor to ensure it's always available and to improve code organization.

 public class InitializeToolsStartup implements IStartup
 {
+    public InitializeToolsStartup() {
+        eimIdfConfiguratinParser = new EimIdfConfiguratinParser();
+    }

233-236: Add method documentation

Document the purpose of this check and explain the significance of the default value.

+    /**
+     * Checks if ESP-IDF tools are installed and configured for the current workspace.
+     * This setting is stored in the workspace preferences and is set to true after
+     * successful tool installation through EIM.
+     *
+     * @return true if ESP-IDF is set up, false otherwise (default)
+     */
     private boolean isEspIdfSet()
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (2)

148-149: Correct the typo in "python" in log messages

There is a typo in the word "python" in the task name and log message.

Apply this diff to correct the spelling:

- monitor.setTaskName("Installing pyhton dependency web-socket"); //$NON-NLS-1$
- log("Installing pyhton dependency web-socket", IStatus.INFO); //$NON-NLS-1$
+ monitor.setTaskName("Installing python dependency websocket-client"); //$NON-NLS-1$
+ log("Installing python dependency websocket-client", IStatus.INFO); //$NON-NLS-1$

356-373: Refactor the process waiting mechanism

The current implementation uses a loop with sleep to wait for the process to finish, which may not be reliable if the process takes longer than expected. If the process exceeds the wait time, it may incorrectly assume the process is stuck.

Consider using process.waitFor(timeout, TimeUnit.SECONDS) to wait for the process completion with a specified timeout. This method is more reliable and makes the code cleaner.

Apply this diff to refactor the waiting mechanism:

- int waitCount = 10;
...
- while (process.isAlive() && waitCount > 0)
- {
-     try
-     {
-         Thread.sleep(300);
-     }
-     catch (InterruptedException e)
-     {
-         Logger.log(e);
-     }
-     waitCount--;
- }
- 
- if (waitCount == 0)
+ boolean finished = process.waitFor(5, TimeUnit.SECONDS);
+ if (!finished)
{
    log("Process possibly stuck", IStatus.ERROR); //$NON-NLS-1$
    return Status.CANCEL_STATUS;
}

Remember to import java.util.concurrent.TimeUnit at the beginning of the file:

+ import java.util.concurrent.TimeUnit;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c9bf5c and 127118d.

📒 Files selected for processing (6)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (4 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/NewProjectHandlerUtil.java (2 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (4 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (13 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_macos
🔇 Additional comments (6)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/NewProjectHandlerUtil.java (2)

19-19: LGTM! Good practice to centralize constants.

The addition of EimConstants import aligns with the goal of centralizing configuration constants.


38-38: Verify all references to the installation flag are updated.

This change from InstallToolsHandler.INSTALL_TOOLS_FLAG to EimConstants.INSTALL_TOOLS_FLAG is a breaking change.

Let's verify all references are updated:

Additionally, please ensure this change is documented in:

  1. Migration guide
  2. Release notes
  3. API documentation
✅ Verification successful

Breaking change migration is complete

All references to the installation flag have been updated to use EimConstants.INSTALL_TOOLS_FLAG consistently, with no remaining references to the old constant.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to the old constant
rg "InstallToolsHandler\.INSTALL_TOOLS_FLAG"

# Search for usage of the new constant to ensure consistency
rg "EimConstants\.INSTALL_TOOLS_FLAG"

Length of output: 928

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java (1)

40-40: LGTM! Import follows proper layering.

The addition of EimConstants import from the core package maintains proper architectural layering.

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (3)

37-38: Fix typo in class and variable names: 'Configuratin' → 'Configuration'

The misspelling exists in both the import and field declaration.

Also applies to: 62-63


142-156: Add method documentation and improve path handling

The method needs documentation to explain its purpose and behavior.

+    /**
+     * Checks if the EIM JSON configuration file exists at the OS-specific location.
+     * For Windows, checks at {@link EimConstants#EIM_WIN_PATH}.
+     * For POSIX systems, checks at {@link EimConstants#EIM_POSIX_PATH}.
+     *
+     * @return true if the configuration file exists, false otherwise
+     */
     private boolean isEimIdfJsonPresent()

Path handling issue with '~' in POSIX paths.


106-113: 🛠️ Refactor suggestion

Enhance error handling for EIM JSON parsing

The current implementation only logs the IOException. Consider informing the user about the configuration parsing failure.

     try
     {
         eimJson = eimIdfConfiguratinParser.getEimJson(true);
     }
     catch (IOException e)
     {
         Logger.log(e);
+        Display.getDefault().asyncExec(() -> {
+            Shell shell = Display.getDefault().getActiveShell();
+            if (shell == null) {
+                shell = new Shell(Display.getDefault());
+            }
+            MessageBox errorBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+            errorBox.setText("Configuration Error");
+            errorBox.setMessage("Failed to read EIM configuration: " + e.getMessage());
+            errorBox.open();
+        });
     }

Likely invalid or redundant comment.

Comment on lines +351 to +355
private String getIdfVersion(IdfInstalled idfInstalled)
{
String version = ToolsUtility.getIdfVersion(idfInstalled, eimJson.getGitPath());
return version;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling to getIdfVersion method.

The method doesn't handle potential null values or exceptions that might occur when accessing eimJson.getGitPath().

Add proper error handling:

 private String getIdfVersion(IdfInstalled idfInstalled) {
+  if (idfInstalled == null || eimJson == null) {
+    return "Unknown";
+  }
+  try {
     String version = ToolsUtility.getIdfVersion(idfInstalled, eimJson.getGitPath());
-    return version;
+    return version != null ? version : "Unknown";
+  } catch (Exception e) {
+    Logger.log(e);
+    return "Error";
+  }
 }
📝 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 String getIdfVersion(IdfInstalled idfInstalled)
{
String version = ToolsUtility.getIdfVersion(idfInstalled, eimJson.getGitPath());
return version;
}
private String getIdfVersion(IdfInstalled idfInstalled)
{
if (idfInstalled == null || eimJson == null) {
return "Unknown";
}
try {
String version = ToolsUtility.getIdfVersion(idfInstalled, eimJson.getGitPath());
return version != null ? version : "Unknown";
} catch (Exception e) {
Logger.log(e);
return "Error";
}
}

@@ -108,7 +106,7 @@ protected IStatus run(IProgressMonitor monitor)
}
};
Preferences scopedPreferenceStore = InstanceScope.INSTANCE.getNode(UIPlugin.PLUGIN_ID);
scopedPreferenceStore.putBoolean(INSTALL_TOOLS_FLAG, true);
scopedPreferenceStore.putBoolean(EimConstants.INSTALL_TOOLS_FLAG, true);
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Migration to EimConstants.INSTALL_TOOLS_FLAG is incomplete

The constant is currently defined in multiple locations:

  • ToolsActivationJob.java still has its own declaration and uses it directly
  • Both EimConstants.java and IToolsInstallationWizardConstants.java define the same constant

The constant should be defined only in EimConstants.java and referenced from there in all other files.

🔗 Analysis chain

Verify all references to INSTALL_TOOLS_FLAG are updated.

The migration to EimConstants.INSTALL_TOOLS_FLAG looks good, but since this is part of the EIM integration:

Let's verify all references are consistently updated:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining direct references to INSTALL_TOOLS_FLAG
# that haven't been migrated to use EimConstants

# Look for string literals of INSTALL_TOOLS_FLAG
rg -l "INSTALL_TOOLS_FLAG" --type java

# Look for constant declarations of INSTALL_TOOLS_FLAG
ast-grep --pattern 'static final String INSTALL_TOOLS_FLAG = $_'

Length of output: 719


Script:

#!/bin/bash
# Check the constant definition and usages

# Show EimConstants definition
echo "=== EimConstants.java ==="
rg -A 1 "INSTALL_TOOLS_FLAG" bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java

# Show any potential conflicting definitions
echo -e "\n=== IToolsInstallationWizardConstants.java ==="
rg -A 1 "INSTALL_TOOLS_FLAG" bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.java

# Show usage in other files
echo -e "\n=== Usage in other files ==="
for f in $(rg -l "INSTALL_TOOLS_FLAG" --type java); do
  if [[ "$f" != *"EimConstants.java"* && "$f" != *"IToolsInstallationWizardConstants.java"* ]]; then
    echo -e "\n--- $f ---"
    rg -A 1 "INSTALL_TOOLS_FLAG" "$f"
  fi
done

Length of output: 5227

Comment on lines 121 to 122
messageBox.setText("No Active ESP-IDF in workspace");
messageBox.setMessage("No active ESP-IDF found in current workspace. Do you want to select the ESP-IDF for current workspace?");
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Externalize dialog messages

Move the hardcoded strings to the Messages class for better maintainability and localization support.

-messageBox.setText("No Active ESP-IDF in workspace");
-messageBox.setMessage("No active ESP-IDF found in current workspace. Do you want to select the ESP-IDF for current workspace?");
+messageBox.setText(Messages.NoActiveEspIdfTitle);
+messageBox.setMessage(Messages.NoActiveEspIdfMessage);

Committable suggestion skipped: line range outside the PR's diff.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (4)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties (1)

5-5: Maintain consistent naming convention across UI elements.

The new column name EspIdfManagerNameCol follows a different pattern compared to other column names. While others use ManagerLocationCol, ManagerVersionCol, this uses ManagerNameCol. Consider aligning with existing pattern.

-EspIdfManagerNameCol=Name
+EspIdfManagerNameCol=ESP-IDF Name
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (3)

26-26: Follow utility class best practices.

As this is a utility class containing only static methods:

  1. Mark the class as final to prevent inheritance
  2. Add a private constructor to prevent instantiation

Apply this diff:

-public class ToolsUtility
+public final class ToolsUtility
 {
+    private ToolsUtility() {
+        throw new AssertionError("Utility class - do not instantiate");
+    }

27-28: Remove unused parameter.

The gitPath parameter is not used in the method implementation.

Remove the unused parameter:

-public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath)
+public static String getIdfVersion(IdfInstalled idfInstalled)

68-86: Enhance OS handling and use constants.

The method could be improved by:

  1. Adding explicit handling for unsupported OS
  2. Using constants for command strings
  3. Validating the input path
+private static final String POWERSHELL_EXE = "powershell.exe";
+private static final String EXECUTION_POLICY = "-ExecutionPolicy";
+private static final String BYPASS = "Bypass";
+private static final String FILE_PARAM = "-File";
+private static final String ECHO_PARAM = "-e";
+private static final String SH = "sh";

 public static List<String> getExportScriptCommand(String activationScriptPath) {
+    if (activationScriptPath == null || activationScriptPath.trim().isEmpty()) {
+        throw new IllegalArgumentException("Activation script path cannot be null or empty");
+    }

     List<String> command = new ArrayList<>();
     if (Platform.getOS().equals(Platform.OS_WIN32)) {
-        command.add("powershell.exe");
-        command.add("-ExecutionPolicy");
-        command.add("Bypass");
-        command.add("-File");
+        command.add(POWERSHELL_EXE);
+        command.add(EXECUTION_POLICY);
+        command.add(BYPASS);
+        command.add(FILE_PARAM);
         command.add(activationScriptPath);
-        command.add("-e");
+        command.add(ECHO_PARAM);
     } else {
-        command.add("sh");
+        command.add(SH);
         command.add(activationScriptPath);
-        command.add("-e");
+        command.add(ECHO_PARAM);
     }
     return command;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 127118d and d06cd33.

📒 Files selected for processing (31)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolSetConfigurationManager.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsPlatformMapping.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (2 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IDFToolSet.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java (0 hunks)
  • bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java (0 hunks)
  • bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties (0 hunks)
  • bundles/com.espressif.idf.ui/plugin.xml (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/UpdateEspIdfHandler.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/GitRepositoryBuilder.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFDownloadPage.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFNewToolsWizard.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/Messages.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages.properties (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages_zh.properties (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/GitWizardRepProgressMonitor.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/LogMessagesThread.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationJob.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsJob.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/ExportIDFTools.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java (0 hunks)
💤 Files with no reviewable changes (28)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages.properties
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/GitRepositoryBuilder.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/Messages.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationJob.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFNewToolsWizard.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/LogMessagesThread.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsPlatformMapping.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IDFToolSet.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFDownloadPage.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolSetConfigurationManager.java
  • bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsJob.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java
  • bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/ExportIDFTools.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/GitWizardRepProgressMonitor.java
  • bundles/com.espressif.idf.ui/plugin.xml
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages_zh.properties
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/UpdateEspIdfHandler.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java
🔇 Additional comments (2)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (2)

50-54: Prevent potential ArrayIndexOutOfBoundsException.

When splitting the line to extract espIdfVersion, ensure that the line contains an = character.


89-93: Prevent potential NullPointerException in isIdfInstalledActive method.

If idfInstalled.getId() could be null, calling .equals() on it may lead to a NullPointerException.

IDFToolsHandler_ToolsManagerConsole=Espressif IDF Tools Console
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Missing Chinese translation for "IDFToolsHandler_ToolsManagerConsole"

The string "IDFToolsHandler_ToolsManagerConsole" is missing in the Chinese localization file messages_zh.properties. This needs to be added to maintain consistent user experience for Chinese users.

  • Add the translation for "IDFToolsHandler_ToolsManagerConsole" in bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages_zh.properties
🔗 Analysis chain

Verify translations for new UI strings.

As this is a breaking change that adds new UI strings, ensure these changes are propagated to all localized message files (if any exist) to maintain consistent user experience across different languages.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other localized versions of messages.properties
echo "Searching for localized message files..."
fd "messages_.*\.properties" "bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/"

Length of output: 265


Script:

#!/bin/bash
# Check if the new string exists in the Chinese translation file
echo "Content of Chinese translation file:"
cat "bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages_zh.properties"

Length of output: 6146

}

tararchiveinputstream.close();
process.waitFor();
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add timeout to process execution.

Add a timeout to process.waitFor() to prevent hanging in case the script execution takes too long.

-process.waitFor();
+if (!process.waitFor(30, TimeUnit.SECONDS)) {
+    process.destroyForcibly();
+    Logger.log("Process timed out while executing: " + activationScript);
+    return null;
+}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +29 to +30
String activationScript = idfInstalled.getActivationScript();
String espIdfVersion = null;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Validate input parameters.

Add validation for the activationScript to prevent potential NPEs or invalid paths.

Add parameter validation:

 String activationScript = idfInstalled.getActivationScript();
+if (activationScript == null || activationScript.trim().isEmpty()) {
+    Logger.log("Activation script path is null or empty");
+    return null;
+}
+File scriptFile = new File(activationScript);
+if (!scriptFile.exists() || !scriptFile.canExecute()) {
+    Logger.log("Activation script does not exist or is not executable: " + activationScript);
+    return null;
+}

Committable suggestion skipped: line range outside the PR's diff.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (3)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (3)

37-38: ⚠️ Potential issue

Fix typo in class name 'EimIdfConfiguratinParser'.

The class name contains a typo: 'Configuratin' should be 'Configuration'.


141-155: ⚠️ Potential issue

Fix home directory path resolution.

The POSIX path using '~' won't be expanded by Java's File class.


157-170: ⚠️ Potential issue

Improve shell management and URL validation.

The shell creation and URL handling need improvements:

  1. Shell is created but never disposed
  2. Direct URL launch without validation
🧹 Nitpick comments (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (1)

116-116: Remove TODO comment and implement proper documentation.

The TODO comment should be replaced with proper documentation explaining the workflow.

Apply this diff to improve documentation:

-            // TODO: Installer config flag is not set so we need to start IDF Manager and let user select the IDF for workspace
+            // When no ESP-IDF is configured for the workspace, prompt the user to select one using the IDF Manager.
+            // This ensures proper tool configuration before development can begin.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d06cd33 and 809200e.

📒 Files selected for processing (3)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties
🔇 Additional comments (5)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java (2)

37-38: LGTM! Message constants follow Eclipse NLS patterns.

The new message constants for EIM installation notifications are properly defined following Eclipse's internationalization patterns.


42-43: LGTM! Message constants follow Eclipse NLS patterns.

The new message constants for ESP-IDF workspace notifications are properly defined following Eclipse's internationalization patterns.

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (3)

232-235: LGTM! Preference access is properly implemented.

The method correctly checks the installation flag from Eclipse preferences.


93-113: ⚠️ Potential issue

Improve error handling and null checks.

The EIM JSON initialization block has several issues:

  1. No error message is shown to the user when IOException occurs
  2. eimJson might be null when used later

Apply this diff to improve error handling:

 try
 {
     eimJson = eimIdfConfiguratinParser.getEimJson(true);
 }
 catch (IOException e)
 {
     Logger.log(e);
+    Display.getDefault().asyncExec(() -> {
+        Shell shell = Display.getDefault().getActiveShell();
+        MessageBox errorBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+        errorBox.setText("Error");
+        errorBox.setMessage("Failed to read EIM configuration: " + e.getMessage());
+        errorBox.open();
+    });
 }

Likely invalid or redundant comment.


117-138: 🛠️ Refactor suggestion

Improve UI responsiveness and error handling.

The synchronous UI update can cause freezes, and error cases aren't properly handled.

Apply this diff to improve the implementation:

-            Display.getDefault().syncExec(()-> {
+            Display.getDefault().asyncExec(()-> {
                 Shell shell = Display.getDefault().getActiveShell();
+                if (shell == null) {
+                    shell = new Shell(Display.getDefault());
+                }
                 MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING| SWT.YES | SWT.NO);
                 messageBox.setText(Messages.NoActiveEspIdfInWorkspaceMsgTitle);
                 messageBox.setMessage(Messages.NoActiveEspIdfInWorkspaceMsg);
                 
                 int response = messageBox.open();
                 if (response == SWT.YES)
                 {
                     IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow();
+                    if (activeww == null) {
+                        Logger.log("No active workbench window found");
+                        return;
+                    }
                     IDFUtil.closeWelcomePage(activeww);
                     try
                     {
+                        if (eimJson == null) {
+                            MessageBox errorBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+                            errorBox.setText("Error");
+                            errorBox.setMessage("EIM configuration is not available");
+                            errorBox.open();
+                            return;
+                        }
                         IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimJson), ESPIDFManagerEditor.EDITOR_ID);
                     }
                     catch (PartInitException e)
                     {
                         Logger.log(e);
+                        MessageBox errorBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+                        errorBox.setText("Error");
+                        errorBox.setMessage("Failed to open ESP-IDF Manager: " + e.getMessage());
+                        errorBox.open();
                     }
                 }
+                if (!shell.isDisposed()) {
+                    shell.dispose();
+                }
             });

Likely invalid or redundant comment.

@alirana01 alirana01 changed the title [WIP] IEP-1334: EIM Integration IEP-1334: EIM Integration Jan 27, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🔭 Outside diff range comments (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)

Update Chinese translation file to match new UI messages

The verification shows that the breaking changes in UI messages are well-contained, with only one required action:

  • The Chinese translation file (bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages_zh.properties) needs to be updated to remove old messages and add translations for the new UI messages.
🔗 Analysis chain

Line range hint 1-37: Document the breaking changes in UI messages.

This file shows significant changes to UI messages as part of the EIM integration. Since this is marked as a breaking change in the PR objectives, please ensure:

  1. The documentation is updated to reflect the new UI messages and removed ones
  2. Any dependent modules using the removed message constants are updated
  3. Translation files for all supported languages are synchronized

Let's verify the impact:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential usage of removed message constants

# Search for usage of removed constants in the codebase
echo "Searching for usage of removed constants..."
rg "EspIdfManagerStateCol|EspIdfManagerDeleteBtnToolTip|EspIdfManagerAddToolsBtn|EspIdfManagerRemoveAllBtn|EspIdfManagerDeleteBtn|IDFDownloadHandler_ESPIDFConfiguration|IDFDownloadHandler_DownloadPage_Title|IDFDownloadHandler_DownloadPageMsg"

Length of output: 901


Script:

#!/bin/bash
# Check for documentation and related files
echo "=== Checking documentation files ==="
fd -e md -e txt -e html . bundles/com.espressif.idf.ui/

echo -e "\n=== Checking all message properties files ==="
fd messages.properties bundles/com.espressif.idf.ui/

echo -e "\n=== Checking Java files that might use these messages ==="
fd -e java . bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/

echo -e "\n=== Checking for old vs new message keys in properties files ==="
for f in $(fd messages.properties bundles/com.espressif.idf.ui/); do
  echo "=== File: $f ==="
  cat "$f"
done

Length of output: 30578

♻️ Duplicate comments (4)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (2)

58-58: 🛠️ Refactor suggestion

Add timeout to process execution.

The current implementation waits indefinitely for the process to complete.


89-93: ⚠️ Potential issue

Prevent potential NPE and add input validation.

The current implementation might throw NPE when comparing IDs.

Apply this diff:

 public static boolean isIdfInstalledActive(IdfInstalled idfInstalled)
 {
+    if (idfInstalled == null) {
+        return false;
+    }
     IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables();
     String espIdfIdEim = idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.ESP_IDF_EIM_ID);
-    return idfInstalled.getId().equals(espIdfIdEim);
+    return Objects.equals(idfInstalled.getId(), espIdfIdEim);
 }
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java (1)

11-11: ⚠️ Potential issue

Correct the typo in EimIdfConfiguratinParser.

The class name contains a typographical error: EimIdfConfiguratinParser should be EimIdfConfigurationParser.

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1)

253-253: ⚠️ Potential issue

Fix syntax error in log statement.

Remove the extraneous closing parenthesis.

-    log("Executing " + arguments.toString(), IStatus.OK); //$NON-NLS-1$)
+    log("Executing " + arguments.toString(), IStatus.OK); //$NON-NLS-1$
🧹 Nitpick comments (5)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (1)

68-86: Add parameter validation and improve command construction.

The method should validate the input parameter and handle path quoting for spaces.

Apply this diff:

 public static List<String> getExportScriptCommand(String activationScriptPath)
 {
+    if (activationScriptPath == null || activationScriptPath.trim().isEmpty()) {
+        throw new IllegalArgumentException("Activation script path cannot be null or empty");
+    }
+
     List<String> command = new ArrayList<>();
     if (Platform.getOS().equals(Platform.OS_WIN32))
     {
         command.add("powershell.exe"); //$NON-NLS-1$
         command.add("-ExecutionPolicy"); //$NON-NLS-1$
         command.add("Bypass"); //$NON-NLS-1$
         command.add("-File"); //$NON-NLS-1$
-        command.add(activationScriptPath);
+        command.add("\"" + activationScriptPath.replace("\"", "\"\"") + "\"");
         command.add("-e"); //$NON-NLS-1$
     }
     else 
     {
         command.add("sh"); //$NON-NLS-1$
-        command.add(activationScriptPath);
+        command.add("\"" + activationScriptPath.replace("\"", "\\\"") + "\"");
         command.add("-e"); //$NON-NLS-1$
     }
     return command;
 }
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)

377-381: Refactor duplicated job creation logic.

The job creation logic is duplicated between the activate and reload buttons. Consider extracting it to a helper method.

+private void scheduleSetupJob(IdfInstalled idfInstalled) {
+    SetupToolsInIde setupToolsInIde = new SetupToolsInIde(
+        idfInstalled, 
+        eimJson, 
+        getConsoleStream(true), 
+        getConsoleStream(false)
+    );
+    SetupToolsJobListener toolsActivationJobListener = new SetupToolsJobListener(
+        this, 
+        setupToolsInIde
+    );
+    setupToolsInIde.addJobChangeListener(toolsActivationJobListener);
+    setupToolsInIde.schedule();
+}

// Then use it in both places:
-SetupToolsInIde setupToolsInIde = new SetupToolsInIde(idfInstalled, eimJson, getConsoleStream(true), getConsoleStream(false));
-SetupToolsJobListener toolsActivationJobListener = new SetupToolsJobListener(
-    ESPIDFMainTablePage.this, setupToolsInIde);
-setupToolsInIde.addJobChangeListener(toolsActivationJobListener);
-setupToolsInIde.schedule();
+scheduleSetupJob(idfInstalled);

Also applies to: 419-423

.github/workflows/ci.yml (1)

13-28: Optimize workflow configuration.

Consider the following improvements to enhance workflow efficiency and maintainability:

  1. Use job dependencies to ensure proper execution order
  2. Implement caching for Python and Maven dependencies
  3. Share common configuration using composite actions

Example implementation:

 jobs:
   build_linux:
     runs-on: [self-hosted, eclipse, BrnoUBU0004]
+    needs: [] # Add dependencies if needed
 
     steps:
     - uses: actions/checkout@v2
 
     - name: Set up Python
       uses: actions/setup-python@v2
       with:
         python-version: '3.10'
+      # Add caching
+      - uses: actions/cache@v3
+        with:
+          path: ~/.cache/pip
+          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+          restore-keys: |
+            ${{ runner.os }}-pip-
 
     - name: Install ESP-IDF via eim
-      uses: Hahihula/esp-idf-install-action@v1
+      # Use composite action for shared configuration
+      uses: ./.github/actions/install-esp-idf
       with:
         esp_idf_version: 'v5.3'
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1)

459-477: Consider using a builder pattern for environment setup.

The setupEnvVarsInEclipse() method handles multiple environment variable operations. Consider refactoring to use a builder pattern for better maintainability and testability.

Example refactor:

public class EnvironmentBuilder {
    private final Map<String, String> envVars = new HashMap<>();
    
    public EnvironmentBuilder withPath(String path) {
        envVars.put(IDFEnvironmentVariables.PATH, path);
        return this;
    }
    
    public EnvironmentBuilder withComponentManager() {
        envVars.put(IDFEnvironmentVariables.IDF_COMPONENT_MANAGER, "1");
        return this;
    }
    
    public void apply(IDFEnvironmentVariables env) {
        envVars.forEach(env::addEnvVariable);
    }
}
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (1)

116-116: Remove TODO comment and implement the feature.

The TODO comment indicates missing functionality for IDF Manager initialization.

Would you like me to help implement this feature or create an issue to track this task?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 809200e and b271300.

⛔ Files ignored due to path filters (1)
  • bundles/com.espressif.idf.ui/icons/tools/delete.png is excluded by !**/*.png
📒 Files selected for processing (51)
  • .github/workflows/ci.yml (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/Messages.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolSetConfigurationManager.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsPlatformMapping.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/messages.properties (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (2 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IDFToolSet.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (1 hunks)
  • bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java (0 hunks)
  • bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties (0 hunks)
  • bundles/com.espressif.idf.ui/plugin.xml (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (4 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/NewProjectHandlerUtil.java (2 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/UpdateEspIdfHandler.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/GitRepositoryBuilder.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFDownloadPage.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFNewToolsWizard.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/Messages.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages.properties (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages_zh.properties (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/GitWizardRepProgressMonitor.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/LogMessagesThread.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java (2 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (4 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationJob.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsJob.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (13 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/ExportIDFTools.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java (0 hunks)
  • tests/com.espressif.idf.ui.test/configs/default-test-linux.properties (1 hunks)
💤 Files with no reviewable changes (28)
  • bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages.properties
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/UpdateEspIdfHandler.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationJob.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/LogMessagesThread.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/Messages.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.java
  • bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolSetConfigurationManager.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IDFToolSet.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsJob.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/GitRepositoryBuilder.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java
  • bundles/com.espressif.idf.ui/plugin.xml
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/ExportIDFTools.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/GitWizardRepProgressMonitor.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFNewToolsWizard.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFDownloadPage.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsPlatformMapping.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages_zh.properties
🚧 Files skipped from review as they are similar to previous changes (14)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/NewProjectHandlerUtil.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/messages.properties
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/Messages.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_macos
🔇 Additional comments (20)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (3)

7-17: LGTM! Clean imports and well-documented class structure.

The imports are appropriate for the new functionality, and the class documentation is complete with copyright and author information.


50-54: ⚠️ Potential issue

Add null check and proper error handling for version parsing.

The current implementation might throw ArrayIndexOutOfBoundsException if the line doesn't contain '='.

Apply this diff:

 if (line.startsWith("ESP_IDF_VERSION=")) //$NON-NLS-1$
 {
-    espIdfVersion = line.split("=")[1]; //$NON-NLS-1$
-    break;
+    String[] parts = line.split("=", 2); //$NON-NLS-1$
+    if (parts.length == 2) {
+        espIdfVersion = parts[1].trim();
+        break;
+    }
 }

Likely invalid or redundant comment.


27-30: 🛠️ Refactor suggestion

Remove unused parameter and add input validation.

The gitPath parameter is not used in the method. Additionally, the activation script path should be validated.

Apply this diff:

-public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath)
+public static String getIdfVersion(IdfInstalled idfInstalled)
 {
     String activationScript = idfInstalled.getActivationScript();
+    if (activationScript == null || activationScript.trim().isEmpty()) {
+        Logger.log("Activation script path is null or empty");
+        return null;
+    }
+    File scriptFile = new File(activationScript);
+    if (!scriptFile.exists() || !scriptFile.canExecute()) {
+        Logger.log("Activation script does not exist or is not executable: " + activationScript);
+        return null;
+    }

Likely invalid or redundant comment.

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java (1)

39-41: Verify the impact of this breaking change.

This change represents a significant architectural shift from file-based to JSON-based configuration. Ensure that:

  1. All dependent components are updated to handle the new configuration format
  2. Migration path exists for existing configurations
  3. Documentation is updated to reflect these changes

Run the following script to identify potential impacts:

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (4)

66-66: ⚠️ Potential issue

Consider making eimJson an instance variable to prevent thread safety issues.

The static eimJson field could lead to race conditions if multiple instances of the UI are opened simultaneously. Consider making it an instance variable instead.

-private static EimJson eimJson;
+private EimJson eimJson;

Likely invalid or redundant comment.


351-355: ⚠️ Potential issue

Add null checks in getIdfVersion method.

The method could throw NPE if either idfInstalled or eimJson is null.

 private String getIdfVersion(IdfInstalled idfInstalled) {
+    if (idfInstalled == null || eimJson == null) {
+        return "Unknown";
+    }
+    try {
         String version = ToolsUtility.getIdfVersion(idfInstalled, eimJson.getGitPath());
-        return version;
+        return version != null ? version : "Unknown";
+    } catch (Exception e) {
+        Logger.log(e);
+        return "Error";
+    }
 }

Likely invalid or redundant comment.


79-87: 🛠️ Refactor suggestion

Refactor singleton pattern to avoid static field modification.

The current implementation modifies a static field in getInstance, which could lead to race conditions. Consider passing the EimJson instance to the constructor instead.

-public static ESPIDFMainTablePage getInstance(EimJson eimJson)
+public static ESPIDFMainTablePage getInstance()
 {
     if (espidfMainTablePage == null)
     {
-        espidfMainTablePage = new ESPIDFMainTablePage();
+        espidfMainTablePage = new ESPIDFMainTablePage(eimJson);
     }
-    ESPIDFMainTablePage.eimJson = eimJson;
     return espidfMainTablePage;
 }

Likely invalid or redundant comment.


132-141: ⚠️ Potential issue

Improve error handling in refreshEditorUI.

The current implementation has two issues:

  1. The catch block only logs the error without proper user feedback
  2. Potential NPE in line 141 if eimJson is null after exception
 try {
     eimJson = eimIdfConfiguratinParser.getEimJson(true);
 } catch (IOException e) {
     Logger.log(e);
+    Display.getDefault().asyncExec(() -> {
+        MessageDialog.openError(
+            Display.getDefault().getActiveShell(),
+            "Configuration Error",
+            "Failed to load IDF configuration: " + e.getMessage());
+    });
+    return;
 }

+if (eimJson == null) {
+    return;
+}
 idfInstalledList = eimJson.getIdfInstalled();

Likely invalid or redundant comment.

.github/workflows/ci.yml (2)

23-23: LGTM: Python version update.

The Python version is appropriately set to 3.10, which is compatible with ESP-IDF v5.3.


13-13: Verify self-hosted runner configuration.

The job has been renamed to build_linux and now runs on a specific self-hosted runner BrnoUBU0004. Please ensure:

  1. The runner is properly maintained and available
  2. The required labels self-hosted, eclipse, and BrnoUBU0004 are configured
  3. The runner has sufficient resources for the build process

Also applies to: 15-15

✅ Verification successful

Self-hosted runner configuration follows established patterns

The runner configuration is consistent with the repository's CI infrastructure:

  • Linux builds use dedicated self-hosted runners (BrnoUBU0004)
  • Similar pattern exists for Windows builds (BrnoWIN0007)
  • Runner labels follow the standard format used across workflows
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify runner configuration and availability

# Check if the runner is online and properly configured
gh api -X GET repos/:owner/:repo/actions/runners \
  --jq '.runners[] | select(.name=="BrnoUBU0004") | {name, status, busy, labels: [.labels[].name]}'

Length of output: 390


Script:

#!/bin/bash
# Search for the runner name across all workflow files
echo "=== Searching for runner usage ==="
rg "BrnoUBU0004" .github/workflows/ -l

echo -e "\n=== Checking workflow file history ==="
git log -p --since="3 months ago" .github/workflows/ci.yml | grep -A 5 -B 5 "build_linux\|BrnoUBU0004"

echo -e "\n=== Looking for other workflow files ==="
fd . .github/workflows/ -e yml -e yaml

Length of output: 760


Script:

#!/bin/bash
# Check runner configurations in CI workflow files
echo "=== CI workflow runner configurations ==="
for file in ci.yml ci_beta.yml ci_release.yml ci_windows.yml; do
  echo -e "\n=== $file ==="
  rg "runs-on:" -A 2 .github/workflows/$file
done

echo -e "\n=== Checking recent changes to CI workflows ==="
for file in ci.yml ci_beta.yml ci_release.yml ci_windows.yml; do
  echo -e "\n=== $file changes ==="
  git log -n 1 --pretty=format:"%h - %an, %ar : %s" .github/workflows/$file
done

Length of output: 1642

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (2)

80-83: LGTM! Good defensive programming.

The null check for espidfMainTablePage before refreshing the UI is a good practice.


55-59: ⚠️ Potential issue

Add null check before calling rollback.

The rollback() call on setupToolsInIde needs a null check to prevent NullPointerException.

 if (event.getResult().getSeverity() != IStatus.OK)
 {
+    if (setupToolsInIde != null) {
         // Rollback all the changes
         setupToolsInIde.rollback();
+    } else {
+        Logger.log("setupToolsInIde is null; rollback cannot be performed.");
+    }
 }

Likely invalid or redundant comment.

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (2)

62-69: LGTM! Well-structured constructor.

The constructor properly initializes all required fields and provides a descriptive job name.


169-227: ⚠️ Potential issue

Improve OpenOCD rules installation on Linux.

The copyOpenOcdRules() method has several issues:

  1. Copying to /etc/udev/rules.d/ requires root privileges
  2. UI operations are performed in a background job
  3. No validation of the rules file content before copying

Consider these improvements:

  1. Check for write permissions before attempting to copy
  2. Move UI operations outside the job
  3. Validate rules file content
  4. Provide alternative installation methods (e.g., user-level rules directory)
 private void copyOpenOcdRules() {
     if (Platform.getOS().equals(Platform.OS_LINUX)
             && !IDFUtil.getOpenOCDLocation().equalsIgnoreCase(StringUtil.EMPTY)) {
         log(Messages.InstallToolsHandler_CopyingOpenOCDRules, IStatus.OK);
         StringBuilder pathToRules = new StringBuilder();
         pathToRules.append(IDFUtil.getOpenOCDLocation());
         pathToRules.append("/../share/openocd/contrib/60-openocd.rules");
         File rulesFile = new File(pathToRules.toString());
         if (rulesFile.exists()) {
             java.nio.file.Path source = Paths.get(pathToRules.toString());
             java.nio.file.Path target = Paths.get("/etc/udev/rules.d/60-openocd.rules");
+            // Check write permissions
+            if (!Files.isWritable(target.getParent())) {
+                log("Insufficient permissions to write to " + target.toString(), IStatus.ERROR);
+                log("Please run the IDE with sudo or copy rules manually", IStatus.ERROR);
+                return;
+            }
+            // Validate rules file
+            try {
+                String content = new String(Files.readAllBytes(source));
+                if (!content.contains("SUBSYSTEM==\"usb\"")) {
+                    log("Invalid OpenOCD rules file", IStatus.ERROR);
+                    return;
+                }
+            } catch (IOException e) {
+                log("Failed to validate rules file", e);
+                return;
+            }

Likely invalid or redundant comment.

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)

23-23: Verify the corresponding entries in messages.properties.

The new message keys need corresponding entries in the properties file.

Run this script to verify the entries exist:

Also applies to: 26-26

✅ Verification successful

Message keys are properly defined in messages.properties

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the new message keys have entries in messages.properties

# Search for the new keys in messages.properties
echo "Checking messages.properties for new keys..."
rg -A 1 "EspIdfManagerNameCol|IDFToolsHandler_ToolsManagerConsole" bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties

Length of output: 384

tests/com.espressif.idf.ui.test/configs/default-test-linux.properties (1)

10-10: Verify ESP-IDF version compatibility.

The path has been updated to use ESP-IDF v5.3. Ensure that this version is compatible with all test scenarios and CI/CD pipelines.

✅ Verification successful

ESP-IDF v5.3 is compatible with the test environment

The codebase explicitly supports ESP-IDF v5.0 and higher. No version-specific test cases or incompatible dependencies were found that would prevent using v5.3.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check ESP-IDF version compatibility in test files and configurations.

# Search for version-specific ESP-IDF references
echo "Searching for ESP-IDF version references in test files..."
rg -g '*.java' -g '*.properties' 'esp-idf-v[0-9]' || echo "No explicit version references found"

# Check test configurations
echo -e "\nChecking test configurations..."
fd -e properties -e xml 'test' -x cat {} \; | grep -i 'esp.*idf.*path'

Length of output: 1145


Script:

#!/bin/bash
# Search for version-specific test cases and build configurations

# Check for version-specific test cases
echo "Checking for version-specific test cases..."
rg -g '*.java' -g '*.xml' -g '*.properties' -A 3 -B 3 '(esp-idf|ESP-IDF).*(version|v[0-9]|V[0-9])'

# Check for version requirements in build files
echo -e "\nChecking build configurations..."
fd -e xml pom.xml -x cat {} \; | grep -A 5 -B 5 'esp.*idf'

# Check for version-related configuration files
echo -e "\nChecking for version configuration files..."
fd -g '*version*.{xml,properties,json}'

Length of output: 24276

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (4)

36-38: Fix typo in class and variable names.

The class name EimIdfConfiguratinParser contains a typo ('Configuratin' should be 'Configuration'). This affects both the import statement and the field declaration.

Also applies to: 61-62


143-154: Fix path resolution for POSIX systems.

The POSIX path containing '~' won't be automatically expanded by Java's File class.


157-170: Improve shell management and URL handling.

The current implementation has several issues:

  1. Shell is created but never disposed
  2. Direct URL launch could be a security concern

105-112: 🛠️ Refactor suggestion

Enhance error handling for EIM JSON parsing.

The catch block only logs the error without any user notification or recovery mechanism. Consider informing the user about the parsing failure.

 catch (IOException e)
 {
     Logger.log(e);
+    Display.getDefault().asyncExec(() -> {
+        Shell shell = Display.getDefault().getActiveShell();
+        if (shell == null) {
+            shell = new Shell(Display.getDefault());
+        }
+        MessageBox errorBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+        errorBox.setText(Messages.ErrorDialogTitle);
+        errorBox.setMessage(Messages.EimJsonParsingError);
+        errorBox.open();
+    });
 }

Likely invalid or redundant comment.

Comment on lines +39 to +41
EimIdfConfiguratinParser eimIdfConfiguratinParser = new EimIdfConfiguratinParser();

IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimIdfConfiguratinParser.getEimJson(true)), ESPIDFManagerEditor.EDITOR_ID);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling and user feedback for configuration parsing.

The current implementation lacks proper error handling and user feedback for configuration parsing failures. Consider the following improvements:

  1. Add specific error handling for getEimJson(true)
  2. Validate the parsed configuration
  3. Provide user feedback on parsing failures

Apply this diff to improve error handling:

 EimIdfConfiguratinParser eimIdfConfiguratinParser = new EimIdfConfiguratinParser();
-					
-IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimIdfConfiguratinParser.getEimJson(true)), ESPIDFManagerEditor.EDITOR_ID);
+var eimJson = eimIdfConfiguratinParser.getEimJson(true);
+if (eimJson == null) {
+    Logger.log("Failed to parse EIM configuration");
+    MessageDialog.openError(
+        activeww.getShell(),
+        "Configuration Error",
+        "Failed to parse ESP-IDF configuration. Please check the configuration file."
+    );
+    return;
+}
+
+IDE.openEditor(
+    activeww.getActivePage(),
+    new EimEditorInput(eimJson),
+    ESPIDFManagerEditor.EDITOR_ID
+);
📝 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
EimIdfConfiguratinParser eimIdfConfiguratinParser = new EimIdfConfiguratinParser();
IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimIdfConfiguratinParser.getEimJson(true)), ESPIDFManagerEditor.EDITOR_ID);
EimIdfConfiguratinParser eimIdfConfiguratinParser = new EimIdfConfiguratinParser();
var eimJson = eimIdfConfiguratinParser.getEimJson(true);
if (eimJson == null) {
Logger.log("Failed to parse EIM configuration");
MessageDialog.openError(
activeww.getShell(),
"Configuration Error",
"Failed to parse ESP-IDF configuration. Please check the configuration file."
);
return;
}
IDE.openEditor(
activeww.getActivePage(),
new EimEditorInput(eimJson),
ESPIDFManagerEditor.EDITOR_ID
);

Comment on lines +489 to 503
IdfInstalled p1 = (IdfInstalled) e1;
IdfInstalled p2 = (IdfInstalled) e2;
int rc = 0;
switch (propertyIndex)
{
case 0:
rc = p1.getIdfVersion().compareTo(p2.getIdfVersion());
rc = p1.getName().compareTo(p2.getName());
break;
case 1:
rc = p1.getIdfLocation().compareTo(p2.getIdfLocation());
rc = p1.getPath().compareTo(p2.getPath());
break;
case 2:
Boolean p1State = p1.isActive();
Boolean p2State = p2.isActive();
Boolean p1State = ToolsUtility.isIdfInstalledActive(p1);
Boolean p2State = ToolsUtility.isIdfInstalledActive(p2);
rc = p1State.compareTo(p2State);
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 column sorting logic and add null checks.

The current implementation has several issues:

  1. Column indices don't match the UI order (activate, version, name, location)
  2. No null checks in comparisons
  3. Version comparison is missing
-IdfInstalled p1 = (IdfInstalled) e1;
-IdfInstalled p2 = (IdfInstalled) e2;
+if (!(e1 instanceof IdfInstalled) || !(e2 instanceof IdfInstalled)) {
+    return 0;
+}
+IdfInstalled p1 = (IdfInstalled) e1;
+IdfInstalled p2 = (IdfInstalled) e2;
 int rc = 0;
 switch (propertyIndex) {
 case 0:
-    rc = p1.getName().compareTo(p2.getName());
+    rc = Boolean.compare(
+        ToolsUtility.isIdfInstalledActive(p1),
+        ToolsUtility.isIdfInstalledActive(p2));
     break;
 case 1:
-    rc = p1.getPath().compareTo(p2.getPath());
+    String v1 = getIdfVersion(p1);
+    String v2 = getIdfVersion(p2);
+    rc = v1.compareTo(v2);
     break;
 case 2:
-    Boolean p1State = ToolsUtility.isIdfInstalledActive(p1);
-    Boolean p2State = ToolsUtility.isIdfInstalledActive(p2);
-    rc = p1State.compareTo(p2State);
+    rc = compareNullSafe(p1.getName(), p2.getName());
+    break;
+case 3:
+    rc = compareNullSafe(p1.getPath(), p2.getPath());
     break;
 }

Add this helper method:

private int compareNullSafe(String s1, String s2) {
    if (s1 == null) return s2 == null ? 0 : -1;
    return s2 == null ? 1 : s1.compareTo(s2);
}

Comment on lines 25 to 28
- name: Install ESP-IDF via eim
uses: Hahihula/esp-idf-install-action@v1
with:
esp_idf_version: 'v5.3'
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

⚠️ Critical: The specified GitHub Action does not exist

The action Hahihula/esp-idf-install-action@v1 is not available (404 Not Found). This poses a significant security risk as:

  • The repository could have been deleted or made private
  • A malicious actor could register this name and inject harmful code
  • Using a major version tag (v1) would automatically accept any new v1.x version

Recommendations:

  • Use the official ESP-IDF installation methods from espressif/esp-idf
  • Create a custom workflow step using official tools
  • If using any third-party actions, always pin to specific commit hashes instead of version tags
🔗 Analysis chain

Review the custom ESP-IDF installation action.

The workflow uses a custom action Hahihula/esp-idf-install-action@v1 which might pose security risks:

  1. The action is from a personal repository rather than an official Espressif source
  2. It's pinned to a major version tag (v1) which could allow breaking changes

Consider:

  1. Using the official Espressif action if available
  2. Pinning to a specific version hash instead of a major version tag
  3. Adding SHA256 verification for the ESP-IDF download
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the custom action's repository and version

# Check the action's repository
echo "Checking action repository..."
gh api repos/Hahihula/esp-idf-install-action \
  --jq '{
    created_at,
    updated_at,
    default_branch,
    archived,
    disabled,
    security: .security_and_analysis
  }'

# Check available versions/tags
echo "Checking available versions..."
gh api repos/Hahihula/esp-idf-install-action/tags \
  --jq '.[].name'

Length of output: 674


Script:

#!/bin/bash
# Check for official Espressif actions
echo "Checking Espressif organization..."
gh api orgs/espressif/repos \
  --jq '.[] | select(.topics | contains(["github-actions"])) | {name, html_url, description}'

echo "Searching for ESP-IDF related repositories..."
gh api search/repositories \
  --raw-field 'q=org:espressif idf install action' \
  --jq '.items[] | {name, html_url, description}'

Length of output: 624


Script:

#!/bin/bash
# Search GitHub Marketplace for ESP-IDF related actions
echo "Searching GitHub Marketplace for ESP-IDF actions..."
gh api search/code \
  --raw-field 'q=path:.github/workflows+org:espressif+esp-idf' \
  --jq '.items[] | {repository.full_name, path, html_url}'

# Direct check of potential official repositories
echo "Checking specific Espressif repositories..."
for repo in "esp-idf" "idf-installer" "esp-idf-actions"; do
  echo "Checking $repo..."
  gh api repos/espressif/$repo --jq '{name, description, html_url}' || true
done

Length of output: 1562

Comment on lines +39 to 41
public SetupToolsJobListener()
{
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove unused default constructor.

The default constructor leaves setupToolsInIde uninitialized, which could lead to a NullPointerException when rollback() is called in the done method. Since the class requires both espidfMainTablePage and setupToolsInIde to function correctly, the default constructor should be removed.

-public SetupToolsJobListener()
-{
-}

Comment on lines +229 to +301
private IStatus handleWebSocketClientInstall()
{
String websocketClient = "websocket-client"; //$NON-NLS-1$
// pip install websocket-client
List<String> arguments = new ArrayList<String>();
final String pythonEnvPath = IDFUtil.getIDFPythonEnvPath(envVarsFromActivationScriptMap.get(IDFEnvironmentVariables.IDF_PYTHON_ENV_PATH));
if (pythonEnvPath == null || !new File(pythonEnvPath).exists())
{
log(String.format("%s executable not found. Unable to run `%s -m pip install websocket-client`", //$NON-NLS-1$
IDFConstants.PYTHON_CMD, IDFConstants.PYTHON_CMD), IStatus.ERROR);
return IDFCorePlugin.errorStatus(
String.format("%s executable not found. Unable to run `%s -m pip install websocket-client`", //$NON-NLS-1$
IDFConstants.PYTHON_CMD, IDFConstants.PYTHON_CMD),
null);
}
arguments.add(pythonEnvPath);
arguments.add("-m"); //$NON-NLS-1$
arguments.add("pip"); //$NON-NLS-1$
arguments.add("list"); //$NON-NLS-1$

ProcessBuilderFactory processRunner = new ProcessBuilderFactory();

try
{
log("Executing " + arguments.toString(), IStatus.OK); //$NON-NLS-1$)

Map<String, String> environment = new HashMap<>(System.getenv());
prepEnvMap(environment);
Logger.log(environment.toString());

IStatus status = processRunner.runInBackground(arguments, org.eclipse.core.runtime.Path.ROOT, environment);
if (status == null)
{
Logger.log(IDFCorePlugin.getPlugin(),
IDFCorePlugin.errorStatus("Unable to get the process status.", null)); //$NON-NLS-1$
log("Unable to get the process status", IStatus.ERROR); //$NON-NLS-1$
return IDFCorePlugin.errorStatus("Unable to get the process status.", null); //$NON-NLS-1$
}

String cmdOutput = status.getMessage();
if (cmdOutput.contains(websocketClient))
{
return IDFCorePlugin.okStatus("websocket-client 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);

status = processRunner.runInBackground(arguments, org.eclipse.core.runtime.Path.ROOT, environment);
if (status == null)
{
Logger.log(IDFCorePlugin.getPlugin(),
IDFCorePlugin.errorStatus("Unable to get the process status.", null)); //$NON-NLS-1$
log("Unable to get the process status", IStatus.ERROR); //$NON-NLS-1$
return IDFCorePlugin.errorStatus("Unable to get the process status.", null); //$NON-NLS-1$
}

log(status.getMessage(), IStatus.OK);

return status;
}
catch (Exception e1)
{
Logger.log(IDFCorePlugin.getPlugin(), e1);
if (errorConsoleStream != null)
{
errorConsoleStream.println(e1.getLocalizedMessage());
}
return IDFCorePlugin.errorStatus(e1.getLocalizedMessage(), e1); // $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.

🛠️ Refactor suggestion

Improve Python package installation error handling.

The handleWebSocketClientInstall() method has several issues:

  1. Hardcoded package name and version
  2. No timeout for pip operations
  3. No verification of successful installation

Consider adding:

  1. Package version specification
  2. Installation verification
  3. Timeout mechanism
  4. Requirements.txt approach for dependency management
 private IStatus handleWebSocketClientInstall() {
-    String websocketClient = "websocket-client";
+    String websocketClient = "websocket-client>=1.0.0";  // Specify minimum version
+    int timeout = 60;  // seconds
     // ... existing code ...
     status = processRunner.runInBackground(arguments, org.eclipse.core.runtime.Path.ROOT, environment);
+    // Add timeout
+    long startTime = System.currentTimeMillis();
+    while (process.isAlive()) {
+        if ((System.currentTimeMillis() - startTime) > timeout * 1000) {
+            process.destroy();
+            return IDFCorePlugin.errorStatus("Package installation timed out", null);
+        }
+        Thread.sleep(100);
+    }
+    // Verify installation
+    if (status.isOK()) {
+        return verifyPackageInstallation(websocketClient, environment);
+    }

Committable suggestion skipped: line range outside the PR's diff.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b271300 and 475b9be.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml (1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.4)
.github/workflows/ci.yml

15-15: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


15-15: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


21-21: the runner of "actions/setup-python@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_macos

Comment on lines 25 to 28
- name: Install ESP-IDF via eim
uses: espressif/esp-idf-install-action@v1
with:
esp_idf_version: 'v5.3'
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Pin action to specific commit hash for security.

While using the official Espressif action is good, version tags can be moved. For better security:

  1. Pin to a specific commit hash:
-      uses: espressif/esp-idf-install-action@v1
+      uses: espressif/esp-idf-install-action@a2c9c4adf5648d7c935d0c9d0d48f2c2c6e2e98b
  1. Verify the action's integrity:
#!/bin/bash
# Description: Verify action's commit hash and repository
echo "Verifying action commit..."
gh api repos/espressif/esp-idf-install-action/commits/v1 --jq '{sha, commit.verification.verified}'

[skip_cloning]

Comment on lines +18 to +24
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.10'
python-version: '3.10'

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Update actions/setup-python to the latest version.

The current setup uses an outdated version of the action. Update to v4 for the latest security improvements and features:

-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v4
 
     - name: Set up Python
-      uses: actions/setup-python@v2
+      uses: actions/setup-python@v4
       with:
         python-version: '3.10'
📝 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
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.10'
python-version: '3.10'
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
🧰 Tools
🪛 actionlint (1.7.4)

21-21: the runner of "actions/setup-python@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 475b9be and 0aa1cca.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java
🧰 Additional context used
🪛 actionlint (1.7.4)
.github/workflows/ci.yml

15-15: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


15-15: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


21-21: the runner of "actions/setup-python@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🪛 YAMLlint (1.35.1)
.github/workflows/ci.yml

[error] 25-25: syntax error: found character '\t' that cannot start any token

(syntax)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_macos
🔇 Additional comments (5)
.github/workflows/ci.yml (5)

13-13: LGTM! Clear and descriptive job name.

The rename from build to build_linux better reflects the job's purpose.


15-15: ⚠️ Critical security risk: Unprotected self-hosted runner in public repository

🧰 Tools
🪛 actionlint (1.7.4)

15-15: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


15-15: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


21-23: Update actions/setup-python to the latest version.

🧰 Tools
🪛 actionlint (1.7.4)

21-21: the runner of "actions/setup-python@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


Line range hint 31-146: LGTM! Well-structured configuration.

The remaining configuration follows best practices with proper version pinning and clear step organization.

🧰 Tools
🪛 actionlint (1.7.4)

15-15: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


15-15: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


21-21: the runner of "actions/setup-python@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🪛 YAMLlint (1.35.1)

[error] 25-25: syntax error: found character '\t' that cannot start any token

(syntax)


26-28: 🛠️ Refactor suggestion

Pin ESP-IDF installation action to specific commit hash.

Using version tags (v1) for third-party actions poses a security risk. Pin to a specific commit hash for better security.

python-version: '3.10'
python-version: '3.10'

- name: Install ESP-IDF via eim
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 YAML syntax error: Remove tab character.

The step name contains a tab character which can cause YAML parsing issues.

-    - name: Install ESP-IDF via eim		
+    - name: Install ESP-IDF via eim
📝 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
- name: Install ESP-IDF via eim
- name: Install ESP-IDF via eim
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 25-25: syntax error: found character '\t' that cannot start any token

(syntax)

- self-hosted
- eclipse
- BrnoUBU0004
runs-on: [self-hosted, eclipse, BrnoUBU0004]
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Custom runner labels need documentation

The custom labels eclipse and BrnoUBU0004 are indeed undocumented. They are only used in ci.yml for a self-hosted runner but their purpose and requirements are not explained anywhere in the repository. The original suggestions remain valid:

  1. Add these labels to .github/actionlint.yaml to validate workflow syntax
  2. Document their purpose in workflow comments to explain:
    • What the eclipse label represents (e.g., required Eclipse development environment)
    • What BrnoUBU0004 represents (specific Ubuntu machine in Brno)
🔗 Analysis chain

Document custom runner labels.

The custom labels eclipse and BrnoUBU0004 should be documented:

  1. Add these labels to .github/actionlint.yaml
  2. Document their purpose in workflow comments
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if labels are documented
echo "Checking for actionlint.yaml..."
fd -g "actionlint.yaml" .github/

echo "Checking for label documentation in workflow..."
grep -B 2 -A 2 "eclipse\|BrnoUBU0004" .github/workflows/ci.yml

Length of output: 352


Script:

#!/bin/bash
# Search for any documentation or usage of these labels
echo "Searching for label documentation in workflow files..."
rg -i "eclipse|BrnoUBU0004" .

echo "Checking for README or documentation files..."
fd -e md . | xargs rg -i "eclipse|BrnoUBU0004"

Length of output: 68250


Script:

#!/bin/bash
# Look for other workflow files and any documentation about runners
echo "Checking for other workflow files..."
fd -e yml -e yaml . .github/workflows/

echo "Checking for any documentation about runners..."
rg -i "runner|self-hosted|BrnoUBU" .github/

Length of output: 1314

🧰 Tools
🪛 actionlint (1.7.4)

15-15: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


15-15: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (6)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (2)

96-100: Consider refining the setupTools() method.
This method is relatively large, handling multiple responsibilities. Consider splitting concerns (e.g., activation script handling, environment variable processing, toolchain setup) into smaller methods to improve readability and maintainability.
Also, there's a minor spelling fix needed for the variable name:

- List<String> arguemnts = new ArrayList<>();
+ List<String> arguments = new ArrayList<>();

148-150: Correct the spelling of "python".

- monitor.setTaskName("Installing pyhton dependency web-socket");
+ monitor.setTaskName("Installing python dependency web-socket");
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)

377-381: Consider adding progress monitoring to SetupToolsInIde job.

The job is scheduled without progress monitoring, which could lead to a poor user experience during long-running operations.

-SetupToolsInIde setupToolsInIde = new SetupToolsInIde(idfInstalled, eimJson, getConsoleStream(true), getConsoleStream(false));
-SetupToolsJobListener toolsActivationJobListener = new SetupToolsJobListener(
-        ESPIDFMainTablePage.this, setupToolsInIde);
-setupToolsInIde.addJobChangeListener(toolsActivationJobListener);
-setupToolsInIde.schedule();
+SetupToolsInIde setupToolsInIde = new SetupToolsInIde(idfInstalled, eimJson, getConsoleStream(true), getConsoleStream(false));
+SetupToolsJobListener toolsActivationJobListener = new SetupToolsJobListener(
+        ESPIDFMainTablePage.this, setupToolsInIde);
+setupToolsInIde.addJobChangeListener(toolsActivationJobListener);
+ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
+try {
+    dialog.run(true, true, monitor -> {
+        monitor.beginTask("Setting up IDF tools...", IProgressMonitor.UNKNOWN);
+        setupToolsInIde.schedule();
+        try {
+            setupToolsInIde.join();
+        } catch (InterruptedException e) {
+            Logger.log(e);
+            monitor.done();
+            Thread.currentThread().interrupt();
+        }
+    });
+} catch (InvocationTargetException | InterruptedException e) {
+    Logger.log(e);
+    MessageDialog.openError(
+        Display.getDefault().getActiveShell(),
+        "Setup Error",
+        "Failed to setup IDF tools: " + e.getMessage());
+}
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (3)

122-122: Address TODO comment about installer config flag.

The TODO comment indicates missing implementation for handling the installer configuration flag.

Would you like me to help implement the missing functionality for handling the installer configuration flag?


185-185: Use try-with-resources for file operations.

The Files.copy operation should be wrapped in a try-with-resources block to ensure proper resource cleanup.

-Files.copy(oldConfig.toPath(), destinationFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+try (var source = Files.newInputStream(oldConfig.toPath());
+     var target = Files.newOutputStream(destinationFile.toPath())) {
+    source.transferTo(target);
+}

203-217: Improve path handling in isEimIdfJsonPresent.

The method should handle path resolution more robustly:

  1. Use System.getProperty("user.home") to resolve ~ in POSIX paths.
  2. Consider using Path.of() instead of File for better path manipulation.
-String path = StringUtil.EMPTY;
-if (Platform.getOS().equals(Platform.OS_WIN32))
-{
-    path = EimConstants.EIM_WIN_PATH;
-}
-else
-{
-    path = EimConstants.EIM_POSIX_PATH;
-}
-
-File file = new File(path);
-return file.exists();
+String path = Platform.getOS().equals(Platform.OS_WIN32) 
+    ? EimConstants.EIM_WIN_PATH 
+    : EimConstants.EIM_POSIX_PATH.replace("~", System.getProperty("user.home"));
+return Files.exists(Path.of(path));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e19fb27 and 4187122.

⛔ Files ignored due to path filters (1)
  • bundles/com.espressif.idf.ui/icons/tools/delete.png is excluded by !**/*.png
📒 Files selected for processing (51)
  • .github/workflows/ci.yml (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/Messages.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolSetConfigurationManager.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsPlatformMapping.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/messages.properties (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (2 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IDFToolSet.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java (0 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (1 hunks)
  • bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java (0 hunks)
  • bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties (0 hunks)
  • bundles/com.espressif.idf.ui/plugin.xml (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (4 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/NewProjectHandlerUtil.java (2 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/UpdateEspIdfHandler.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/GitRepositoryBuilder.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFDownloadPage.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFNewToolsWizard.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/Messages.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages.properties (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages_zh.properties (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/GitWizardRepProgressMonitor.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/LogMessagesThread.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java (2 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (4 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationJob.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsJob.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (13 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties (1 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/ExportIDFTools.java (0 hunks)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java (0 hunks)
  • tests/com.espressif.idf.ui.test/configs/default-test-linux.properties (1 hunks)
💤 Files with no reviewable changes (28)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/Messages.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/GitRepositoryBuilder.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFNewToolsWizard.java
  • bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolSetConfigurationManager.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages.properties
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsPlatformMapping.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/LogMessagesThread.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/ExportIDFTools.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/UpdateEspIdfHandler.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsJob.java
  • bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationJob.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/GitWizardRepProgressMonitor.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IDFToolSet.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFDownloadPage.java
  • bundles/com.espressif.idf.ui/plugin.xml
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages_zh.properties
🚧 Files skipped from review as they are similar to previous changes (15)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/NewProjectHandlerUtil.java
  • tests/com.espressif.idf.ui.test/configs/default-test-linux.properties
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/messages.properties
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/Messages.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties
🧰 Additional context used
🪛 actionlint (1.7.4)
.github/workflows/ci.yml

15-15: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


15-15: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


21-21: the runner of "actions/setup-python@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🪛 YAMLlint (1.35.1)
.github/workflows/ci.yml

[error] 25-25: syntax error: found character '\t' that cannot start any token

(syntax)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_macos
  • GitHub Check: build_linux
🔇 Additional comments (25)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java (2)

11-11: Fix the typo in the import statement.

The class name contains a typo: EimIdfConfiguratinParser should be EimIdfConfigurationParser.


39-46: Improve error handling and logging.

  1. The error handling for configuration parsing needs improvement as previously noted.
  2. The generic error logging at line 45 should be enhanced to:
    • Log specific error details
    • Provide user feedback through the UI
    • Handle different types of failures separately

Apply this diff to improve error handling and logging:

 try
 {
     EimIdfConfiguratinParser eimIdfConfiguratinParser = new EimIdfConfiguratinParser();
     
-    IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimIdfConfiguratinParser.getEimJson(true)), ESPIDFManagerEditor.EDITOR_ID);
+    var eimJson = eimIdfConfiguratinParser.getEimJson(true);
+    if (eimJson == null) {
+        String msg = "Failed to parse EIM configuration";
+        Logger.log(msg);
+        MessageDialog.openError(
+            activeww.getShell(),
+            "Configuration Error",
+            msg + ". Please check the configuration file."
+        );
+        return;
+    }
+    
+    IDE.openEditor(
+        activeww.getActivePage(),
+        new EimEditorInput(eimJson),
+        ESPIDFManagerEditor.EDITOR_ID
+    );
 }
 catch (Exception e)
 {
-    Logger.log(e);
+    String msg = "Failed to open ESP-IDF Manager";
+    Logger.log(msg, e);
+    MessageDialog.openError(
+        activeww.getShell(),
+        "Editor Error",
+        msg + ": " + e.getMessage()
+    );
 }
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (3)

23-23: LGTM! New message field for ESP-IDF manager name column.

The addition follows proper i18n conventions and aligns with the UI restructuring for EIM integration.


25-26: Verify message properties file update.

The new console-related message field looks good and aligns with the shift to console-based tools management.

Let's verify that the corresponding message properties file has been updated:

✅ Verification successful

Message properties update verified.
The new key IDFToolsHandler_ToolsManagerConsole appears in both the tools and update properties files as expected:

  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/messages.properties
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the message properties file contains the new message keys

# Find and check the messages.properties file
fd -t f "messages.properties" | xargs grep -l "IDFToolsHandler_ToolsManagerConsole\|EspIdfManagerNameCol"

Length of output: 266


1-38: Document breaking changes in translations.

The significant removal of message fields constitutes a breaking change that will affect existing translations. Please ensure that:

  1. The changes are documented in the migration guide
  2. Translators are notified about the removed and new message keys
  3. All language-specific properties files are updated accordingly

Let's check for existing translations that might be affected:

✅ Verification successful

Translation Files Impact – Update Migration Guide and Notify Translators

The removal of several message fields in bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java directly impacts the corresponding translation file (bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties) as well as any localized versions (e.g., messages_zh.properties). Please ensure that:

  • The migration guide clearly documents the removed message keys.
  • Translators are alerted to update their respective files to reflect these changes.
  • All affected translation property files across the project (as identified by the search, such as those under bundles/com.espressif.idf.core, bundles/com.espressif.idf.ui, etc.) are reviewed and updated accordingly.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all language-specific properties files that might need updates

# Find all properties files in the project
fd -t f "messages.*\.properties"

Length of output: 4868

.github/workflows/ci.yml (3)

13-16: 🛠️ Refactor suggestion

Job Identifier and Runner Labels:
The job has been renamed to build_linux to clearly indicate its target platform. However, the runs-on list now includes custom labels eclipse and BrnoUBU0004 which are not standard. Ensure these custom labels are properly declared in your .github/actionlint.yaml configuration and their purpose is documented in the repository to help maintain clarity and avoid runner selection issues.

🧰 Tools
🪛 actionlint (1.7.4)

15-15: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


15-15: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


20-23: Update Setup-Python Action Version:
This step uses actions/setup-python@v2, which is considered outdated. Upgrading to a newer major version (e.g. v4) is recommended to benefit from improved functionality, security, and compatibility with the latest GitHub Actions features.

Suggested diff:

-      uses: actions/setup-python@v2
+      uses: actions/setup-python@v4
✅ Verification successful

Update Setup-Python Action to v4 in .github/workflows/ci.yml
The current workflow file uses actions/setup-python@v2; upgrading to version v4 is recommended for improved functionality and security. Please update the workflow step accordingly:

-      uses: actions/setup-python@v2
+      uses: actions/setup-python@v4
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found

🧰 Tools
🪛 actionlint (1.7.4)

21-21: the runner of "actions/setup-python@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


25-28: 🛠️ Refactor suggestion

⚠️ Potential issue

Fix YAML Syntax and Improve Action Security:
The step name "Install ESP-IDF via eim" (line 25) contains a tab character, which can lead to YAML syntax errors. Replace any tab characters with spaces. Additionally, the action is currently referenced with a loose version tag @v1. For better security and stability, pin the action to a specific commit hash, so any unintended changes in future releases don’t affect your workflow.

Suggested diff:

-    - name: Install ESP-IDF via eim		
+    - name: Install ESP-IDF via eim
-      uses: espressif/install-esp-idf-action@v1
+      uses: espressif/install-esp-idf-action@<SPECIFIC_COMMIT_HASH>

Replace <SPECIFIC_COMMIT_HASH> with the exact commit hash you intend to pin.

Likely invalid or redundant comment.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 25-25: syntax error: found character '\t' that cannot start any token

(syntax)

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (4)

1-4: Header & License block look good.
No concerns here.


77-94: Validate existingEnvVarsInIdeForRollback before usage.
If createExistingBackup() is never invoked prior to rollback, existingEnvVarsInIdeForRollback can be null, causing a potential NullPointerException.

Would you like me to generate a shell script to scan for all invocations of rollback() to confirm that createExistingBackup() is always called first?


169-227: Add dedicated permission handling for OpenOCD rules copying.
If the process lacks elevated privileges, copying rules into /etc/udev/rules.d may fail. Log messages alone might not suffice to guide the user to correct the permission issue.


253-253: Remove extraneous parenthesis to fix syntax error.
Below is the same fix identified in a previous review:

- log("Executing " + arguments.toString(), IStatus.OK); //$NON-NLS-1$)
+ log("Executing " + arguments.toString(), IStatus.OK); //$NON-NLS-1$
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (4)

39-41: Remove or revise the default constructor to avoid potential NPE.
If this empty constructor is used, setupToolsInIde remains uninitialized, which could cause a NullPointerException in done().


55-59: Guard against NullPointerException when rolling back.
If setupToolsInIde is null, setupToolsInIde.rollback() triggers a NullPointerException.


63-67: Storing installation flag looks correct.
Writing the boolean to the scoped preferences is straightforward and meets the requirement for tracking whether tools are installed.


79-86: UI refresh and launchbar event handling look good.
The asynchronous execution ensures the UI remains responsive, and re-enabling launchbar events is well-placed after the job finishes.

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (3)

50-54: Prevent potential ArrayIndexOutOfBoundsException when splitting version string.

When splitting the line to extract espIdfVersion, ensure that the line contains an = character.

Apply this fix:

 if (line.startsWith("ESP_IDF_VERSION=")) //$NON-NLS-1$
 {
+    if (line.contains("=")) {
         espIdfVersion = line.split("=")[1]; //$NON-NLS-1$
         break;
+    }
 }

58-58: Add timeout to process execution.

Add a timeout to process.waitFor() to prevent hanging in case the script execution takes too long.

-process.waitFor();
+if (!process.waitFor(30, TimeUnit.SECONDS)) {
+    process.destroyForcibly();
+    Logger.log("Process timed out while executing: " + activationScript);
+    return null;
+}

89-94: Prevent potential NullPointerException in isIdfInstalledActive method.

If idfInstalled.getId() could be null, calling .equals() on it may lead to a NullPointerException.

Apply this fix:

+import java.util.Objects;

 public static boolean isIdfInstalledActive(IdfInstalled idfInstalled)
 {
+    if (idfInstalled == null) {
+        return false;
+    }
     IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables();
     String espIdfIdEim = idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.ESP_IDF_EIM_ID);
-    return idfInstalled.getId().equals(espIdfIdEim);
+    return Objects.equals(idfInstalled.getId(), espIdfIdEim);
 }
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (3)

66-67: ⚠️ Potential issue

Consider making eimJson an instance variable instead of static.

The static eimJson field could lead to thread safety issues in a multi-threaded UI environment. Consider making it an instance variable to maintain proper encapsulation and thread safety.

-private static EimJson eimJson;
+private EimJson eimJson;

Likely invalid or redundant comment.


351-355: 🛠️ Refactor suggestion

Add error handling to getIdfVersion method.

The method doesn't handle potential null values or exceptions that might occur when accessing eimJson.getGitPath().

 private String getIdfVersion(IdfInstalled idfInstalled)
 {
+    if (idfInstalled == null || eimJson == null) {
+        return "Unknown";
+    }
+    try {
         String version = ToolsUtility.getIdfVersion(idfInstalled, eimJson.getGitPath());
-        return version;
+        return version != null ? version : "Unknown";
+    } catch (Exception e) {
+        Logger.log(e);
+        return "Error";
+    }
 }

Likely invalid or redundant comment.


79-87: 🛠️ Refactor suggestion

Refactor singleton pattern to avoid shared mutable state.

The current implementation modifies static state in getInstance, which could lead to race conditions. Consider using a thread-safe singleton pattern or dependency injection.

-public static ESPIDFMainTablePage getInstance(EimJson eimJson)
-{
-    if (espidfMainTablePage == null)
-    {
-        espidfMainTablePage = new ESPIDFMainTablePage();
-    }
-    
-    ESPIDFMainTablePage.eimJson = eimJson;
-    return espidfMainTablePage;
-}
+public static synchronized ESPIDFMainTablePage getInstance(EimJson eimJson)
+{
+    if (espidfMainTablePage == null)
+    {
+        espidfMainTablePage = new ESPIDFMainTablePage(eimJson);
+    }
+    else
+    {
+        espidfMainTablePage.setEimJson(eimJson);
+    }
+    return espidfMainTablePage;
+}

Likely invalid or redundant comment.

bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (3)

66-67: Fix typo in class and variable names.

The class name has a typo: "Configuratin" should be "Configuration".


234-247: 🛠️ Refactor suggestion

Improve shell management in userNotficationToInstallEim.

The shell is created but never disposed, which could lead to resource leaks.

 Display.getDefault().asyncExec(()-> {
-    Shell shell = new Shell(Display.getDefault());
+    Shell shell = Display.getDefault().getActiveShell();
+    if (shell == null) {
+        shell = new Shell(Display.getDefault());
+    }
     MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.YES | SWT.NO);
     
     messageBox.setText(Messages.ToolsInitializationEimMissingMsgBoxTitle);
     messageBox.setMessage(Messages.ToolsInitializationEimMissingMsgBoxMessage);
     int response = messageBox.open();
     if (response == SWT.YES)
     {
         Program.launch(EimConstants.EIM_URL);
-    }	
+    }
+    if (!shell.isDisposed()) {
+        shell.dispose();
+    }
 });

Likely invalid or redundant comment.


123-144: 🛠️ Refactor suggestion

Replace syncExec with asyncExec to prevent UI blocking.

Using syncExec can block the UI thread. Since this is a notification dialog, asyncExec would be more appropriate.

-Display.getDefault().syncExec(()-> {
+Display.getDefault().asyncExec(()-> {

Likely invalid or redundant comment.

Comment on lines 68 to 70
public static List<String> getExportScriptCommand(String activationScriptPath)
{
FileInputStream fis = new FileInputStream(file);
byte[] byteArray = new byte[1024];
int bytesCount = 0;
while ((bytesCount = fis.read(byteArray)) != -1)
List<String> command = new ArrayList<>();
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation and consider security implications.

The method should validate the input parameter and document security implications of bypassing PowerShell execution policy.

Add parameter validation and documentation:

+/**
+ * Builds a platform-specific command list to execute the activation script.
+ * 
+ * @param activationScriptPath The path to the activation script
+ * @return List of command arguments
+ * @throws IllegalArgumentException if activationScriptPath is null or empty
+ * @security Uses PowerShell execution policy bypass on Windows, which should be
+ *           used cautiously as it temporarily disables script execution restrictions
+ */
 public static List<String> getExportScriptCommand(String activationScriptPath)
 {
+    if (activationScriptPath == null || activationScriptPath.trim().isEmpty()) {
+        throw new IllegalArgumentException("Activation script path cannot be null or empty");
+    }
     List<String> command = new ArrayList<>();
📝 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
public static List<String> getExportScriptCommand(String activationScriptPath)
{
FileInputStream fis = new FileInputStream(file);
byte[] byteArray = new byte[1024];
int bytesCount = 0;
while ((bytesCount = fis.read(byteArray)) != -1)
List<String> command = new ArrayList<>();
/**
* Builds a platform-specific command list to execute the activation script.
*
* @param activationScriptPath The path to the activation script
* @return List of command arguments
* @throws IllegalArgumentException if activationScriptPath is null or empty
* @security Uses PowerShell execution policy bypass on Windows, which should be
* used cautiously as it temporarily disables script execution restrictions
*/
public static List<String> getExportScriptCommand(String activationScriptPath)
{
if (activationScriptPath == null || activationScriptPath.trim().isEmpty()) {
throw new IllegalArgumentException("Activation script path cannot be null or empty");
}
List<String> command = new ArrayList<>();
// ... rest of the method code
}

Comment on lines 27 to 29
public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath)
{
File homeDir = new File(ESPRESSIF_HOME_DIR);
if (!homeDir.exists())
{
return false;
}

File toolDirectory = new File(ESPRESSIF_HOME_TOOLS_DIR.concat(FORWARD_SLASH).concat(toolName)
.concat(FORWARD_SLASH).concat(versionsName));
if (toolDirectory.exists())
{
IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables();
String pathValue = idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.PATH);
String[] splittedPaths = pathValue.split(File.pathSeparator);
String directorySplittor = Platform.getOS().equals(Platform.OS_WIN32) ? SLASH : FORWARD_SLASH;
for (String splittedPath : splittedPaths)
{
if (splittedPath.contains(toolName.concat(directorySplittor).concat(versionsName)))
{
return true;
}
}
}

return false;
}
String activationScript = idfInstalled.getActivationScript();
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input parameter validation.

The method should validate input parameters to prevent potential NPEs or invalid paths.

Add parameter validation:

 public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath)
 {
+    if (idfInstalled == null) {
+        Logger.log("IdfInstalled parameter is null");
+        return null;
+    }
     String activationScript = idfInstalled.getActivationScript();
+    if (activationScript == null || activationScript.trim().isEmpty()) {
+        Logger.log("Activation script path is null or empty");
+        return null;
+    }
+    File scriptFile = new File(activationScript);
+    if (!scriptFile.exists() || !scriptFile.canExecute()) {
+        Logger.log("Activation script does not exist or is not executable: " + activationScript);
+        return null;
+    }
📝 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
public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath)
{
File homeDir = new File(ESPRESSIF_HOME_DIR);
if (!homeDir.exists())
{
return false;
}
File toolDirectory = new File(ESPRESSIF_HOME_TOOLS_DIR.concat(FORWARD_SLASH).concat(toolName)
.concat(FORWARD_SLASH).concat(versionsName));
if (toolDirectory.exists())
{
IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables();
String pathValue = idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.PATH);
String[] splittedPaths = pathValue.split(File.pathSeparator);
String directorySplittor = Platform.getOS().equals(Platform.OS_WIN32) ? SLASH : FORWARD_SLASH;
for (String splittedPath : splittedPaths)
{
if (splittedPath.contains(toolName.concat(directorySplittor).concat(versionsName)))
{
return true;
}
}
}
return false;
}
String activationScript = idfInstalled.getActivationScript();
public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath)
{
if (idfInstalled == null) {
Logger.log("IdfInstalled parameter is null");
return null;
}
String activationScript = idfInstalled.getActivationScript();
if (activationScript == null || activationScript.trim().isEmpty()) {
Logger.log("Activation script path is null or empty");
return null;
}
File scriptFile = new File(activationScript);
if (!scriptFile.exists() || !scriptFile.canExecute()) {
Logger.log("Activation script does not exist or is not executable: " + activationScript);
return null;
}
// ... rest of the method implementation ...
}

Comment on lines +489 to 504
IdfInstalled p1 = (IdfInstalled) e1;
IdfInstalled p2 = (IdfInstalled) e2;
int rc = 0;
switch (propertyIndex)
{
case 0:
rc = p1.getIdfVersion().compareTo(p2.getIdfVersion());
rc = p1.getName().compareTo(p2.getName());
break;
case 1:
rc = p1.getIdfLocation().compareTo(p2.getIdfLocation());
rc = p1.getPath().compareTo(p2.getPath());
break;
case 2:
Boolean p1State = p1.isActive();
Boolean p2State = p2.isActive();
Boolean p1State = ToolsUtility.isIdfInstalledActive(p1);
Boolean p2State = ToolsUtility.isIdfInstalledActive(p2);
rc = p1State.compareTo(p2State);
break;
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 column sorting logic and add null checks.

The current implementation has several issues:

  1. Column indices don't match the UI order (activate, version, name, location)
  2. No null checks in comparisons
  3. Version comparison is missing
-IdfInstalled p1 = (IdfInstalled) e1;
-IdfInstalled p2 = (IdfInstalled) e2;
+if (!(e1 instanceof IdfInstalled) || !(e2 instanceof IdfInstalled)) {
+    return 0;
+}
+IdfInstalled p1 = (IdfInstalled) e1;
+IdfInstalled p2 = (IdfInstalled) e2;
 int rc = 0;
 switch (propertyIndex)
 {
 case 0:
-    rc = p1.getName().compareTo(p2.getName());
+    rc = Boolean.compare(
+        ToolsUtility.isIdfInstalledActive(p1),
+        ToolsUtility.isIdfInstalledActive(p2));
     break;
 case 1:
-    rc = p1.getPath().compareTo(p2.getPath());
+    String v1 = getIdfVersion(p1);
+    String v2 = getIdfVersion(p2);
+    rc = v1.compareTo(v2);
     break;
 case 2:
-    Boolean p1State = ToolsUtility.isIdfInstalledActive(p1);
-    Boolean p2State = ToolsUtility.isIdfInstalledActive(p2);
-    rc = p1State.compareTo(p2State);
+    rc = compareNullSafe(p1.getName(), p2.getName());
+    break;
+case 3:
+    rc = compareNullSafe(p1.getPath(), p2.getPath());
     break;
 }

Add this helper method:

private int compareNullSafe(String s1, String s2) {
    if (s1 == null) return s2 == null ? 0 : -1;
    return s2 == null ? 1 : s1.compareTo(s2);
}

Comment on lines +132 to +139
try
{
eimJson = eimIdfConfiguratinParser.getEimJson(true);
}
catch (IOException e)
{
Logger.log(e);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling in refreshEditorUI.

The catch block only logs the error without proper user feedback or recovery mechanism.

 try
 {
     eimJson = eimIdfConfiguratinParser.getEimJson(true);
 }
 catch (IOException e)
 {
     Logger.log(e);
+    MessageDialog.openError(
+        Display.getDefault().getActiveShell(),
+        "Configuration Error",
+        "Failed to load IDF configuration: " + e.getMessage());
+    return;
 }
📝 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
{
eimJson = eimIdfConfiguratinParser.getEimJson(true);
}
catch (IOException e)
{
Logger.log(e);
}
try
{
eimJson = eimIdfConfiguratinParser.getEimJson(true);
}
catch (IOException e)
{
Logger.log(e);
MessageDialog.openError(
Display.getDefault().getActiveShell(),
"Configuration Error",
"Failed to load IDF configuration: " + e.getMessage());
return;
}

Comment on lines +97 to 101
checkAndHandleOldConfig();
if (isEimInstalled())
{
Logger.log(MessageFormat.format("esp-idf.json file doesn't exist at this location: '{0}'", url.getPath()));
return;
notifyAndSetEspIdf();
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for edge cases in startup sequence.

The startup sequence should handle potential errors that might occur during initialization:

  1. What happens if checking old config fails?
  2. What if EIM installation check throws an exception?
 checkAndHandleOldConfig();
-if (isEimInstalled())
+try {
+    if (isEimInstalled())
+    {
+        notifyAndSetEspIdf();
+    }
+} catch (Exception e) {
+    Logger.log(e);
+    Display.getDefault().asyncExec(() -> {
+        Shell shell = Display.getDefault().getActiveShell();
+        MessageDialog.openError(shell, 
+            Messages.InitializationErrorTitle,
+            Messages.InitializationErrorMessage + e.getMessage());
+    });
+}
📝 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
checkAndHandleOldConfig();
if (isEimInstalled())
{
Logger.log(MessageFormat.format("esp-idf.json file doesn't exist at this location: '{0}'", url.getPath()));
return;
notifyAndSetEspIdf();
}
checkAndHandleOldConfig();
try {
if (isEimInstalled())
{
notifyAndSetEspIdf();
}
} catch (Exception e) {
Logger.log(e);
Display.getDefault().asyncExec(() -> {
Shell shell = Display.getDefault().getActiveShell();
MessageDialog.openError(shell,
Messages.InitializationErrorTitle,
Messages.InitializationErrorMessage + e.getMessage());
});
}

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (1)
tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java (1)

15-18: Unused Code Alert – Clean-Up Recommended

The search confirms that the constants are only defined in tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java and are not referenced anywhere else in the codebase. Please consider removing the following if they are no longer needed:

  • ESP_IDF_PATH_PROPERTY
  • GIT_PATH_PROPERTY
  • PYTHON_PATH_PROPERTY
  • PYTHON_VERSION_PROPERTY
🔗 Analysis chain

Verify if these constants are still needed.

These path-related constants appear to be unused in the current implementation. Consider removing them if they are no longer referenced elsewhere in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of the path constants
echo "Searching for ESP_IDF_PATH_PROPERTY usage..."
rg "ESP_IDF_PATH_PROPERTY"

echo -e "\nSearching for GIT_PATH_PROPERTY usage..."
rg "GIT_PATH_PROPERTY"

echo -e "\nSearching for PYTHON_PATH_PROPERTY usage..."
rg "PYTHON_PATH_PROPERTY"

echo -e "\nSearching for PYTHON_VERSION_PROPERTY usage..."
rg "PYTHON_VERSION_PROPERTY"

Length of output: 1230

♻️ Duplicate comments (4)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (4)

42-43: ⚠️ Potential issue

Fix typo in class name and field.

The class name EimIdfConfiguratinParser contains a typo ('Configuratin' should be 'Configuration'). This typo is propagated to the field declaration.

Also applies to: 66-67


97-101: 🛠️ Refactor suggestion

Add error handling for initialization sequence.

The initialization sequence lacks proper error handling for potential failures during old config migration and EIM installation checks.


215-227: ⚠️ Potential issue

Fix path handling for POSIX systems.

The code doesn't properly handle the '~' character in POSIX paths, which Java's File class doesn't automatically expand.


244-257: ⚠️ Potential issue

Improve shell management and URL validation in user notification.

The shell is created but never disposed, and the URL launch could be a security concern.

🧹 Nitpick comments (2)
tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java (1)

38-38: Review the timeout value for waiting on console output.

The current timeout of 99000000 milliseconds (≈27.5 hours) seems excessive. Consider using a more reasonable timeout value based on typical tool setup completion times.

Example improvement:

-TestWidgetWaitUtility.waitUntilViewContains(bot, "Tools Setup complete", consoleView, 99000000);
+// Use a more reasonable timeout (e.g., 5 minutes = 300000 milliseconds)
+TestWidgetWaitUtility.waitUntilViewContains(bot, "Tools Setup complete", consoleView, 300000);
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (1)

323-326: Consider renaming method for clarity.

The method name isEspIdfSet() could be more descriptive about what it's actually checking (installation tools flag).

Apply this diff to improve clarity:

-private boolean isEspIdfSet()
+private boolean isEspIdfToolsInstalled()
 {
     return getPreferences().getBoolean(EimConstants.INSTALL_TOOLS_FLAG, false);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4187122 and 702c2b1.

📒 Files selected for processing (2)
  • bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (4 hunks)
  • tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_macos
  • GitHub Check: build_linux
🔇 Additional comments (2)
tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java (1)

22-71: Document the new setup process and its implications.

This change represents a significant shift in how the ESP-IDF environment is initialized, moving from a manual path configuration approach to an automated setup through the ESP-IDF Manager. Given that this is a breaking change (as mentioned in the PR objectives), please:

  1. Add detailed comments explaining the new setup process
  2. Document any prerequisites or assumptions
  3. Update the class-level documentation to reflect these changes
  4. Consider adding a migration guide for users of the old setup process
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java (1)

122-140: 🛠️ Refactor suggestion

Improve thread safety and shell management.

The code uses syncExec which could cause UI freezes, and the shell management could be improved.

Apply this diff to improve the implementation:

-Display.getDefault().syncExec(()-> {
+Display.getDefault().asyncExec(()-> {
     String skipTestsValue = System.getProperty("skipTests");
     if (!StringUtil.isEmpty(skipTestsValue) && !Boolean.parseBoolean(skipTestsValue))
     {
         openEspIdfManager();
         return;
     }
-    Shell shell = Display.getDefault().getActiveShell();
+    Shell shell = Display.getDefault().getActiveShell();
+    if (shell == null) {
+        shell = new Shell(Display.getDefault());
+    }
     MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING| SWT.YES | SWT.NO);
     messageBox.setText(Messages.NoActiveEspIdfInWorkspaceMsgTitle);
     messageBox.setMessage(Messages.NoActiveEspIdfInWorkspaceMsg);
     
     int response = messageBox.open();
     if (response == SWT.YES)
     {
         openEspIdfManager();
     }
+    if (!shell.isDisposed()) {
+        shell.dispose();
+    }
 });

Likely invalid or redundant comment.

Comment on lines +32 to +33
SWTBotEditor espIdfManagerView = bot.editorByTitle("ESP-IDF Manager");
espIdfManagerView.bot().radio(0).click();
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace hardcoded radio button index with a more robust selector.

Using a hardcoded index (0) for the radio button selection is fragile and could break if the UI layout changes. Consider using a more robust selector based on the radio button's text or tooltip.

Example improvement:

-espIdfManagerView.bot().radio(0).click();
+espIdfManagerView.bot().radio("Expected Radio Button Text").click();
📝 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
SWTBotEditor espIdfManagerView = bot.editorByTitle("ESP-IDF Manager");
espIdfManagerView.bot().radio(0).click();
SWTBotEditor espIdfManagerView = bot.editorByTitle("ESP-IDF Manager");
espIdfManagerView.bot().radio("Expected Radio Button Text").click();

Comment on lines +31 to +41

SWTBotEditor espIdfManagerView = bot.editorByTitle("ESP-IDF Manager");
espIdfManagerView.bot().radio(0).click();

SWTBotView consoleView = bot.viewById("org.eclipse.ui.console.ConsoleView");
consoleView.show();
consoleView.setFocus();
TestWidgetWaitUtility.waitUntilViewContains(bot, "Tools Setup complete", consoleView, 99000000);
bot.cTabItem("ESP-IDF Manager").activate();
bot.cTabItem("ESP-IDF Manager").close();

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for UI interactions.

The current implementation assumes that all UI elements will be available and interactions will succeed. Consider adding error handling to gracefully handle cases where:

  • ESP-IDF Manager editor is not found
  • Radio button is not available
  • Console view is not accessible
  • Tools setup fails to complete

Example improvement:

+try {
   SWTBotEditor espIdfManagerView = bot.editorByTitle("ESP-IDF Manager");
   espIdfManagerView.bot().radio(0).click();
   
   SWTBotView consoleView = bot.viewById("org.eclipse.ui.console.ConsoleView");
   consoleView.show();
   consoleView.setFocus();
   TestWidgetWaitUtility.waitUntilViewContains(bot, "Tools Setup complete", consoleView, 99000000);
   bot.cTabItem("ESP-IDF Manager").activate();
   bot.cTabItem("ESP-IDF Manager").close();
+} catch (WidgetNotFoundException e) {
+   throw new SetupException("Failed to setup ESP-IDF environment: " + e.getMessage(), e);
+}
📝 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
SWTBotEditor espIdfManagerView = bot.editorByTitle("ESP-IDF Manager");
espIdfManagerView.bot().radio(0).click();
SWTBotView consoleView = bot.viewById("org.eclipse.ui.console.ConsoleView");
consoleView.show();
consoleView.setFocus();
TestWidgetWaitUtility.waitUntilViewContains(bot, "Tools Setup complete", consoleView, 99000000);
bot.cTabItem("ESP-IDF Manager").activate();
bot.cTabItem("ESP-IDF Manager").close();
try {
SWTBotEditor espIdfManagerView = bot.editorByTitle("ESP-IDF Manager");
espIdfManagerView.bot().radio(0).click();
SWTBotView consoleView = bot.viewById("org.eclipse.ui.console.ConsoleView");
consoleView.show();
consoleView.setFocus();
TestWidgetWaitUtility.waitUntilViewContains(bot, "Tools Setup complete", consoleView, 99000000);
bot.cTabItem("ESP-IDF Manager").activate();
bot.cTabItem("ESP-IDF Manager").close();
} catch (WidgetNotFoundException e) {
throw new SetupException("Failed to setup ESP-IDF environment: " + e.getMessage(), e);
}

Comment on lines +111 to +119
try
{
eimJson = eimIdfConfiguratinParser.getEimJson(true);
}
catch (IOException e)
{
Logger.log(e);
}

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling for EIM JSON parsing.

The catch block only logs the exception without any user notification or recovery action.

Apply this diff to improve error handling:

 try
 {
     eimJson = eimIdfConfiguratinParser.getEimJson(true);
 }
 catch (IOException e)
 {
     Logger.log(e);
+    Display.getDefault().asyncExec(() -> {
+        Shell shell = Display.getDefault().getActiveShell();
+        MessageDialog.openError(shell,
+            Messages.EimJsonParseErrorTitle,
+            Messages.EimJsonParseErrorMessage + e.getMessage());
+    });
 }
📝 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
{
eimJson = eimIdfConfiguratinParser.getEimJson(true);
}
catch (IOException e)
{
Logger.log(e);
}
try
{
eimJson = eimIdfConfiguratinParser.getEimJson(true);
}
catch (IOException e)
{
Logger.log(e);
Display.getDefault().asyncExec(() -> {
Shell shell = Display.getDefault().getActiveShell();
MessageDialog.openError(shell,
Messages.EimJsonParseErrorTitle,
Messages.EimJsonParseErrorMessage + e.getMessage());
});
}

Comment on lines +143 to +155
private void openEspIdfManager()
{
IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow();
IDFUtil.closeWelcomePage(activeww);
try
{
IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimJson), ESPIDFManagerEditor.EDITOR_ID);
}
catch (PartInitException e)
{
Logger.log(e);
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add null checks and improve error handling in openEspIdfManager.

The method doesn't check for null workbench window or handle editor opening errors properly.

Apply this diff to add proper checks:

 private void openEspIdfManager()
 {
     IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow();
+    if (activeww == null) {
+        Logger.log("No active workbench window found");
+        return;
+    }
     IDFUtil.closeWelcomePage(activeww);
     try
     {
+        if (eimJson == null) {
+            Logger.log("EIM configuration data is unavailable");
+            return;
+        }
         IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimJson), ESPIDFManagerEditor.EDITOR_ID);
     }
     catch (PartInitException e)
     {
         Logger.log(e);
+        Display.getDefault().asyncExec(() -> {
+            Shell shell = Display.getDefault().getActiveShell();
+            MessageDialog.openError(shell,
+                Messages.EditorOpenErrorTitle,
+                Messages.EditorOpenErrorMessage + e.getMessage());
+        });
     }
 }
📝 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 void openEspIdfManager()
{
IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow();
IDFUtil.closeWelcomePage(activeww);
try
{
IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimJson), ESPIDFManagerEditor.EDITOR_ID);
}
catch (PartInitException e)
{
Logger.log(e);
}
}
private void openEspIdfManager()
{
IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow();
if (activeww == null) {
Logger.log("No active workbench window found");
return;
}
IDFUtil.closeWelcomePage(activeww);
try
{
if (eimJson == null) {
Logger.log("EIM configuration data is unavailable");
return;
}
IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimJson), ESPIDFManagerEditor.EDITOR_ID);
}
catch (PartInitException e)
{
Logger.log(e);
Display.getDefault().asyncExec(() -> {
Shell shell = Display.getDefault().getActiveShell();
MessageDialog.openError(shell,
Messages.EditorOpenErrorTitle,
Messages.EditorOpenErrorMessage + e.getMessage());
});
}
}

Copy link
Collaborator Author

@alirana01 alirana01 left a comment

Choose a reason for hiding this comment

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

Self Review

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/ci.yml (1)

20-24: Update Python Setup Action

While the formatting and indentation have been corrected, note that actions/setup-python@v2 is flagged as outdated by static analysis. Consider upgrading to a more recent version (for example, actions/setup-python@v4) to benefit from the latest features and security improvements.

🧰 Tools
🪛 actionlint (1.7.4)

21-21: the runner of "actions/setup-python@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a97d4fd and 9319826.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml (1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.4)
.github/workflows/ci.yml

15-15: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


15-15: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


21-21: the runner of "actions/setup-python@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🪛 YAMLlint (1.35.1)
.github/workflows/ci.yml

[error] 25-25: syntax error: found character '\t' that cannot start any token

(syntax)


[error] 34-34: trailing spaces

(trailing-spaces)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_macos
🔇 Additional comments (4)
.github/workflows/ci.yml (4)

13-14: Job Naming and Structure is Clear

The new build_linux job is well-defined and clearly indicates its Linux-focused build.


15-15: Validate Runner Labels and Update Documentation

The runs-on field includes custom labels eclipse and BrnoUBU0004, which are not among the default runner labels. Please ensure these custom labels are defined in your .github/actionlint.yaml configuration or are documented clearly in your repository guidelines to avoid potential misconfiguration.

🧰 Tools
🪛 actionlint (1.7.4)

15-15: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


15-15: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


18-18: Updated Checkout Action

Using actions/checkout@v4 is a positive update that enhances performance and security relative to older versions.


35-41: Well-Configured JDK Setup

The setup for JDK 17 using actions/setup-java@v4, along with the Maven cache configuration, is well-implemented and properly structured.

Comment on lines +25 to 29
- name: Install ESP-IDF via eim
uses: espressif/install-esp-idf-action@v1
with:
version: 'v5.3'

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Resolve YAML Syntax Issue and Confirm ESP-IDF Action Security

A tab character is present in the step name for "Install ESP-IDF via eim" (line 25) and should be removed to prevent YAML parsing errors. Additionally, while using espressif/install-esp-idf-action@v1 is acceptable, it is recommended to consider pinning the action to a specific commit hash to reduce potential security risks associated with mutable version tags.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 25-25: syntax error: found character '\t' that cannot start any token

(syntax)

Copy link
Collaborator

@kolipakakondal kolipakakondal left a comment

Choose a reason for hiding this comment

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

LGTM from the code level. I haven't run the installer to verify the functionality.


public interface EimConstants
{
String EIM_WIN_PATH = "C:\\Espressif\\tools\\esp_ide.json"; //$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.

For some reason, if user is not installed in C:\Espressif\ folder, do we have other mechanism to identify this file?

{
eimJson = gson.fromJson(fileReader, EimJson.class);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you also handle eim file not found, parsing exception issues and version specific things(not sure if it's already introduced version number the eim_ide.json file)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants