Skip to content

#1754: Add support for VS Code plugin versions#1832

Open
areinicke wants to merge 9 commits intodevonfw:mainfrom
areinicke:feature/1754-Add-support-for-vscode-plugin-versions
Open

#1754: Add support for VS Code plugin versions#1832
areinicke wants to merge 9 commits intodevonfw:mainfrom
areinicke:feature/1754-Add-support-for-vscode-plugin-versions

Conversation

@areinicke
Copy link
Copy Markdown
Contributor

@areinicke areinicke commented Apr 17, 2026

This PR fixes #1754

Implemented changes:

  • VS Code extensions can now be specified with a plugin version in the extension .properties file (found under $IDE_HOME/settings/vscode/plugins/)
  • Example usage:
plugin_id=esbenp.prettier-vscode
plugin_active=true
tags=formatter
version=12.1.0

If the specified version is unavailable, the plugin installation will fail.

  • Plugins can be freely upgraded or downgraded by changing the specified version in the .properties file
  • Added several test cases that test the intended behavior

Checklist for this PR

Make sure everything is checked before merging this PR. For further info please also see
our DoD.

  • When running mvn clean test locally all tests pass and build is successful
  • PR title is of the form #«issue-id»: «brief summary» (e.g. #921: fixed setup.bat). If no issue ID exists, title only.
  • PR top-level comment summarizes what has been done and contains link to addressed issue(s)
  • PR and issue(s) have suitable labels
  • Issue is set to In Progress and assigned to you or there is no issue (might happen for very small PRs)
  • You followed all coding conventions
  • You have added the issue implemented by your PR in CHANGELOG.adoc unless issue is labeled
    with internal

@github-project-automation github-project-automation Bot moved this to 🆕 New in IDEasy board Apr 17, 2026
@areinicke areinicke self-assigned this Apr 17, 2026
@areinicke areinicke moved this from 🆕 New to 🏗 In progress in IDEasy board Apr 17, 2026
@areinicke areinicke added enhancement New feature or request vscode Microsoft visual studio code plugins related to plugins (for Eclipse, Intellij, VSCode, etc.) labels Apr 17, 2026
@coveralls
Copy link
Copy Markdown
Collaborator

coveralls commented Apr 17, 2026

Coverage Report for CI Build 25362807967

Coverage increased (+0.06%) to 70.716%

Details

  • Coverage increased (+0.06%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 20 coverage regressions across 5 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

20 previously-covered lines in 5 files lost coverage.

File Lines Losing Coverage Coverage
com/devonfw/tools/ide/tool/plugin/PluginBasedCommandlet.java 9 86.29%
com/devonfw/tools/ide/tool/vscode/Vscode.java 5 80.36%
com/devonfw/tools/ide/tool/plugin/ToolPluginDescriptor.java 4 84.44%
com/devonfw/tools/ide/tool/ide/IdeToolCommandlet.java 1 78.33%
com/devonfw/tools/ide/version/VersionSegment.java 1 90.55%

Coverage Stats

Coverage Status
Relevant Lines: 15388
Covered Lines: 11337
Line Coverage: 73.67%
Relevant Branches: 6890
Covered Branches: 4417
Branch Coverage: 64.11%
Branches in Coverage %: Yes
Coverage Strength: 3.12 hits per line

💛 - Coveralls

@areinicke areinicke marked this pull request as ready for review April 17, 2026 10:47
@areinicke areinicke moved this from 🏗 In progress to Team Review in IDEasy board Apr 17, 2026
@ducminh02 ducminh02 self-requested a review April 17, 2026 10:59
@ducminh02 ducminh02 self-assigned this Apr 17, 2026

String markerFilePrefix = "plugin" + "." + getName() + "." + getInstalledEdition() + "." + plugin.name();
List<Path> markerFiles = fileAccess.listChildren(currentMarkerFilePath.getParent(),
p -> Files.isRegularFile(p) && p.getFileName().toString().startsWith(markerFilePrefix));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great addition! However, there is a subtle edge case here with how .startsWith() matches the prefix.

If a user has two plugins installed where one plugin's name is a prefix of another (for example, java and java-extension-pack), installing or updating the shorter one (java) will accidentally delete the marker file for the longer one (java-extension-pack). This happens because "plugin.vscode.null.java-extension-pack" starts with "plugin.vscode.null.java".

To fix this and ensure we don't accidentally delete other plugins' marker files, we should check that the file name either matches the unversioned prefix exactly, or is followed specifically by the .version- delimiter.

Suggested change
p -> Files.isRegularFile(p) && p.getFileName().toString().startsWith(markerFilePrefix));
p -> {
String fileName = p.getFileName().toString();
return Files.isRegularFile(p) && (fileName.equals(markerFilePrefix)
|| fileName.startsWith(markerFilePrefix + ".version-"));
});

Properties properties = context.getFileAccess().readProperties(propertiesFile);
String id = getString(properties, "id", "plugin_id");
String url = getString(properties, "url", "plugin_url");
String version = getString(properties, "version", "plugin_version");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Users sometimes accidentally leave trailing spaces in .properties files (version=1.44.2 ), which would end up in the CLI command and the marker file.

Suggested change
String version = getString(properties, "version", "plugin_version");
String version = getString(properties, "version", "plugin_version");
if (version != null) {
version = version.trim();
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ok, I see the issue. But this issue also affects the other fields (e.g., "id"). It would be odd to implement special handling just for this field. We could instead just trim all fields automatically in the getString() method, no? What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

okay I get what you mean, it is actually better that way to be honest, with that implementation we can keep the error away from all of the fields and not only the version field

extensionsCommands.add(plugin.id());
String extensionInstallTarget = plugin.id();
// If a version number was specified, add it to the extension identifier with the format "extensionId@version"
Boolean versionSpecified = (plugin.version() != null) && !plugin.version().isBlank();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It is better to use the primitive boolean here instead of the boxed Boolean object. This avoids unnecessary object overhead and eliminates the risk of a NullPointerException during unboxing, as this flag will never need to be null.

Suggested change
Boolean versionSpecified = (plugin.version() != null) && !plugin.version().isBlank();
boolean versionSpecified = (plugin.version() != null) && !plugin.version().isBlank();

Copy link
Copy Markdown
Contributor

@ducminh02 ducminh02 left a comment

Choose a reason for hiding this comment

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

Amazing job on this PR Alex! 🚀

The implementation is very clean and It handles the versioned plugin requirement perfectly!

I've left a few comments on some very minor adjustments and one subtle edge case regarding the marker file cleanup logic that we should address to ensure different plugins with similar names don't conflict.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request plugins related to plugins (for Eclipse, Intellij, VSCode, etc.) vscode Microsoft visual studio code

Projects

Status: Team Review

Development

Successfully merging this pull request may close these issues.

Add version support to vscode settings .plugin files

3 participants