-
Notifications
You must be signed in to change notification settings - Fork 133
[WIP] Release/v4.0.0 This is just to have the release 4.0 builds for testing (Please dont merge it yet #1217
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
Conversation
WalkthroughThis update removes the legacy ESP-IDF tools installation, configuration, and management UI and backend logic, replacing it with a new JSON-based system centered around EIM (Espressif Integration Manager). The codebase eliminates preference-based and wizard-driven tool setup, introduces new classes for EIM JSON parsing and monitoring, and updates environment handling to use system defaults. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant EclipseIDE
participant EspressifToolStartup
participant ToolInitializer
participant EimIdfConfiguratinParser
participant ESPIDFManagerEditor
User->>EclipseIDE: Start IDE
activate EclipseIDE
EclipseIDE->>EspressifToolStartup: earlyStartup()
EspressifToolStartup->>ToolInitializer: isEimInstalled()
alt EIM not installed
EspressifToolStartup->>User: Show warning dialog with EIM download link
else EIM installed
EspressifToolStartup->>EimIdfConfiguratinParser: getEimJson()
alt No ESP-IDF set
EspressifToolStartup->>User: Prompt to open ESP-IDF Manager
User-->>EspressifToolStartup: Accept/Decline
alt Accept
EspressifToolStartup->>EclipseIDE: Open ESPIDFManagerEditor with EimJson
end
end
EspressifToolStartup->>EimJsonStateChecker: wasModifiedSinceLastRun()
alt Modified
EspressifToolStartup->>User: Show info dialog about EIM JSON change
end
EspressifToolStartup->>EimJsonWatchService: addEimJsonChangeListener()
end
deactivate EclipseIDE
Possibly related PRs
Suggested reviewers
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 28
🧹 Nitpick comments (24)
.github/workflows/ci.yml (1)
43-45: Remove trailing spaces
There are trailing spaces on thedistributionandcachelines. Cleaning these up improves file hygiene.- distribution: 'temurin' - cache: 'maven' + distribution: 'temurin' + cache: 'maven'🧰 Tools
🪛 YAMLlint (1.35.1)
[error] 43-43: trailing spaces
(trailing-spaces)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/messages.properties (1)
1-7: Message keys naming may need adjustment.The message keys have the prefix "InstallToolsHandler_" but according to the PR summary, the
InstallToolsHandlerclass has been replaced with a newSetupToolsInIdeclass. Consider renaming the message keys to reflect the new class name for better maintainability.-InstallToolsHandler_CopyingOpenOCDRules=Copying OpenOCD Rules -InstallToolsHandler_OpenOCDRulesCopyPaths=Copying File: %s to destination: %s -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 -InstallToolsHandler_OpenOCDRulesCopied=Rules Copied to system +SetupToolsInIde_CopyingOpenOCDRules=Copying OpenOCD Rules +SetupToolsInIde_OpenOCDRulesCopyPaths=Copying File: %s to destination: %s +SetupToolsInIde_OpenOCDRulesCopyWarning=Warning +SetupToolsInIde_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 +SetupToolsInIde_OpenOCDRulesNotCopied=Rules Not Copied to system +SetupToolsInIde_OpenOCDRulesCopyError=Unable to copy rules for OpenOCD to system directory, try running the eclipse with sudo command +SetupToolsInIde_OpenOCDRulesCopied=Rules Copied to systembundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java (1)
56-62: Integration with new EIM JSON-based configuration model.The changes correctly integrate the editor with the new JSON-driven configuration workflow by passing the EimJson object to the ESPIDFMainTablePage singleton and triggering initial setup when appropriate.
Consider adding null checks for the editor input to prevent potential NullPointerExceptions:
-ESPIDFMainTablePage espidfMainTablePage = ESPIDFMainTablePage - .getInstance(((EimEditorInput) getEditorInput()).getEimJson()); +IEditorInput input = getEditorInput(); +if (input instanceof EimEditorInput) { + EimEditorInput eimInput = (EimEditorInput) input; + ESPIDFMainTablePage espidfMainTablePage = ESPIDFMainTablePage + .getInstance(eimInput.getEimJson()); + espidfMainTablePage.createPage(parent); + if (eimInput.isFirstStartup()) { + espidfMainTablePage.setupInitialEspIdf(); + } +}tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java (1)
31-41: Test refactored to use the new ESP-IDF Manager editor workflowThe test has been updated to use the new EIM-centric workflow, which aligns with the broader refactoring of the tool management system. Instead of manually interacting with installation dialogs, it now works with the ESP-IDF Manager editor directly.
However, the timeout value set for waiting is extremely large (99000000 ms ≈ 27.5 hours).
Consider using a more reasonable timeout value or making it configurable:
-TestWidgetWaitUtility.waitUntilViewContains(bot, "Tools Setup complete", consoleView, 99000000); +TestWidgetWaitUtility.waitUntilViewContains(bot, "Tools Setup complete", consoleView, 300000); // 5 minute timeoutAlternatively, you could define the timeout as a constant with a descriptive name:
+private static final int TOOLS_SETUP_TIMEOUT_MS = 300000; // 5 minute timeout -TestWidgetWaitUtility.waitUntilViewContains(bot, "Tools Setup complete", consoleView, 99000000); +TestWidgetWaitUtility.waitUntilViewContains(bot, "Tools Setup complete", consoleView, TOOLS_SETUP_TIMEOUT_MS);bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (2)
15-15: Consider using a mutable list for initializationThe field is initialized with an immutable list via
Collections.emptyList(). This could causeUnsupportedOperationExceptionif any code attempts to directly modify this list without first replacing it through the setter.- private List<IdfInstalled> idfInstalled = Collections.emptyList(); + private List<IdfInstalled> idfInstalled = new ArrayList<>();
37-40: Consider returning a defensive copy of the listReturning the list reference directly allows external code to modify the internal state of this object, which could lead to unexpected behavior in a multi-threaded environment or when the object needs to maintain invariants.
public List<IdfInstalled> getIdfInstalled() { - return idfInstalled; + return new ArrayList<>(idfInstalled); }bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java (2)
7-7: Use Path API for file path handlingString concatenation for path construction may not handle path separators correctly across all systems. Consider using the
java.nio.file.PathAPI which provides better cross-platform path handling.- String EIM_POSIX_DIR = System.getProperty("user.home").concat("/.espressif/tools/"); //$NON-NLS-1$//$NON-NLS-2$ + String EIM_POSIX_DIR = Paths.get(System.getProperty("user.home"), ".espressif", "tools").toString() + File.separator; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
3-21: Add documentation for constantsThe interface lacks documentation explaining the purpose and usage of each constant. This makes maintenance more difficult and can lead to misuse of these constants.
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java (1)
12-12: Fix spelling in class nameThere is a typo in the class name: "Configuratin" should be "Configuration".
-public class EimIdfConfiguratinParser +public class EimIdfConfigurationParserbundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java (1)
1-4: Update copyright yearThe copyright statement shows year 2025, which is in the future. Update to the current year (2024).
-/******************************************************************************* - * Copyright 2025 Espressif Systems (Shanghai) PTE LTD. All rights reserved. - * Use is subject to license terms. - *******************************************************************************/ +/******************************************************************************* + * Copyright 2024 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java (3)
1-3: Update copyright year to match current year.The copyright year is set to 2025, which is in the future. It should be updated to the current year 2024.
-/******************************************************************************* - * Copyright 2025 Espressif Systems (Shanghai) PTE LTD. All rights reserved. - * Use is subject to license terms. +/******************************************************************************* + * Copyright 2024 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms.
33-52: Add preference flushing when detecting first run.When no last seen timestamp is found (first run), the method should update the timestamp to avoid repeatedly detecting it as a first run if Eclipse crashes before properly updating the timestamp later.
if (lastSeen == 0L) { // First run ever, don't treat as changed Logger.log("eim_idf.json detected, but no last seen timestamp — assuming first run."); //$NON-NLS-1$ + // Set initial timestamp to avoid repeatedly detecting first run + preferences.putLong(LAST_MODIFIED_PREF_KEY, lastModified); + try { + preferences.flush(); + } catch (BackingStoreException e) { + Logger.log(e); + } return false; }
47-47: Consider using message constants for logging messages.The hardcoded log message should ideally use a message constant from a Messages class for proper internationalization.
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java (3)
5-5: Remove unused import.The ArrayList import is not used anywhere in the code and should be removed.
-import java.text.MessageFormat; -import java.util.ArrayList; +import java.text.MessageFormat;
17-17: Typo in class name EimIdfConfiguratinParser.There's a spelling error in the class name (missing 'o' in 'Configuration').
-import com.espressif.idf.core.tools.EimIdfConfiguratinParser; +import com.espressif.idf.core.tools.EimIdfConfigurationParser;This should be fixed in the class name itself and all references to it.
46-57: Simplify EimJson initialization and improve error handling.The initialization of the empty EimJson object is redundant since you immediately try to populate it. Also, you should log more information about the error when JSON parsing fails.
-EimJson eimJson = new EimJson(); +EimJson eimJson; try { EimIdfConfiguratinParser eimIdfConfiguratinParser = new EimIdfConfiguratinParser(); eimJson = eimIdfConfiguratinParser.getEimJson(true); } catch (IOException e) { - Logger.log(e); + Logger.log("Failed to parse EIM JSON configuration: " + e.getMessage(), e); // Proceed with an empty EimJson object + eimJson = new EimJson(); }bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java (2)
72-85: Enhance equals method to consider EimJson content.The current implementation only compares the FILE_NAME constant, which means all instances of EimEditorInput will be equal regardless of their EimJson content. This could lead to unexpected behavior when multiple editors are open.
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } EimEditorInput that = (EimEditorInput) obj; - return FILE_NAME.equals(that.FILE_NAME); + // Since FILE_NAME is constant, also compare EimJson content if available + if (this.eimJson == null && that.eimJson == null) { + return true; + } + return (this.eimJson != null && that.eimJson != null && + this.eimJson.getIdfSelectedId() != null && + this.eimJson.getIdfSelectedId().equals(that.eimJson.getIdfSelectedId()));
87-91: Update hashCode to be consistent with equals.If you update the equals method to consider EimJson content, the hashCode method should also be updated to maintain the contract that equal objects have equal hash codes.
@Override public int hashCode() { - return FILE_NAME.hashCode(); + final int prime = 31; + int result = FILE_NAME.hashCode(); + result = prime * result + ((eimJson == null || eimJson.getIdfSelectedId() == null) ? 0 : + eimJson.getIdfSelectedId().hashCode()); + return result; }bundles/com.espressif.idf.sdk.config.core/src/com/espressif/idf/sdk/config/core/server/JsonConfigServer.java (1)
164-170: Consider using Map.Entry for enhanced type safety.Instead of using the raw Entry type, consider using Map.Entry for better type safety.
- for (Entry<String, String> entry : idfEnvironmentVariables.getEnvMap().entrySet()) + for (Map.Entry<String, String> entry : idfEnvironmentVariables.getEnvMap().entrySet())bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java (1)
89-92: Consider providing a method to update the ESP-IDF set flag.The class provides a method to check if ESP-IDF is set, but no method to update this flag. This would be useful for classes that need to modify this state.
public boolean isEspIdfSet() { return preferences.getBoolean(EimConstants.INSTALL_TOOLS_FLAG, false); } + + public void setEspIdfSet(boolean value) + { + preferences.putBoolean(EimConstants.INSTALL_TOOLS_FLAG, value); + }bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/EspressifGeneralStartup.java (1)
83-92: Null-check listener & remove redundant@SuppressWarnings
launchBarListenercan benullif events are fired beforehookLaunchBarListeners()finishes registering – rare, but possible during early start-up.
Also, thestatic-accesssuppression is unnecessary; we are calling an instance method.-@SuppressWarnings("static-access") -private void disableLaunchBarEvents() -{ - launchBarListener.setIgnoreTargetChange(true); -} +private void disableLaunchBarEvents() +{ + if (launchBarListener != null) + launchBarListener.setIgnoreTargetChange(true); +}Apply the same pattern to
enableLaunchBarEvents()and drop the@SuppressWarnings.bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1)
148-151: Typo in progress message
"Installing pyhton dependency web-socket"→"Installing Python dependency websocket-client".bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)
106-122: Blocking browser launch on UI thread
java.awt.Desktop.getDesktop().browse()may block while the platform launches the external browser.
Triggering this directly inside the SWT selection listener freezes the UI if the operation takes noticeable time, especially on Linux/Wayland.
Wrap the call inDisplay.getDefault().asyncExec()or, better, run it in a background job and useProgram.launch()from SWT which is non-blocking.bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (1)
95-100: Possible NPE when comparing installation IDs
isIdfInstalledActivedoes
idfInstalled.getId().equals(espIdfIdEim).
WhengetId()returnsnull, this throws.
UseObjects.equals(idfInstalled.getId(), espIdfIdEim)to be safe.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bundles/com.espressif.idf.ui/icons/tools/delete.pngis excluded by!**/*.png
📒 Files selected for processing (76)
.github/workflows/ci.yml(2 hunks).github/workflows/ci_windows.yml(1 hunks)bundles/com.espressif.idf.core/META-INF/MANIFEST.MF(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFCorePreferenceConstants.java(0 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java(2 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.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/toolchain/ESPToolChainManager.java(2 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/ToolInitializer.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/tools/watcher/EimJsonChangeListener.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/EspToolCommands.java(3 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java(3 hunks)bundles/com.espressif.idf.sdk.config.core/src/com/espressif/idf/sdk/config/core/server/JsonConfigServer.java(3 hunks)bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java(1 hunks)bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties(0 hunks)bundles/com.espressif.idf.ui/plugin.xml(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/EspressifGeneralStartup.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java(0 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SbomCommandDialog.java(3 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/help/ProductInformationHandler.java(1 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/preferences/EspresssifPreferencesPage.java(0 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeDataManager.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java(1 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/tools/watcher/EimJsonUiChangeHandler.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tracing/AppLvlTracingDialog.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/AbstractToolsHandler.java(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)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectSDKconfigTest.java(1 hunks)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectTest.java(0 hunks)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java(2 hunks)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/ProjectTestOperations.java(1 hunks)tests/pom.xml(1 hunks)
💤 Files with no reviewable changes (30)
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.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/messages.properties
- bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.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
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/GitWizardRepProgressMonitor.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/vo/VersionDetailsVO.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/IDFToolSet.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolSetConfigurationManager.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/preferences/EspresssifPreferencesPage.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/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/IDFCorePreferenceConstants.java
- tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectTest.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/ToolsInstallationJob.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/UpdateEspIdfHandler.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/ExportIDFTools.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.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/IDFNewToolsWizard.java
🧰 Additional context used
🧬 Code Graph Analysis (14)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)
ESPIDFMainTablePage(56-557)
tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectSDKconfigTest.java (1)
tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/ProjectTestOperations.java (1)
ProjectTestOperations(50-656)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-137)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (13)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)
Messages(15-42)bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-137)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java (1)
ToolInitializer(26-93)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1)
EimJson(8-47)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java (1)
EimJsonStateChecker(22-67)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java (1)
EimJsonWatchService(23-152)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (1)
IDFUtil(58-889)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/StringUtil.java (1)
StringUtil(11-25)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/MessageLinkDialog.java (1)
MessageLinkDialog(40-135)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/EclipseHandler.java (1)
EclipseHandler(21-79)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java (1)
ESPIDFManagerEditor(22-78)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java (1)
EimEditorInput(9-93)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java (1)
EimJsonUiChangeHandler(23-44)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1)
EimJson(8-47)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-137)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1)
EimJson(8-47)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (3)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1)
SetupToolsInIde(53-564)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)
ESPIDFMainTablePage(56-557)bundles/com.espressif.idf.core/src/com/espressif/idf/core/resources/OpenDialogListenerSupport.java (1)
OpenDialogListenerSupport(9-22)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/Messages.java (2)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java (1)
Messages(9-63)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)
Messages(15-42)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/StringUtil.java (1)
StringUtil(11-25)
bundles/com.espressif.idf.sdk.config.core/src/com/espressif/idf/sdk/config/core/server/JsonConfigServer.java (4)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/ProcessBuilderFactory.java (1)
ProcessBuilderFactory(16-163)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (1)
IDFUtil(58-889)bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-137)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/StringUtil.java (1)
StringUtil(11-25)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java (2)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-137)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1)
EimJson(8-47)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (7)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java (1)
EimIdfConfiguratinParser(12-47)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1)
SetupToolsInIde(53-564)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (1)
ToolsUtility(25-101)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1)
EimJson(8-47)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java (1)
IdfInstalled(5-80)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/IDFConsole.java (1)
IDFConsole(27-100)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (1)
SetupToolsJobListener(28-88)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (2)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-137)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java (1)
IdfInstalled(5-80)
🪛 YAMLlint (1.35.1)
.github/workflows/ci_windows.yml
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
.github/workflows/ci.yml
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
[warning] 22-22: wrong indentation: expected 6 but found 4
(indentation)
[error] 29-29: syntax error: found character '\t' that cannot start any token
(syntax)
[error] 43-43: trailing spaces
(trailing-spaces)
🪛 actionlint (1.7.4)
.github/workflows/ci.yml
19-19: 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)
19-19: 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)
25-25: 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 (3)
- GitHub Check: build_macos
- GitHub Check: build_macos
- GitHub Check: build_linux
🔇 Additional comments (55)
.github/workflows/ci_windows.yml (1)
8-14: Approve expansion of CI triggers
Addingrelease/**alongsidemasterfor bothpushandpull_requestensures CI runs on release branches as intended.🧰 Tools
🪛 YAMLlint (1.35.1)
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
.github/workflows/ci.yml (3)
17-20: Job renamed tobuild_linuxand custom runners
The job name change frombuildtobuild_linuxis clear and descriptive. Confirm that the self-hosted runner labelseclipseandBrnoUBU0004are defined in your Actionlint configuration or consider replacing them with standard labels to avoid runner-label validation errors.🧰 Tools
🪛 actionlint (1.7.4)
19-19: 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)
19-19: 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)
29-33: Approve use ofespressif/install-esp-idf-action@v1
Switching from manual checkout of ESP-IDF to the officialinstall-esp-idf-action@v1streamlines environment setup and aligns with the new EIM-based tool management.🧰 Tools
🪛 YAMLlint (1.35.1)
[error] 29-29: syntax error: found character '\t' that cannot start any token
(syntax)
8-14: Approve trigger expansion for release branches
Includingrelease/**in the trigger patterns matches the Windows workflow and ensures consistent CI coverage for release branches.🧰 Tools
🪛 YAMLlint (1.35.1)
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
tests/com.espressif.idf.ui.test/configs/default-test-linux.properties (1)
10-10:Details
❓ Verification inconclusive
Verify updated ESP-IDF test path
The path fordefault.env.esp.idf.pathnow points todependencies/idf-tools/v5.3/esp-idf. Ensure that theinstall-esp-idf-action@v1step installs ESP-IDF to this exact location. You can add a CI check:
🏁 Script executed:
#!/bin/bash if [ ! -d "$GITHUB_WORKSPACE/dependencies/idf-tools/v5.3/esp-idf" ]; then echo "ERROR: ESP-IDF path not found at expected location" exit 1 fiLength of output: 173
Confirm ESP-IDF installation path in CI
We’ve updateddefault.env.esp.idf.pathto point atdependencies/idf-tools/v5.3/esp-idf. Make sure yourinstall-esp-idf-action@v1step installs ESP-IDF into exactly that directory under$GITHUB_WORKSPACE. For example, add a CI check:#!/bin/bash ESP_IDF_DIR="${GITHUB_WORKSPACE}/dependencies/idf-tools/v5.3/esp-idf" if [ ! -d "$ESP_IDF_DIR" ]; then echo "ERROR: ESP-IDF not found at $ESP_IDF_DIR" exit 1 fi• File: tests/com.espressif.idf.ui.test/configs/default-test-linux.properties
• Line: 10 (default.env.esp.idf.path)Please verify this path in your workflow and adjust if needed.
bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java (2)
54-54: Addition of ESP_IDF_EIM_ID constant looks good.This new environment variable constant is consistent with the naming pattern and will support the EIM-based configuration approach.
133-133: Simplified environment map initialization.The code now uses
System.getenv()directly instead of a utility method, which aligns with the broader environment variable handling refactoring in the codebase. This approach is more straightforward and maintains consistency with the changes made in related classes.bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/Messages.java (1)
1-27: Class structure follows NLS pattern correctly.The Messages class follows the standard Eclipse NLS pattern with proper static initialization. If you update the message keys in the properties file as suggested in the previous comment, remember to update the constant names here as well.
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/NewProjectHandlerUtil.java (2)
19-19: Import updated to reflect architectural changes.Replacing the import of
InstallToolsHandlerwithEimConstantsaligns with the broader refactoring of the tool management system.
38-38: Preference key updated for tool installation flag.The change from using
InstallToolsHandler.INSTALL_TOOLS_FLAGtoEimConstants.INSTALL_TOOLS_FLAGaligns with the new EIM-based tool management approach. This ensures consistency with the new setup infrastructure.tests/pom.xml (1)
33-33: System property added for test automationAdding the
-DtestRun=trueflag to the JVM arguments enables conditional behavior in the IDE during automated tests. This is a well-structured approach for controlling UI behavior during test runs.bundles/com.espressif.idf.core/META-INF/MANIFEST.MF (1)
48-48: Properly exposing new watcher packageThe addition of
com.espressif.idf.core.tools.watcherto the exported packages list correctly makes the new EIM JSON file monitoring functionality accessible to other bundles in the plugin system.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeDataManager.java (1)
208-208: Environment variable handling standardizationSwitching to
System.getenv()standardizes environment variable handling across the codebase, aligning with similar changes made throughout the PR. This simplifies the codebase by using Java's standard API directly instead of custom utility methods.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tracing/AppLvlTracingDialog.java (1)
301-301: Consistent environment variable managementUsing
System.getenv()here maintains consistency with similar changes throughout the PR. The approach of creating a HashMap copy still allows for potential environment customization before passing to the process builder if needed.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/help/ProductInformationHandler.java (1)
134-134: Consistent environment variable sourcing approach.The change from custom environment map to using
System.getenv()aligns with the broader standardization of environment variable handling across the codebase. This simplifies the code and reduces maintenance overhead.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SbomCommandDialog.java (3)
286-287: Standardized environment variable handling.Good change to use the standard Java system environment variables instead of a custom environment map. Creating a mutable HashMap copy is the correct approach since
System.getenv()returns an unmodifiable map.
438-439: Consistent environment variable approach across methods.This change maintains consistency with the previous method by using the same standardized approach to environment variables.
453-454: Completed standardization of environment variable handling.This completes the standardization of environment variable handling in all three methods of this class. The consistent approach improves maintainability.
bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/EspToolCommands.java (3)
29-29: Standardized environment handling for process builders.Good approach using
putAllon the ProcessBuilder's environment map, which is already mutable. This directly incorporates the system environment variables without needing to create an intermediate HashMap.
38-38: Consistent process environment handling.Maintains the same standardized approach used in the previous method. The consistency across related methods is good for maintainability.
47-47: Completed environment standardization for all process methods.This completes the standardization across all three process creation methods in the class. Using
System.getenv()directly is more straightforward than the previous approach.tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/ProjectTestOperations.java (1)
582-582: Increased timeout for console output verification.The timeout was increased from 3 seconds to 30 seconds. This change is likely necessary due to the new EIM-based workflow which might take longer to complete operations.
Consider adding a comment explaining why the timeout needed to be increased to help future maintainers understand the rationale behind this change.
tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectSDKconfigTest.java (2)
185-185: Same 15-minute timeout applied to context menu method.This method also has the timeout increased to 15 minutes for the same operation, suggesting a systematic change in how SDK configuration loading works in the new architecture.
Are there any plans to improve the performance in future releases so that these extreme timeouts won't be necessary?
178-178:Details
❓ Verification inconclusive
The timeout value has been significantly increased to 15 minutes.
The timeout for waiting for the SDK Configuration tab to appear has been increased from what appears to be 5 seconds to 15 minutes (900,000ms). While this might be necessary for the new EIM-based workflow, such a long timeout could potentially mask underlying performance issues.
Could you:
- Explain why such a long timeout is necessary?
- Confirm whether there's any user feedback during this potentially lengthy wait?
- Consider if there might be a better approach, such as waiting for a specific event rather than using a fixed timeout?
🏁 Script executed:
#!/bin/bash # Check for any logging or feedback mechanism during the wait period grep -r "waitForSDKConfigurationTab" --include="*.java" . grep -r "TestWidgetWaitUtility" --include="*.java" .Length of output: 8896
🏁 Script executed:
#!/bin/bash # Show implementation and any logging inside waitForSDKConfigurationTab grep -R -n -C5 "waitForSDKConfigurationTab" tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/common/utility/TestWidgetWaitUtility.javaLength of output: 492
🏁 Script executed:
#!/bin/bash # Retrieve full implementation of waitForSDKConfigurationTab sed -n '273,330p' tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/common/utility/TestWidgetWaitUtility.javaLength of output: 931
Excessive maximum timeout in SDK Configuration test
The two calls to
TestWidgetWaitUtility.waitForSDKConfigurationTab(bot, 900_000);raise the max wait from a few seconds to 15 minutes. While
waitUntilis reactive (it ends as soon as the tab is active), a 15-minute ceiling can mask hangs or environment issues and there’s no intermediate feedback during that period.Could you:
- Explain why a 15-minute maximum is required under the new EIM workflow?
- Confirm how the test runner or user sees progress (any logs or UI cues) while waiting?
- Consider reducing the ceiling, adding interim logging, or surfacing a “loading…” indicator so failures don’t stall pipelines for so long?
bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.java (1)
480-481:Details
❓ Verification inconclusive
Removal of IDF_TOOLS_PATH from environment variables.
The code no longer explicitly passes the
IDF_TOOLS_PATHenvironment variable to the build process. This aligns with the broader changes in environment variable handling where standard system environment variables are used instead of custom environment maps.Can you confirm that the build process will still correctly access the
IDF_TOOLS_PATHthrough the system environment? This change seems to be part of a larger refactoring effort, but it's important to ensure the build functionality remains intact.
🏁 Script executed:
#!/bin/bash # Check for other uses of IDF_TOOLS_PATH in the codebase grep -r "IDF_TOOLS_PATH" --include="*.java" . # Check how environment variables are now handled grep -r "System.getenv" --include="*.java" . | grep -i "idf"Length of output: 5874
I want to confirm how
startBuildProcessconstructs the process environment—whether it merges the full system environment or only uses the provided vars. Let’s inspect its implementation:
🏁 Script executed:
#!/bin/bash grep -n -C3 "startBuildProcess" bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.javaLength of output: 1031
Let’s inspect how
startBuildProcessis implemented—in particular, whether it merges the full system environment with the supplied vars or only uses the latter.
🏁 Script executed:
#!/bin/bash grep -n -C5 "startBuildProcess" bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/CMakeBuildConfiguration.javaLength of output: 250
I need to inspect the
startBuildProcessimplementation inIDFBuildConfiguration.javato confirm how it handles environment variables:
🏁 Script executed:
#!/bin/bash grep -n -C10 "startBuildProcess" bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.javaLength of output: 2925
I need to locate the
startBuildProcessmethod definition to verify how it merges (or replaces) environment variables:
🏁 Script executed:
#!/bin/bash # Find the method signature for startBuildProcess in IDFBuildConfiguration.java grep -R -n "Process startBuildProcess" bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.javaLength of output: 131
Let’s search the entire repo for the
startBuildProcessdefinition to locate its implementation:
🏁 Script executed:
#!/bin/bash grep -R -n "startBuildProcess" .Length of output: 598
I need to identify the class hierarchy to locate
startBuildProcess. Let’s list the build package and inspect theIDFBuildConfigurationdeclaration:
🏁 Script executed:
#!/bin/bash echo "Build package files:" ls bundles/com.espressif.idf.core/src/com/espressif/idf/core/build echo echo "IDFBuildConfiguration declaration:" grep -n "class IDFBuildConfiguration" bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.javaLength of output: 769
Confirmation needed: ensure
IDF_TOOLS_PATHis picked up from the system environmentWe’ve removed the explicit passing of
IDF_TOOLS_PATHto the build process—now onlyPYTHONUNBUFFERED(and any other vars) are passed tostartBuildProcess. SincestartBuildProcessis inherited fromCBuildConfiguration, please verify that:
CBuildConfiguration.startBuildProcess(...)mergesSystem.getenv()into the child process’s environment rather than replacing it.- Under normal usage,
IDF_TOOLS_PATHis present inSystem.getenv()when the build runs.- No code path calls
startBuildProcess(...)with an empty or minimal env array without first seeding it with system vars.Without this confirmation, builds may lose access to the tools in
IDF_TOOLS_PATH.bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonChangeListener.java (1)
7-17: Well-designed interface for the new EIM architecture.This interface follows good design principles with a focused single responsibility, clear method signature, and descriptive naming. It will serve as an important component in the new EIM JSON-driven workflow, allowing components to react to configuration changes.
bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java (1)
158-158: Environment variable handling standardized to use System.getenv()This change aligns with the broader refactoring across the codebase to use
System.getenv()directly instead of custom environment maps viaIDFUtil.getSystemEnv(). This simplifies environment handling and creates more consistent behavior.bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java (2)
180-181: Improved directory filtering to prevent potential issuesThe refactored method now properly filters out non-existent paths and non-directory entries, which is a good defensive programming practice. This will prevent potential issues when these paths are used to find toolchains later in the code.
319-319: Environment variable handling standardized to use System.getenv()This change aligns with the broader refactoring across the codebase to use
System.getenv()directly instead of custom environment maps fromIDFUtil. This creates more consistent behavior in environment variable handling.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/AbstractToolsHandler.java (1)
144-147: Environment variable handling standardizedThe code now uses
System.getenv()directly instead of a custom environment map fromIDFUtil.getSystemEnv(). This aligns with the broader refactoring of environment variable handling across the codebase.Also note that the removal of the
IDF_GITHUB_ASSETSandPIP_EXTRA_INDEX_URLenvironment variables (which were previously set from preferences) is part of the cleanup of deprecated or unused environment configuration related to tool installation URLs.bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java (3)
37-39: Appropriate message constants added for EIM-related notifications.These new message constants properly support the EIM-based workflow by providing standardized messages for notifying users when EIM tooling is missing.
42-44: LGTM - Clear notification messages for ESP-IDF workspace state.These message constants appropriately inform users when there's no active ESP-IDF in the workspace, which is essential for the new EIM-centric workflow.
45-52: Well-structured message constants for configuration migration.These constants provide a complete set of messages for guiding users through the old configuration export process, covering all necessary dialog states (title, selection, success, and failure messages).
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (4)
28-37: Class correctly refactored to work with SetupToolsInIde.The class has been properly renamed and updated to store a reference to the SetupToolsInIde job it's listening to. The constructor parameters and member initialization align with the new architecture.
53-60: Good addition of rollback mechanism for error handling.The listener now correctly checks the job result severity and invokes rollback on the SetupToolsInIde job if it failed, which provides a clean recovery mechanism for installation failures.
61-68: Successfully updated preference flag to use EimConstants.The code correctly uses the new EimConstants.INSTALL_TOOLS_FLAG instead of the removed InstallToolsHandler constant, properly aligning with the refactored architecture.
79-86: Improved UI thread handling with async execution.Moving the UI refresh operations to run asynchronously on the UI thread is a good practice that prevents blocking the job thread and improves responsiveness.
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java (1)
1-80: Well-structured POJO for ESP-IDF installation representation.This is a clean, well-structured value object class that represents an installed ESP-IDF instance. The Gson
@Exposeannotations properly mark fields for JSON serialization/deserialization, which aligns with the JSON-driven configuration approach mentioned in the PR summary.bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties (1)
22-41: Good user guidance messages for ESP-IDF installation and configuration.These new message keys provide clear guidance to users about ESP-IDF installation status, configuration migration, and actions needed. The messages are well-structured with placeholders for dynamic content and include HTML formatting for hyperlinks where appropriate.
bundles/com.espressif.idf.ui/plugin.xml (1)
546-550: Updated startup classes to match new architecture.The change replaces the previous startup classes with new
EspressifGeneralStartupandEspressifToolStartupclasses. This aligns with the PR's objective to refactor the tool management system and move to a JSON-driven configuration approach.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties (1)
5-12: Simplified UI messages focused on ESP-IDF Manager.The changes streamline the message keys to focus on the ESP-IDF Manager UI elements and notifications, replacing the previous detailed installation messages. This reflects the architectural shift from wizard-driven tool installation to a JSON-based configuration model.
bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (2)
212-235: Good addition of overloaded method for Python environment path resolution.This new overloaded method for resolving Python environment paths is well-implemented and supports the new EIM-based workflow. It properly handles platform-specific subdirectories and has appropriate fallback logic.
802-803: Updated to use standard system environment.The change to use
System.getenv()directly instead of a custom environment map is consistent with the PR's goal of standardizing environment variable handling across the codebase.bundles/com.espressif.idf.sdk.config.core/src/com/espressif/idf/sdk/config/core/server/JsonConfigServer.java (2)
95-127: Well-refactored process launching with improved error handling.The process launching code has been nicely refactored to use a more modular approach with better encapsulation:
- Environment setup is extracted to dedicated methods
- Arguments are built incrementally for better readability
- The ProcessBuilderFactory encapsulates process creation
- Exception handling is broadened to catch all exceptions
These changes improve maintainability and make the code more robust.
134-139: Good method extraction for environment preparation.Extracting environment setup into a dedicated method improves code organization and reusability.
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java (6)
1-44: Well-designed file watcher implementation with proper threading.The EimJsonWatchService is well implemented with:
- Proper daemon thread setup
- Platform-specific directory path detection
- Appropriate watch event registration
- Clean initialization with logging
46-67: Good singleton pattern implementation.The singleton pattern is implemented using the thread-safe initialization-on-demand holder idiom, which is a best practice for singleton creation in Java.
69-80: Thread-safe listener collection implemented correctly.Using CopyOnWriteArrayList for listeners and null-checking before adding listeners is a good practice for concurrent access patterns.
82-127: Well-implemented event processing with proper error handling.The run method contains proper exception handling for:
- InterruptedException with thread interruption
- ClosedWatchServiceException
- OVERFLOW event filtering
- Watch key validity checking
The pattern matching syntax for context objects is modern and clean.
128-138: Good resource cleanup in the watch service.The code properly closes the WatchService in a try-catch block, which is essential for resource management.
140-151: Well-designed thread termination methods.The interrupt and shutdown methods properly set the running flag to false before calling super.interrupt(), ensuring clean thread termination.
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java (3)
1-36: Well-structured initialization class with clear responsibilities.The ToolInitializer class is well-designed with appropriate field declarations, constructor, and clear purpose as indicated in the class javadoc.
60-69: Good file operation handling with exception propagation.The exportOldConfigIfNeeded method correctly:
- Checks for file existence before attempting to copy
- Uses Files.copy with appropriate StandardCopyOption
- Propagates IOException to caller for proper handling
- Updates preferences to track the export operation
82-87:Details
❓ Verification inconclusive
Consider more robust path handling for cross-platform compatibility.
The isEimIdfJsonPresent method relies on platform-specific path constants. Consider adding a unit test to verify this works correctly across different operating systems.
🏁 Script executed:
#!/bin/bash # Check if the platform-specific path constants are defined correctly echo "Checking EimConstants path definitions..." ast-grep --pattern $'String EIM_WIN_PATH = $_;$\nString EIM_POSIX_PATH = $_;'Length of output: 170
🏁 Script executed:
#!/bin/bash # Locate the EimConstants class and inspect the path constants echo "Finding EimConstants class file..." EC_FILE=$(rg -l "class EimConstants") if [ -z "$EC_FILE" ]; then echo "EimConstants class not found." exit 1 fi echo "Found EimConstants at: $EC_FILE" echo echo "EIM_WIN_PATH definition:" grep -n "EIM_WIN_PATH" "$EC_FILE" echo echo "EIM_POSIX_PATH definition:" grep -n "EIM_POSIX_PATH" "$EC_FILE"Length of output: 213
Strengthen cross-platform path resolution and add tests
I wasn’t able to locate the
EimConstantsdefinitions in the repo, so please confirm thatEIM_WIN_PATHandEIM_POSIX_PATHare defined correctly (and cover all supported OS variants). In addition:
Consider using
java.nio.file.Path/PathsandFiles.exists(...)instead of hard-coded string constants to build the path (e.g.,Path eimJson = Paths.get(System.getProperty("user.home"), ".espressif", "idf.json"); return Files.exists(eimJson);).
Add a lightweight unit test (e.g. with JUnit and System rules or Mockito) to simulate different
Platform.getOS()values and verify that the detection logic resolves the expected file locations on both Windows and POSIX.This will make maintenance easier and ensure consistent behavior across environments.
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)
23-31: Remember to add the new keys to the properties bundle
EspIdfManagerNameCol,IDFGuideLinkLabel_Text, and the new EIM-JSON messages must exist incom.espressif.idf.ui.tools.messages.properties; otherwiseNLSwill log missing-key errors at runtime.
| branches: | ||
| - master | ||
| - release/** | ||
| pull_request: | ||
| branches: [ master ] | ||
| branches: | ||
| - master | ||
| - release/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix YAML indentation under triggers
Indentation of list items under both push.branches and pull_request.branches is off by one space (5 vs. 6), which can lead to malformed YAML or unexpected behavior.
Proposed patch:
on:
push:
- branches:
- - master
- - release/**
+ branches:
+ - master
+ - release/**
pull_request:
- branches:
- - master
- - release/**
+ branches:
+ - master
+ - release/**📝 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.
| branches: | |
| - master | |
| - release/** | |
| pull_request: | |
| branches: [ master ] | |
| branches: | |
| - master | |
| - release/** | |
| on: | |
| push: | |
| branches: | |
| - master | |
| - release/** | |
| pull_request: | |
| branches: | |
| - master | |
| - release/** |
🧰 Tools
🪛 YAMLlint (1.35.1)
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
| - name: Set up Python | ||
| uses: actions/setup-python@v2 | ||
| with: | ||
| python-version: '3.10' | ||
| python-version: '3.10' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update Python setup action to latest version
The workflow uses actions/setup-python@v2, which is outdated. Align with other workflows and benefit from bug fixes by upgrading to:
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4📝 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.
| - name: Set up Python | |
| uses: actions/setup-python@v2 | |
| with: | |
| python-version: '3.10' | |
| python-version: '3.10' | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.10' |
🧰 Tools
🪛 actionlint (1.7.4)
25-25: 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)
| branches: | ||
| - master | ||
| - release/** | ||
| pull_request: | ||
| branches: [ master ] | ||
| branches: | ||
| - master | ||
| - release/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix YAML indentation under triggers
The list items for push.branches and pull_request.branches are mis-indented (5 spaces instead of 6). Correcting this will prevent YAML parsing issues.
on:
push:
- branches:
- - master
- - release/**
+ branches:
+ - master
+ - release/**
pull_request:
- branches:
- - master
- - release/**
+ branches:
+ - master
+ - release/**🧰 Tools
🪛 YAMLlint (1.35.1)
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
|
|
||
| String EIM_POSIX_DIR = System.getProperty("user.home").concat("/.espressif/tools/"); //$NON-NLS-1$//$NON-NLS-2$ | ||
|
|
||
| String EIM_WIN_DIR = "C:\\Espressif\\tools\\"; //$NON-NLS-1$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid hardcoding installation paths
The Windows installation directory is hardcoded, which may not respect user customizations or non-standard installation locations. Consider using environment variables or configuration settings to allow for customization.
|
|
||
| public EimJson getEimJson(boolean reload) throws IOException | ||
| { | ||
| if (reload) | ||
| { | ||
| load(); | ||
| } | ||
|
|
||
| if (eimJson == null) | ||
| { | ||
| load(); | ||
| } | ||
|
|
||
| return eimJson; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve method efficiency and thread safety
The getEimJson method could potentially perform duplicate loads if both reload is true and eimJson is null. Additionally, there are no synchronization mechanisms to ensure thread safety.
-public EimJson getEimJson(boolean reload) throws IOException
+public synchronized EimJson getEimJson(boolean reload) throws IOException
{
- if (reload)
+ if (reload || eimJson == null)
{
load();
}
-
- if (eimJson == null)
- {
- load();
- }
return eimJson;
}| { | ||
| removeColumn.getColumn().dispose(); | ||
| } | ||
|
|
||
| if (nameColumn != null && nameColumn.getColumn() != null) | ||
| { | ||
| nameColumn.getColumn().dispose(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential Colour leak when columns are recreated
setupColumns() disposes TableViewerColumns but the associated ColumnLabelProvider (which owns an SWT Color) is not disposed until the viewer is disposed.
Because setupColumns() can be invoked repeatedly (refreshEditorUI()), many Color objects can accumulate.
Add labelProvider.dispose() before the column is disposed, or cache/re-use a single label-provider instance.
| case 1: | ||
| cell.setText(idfToolSet.getIdfVersion()); | ||
| cell.setText(getIdfVersion(idfInstalled)); | ||
| break; | ||
| case 2: | ||
| cell.setText(idfToolSet.getIdfLocation()); | ||
| cell.setText(idfInstalled.getName()); | ||
| break; | ||
| case 3: | ||
| cell.setText(idfInstalled.getPath()); | ||
| break; | ||
| case 4: | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| private String getIdfVersion(IdfInstalled idfInstalled) | ||
| { | ||
| String version = ToolsUtility.getIdfVersion(idfInstalled, eimJson.getGitPath()); | ||
| return version; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heavy external process executed on UI thread for every cell refresh
getIdfVersion() launches a shell, executes the activation script and waits for completion.
Because update() runs in the SWT UI thread, the table freezes while every row (and every repaint) spawns a new process – catastrophic for responsiveness on large lists.
Cache the version once per IdfInstalled (e.g., in a Map<IdfInstalled,String>), and/or compute it in a background Job then update the viewer asynchronously.
| public static ESPIDFMainTablePage getInstance(EimJson eimJson) | ||
| { | ||
| if (espidfMainTablePage == null) | ||
| { | ||
| espidfMainTablePage = new ESPIDFMainTablePage(); | ||
| } | ||
|
|
||
| ESPIDFMainTablePage.eimJson = eimJson; | ||
| return espidfMainTablePage; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Singleton keeps mutable global state – risk of stale data & race-conditions
eimJson is held in a static field that is overwritten every time getInstance() is called.
Because the method is not synchronized, concurrent calls from UI thread / background jobs can race, and previously opened editors might suddenly see a different JSON instance than they were created with.
Consider either
- removing the static field and passing the current
EimJsonthrough explicit method parameters, or - synchronising access and cloning the model to avoid unexpected mutation.
| nameColumn = new TableViewerColumn(tableViewer, SWT.NONE); | ||
| nameColumn.getColumn().setText(Messages.EspIdfManagerNameCol); | ||
| nameColumn.setLabelProvider(new IdfManagerTableColumnLabelProvider()); | ||
| setComparatorForCols(nameColumn, colIndex++); | ||
| tableColumnLayout.setColumnData(nameColumn.getColumn(), new ColumnWeightData(3, 50, true)); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Comparator index/order mismatch leads to wrong sorting
The comparator is told that versionColumn is index 0, nameColumn is index 1 and locationColumn is index 2, but the compare() implementation (lines 530-545) assumes 0 → name, 1 → path, 2 → active‐state.
Clicking “Version” currently sorts by name, etc.
Patch either the index assignment or the switch logic.
A minimal fix is shown below.
@@
- switch (propertyIndex)
+ switch (propertyIndex)
{
- case 0: // Version column
- rc = ToolsUtility.getIdfVersion(p1, eimJson.getGitPath())
- .compareTo(
- ToolsUtility.getIdfVersion(p2, eimJson.getGitPath()));
+ case 0: // Version column
+ rc = ToolsUtility
+ .getIdfVersion(p1, eimJson.getGitPath())
+ .compareTo(
+ ToolsUtility.getIdfVersion(p2, eimJson.getGitPath()));
break;
- case 1:
- rc = p1.getPath().compareTo(p2.getPath()); // Name column
+ case 1: // Name column
+ rc = p1.getName().compareTo(p2.getName());
break;
- case 2:
- Boolean p1State = ToolsUtility.isIdfInstalledActive(p1); // Location column
- Boolean p2State = ToolsUtility.isIdfInstalledActive(p2);
- rc = p1State.compareTo(p2State);
+ case 2: // Location column
+ rc = p1.getPath().compareTo(p2.getPath());
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.
| nameColumn = new TableViewerColumn(tableViewer, SWT.NONE); | |
| nameColumn.getColumn().setText(Messages.EspIdfManagerNameCol); | |
| nameColumn.setLabelProvider(new IdfManagerTableColumnLabelProvider()); | |
| setComparatorForCols(nameColumn, colIndex++); | |
| tableColumnLayout.setColumnData(nameColumn.getColumn(), new ColumnWeightData(3, 50, true)); | |
| // … somewhere inside your compare(p1, p2, propertyIndex) method … | |
| switch (propertyIndex) | |
| { | |
| case 0: // Version column | |
| rc = ToolsUtility | |
| .getIdfVersion(p1, eimJson.getGitPath()) | |
| .compareTo( | |
| ToolsUtility.getIdfVersion(p2, eimJson.getGitPath())); | |
| break; | |
| case 1: // Name column | |
| rc = p1.getName().compareTo(p2.getName()); | |
| break; | |
| case 2: // Location column | |
| rc = p1.getPath().compareTo(p2.getPath()); | |
| break; | |
| } |
| public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath) | ||
| { | ||
| File homeDir = new File(ESPRESSIF_HOME_DIR); | ||
| if (!homeDir.exists()) | ||
| { | ||
| return false; | ||
| } | ||
| String activationScript = idfInstalled.getActivationScript(); | ||
| String espIdfVersion = null; | ||
|
|
||
| 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; | ||
| } | ||
|
|
||
| public static void removeToolDirectory(String toolName) throws IOException | ||
| { | ||
| File toolDirectory = new File(ESPRESSIF_HOME_TOOLS_DIR.concat(FORWARD_SLASH).concat(toolName)); | ||
| if (!toolDirectory.exists()) | ||
| try | ||
| { | ||
| return; | ||
| } | ||
| FileUtil.deleteDirectory(toolDirectory); | ||
| } | ||
| // Determine the command to execute based on the OS | ||
| List<String> args = getExportScriptCommand(activationScript); | ||
| String[] command = args.toArray(new String[args.size()]); | ||
| // Execute the script | ||
| ProcessBuilder processBuilder = new ProcessBuilder(command); | ||
| processBuilder.directory(new File(activationScript).getParentFile()); | ||
| processBuilder.redirectErrorStream(true); | ||
|
|
||
| public static String getFileExtension(String filename) | ||
| { | ||
| return Optional.ofNullable(filename).filter(f -> f.contains(".")) //$NON-NLS-1$ | ||
| .map(f -> f.substring(filename.lastIndexOf(".") + 1)).get(); //$NON-NLS-1$ | ||
| } | ||
| Process process = processBuilder.start(); | ||
|
|
||
| public static void extractZip(String zipFilePath, String extractDirectory) | ||
| { | ||
| InputStream inputStream = null; | ||
| try | ||
| { | ||
| Path filePath = Paths.get(zipFilePath); | ||
| inputStream = Files.newInputStream(filePath); | ||
| ArchiveStreamFactory archiveStreamFactory = new ArchiveStreamFactory(); | ||
| ArchiveInputStream archiveInputStream = archiveStreamFactory | ||
| .createArchiveInputStream(ArchiveStreamFactory.ZIP, inputStream); | ||
| ArchiveEntry archiveEntry = null; | ||
| while ((archiveEntry = archiveInputStream.getNextEntry()) != null) | ||
| // Read the script output | ||
| try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) | ||
| { | ||
| Path path = Paths.get(extractDirectory, archiveEntry.getName()); | ||
| File file = path.toFile(); | ||
| if (archiveEntry.isDirectory()) | ||
| { | ||
| if (!file.isDirectory()) | ||
| { | ||
| file.mkdirs(); | ||
| } | ||
| } | ||
| else | ||
| String line; | ||
| while ((line = reader.readLine()) != null) | ||
| { | ||
| File parent = file.getParentFile(); | ||
| if (!parent.isDirectory()) | ||
| { | ||
| parent.mkdirs(); | ||
| } | ||
| try (OutputStream outputStream = Files.newOutputStream(path)) | ||
| if (line.startsWith("ESP_IDF_VERSION=")) //$NON-NLS-1$ | ||
| { | ||
| IOUtils.copy(archiveInputStream, outputStream); | ||
| espIdfVersion = line.split("=")[1]; //$NON-NLS-1$ | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| catch (Exception e) | ||
| { | ||
| Logger.log(e); | ||
| } | ||
| } | ||
|
|
||
| public static void extractTarGz(String tarFile, String outputDir) | ||
| { | ||
| Path pathInput = Paths.get(tarFile); | ||
| Path pathOutput = Paths.get(outputDir); | ||
| try | ||
| { | ||
| TarArchiveInputStream tararchiveinputstream = new TarArchiveInputStream( | ||
| new GzipCompressorInputStream(new BufferedInputStream(Files.newInputStream(pathInput)))); | ||
|
|
||
| ArchiveEntry archiveentry = null; | ||
| while ((archiveentry = tararchiveinputstream.getNextEntry()) != null) | ||
| { | ||
| Path pathEntryOutput = pathOutput.resolve(archiveentry.getName()); | ||
| if (archiveentry.isDirectory()) | ||
| { | ||
| if (!Files.exists(pathEntryOutput)) | ||
| Files.createDirectories(pathEntryOutput); | ||
| } | ||
| else | ||
| { | ||
| Files.createDirectories(pathEntryOutput.getParent()); | ||
| Files.copy(tararchiveinputstream, pathEntryOutput, StandardCopyOption.REPLACE_EXISTING); | ||
| Runtime.getRuntime().exec("/bin/chmod 755 ".concat(pathEntryOutput.toString())); //$NON-NLS-1$ | ||
| } | ||
|
|
||
| } | ||
|
|
||
| tararchiveinputstream.close(); | ||
| process.waitFor(); | ||
| } | ||
| catch (Exception e) | ||
| { | ||
| Logger.log(e); | ||
| } | ||
| } | ||
|
|
||
| public static void extractTarXz(String tarFile, String outputDir) | ||
| { | ||
| Path pathOutput = Paths.get(outputDir); | ||
| Map<Path, Path> symLinks = new HashMap<>(); | ||
| Map<Path, Path> hardLinks = new HashMap<>(); | ||
| try | ||
| { | ||
| FileInputStream fileInputStream = new FileInputStream(tarFile); | ||
| BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); | ||
| XZInputStream xzInputStream = new XZInputStream(bufferedInputStream); | ||
| TarArchiveInputStream tararchiveinputstream = new TarArchiveInputStream(xzInputStream); | ||
| TarArchiveEntry archiveentry = null; | ||
| while ((archiveentry = tararchiveinputstream.getNextTarEntry()) != null) | ||
| { | ||
| Path pathEntryOutput = pathOutput.resolve(archiveentry.getName()); | ||
| if (archiveentry.isSymbolicLink()) | ||
| { | ||
| symLinks.put(pathEntryOutput, | ||
| pathOutput.resolve(archiveentry.getName()).getParent().resolve(archiveentry.getLinkName())); | ||
| continue; | ||
| } | ||
| else if (archiveentry.isLink()) | ||
| { | ||
| hardLinks.put(pathEntryOutput, | ||
| pathOutput.resolve(archiveentry.getLinkName())); | ||
| continue; | ||
| } | ||
| else if (archiveentry.isDirectory()) | ||
| { | ||
| if (!Files.exists(pathEntryOutput)) | ||
| Files.createDirectories(pathEntryOutput); | ||
| } | ||
| else | ||
| { | ||
| System.out.println(pathEntryOutput.toString() + " " + archiveentry.getSize()); //$NON-NLS-1$ | ||
| Files.copy(tararchiveinputstream, pathEntryOutput, StandardCopyOption.REPLACE_EXISTING); | ||
| Runtime.getRuntime().exec("/bin/chmod 755 ".concat(pathEntryOutput.toString())); //$NON-NLS-1$ | ||
| } | ||
| } | ||
| tararchiveinputstream.close(); | ||
| xzInputStream.close(); | ||
| fileInputStream.close(); | ||
| hardLinks.forEach(ToolsUtility::createHardLinks); | ||
| symLinks.forEach(ToolsUtility::createSymLinks); | ||
| } | ||
| catch (Exception e) | ||
| { | ||
| Logger.log(e); | ||
| } | ||
| } | ||
|
|
||
| private static void createHardLinks(Path link, Path target) | ||
| { | ||
| try | ||
| { | ||
| Files.deleteIfExists(link); | ||
| Files.createLink(link, target); | ||
| } | ||
| catch (Exception e) | ||
| { | ||
| Logger.log(e); | ||
| } | ||
| } | ||
|
|
||
| private static void createSymLinks(Path link, Path target) | ||
| { | ||
| try | ||
| { | ||
| Files.deleteIfExists(link); | ||
| Files.createSymbolicLink(link, target.toRealPath()); | ||
| } | ||
| catch (Exception e) | ||
| { | ||
| Logger.log(e); | ||
| } | ||
| } | ||
|
|
||
| public static String getReadableSizeMB(double size) | ||
| { | ||
| size /= 1024; // KB | ||
| size /= 1024; // MB | ||
| DecimalFormat df = new DecimalFormat("0.00"); //$NON-NLS-1$ | ||
| return String.valueOf(df.format(size)).concat(" MB"); //$NON-NLS-1$ | ||
| return espIdfVersion; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Null-safety & early-exit checks missing
activationScript and idfInstalled fields are assumed non-null. If the JSON is malformed, activationScript can be null, causing NPEs in new File(...) or ProcessBuilder.
Guard with:
if (idfInstalled == null || idfInstalled.getActivationScript() == null) {
return null;
}
sigmaaa
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @alirana01,
Thanks for the PR! It looks good overall. I’ve left a few comments with suggestions we can check together.
| private void prepEnvMap(Map<String, String> env) | ||
| { | ||
| env.put("PYTHONUNBUFFERED", "1"); //$NON-NLS-1$ //$NON-NLS-2$ | ||
| env.put("IDF_CCACHE_ENABLE", "false"); //$NON-NLS-1$ //$NON-NLS-2$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to set IDF_CCACHE_ENABLE to false here? I believe it will cause a redundant build if IDF_CCACHE_ENABLE is set to true in the environment variables.
| t.start(); | ||
| } | ||
| catch (CoreException e) | ||
| catch (Exception e) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think throwing a generic Exception is not a good practice. It's better to be as specific as possible with exception handling to make the code more robust and maintainable.
There was a problem hiding this 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
♻️ Duplicate comments (13)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (1)
120-134: Potential NPE when workbench window is not yet availablebundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (4)
100-108: Modified environment is ignored when running activation script
257-258: Environment dump to log may leak secrets
496-503: Duplicate keys inparseEnvKeyswill crash withIllegalStateException
543-562: Null-safe handling & Windows path separatorbundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (4)
83-92:⚠️ Potential issueDuplicate Issue: Static mutable state still poses concurrency risks
The static
eimJsonfield continues to create the same concurrency and stale data issues identified in previous reviews. The field is overwritten on everygetInstance()call without synchronization, and previously opened editors may see different JSON instances than they were created with.
274-279:⚠️ Potential issueComparator logic still incorrect after column reordering
The comparator index/order mismatch persists. The
versionColumnis assigned index 0,nameColumnindex 1, andlocationColumnindex 2, but thecompare()method still assumes different mappings, causing incorrect sorting behavior.Apply this fix to align the comparator with the actual column order:
switch (propertyIndex) { case 0: - rc = p1.getName().compareTo(p2.getName()); + rc = ToolsUtility.getIdfVersion(p1, eimJson.getGitPath()) + .compareTo(ToolsUtility.getIdfVersion(p2, eimJson.getGitPath())); break; case 1: - rc = p1.getPath().compareTo(p2.getPath()); + rc = p1.getName().compareTo(p2.getName()); break; case 2: - Boolean p1State = ToolsUtility.isIdfInstalledActive(p1); - Boolean p2State = ToolsUtility.isIdfInstalledActive(p2); - rc = p1State.compareTo(p2State); + rc = p1.getPath().compareTo(p2.getPath()); break;
392-396:⚠️ Potential issueUI thread blocking issue unresolved
The
getIdfVersion()method still executes heavy external processes on the UI thread during table cell updates, causing UI freezing as previously identified. This affects table responsiveness especially with multiple IDF installations.Cache the version results or compute them in background jobs to avoid blocking the UI thread.
248-256:⚠️ Potential issueResource leak: Column label providers not disposed
The color resource leak issue remains unresolved. While
TableViewerColumns are disposed indisposeColumns(), their associatedColumnLabelProviders (which own SWTColorobjects) are not disposed until the viewer is disposed, potentially causing resource accumulation.bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (1)
27-66:⚠️ Potential issueNull safety checks still missing
The null safety issues identified in previous reviews remain unaddressed. The method assumes
idfInstalledandactivationScriptare non-null, which can cause NPEs if the JSON is malformed.Add the recommended null safety guards:
public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath) { + if (idfInstalled == null || idfInstalled.getActivationScript() == null) { + return null; + } String activationScript = idfInstalled.getActivationScript();.github/workflows/ci_windows.yml (1)
8-10: Fix YAML indentation under triggersThe
branches:key and its list items under bothpushandpull_requestare mis-indented by one space, which will cause the workflow to fail parsing.Suggested patch:
on: push: - branches: - - master - - release/** + branches: + - master + - release/** pull_request: - branches: - - master - - release/** + branches: + - master + - release/**Also applies to: 12-14
🧰 Tools
🪛 YAMLlint (1.37.1)
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
.github/workflows/ci.yml (2)
8-10: Fix YAML indentation under triggersJust like in the Windows CI, the
branches:key and its items underpushandpull_requestneed an extra two spaces of indentation to be valid YAML.on: push: - branches: - - master - - release/** + branches: + - master + - release/** pull_request: - branches: - - master - - release/** + branches: + - master + - release/**Also applies to: 12-14
🧰 Tools
🪛 YAMLlint (1.37.1)
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
29-29:⚠️ Potential issueRemove trailing tab characters
Line ends with tab characters, which YAML does not allow. Trim to:- - name: Install ESP-IDF via eim + - name: Install ESP-IDF via eim🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 29-29: syntax error: found character '\t' that cannot start any token
(syntax)
🧹 Nitpick comments (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)
106-122: Consider error handling for desktop browse operationThe desktop browse operation has basic exception handling but doesn't provide user feedback when the operation fails.
Consider showing a user-friendly error message:
catch (Exception ex) { Logger.log(ex); + // Consider showing user notification about failed browser launch }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bundles/com.espressif.idf.ui/icons/tools/delete.pngis excluded by!**/*.png
📒 Files selected for processing (75)
.github/workflows/ci.yml(2 hunks).github/workflows/ci_windows.yml(1 hunks)bundles/com.espressif.idf.core/META-INF/MANIFEST.MF(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFCorePreferenceConstants.java(0 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java(2 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.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/toolchain/ESPToolChainManager.java(2 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/ToolInitializer.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/tools/watcher/EimJsonChangeListener.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/EspToolCommands.java(3 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java(3 hunks)bundles/com.espressif.idf.sdk.config.core/src/com/espressif/idf/sdk/config/core/server/JsonConfigServer.java(3 hunks)bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java(1 hunks)bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties(0 hunks)bundles/com.espressif.idf.ui/plugin.xml(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/EspressifGeneralStartup.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java(0 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SbomCommandDialog.java(3 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/help/ProductInformationHandler.java(1 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/preferences/EspresssifPreferencesPage.java(0 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeDataManager.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java(1 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/tools/watcher/EimJsonUiChangeHandler.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tracing/AppLvlTracingDialog.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/AbstractToolsHandler.java(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)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectTest.java(0 hunks)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java(2 hunks)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/ProjectTestOperations.java(1 hunks)tests/pom.xml(1 hunks)
💤 Files with no reviewable changes (30)
- bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/ExportIDFTools.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFNewToolsWizard.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFCorePreferenceConstants.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/ToolsJsonParser.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/install/messages_zh.properties
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.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/GitWizardRepProgressMonitor.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/JsonKey.java
- tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectTest.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/ToolsPlatformMapping.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/tools/ToolsActivationJob.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/preferences/EspresssifPreferencesPage.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/vo/ToolsVO.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.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/GitRepositoryBuilder.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/UpdateEspIdfHandler.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFDownloadPage.java
✅ Files skipped from review due to trivial changes (4)
- bundles/com.espressif.idf.ui/plugin.xml
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tracing/AppLvlTracingDialog.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/AbstractToolsHandler.java
🚧 Files skipped from review as they are similar to previous changes (33)
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.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/watcher/EimJsonStateChecker.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties
- bundles/com.espressif.idf.core/META-INF/MANIFEST.MF
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java
- tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.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/toolchain/ESPToolChainManager.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/EspToolCommands.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeDataManager.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/help/ProductInformationHandler.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/NewProjectHandlerUtil.java
- bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java
- tests/pom.xml
- tests/com.espressif.idf.ui.test/configs/default-test-linux.properties
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java
- tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/ProjectTestOperations.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.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/watcher/EimJsonChangeListener.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SbomCommandDialog.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/messages.properties
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/Messages.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java
- bundles/com.espressif.idf.sdk.config.core/src/com/espressif/idf/sdk/config/core/server/JsonConfigServer.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/EspressifGeneralStartup.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/tools/watcher/EimJsonWatchService.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (12)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)
Messages(15-42)bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-137)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java (1)
ToolInitializer(26-93)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1)
EimJson(8-47)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java (1)
EimJsonStateChecker(22-67)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java (1)
EimJsonWatchService(23-152)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/StringUtil.java (1)
StringUtil(11-25)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/MessageLinkDialog.java (1)
MessageLinkDialog(40-135)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/EclipseHandler.java (1)
EclipseHandler(21-79)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java (1)
ESPIDFManagerEditor(22-78)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java (1)
EimEditorInput(9-93)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java (1)
EimJsonUiChangeHandler(23-44)
🪛 actionlint (1.7.7)
.github/workflows/ci.yml
19-19: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "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", "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)
19-19: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "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", "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)
25-25: 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.37.1)
.github/workflows/ci.yml
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
[warning] 22-22: wrong indentation: expected 6 but found 4
(indentation)
[error] 29-29: syntax error: found character '\t' that cannot start any token
(syntax)
[error] 43-43: trailing spaces
(trailing-spaces)
.github/workflows/ci_windows.yml
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: build_macos
- GitHub Check: build_macos
🔇 Additional comments (9)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties (1)
8-8:⚠️ Potential issueFix typo: "pyhton" → "python"
-IDFToolsHandler_ToolsManagerConsole=Espressif IDF Tools Console +IDFToolsHandler_ToolsManagerConsole=Espressif IDF Tools ConsoleWait, that's not the right line. Let me check line 148 in SetupToolsInIde.java where the typo appears to originate from.
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)
124-140:Details
✅ Verification successful
Verify preference scope and key usage
The initial setup logic uses
InstanceScopeandEimConstants.INSTALL_TOOLS_FLAG- ensure this preference key is properly documented and the scope is appropriate for this use case.
🏁 Script executed:
#!/bin/bash # Description: Verify the usage of INSTALL_TOOLS_FLAG preference key across the codebase # Expected: Find where this flag is set/reset to understand the lifecycle rg -A 3 -B 3 "INSTALL_TOOLS_FLAG"Length of output: 4676
🏁 Script executed:
#!/bin/bash # Inspect SetupToolsJobListener to see how scopedPreferenceStore is initialized sed -n '1,200p' bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.javaLength of output: 2661
Preference scope and key usage confirmed
TheINSTALL_TOOLS_FLAGconstant is defined inEimConstantsand consistently used by:
ESPIDFMainTablePage(checks flag before setup)SetupToolsJobListener(sets/clears flag on job completion)NewProjectHandlerUtil(reads flag when creating new projects)ToolInitializer(reads/clears flag in core)All modules use
InstanceScope.INSTANCE.getNode(UIPlugin.PLUGIN_ID), making the workspace-wide scope and key usage appropriate. No changes needed.bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (2)
68-93: Platform detection logic is completeThe command construction correctly handles Windows, Linux, and defaults to zsh for other platforms (likely macOS). The implementation looks solid.
95-100: Active IDF detection implementation is correctThe method properly uses the new
ESP_IDF_EIM_IDenvironment variable to determine if an IDF installation is active. The logic is straightforward and correct.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)
15-42: Message class properly structuredThe
Messagesclass follows standard Eclipse NLS patterns with proper bundle initialization and private constructor. The reduced message set aligns well with the simplified UI design..github/workflows/ci.yml (4)
17-17: Rename job tobuild_linux
The new job name clearly distinguishes the Linux build from Windows and macOS jobs, improving readability.
19-19: Validate custom runner labels
You’re using[self-hosted, eclipse, BrnoUBU0004]. The labelseclipseandBrnoUBU0004aren’t standard GitHub-hosted runners. Ensure these are correctly registered in your self-hosted runner group.🧰 Tools
🪛 actionlint (1.7.7)
19-19: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "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", "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)
19-19: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "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", "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)
27-27: The Python version change (3.10) is intentional and valid; no action required here.
30-32: Use official ESP-IDF action
Switching toespressif/install-esp-idf-action@v1withversion: 'v5.3'correctly replaces the legacy checkout logic for ESP-IDF. This aligns with the new EIM-based setup.
| monitor.worked(1); | ||
|
|
||
| monitor.setTaskName("Installing pyhton dependency web-socket"); //$NON-NLS-1$ | ||
| log("Installing pyhton dependency web-socket", IStatus.INFO); //$NON-NLS-1$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo: "pyhton" → "python"
-log("Installing pyhton dependency web-socket", IStatus.INFO); //$NON-NLS-1$
+log("Installing python dependency web-socket", IStatus.INFO); //$NON-NLS-1$📝 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.
| log("Installing pyhton dependency web-socket", IStatus.INFO); //$NON-NLS-1$ | |
| log("Installing python dependency web-socket", IStatus.INFO); //$NON-NLS-1$ |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java
at line 149, correct the typo in the log message by changing "pyhton" to
"python" to ensure the message is spelled correctly.
| setUpToolChainsAndTargets(false); | ||
| monitor.worked(1); | ||
|
|
||
| monitor.setTaskName("Installing pyhton dependency web-socket"); //$NON-NLS-1$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo: "pyhton" → "python"
-monitor.setTaskName("Installing pyhton dependency web-socket"); //$NON-NLS-1$
+monitor.setTaskName("Installing python dependency web-socket"); //$NON-NLS-1$📝 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.
| monitor.setTaskName("Installing pyhton dependency web-socket"); //$NON-NLS-1$ | |
| monitor.setTaskName("Installing python dependency web-socket"); //$NON-NLS-1$ |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java
at line 148, correct the typo in the task name string from "pyhton" to "python"
to ensure the message reads "Installing python dependency web-socket".
| distribution: 'temurin' | ||
| cache: 'maven' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove trailing spaces
The lines for distribution: 'temurin' and cache: 'maven' end with extra spaces, which YAMLlint flags. Trim them:
- distribution: 'temurin'
+ distribution: 'temurin'
- cache: 'maven'
+ cache: 'maven'📝 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.
| distribution: 'temurin' | |
| cache: 'maven' | |
| distribution: 'temurin' | |
| cache: 'maven' |
🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 43-43: trailing spaces
(trailing-spaces)
🤖 Prompt for AI Agents
In .github/workflows/ci.yml at lines 43 to 44, remove the trailing spaces at the
end of the lines containing "distribution: 'temurin'" and "cache: 'maven'".
Ensure there are no extra spaces after the values to comply with YAMLlint rules.
| path: dependencies/idf-tools | ||
| submodules: 'true' | ||
| ref: release/v5.1 | ||
| - uses: actions/checkout@v4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct indentation of checkout step
The - uses: actions/checkout@v4 line is only indented 4 spaces under steps. It should be indented 6 spaces to align with YAML expectations:
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 YAMLlint (1.37.1)
[warning] 22-22: wrong indentation: expected 6 but found 4
(indentation)
🤖 Prompt for AI Agents
In .github/workflows/ci.yml at line 22, the indentation of the line '- uses:
actions/checkout@v4' is incorrect; it is currently indented 4 spaces under
'steps' but should be indented 6 spaces to conform to YAML syntax. Adjust the
indentation of this line to 6 spaces so it aligns properly with other step
entries under 'steps'.
There was a problem hiding this 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/tools/watcher/EimJsonUiChangeHandler.java (2)
44-47: Add null check for preferences parameter
49-54: Add error handling for UI operationsbundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (1)
179-193: Fix potential NPE when workbench window is not available
🧹 Nitpick comments (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (1)
92-130: Consider extracting nested method to improve readabilityThe
handleOldConfigExportmethod has deeply nested logic that could be simplified for better maintainability.private void handleOldConfigExport() { - final int[] response = new int[] { -1 }; - Display display = Display.getDefault(); - display.syncExec(() -> { - MessageDialog messageDialog = new MessageDialog(display.getActiveShell(), - Messages.OldConfigFoundMsgBoxTitle, null, Messages.OldConfigFoundMsgBoxMsg, 0, 0, - new String[] { Messages.ToolsInitializationDifferentPathMessageBoxOptionYes, - Messages.ToolsInitializationDifferentPathMessageBoxOptionNo }); - response[0] = messageDialog.open(); - }); - - if (response[0] == 0) + int response = promptUserForOldConfigExport(); + if (response == 0) { - try - { - IStatus status = toolInitializer.exportOldConfig(); - Logger.log("Tools Conversion Process Message: "); - Logger.log(status.getMessage()); - if (status.getSeverity() != IStatus.ERROR) - { - preferences.putBoolean(EimConstants.OLD_CONFIG_EXPORTED_FLAG, true); - displayInformationMessageBox(Messages.OldConfigExportCompleteSuccessMsgTitle, - Messages.OldConfigExportCompleteSuccessMsg); - } - else - { - displayInformationMessageBox(Messages.OldConfigExportCompleteFailMsgTitle, - Messages.OldConfigExportCompleteFailMsg); - } - } - catch (IOException e) - { - Logger.log("Error exporting old configuration", e); - displayInformationMessageBox(Messages.OldConfigExportCompleteFailMsgTitle, - Messages.OldConfigExportCompleteFailMsg); - } + performOldConfigExport(); } } + +private int promptUserForOldConfigExport() +{ + final int[] response = new int[] { -1 }; + Display display = Display.getDefault(); + display.syncExec(() -> { + MessageDialog messageDialog = new MessageDialog(display.getActiveShell(), + Messages.OldConfigFoundMsgBoxTitle, null, Messages.OldConfigFoundMsgBoxMsg, 0, 0, + new String[] { Messages.ToolsInitializationDifferentPathMessageBoxOptionYes, + Messages.ToolsInitializationDifferentPathMessageBoxOptionNo }); + response[0] = messageDialog.open(); + }); + return response[0]; +} + +private void performOldConfigExport() +{ + try + { + IStatus status = toolInitializer.exportOldConfig(); + Logger.log("Tools Conversion Process Message: "); + Logger.log(status.getMessage()); + if (status.getSeverity() != IStatus.ERROR) + { + preferences.putBoolean(EimConstants.OLD_CONFIG_EXPORTED_FLAG, true); + displayInformationMessageBox(Messages.OldConfigExportCompleteSuccessMsgTitle, + Messages.OldConfigExportCompleteSuccessMsg); + } + else + { + displayInformationMessageBox(Messages.OldConfigExportCompleteFailMsgTitle, + Messages.OldConfigExportCompleteFailMsg); + } + } + catch (IOException e) + { + Logger.log("Error exporting old configuration", e); + displayInformationMessageBox(Messages.OldConfigExportCompleteFailMsgTitle, + Messages.OldConfigExportCompleteFailMsg); + } +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
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/logging/Logger.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.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/watcher/EimJsonWatchService.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java(1 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/messages.properties(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java
🚧 Files skipped from review as they are similar to previous changes (5)
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.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/build/messages.properties
🧰 Additional context used
🧬 Code Graph Analysis (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (14)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java (1)
Messages(9-63)bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-141)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java (1)
ToolInitializer(30-107)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1)
EimJson(8-59)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java (1)
EimJsonStateChecker(22-67)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java (1)
EimJsonWatchService(23-153)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (1)
IDFUtil(58-889)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/StringUtil.java (1)
StringUtil(11-25)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/UIPlugin.java (1)
UIPlugin(22-104)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/MessageLinkDialog.java (1)
MessageLinkDialog(40-135)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/EclipseHandler.java (1)
EclipseHandler(21-79)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/ESPIDFManagerEditor.java (1)
ESPIDFManagerEditor(22-78)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java (1)
EimEditorInput(9-93)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java (1)
EimJsonUiChangeHandler(39-150)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build_macos
🔇 Additional comments (4)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java (2)
145-149: LGTM!The console stream helper method is correctly implemented.
121-143:⚠️ Potential issueFix potential NPE when accessing workbench window
The method doesn't check if
EclipseHandler.getActiveWorkbenchWindow()returns null before calling methods on it, which could cause a NullPointerException.private void launchEspIdfManager() throws PartInitException { Display.getDefault().asyncExec(() -> { IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow(); if (activeww == null || activeww.getActivePage() == null) { Logger.log("Cannot open ESP-IDF Manager. No active workbench window or active page."); return; } try { IDE.openEditor(activeww.getActivePage(), new EimEditorInput(eimJson), ESPIDFManagerEditor.EDITOR_ID, true); } catch (PartInitException e) { Logger.log("Failed to open ESP-IDF Manager Editor."); Logger.log(e); } }); }Likely an incorrect or invalid review comment.
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (1)
50-90: LGTM! Startup initialization logic is well-structuredThe
earlyStartupmethod properly handles the initialization flow with appropriate checks for EIM installation, old config migration, and tool setup.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)
23-35: LGTM! Message field additions are consistentThe new message fields follow proper naming conventions and align with the new JSON-driven tool management approach.
There was a problem hiding this 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
♻️ Duplicate comments (5)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (5)
108-109: Environment map created but not passed to the process
addGitToEnvironment(env, …)mutatesenv, yetrunInBackground(…, System.getenv())discards those edits. Use the modified map or the Git binary will stay offPATHon systems that need it.
148-149: Typo: “pyhton” → “python”
String appears twice; fix both to keep UI text professional.
255-258: Full environment dump leaks secrets
Logger.log(environment.toString())prints every variable—including credentials—to the IDE log. Redact or omit sensitive values.
496-503: Duplicate keys inparseEnvKeyswill blow up
Collectors.toMapwithout a merge function throwsIllegalStateExceptionwhen a key (e.g.,PATH) appears twice. Provide a merge strategy ((oldV,newV)->newV).
545-560: Null-safety & platform separator
executablePathmay be null; check before creatingnew Path(). Also useFile.pathSeparatorinstead of hard-coding;, so Unix hosts get “:”.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
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/util/IDFUtil.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/util/IDFUtil.java
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: build_macos
- GitHub Check: build_linux
| private void loadIdfPathWithSystemPath(Map<String, String> systemEnv) | ||
| { | ||
| String idfExportPath = envVarsFromActivationScriptMap.get(IDFEnvironmentVariables.PATH); | ||
| String pathVar = "PATH"; // for Windows //$NON-NLS-1$ | ||
| String pathEntry = systemEnv.get(pathVar); // $NON-NLS-1$ | ||
| if (pathEntry == null) | ||
| { | ||
| pathVar = "Path"; //$NON-NLS-1$ | ||
| pathEntry = systemEnv.get(pathVar); | ||
| if (pathEntry == null) // no idea | ||
| { | ||
| Logger.log(new Exception("No PATH found in the system environment variables")); //$NON-NLS-1$ | ||
| } | ||
| } | ||
|
|
||
| if (!StringUtil.isEmpty(pathEntry)) | ||
| { | ||
| idfExportPath = idfExportPath.replace("$PATH", pathEntry); // macOS //$NON-NLS-1$ | ||
| idfExportPath = idfExportPath.replace("%PATH%", pathEntry); // Windows //$NON-NLS-1$ | ||
| } | ||
| systemEnv.put(pathVar, idfExportPath); | ||
| for (Entry<String, String> entry : envVarsFromActivationScriptMap.entrySet()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possible NPE when PATH missing from activation output
idfExportPath = envVarsFromActivationScriptMap.get(PATH) can be null; subsequent replace(...) calls will throw. Guard for null and fail gracefully.
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java
around lines 404 to 425, the variable idfExportPath is assigned from
envVarsFromActivationScriptMap.get(IDFEnvironmentVariables.PATH) which can be
null, causing a NullPointerException when calling replace on it. To fix this,
add a null check for idfExportPath before calling replace, and handle the null
case gracefully, such as logging an error or returning early to avoid the NPE.
| while (process.isAlive() && waitCount > 0) | ||
| { | ||
| try | ||
| { | ||
| Thread.sleep(300); | ||
| } | ||
| catch (InterruptedException e) | ||
| { | ||
| Logger.log(e); | ||
| } | ||
| waitCount--; | ||
| } | ||
|
|
||
| if (waitCount == 0) | ||
| { | ||
| log("Process possibly stuck", IStatus.ERROR); //$NON-NLS-1$ | ||
| return Status.CANCEL_STATUS; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Timeout far too short – 3 s can kill legitimate builds
list-targets often takes >3 s on first run. The 10×300 ms spin loop aborts good processes and returns CANCEL_STATUS. Replace with process.waitFor(timeout, unit) using a sensible timeout (e.g. 2 min) or make it user-configurable.
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java
around lines 360 to 377, the current timeout loop waits only 3 seconds total by
sleeping 300 ms increments 10 times, which is too short and may cancel
legitimate long-running processes. Replace this loop with a single call to
process.waitFor(timeout, unit) using a longer timeout such as 2 minutes to allow
sufficient time for the process to complete. Optionally, make this timeout
configurable by the user. Remove the manual sleep and waitCount logic and handle
the case where waitFor returns false by logging the error and returning
Status.CANCEL_STATUS.
716555d to
667197c
Compare
There was a problem hiding this 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
♻️ Duplicate comments (15)
.github/workflows/ci_windows.yml (1)
8-14: Fix YAML indentation under triggers
branches:items are indented 5 spaces instead of 6, breaking YAML structure. Align them with two extra spaces as already suggested earlier..github/workflows/ci.yml (1)
8-14: Address remaining YAML-lint / action-lint errorsThe earlier remarks still apply:
- Mis-indented
branches:lists (lines 8-14).- Step item
- uses: actions/checkout@v4needs two more spaces (line 22).- The
Install ESP-IDFstep contains tab characters – replace with spaces (line 29).- Upgrade
actions/setup-python@v2→@v4(line 25, inside this hunk).- Strip trailing spaces after
distribution:andcache:(lines 43-44).These must be fixed for the workflow to parse.
Also applies to: 22-23, 29-33, 43-44
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (7)
100-109: Environment map prepared but never used
addGitToEnvironment(env, …)mutatesenv, yetrunInBackgroundreceivesSystem.getenv(), discarding the change. Passenvinstead.- IStatus status = processBuilderFactory.runInBackground(arguemnts, Path.ROOT, System.getenv()); + IStatus status = processBuilderFactory.runInBackground(arguemnts, Path.ROOT, env);
148-150: Typo: “pyhton”Spelling mistake in user-visible strings.
-Installing pyhton dependency web-socket +Installing python dependency web-socket
253-259: Avoid dumping full environment to log
Logger.log(environment.toString())can leak secrets (tokens, keys) into the Eclipse log. Log only the size or redact sensitive entries.
330-377: Three-second spin-wait cancels valid buildsThe manual 10×300 ms loop is too aggressive; legitimate
list-targetsruns often exceed 3 s. Replace withprocess.waitFor(long, TimeUnit)with a sane timeout (e.g. 2 min) or make it configurable.
404-425: Possible NPE when PATH absent
idfExportPath = envVarsFromActivationScriptMap.get(PATH)may be null; subsequentreplacecalls would crash. Add null check and fail gracefully.
496-503: Handle duplicate env keys when parsing
Collectors.toMapwithout a merge function throws if the activation script exports the same variable twice (e.g.,PATH). Provide a merge strategy.
543-560: Hard-coded ‘;’ path separator & missing null-check
- Use
File.pathSeparatorinstead of";"for cross-platform compatibility.executablePathcan be null – guard beforenew Path(executablePath).bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (1)
181-188: Null-check workbench window before use
EclipseHandler.getActiveWorkbenchWindow()can return null during early startup or headless tests. Guard before dereferencing.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (4)
70-72: StaticeimJsonfield is still a mutable singleton – existing race-condition remains
eimJsonis overwritten on everygetInstance()call. Concurrent calls from background jobs/UI threads can race and editors created earlier may suddenly operate on a different JSON instance.
Previous review already raised this (see history) but code is unchanged.
268-284: Comparator ↔ column index mapping is wrong again – sorting yields unexpected order
setupColumns()assigns
• index 0 → versionColumn
• index 1 → nameColumn
• index 2 → locationColumnbut
compare()interprets
• case 0 → name
• case 1 → path
• case 2 → active-stateClicking “Version” will sort by Name, etc. This is the exact issue pointed out in the former review and still un-fixed.
--- in compare() -case 0: - rc = p1.getName().compareTo(p2.getName()); +case 0: // Version column + rc = ToolsUtility.getIdfVersion(p1, null) + .compareTo(ToolsUtility.getIdfVersion(p2, null)); ... -case 1: - rc = p1.getPath().compareTo(p2.getPath()); +case 1: // Name column + rc = p1.getName().compareTo(p2.getName()); ... -case 2: - Boolean p1State = ToolsUtility.isIdfInstalledActive(p1); - Boolean p2State = ToolsUtility.isIdfInstalledActive(p2); - rc = p1State.compareTo(p2State); +case 2: // Location column + rc = p1.getPath().compareTo(p2.getPath());Also applies to: 530-545
230-256: Colour objects still leak when columns are recreated
setupColumns()disposesTableViewerColumns but their associatedIdfManagerTableColumnLabelProviderinstances (each holding an SWTColor) are not disposed, so every refresh leaks oneColor.
Same issue flagged previously. Dispose the label-provider before or indisposeColumns().+ if (activateColumn != null) { + ColumnLabelProvider lp = (ColumnLabelProvider) activateColumn.getLabelProvider(); + if (lp != null) { + lp.dispose(); + } + }(Repeat for the other columns.)
Also applies to: 317-326
379-396:getIdfVersionis invoked for every paint → spawns external process on UI thread
updateDataIntoCells()callsToolsUtility.getIdfVersion()which launches a shell and blocks (waitFor()).
Rendering the table for 20 rows means 20 processes and UI freeze – the same performance problem highlighted in the last round.Immediate mitigation: cache once per
IdfInstalledor compute in a backgroundJoband refresh asynchronously.bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (1)
27-41: Null-safety still missing and unused parameter detected
activationScriptmay benull;new File(null)will NPE.
Also, thegitPathparameter is never referenced – delete it or use it.-public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath) +public static String getIdfVersion(IdfInstalled idfInstalled) { - String activationScript = idfInstalled.getActivationScript(); + if (idfInstalled == null || idfInstalled.getActivationScript() == null) { + return null; + } + String activationScript = idfInstalled.getActivationScript();
🧹 Nitpick comments (4)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties (1)
5-13: Clean up typos & leading-space keys
refereshing→refreshinginEimJsonChangedMsgDetail.- Remove the leading space before
MsgYes/MsgNo; they currently save the key with the space included, so look-ups will fail.bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (2)
68-93: Platform command construction – brittle fallback
/bin/zshis assumed for “other” OSes, which includes macOS and unknowns.
Many Linux/macOS systems lack zsh; prefer/bin/bashfallback or detect shell availability.
95-100: Repeated environment lookup could be cached
isIdfInstalledActiveinstantiatesIDFEnvironmentVariablesevery call; this runs for every table repaint.
Cache the env value once or expose a static helper.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)
23-35: Minor: Keep message fields sorted alphabetically for maintainabilityThe list is small now; alphabetic order helps during future additions.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bundles/com.espressif.idf.ui/icons/tools/delete.pngis excluded by!**/*.png
📒 Files selected for processing (76)
.github/workflows/ci.yml(2 hunks).github/workflows/ci_windows.yml(1 hunks)bundles/com.espressif.idf.core/META-INF/MANIFEST.MF(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFCorePreferenceConstants.java(0 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java(2 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.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/logging/Logger.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java(2 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/ToolInitializer.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/tools/watcher/EimJsonChangeListener.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/EspToolCommands.java(3 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java(4 hunks)bundles/com.espressif.idf.sdk.config.core/src/com/espressif/idf/sdk/config/core/server/JsonConfigServer.java(3 hunks)bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java(1 hunks)bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties(0 hunks)bundles/com.espressif.idf.ui/plugin.xml(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/EspressifGeneralStartup.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java(0 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SbomCommandDialog.java(3 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/help/ProductInformationHandler.java(1 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/preferences/EspresssifPreferencesPage.java(0 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeDataManager.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java(1 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/tools/watcher/EimJsonUiChangeHandler.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tracing/AppLvlTracingDialog.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/AbstractToolsHandler.java(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)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectTest.java(0 hunks)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java(2 hunks)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/ProjectTestOperations.java(1 hunks)tests/pom.xml(1 hunks)
💤 Files with no reviewable changes (30)
- bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.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/ToolsSystemWrapper.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.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/GitWizardRepProgressMonitor.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/VersionsVO.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages_zh.properties
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFCorePreferenceConstants.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages.properties
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/Messages.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/preferences/EspresssifPreferencesPage.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java
- tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectTest.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/GitRepositoryBuilder.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/UpdateEspIdfHandler.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.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/IDFDownloadPage.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationJob.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/ToolsJob.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.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
🚧 Files skipped from review as they are similar to previous changes (38)
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tracing/AppLvlTracingDialog.java
- tests/pom.xml
- bundles/com.espressif.idf.core/META-INF/MANIFEST.MF
- 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.ui/src/com/espressif/idf/ui/size/IDFSizeDataManager.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SbomCommandDialog.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/help/ProductInformationHandler.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/EspToolCommands.java
- tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/ProjectTestOperations.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/messages.properties
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonChangeListener.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/build/IDFBuildConfiguration.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/AbstractToolsHandler.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/IDFEnvironmentVariables.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java
- tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.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/plugin.xml
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java
- 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/EimConstants.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/tools/vo/IdfInstalled.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties
- bundles/com.espressif.idf.sdk.config.core/src/com/espressif/idf/sdk/config/core/server/JsonConfigServer.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/EspressifGeneralStartup.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (10)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFCorePlugin.java (1)
IDFCorePlugin(20-77)bundles/com.espressif.idf.core/src/com/espressif/idf/core/ProcessBuilderFactory.java (1)
ProcessBuilderFactory(16-163)bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-141)bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java (1)
ESPToolChainManager(61-680)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (1)
ToolsUtility(25-101)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1)
EimJson(8-59)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java (1)
IdfInstalled(5-80)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (1)
IDFUtil(58-838)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/StringUtil.java (1)
StringUtil(11-25)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/Messages.java (1)
Messages(6-27)
🪛 actionlint (1.7.7)
.github/workflows/ci.yml
19-19: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "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", "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)
19-19: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "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", "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)
25-25: 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.37.1)
.github/workflows/ci.yml
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
[warning] 22-22: wrong indentation: expected 6 but found 4
(indentation)
[error] 29-29: syntax error: found character '\t' that cannot start any token
(syntax)
[error] 43-43: trailing spaces
(trailing-spaces)
.github/workflows/ci_windows.yml
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: build_macos
- GitHub Check: build_macos
| public void rollback() | ||
| { | ||
| IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables(); | ||
|
|
||
| for (Entry<String, String> entry : existingEnvVarsInIdeForRollback.entrySet()) | ||
| { | ||
| idfEnvironmentVariables.addEnvVariable(entry.getKey(), entry.getValue()); | ||
| } | ||
| IDFUtil.updateEspressifPrefPageOpenocdPath(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Null-safe rollback
existingEnvVarsInIdeForRollback may still be null when rollback() is called after an early failure, leading to NPE. Guard for null before iterating.
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java
around lines 77 to 85, the rollback() method iterates over
existingEnvVarsInIdeForRollback without checking if it is null, which can cause
a NullPointerException. Add a null check before the for loop to ensure
existingEnvVarsInIdeForRollback is not null before iterating over its entries.
| display.syncExec(() -> { | ||
| MessageDialog messageDialog = new MessageDialog(display.getActiveShell(), | ||
| Messages.OldConfigFoundMsgBoxTitle, null, Messages.OldConfigFoundMsgBoxMsg, 0, 0, | ||
| new String[] { Messages.ToolsInitializationDifferentPathMessageBoxOptionYes, | ||
| Messages.ToolsInitializationDifferentPathMessageBoxOptionNo }); | ||
| response[0] = messageDialog.open(); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MessageDialog constructor parameters out of order – compilation fails
MessageDialog expects (Shell, String, Image, String, int, String[], int). You pass two ints before the label array. Swap the arguments.
- MessageDialog messageDialog = new MessageDialog(display.getActiveShell(),
- Messages.OldConfigFoundMsgBoxTitle, null, Messages.OldConfigFoundMsgBoxMsg, 0, 0,
- new String[] { ... });
+ MessageDialog messageDialog = new MessageDialog(display.getActiveShell(),
+ Messages.OldConfigFoundMsgBoxTitle, null, Messages.OldConfigFoundMsgBoxMsg,
+ MessageDialog.QUESTION, new String[] { ... }, 0);📝 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.
| display.syncExec(() -> { | |
| MessageDialog messageDialog = new MessageDialog(display.getActiveShell(), | |
| Messages.OldConfigFoundMsgBoxTitle, null, Messages.OldConfigFoundMsgBoxMsg, 0, 0, | |
| new String[] { Messages.ToolsInitializationDifferentPathMessageBoxOptionYes, | |
| Messages.ToolsInitializationDifferentPathMessageBoxOptionNo }); | |
| response[0] = messageDialog.open(); | |
| }); | |
| display.syncExec(() -> { | |
| MessageDialog messageDialog = new MessageDialog(display.getActiveShell(), | |
| Messages.OldConfigFoundMsgBoxTitle, null, Messages.OldConfigFoundMsgBoxMsg, | |
| MessageDialog.QUESTION, new String[] { | |
| Messages.ToolsInitializationDifferentPathMessageBoxOptionYes, | |
| Messages.ToolsInitializationDifferentPathMessageBoxOptionNo | |
| }, 0); | |
| response[0] = messageDialog.open(); | |
| }); |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java
around lines 96 to 103, the MessageDialog constructor parameters are incorrectly
ordered, causing compilation errors. Change the constructor call to pass the int
parameter before the String array and then the int parameter last, matching the
expected signature (Shell, String, Image, String, int, String[], int). Swap the
two int arguments accordingly to fix the issue.
| @Override | ||
| public void earlyStartup() | ||
| { | ||
| Preferences preferences = org.eclipse.core.runtime.preferences.InstanceScope.INSTANCE | ||
| .getNode(UIPlugin.PLUGIN_ID); | ||
| ToolInitializer toolInitializer = new ToolInitializer(preferences); | ||
| EimJsonStateChecker stateChecker = new EimJsonStateChecker(preferences); | ||
| eimJsonUiChangeHandler = new EimJsonUiChangeHandler(preferences); | ||
| stateChecker.updateLastSeenTimestamp(); | ||
| EimJsonWatchService.getInstance().addEimJsonChangeListener(eimJsonUiChangeHandler); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instance fields never initialised
earlyStartup() creates local variables preferences and toolInitializer, leaving the declared fields null. Subsequent methods dereference toolInitializer / preferences, causing NPEs.
- Preferences preferences = ...
- ToolInitializer toolInitializer = ...
+ this.preferences = org.eclipse.core.runtime.preferences.InstanceScope.INSTANCE.getNode(UIPlugin.PLUGIN_ID);
+ this.toolInitializer = new ToolInitializer(this.preferences);📝 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.
| @Override | |
| public void earlyStartup() | |
| { | |
| Preferences preferences = org.eclipse.core.runtime.preferences.InstanceScope.INSTANCE | |
| .getNode(UIPlugin.PLUGIN_ID); | |
| ToolInitializer toolInitializer = new ToolInitializer(preferences); | |
| EimJsonStateChecker stateChecker = new EimJsonStateChecker(preferences); | |
| eimJsonUiChangeHandler = new EimJsonUiChangeHandler(preferences); | |
| stateChecker.updateLastSeenTimestamp(); | |
| EimJsonWatchService.getInstance().addEimJsonChangeListener(eimJsonUiChangeHandler); | |
| @Override | |
| public void earlyStartup() | |
| { | |
| // initialize the instance fields instead of shadowing them | |
| this.preferences = org.eclipse.core.runtime.preferences.InstanceScope.INSTANCE | |
| .getNode(UIPlugin.PLUGIN_ID); | |
| this.toolInitializer = new ToolInitializer(this.preferences); | |
| EimJsonStateChecker stateChecker = new EimJsonStateChecker(preferences); | |
| eimJsonUiChangeHandler = new EimJsonUiChangeHandler(preferences); | |
| stateChecker.updateLastSeenTimestamp(); | |
| EimJsonWatchService.getInstance().addEimJsonChangeListener(eimJsonUiChangeHandler); | |
| } |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java
around lines 50 to 60, the instance fields for preferences and toolInitializer
are not being initialized and only local variables are created in
earlyStartup(), leading to null pointer exceptions later. To fix this, assign
the preferences and toolInitializer objects to the corresponding instance fields
instead of local variables so they are properly initialized and accessible
throughout the class.
There was a problem hiding this 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 (6)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (6)
81-84: Possible NPE whenexistingEnvVarsInIdeForRollbackis still null
rollback()iterates overexistingEnvVarsInIdeForRollback.entrySet()without guarding for the field being unset when the job aborts early.
This is the same issue flagged in an earlier review round.
100-109: Environment prepared inenvis ignored
addGitToEnvironment()mutates the localenvmap, yetrunInBackgroundis invoked withSystem.getenv()instead of the updated map—identical to the previously reported bug.
270-296: 3 s spin-loop still cancels legitimate runs
The manual 10 × 300 ms wait is unchanged; long-running first invocations ofidf.py list-targetscan legitimately exceed this.
325-346:idfExportPathmay be null → NPE onreplace(...)
If the activation output is missingPATH,idfExportPathis null and thereplacecalls crash. This was already raised in the previous review.
417-424: Duplicate keys in activation output still throwIllegalStateException
Collectors.toMapis used without a merge function, so repeated exports (e.g. forPATH) will break. Same as the earlier comment.
464-481: Hard-coded";"separator & missing null check forexecutablePath
Platform-specific path separator and potential NPE remain unaddressed, matching the prior feedback.
🧹 Nitpick comments (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1)
98-105: Progress monitor ticks don’t add up
beginTask("…", 7)is followed by only 5worked(1)calls, so the monitor never reaches 100 %. Either adjust the total or add the missing ticks.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: build_macos
- GitHub Check: build_macos
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
♻️ Duplicate comments (13)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java (1)
12-14: Avoid hardcoding installation pathsThe Windows installation directory is hardcoded, which may not respect user customizations or non-standard installation locations. Consider using environment variables or configuration settings to allow for customization.
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java (1)
60-71: Consider more robust error handling when loading EimJson.The loadEimJson method catches IOException but returns null on error. This could lead to NullPointerExceptions later when callers try to use the returned object.
Consider throwing a checked exception or returning an empty EimJson object instead of null:
public EimJson loadEimJson() { try { return parser.getEimJson(true); } catch (IOException e) { Logger.log(e); - return null; + // Return an empty EimJson object instead of null + return new EimJson(); } }bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (6)
77-85: Add null check for rollback map.The
existingEnvVarsInIdeForRollbackmay be null whenrollback()is called after an early failure, leading to NPE.public void rollback() { + if (existingEnvVarsInIdeForRollback == null) + { + Logger.log("No backup environment variables to restore"); + return; + } + IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables(); for (Entry<String, String> entry : existingEnvVarsInIdeForRollback.entrySet())
100-108: Use modified environment when running activation script.The local
envmap is modified byaddGitToEnvironment()but thenSystem.getenv()is passed instead, losing the Git path adjustments.-IStatus status = processBuilderFactory.runInBackground(arguemnts, Path.ROOT, System.getenv()); +IStatus status = processBuilderFactory.runInBackground(arguemnts, Path.ROOT, env);
406-412: Handle duplicate keys in environment parsing.The
parseEnvKeysmethod will throwIllegalStateExceptionif the activation script outputs duplicate environment variable names..collect(Collectors.toMap(parts -> parts[0].trim(), parts -> parts[1].trim())); +.collect(Collectors.toMap( + parts -> parts[0].trim(), + parts -> parts[1].trim(), + (oldV, newV) -> newV // keep the latest +));
312-333: Add null check for PATH variable.The
idfExportPathcan be null if PATH is missing from the activation script output, causing NPE when callingreplace().private void loadIdfPathWithSystemPath(Map<String, String> systemEnv) { String idfExportPath = envVarsFromActivationScriptMap.get(IDFEnvironmentVariables.PATH); + if (idfExportPath == null) + { + Logger.log("PATH not found in activation script output"); + return; + } + String pathVar = "PATH"; // for Windows //$NON-NLS-1$
268-285: Increase timeout for target listing process.The current 3-second timeout (10 × 300ms) is too short for the
list-targetscommand, which often takes longer on first run.-while (process.isAlive() && waitCount > 0) -{ - try - { - Thread.sleep(300); - } - catch (InterruptedException e) - { - Logger.log(e); - } - waitCount--; -} - -if (waitCount == 0) -{ - log("Process possibly stuck", IStatus.ERROR); //$NON-NLS-1$ - return Status.CANCEL_STATUS; -} +try +{ + if (!process.waitFor(120, TimeUnit.SECONDS)) + { + process.destroyForcibly(); + log("Process timed out after 2 minutes", IStatus.ERROR); + return Status.CANCEL_STATUS; + } +} +catch (InterruptedException e) +{ + Thread.currentThread().interrupt(); + Logger.log(e); + return Status.CANCEL_STATUS; +}
453-471: Add null check and use correct path separator.The
executablePathcan be null and the hard-coded semicolon separator only works on Windows.private void addGitToEnvironment(Map<String, String> envMap, String executablePath) { + if (executablePath == null) + { + return; + } + IPath gitPath = new Path(executablePath); if (gitPath.toFile().exists()) { String gitDir = gitPath.removeLastSegments(1).toOSString(); String path1 = envMap.get("PATH"); //$NON-NLS-1$ String path2 = envMap.get("Path"); //$NON-NLS-1$ if (!StringUtil.isEmpty(path1) && !path1.contains(gitDir)) // Git not found on the PATH environment { - path1 = gitDir.concat(";").concat(path1); //$NON-NLS-1$ + path1 = gitDir.concat(File.pathSeparator).concat(path1); envMap.put("PATH", path1); //$NON-NLS-1$ } else if (!StringUtil.isEmpty(path2) && !path2.contains(gitDir)) // Git not found on the Path environment { - path2 = gitDir.concat(";").concat(path2); //$NON-NLS-1$ + path2 = gitDir.concat(File.pathSeparator).concat(path2); envMap.put("Path", path2); //$NON-NLS-1$ } } }bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (3)
89-98: Singleton keeps mutable global state causing potential race conditions.The static
eimJsonfield is overwritten on everygetInstance()call without synchronization, potentially causing race conditions and stale data issues.Consider passing
EimJsonthrough explicit method parameters instead of storing it as mutable static state.
403-407: Heavy external process executed on UI thread for every cell refresh.The
getIdfVersion()method launches shell processes and waits for completion in the UI thread, causing the table to freeze during repaints.Cache the version per
IdfInstalledinstance or compute it in a background job and update the viewer asynchronously.
544-556: Comparator logic doesn't match column assignments.The comparator switch statement logic doesn't align with the column index assignments. Case 0 should compare versions, case 1 should compare names, case 2 should compare paths.
switch (propertyIndex) { case 0: - rc = p1.getName().compareTo(p2.getName()); + rc = ToolsUtility.getIdfVersion(p1, eimJson.getGitPath()) + .compareTo(ToolsUtility.getIdfVersion(p2, eimJson.getGitPath())); break; case 1: - rc = p1.getPath().compareTo(p2.getPath()); + rc = p1.getName().compareTo(p2.getName()); break; case 2: - Boolean p1State = ToolsUtility.isIdfInstalledActive(p1); - Boolean p2State = ToolsUtility.isIdfInstalledActive(p2); - rc = p1State.compareTo(p2State); + rc = p1.getPath().compareTo(p2.getPath()); break;bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (2)
148-152: Fix MessageDialog constructor parameter order.The
MessageDialogconstructor parameters are in the wrong order. The constructor expects(Shell, String, Image, String, int, String[], int)but you're passing two int values before the String array.-MessageDialog messageDialog = new MessageDialog(display.getActiveShell(), - Messages.OldConfigFoundMsgBoxTitle, null, Messages.OldConfigFoundMsgBoxMsg, 0, 0, - new String[] { Messages.ToolsInitializationDifferentPathMessageBoxOptionYes, - Messages.ToolsInitializationDifferentPathMessageBoxOptionNo }); +MessageDialog messageDialog = new MessageDialog(display.getActiveShell(), + Messages.OldConfigFoundMsgBoxTitle, null, Messages.OldConfigFoundMsgBoxMsg, + MessageDialog.QUESTION, new String[] { Messages.ToolsInitializationDifferentPathMessageBoxOptionYes, + Messages.ToolsInitializationDifferentPathMessageBoxOptionNo }, 0);
294-300: Add null check for workbench window.The
EclipseHandler.getActiveWorkbenchWindow()can return null during early startup, but the code callsgetActivePage()without checking.private void openEspIdfManager(EimJson eimJson) { Display.getDefault().asyncExec(() -> { IWorkbenchWindow window = EclipseHandler.getActiveWorkbenchWindow(); + if (window == null) + { + Logger.log("Workbench window not available – skipping ESP-IDF manager opening"); + return; + } + IDFUtil.closeWelcomePage(window); try { EimEditorInput input = new EimEditorInput(eimJson); input.setFirstStartup(true); IDE.openEditor(window.getActivePage(), input, ESPIDFManagerEditor.EDITOR_ID); - IDFUtil.closeWelcomePage(window); }
🧹 Nitpick comments (2)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimConstants.java (1)
10-10: Use Paths.get() consistently for path constructionConsider using
Paths.get()for all path construction instead of string concatenation for better platform compatibility and consistency.-String EIM_POSIX_DIR = System.getProperty("user.home").concat(File.separator + ".espressif" + File.separator + "tools" + File.separator); +String EIM_POSIX_DIR = Paths.get(System.getProperty("user.home"), ".espressif", "tools").toString() + File.separator; -String EIM_WIN_DIR = EIM_WIN_ESPRESSIF_DIR + File.separator + "tools" + File.separator; +String EIM_WIN_DIR = Paths.get(EIM_WIN_ESPRESSIF_DIR, "tools").toString() + File.separator; -String EIM_POSIX_PATH = EIM_POSIX_DIR + EIM_JSON; +String EIM_POSIX_PATH = Paths.get(EIM_POSIX_DIR, EIM_JSON).toString();Also applies to: 14-14, 20-20
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimLoader.java (1)
305-320: Improve process monitoring implementationThe
waitForProcessWindowsmethod uses a busy-wait loop with Thread.sleep which is inefficient and could miss process termination events.Consider using a more efficient approach with exponential backoff:
private IStatus waitForProcessWindows() { + int sleepTime = 100; // Start with 100ms + final int maxSleepTime = 5000; // Max 5 seconds + while (isWindowsProcessAlive(windowsPid)) { try { - Thread.sleep(1000); + Thread.sleep(sleepTime); + // Exponential backoff up to max + sleepTime = Math.min(sleepTime * 2, maxSleepTime); } catch (InterruptedException e) { Logger.log(e); + Thread.currentThread().interrupt(); + return Status.CANCEL_STATUS; } } return Status.OK_STATUS; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java(2 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/DownloadListener.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/EimLoader.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/ToolInitializer.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonChangeListener.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java(4 hunks)bundles/com.espressif.idf.ui/plugin.xml(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeAnalysisEditor.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeDataManager.java(2 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EimButtonLaunchListener.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java(1 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/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/tools/watcher/EimJsonUiChangeHandler.java(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/DownloadListener.java
🚧 Files skipped from review as they are similar to previous changes (8)
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeDataManager.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java
- bundles/com.espressif.idf.ui/plugin.xml
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java
🧰 Additional context used
🧬 Code Graph Analysis (2)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-141)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimLoader.java (3)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-141)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java (1)
EimJsonWatchService(24-192)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/StringUtil.java (1)
StringUtil(11-25)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: build_macos
- GitHub Check: build_macos
🔇 Additional comments (8)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeAnalysisEditor.java (1)
79-82: LGTM! Good addition for handling the master branch.The special case handling for "master" version is a sensible improvement that bypasses numeric version parsing for the development branch. The case-insensitive comparison and early return are appropriate design choices.
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonChangeListener.java (1)
14-17: LGTM! Well-designed listener interface.The interface is focused and follows good design principles with clear documentation and appropriate method signature.
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties (1)
1-16: LGTM! UI messages are clear and well-structured.The localization strings are appropriately defined for the ESP-IDF Manager UI.
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EimButtonLaunchListener.java (1)
115-137: Add null check for workbench window.The method doesn't check if
activewwis null before callinggetActivePage(), which could cause a NPE during startup or in headless environments.private void launchEspIdfManager() throws PartInitException { Display.getDefault().asyncExec(() -> { IWorkbenchWindow activeww = EclipseHandler.getActiveWorkbenchWindow(); - if (activeww == null || activeww.getActivePage() == null) + if (activeww == null) { - Logger.log("Cannot open ESP-IDF Manager. No active workbench window or active page."); + Logger.log("Cannot open ESP-IDF Manager. No active workbench window."); return; } + + if (activeww.getActivePage() == null) + { + Logger.log("Cannot open ESP-IDF Manager. No active page."); + return; + }Likely an incorrect or invalid review comment.
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java (3)
53-74: LGTM! Well-implemented thread-safe singleton.The Holder idiom is correctly used for thread-safe lazy initialization of the singleton, and proper exception handling is in place for initialization failures.
89-107: LGTM! Robust utility method for pausing listeners.The
withPausedListenersmethod properly handles the pause/unpause lifecycle with exception safety using try-finally, ensuring listeners are properly restored even if the task throws an exception.
122-178: LGTM! Proper file watching implementation.The main watching loop correctly handles interruptions, closed watch services, and overflow events. Resource cleanup is properly handled in the finally block equivalent.
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java (1)
15-47: LGTM - Standard NLS Messages class structure.The class follows proper Eclipse NLS patterns with correct initialization and structure.
| public IStatus exportOldConfig(String eimPath) throws IOException | ||
| { | ||
| File oldConfig = getOldConfigFile(); | ||
| if (oldConfig.exists()) | ||
| { | ||
| // eim import pathToOldConfigJson | ||
| List<String> commands = new ArrayList<>(); | ||
| commands.add(StringUtil.isEmpty(eimPath) ? | ||
| idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.EIM_PATH) : eimPath); | ||
| commands.add("import"); //$NON-NLS-1$ | ||
| commands.add(oldConfig.getAbsolutePath()); | ||
| Logger.log("Running: " + commands.toString()); //$NON-NLS-1$ | ||
| ProcessBuilderFactory processBuilderFactory = new ProcessBuilderFactory(); | ||
| IStatus status = processBuilderFactory.runInBackground(commands, org.eclipse.core.runtime.Path.ROOT, | ||
| System.getenv()); | ||
|
|
||
| Logger.log(status.getMessage()); | ||
| return status; | ||
| } | ||
|
|
||
| return new Status(IStatus.ERROR, IDFCorePlugin.getId(), -1, "Error in conversion", null); //$NON-NLS-1$ | ||
| } |
There was a problem hiding this comment.
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 and command construction
The exportOldConfig method has a couple of issues:
- The error message is generic and doesn't help diagnose the problem
- The ternary operator for eimPath makes the code less readable
public IStatus exportOldConfig(String eimPath) throws IOException
{
File oldConfig = getOldConfigFile();
if (oldConfig.exists())
{
// eim import pathToOldConfigJson
List<String> commands = new ArrayList<>();
- commands.add(StringUtil.isEmpty(eimPath) ?
- idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.EIM_PATH) : eimPath);
+ String effectiveEimPath = StringUtil.isEmpty(eimPath)
+ ? idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.EIM_PATH)
+ : eimPath;
+ if (StringUtil.isEmpty(effectiveEimPath))
+ {
+ return new Status(IStatus.ERROR, IDFCorePlugin.getId(), -1,
+ "EIM path not found in environment or parameters", null);
+ }
+ commands.add(effectiveEimPath);
commands.add("import"); //$NON-NLS-1$
commands.add(oldConfig.getAbsolutePath());
Logger.log("Running: " + commands.toString()); //$NON-NLS-1$
ProcessBuilderFactory processBuilderFactory = new ProcessBuilderFactory();
IStatus status = processBuilderFactory.runInBackground(commands, org.eclipse.core.runtime.Path.ROOT,
System.getenv());
Logger.log(status.getMessage());
return status;
}
- return new Status(IStatus.ERROR, IDFCorePlugin.getId(), -1, "Error in conversion", null); //$NON-NLS-1$
+ return new Status(IStatus.ERROR, IDFCorePlugin.getId(), -1,
+ "Old configuration file not found at: " + oldConfig.getAbsolutePath(), 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.
| public IStatus exportOldConfig(String eimPath) throws IOException | |
| { | |
| File oldConfig = getOldConfigFile(); | |
| if (oldConfig.exists()) | |
| { | |
| // eim import pathToOldConfigJson | |
| List<String> commands = new ArrayList<>(); | |
| commands.add(StringUtil.isEmpty(eimPath) ? | |
| idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.EIM_PATH) : eimPath); | |
| commands.add("import"); //$NON-NLS-1$ | |
| commands.add(oldConfig.getAbsolutePath()); | |
| Logger.log("Running: " + commands.toString()); //$NON-NLS-1$ | |
| ProcessBuilderFactory processBuilderFactory = new ProcessBuilderFactory(); | |
| IStatus status = processBuilderFactory.runInBackground(commands, org.eclipse.core.runtime.Path.ROOT, | |
| System.getenv()); | |
| Logger.log(status.getMessage()); | |
| return status; | |
| } | |
| return new Status(IStatus.ERROR, IDFCorePlugin.getId(), -1, "Error in conversion", null); //$NON-NLS-1$ | |
| } | |
| public IStatus exportOldConfig(String eimPath) throws IOException | |
| { | |
| File oldConfig = getOldConfigFile(); | |
| if (oldConfig.exists()) | |
| { | |
| // eim import pathToOldConfigJson | |
| List<String> commands = new ArrayList<>(); | |
| String effectiveEimPath = StringUtil.isEmpty(eimPath) | |
| ? idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.EIM_PATH) | |
| : eimPath; | |
| if (StringUtil.isEmpty(effectiveEimPath)) | |
| { | |
| return new Status(IStatus.ERROR, IDFCorePlugin.getId(), -1, | |
| "EIM path not found in environment or parameters", null); | |
| } | |
| commands.add(effectiveEimPath); | |
| commands.add("import"); //$NON-NLS-1$ | |
| commands.add(oldConfig.getAbsolutePath()); | |
| Logger.log("Running: " + commands.toString()); //$NON-NLS-1$ | |
| ProcessBuilderFactory processBuilderFactory = new ProcessBuilderFactory(); | |
| IStatus status = processBuilderFactory.runInBackground(commands, org.eclipse.core.runtime.Path.ROOT, | |
| System.getenv()); | |
| Logger.log(status.getMessage()); | |
| return status; | |
| } | |
| return new Status(IStatus.ERROR, IDFCorePlugin.getId(), -1, | |
| "Old configuration file not found at: " + oldConfig.getAbsolutePath(), null); | |
| } |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java
between lines 78 and 99, improve error handling by replacing the generic error
message with a more descriptive one that includes context about the failure.
Refactor the command construction by replacing the ternary operator with a
clearer if-else statement to assign the eimPath value, enhancing code
readability.
| private void storePid(Process powershellProcess) | ||
| { | ||
| try (BufferedReader reader = new BufferedReader(new InputStreamReader(powershellProcess.getInputStream()))) | ||
| { | ||
| String line; | ||
| while ((line = reader.readLine()) != null) | ||
| { | ||
| line = line.trim(); | ||
| if (!line.isEmpty()) | ||
| { | ||
| try | ||
| { | ||
| windowsPid = Long.parseLong(line); | ||
|
|
||
| } | ||
| catch (NumberFormatException ignored) | ||
| { | ||
| // skipping invalid lines | ||
| } | ||
| } | ||
| } | ||
| } | ||
| catch (IOException e) | ||
| { | ||
| Logger.log(e); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix variable reference bug in isWindowsProcessAlive check
The storePid method stores the PID in windowsPid field, but in isWindowsProcessAlive method at line 336, it uses windowsPid instead of the pid parameter.
private boolean isWindowsProcessAlive(long pid)
{
try
{
Process check = new ProcessBuilder("cmd.exe", //$NON-NLS-1$
"/c", //$NON-NLS-1$
"tasklist", //$NON-NLS-1$
"/FI", //$NON-NLS-1$
"\"PID eq " + pid + "\"").redirectErrorStream(true).start(); //$NON-NLS-1$ //$NON-NLS-2$
try (BufferedReader reader = new BufferedReader(new InputStreamReader(check.getInputStream())))
{
String line;
while ((line = reader.readLine()) != null)
{
- if (line.contains(String.valueOf(windowsPid)))
+ if (line.contains(String.valueOf(pid)))
{
return true;
}
}
}
}
catch (IOException e)
{
Logger.log(e);
}
return false;
}📝 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.
| private void storePid(Process powershellProcess) | |
| { | |
| try (BufferedReader reader = new BufferedReader(new InputStreamReader(powershellProcess.getInputStream()))) | |
| { | |
| String line; | |
| while ((line = reader.readLine()) != null) | |
| { | |
| line = line.trim(); | |
| if (!line.isEmpty()) | |
| { | |
| try | |
| { | |
| windowsPid = Long.parseLong(line); | |
| } | |
| catch (NumberFormatException ignored) | |
| { | |
| // skipping invalid lines | |
| } | |
| } | |
| } | |
| } | |
| catch (IOException e) | |
| { | |
| Logger.log(e); | |
| } | |
| } | |
| private boolean isWindowsProcessAlive(long pid) | |
| { | |
| try | |
| { | |
| Process check = new ProcessBuilder("cmd.exe", //$NON-NLS-1$ | |
| "/c", //$NON-NLS-1$ | |
| "tasklist", //$NON-NLS-1$ | |
| "/FI", //$NON-NLS-1$ | |
| "\"PID eq " + pid + "\"").redirectErrorStream(true).start(); //$NON-NLS-1$ //$NON-NLS-2$ | |
| try (BufferedReader reader = new BufferedReader(new InputStreamReader(check.getInputStream()))) | |
| { | |
| String line; | |
| while ((line = reader.readLine()) != null) | |
| { | |
| if (line.contains(String.valueOf(pid))) | |
| { | |
| return true; | |
| } | |
| } | |
| } | |
| } | |
| catch (IOException e) | |
| { | |
| Logger.log(e); | |
| } | |
| return false; | |
| } |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimLoader.java
around lines 150 to 176, the storePid method correctly assigns the process ID to
the windowsPid field, but in the isWindowsProcessAlive method at line 336, the
code incorrectly uses the windowsPid field instead of the method's pid
parameter. To fix this, update isWindowsProcessAlive to use the pid parameter
for its checks instead of the windowsPid field to ensure it verifies the correct
process ID.
| private Path unzip(Path zipPath, Path destDir) throws IOException | ||
| { | ||
| Files.createDirectories(destDir); | ||
| Path firstExecutable = null; | ||
|
|
||
| try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipPath.toFile()))) | ||
| { | ||
| ZipEntry entry; | ||
| while ((entry = zis.getNextEntry()) != null) | ||
| { | ||
| Path newPath = destDir.resolve(entry.getName()); | ||
| if (entry.isDirectory()) | ||
| { | ||
| Files.createDirectories(newPath); | ||
| } | ||
| else | ||
| { | ||
| Files.createDirectories(newPath.getParent()); | ||
| Files.copy(zis, newPath, StandardCopyOption.REPLACE_EXISTING); | ||
| if (firstExecutable == null && Files.isRegularFile(newPath)) | ||
| { | ||
| newPath.toFile().setExecutable(true); | ||
| firstExecutable = newPath; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return firstExecutable != null ? firstExecutable : destDir; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Ensure executable permissions are set correctly
The unzip method only sets executable permission on the first file, which may not be the actual executable. This could cause issues on Linux/macOS.
private Path unzip(Path zipPath, Path destDir) throws IOException
{
Files.createDirectories(destDir);
Path firstExecutable = null;
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipPath.toFile())))
{
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null)
{
Path newPath = destDir.resolve(entry.getName());
if (entry.isDirectory())
{
Files.createDirectories(newPath);
}
else
{
Files.createDirectories(newPath.getParent());
Files.copy(zis, newPath, StandardCopyOption.REPLACE_EXISTING);
- if (firstExecutable == null && Files.isRegularFile(newPath))
+ // Check if this is likely an executable (no extension or specific extensions)
+ String fileName = newPath.getFileName().toString();
+ if (Files.isRegularFile(newPath) &&
+ (fileName.equals("eim") || fileName.endsWith(".sh") ||
+ !fileName.contains(".") || entry.getMethod() == ZipEntry.STORED))
{
newPath.toFile().setExecutable(true);
- firstExecutable = newPath;
+ if (firstExecutable == null && fileName.equals("eim"))
+ {
+ firstExecutable = newPath;
+ }
}
}
}
}
return firstExecutable != null ? firstExecutable : destDir;
}📝 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.
| private Path unzip(Path zipPath, Path destDir) throws IOException | |
| { | |
| Files.createDirectories(destDir); | |
| Path firstExecutable = null; | |
| try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipPath.toFile()))) | |
| { | |
| ZipEntry entry; | |
| while ((entry = zis.getNextEntry()) != null) | |
| { | |
| Path newPath = destDir.resolve(entry.getName()); | |
| if (entry.isDirectory()) | |
| { | |
| Files.createDirectories(newPath); | |
| } | |
| else | |
| { | |
| Files.createDirectories(newPath.getParent()); | |
| Files.copy(zis, newPath, StandardCopyOption.REPLACE_EXISTING); | |
| if (firstExecutable == null && Files.isRegularFile(newPath)) | |
| { | |
| newPath.toFile().setExecutable(true); | |
| firstExecutable = newPath; | |
| } | |
| } | |
| } | |
| } | |
| return firstExecutable != null ? firstExecutable : destDir; | |
| } | |
| private Path unzip(Path zipPath, Path destDir) throws IOException | |
| { | |
| Files.createDirectories(destDir); | |
| Path firstExecutable = null; | |
| try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipPath.toFile()))) | |
| { | |
| ZipEntry entry; | |
| while ((entry = zis.getNextEntry()) != null) | |
| { | |
| Path newPath = destDir.resolve(entry.getName()); | |
| if (entry.isDirectory()) | |
| { | |
| Files.createDirectories(newPath); | |
| } | |
| else | |
| { | |
| Files.createDirectories(newPath.getParent()); | |
| Files.copy(zis, newPath, StandardCopyOption.REPLACE_EXISTING); | |
| // Check if this is likely an executable (no extension or specific extensions) | |
| String fileName = newPath.getFileName().toString(); | |
| if (Files.isRegularFile(newPath) && | |
| (fileName.equals("eim") || fileName.endsWith(".sh") || | |
| !fileName.contains(".") || entry.getMethod() == ZipEntry.STORED)) | |
| { | |
| newPath.toFile().setExecutable(true); | |
| if (firstExecutable == null && fileName.equals("eim")) | |
| { | |
| firstExecutable = newPath; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return firstExecutable != null ? firstExecutable : destDir; | |
| } |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimLoader.java
around lines 522 to 550, the unzip method sets executable permission only on the
first extracted file, which might not be the intended executable. Modify the
code to correctly identify and set executable permissions on all relevant files,
or implement logic to determine the actual executable file(s) and set their
permissions accordingly instead of just the first file.
| public String installAndLaunchDmg(Path dmgPath) throws IOException, InterruptedException | ||
| { | ||
| logMessage("Mounting DMG…\n"); //$NON-NLS-1$ | ||
| Process mountProcess = new ProcessBuilder("hdiutil", "attach", dmgPath.toString()) //$NON-NLS-1$ //$NON-NLS-2$ | ||
| .redirectErrorStream(true).start(); | ||
|
|
||
| int mountExit = mountProcess.waitFor(); | ||
| if (mountExit != 0) | ||
| throw new IOException("hdiutil attach failed (exit " + mountExit + "): " //$NON-NLS-1$ //$NON-NLS-2$ | ||
| + readProcessOutput(mountProcess)); | ||
|
|
||
| String volumePath = parseVolumePath(mountProcess.getInputStream()); | ||
| if (volumePath == null) | ||
| throw new IOException("Failed to mount DMG: volume path not found."); //$NON-NLS-1$ | ||
|
|
||
| File[] apps = new File(volumePath).listFiles((dir, name) -> name.endsWith(".app")); //$NON-NLS-1$ | ||
| if (apps == null || apps.length == 0) | ||
| throw new FileNotFoundException("No .app found inside DMG."); //$NON-NLS-1$ | ||
|
|
||
| File appBundle = apps[0]; | ||
| Path targetAppPath = Paths.get("/Applications", appBundle.getName()); //$NON-NLS-1$ | ||
|
|
||
| logMessage("Copying app to /Applications…\n"); //$NON-NLS-1$ | ||
| Process copyProcess = new ProcessBuilder("cp", "-R", appBundle.getAbsolutePath(), //$NON-NLS-1$ //$NON-NLS-2$ | ||
| targetAppPath.toString()).redirectErrorStream(true).start(); | ||
|
|
||
| int copyExit = copyProcess.waitFor(); | ||
| if (copyExit != 0) | ||
| throw new IOException("Copy failed (exit " + copyExit + "): " //$NON-NLS-1$ //$NON-NLS-2$ | ||
| + readProcessOutput(copyProcess)); | ||
|
|
||
| logMessage("Unmounting DMG…\n"); //$NON-NLS-1$ | ||
| Process detachProcess = new ProcessBuilder("hdiutil", "detach", volumePath) //$NON-NLS-1$ //$NON-NLS-2$ | ||
| .redirectErrorStream(true).start(); | ||
|
|
||
| int detachExit = detachProcess.waitFor(); | ||
| if (detachExit != 0) | ||
| throw new IOException("hdiutil detach failed (exit " + detachExit + "): " //$NON-NLS-1$ //$NON-NLS-2$ | ||
| + readProcessOutput(detachProcess)); | ||
|
|
||
| String eimPath = targetAppPath.resolve("Contents/MacOS/eim").toString(); //$NON-NLS-1$ | ||
| new IDFEnvironmentVariables().addEnvVariable(IDFEnvironmentVariables.EIM_PATH, eimPath); | ||
| return eimPath; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add permission check for macOS installation
The DMG installation to /Applications requires admin privileges on macOS but there's no check or user notification about this requirement. The copy might fail silently for non-admin users.
Consider checking write permissions before attempting the copy:
public String installAndLaunchDmg(Path dmgPath) throws IOException, InterruptedException
{
logMessage("Mounting DMG…\n"); //$NON-NLS-1$
Process mountProcess = new ProcessBuilder("hdiutil", "attach", dmgPath.toString()) //$NON-NLS-1$ //$NON-NLS-2$
.redirectErrorStream(true).start();
int mountExit = mountProcess.waitFor();
if (mountExit != 0)
throw new IOException("hdiutil attach failed (exit " + mountExit + "): " //$NON-NLS-1$ //$NON-NLS-2$
+ readProcessOutput(mountProcess));
String volumePath = parseVolumePath(mountProcess.getInputStream());
if (volumePath == null)
throw new IOException("Failed to mount DMG: volume path not found."); //$NON-NLS-1$
File[] apps = new File(volumePath).listFiles((dir, name) -> name.endsWith(".app")); //$NON-NLS-1$
if (apps == null || apps.length == 0)
throw new FileNotFoundException("No .app found inside DMG."); //$NON-NLS-1$
File appBundle = apps[0];
Path targetAppPath = Paths.get("/Applications", appBundle.getName()); //$NON-NLS-1$
+
+ // Check if we have write permissions to /Applications
+ if (!Files.isWritable(Paths.get("/Applications"))) //$NON-NLS-1$
+ {
+ logError("No write permission to /Applications. Admin privileges may be required.\n"); //$NON-NLS-1$
+ // Consider falling back to user Applications folder
+ targetAppPath = Paths.get(System.getProperty("user.home"), "Applications", appBundle.getName()); //$NON-NLS-1$ //$NON-NLS-2$
+ Files.createDirectories(targetAppPath.getParent());
+ }
logMessage("Copying app to /Applications…\n"); //$NON-NLS-1$
Process copyProcess = new ProcessBuilder("cp", "-R", appBundle.getAbsolutePath(), //$NON-NLS-1$ //$NON-NLS-2$
targetAppPath.toString()).redirectErrorStream(true).start();📝 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.
| public String installAndLaunchDmg(Path dmgPath) throws IOException, InterruptedException | |
| { | |
| logMessage("Mounting DMG…\n"); //$NON-NLS-1$ | |
| Process mountProcess = new ProcessBuilder("hdiutil", "attach", dmgPath.toString()) //$NON-NLS-1$ //$NON-NLS-2$ | |
| .redirectErrorStream(true).start(); | |
| int mountExit = mountProcess.waitFor(); | |
| if (mountExit != 0) | |
| throw new IOException("hdiutil attach failed (exit " + mountExit + "): " //$NON-NLS-1$ //$NON-NLS-2$ | |
| + readProcessOutput(mountProcess)); | |
| String volumePath = parseVolumePath(mountProcess.getInputStream()); | |
| if (volumePath == null) | |
| throw new IOException("Failed to mount DMG: volume path not found."); //$NON-NLS-1$ | |
| File[] apps = new File(volumePath).listFiles((dir, name) -> name.endsWith(".app")); //$NON-NLS-1$ | |
| if (apps == null || apps.length == 0) | |
| throw new FileNotFoundException("No .app found inside DMG."); //$NON-NLS-1$ | |
| File appBundle = apps[0]; | |
| Path targetAppPath = Paths.get("/Applications", appBundle.getName()); //$NON-NLS-1$ | |
| logMessage("Copying app to /Applications…\n"); //$NON-NLS-1$ | |
| Process copyProcess = new ProcessBuilder("cp", "-R", appBundle.getAbsolutePath(), //$NON-NLS-1$ //$NON-NLS-2$ | |
| targetAppPath.toString()).redirectErrorStream(true).start(); | |
| int copyExit = copyProcess.waitFor(); | |
| if (copyExit != 0) | |
| throw new IOException("Copy failed (exit " + copyExit + "): " //$NON-NLS-1$ //$NON-NLS-2$ | |
| + readProcessOutput(copyProcess)); | |
| logMessage("Unmounting DMG…\n"); //$NON-NLS-1$ | |
| Process detachProcess = new ProcessBuilder("hdiutil", "detach", volumePath) //$NON-NLS-1$ //$NON-NLS-2$ | |
| .redirectErrorStream(true).start(); | |
| int detachExit = detachProcess.waitFor(); | |
| if (detachExit != 0) | |
| throw new IOException("hdiutil detach failed (exit " + detachExit + "): " //$NON-NLS-1$ //$NON-NLS-2$ | |
| + readProcessOutput(detachProcess)); | |
| String eimPath = targetAppPath.resolve("Contents/MacOS/eim").toString(); //$NON-NLS-1$ | |
| new IDFEnvironmentVariables().addEnvVariable(IDFEnvironmentVariables.EIM_PATH, eimPath); | |
| return eimPath; | |
| } | |
| public String installAndLaunchDmg(Path dmgPath) throws IOException, InterruptedException | |
| { | |
| logMessage("Mounting DMG…\n"); //$NON-NLS-1$ | |
| Process mountProcess = new ProcessBuilder("hdiutil", "attach", dmgPath.toString()) //$NON-NLS-1$ //$NON-NLS-2$ | |
| .redirectErrorStream(true).start(); | |
| int mountExit = mountProcess.waitFor(); | |
| if (mountExit != 0) | |
| throw new IOException("hdiutil attach failed (exit " + mountExit + "): " //$NON-NLS-1$ //$NON-NLS-2$ | |
| + readProcessOutput(mountProcess)); | |
| String volumePath = parseVolumePath(mountProcess.getInputStream()); | |
| if (volumePath == null) | |
| throw new IOException("Failed to mount DMG: volume path not found."); //$NON-NLS-1$ | |
| File[] apps = new File(volumePath).listFiles((dir, name) -> name.endsWith(".app")); //$NON-NLS-1$ | |
| if (apps == null || apps.length == 0) | |
| throw new FileNotFoundException("No .app found inside DMG."); //$NON-NLS-1$ | |
| File appBundle = apps[0]; | |
| Path targetAppPath = Paths.get("/Applications", appBundle.getName()); //$NON-NLS-1$ | |
| // Check if we have write permissions to /Applications | |
| if (!Files.isWritable(Paths.get("/Applications"))) //$NON-NLS-1$ | |
| { | |
| logError("No write permission to /Applications. Admin privileges may be required.\n"); //$NON-NLS-1$ | |
| // Consider falling back to user Applications folder | |
| targetAppPath = Paths.get(System.getProperty("user.home"), "Applications", appBundle.getName()); //$NON-NLS-1$ //$NON-NLS-2$ | |
| Files.createDirectories(targetAppPath.getParent()); | |
| } | |
| logMessage("Copying app to /Applications…\n"); //$NON-NLS-1$ | |
| Process copyProcess = new ProcessBuilder("cp", "-R", appBundle.getAbsolutePath(), //$NON-NLS-1$ //$NON-NLS-2$ | |
| targetAppPath.toString()).redirectErrorStream(true).start(); | |
| int copyExit = copyProcess.waitFor(); | |
| if (copyExit != 0) | |
| throw new IOException("Copy failed (exit " + copyExit + "): " //$NON-NLS-1$ //$NON-NLS-2$ | |
| + readProcessOutput(copyProcess)); | |
| logMessage("Unmounting DMG…\n"); //$NON-NLS-1$ | |
| Process detachProcess = new ProcessBuilder("hdiutil", "detach", volumePath) //$NON-NLS-1$ //$NON-NLS-2$ | |
| .redirectErrorStream(true).start(); | |
| int detachExit = detachProcess.waitFor(); | |
| if (detachExit != 0) | |
| throw new IOException("hdiutil detach failed (exit " + detachExit + "): " //$NON-NLS-1$ //$NON-NLS-2$ | |
| + readProcessOutput(detachProcess)); | |
| String eimPath = targetAppPath.resolve("Contents/MacOS/eim").toString(); //$NON-NLS-1$ | |
| new IDFEnvironmentVariables().addEnvVariable(IDFEnvironmentVariables.EIM_PATH, eimPath); | |
| return eimPath; | |
| } |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimLoader.java
between lines 178 and 221, the method installs an app by copying it to
/Applications without verifying if the user has write permissions there, which
can cause silent failures on macOS for non-admin users. Before starting the copy
process, add a check to confirm write access to the /Applications directory and
if the permission is lacking, throw an IOException or notify the user about the
need for admin privileges to proceed with the installation.
|
|
||
| } | ||
|
|
||
| private class EimDownlaodListener implements DownloadListener |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in class name.
Same typo as above: "EimDownlaodListener" should be "EimDownloadListener".
-private class EimDownlaodListener implements DownloadListener
+private class EimDownloadListener implements DownloadListener📝 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.
| private class EimDownlaodListener implements DownloadListener | |
| private class EimDownloadListener implements DownloadListener |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EimButtonLaunchListener.java
at line 141, fix the typo in the class name by renaming "EimDownlaodListener" to
"EimDownloadListener" to correct the spelling.
| this.errorConsoleStream = errorConsoleStream; | ||
| preferences = org.eclipse.core.runtime.preferences.InstanceScope.INSTANCE.getNode(UIPlugin.PLUGIN_ID); | ||
| toolInitializer = new ToolInitializer(preferences); | ||
| eimLoader = new EimLoader(new EimDownlaodListener(), standardConsoleStream, errorConsoleStream, display); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in class name.
There's a typo in the class name: "EimDownlaodListener" should be "EimDownloadListener".
-eimLoader = new EimLoader(new EimDownlaodListener(), standardConsoleStream, errorConsoleStream, display);
+eimLoader = new EimLoader(new EimDownloadListener(), standardConsoleStream, errorConsoleStream, display);📝 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.
| eimLoader = new EimLoader(new EimDownlaodListener(), standardConsoleStream, errorConsoleStream, display); | |
| eimLoader = new EimLoader(new EimDownloadListener(), standardConsoleStream, errorConsoleStream, display); |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EimButtonLaunchListener.java
at line 63, correct the typo in the class name from "EimDownlaodListener" to
"EimDownloadListener" to match the proper class name and avoid compilation
errors.
| public static String EspIdfManagerNameCol; | ||
| public static String EspIdfManagerReloadBtnToolTip; | ||
| public static String EspIdfManagerDeleteBtnToolTip; | ||
| public static String IDFGuideLinkLabel_Text; | ||
| public static String EIMButtonDownloadText; | ||
| public static String EIMButtonLaunchText; | ||
|
|
||
| public static String IDFToolsHandler_ToolsManagerConsole; | ||
|
|
||
| public static String EimJsonChangedMsgTitle; | ||
| public static String EimJsonChangedMsgDetail; | ||
| public static String EimJsonStateChangedMsgDetail; | ||
|
|
||
| public static String MsgYes; | ||
| public static String MsgNo; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify that all message keys are used and have corresponding properties.
The new message keys for EIM functionality look appropriate, but please ensure:
- All these message keys are actually referenced in the UI code
- The corresponding
messages.propertiesfile contains entries for these keys
🏁 Script executed:
#!/bin/bash
# Description: Verify message key usage and properties file existence
# Expected: All keys should be used in Java files and exist in properties
echo "=== Checking for message key usage in Java files ==="
message_keys=(
"EspIdfManagerNameCol"
"IDFGuideLinkLabel_Text"
"EIMButtonDownloadText"
"EIMButtonLaunchText"
"IDFToolsHandler_ToolsManagerConsole"
"EimJsonChangedMsgTitle"
"EimJsonChangedMsgDetail"
"EimJsonStateChangedMsgDetail"
"MsgYes"
"MsgNo"
)
for key in "${message_keys[@]}"; do
echo "Searching for usage of: $key"
rg -A 2 -B 2 "$key" --type java
echo "---"
done
echo "=== Checking for properties file ==="
fd "messages.properties" bundles/com.espressif.idf.ui/
echo "=== Checking properties file content ==="
if [ -f "bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties" ]; then
echo "Properties file found, checking for message keys:"
for key in "${message_keys[@]}"; do
echo "Checking for key: $key"
grep "^$key=" bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties || echo "NOT FOUND: $key"
done
else
echo "Properties file not found at expected location"
fiLength of output: 33639
🏁 Script executed:
#!/bin/bash
echo "=== Verifying usage of EspIdfManagerReloadBtnToolTip in Java sources ==="
rg -n "EspIdfManagerReloadBtnToolTip" --type java || echo "No usages found"Length of output: 639
🏁 Script executed:
#!/bin/bash
echo "=== Searching for usage of EimJsonStateChangedMsgDetail in Java code ==="
rg -n "EimJsonStateChangedMsgDetail" --type java || echo "No usages found"Length of output: 619
Missing reference for EimJsonStateChangedMsgDetail
All new message keys have matching entries in messages.properties and are used in the UI except:
- EimJsonStateChangedMsgDetail – declared in Messages.java and properties but never referenced in any Java source
Please either remove this unused key (and its property) or add its usage where the “state changed” dialog should appear (e.g., in EimJsonUiChangeHandler).
🤖 Prompt for AI Agents
In bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java
lines 23 to 36, the key EimJsonStateChangedMsgDetail is declared but never used
in the Java code. To fix this, either remove the EimJsonStateChangedMsgDetail
declaration from Messages.java and its corresponding entry in
messages.properties if it is not needed, or locate the appropriate place in the
code (such as in EimJsonUiChangeHandler) where the "state changed" dialog should
appear and add a reference to this message key there.
There was a problem hiding this 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 (4)
docs/en/installation.rst (4)
42-43: Grammar & clarity: rewrite awkward sentence
“If you are coming trying to open the workspace from and older version …” is hard to parse and has multiple typos. A concise replacement:-The Espressif-IDE allows you to download and launch the EIM directly from the IDE, making it easier to manage your ESP-IDF versions and tools. If you are coming trying to open the workspace from and older version of Espressif-IDE you will be prompted to convert the older configuration to use with EIM. +Espressif-IDE lets you download and launch EIM directly, making it easy to manage ESP-IDF versions and tools. +If you open a workspace created with an older Espressif-IDE, the IDE prompts you to convert the configuration for use with EIM.
70-71: Break up very long note sentence
The note spans >40 words and mixes two ideas. Split for readability:-Any manual changes made to the ESP-IDF directory will not be reflected in the IDE until you refresh the active ESP-IDF version using the refresh button but if you made any changes to the installation of ESP-IDF using the EIM, those changes will be detected and a popup message will be shown to you to update the ESP-IDF version in the IDE. +Manual changes to the ESP-IDF directory are not reflected until you click the refresh button for the active version. +Changes performed via EIM are detected automatically, and the IDE shows a pop-up prompting you to update the ESP-IDF version.
90-91: Step wording: fix grammar & punctuation-2. Open the Espressif-IDE if already running restart it. +2. If Espressif-IDE is running, restart it.
94-95: Clarify activation instruction-The ESP-IDF Manager editor will open, and you can proceed to select activate against the version you want. +The ESP-IDF Manager editor opens; select the version you want and click the “Activate” radio button.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
docs_readme/images/ToolsManager/ESP-IDF_Manager_Conversion_old_worskpace.pngis excluded by!**/*.pngmedia/ToolsManager/ESP-IDF_Configuration_Download_or_Use_ESP-IDF.pngis excluded by!**/*.pngmedia/ToolsManager/ESP-IDF_Manager_Changed_Installation_Message.pngis excluded by!**/*.pngmedia/ToolsManager/ESP-IDF_Manager_Editor_Screen.pngis excluded by!**/*.pngmedia/ToolsManager/ESP-IDF_Manager_Multiple_versions.pngis excluded by!**/*.png
📒 Files selected for processing (2)
docs/_static/docs_version.js(1 hunks)docs/en/installation.rst(3 hunks)
✅ Files skipped from review due to trivial changes (1)
- docs/_static/docs_version.js
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build_macos
| 3. Once you close the EIM your ESP-IDF Manager editor will be updated with the latest information about the ESP-IDF versions and tools available. | ||
|
|
||
| .. note:: | ||
| Please note that the python executable is not the one from the virtual environment created from the installation of the ESP-IDF via other means like from CLI. If you are selecting an already installed ESP-IDF directory IDE will automatically pick up the python once you have installed the tools | ||
| Please note that the EIM will be the only tool going forward to manage the ESP-IDF versions and tools. The previous versions of the Espressif-IDE used to manage tools internally but now the only point of entry into the ESP-IDF will be through the EIM. | ||
|
|
||
| After you have clicked ``Finish``, you will see the progress in the console for the tools getting installed. Once the installation is done, and if this is the very first set of ESP-IDF installed in the IDE, it will be activated as well. You will see a similar entry in the editor for ESP-IDF Manager: | ||
| After the EIM is closed the ESP-IDF Manager editor will be updated with the latest information about the ESP-IDF versions and tools available.: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove duplicate sentence & stray punctuation
Lines 55 and 60 convey the same information; the second instance also ends with “available.:” (extra “.:”). Keep just one occurrence:
-3. Once you close the EIM your ESP-IDF Manager editor will be updated with the latest information about the ESP-IDF versions and tools available.
-
-After the EIM is closed the ESP-IDF Manager editor will be updated with the latest information about the ESP-IDF versions and tools available.:
+3. After you close EIM, the ESP-IDF Manager editor is refreshed with the latest ESP-IDF versions and tools.📝 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.
| 3. Once you close the EIM your ESP-IDF Manager editor will be updated with the latest information about the ESP-IDF versions and tools available. | |
| .. note:: | |
| Please note that the python executable is not the one from the virtual environment created from the installation of the ESP-IDF via other means like from CLI. If you are selecting an already installed ESP-IDF directory IDE will automatically pick up the python once you have installed the tools | |
| Please note that the EIM will be the only tool going forward to manage the ESP-IDF versions and tools. The previous versions of the Espressif-IDE used to manage tools internally but now the only point of entry into the ESP-IDF will be through the EIM. | |
| After you have clicked ``Finish``, you will see the progress in the console for the tools getting installed. Once the installation is done, and if this is the very first set of ESP-IDF installed in the IDE, it will be activated as well. You will see a similar entry in the editor for ESP-IDF Manager: | |
| After the EIM is closed the ESP-IDF Manager editor will be updated with the latest information about the ESP-IDF versions and tools available.: | |
| 3. After you close EIM, the ESP-IDF Manager editor is refreshed with the latest ESP-IDF versions and tools. | |
| .. note:: | |
| Please note that the EIM will be the only tool going forward to manage the ESP-IDF versions and tools. The previous versions of the Espressif-IDE used to manage tools internally but now the only point of entry into the ESP-IDF will be through the EIM. |
🤖 Prompt for AI Agents
In docs/en/installation.rst around lines 55 to 60, there is a duplicate sentence
about the ESP-IDF Manager editor updating after closing the EIM, and the second
occurrence ends with an extra " .:". Remove the second instance entirely to
eliminate redundancy and delete the stray punctuation to keep only the first,
correct sentence.
There was a problem hiding this 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
♻️ Duplicate comments (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (1)
317-333: Potential NPE when workbench window is not yet available
EclipseHandler.getActiveWorkbenchWindow()can legally returnnullduring very early start-up or headless test runs. Dereferencingwindow.getActivePage()without a null-check will crash the plug-in.private void openEspIdfManager(EimJson eimJson) { Display.getDefault().asyncExec(() -> { IWorkbenchWindow window = EclipseHandler.getActiveWorkbenchWindow(); + if (window == null) + { + Logger.log("Workbench window not available – skipping Esp-IDF manager opening"); + return; + } + IDFUtil.closeWelcomePage(window); try { EimEditorInput input = new EimEditorInput(eimJson); input.setFirstStartup(true); IDE.openEditor(window.getActivePage(), input, ESPIDFManagerEditor.EDITOR_ID); - IDFUtil.closeWelcomePage(window); }
🧹 Nitpick comments (3)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (3)
275-279: Consider reusing console instances for better resource management.Creating new
IDFConsoleinstances for each stream call may be inefficient. Consider reusing a single console instance or implementing proper resource management.+private IDFConsole idfConsole; + private MessageConsoleStream getConsoleStream(boolean errorStream) { - IDFConsole idfConsole = new IDFConsole(); + if (idfConsole == null) { + idfConsole = new IDFConsole(); + } return idfConsole.getConsoleStream("EIM Launch Console", null, errorStream); }
400-413: Improve exception handling and logging.Consider preserving more context from the original exception and simplifying the nested try-catch structure.
@Override public void onError(String message, Exception e) { Display.getDefault().asyncExec(() -> { try { - errorConsoleStream.write("Download Failed: " + e.getMessage()); + String errorMessage = String.format("Download Failed: %s - %s", message, e.getMessage()); + errorConsoleStream.write(errorMessage); } catch (IOException e1) { - Logger.log(e1); + Logger.log("Failed to write error to console", e1); } }); + Logger.log("EIM download failed: " + message, e); }
58-67: Consider architectural improvements for better separation of concerns.This class handles multiple responsibilities: startup orchestration, UI interactions, file operations, and process management. Consider extracting some responsibilities into separate classes for better maintainability and testability.
Potential improvements:
- Extract EIM installation and launch logic into a dedicated
EimInstallationService- Create a
ConfigurationMigrationServicefor old config handling- Separate UI interaction logic into a
StartupUiController- Consider using dependency injection for better testability
This would make the startup class focus primarily on orchestration while delegating specific tasks to specialized services.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/GlobalModalLock.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LaunchBarListener.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build_macos
- GitHub Check: build_macos
🔇 Additional comments (4)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/GlobalModalLock.java (3)
13-19: Well-designed utility class with proper encapsulation.The class follows best practices with a private constructor to prevent instantiation and static methods for utility functionality.
15-15: Appropriate semaphore initialization for exclusive access.The semaphore with 1 permit correctly ensures only one modal dialog can be displayed at a time, preventing UI conflicts.
21-43: Excellent implementation of thread-safe modal dialog management.The implementation correctly:
- Uses a background thread to acquire the semaphore without blocking the UI
- Executes dialog operations on the SWT UI thread via
syncExec- Properly releases the semaphore in the finally block
- Handles InterruptedException by restoring the thread's interrupt status
- Uses descriptive thread naming for debugging
This design will significantly improve UI responsiveness by making modal dialogs asynchronous.
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LaunchBarListener.java (1)
147-157: Excellent refactoring to improve UI responsiveness.The transition from synchronous
MessageDialog.openQuestionto asynchronousGlobalModalLock.showModalis well-executed:
- The callback lambda correctly handles the boolean result
- The
deleteBuildFolderlogic is preserved exactly as before- UI responsiveness is significantly improved by removing the blocking call
- Integration with the GlobalModalLock ensures proper modal dialog serialization
This change aligns perfectly with the architectural improvements mentioned in the PR objectives.
| @Override | ||
| public void onCompleted(String filePath) | ||
| { | ||
| Display.getDefault().syncExec(() -> { | ||
| try | ||
| { | ||
| standardConsoleStream.write("\nEIM Downloaded to: " + filePath + "\nLaunching...\n"); | ||
| } | ||
| catch (IOException e) | ||
| { | ||
| Logger.log(e); | ||
| } | ||
| }); | ||
|
|
||
| Process process = null; | ||
| String appToLaunch = filePath; | ||
| try | ||
| { | ||
| if (filePath.endsWith(".dmg")) | ||
| { | ||
| appToLaunch = eimLoader.installAndLaunchDmg(Paths.get(filePath)); | ||
| } | ||
|
|
||
| idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.EIM_PATH, appToLaunch); | ||
| process = eimLoader.launchEim(appToLaunch); | ||
| } | ||
| catch ( | ||
| IOException | ||
| | InterruptedException e) | ||
| { | ||
| Logger.log(e); | ||
| } | ||
|
|
||
| eimLoader.waitForEimClosure(process, () -> { | ||
| if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported()) | ||
| { | ||
| Logger.log("Old configuration found and not converted"); | ||
| handleOldConfigExport(); | ||
| } | ||
| eimJson = toolInitializer.loadEimJson(); | ||
| openEspIdfManager(eimJson); | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Refactor the onCompleted method to improve maintainability.
This method handles multiple responsibilities: console logging, installation, process management, and UI operations. Consider breaking it down into smaller methods for better error handling and testability.
@Override
public void onCompleted(String filePath)
{
- Display.getDefault().syncExec(() -> {
- try
- {
- standardConsoleStream.write("\nEIM Downloaded to: " + filePath + "\nLaunching...\n");
- }
- catch (IOException e)
- {
- Logger.log(e);
- }
- });
-
- Process process = null;
- String appToLaunch = filePath;
- try
- {
- if (filePath.endsWith(".dmg"))
- {
- appToLaunch = eimLoader.installAndLaunchDmg(Paths.get(filePath));
- }
-
- idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.EIM_PATH, appToLaunch);
- process = eimLoader.launchEim(appToLaunch);
- }
- catch (
- IOException
- | InterruptedException e)
- {
- Logger.log(e);
- }
-
- eimLoader.waitForEimClosure(process, () -> {
- if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported())
- {
- Logger.log("Old configuration found and not converted");
- handleOldConfigExport();
- }
- eimJson = toolInitializer.loadEimJson();
- openEspIdfManager(eimJson);
- });
+ logDownloadCompletion(filePath);
+ Process process = installAndLaunchEim(filePath);
+ setupPostLaunchActions(process);
}
+
+private void logDownloadCompletion(String filePath) {
+ Display.getDefault().syncExec(() -> {
+ try {
+ standardConsoleStream.write("\nEIM Downloaded to: " + filePath + "\nLaunching...\n");
+ } catch (IOException e) {
+ Logger.log(e);
+ }
+ });
+}
+
+private Process installAndLaunchEim(String filePath) {
+ try {
+ String appToLaunch = filePath;
+ if (filePath.endsWith(".dmg")) {
+ appToLaunch = eimLoader.installAndLaunchDmg(Paths.get(filePath));
+ }
+
+ idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.EIM_PATH, appToLaunch);
+ return eimLoader.launchEim(appToLaunch);
+ } catch (IOException | InterruptedException e) {
+ Logger.log(e);
+ return null;
+ }
+}
+
+private void setupPostLaunchActions(Process process) {
+ eimLoader.waitForEimClosure(process, () -> {
+ handlePostLaunchConfiguration();
+ eimJson = toolInitializer.loadEimJson();
+ openEspIdfManager(eimJson);
+ });
+}
+
+private void handlePostLaunchConfiguration() {
+ if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported()) {
+ Logger.log("Old configuration found and not converted");
+ handleOldConfigExport();
+ }
+}📝 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.
| @Override | |
| public void onCompleted(String filePath) | |
| { | |
| Display.getDefault().syncExec(() -> { | |
| try | |
| { | |
| standardConsoleStream.write("\nEIM Downloaded to: " + filePath + "\nLaunching...\n"); | |
| } | |
| catch (IOException e) | |
| { | |
| Logger.log(e); | |
| } | |
| }); | |
| Process process = null; | |
| String appToLaunch = filePath; | |
| try | |
| { | |
| if (filePath.endsWith(".dmg")) | |
| { | |
| appToLaunch = eimLoader.installAndLaunchDmg(Paths.get(filePath)); | |
| } | |
| idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.EIM_PATH, appToLaunch); | |
| process = eimLoader.launchEim(appToLaunch); | |
| } | |
| catch ( | |
| IOException | |
| | InterruptedException e) | |
| { | |
| Logger.log(e); | |
| } | |
| eimLoader.waitForEimClosure(process, () -> { | |
| if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported()) | |
| { | |
| Logger.log("Old configuration found and not converted"); | |
| handleOldConfigExport(); | |
| } | |
| eimJson = toolInitializer.loadEimJson(); | |
| openEspIdfManager(eimJson); | |
| }); | |
| } | |
| @Override | |
| public void onCompleted(String filePath) | |
| { | |
| logDownloadCompletion(filePath); | |
| Process process = installAndLaunchEim(filePath); | |
| setupPostLaunchActions(process); | |
| } | |
| private void logDownloadCompletion(String filePath) { | |
| Display.getDefault().syncExec(() -> { | |
| try { | |
| standardConsoleStream.write("\nEIM Downloaded to: " + filePath + "\nLaunching...\n"); | |
| } catch (IOException e) { | |
| Logger.log(e); | |
| } | |
| }); | |
| } | |
| private Process installAndLaunchEim(String filePath) { | |
| try { | |
| String appToLaunch = filePath; | |
| if (filePath.endsWith(".dmg")) { | |
| appToLaunch = eimLoader.installAndLaunchDmg(Paths.get(filePath)); | |
| } | |
| idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.EIM_PATH, appToLaunch); | |
| return eimLoader.launchEim(appToLaunch); | |
| } catch (IOException | InterruptedException e) { | |
| Logger.log(e); | |
| return null; | |
| } | |
| } | |
| private void setupPostLaunchActions(Process process) { | |
| eimLoader.waitForEimClosure(process, () -> { | |
| handlePostLaunchConfiguration(); | |
| eimJson = toolInitializer.loadEimJson(); | |
| openEspIdfManager(eimJson); | |
| }); | |
| } | |
| private void handlePostLaunchConfiguration() { | |
| if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported()) { | |
| Logger.log("Old configuration found and not converted"); | |
| handleOldConfigExport(); | |
| } | |
| } |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java
between lines 356 and 398, the onCompleted method is handling multiple
responsibilities including console logging, installation, process launching, and
UI updates, which reduces maintainability. Refactor this method by extracting
distinct parts into smaller private methods such as one for logging the download
completion, another for handling installation and launching of the app, and a
third for managing the post-launch UI operations and configuration checks. This
will improve error handling, readability, and testability.
| @Override | ||
| public void earlyStartup() | ||
| { | ||
| preferences = org.eclipse.core.runtime.preferences.InstanceScope.INSTANCE.getNode(UIPlugin.PLUGIN_ID); | ||
| toolInitializer = new ToolInitializer(preferences); | ||
| standardConsoleStream = getConsoleStream(false); | ||
| errorConsoleStream = getConsoleStream(true); | ||
| idfEnvironmentVariables = new IDFEnvironmentVariables(); | ||
| eimLoader = new EimLoader(new StartupClassDownloadEimDownloadListener(), standardConsoleStream, | ||
| errorConsoleStream, Display.getDefault()); | ||
| EimJsonStateChecker stateChecker = new EimJsonStateChecker(preferences); | ||
| eimJsonUiChangeHandler = new EimJsonUiChangeHandler(preferences); | ||
| stateChecker.updateLastSeenTimestamp(); | ||
| EimJsonWatchService.getInstance().addEimJsonChangeListener(eimJsonUiChangeHandler); | ||
|
|
||
| if (!toolInitializer.isEimInstalled() && !toolInitializer.isEimIdfJsonPresent()) | ||
| { | ||
| Logger.log("EIM not installed"); | ||
| notifyMissingTools(); | ||
| return; | ||
| } | ||
|
|
||
| eimJson = toolInitializer.loadEimJson(); | ||
|
|
||
| if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported()) | ||
| { | ||
| Logger.log("Old configuration found and not converted"); | ||
| boolean isEimInApplications = checkIfEimPathMacOsIsInApplications(); | ||
| if (!isEimInApplications) | ||
| { | ||
| promptUserToMoveEimToApplications(); | ||
| } | ||
|
|
||
| EimJsonWatchService.withPausedListeners(() -> handleOldConfigExport()); | ||
| } | ||
| else if (toolInitializer.isEimIdfJsonPresent() && !toolInitializer.isEspIdfSet()) | ||
| { | ||
| promptUserToOpenToolManager(eimJson); | ||
| } | ||
|
|
||
| // Set EimPath on every startup to ensure proper path in configurations | ||
| if (eimJson != null) | ||
| { | ||
| idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.EIM_PATH, eimJson.getEimPath()); | ||
| } | ||
| else | ||
| { | ||
| // Fail-safe call to ensure if the eim is in Applications or user.home it is setup in env vars | ||
| toolInitializer.findAndSetEimPath(); | ||
| } | ||
|
|
||
| if (stateChecker.wasModifiedSinceLastRun()) | ||
| { | ||
| showEimJsonStateChangeNotification(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Refactor the earlyStartup method to improve maintainability.
This method is handling multiple responsibilities: component initialization, installation checks, configuration handling, and UI prompts. Consider breaking it down into smaller, focused methods for better readability and testability.
@Override
public void earlyStartup()
{
- preferences = org.eclipse.core.runtime.preferences.InstanceScope.INSTANCE.getNode(UIPlugin.PLUGIN_ID);
- toolInitializer = new ToolInitializer(preferences);
- standardConsoleStream = getConsoleStream(false);
- errorConsoleStream = getConsoleStream(true);
- idfEnvironmentVariables = new IDFEnvironmentVariables();
- eimLoader = new EimLoader(new StartupClassDownloadEimDownloadListener(), standardConsoleStream,
- errorConsoleStream, Display.getDefault());
- EimJsonStateChecker stateChecker = new EimJsonStateChecker(preferences);
- eimJsonUiChangeHandler = new EimJsonUiChangeHandler(preferences);
- stateChecker.updateLastSeenTimestamp();
- EimJsonWatchService.getInstance().addEimJsonChangeListener(eimJsonUiChangeHandler);
-
- if (!toolInitializer.isEimInstalled() && !toolInitializer.isEimIdfJsonPresent())
- {
- Logger.log("EIM not installed");
- notifyMissingTools();
- return;
- }
-
- eimJson = toolInitializer.loadEimJson();
-
- if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported())
- {
- Logger.log("Old configuration found and not converted");
- boolean isEimInApplications = checkIfEimPathMacOsIsInApplications();
- if (!isEimInApplications)
- {
- promptUserToMoveEimToApplications();
- }
-
- EimJsonWatchService.withPausedListeners(() -> handleOldConfigExport());
- }
- else if (toolInitializer.isEimIdfJsonPresent() && !toolInitializer.isEspIdfSet())
- {
- promptUserToOpenToolManager(eimJson);
- }
-
- // Set EimPath on every startup to ensure proper path in configurations
- if (eimJson != null)
- {
- idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.EIM_PATH, eimJson.getEimPath());
- }
- else
- {
- // Fail-safe call to ensure if the eim is in Applications or user.home it is setup in env vars
- toolInitializer.findAndSetEimPath();
- }
-
- if (stateChecker.wasModifiedSinceLastRun())
- {
- showEimJsonStateChangeNotification();
- }
+ initializeComponents();
+ EimJsonStateChecker stateChecker = setupWatchService();
+
+ if (!isEimAvailable()) {
+ notifyMissingTools();
+ return;
+ }
+
+ eimJson = toolInitializer.loadEimJson();
+ handleConfigurationState();
+ setupEnvironmentVariables();
+
+ if (stateChecker.wasModifiedSinceLastRun()) {
+ showEimJsonStateChangeNotification();
+ }
}
+
+private void initializeComponents() {
+ preferences = org.eclipse.core.runtime.preferences.InstanceScope.INSTANCE.getNode(UIPlugin.PLUGIN_ID);
+ toolInitializer = new ToolInitializer(preferences);
+ standardConsoleStream = getConsoleStream(false);
+ errorConsoleStream = getConsoleStream(true);
+ idfEnvironmentVariables = new IDFEnvironmentVariables();
+ eimLoader = new EimLoader(new StartupClassDownloadEimDownloadListener(), standardConsoleStream,
+ errorConsoleStream, Display.getDefault());
+}
+
+private EimJsonStateChecker setupWatchService() {
+ EimJsonStateChecker stateChecker = new EimJsonStateChecker(preferences);
+ eimJsonUiChangeHandler = new EimJsonUiChangeHandler(preferences);
+ stateChecker.updateLastSeenTimestamp();
+ EimJsonWatchService.getInstance().addEimJsonChangeListener(eimJsonUiChangeHandler);
+ return stateChecker;
+}
+
+private boolean isEimAvailable() {
+ return toolInitializer.isEimInstalled() || toolInitializer.isEimIdfJsonPresent();
+}
+
+private void handleConfigurationState() {
+ if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported()) {
+ handleOldConfiguration();
+ } else if (toolInitializer.isEimIdfJsonPresent() && !toolInitializer.isEspIdfSet()) {
+ promptUserToOpenToolManager(eimJson);
+ }
+}
+
+private void handleOldConfiguration() {
+ Logger.log("Old configuration found and not converted");
+ boolean isEimInApplications = checkIfEimPathMacOsIsInApplications();
+ if (!isEimInApplications) {
+ promptUserToMoveEimToApplications();
+ }
+ EimJsonWatchService.withPausedListeners(() -> handleOldConfigExport());
+}
+
+private void setupEnvironmentVariables() {
+ if (eimJson != null) {
+ idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.EIM_PATH, eimJson.getEimPath());
+ } else {
+ toolInitializer.findAndSetEimPath();
+ }
+}🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java
between lines 69 and 124, the earlyStartup method is doing too many things,
making it hard to read and maintain. Refactor by extracting distinct
responsibilities into separate private methods, such as one for initializing
components, another for checking installation and configuration status, one for
handling old configuration export, and another for managing UI prompts and
environment variable setup. Then call these smaller methods sequentially from
earlyStartup to improve clarity and testability.
There was a problem hiding this 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
♻️ Duplicate comments (3)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (3)
335-351: Potential NPE when workbench window is not yet available.
EclipseHandler.getActiveWorkbenchWindow()can returnnullduring early startup or headless test runs. The code doesn't check for null before callingwindow.getActivePage().Apply the null check as previously suggested:
private void openEspIdfManager(EimJson eimJson) { Display.getDefault().asyncExec(() -> { IWorkbenchWindow window = EclipseHandler.getActiveWorkbenchWindow(); + if (window == null) + { + Logger.log("Workbench window not available – skipping Esp-IDF manager opening"); + return; + } try { EimEditorInput input = new EimEditorInput(eimJson); input.setFirstStartup(true); IDE.openEditor(window.getActivePage(), input, ESPIDFManagerEditor.EDITOR_ID); IDFUtil.closeWelcomePage(window); }
72-121: Consider refactoring the earlyStartup method for better maintainability.The method handles multiple responsibilities including initialization, EIM checks, configuration handling, and environment setup. This makes it harder to test and maintain.
As previously suggested, consider extracting responsibilities into separate methods:
initializeComponents()for component setupcheckEimAvailability()for EIM installation checkshandleConfigurationState()for configuration managementsetupEnvironmentVariables()for environment setup
375-416: Refactor the onCompleted method to improve maintainability.This method handles multiple responsibilities: console logging, installation, process management, and UI operations.
As previously suggested, consider breaking it down into smaller methods for better error handling and testability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-141)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build_macos
- GitHub Check: build_macos
🔇 Additional comments (6)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java (3)
130-204: Excellent implementation of the watch service run loop.The run loop properly handles interrupts, exceptions, and resource cleanup. The duplicate event filtering using timestamps is a good approach to avoid unnecessary notifications.
206-218: Proper thread shutdown mechanism.The interrupt and shutdown methods correctly follow the pattern for stopping long-running threads by setting the running flag and calling interrupt.
33-41: Well-designed thread-safe implementation.The class uses appropriate synchronization mechanisms (
volatilefields andCopyOnWriteArrayList) and properly implements the daemon thread pattern for background monitoring.bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (3)
72-82: Instance field initialization properly resolved.The instance fields are correctly initialized (addressing the previous review comment about using local variables instead of instance fields).
146-158: Excellent UI thread safety implementation.The code properly uses
Display.getDefault().syncExec()andasyncExec()for UI operations, and theGlobalModalLockfor modal dialog synchronization is a good approach.Also applies to: 240-255, 299-323
293-297: Resource management is appropriate.Console streams are properly managed by the Eclipse platform, and process resources are handled by the
eimLoader.waitForEimClosure()method.
| private static class Holder | ||
| { | ||
| private static EimJsonWatchService INSTANCE; | ||
|
|
||
| static | ||
| { | ||
| try | ||
| { | ||
| INSTANCE = new EimJsonWatchService(); | ||
| } | ||
| catch (IOException e) | ||
| { | ||
| Logger.log("Failed to initialize EimJsonWatchService"); //$NON-NLS-1$ | ||
| Logger.log(e); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public static EimJsonWatchService getInstance() | ||
| { | ||
| return Holder.INSTANCE; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle singleton initialization failure more robustly.
If the EimJsonWatchService initialization fails, the INSTANCE field remains null, and subsequent calls to getInstance() will return null without any indication of the failure. This could lead to NPEs in calling code.
Consider throwing a runtime exception or implementing a retry mechanism:
private static class Holder
{
- private static EimJsonWatchService INSTANCE;
+ private static final EimJsonWatchService INSTANCE;
static
{
try
{
INSTANCE = new EimJsonWatchService();
}
catch (IOException e)
{
Logger.log("Failed to initialize EimJsonWatchService");
Logger.log(e);
+ throw new RuntimeException("Failed to initialize EimJsonWatchService", 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.
| private static class Holder | |
| { | |
| private static EimJsonWatchService INSTANCE; | |
| static | |
| { | |
| try | |
| { | |
| INSTANCE = new EimJsonWatchService(); | |
| } | |
| catch (IOException e) | |
| { | |
| Logger.log("Failed to initialize EimJsonWatchService"); //$NON-NLS-1$ | |
| Logger.log(e); | |
| } | |
| } | |
| } | |
| public static EimJsonWatchService getInstance() | |
| { | |
| return Holder.INSTANCE; | |
| } | |
| private static class Holder | |
| { | |
| - private static EimJsonWatchService INSTANCE; | |
| + private static final EimJsonWatchService INSTANCE; | |
| static | |
| { | |
| try | |
| { | |
| INSTANCE = new EimJsonWatchService(); | |
| } | |
| catch (IOException e) | |
| { | |
| Logger.log("Failed to initialize EimJsonWatchService"); //$NON-NLS-1$ | |
| Logger.log(e); | |
| + throw new RuntimeException("Failed to initialize EimJsonWatchService", e); | |
| } | |
| } | |
| } | |
| public static EimJsonWatchService getInstance() | |
| { | |
| return Holder.INSTANCE; | |
| } |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java
between lines 62 and 83, the singleton INSTANCE can remain null if
initialization fails, causing getInstance() to return null and potentially
leading to NullPointerExceptions. Modify the static initializer to throw a
runtime exception after logging the error to prevent returning a null instance,
ensuring callers are immediately aware of the failure instead of silently
receiving null.
| public static void withPausedListeners(Runnable task) | ||
| { | ||
| EimJsonWatchService watchService = getInstance(); | ||
| boolean wasPaused = watchService.paused; | ||
| watchService.pauseListeners(); | ||
|
|
||
| try | ||
| { | ||
| task.run(); | ||
| } | ||
| catch (Exception e) | ||
| { | ||
| Logger.log(e); | ||
| } finally | ||
| { | ||
| if (!wasPaused) | ||
| watchService.unpauseListeners(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider synchronizing the pause/unpause mechanism.
The withPausedListeners method has a potential race condition if multiple threads call it simultaneously. The pause/unpause logic isn't synchronized, which could lead to inconsistent state.
Add synchronization to prevent race conditions:
public static void withPausedListeners(Runnable task)
{
EimJsonWatchService watchService = getInstance();
- boolean wasPaused = watchService.paused;
- watchService.pauseListeners();
+ synchronized (watchService) {
+ boolean wasPaused = watchService.paused;
+ watchService.pauseListeners();
- try
- {
- task.run();
- }
- catch (Exception e)
- {
- Logger.log(e);
- } finally
- {
- if (!wasPaused)
- watchService.unpauseListeners();
+ try
+ {
+ task.run();
+ }
+ catch (Exception e)
+ {
+ Logger.log(e);
+ } finally
+ {
+ if (!wasPaused)
+ watchService.unpauseListeners();
+ }
}
}📝 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.
| public static void withPausedListeners(Runnable task) | |
| { | |
| EimJsonWatchService watchService = getInstance(); | |
| boolean wasPaused = watchService.paused; | |
| watchService.pauseListeners(); | |
| try | |
| { | |
| task.run(); | |
| } | |
| catch (Exception e) | |
| { | |
| Logger.log(e); | |
| } finally | |
| { | |
| if (!wasPaused) | |
| watchService.unpauseListeners(); | |
| } | |
| } | |
| public static void withPausedListeners(Runnable task) | |
| { | |
| EimJsonWatchService watchService = getInstance(); | |
| synchronized (watchService) | |
| { | |
| boolean wasPaused = watchService.paused; | |
| watchService.pauseListeners(); | |
| try | |
| { | |
| task.run(); | |
| } | |
| catch (Exception e) | |
| { | |
| Logger.log(e); | |
| } | |
| finally | |
| { | |
| if (!wasPaused) | |
| watchService.unpauseListeners(); | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java
around lines 98 to 116, the pause and unpause logic in withPausedListeners is
not synchronized, risking race conditions when accessed by multiple threads. To
fix this, synchronize the block that pauses listeners, runs the task, and
conditionally unpauses listeners to ensure only one thread modifies the paused
state at a time, preventing inconsistent state changes.
There was a problem hiding this 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
♻️ Duplicate comments (3)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (3)
318-323: Critical NPE risk - add null check for workbench windowThe
EclipseHandler.getActiveWorkbenchWindow()method can returnnullduring early startup or headless test runs. Callingwindow.getActivePage()without null-checking will cause a NullPointerException.private void openEspIdfManager(EimJson eimJson) { Display.getDefault().asyncExec(() -> { IWorkbenchWindow window = EclipseHandler.getActiveWorkbenchWindow(); + if (window == null) { + Logger.log("Workbench window not available – skipping ESP-IDF manager opening"); + return; + } try { EimEditorInput input = new EimEditorInput(eimJson); input.setFirstStartup(true); IDE.openEditor(window.getActivePage(), input, ESPIDFManagerEditor.EDITOR_ID); IDFUtil.closeWelcomePage(window); }
72-121: Consider refactoring the earlyStartup method for better maintainabilityThis method handles multiple responsibilities: component initialization, installation checks, configuration handling, and UI operations. Breaking it into smaller, focused methods would improve readability and testability.
The method could be decomposed into:
initializeComponents()- lines 74-82handleToolsAvailability()- lines 84-89handleConfigurationStates()- lines 93-108setupEnvironmentVariables()- lines 110-119
355-396: Refactor onCompleted method to reduce complexityThis method handles multiple responsibilities: console logging, installation, process management, and UI operations. Consider extracting these into separate methods for better error handling and maintainability.
The method could be decomposed into:
logDownloadCompletion(String filePath)- lines 357-366installAndLaunchEim(String filePath)- lines 368-385setupPostLaunchActions(Process process)- lines 387-395
🧹 Nitpick comments (2)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (2)
207-211: Simplify lambda expression with no meaningful returnThe lambda returns
nulland the response is ignored. This can be simplified to make the intent clearer.- GlobalModalLock.showModal(() -> { - MessageDialog.openInformation(display.getActiveShell(), messageTitle, message); - return null; - }, ignored -> { - }); + GlobalModalLock.showModal(() -> { + MessageDialog.openInformation(display.getActiveShell(), messageTitle, message); + return null; + }, ignored -> { /* no action needed */ });
181-194: Consider more specific exception handlingThe method catches
IOExceptionbut theexportOldConfigmethod might throw other exceptions. Consider catching more specific exceptions or documenting which exceptions are expected.#!/bin/bash # Check what exceptions the exportOldConfig method can throw ast-grep --pattern 'exportOldConfig($$$) throws $$$'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: build_macos
- GitHub Check: build_linux
- GitHub Check: build_macos
🔇 Additional comments (2)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java (2)
74-81: Approve the instance field initialization fixThe instance fields are now properly initialized in the
earlyStartupmethod, addressing the previous NPE concerns.
343-343: Ensure Java 11+ compatibility for String.repeat()
The code at bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java:343 uses String.repeat(), which is only available starting in Java 11. We were unable to find any Maven/Gradle or PDE/Eclipse configuration that enforces a minimum Java version. Please verify that your target Eclipse runtime or build environment is configured to Java 11 or higher.
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java: line 343
| eimLoader.waitForEimClosure(process, () -> { | ||
| if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported()) | ||
| { | ||
| Logger.log("Old configuration found and not converted"); | ||
| handleOldConfigExport(); | ||
| } | ||
| eimJson = toolInitializer.loadEimJson(); | ||
| openEspIdfManager(eimJson); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Potential race condition in post-launch configuration handling
The callback executed after EIM closure may run on a different thread. Consider thread safety when accessing toolInitializer and eimJson fields.
🏁 Script executed:
#!/bin/bash
# Check the EimLoader.waitForEimClosure method to understand threading model
ast-grep --pattern 'waitForEimClosure($_, $_) {
$$$
}'Length of output: 58
🏁 Script executed:
#!/bin/bash
# Broaden search for the waitForEimClosure implementation and EimLoader class
rg -n 'waitForEimClosure' .
rg -n 'class EimLoader' .
# If EimLoader.java exists, print its header to inspect its threading behavior
fd 'EimLoader.java' -x sed -n '1,200p' {}Length of output: 7035
🏁 Script executed:
#!/bin/bash
# Extract the implementation of waitForEimClosure to inspect threading behavior
sed -n '350,460p' bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimLoader.javaLength of output: 2745
Ensure UI interactions occur on the SWT UI thread
The Runnable you pass into waitForEimClosure is invoked from the background Job’s done() callback (i.e. not on the UI thread). Any calls to handleOldConfigExport(), loadEimJson(), or openEspIdfManager(...) (which touch UI/model state) must be wrapped in Display.asyncExec(...). For example, in EspressifToolStartup.java:
- eimLoader.waitForEimClosure(process, () -> {
- if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported())
- {
- Logger.log("Old configuration found and not converted");
- handleOldConfigExport();
- }
- eimJson = toolInitializer.loadEimJson();
- openEspIdfManager(eimJson);
- });
+ eimLoader.waitForEimClosure(process, () -> {
+ Display.getDefault().asyncExec(() -> {
+ if (toolInitializer.isOldEspIdfConfigPresent() && !toolInitializer.isOldConfigExported()) {
+ Logger.log("Old configuration found and not converted");
+ handleOldConfigExport();
+ }
+ JsonObject eimJson = toolInitializer.loadEimJson();
+ openEspIdfManager(eimJson);
+ });
+ });Alternatively, you could modify EimLoader.done() so that it invokes callback.run() inside Display.asyncExec.
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java
around lines 387 to 395, the Runnable passed to waitForEimClosure runs on a
background thread, but it calls UI-related methods like handleOldConfigExport(),
loadEimJson(), and openEspIdfManager() which must run on the SWT UI thread. To
fix this, wrap the entire Runnable body inside Display.asyncExec(...) so these
UI interactions execute on the UI thread, ensuring thread safety and preventing
UI errors.
There was a problem hiding this 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
♻️ Duplicate comments (4)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (4)
90-99: Singleton pattern still has thread safety and mutable state issuesThe static
EimJsonfield is overwritten on eachgetInstance()call without synchronization, creating race conditions and potential stale data issues for concurrent access.
278-309: Color leak when columns are recreated
setupColumns()disposesTableViewerColumns but the associatedColumnLabelProvider(which owns an SWTColor) is not disposed until the viewer is disposed. SincesetupColumns()is called repeatedly inrefreshEditorUI(), Color objects accumulate.
412-416: Heavy external process executed on UI thread for every cell refresh
getIdfVersion()launches external processes and waits for completion on the UI thread, causing table freezing during repaints. This is particularly problematic with the new name column adding more cells.
555-570: Comparator index/order mismatch leads to wrong sortingThe comparator cases don't match the column setup indices. Version column (index 0) sorts by name, Name column (index 1) sorts by path, Location column (index 2) sorts by active state - all incorrect.
🧹 Nitpick comments (2)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (2)
122-122: Avoid hardcoded URLsThe support periods URL is hardcoded, making it difficult to update and maintain.
- .browse(new java.net.URI("https://dl.espressif.com/dl/esp-idf/support-periods.svg")); + .browse(new java.net.URI(Messages.IDF_SUPPORT_PERIODS_URL));
250-276: Add null checks before disposing columnsThe
disposeColumns()method should check if columns are already disposed before attempting to dispose them to avoid potential exceptions.if (activateColumn != null && activateColumn.getColumn() != null) { + if (!activateColumn.getColumn().isDisposed()) { activateColumn.getColumn().dispose(); + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java(11 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build_macos
- GitHub Check: build_linux
| SetupToolsInIde setupToolsInIde = new SetupToolsInIde(idfInstalledList.get(0), eimJson, | ||
| getConsoleStream(true), getConsoleStream(false)); | ||
| SetupToolsJobListener toolsActivationJobListener = new SetupToolsJobListener(ESPIDFMainTablePage.this, | ||
| setupToolsInIde); | ||
| setupToolsInIde.addJobChangeListener(toolsActivationJobListener); | ||
| setupToolsInIde.schedule(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
No check for concurrent job execution
Multiple SetupToolsInIde jobs can be scheduled simultaneously without checking if previous jobs are still running, potentially causing conflicts.
Consider adding a job state check or using a job family to prevent concurrent execution:
private static final Object SETUP_TOOLS_JOB_FAMILY = new Object();
// In job creation:
setupToolsInIde.setJobFamily(SETUP_TOOLS_JOB_FAMILY);
// Before scheduling:
if (Job.getJobManager().find(SETUP_TOOLS_JOB_FAMILY).length == 0) {
setupToolsInIde.schedule();
}Also applies to: 438-443, 481-486
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java
around lines 145 to 150, the code schedules SetupToolsInIde jobs without
checking if similar jobs are already running, which can cause conflicts. To fix
this, define a static final job family object and assign it to each
SetupToolsInIde job using setJobFamily. Before scheduling a new job, query the
JobManager for running jobs of this family and only schedule if none are found.
Apply the same pattern to the code blocks at lines 438-443 and 481-486 to
prevent concurrent execution of these jobs.
| try | ||
| { | ||
| eimJson = eimIdfConfiguratinParser.getEimJson(true); | ||
| // eimJson is null if EIM was closed before tool installation completed | ||
| if (eimJson == null) | ||
| { | ||
| return; | ||
| } | ||
| } | ||
| catch (IOException e) | ||
| { | ||
| Logger.log(e); | ||
| } |
There was a problem hiding this comment.
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 JSON parsing
The catch block only logs the exception but continues execution, potentially leading to inconsistent state. Consider returning early or setting a flag to indicate the error state.
catch (IOException e)
{
Logger.log(e);
+ // Show error to user and return early
+ 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.
| try | |
| { | |
| eimJson = eimIdfConfiguratinParser.getEimJson(true); | |
| // eimJson is null if EIM was closed before tool installation completed | |
| if (eimJson == null) | |
| { | |
| return; | |
| } | |
| } | |
| catch (IOException e) | |
| { | |
| Logger.log(e); | |
| } | |
| try | |
| { | |
| eimJson = eimIdfConfiguratinParser.getEimJson(true); | |
| // eimJson is null if EIM was closed before tool installation completed | |
| if (eimJson == null) | |
| { | |
| return; | |
| } | |
| } | |
| catch (IOException e) | |
| { | |
| Logger.log(e); | |
| // Show error to user and return early | |
| return; | |
| } |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java
around lines 186 to 198, the catch block for IOException only logs the error but
allows execution to continue, which may cause inconsistent state. Modify the
catch block to return early or set an error flag after logging the exception to
prevent further processing when JSON parsing fails.
| { | ||
| toolSetConfigurationManager = new ToolSetConfigurationManager(); | ||
| idfToolSets = toolSetConfigurationManager.getIdfToolSets(true); | ||
| idfInstalledList = eimJson != null ? eimJson.getIdfInstalled() : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle null EimJson gracefully
When eimJson is null, idfInstalledList becomes null, but the method continues execution which could lead to NPE in subsequent operations.
- idfInstalledList = eimJson != null ? eimJson.getIdfInstalled() : null;
+ if (eimJson == null) {
+ Logger.log("EimJson is null, cannot initialize IDF table");
+ return container;
+ }
+ idfInstalledList = eimJson.getIdfInstalled();📝 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.
| idfInstalledList = eimJson != null ? eimJson.getIdfInstalled() : null; | |
| if (eimJson == null) { | |
| Logger.log("EimJson is null, cannot initialize IDF table"); | |
| return container; | |
| } | |
| idfInstalledList = eimJson.getIdfInstalled(); |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java
at line 103, the assignment sets idfInstalledList to null if eimJson is null,
but subsequent code may not handle this null safely. Modify the code to check if
eimJson is null and if so, either return early from the method or initialize
idfInstalledList to an empty list to prevent NullPointerExceptions later in the
method.
| private MessageConsoleStream getConsoleStream(boolean errorStream) | ||
| { | ||
| IDFConsole idfConsole = new IDFConsole(); | ||
| return idfConsole.getConsoleStream(Messages.IDFToolsHandler_ToolsManagerConsole, null, errorStream, true); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Potential resource leak with repeated console creation
A new IDFConsole is created each time getConsoleStream() is called, which could lead to resource leaks if not properly managed.
+private IDFConsole idfConsole;
+
private MessageConsoleStream getConsoleStream(boolean errorStream)
{
- IDFConsole idfConsole = new IDFConsole();
+ if (idfConsole == null) {
+ idfConsole = new IDFConsole();
+ }
return idfConsole.getConsoleStream(Messages.IDFToolsHandler_ToolsManagerConsole, null, errorStream, true);
}📝 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.
| private MessageConsoleStream getConsoleStream(boolean errorStream) | |
| { | |
| IDFConsole idfConsole = new IDFConsole(); | |
| return idfConsole.getConsoleStream(Messages.IDFToolsHandler_ToolsManagerConsole, null, errorStream, true); | |
| } | |
| private IDFConsole idfConsole; | |
| private MessageConsoleStream getConsoleStream(boolean errorStream) | |
| { | |
| if (idfConsole == null) { | |
| idfConsole = new IDFConsole(); | |
| } | |
| return idfConsole.getConsoleStream( | |
| Messages.IDFToolsHandler_ToolsManagerConsole, | |
| null, | |
| errorStream, | |
| true | |
| ); | |
| } |
🤖 Prompt for AI Agents
In
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java
around lines 516 to 520, the method getConsoleStream creates a new IDFConsole
instance every call, risking resource leaks. Refactor the code to create the
IDFConsole instance once, store it as a class-level field, and reuse this
instance in subsequent calls to getConsoleStream to prevent repeated console
creation and potential leaks.
* Initial integration Initial integration for the eim starting from the start to handle the empty workspace. Tools activation is still to be done along with code cleanup. Just the basic display is working which will also be enhanced. * Initial first flow with successful installation and loading of env in IDE with EIM * constants moved to single place and added refresh function * minor cleanup and logging for user * IEP-1334: code cleanup (Active Review) (#1125) * cleanup of unused classes and code * String internalization * update to ci file * ci error fixed * ci error fix * ci fix * fixing ci error * ci error fix * ci error fix * ci syntax fix * ci syntax indentation fix * ci syntax fix * ci syntax fix * ci fixed * ci fixed2 * ci trigger * workflow trigger fix * cleanup * ci deps isntalled * eim fix * using eim action to install * using Petr's fork * switched back to official action repo * Revert "switched back to official action repo" This reverts commit f8cd7a7. * trying to fix action for eim * trying with petrs fork again * ci fix * back to espressif * name fixed * updated url for eim * old config export handling * fixing tests env setup * logging to verify skip tests * fixing POSIX path resolution * activation script properly sourced * added test run variable in test pom directly * adding cache option for the maven * file name updated * increasing timeout for tests * test fixes and removing redundant and outdated tests * cleanup and update for user messages * updated to handle activation of single esp-idf from eim * removing unwanted test for fixing failures * increased timeout for tests * ci updated for the release branch trigger as well * ci error fix * fix for sdkconfig server * cleaning up the idf_tools_path configuration in the IDE * added the option to include homebrew paths on macos * changes for guide link * Guidance link added to NLS * fix: Launch ESP-IDF Manager view even there is no eim_idf.json file found * fix: Don't launch multiple ESP-IDF Manager editors * fix: Update the msg and convert it to MessageDialog * fix: notify IDF not found while opening Manager view * fix: java.lang.UnsupportedOperationException * fix: File Not found issue and others * updated code for eim watcher added Next commits will do some refactoring and then implement the logic to handle these changes * refactored startup classes * initial base level logic for file watcher So this is very basic first level of file watcher service that watches the file and then also takes care that the file is wasnt changes since last startup. Initial changes only take that the file last modified is verified and just any change in file simply will give you a message box telling that something changed. More advanced and robust checks in upcoming commits * missing copyright added --------- Co-authored-by: Kondal Kolipaka <kondal.kolipaka@espressif.com>
* automatic refresh added * switched to message dialog * improved null checks * file watcher added first
…df.json (#1218) * eim auto import for old config added
* IEP-1552: Fix for system python executable
IEP-1554: Launch and Download of EIM added --------- Co-authored-by: Kondal Kolipaka <kondal.kolipaka@espressif.com>
* IEP-1557: Documentation for the ESP-IDF Manager * version.js added
* IEP-1585: Fixed eim old config import handling
fix: added global modal lock to avoid multiple modals
* IEP-1583: Closing old editor window when old workspace is found * fix: address NPE while launching --------- Co-authored-by: Kondal Kolipaka <kondal.kolipaka@gmail.com>
e887f96 to
cf93936
Compare
There was a problem hiding this 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
🔭 Outside diff range comments (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (1)
552-576: Fix comparator index/order mismatch for correct column sorting.The comparator is told that
versionColumnis index 0,nameColumnis index 1 andlocationColumnis index 2, but thecompare()implementation assumes 0 → name, 1 → path, 2 → active state. Clicking "Version" currently sorts by name, etc.switch (propertyIndex) { case 0: // Version column - rc = p1.getName().compareTo(p2.getName()); + rc = ToolsUtility.getIdfVersion(p1, eimJson.getGitPath()) + .compareTo( + ToolsUtility.getIdfVersion(p2, eimJson.getGitPath())); break; case 1: // Name column - rc = p1.getPath().compareTo(p2.getPath()); + rc = p1.getName().compareTo(p2.getName()); break; case 2: // Location column - Boolean p1State = ToolsUtility.isIdfInstalledActive(p1); - Boolean p2State = ToolsUtility.isIdfInstalledActive(p2); - rc = p1State.compareTo(p2State); + rc = p1.getPath().compareTo(p2.getPath()); break; }
♻️ Duplicate comments (22)
.github/workflows/ci_windows.yml (1)
8-14: Indentation ofbranchesstill off – YAML will not parseSame issue flagged in earlier review: list items are indented 5 spaces instead of the required 6. This is a pure syntax problem; the workflow will be ignored by Actions runners.
on: push: - branches: - - master - - release/** + branches: + - master + - release/** pull_request: - branches: - - master - - release/** + branches: + - master + - release/**.github/workflows/ci.yml (3)
8-14: Fix YAML indentation under triggers (again)Identical to the Windows workflow: the
brancheslist is still indented one space too little, breaking theon:block.on: push: - branches: - - master - - release/** + branches: + - master + - release/** pull_request: - branches: - - master - - release/** + branches: + - master + - release/**
24-27: Upgrade to latestactions/setup-python
v2is deprecated and flagged by actionlint. Move tov4for security and caching improvements.- uses: actions/setup-python@v2 + uses: actions/setup-python@v4
17-22:stepslist incorrectly indented – runner will reject the file
- uses: actions/checkout@v4(and all subsequent steps) must be indented 6 spaces understeps:. Currently it is only 4.steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolInitializer.java (2)
69-80: Improve error handling when loading EimJson.The method catches IOException but returns null on error, which could lead to NullPointerExceptions later when callers try to use the returned object.
Consider returning an empty EimJson object instead of null:
public EimJson loadEimJson() { try { return parser.getEimJson(true); } catch (IOException e) { Logger.log(e); - return null; + // Return an empty EimJson object instead of null + return new EimJson(); } }
118-118: Replace generic error message with descriptive context.The error message "Error in conversion" is too generic and doesn't help diagnose the problem. Consider providing more context about what specifically failed.
- return new Status(IStatus.ERROR, IDFCorePlugin.getId(), -1, "Error in conversion", null); //$NON-NLS-1$ + return new Status(IStatus.ERROR, IDFCorePlugin.getId(), -1, + "Old configuration file not found at: " + getOldConfigFile().getAbsolutePath(), null);bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimLoader.java (3)
322-349: Fix variable reference bug in isWindowsProcessAlive check.The method uses the
windowsPidfield instead of thepidparameter at line 336, which is incorrect.private boolean isWindowsProcessAlive(long pid) { try { Process check = new ProcessBuilder("cmd.exe", //$NON-NLS-1$ "/c", //$NON-NLS-1$ "tasklist", //$NON-NLS-1$ "/FI", //$NON-NLS-1$ "\"PID eq " + pid + "\"").redirectErrorStream(true).start(); //$NON-NLS-1$ //$NON-NLS-2$ try (BufferedReader reader = new BufferedReader(new InputStreamReader(check.getInputStream())) { String line; while ((line = reader.readLine()) != null) { - if (line.contains(String.valueOf(windowsPid))) + if (line.contains(String.valueOf(pid))) { return true; } } } } catch (IOException e) { Logger.log(e); } return false; }
522-550: Ensure executable permissions are set correctly.The unzip method only sets executable permission on the first file, which may not be the actual executable. This could cause issues on Linux/macOS.
Consider implementing logic to correctly identify executable files:
private Path unzip(Path zipPath, Path destDir) throws IOException { Files.createDirectories(destDir); Path firstExecutable = null; try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipPath.toFile()))) { ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { Path newPath = destDir.resolve(entry.getName()); if (entry.isDirectory()) { Files.createDirectories(newPath); } else { Files.createDirectories(newPath.getParent()); Files.copy(zis, newPath, StandardCopyOption.REPLACE_EXISTING); - if (firstExecutable == null && Files.isRegularFile(newPath)) + // Check if this is likely an executable (no extension or specific extensions) + String fileName = newPath.getFileName().toString(); + if (Files.isRegularFile(newPath) && + (fileName.equals("eim") || fileName.endsWith(".sh") || + !fileName.contains(".") || entry.getMethod() == ZipEntry.STORED)) { newPath.toFile().setExecutable(true); - firstExecutable = newPath; + if (firstExecutable == null && fileName.equals("eim")) + { + firstExecutable = newPath; + } } } } } return firstExecutable != null ? firstExecutable : destDir; }
178-221: Add permission check for macOS installation.The DMG installation to
/Applicationsrequires admin privileges on macOS but there's no check or user notification about this requirement. The copy might fail silently for non-admin users.Consider checking write permissions before attempting the copy:
public String installAndLaunchDmg(Path dmgPath) throws IOException, InterruptedException { logMessage("Mounting DMG…\n"); //$NON-NLS-1$ Process mountProcess = new ProcessBuilder("hdiutil", "attach", dmgPath.toString()) //$NON-NLS-1$ //$NON-NLS-2$ .redirectErrorStream(true).start(); int mountExit = mountProcess.waitFor(); if (mountExit != 0) throw new IOException("hdiutil attach failed (exit " + mountExit + "): " //$NON-NLS-1$ //$NON-NLS-2$ + readProcessOutput(mountProcess)); String volumePath = parseVolumePath(mountProcess.getInputStream()); if (volumePath == null) throw new IOException("Failed to mount DMG: volume path not found."); //$NON-NLS-1$ File[] apps = new File(volumePath).listFiles((dir, name) -> name.endsWith(".app")); //$NON-NLS-1$ if (apps == null || apps.length == 0) throw new FileNotFoundException("No .app found inside DMG."); //$NON-NLS-1$ File appBundle = apps[0]; Path targetAppPath = Paths.get("/Applications", appBundle.getName()); //$NON-NLS-1$ + + // Check if we have write permissions to /Applications + if (!Files.isWritable(Paths.get("/Applications"))) //$NON-NLS-1$ + { + logError("No write permission to /Applications. Admin privileges may be required.\n"); //$NON-NLS-1$ + // Consider falling back to user Applications folder + targetAppPath = Paths.get(System.getProperty("user.home"), "Applications", appBundle.getName()); //$NON-NLS-1$ //$NON-NLS-2$ + Files.createDirectories(targetAppPath.getParent()); + } logMessage("Copying app to /Applications…\n"); //$NON-NLS-1$ Process copyProcess = new ProcessBuilder("cp", "-R", appBundle.getAbsolutePath(), //$NON-NLS-1$ //$NON-NLS-2$ targetAppPath.toString()).redirectErrorStream(true).start();bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (6)
77-94: Add null-safe check in rollback method.The
existingEnvVarsInIdeForRollbackmay still benullwhenrollback()is called after an early failure, leading to NPE.public void rollback() { IDFEnvironmentVariables idfEnvironmentVariables = new IDFEnvironmentVariables(); + if (existingEnvVarsInIdeForRollback != null) + { for (Entry<String, String> entry : existingEnvVarsInIdeForRollback.entrySet()) { idfEnvironmentVariables.addEnvVariable(entry.getKey(), entry.getValue()); } + } IDFUtil.updateEspressifPrefPageOpenocdPath(); try { setUpToolChainsAndTargets(true); } catch (Exception e) { Logger.log(e); } }
100-108: Modified environment is ignored when running activation script.The
addGitToEnvironment(env, ...)call mutates the localenvmap, yet the subsequent call passesSystem.getenv()– losing the adjustments. This prevents Git from being onPATHfor the activation script on systems where it is not already present.- IStatus status = processBuilderFactory.runInBackground(arguemnts, Path.ROOT, System.getenv()); + IStatus status = processBuilderFactory.runInBackground(arguemnts, Path.ROOT, env);
406-412: Handle duplicate keys in parseEnvKeys to prevent crashes.When the activation script prints multiple exports for the same variable (e.g., PATH),
Collectors.toMapwithout a merge function will throwIllegalStateException.- .collect(Collectors.toMap(parts -> parts[0].trim(), parts -> parts[1].trim())); + .collect(Collectors.toMap( + parts -> parts[0].trim(), + parts -> parts[1].trim(), + (oldV, newV) -> newV // keep the latest + ));
312-340: Add null check for idfExportPath to prevent NPE.The
idfExportPath = envVarsFromActivationScriptMap.get(IDFEnvironmentVariables.PATH)can be null; subsequentreplace(...)calls will throw NPE.private void loadIdfPathWithSystemPath(Map<String, String> systemEnv) { String idfExportPath = envVarsFromActivationScriptMap.get(IDFEnvironmentVariables.PATH); + if (idfExportPath == null) + { + Logger.log(new Exception("PATH not found in activation script output")); //$NON-NLS-1$ + return; + } + String pathVar = "PATH"; // for Windows //$NON-NLS-1$ String pathEntry = systemEnv.get(pathVar); // $NON-NLS-1$ if (pathEntry == null) { pathVar = "Path"; //$NON-NLS-1$ pathEntry = systemEnv.get(pathVar); if (pathEntry == null) // no idea { Logger.log(new Exception("No PATH found in the system environment variables")); //$NON-NLS-1$ } } if (!StringUtil.isEmpty(pathEntry)) { idfExportPath = idfExportPath.replace("$PATH", pathEntry); // macOS //$NON-NLS-1$ idfExportPath = idfExportPath.replace("%PATH%", pathEntry); // Windows //$NON-NLS-1$ } systemEnv.put(pathVar, idfExportPath); for (Entry<String, String> entry : envVarsFromActivationScriptMap.entrySet()) { if (entry.getKey().equals(IDFEnvironmentVariables.PATH)) continue; systemEnv.put(entry.getKey(), entry.getValue()); } }
268-285: Increase timeout for process completion.The current timeout of 3 seconds (10 × 300ms) is too short and may kill legitimate processes. The
list-targetscommand often takes longer than 3 seconds on first run.Replace the manual timeout loop with a proper timeout:
- while (process.isAlive() && waitCount > 0) - { - try - { - Thread.sleep(300); - } - catch (InterruptedException e) - { - Logger.log(e); - } - waitCount--; - } - - if (waitCount == 0) - { - log("Process possibly stuck", IStatus.ERROR); //$NON-NLS-1$ - return Status.CANCEL_STATUS; - } + if (!process.waitFor(2, java.util.concurrent.TimeUnit.MINUTES)) + { + log("Process timed out after 2 minutes", IStatus.ERROR); //$NON-NLS-1$ + process.destroyForcibly(); + return Status.CANCEL_STATUS; + }
453-472: Add null-safe handling and use proper path separator.The
executablePathcan be null (field missing in JSON), and the hard-coded";"separator only works on Windows.private void addGitToEnvironment(Map<String, String> envMap, String executablePath) { + if (executablePath == null) + { + return; + } IPath gitPath = new Path(executablePath); if (gitPath.toFile().exists()) { String gitDir = gitPath.removeLastSegments(1).toOSString(); String path1 = envMap.get("PATH"); //$NON-NLS-1$ String path2 = envMap.get("Path"); //$NON-NLS-1$ + String sep = File.pathSeparator; if (!StringUtil.isEmpty(path1) && !path1.contains(gitDir)) // Git not found on the PATH environment { - path1 = gitDir.concat(";").concat(path1); //$NON-NLS-1$ + path1 = gitDir.concat(sep).concat(path1); envMap.put("PATH", path1); //$NON-NLS-1$ } else if (!StringUtil.isEmpty(path2) && !path2.contains(gitDir)) // Git not found on the Path environment { - path2 = gitDir.concat(";").concat(path2); //$NON-NLS-1$ + path2 = gitDir.concat(sep).concat(path2); envMap.put("Path", path2); //$NON-NLS-1$ } } }bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (6)
516-520: Prevent resource leak by reusing IDFConsole instance.A new
IDFConsoleis created each timegetConsoleStream()is called, which could lead to resource leaks if not properly managed.+private IDFConsole idfConsole; + private MessageConsoleStream getConsoleStream(boolean errorStream) { - IDFConsole idfConsole = new IDFConsole(); + if (idfConsole == null) { + idfConsole = new IDFConsole(); + } return idfConsole.getConsoleStream(Messages.IDFToolsHandler_ToolsManagerConsole, null, errorStream, true); }
90-99: Singleton with mutable global state creates risk of stale data and race conditions.The
eimJsonis held in a static field that is overwritten every timegetInstance()is called. Because the method is not synchronized, concurrent calls from UI thread/background jobs can race, and previously opened editors might suddenly see a different JSON instance than they were created with.Consider either:
- Removing the static field and passing the current
EimJsonthrough explicit method parameters, or- Synchronizing access and cloning the model to avoid unexpected mutation
103-103: Handle null EimJson gracefully to prevent NPE.When
eimJsonis null,idfInstalledListbecomes null, but the method continues execution which could lead to NPE in subsequent operations.- idfInstalledList = eimJson != null ? eimJson.getIdfInstalled() : null; + if (eimJson == null) + { + Logger.log("EimJson is null, cannot initialize IDF table"); + return container; + } + idfInstalledList = eimJson.getIdfInstalled();
145-150: Prevent concurrent job execution to avoid conflicts.Multiple
SetupToolsInIdejobs can be scheduled simultaneously without checking if previous jobs are still running, potentially causing conflicts.Consider adding a job state check or using a job family to prevent concurrent execution:
private static final Object SETUP_TOOLS_JOB_FAMILY = new Object(); // In job creation: setupToolsInIde.setJobFamily(SETUP_TOOLS_JOB_FAMILY); // Before scheduling: if (Job.getJobManager().find(SETUP_TOOLS_JOB_FAMILY).length == 0) { setupToolsInIde.schedule(); }Also applies to similar job scheduling patterns elsewhere in this class.
186-198: Improve error handling for JSON parsing.The catch block only logs the exception but continues execution, potentially leading to inconsistent state. Consider returning early or setting a flag to indicate the error state.
catch (IOException e) { Logger.log(e); + // Show error to user and return early + return; }
412-416: Move heavy process execution off UI thread to prevent freezing.The
getIdfVersion()method launches a shell, executes the activation script and waits for completion. Becauseupdate()runs in the SWT UI thread, the table freezes while every row (and every repaint) spawns a new process – catastrophic for responsiveness on large lists.Cache the version once per
IdfInstalled(e.g., in aMap<IdfInstalled,String>), and/or compute it in a backgroundJobthen update the viewer asynchronously.bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (1)
27-66: Add null-safety checks for method parameters.The
activationScriptandidfInstalledfields are assumed non-null. If the JSON is malformed,activationScriptcan benull, causing NPEs innew File(...)orProcessBuilder.Guard with:
public static String getIdfVersion(IdfInstalled idfInstalled, String gitPath) { + if (idfInstalled == null || idfInstalled.getActivationScript() == null) + { + return null; + } String activationScript = idfInstalled.getActivationScript(); String espIdfVersion = null;
🧹 Nitpick comments (1)
.github/workflows/ci.yml (1)
43-45: Remove trailing spaces to satisfy YAMLlint- distribution: 'temurin' - cache: 'maven' + distribution: 'temurin' + cache: 'maven'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (8)
bundles/com.espressif.idf.ui/icons/tools/delete.pngis excluded by!**/*.pngdocs_readme/images/ToolsManager/ESP-IDF_Manager_Conversion.pngis excluded by!**/*.pngdocs_readme/images/ToolsManager/ESP-IDF_Manager_Editor_Screen.pngis excluded by!**/*.pngmedia/ToolsManager/ESP-IDF_Configuration_Download_or_Use_ESP-IDF.pngis excluded by!**/*.pngmedia/ToolsManager/ESP-IDF_Manager_Changed_Installation_Message.pngis excluded by!**/*.pngmedia/ToolsManager/ESP-IDF_Manager_Conversion.pngis excluded by!**/*.pngmedia/ToolsManager/ESP-IDF_Manager_Editor_Screen.pngis excluded by!**/*.pngmedia/ToolsManager/ESP-IDF_Manager_Multiple_versions.pngis excluded by!**/*.png
📒 Files selected for processing (84)
.github/workflows/ci.yml(2 hunks).github/workflows/ci_windows.yml(1 hunks)bundles/com.espressif.idf.core/META-INF/MANIFEST.MF(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFCorePreferenceConstants.java(0 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java(2 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.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/logging/Logger.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java(2 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/DownloadListener.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/EimIdfConfiguratinParser.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimLoader.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/ToolInitializer.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/tools/watcher/EimJsonChangeListener.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java(1 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/EspToolCommands.java(3 hunks)bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java(4 hunks)bundles/com.espressif.idf.sdk.config.core/src/com/espressif/idf/sdk/config/core/server/JsonConfigServer.java(3 hunks)bundles/com.espressif.idf.serial.monitor/src/com/espressif/idf/serial/monitor/core/IDFMonitor.java(1 hunks)bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties(0 hunks)bundles/com.espressif.idf.ui/plugin.xml(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/EspressifGeneralStartup.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/GlobalModalLock.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java(0 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LaunchBarListener.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SbomCommandDialog.java(3 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/help/ProductInformationHandler.java(1 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/preferences/EspresssifPreferencesPage.java(0 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeAnalysisEditor.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeDataManager.java(2 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EimButtonLaunchListener.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java(1 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(2 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(11 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/tools/watcher/EimJsonUiChangeHandler.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tracing/AppLvlTracingDialog.java(1 hunks)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/AbstractToolsHandler.java(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)docs/_static/docs_version.js(1 hunks)docs/en/installation.rst(3 hunks)tests/com.espressif.idf.ui.test/configs/default-test-linux.properties(1 hunks)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectTest.java(0 hunks)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.java(2 hunks)tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/ProjectTestOperations.java(1 hunks)tests/pom.xml(1 hunks)
💤 Files with no reviewable changes (30)
- bundles/com.espressif.idf.ui/OSGI-INF/l10n/bundle.properties
- 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/IToolsJsonKeys.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages_zh.properties
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.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.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFCorePreferenceConstants.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.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/preferences/EspresssifPreferencesPage.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/GitRepositoryBuilder.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/UpdateEspIdfHandler.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsPlatformMapping.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/InitializeToolsStartup.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/messages.properties
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationJob.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolSetConfigurationManager.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/LogMessagesThread.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/install/IDFDownloadPage.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/ExportIDFTools.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/ToolsJob.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/InstallToolsHandler.java
- tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/executable/cases/project/NewEspressifIDFProjectTest.java
🚧 Files skipped from review as they are similar to previous changes (47)
- tests/pom.xml
- 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/size/IDFSizeDataManager.java
- tests/com.espressif.idf.ui.test/configs/default-test-linux.properties
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/SbomCommandDialog.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/help/ProductInformationHandler.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/update/AbstractToolsHandler.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/size/IDFSizeAnalysisEditor.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonChangeListener.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/handlers/NewProjectHandlerUtil.java
- bundles/com.espressif.idf.core/META-INF/MANIFEST.MF
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/LaunchBarListener.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tracing/AppLvlTracingDialog.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java
- docs/_static/docs_version.js
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java
- tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/ProjectTestOperations.java
- tests/com.espressif.idf.ui.test/src/com/espressif/idf/ui/test/operations/EnvSetupOperations.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/util/EspToolCommands.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/Messages.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/IDFEnvironmentVariables.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/messages.properties
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/DownloadListener.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageEspIdfVersionsHandler.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/IDFBuildConfiguration.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java
- bundles/com.espressif.idf.sdk.config.core/src/com/espressif/idf/sdk/config/core/server/JsonConfigServer.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonStateChecker.java
- docs/en/installation.rst
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/GlobalModalLock.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/EspressifGeneralStartup.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/EimConstants.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java
- bundles/com.espressif.idf.ui/plugin.xml
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/EimEditorInput.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EimButtonLaunchListener.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/watcher/EimJsonUiChangeHandler.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/watcher/EimJsonWatchService.java
- bundles/com.espressif.idf.core/src/com/espressif/idf/core/build/messages.properties
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java
- bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EspressifToolStartup.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/manager/pages/ESPIDFMainTablePage.java (9)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/logging/Logger.java (1)
Logger(21-141)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/EimIdfConfiguratinParser.java (1)
EimIdfConfiguratinParser(14-52)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/SetupToolsInIde.java (1)
SetupToolsInIde(53-474)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java (1)
ToolsUtility(25-101)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/EimJson.java (1)
EimJson(8-59)bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/IdfInstalled.java (1)
IdfInstalled(5-80)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/IDFConsole.java (1)
IDFConsole(27-100)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/EimButtonLaunchListener.java (1)
EimButtonLaunchListener(43-220)bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/SetupToolsJobListener.java (1)
SetupToolsJobListener(28-88)
🪛 actionlint (1.7.7)
.github/workflows/ci.yml
19-19: label "eclipse" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "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", "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)
19-19: label "BrnoUBU0004" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "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", "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)
25-25: 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.37.1)
.github/workflows/ci.yml
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
[warning] 22-22: wrong indentation: expected 6 but found 4
(indentation)
[error] 29-29: syntax error: found character '\t' that cannot start any token
(syntax)
[error] 43-43: trailing spaces
(trailing-spaces)
.github/workflows/ci_windows.yml
[warning] 9-9: wrong indentation: expected 6 but found 5
(indentation)
[warning] 13-13: wrong indentation: expected 6 but found 5
(indentation)
🔇 Additional comments (1)
.github/workflows/ci.yml (1)
19-19: Custom runner labels need explicit configuration
runs-on: [self-hosted, eclipse, BrnoUBU0004]will silently queue forever unless those extra labels are registered on the self-hosted runner and listed in anactionlint.yaml/organization settings. Double-check the spelling or drop the extra labels.
| - name: Install ESP-IDF via eim | ||
| uses: espressif/install-esp-idf-action@v1 | ||
| with: | ||
| version: 'v5.3' | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tab characters break YAML parsing
Line 29 contains two \t characters after the step name. YAML forbids tabs.
- - 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.
| - name: Install ESP-IDF via eim | |
| uses: espressif/install-esp-idf-action@v1 | |
| with: | |
| version: 'v5.3' | |
| - name: Install ESP-IDF via eim | |
| uses: espressif/install-esp-idf-action@v1 | |
| with: | |
| version: 'v5.3' |
🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 29-29: syntax error: found character '\t' that cannot start any token
(syntax)
🤖 Prompt for AI Agents
In .github/workflows/ci.yml at lines 29 to 33, replace the tab characters after
the step name "Install ESP-IDF via eim" with spaces, as YAML does not allow tab
characters for indentation. Ensure all indentation uses spaces consistently to
fix the YAML parsing error.
* ci: update the beta workflow and merge release&beta ci
There was a problem hiding this 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_release.yml (1)
55-59: Trailing whitespace sneaked in – fails YAML-lint
There are extra spaces on line 58 after thecodesign -v -vvv --deep …command.
YAML parsers ignore them, but the linter (and “git diff --check”) flags this. Please strip to keep the file clean.- /usr/bin/codesign -v -vvv --deep $PWD/releng/com.espressif.idf.product/target/products/com.espressif.idf.product/macosx/cocoa/x86_64/Espressif-IDE.app - + /usr/bin/codesign -v -vvv --deep $PWD/releng/com.espressif.idf.product/target/products/com.espressif.idf.product/macosx/cocoa/x86_64/Espressif-IDE.app
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
.github/workflows/ci_beta.yml(0 hunks).github/workflows/ci_release.yml(4 hunks)bundles/com.espressif.idf.branding/META-INF/MANIFEST.MF(1 hunks)features/com.espressif.idf.feature/feature.xml(1 hunks)releng/com.espressif.idf.configuration/pom.xml(1 hunks)releng/com.espressif.idf.product/idf.product(1 hunks)
💤 Files with no reviewable changes (1)
- .github/workflows/ci_beta.yml
✅ Files skipped from review due to trivial changes (4)
- releng/com.espressif.idf.configuration/pom.xml
- bundles/com.espressif.idf.branding/META-INF/MANIFEST.MF
- releng/com.espressif.idf.product/idf.product
- features/com.espressif.idf.feature/feature.xml
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/ci_release.yml
7-7: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
7-7: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
🪛 YAMLlint (1.37.1)
.github/workflows/ci_release.yml
[error] 58-58: trailing spaces
(trailing-spaces)
[error] 316-316: trailing spaces
(trailing-spaces)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_linux
🔇 Additional comments (1)
.github/workflows/ci_release.yml (1)
302-306: Potentially destructiveaws s3 rmwipes every build under beta/latestaws s3 rm ".../updates/$UPLOAD_PATH" --recursiveWith
UPLOAD_PATH=betathis deletes all beta update-sites, not just the one being replaced.
If multiple concurrent beta tags (e.g.-beta.1,-beta.2) should coexist, consider targeting only the version being published:-aws s3 rm "s3://${{ secrets.DL_BUCKET }}/dl/idf-eclipse-plugin/updates/$UPLOAD_PATH" --recursive +aws s3 rm "s3://${{ secrets.DL_BUCKET }}/dl/idf-eclipse-plugin/updates/$UPLOAD_PATH/v$VERSION" --recursiveOtherwise, please confirm that nuking the whole channel is intentional.
| tags: | ||
| - "v[0-9]+.[0-9]+.[0-9]+" | ||
| - "v[0-9]+\\.[0-9]+\\.[0-9]+-beta" | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tag filter patterns are illegal ‒ the workflow will never trigger on beta (or any) tags
GitHub Actions on.push.tags accepts glob syntax, not regex.
[], + and the escaped \. characters in
- "v[0-9]+.[0-9]+.[0-9]+"
- "v[0-9]+\\.[0-9]+\\.[0-9]+-beta"violate the ref-format rules (see action-lint error) and will be ignored at runtime, so the release pipeline will never start.
Diff suggestion (keep it simple, glob–style):
- - "v[0-9]+.[0-9]+.[0-9]+"
- - "v[0-9]+\\.[0-9]+\\.[0-9]+-beta"
+# stable tags, e.g. v4.0.0
+ - "v*.*.*"
+# beta tags, e.g. v4.0.0-beta or v4.0.0-beta.1
+ - "v*.*.*-beta*"🧰 Tools
🪛 actionlint (1.7.7)
7-7: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
7-7: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
🤖 Prompt for AI Agents
In .github/workflows/ci_release.yml lines 5 to 8, the tag filter patterns use
regex syntax which is invalid for GitHub Actions push tag filters that require
glob patterns. Replace the regex-style patterns with equivalent glob patterns by
removing brackets, plus signs, and backslashes, using wildcards like '*' and '?'
to match version numbers and the '-beta' suffix correctly so the workflow
triggers on the intended tags.
There was a problem hiding this 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 (1)
.github/workflows/ci_release.yml (1)
5-8: Release-tag trigger still uses regex syntax – workflow will not runThe patterns in lines 6-7 are still written as regular expressions.
on.push.tagsonly supports simple glob syntax; characters like[,+,\.and the optional-group(…)invalidate the filter and the workflow will never trigger.- - "v[0-9]+.[0-9]+.[0-9]+" - - "v[0-9]+\\.[0-9]+\\.[0-9]+-beta(\\.[0-9]+)?" +# stable tags, e.g. v4.0.0 + - "v*.*.*" +# beta tags, e.g. v4.0.0-beta or v4.0.0-beta.1 + - "v*.*.*-beta*"
🧹 Nitpick comments (3)
.github/workflows/ci_release.yml (3)
56-58: Trim trailing whitespaceLine 58 contains stray spaces that fail
yamllint(trailing-spaces).
They are harmless for execution but pollute the diff – please remove them.
260-270: Minor shell-safety & readability tweaks
- Quote the RHS of each
echoto keep$VALUEs containing*or spaces intact.FOLDERappears unused later; consider dropping it to avoid confusion.-echo "VERSION=$VERSION" >> $GITHUB_ENV +echo "VERSION=\"$VERSION\"" >> "$GITHUB_ENV" … -echo "FOLDER=v$VERSION" >> $GITHUB_ENV +# FOLDER currently unused – delete or wire it into later steps
271-277: Unused environment exports
TAGandFOLDERare exported but never referenced in later steps.
Remove them (or wire them in) to keep the environment clean and avoid future dead-code confusion.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/ci_release.yml(4 hunks)
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/ci_release.yml
7-7: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
7-7: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
7-7: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
🪛 YAMLlint (1.37.1)
.github/workflows/ci_release.yml
[error] 58-58: trailing spaces
(trailing-spaces)
[error] 316-316: trailing spaces
(trailing-spaces)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_macos
🔇 Additional comments (2)
.github/workflows/ci_release.yml (2)
309-316: Verify unzip target path before S3 copy
zip -r … artifacts/update/*stores files with theartifacts/update/…prefix, so the subsequent copy expects
$TMP_UPDATE_DIR/artifacts/update/.
If the directory structure ever changes, this will silently break the upload. Consider an explicit check:if [ ! -d "$TMP_UPDATE_DIR/artifacts/update" ]; then echo "❌ update site directory not found"; exit 1 fi
323-332: S3 website redirects – double-check object keysUsing
$REDIRECT_PATH(latestorbeta) as a filename means each redirect object is created inside the product-specific prefix, producing keys like
…/Espressif-IDE-win32.win32.x86_64/latest.Confirm that your download URLs are built accordingly (
…/…/latest) or adjust to place the redirect object at the parent folder root.No action required if this is intentional.
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java(4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_macos
🔇 Additional comments (2)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (2)
796-796: LGTM! Environment handling simplification is consistent with refactoring goals.The change from using a custom
getSystemEnv()method to directly usingSystem.getenv()aligns with the broader removal of preference-based tools path management described in the AI summary.
255-256: Missing call sites for getPythonExecutable – please verify external usageI didn’t find any references to IDFUtil.getPythonExecutable() in the Java codebase.
If this API is invoked by other modules or native integrations, ensure callers handle a null/empty return (or provide a sensible fallback) whenPYTHON_EXE_PATHisn’t set.No changes required here, but please confirm external consumers won’t break.
| 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); | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Eliminate code duplication by refactoring the existing method.
The new overloaded method duplicates most of the logic from the existing getIDFPythonEnvPath() method. This violates the DRY principle and creates maintenance issues.
Consider refactoring the existing method to use the new overloaded method:
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 getIDFPythonEnvPath(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.
| 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); | |
| } | |
| public static String getIDFPythonEnvPath() | |
| { | |
| String idfPyEnvPath = new IDFEnvironmentVariables() | |
| .getEnvValue(IDFEnvironmentVariables.IDF_PYTHON_ENV_PATH); | |
| return getIDFPythonEnvPath(idfPyEnvPath); | |
| } |
🤖 Prompt for AI Agents
In bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java
between lines 215 and 237, the getIDFPythonEnvPath method duplicates logic
present in the new overloaded version, violating the DRY principle. Refactor the
existing method to call the new overloaded method by passing the idfPyEnvPath
parameter, thereby centralizing the logic in one place and eliminating
duplication for easier maintenance.
There was a problem hiding this 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
🔭 Outside diff range comments (1)
.github/workflows/ci_release.yml (1)
37-41: Keystore path expansion is broken – secret never interpolatesInside a
run:block you cannot use{{secrets.X}}; the expression must be resolved by the workflow parser before the shell starts.- KEYSTORE_FILE="${PWD}/{{secrets.JARSIGNER_KEYSTORE}}" + KEYSTORE_FILE="${PWD}/${{ secrets.JARSIGNER_REL_KEYSTORE }}"Without this fix the subsequent
base64 -dfails because the output file path is literally{{secrets.JARSIGNER_KEYSTORE}}.
♻️ Duplicate comments (1)
.github/workflows/ci_release.yml (1)
6-7: Tag filters still use regex, so the workflow will never trigger
on.push.tagsexpects simple glob patterns, not full regex syntax. The back-slashes and+quantifiers you re-introduced violate ref-format;actionlintis again reporting the same error.- - "v[0-9]+\\.[0-9]+\\.[0-9]+" - - "v[0-9]+\\.[0-9]+\\.[0-9]+-beta(\\.[0-9]+)?" +# stable tags, e.g. v4.0.0 + - "v*.*.*" +# beta tags, e.g. v4.0.0-beta or v4.0.0-beta.1 + - "v*.*.*-beta*"
🧹 Nitpick comments (2)
.github/workflows/ci_release.yml (2)
58-58: Trailing whitespaceLine contains only spaces → YAML-lint error. Please trim.
315-316: Trailing whitespace sneaked in
aws s3 cp … index.html …ends with an extra space, flagged by YAML-lint. Harmless but worth cleaning.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/ci_release.yml(4 hunks)
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/ci_release.yml
6-6: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
6-6: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
7-7: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
7-7: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
7-7: character '' is invalid for branch and tag names. only special characters [, ?, +, *, , ! can be escaped with . see man git-check-ref-format for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
(glob)
🪛 YAMLlint (1.37.1)
.github/workflows/ci_release.yml
[error] 58-58: trailing spaces
(trailing-spaces)
[error] 316-316: trailing spaces
(trailing-spaces)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_macos
There was a problem hiding this 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 (1)
.github/workflows/ci_release.yml (1)
5-7: Release workflow still uses regex patterns – tags will never triggerThe filter values under
on.push.tagsmust be glob patterns, not regex. The[],+, and escaped dots are illegal and will be ignored, so neither stable nor beta tags will start the workflow.
Re-use the simple glob suggested in the prior review.- - "v[0-9]+.[0-9]+.[0-9]+" - - "v[0-9]+.[0-9]+.[0-9]+-beta.*" +# stable tags, e.g. v4.0.0 + - "v*.*.*" +# beta tags, e.g. v4.0.0-beta or v4.0.0-beta.1 + - "v*.*.*-beta*"
🧹 Nitpick comments (1)
.github/workflows/ci_release.yml (1)
58-58: Clean up trailing whitespace flagged by YAML-lintTwo lines contain only spaces, tripping the linter. Remove the superfluous spaces to keep the workflow YAML-clean.
- +(and the same one-liner at ~316)
Also applies to: 316-316
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/ci_release.yml(4 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/ci_release.yml
[error] 58-58: trailing spaces
(trailing-spaces)
[error] 316-316: trailing spaces
(trailing-spaces)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: macos-build
Summary by CodeRabbit
New Features
Improvements
Removals
Bug Fixes
Chores