Skip to content

IntelliJ 2026.2 compatibility#952

Open
dividedmind wants to merge 8 commits into
mainfrom
chore/262-compat
Open

IntelliJ 2026.2 compatibility#952
dividedmind wants to merge 8 commits into
mainfrom
chore/262-compat

Conversation

@dividedmind

@dividedmind dividedmind commented Jul 2, 2026

Copy link
Copy Markdown
Contributor
  • Add compatibility for the upcoming 2026.2 IntelliJ release.
  • Add relevant run and compilation targets.
  • Run tests against 2026.2 in CI.
  • Update gradle plugin version.
  • Conditionally select JVM 25 when running with 262 platform.
  • Add optional dependency on JCEF which is no longer implicitly loaded in 262.
  • Remove deprecated workarounds and usage of APIs now marked as internal.
  • Remove legacy env providers.

Note: because of JetBrains/intellij-platform-gradle-plugin#1930 I had to add explicit transitive dependency list to get the java plugin to load in tests correctly.

Use CommonBundle.message("button.overwrite") instead of
IdeBundle.message("action.overwrite"). The latter is now marked as
internal API.
Upgrades intellij-platform-gradle-plugin to 2.17.0 and aligns the JVM
target dynamically between Kotlin and Java compilers based on the target
IntelliJ platform version (JVM 25 for platform 262, JVM 21 for platform
251).

Declares JCEF and VCS DVCS bundled module dependencies conditionally for
platform 253+ to resolve class resolution errors on newer SDK releases
without breaking backward compatibility on 251. Upgrades Lombok to
1.18.46 for JDK 25 compiler compatibility.

Removes stale run configurations and workaround for bugs that have since
been fixed. Adds testing for 262 platform version in CI. 261 has been
kept to ensure compatibility with the latest released version.
Declares the 'com.intellij.modules.jcef' optional dependency in
appmap-core.xml, pointing to a new placeholder appmap-jcef.xml descriptor file.
Includes comprehensive inline comments explaining this setup: JCEF is implicitly
loaded in Platform 251's core classloader but requires explicit opt-in under
Platform 262's isolated modular classloader.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the AppMap IntelliJ plugin to support IntelliJ Platform 262 (2026.2 EAP), including build/CI target updates, optional JCEF module wiring, and removal of legacy CLI env providers.

Changes:

  • Added IntelliJ Platform 262 (2026.2) build targets and CI coverage, and updated the IntelliJ Platform Gradle plugin.
  • Introduced optional com.intellij.modules.jcef dependency wiring for Platform 262 while retaining compatibility with Platform 251.
  • Refactored plugin descriptor resolution to avoid static internal API references in production code paths and removed legacy env-provider implementations.

Reviewed changes

Copilot reviewed 16 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
plugin-core/src/main/resources/META-INF/appmap-jcef.xml Adds placeholder config needed for optional JCEF dependency declarations.
plugin-core/src/main/resources/META-INF/appmap-core.xml Declares optional com.intellij.modules.jcef dependency; removes legacy env provider registration.
plugin-core/src/main/java/appland/webviews/appMap/ExportSvgUtil.java Replaces overwrite button label lookup with a non-IdeBundle message key.
plugin-core/src/main/java/appland/AppMapPlugin.java Avoids static internal API usage by using PluginAwareClassLoader and reflective lookup in test/dev paths.
plugin-copilot/src/main/java/appland/copilotChat/CopilotStartupNotificationActivity.java Switches Copilot availability check to CopilotModelInfoProvider.
plugin-copilot/src/main/java/appland/copilotChat/CopilotModelInfoProvider.java Updates Copilot plugin availability check implementation.
gradle.properties Updates Lombok version.
gradle-262.properties Adds 262 IDE version pin for builds/tests.
gradle-261.properties Normalizes file formatting.
gradle-253.properties Removes legacy platform target.
gradle-252.properties Removes legacy platform target.
build.gradle.kts Updates Gradle IntelliJ Platform plugin, targets, bundled modules/plugins, JVM selection logic, and composed module setup.
.run/runIDE 2026.2.run.xml Adds/updates run configuration for 2026.2 runIde.
.run/runIDE 2026.1.run.xml Updates run configuration parameters/name for 2026.1.
.github/workflows/build.yml Extends CI matrix to run tests on 262 (EAP) on Ubuntu.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugin-core/src/main/java/appland/AppMapPlugin.java
Remove legacy env provider that supplied openai key for the copilot proxy
using OPENAI_API_KEY environment variable.
The key is now supplied via RPC.
PluginManagerCore.getPlugin(PluginId) is marked @ApiStatus.Internal in
262, so AppMapPlugin.getDescriptor() tripped verifyPlugin's
INTERNAL_API_USAGES check. There is no public by-id descriptor lookup on
the 251 base target: the whole PluginManager/PluginManagerCore lookup
surface (getPlugin, findEnabledPlugin, getPluginByClass) is internal, and
PluginDetailsService — the public replacement — is 262-only and
@ApiStatus.Experimental, so it is unusable while we still target 251.

Since we only ever need our *own* descriptor (for the plugin path,
version and id), read it off the plugin's classloader instead:
PluginAwareClassLoader#getPluginDescriptor() is public API. In a deployed
plugin our classes are loaded by a PluginClassLoader, so this is the path
the shipped artifact takes and it contains no internal-API reference.

The test/dev runtime loads our classes from a flat classpath rather than a
PluginClassLoader, so getPluginDescriptor() is unavailable there and the
descriptor must be looked up in the registry by id. PathManager /
PluginPathManager do not help: getPluginDistDirByClass returns null for a
class loaded from a directory (the test case), so it has the same gap.
The registry lookup is the internal PluginManagerCore.getPlugin, so we
reach it reflectively — this keeps the shipped plugin free of any static
internal-API reference (verifyPlugin only inspects bytecode references),
and the branch never runs in a real IDE. If the internal signature ever
changes it fails loudly in CI, never in production.

Assisted-by: Claude:claude-opus-4-8
PluginManager.getLoadedPlugins() is @ApiStatus.Internal and tripped
verifyPlugin's INTERNAL_API_USAGES check in 262. It was only used to test
whether the GitHub Copilot plugin is present and active.

Replace it with the public PluginManagerCore.isPluginInstalled(PluginId)
and isDisabled(PluginId) (both @JvmStatic, non-internal, available on the
251 base target). The new expression matches the method's documented
contract directly: unavailable when the plugin is not installed or is
disabled. Behaviour is equivalent — not-installed and disabled both map
to "unavailable", installed-and-enabled maps to "available".

Assisted-by: Claude:claude-opus-4-8
On build 262 the AppMap indexes returned nothing, so metadata/name/classMap
lookups (and AppMap discovery) came up empty. Root cause: both the index
input filters and the appMapsWithExcluded search scope gated on
JsonFileType.INSTANCE, but JSON language support is provided by a separate
platform module whose file-type registration is not active in every runtime
(notably the 262 test sandbox). Files such as metadata.json were therefore
not classified as JSON, so a FileTypeSpecificInputFilter never offered them
to the indexer and getScopeRestrictedByFileTypes(..., JsonFileType) excluded
them from the query scope.

The files we index have specific, known names, so the JSON file type gate was
only ever an optimisation on top of an exact-name match. Replace the
FileTypeSpecificInputFilter with a plain FileBasedIndex.InputFilter that matches
by file name alone, and drop the JsonFileType restriction from
appMapsWithExcluded. The scope is only used to query our own name-matched
indexes and to locate *.appmap.json files by extension via the platform's
FilenameIndex, neither of which needs a file-type restriction.

Bump the shared index version (66 -> 67) to rebuild indexes once on upgrade.

Verified: the index tests and OpenRecentAppMapActionTest pass on both 251 and
262 (they failed on 262 before this change).

Assisted-by: Claude:claude-opus-4-8
On 262 the plugin-java tests failed with the Java plugin's services
missing: JavaDirectoryService.getInstance() returned null,
ProjectJdkTable could not be cast to JavaAwareProjectJdkTableImpl, and
JarApplicationConfigurationType was not a registered run-config type.

Root cause: the whole 'Java' plugin was excluded from the test sandbox
because several bundled plugins it depends on (structure view, bookmarks,
test runner, todo, structural search, misc libraries, copyright, terminal,
XPath) were not present, and the Gradle plugin no longer resolves the
transitive bundled-plugin dependencies of a bundledPlugin() automatically
since 2.4.0 (JetBrains/intellij-platform-gradle-plugin#1930). Once a
required content module cannot resolve, the entire Java plugin — including
its impl/execution/backend modules that register those services — is
dropped.

There is no catch-all or "full IDE" test mode, so declare the companion
plugins explicitly. Kept as a single documented list (javaTestCompanionPlugins)
and guarded to platformVersion >= 262 so 251 is untouched.

Verified: full :plugin-java:test passes on both 251 and 262.

Assisted-by: Claude:claude-opus-4-8

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 22 changed files in this pull request and generated no new comments.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants