# Summer 2026 IntelliJ Platform Changes for Plugin Developers

**URL:** <https://platform.jetbrains.com/t/summer-2026-intellij-platform-changes-for-plugin-developers/5041>\
**Category:** Announcements\
**Created:** [September 11, 2026, 3:24am UTC](https://platform.jetbrains.com/t/summer-2026-intellij-platform-changes-for-plugin-developers/5041 "2026-09-11T03:24:31Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![patrick.scheibe](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/patrick.scheibe/32/2594_2.png) [@patrick.scheibe](https://platform.jetbrains.com/u/patrick.scheibe)\
**Post date:** [September 11, 2026, 3:24am UTC](https://platform.jetbrains.com/t/summer-2026-intellij-platform-changes-for-plugin-developers/5041/1 "2026-09-11T03:24:31Z")

</div>

Summer is over, and the IntelliJ Platform kept moving. The short video gives you the quickest possible version of ten changes that stood out for plugin authors. This post is the slower companion and explains why you should care about each change, when to act, and  
where to start if it touches your plugin.

[![](https://us1.discourse-cdn.com/flex001/uploads/jetbrains_platform/original/2X/7/72e6ada657fffed9026e67bf74edc50685be4396.jpeg "IntelliJ Platform Summer Update 2026") ](https://www.youtube.com/watch?v=5mQixmpezuI)

## 1. Native plugin variants in the Gradle plugin

This topic is for you if your plugin ships native binaries such as launchers, helper tools, native libraries, or anything else that varies by operating system or CPU architecture. Previously, many plugins either bundled all native artifacts into a single ZIP or maintained custom packaging logic. Native plugin variants make that a first-class Gradle Plugin workflow.

The important question is whether your users need different native files on Linux, macOS, or Windows, and whether you are ready to target the 2026.1 platform baseline or newer. If the answer is yes, you can use `intellijPlatform.nativeVariants` to describe the native files for each target, then build variant ZIPs instead of one universal package. The generated descriptors are patched with OS and architecture dependencies, and publishing can upload the generated ZIPs together.

If your plugin is pure JVM code, you probably do not need to do anything. If you currently ship one large archive because native packaging was awkward, you can use this in your next 2026.1+ release. Platform-specific packages are already visible on the Marketplace: the [Android plugin](https://plugins.jetbrains.com/plugin/22989-android) publishes OS/architecture-specific packages, and [GitHub Copilot](https://plugins.jetbrains.com/plugin/17718-github-copilot--your-ai-pair-programmer) also publishes platform-specific packages for 2026.1+ IDEs. These are examples of real plugins that need to ship different native payloads without making every user download every platform’s binaries.

Start with the official Gradle Plugin documentation for [  
 `intellijPlatform.nativeVariants`](https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-extension.html#intellijPlatform-nativeVariants), because it shows the DSL and the platform-baseline requirement. The [Gradle task documentation for `buildPluginVariants`](https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-tasks.html#buildPluginVariants) explains the generated build tasks and classifiers. If you need to understand exactly how descriptors are patched and validated, the implementation is in [  
 `PreparePluginVariantTask.kt`](https://github.com/JetBrains/intellij-platform-gradle-plugin/blob/main/src/main/kotlin/org/jetbrains/intellij/platform/gradle/tasks/PreparePluginVariantTask.kt).

## 2. Integration testing with Starter, Driver, and `testIdeUi`

Plugin integration tests have always been something you don’t talk about at parties. To be fair, AI wanted me to tell you that integration tests were the part where many projects quietly accumulate custom scripts, but who are we kidding, right? However, now the updated SDK guidance gives plugin authors a documented route for starting an IDE, installing the plugin, opening a project, collecting logs, and driving UI or API checks from tests.

It is something for you if your plugin behavior depends on a real IDE instance. That includes tool windows, actions, project indexing behavior, UI flows, settings pages, and workflows where unit tests just don’t cut it. _Starter_ handles IDE preparation and launch. _Driver_ talks to the running IDE, including UI interactions and API calls. On the Gradle side, `intellijPlatformTesting.testIdeUi` gives you a task model instead of a hand-rolled launcher.

The caveat is that both Driver and UI APIs are still experimental. For plugin projects that already have fragile UI tests, this may still be an improvement, but do not treat the API surface as frozen. For new integration tests, though, this is the path I would start from rather than inventing another local test harness.

The best entry point is the SDK page on [integration tests](https://plugins.jetbrains.com/docs/intellij/integration-tests-intro.html), which explains the  
Starter and Driver split and the Gradle setup. The [UI testing page](https://plugins.jetbrains.com/docs/intellij/integration-tests-ui.html) is where to look once you need component lookup and interaction examples. The Gradle side is documented under [  
 `testIdeUi`](https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-tasks.html#testIdeUi), including its incubating status.

## 3. LSP OpenAPI moved from server names to client names

If you use IntelliJ Platform LSP support, check your imports and extension registration. The IDE-side API is moving away from names like `LspServerSupportProvider` and toward names that match the LSP model more accurately. Now, the IDE is the “LSP client”, and it talks to a “language server”.

New code should use the client-named APIs, including `LspIntegrationProvider`, `LspClientDescriptor`, `ProjectWideLspClientDescriptor`, and `LspClientManager`. The extension point to use is `com.intellij.platform.lsp.integrationProvider`. The older server-named APIs and extension point remain as deprecated for a while, in case you still support older IDE builds, but they should not be the default for new 2026.x work.

The migration is straightforward if your usage is close to the documented API. It becomes more interesting if you have abstractions around service lookup, extension registration, or compatibility layers across multiple platform versions. In that case, make the naming change deliberately and test against the oldest IDE you still support.

The SDK has a direct [LSP API refactoring section](https://plugins.jetbrains.com/docs/intellij/language-server-protocol.html#lsp-api-refactoring) with the rename table. For source-level confirmation, [`LspIntegrationProvider.kt`](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/platform/lsp/src/api/LspIntegrationProvider.kt) shows the current provider API, while the LSP implementation XML shows both the current and deprecated [extension point declarations](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/platform/lsp-impl/resources/intellij.platform.lsp.impl.xml#L162-L166).

## 4. Stricter plugin descriptor reachability and dynamic plugin checks

This is mostly a correctness change, but it can feel like a build or IDE inspection suddenly became stricter. You will see it most often in multi-module plugins, plugins with optional descriptors, plugins split into content modules, and plugins that reference classes or extension points from another bundled or external plugin.

Practically, it just means if your `plugin.xml` references a class, action, group, resource bundle, or extension point, that thing must be reachable through the plugin’s declared dependency graph. A Gradle dependency alone may not be enough, because runtime plugin loading follows descriptor dependencies. When DevKit reports an unreachable reference, fix both sides: the build-system dependency and the corresponding `plugin.xml` dependency structure.

Also, be careful if your plugin supports dynamic unload and reload. Dynamic plugin checks are stricter about descriptor shape and runtime behavior. For example, dynamic extension points need to be declared correctly, action groups need IDs, and some plugin structures still require a restart.

The public SDK page on [dynamic plugins](https://plugins.jetbrains.com/docs/intellij/dynamic-plugins.html) is the best starting point for understanding what can and cannot reload dynamically. The page on [dynamic extension points](https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html#dynamic-extension-points) explains what is required when declaring EPs that support dynamic behavior. The newer descriptor reachability inspection is mainly source-backed; [`PluginXmlReferencesModuleReachabilityInspection.kt`](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/plugins/devkit/devkit-core/src/inspections/PluginXmlReferencesModuleReachabilityInspection.kt) is the place to look if you need to understand exactly what DevKit is checking.

## 5. Search Everywhere contributor API deprecation

Plugins that add results to _Search Everywhere_ should look at this one. You don’t need to rush into a procrastinatory refactoring session, but take a look. The older `SearchEverywhereContributor` and `SearchEverywhereContributorFactory` APIs are deprecated. The replacement direction is `SeItemsProvider` and `SeItemsProviderFactory`, registered through `com.intellij.searchEverywhere.itemsProviderFactory`.

You should know about the deprecation because _Search Everywhere_ integrations are often central to productivity plugins, and deprecated APIs can become annoying if ignored for too long. You shouldn’t rush into it, because the new provider API is still experimental, and parts of the source surface are not as stable as a normal OpenAPI migration target.

For now, I would avoid writing new code against the old contributor model. For existing plugins, start by identifying your current `SearchEverywhereContributor` implementations and watching the newer provider model. If you need to migrate soon, isolate the integration behind your own small adapter so you have less code to revisit if the experimental API changes.

The official [extension point list](https://plugins.jetbrains.com/docs/intellij/intellij-platform-extension-point-list.html) is useful here because it shows `com.intellij.searchEverywhere.itemsProviderFactory` and its experimental status. The  
replacement source is [`SeItemsProvider.kt`](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/platform/searchEverywhere/shared/src/SeItemsProvider.kt). The old API deprecation is visible in [`SearchEverywhereContributor.java`](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/platform/lang-api/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereContributor.java), which is helpful when you need to confirm what exactly is being phased out.

## 6. Plugin error reporting and automatic observability

Error reporting now has a clearer split in the SDK docs. `ErrorReportSubmitter` is still the path for user-submitted reports from the Fatal Errors UI. The newer `ErrorReportSink` extension point is for automatic plugin-attributed exception and freeze reports.

You should definitely take a look if you maintain a plugin with enough users that production diagnostics are worth the effort, especially if you currently rely only on users manually reporting errors. Automatic reporting can include unhandled exceptions and freeze reports. Freeze reports can carry duration, attachments, and thread dumps, which is exactly the sort of information that is hard to reconstruct after the fact.

There are several caveats. `ErrorReportSink` is experimental. Delivery is best effort, not a guarantee. There are limits, and the platform does not solve your deduplication, debouncing, rate limiting, or privacy policy for you. In other words, this is a useful observability hook, not a complete reporting product.

Start with the SDK page on [error reporting](https://plugins.jetbrains.com/docs/intellij/error-reporting.html), because I updated it recently and tried my best to explain everything in detail. If you want to use JetBrains infrastructure for user-submitted reports, the Marketplace documentation for the [Exception Analyzer](https://plugins.jetbrains.com/docs/marketplace/exception-analyzer.html) explains that path. For exact report types, limits, and extension point details, read [`ErrorReportSink.kt`](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/platform/platform-api/src/com/intellij/openapi/diagnostic/ErrorReportSink.kt).

## 7. Kotlin UI DSL 1.0 removal

This is the most direct migration warning in the list. Kotlin UI DSL 1.0, the old `com.intellij.ui.layout` API, is gone. If your plugin still imports that package, expect compilation failures or runtime problems when targeting newer builds.

If you use settings pages, configurables, inspection option panels, dialogs, or custom forms written with the old Kotlin UI DSL, the compiler will come for you.  
The replacement is Kotlin UI DSL v2, now the current Kotlin UI DSL, under `com.intellij.ui.dsl.builder`. In day-to-day code this usually means replacing old layout imports and updating panel, row, cell, and binding calls to the v2 shape.

This is easy to triage. Search your plugin for `com.intellij.ui.layout`. If it appears, schedule the migration before you move your target platform forward. Also check module dependencies if you were depending on implementation modules just to access UI DSL APIs.

The official [2026 API changes list](https://plugins.jetbrains.com/docs/intellij/api-changes-list-2026.html) calls out the removal. The older UI DSL page has the useful [migration to version 2](https://plugins.jetbrains.com/docs/intellij/kotlin-ui-dsl.html#migration-to-version-2) table. For current code, use the [Kotlin UI DSL v2 documentation](https://plugins.jetbrains.com/docs/intellij/kotlin-ui-dsl-version-2.html), which covers the `com.intellij.ui.dsl.builder` API.

## 8. PolySymbols PSI-linked APIs and own references

This is narrower than some of the other changes, but it is aimed at language, framework, and web ecosystem plugins that use PolySymbols. The old PSI-sourced terminology has been renamed to PSI-linked terminology. In practice, `PsiSourcedPolySymbol` becomes `PsiLinkedPolySymbol`, and `source` becomes `linkedElement`.

The rename describes the model more clearly: a PolySymbol can be linked one-to-one to a real PSI element, and platform features such as navigation, rename, usages, and equivalence can route through that linked element. If your plugin exposes framework-specific symbols backed by PSI, this is the area to review.

There is also a new own references mechanism: `PolySymbolOwnReferenceHost` and `polySymbolOwnReferences(...)`. Use it when the reference belongs intrinsically to the PSI element itself. One detail to watch: own references take priority over external `polySymbols.psiReferenceProvider` references, so do not accidentally model the same thing twice.

The [PolySymbols section in the 2026 API changes list](https://plugins.jetbrains.com/docs/intellij/api-changes-list-2026.html#polysymbols-20262) is the best starting point for the rename. The source for [`PsiLinkedPolySymbol`](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/platform/polySymbols/src/com/intellij/polySymbols/search/PsiLinkedPolySymbol.kt) shows the linked-element model. The own references behavior is documented in code in [`PolySymbolOwnReferences.kt`](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/platform/polySymbols/backend/src/com/intellij/polySymbols/references/PolySymbolOwnReferences.kt).

## 9. Coroutine `edtWriteAction`

Coroutine-based plugin code now has a clearer API when you need to perform write work, and that write work must run on the Event Dispatch Thread. The API is `suspend fun <T> edtWriteAction(action: () -> T): T` in `com.intellij.openapi.application`.

Use it for the actual mutation step when PSI, VFS, or project model changes require a write lock and must happen on the UI thread (EDT, yep, same thing). Do not use it as a way to move a large operation onto the UI thread. Prepare data in the background, then keep the write block small. If the operation should participate in undo/redo, use a write command instead.

This is most relevant if your plugin already uses Kotlin coroutines and you have code that manually combines EDT dispatching with write actions. For general coroutine write work, also look at the broader suspending write-action APIs and threading guidance, because `edtWriteAction` is not a replacement for understanding where write actions belong.

The exact API is in [`coroutines.kt`](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/platform/core-api/src/com/intellij/openapi/application/coroutines.kt#L258-L268). The SDK [threading model](https://plugins.jetbrains.com/docs/intellij/threading-model.html#write-actions-api) explains write actions and when to use command-aware alternatives. The [coroutine dispatchers](https://plugins.jetbrains.com/docs/intellij/coroutine-dispatchers.html) page is useful background for EDT dispatching and modality in coroutine code.

## 10. Background-capable bulk VFS listeners

If your plugin listens to VFS changes and does real work in those callbacks, this one is worth checking. `BulkFileListenerBackgroundable` is now stable OpenAPI for listeners that need synchronous bulk VFS event delivery but can safely run on a background thread. The related topic is `VirtualFileManager.VFS_CHANGES_BG`.

This is not a recommendation to move every VFS listener. Prefer `AsyncFileListener` when it is enough, because it is designed for asynchronous preparation around VFS events. Use the background bulk listener path when you truly need synchronous delivery, and your listener is thread-safe, project-aware, and has no UI dependency.

Pay attention to the threading detail. The callbacks still run under a write action, but on a background thread, and `before` and `after` callbacks are not guaranteed to use the same thread. VFS events are also project-agnostic, so plugins still need to filter by project content themselves.

The SDK [notable API changes page](https://plugins.jetbrains.com/docs/intellij/api-notable-list-2026.html) has the public entry for background-capable VFS listeners. The source contract for the listener is in [`BulkFileListenerBackgroundable.kt`](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/platform/core-api/src/com/intellij/openapi/vfs/newvfs/BulkFileListenerBackgroundable.kt). [  
 `VirtualFileManager.java`](https://github.com/JetBrains/intellij-community/blob/idea/262.8665.337/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileManager.java#L32-L40) shows the `VFS_CHANGES_BG` topic.

## What to check in your plugin

If you only have time for a quick pass, search your codebase for the obvious migration markers: `com.intellij.ui.layout`, `SearchEverywhereContributor`, `LspServer`, `LspServerSupportProvider`, `PsiSourcedPolySymbol`, custom VFS listeners, and old custom IDE test launchers. Also, review `plugin.xml` dependencies if your plugin is split across modules or uses optional descriptors.

As always, if you’ve got any questions, feel free to ask, and we’ll do our best to answer.

---

<div class="post-metadata">

**Author:** ![patrick.scheibe](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/patrick.scheibe/32/2594_2.png) [@patrick.scheibe](https://platform.jetbrains.com/u/patrick.scheibe)\
**Post date:** [September 11, 2026, 3:20pm UTC](https://platform.jetbrains.com/t/summer-2026-intellij-platform-changes-for-plugin-developers/5041/2 "2026-09-11T15:20:21Z")

</div>

Listed on September 11, 2026, 3:20pm UTC


