Skip to content

Release/2026.2.3 - #356

Open
DetachHead wants to merge 1852 commits into
masterfrom
release/2026.2.3
Open

DetachHead wants to merge 1852 commits into
masterfrom
release/2026.2.3

Conversation

@DetachHead

Copy link
Copy Markdown
Owner

No description provided.

piotrtomiak and others added 30 commits August 19, 2026 18:48
…orrectly logged `onClose` errors.

(cherry picked from commit e9834da7cfc840091ae9c663748f3731536225e9)

IJ-CR-210268

GitOrigin-RevId: d01f70590e2d7d572ac541e739a867686b6e2eae
…ent sync manager is disposed

(cherry picked from commit a67ef53f818901a254931ad729826730a2780c28)

IJ-CR-210268

GitOrigin-RevId: 40a151e4ce0b1c89d3677d81559c0616cce72bd2
(cherry picked from commit 93675422432e0d8c634c2bee1290289bbb4860ab)

IJ-CR-210268

GitOrigin-RevId: 7f182e7a1d57f3ff198e958b788e268f7c6f6c61
(cherry picked from commit e9e964c16ee2240aa45eed11671b626970de4c13)

IJ-CR-210268

GitOrigin-RevId: 632b359925c3ad4147e788373e69a03f22418e08
…" page

Port of master 51263729e4983. 262 only received the first iteration of
this fix (the retargeted PythonPackageRepositoriesDialogUi locator); the
test-side half was never cherry-picked, so packagesTable still matched
the two PyPackagesTree nodes reported in the ticket, and
CustomRepositoryTest still clicked the removed gear button and waited for
the removed "Manage Repositories" popup item.

- add PackageRepositoriesSettingsUi with packageRepositoriesSettingsPage,
  which navigates the Settings tree to Python | Package Repositories
- drop PythonPackageRepositoriesDialogUi, obsolete since PY-89838 moved
  repository management out of the standalone dialog
- PythonPackagesToolWindowUiComponent: scope packagesTable to the
  JBScrollPane wrapper so it resolves to one component again, and replace
  settingsButton with optionsButton (the toolbar group is now
  AllIcons.Actions.More / "Options")
- CustomRepositoryTest: open the page via Options -> "Repositories...",
  fix the copy-pasted @DisplayName, restore the Allure labels the rest of
  the packaging package already carries

Adapted to the 262 Finder API: the x() readableName overloads only exist
on master, so the component locators here carry no readable names.

GitOrigin-RevId: 43e51c472684cb4586ca241345253392cd493e9b
(cherry picked from commit 4a7a99f3f5be36b189615d05b03d1f750f2b2416)

IJ-CR-219380

GitOrigin-RevId: 00c98e6bf002aa05de973bad96d423da3cca26af
…thod for the sake of compatibility

GitOrigin-RevId: cd529b509056f80c047d910901a591343dc748cd
(cherry picked from commit c13e3c73397748f1449a3e7a0774f7d2c470ab5b)
IJ-CR-218650

GitOrigin-RevId: e1fda984eebc3e73f9e09187fd59316b47e356d5
(cherry picked from commit c2bd874045ade0d4e02a233179e79db1efc6dff1,, IJ-CR-219371)

GitOrigin-RevId: b9b8dcc8eb4cf173c2a558129451d67a6b630f2d
…rumented breakpoints

The fix itself in the agent code

(cherry picked from commit 3d451f0244b29c4a3a7fac3c703221820c079f3f)

IJ-CR-219236

GitOrigin-RevId: 122cea274e535856bd77cb8b15dd5a5cd71a875b
…27 [fus]: auto-update bundled metadata

https://buildserver.labs.intellij.net/build/1037065823

GitOrigin-RevId: c0be012ade044c3e5697e5cf49e8878ab7e89c31
…state with master branch to offer devs who do not use nightly builds the same tooling that the safe push checks use

GitOrigin-RevId: be32cc21e0147ac93fefaef9dfd802483f3d98aa
GitOrigin-RevId: 72bd489a316df817fe00d64ceffd8f2d50be7070
…ject by default, fallback to bundled if not available

If the project version is rather old, that might be inconsistent with CI, but it is better than relying on only bundled versions since project update is expected to happen more frequently than ide update

(cherry picked from commit d407b312cf9adf52a0486eb640cd819573f95cbf)

GitOrigin-RevId: 63697d8321dc446c84e27c64451e82b664066dd9
to get more data

IJ-MR-219409

GitOrigin-RevId: d3d35f0feceea970f0a3dd7dbf4852e61bc48940
…rsion check

(cherry picked from commit 4d0688ef53c081e4d16874672226b73a830bcf89)


Merge-request: IJ-MR-219549
Merged-by: Kirill Bochkarev <kirill.bochkarev@jetbrains.com>

GitOrigin-RevId: b8f6799cc03ed31ef5d30972fc017e57d04b2556
…tial

IJ-CR-219419

(cherry picked from commit e54ad5c16228692a5df7ee95cdab4ba5b48c84d1)

GitOrigin-RevId: 6316f2e84611a854659b7ae58358a98c716524d1
(cherry picked from commit 53d1fc67fb6a1cbe45f4737ca8ebfed70e6f1f9c)

GitOrigin-RevId: 9de2befa307f4a313cac85dc3fab34e89e933b93
…ta EE 10 and 11 specifications

(cherry picked from commit 21ee8ae4beeb840ee11bed94305bac55a9fc7a6b)

IJ-CR-219600

GitOrigin-RevId: a9a76a5eab6e1d361e85811c0937c915b20358ea
…ated file templates

(cherry picked from commit 4d270a6723df469b7b960ec95fd8f3f9b9efdd22)

IJ-CR-219600

GitOrigin-RevId: 0d9fcde60519bfd027fa0cf2c9154e94d34b9895
…ke tests

(cherry picked from commit 16418d707ce4bbcceea7040eab2e48946978acd4)

IJ-MR-218184

GitOrigin-RevId: af16cc85eafc412a20c70f4b8b79fb43ad76461b
A dict literal was promoted to a matching `TypedDict` type only when the
expected type was directly a `TypedDict`, so with a union like
`Address | None` the literal kept its `dict[...]` type and failed
the assignability check.

Promote the dict literal against any `TypedDict` member of the expected
type (union included), returning the first member it structurally
matches.

(cherry picked from commit 4088672b2d63fb709ebfb96507429b6c14f54c17)

GitOrigin-RevId: 0ed8321e9393e188437026ee0bd95ebfa44f4f1a
On targets the tool path cannot be persisted, so the field is
disabled and has no browse button. When the tool is not installed there, the
dialog still showed an empty disabled field under a warning row that already
said everything actionable.

With canBeEdited off, exactly one row is now on screen: a spinner while the
lookup runs, the "no executable found" warning once it comes back empty, and the
path field only once a path was resolved. The field stays when a path was found
but its version probe failed, so the inline error keeps a visible component to
attach to. The warning now also waits for the first verdict instead of claiming
the tool is missing before anything has been looked up.

The field validator can no longer bail out on !component.isVisible alone: that
guard also covers the unselected environment managers, which are all built up
front and hidden, so it now asks whether any row of this section is on screen.
Otherwise hiding the field dropped the sticky "executable is not detected" info
from DialogPanelValidator and re-enabled the wizard's action button on a target
where setup was guaranteed to fail.

Also disable the field from construction rather than from the first validation
round, so a read-only field is never briefly editable.


(cherry picked from commit ea3decb37c54e6dce2f80de43210cf2b68e7609e)

IJ-MR-219733

GitOrigin-RevId: b8ec832ec2c9ea6bc847d64cf6653b6ac8a25cf2
…0.4.1b508.30

GitOrigin-RevId: bf096a15e5d9e1aae58e7404eba5a3df1071145a
…numeric tags in YAMLIncompatibleTypes

YamlNumberType now recognizes non-decimal YAML integer literals (hex, octal,
binary, sexagesimal and comma-grouped) and treats any value carrying an
explicit numeric tag (!!int/!!float/...) as a number regardless of its lexical
form, mirroring how !!str forces the string type.

Co-authored-by: Junie <junie@jetbrains.com>
M-Session-Id: M-12e88fdd-8c8c-4d84-ae67-c7c3120fa548


(cherry picked from commit e7ed3bc5dee7bbc559cab1becd71183317b33da5)

IJ-CR-215442

GitOrigin-RevId: b81c588ca12cf5bd38ea6b939916987a5f05fc41
…icationStarter in Headless Mode

GitOrigin-RevId: 0df7e51edee0555c91db93b722c338df88f46be9
…icationStarter in Headless Mode

Update shouldReportStatistics to use !isHeadless
Update KDoc

GitOrigin-RevId: 1099d3dd36c74b5b34ac40a1b6cdcc7a46846d94
…ng a recent project

 scheduleStructureUpdate() was moved from activated() (where the tool window doesn't exist yet and the call is always a no-op) to the end
  of initializeToolWindow(), where the tool window is guaranteed to be registered. The stateChanged listener that previously served as a
  fragile rescue path for this was removed as it's no longer needed.


(cherry picked from commit d74a1a7efd5e75d7a508975ab0c750c01286a002)

IJ-CR-219652

GitOrigin-RevId: 858f97c48b6b613cee63ed5a852f1f623a93bfc9
mikhail-pyltsin and others added 26 commits September 11, 2026 14:47
… with JSpecify method references

- don't resolve method references

(cherry picked from commit 4ce3a12e166d4fd7ba4824410561e961e9a5cbb3)


(cherry picked from commit 54d72d94c00589c6ca35919cc5c4d8a345052bb2)

IJ-MR-222890

GitOrigin-RevId: 00e7980dc75d7c386be00770bd97e907832b184d
…ly with real evidence

A type stub omits a `__str__` and a `__repr__` that only override the `object` ones. The flake8-pyi
rule Y029 removes them. `builtins.pyi` declares them on `object` and on `BaseException` only, and
`ipaddress.pyi` declares neither on `_BaseAddress`.

The inspection read the absence as proof, and reported the type. A generated skeleton hid the defect
on a local interpreter. WSL generates no skeleton, so the inspection reported every type there.

The lookup now gives three answers: DEFINED, NOT_DEFINED and UNKNOWN. It asks the runtime class of
every class of the MRO, one class at a time, so a `__str__` that an ancestor defines also counts. It
also searches the ancestors of each runtime class, because a stub often flattens a private base. It
answers UNKNOWN when a stub has no runtime class, and an UNKNOWN answer never reports.

`PyStringDunderUtil.TYPES_WITHOUT_USEFUL_STRING_CONVERSION` holds `zip`, `map`, `filter`, `enumerate`,
`reversed` and the generator types. The inspection reports them without a skeleton. A hit stops the
stubs after it from adding UNKNOWN, but the walk goes on, because a later base of a subclass can still
define `__str__`. The set replaces `TYPES_WITH_BUILTIN_STR`.

The mock SDK has no runtime module and no skeleton, so a unit test cannot cover the runtime lookup.
`PyStringConversionWithoutDunderMethodEnvTest` covers it with a real interpreter.

Also fixes PY-91292 and PY-89218.


(cherry picked from commit 944221d93ad86882af8b2c4070c2f4183f508083)

IJ-MR-222607

GitOrigin-RevId: 270848329319b6f87d0b9271a0e9e00a1c278f97
…`__new__` call

`str(x)` resolves to `builtins.str.__new__`. An explicit `str.__new__(cls)` and a `super().__new__(cls)`
in a `str` subclass resolve to the same declaration, and the inspection reported the type of `cls`.
A conversion never names `__new__`, so the callee name now selects it out.


(cherry picked from commit ca96135ee3a0a94aa0660a44715af07c3fa5b62c)

IJ-MR-222607

GitOrigin-RevId: 9a360a384680c95312ee06290d6522e7bf5af416
…252505

GitOrigin-RevId: bbdc4b3c172b4bbec0791b737ecb2f04839ed254
…e no changes IJPL-252505

Also related to IJPL-251324

GitOrigin-RevId: 644742e4923112a268f3af87f7eef3070f8d1b4d
…iser has none

The advertiser matches a plugin to an UnknownFeature by string equality on the
implementation name. A dependencySupport bean cannot express an offer that depends
on which version of a dependency the project declares. A plugin with a version-aware
offer therefore raises its own balloon on project open, and that balloon and the
advertiser's own can sit on the screen together.

PluginSuggestionNotificationProvider is a new extension point, next to
pluginSuggestionProvider, which does the same job for the editor banner. A provider
returns a ready Notification, or null. The advertiser decides whether to ask. The
provider decides what the balloon says, which notification group it belongs to, and
which actions it carries.

notifyUser now returns whether the advertiser has an offer of its own for the project.
It returns true on the suggest-or-enable branch, on the bundled Try Ultimate branch, and
on the includeIgnored branch that says no plugin was suggested. It returns false where
it built no offer, and run() asks the providers on that false. The return says the
advertiser reached notify, and notify raises no balloon while an earlier balloon of the
group is visible, and none at all for a group the user set to no popup.

The call site sits inside PluginAdvertiserServiceImpl.run, so a path where the
advertiser never reaches notifyUser asks nobody: the registry key
ide.show.plugin.suggestions.on.open switched off, an untrusted project, and headless.
HeadlessPluginAdvertiserServiceImpl.run stays an empty override, so the headless
service and the test service ask nobody either. RiderPluginAdvertiserService overrides
getAddressedMessagePresentation and inherits the new path.

The first answer wins. The advertiser asks to fill the one balloon it did not raise, so
a second balloon here recreates the stacking this extension point prevents.

A provider is called on a background thread. It may suspend and it may take a read
action, because it answers from project content. The advertiser publishes the
notification on the EDT, where a provider takes its own notification down, and it
publishes nothing the provider has already expired. A provider that fails is logged
under its own class and skipped, in the way ExtensionProcessingHelper.computeSafeIfAny
handles a provider that does not suspend. That helper takes a non-suspend function, so
the handling is written out here.

With no provider registered the extension list is empty, the advertiser publishes
nothing extra, and the IDE behaves as it did before.

Verified: bazel build of intellij.platform.ide.impl; 8 tests in
PluginSuggestionNotificationProviderTest and 23 over com.intellij.ide.plugins.advertiser,
all passing; lint_files clean over the new files. Six mutation rows, each turning one
case red: the call site in run() deleted, notifyUser returning true where it built no
offer, the expired-notification guard removed, the first-answer rule replaced by every
answer, the EDT hop removed, and a provider exception let out of the extension list.

Claude-Session: https://claude.ai/code/session_01XabGLGJyJQCmYSPE6kX9Dd
(cherry picked from commit acc9aab3a62f91fc78e81c353838b6a99dcf7ac4)

GitOrigin-RevId: b03f28925ec2772b4540ad38af20363d84f2e1e4
… to Figma

A Markdown file whose text contains a figma.com file, design or proto URL
draws the platform's editor banner with an offer to install Figma Connect.
The offer is shown once per project and it is answered once per project.

The new content module `intellij.markdown.figmaAdvertiser` registers
`com.intellij.pluginSuggestionProvider`. It depends on no `intellij.figma.*`
module, because that plugin loads only when it is installed, which is the one
case this offer does not exist for. The Figma URL rule and the tool window id
are therefore written again here, each with the reason in its KDoc. The URL
rule is deliberately the broader of the two copies: `FigmaUrlDetector` asks
which node to open and so needs a file key, while this asks whether the
author works with Figma, which a keyless link still answers.

The order of the questions follows the cost of answering them: the registry
switch, the file extension, the per-project dismissal, then
`buildSuggestionIfNeeded`, which drops a plugin id that is already loaded.
The file's own text is read last, and the answer is kept on the
`VirtualFile`, so a repaint reads it instead of the text.

The offer's word follows whether the plugin is on disk, not whether it is
switched off. The banner is drawn whenever the plugin is not loaded, and on
disk, switched on and not loaded is an ordinary state: `PluginEnabler.HEADLESS`
writes the flag and loads nothing, and every accepted plugin-advertiser offer
runs it. Such a user would otherwise be offered an install and sent to
Marketplace for a plugin they already have. The click asks the enabler in both
on-disk states, because `DynamicPluginEnabler.enable` loads a descriptor that
is switched on and not loaded rather than needing a restart.

The restart offer is the platform's own, and nothing is added here.
`installAndEnable` runs its success body through
`InstallAndEnableTask.runOnSuccess`, which is given the result of
`PluginInstaller.installAndLoadDynamicPlugin` — false when the plugin needs a
restart. On that branch `PluginsAdvertiserDialogPluginInstaller` has already
run `PluginManagerMain.notifyPluginsUpdated`, whose notification carries the
"Restart to activate plugin updates" action. The Figma tool window, which is
the setup wizard's entry point for a first-time user, is opened through a
safe call that does nothing when the plugin did not load.

`markdown.figma.advertiser` is a FUS group of its own, with a `trigger` field.
`figma.connect` is declared in a module that is absent exactly when this code
runs, and the platform's `plugins.advertiser` group has no field saying which
trigger fired.

Tests: `intellij.markdown.tests`, 20 tests over
`MarkdownFigmaAdvertiserDecisionTest` and `MarkdownFigmaAdvertiserBannerTest`.
Eleven mutation rows, 17 kills, every prediction matched. A UI test is added
to `intellij.figma.uiTests` and is not run; the phase batches one TeamCity
pass.

Claude-Session: https://claude.ai/code/session_01KRDwfXtkThVhoM8EKVGeMC

(cherry picked from commit 2f618d22f0c64a0ad6fb54da8008bf2bd1c34483)

GitOrigin-RevId: 9d6d437048859fb33e986126cb7c1c6bd7c60c46
The banner over a Markdown file was answered only when the file was opened.
EditorNotificationsImpl recomputes on a file being opened, on dumb mode, on a root change and
on a plugin loading or unloading (EditorNotificationsImpl.kt:97-132). Editing a file is none
of those, so a link added to an open README waited for the file to be opened again.

FigmaLinkDocumentListener is registered on com.intellij.editorFactoryDocumentListener and
asks EditorNotifications to recompute that one file.

Every document in the IDE reaches it, so the questions are ordered by cost: the registry
switch, then the file's extension, then a search. The search reads a window around the change
and not the file, and it keeps a match only when the match meets the change. A link the change
created always does: a match that is there after a change and was not there before it holds a
character the change wrote, and a match a pure deletion produced spans the position the
deletion left behind. The pattern matches at most 29 characters, so such a match lies within
FIGMA_URL_MAX_MATCH of the change.

The overlap is what makes the ask one per link. Asking for every change with a link merely
near it charges one recompute per keystroke for the life of a file that holds a link, and the
platform's own coalescing sits after an EDT dispatch, so it would coalesce the recompute and
not the dispatch.

ProjectLocator.getProjectsForFile answers which projects to ask. It keeps a project whose file
index reports the file as in content or as excluded, so a file under no project root keeps the
old behaviour and is answered when it is opened.

The suppression of SplitModeApiUsage is written down at the class: the module is shared, and
the listener reads a document and asks for one file's notifications.

MarkdownFigmaAdvertiserBannerTest gains six cases. The URL is typed one character at a time,
and the recorded list is asserted whole, so forty-eight keystrokes have to produce exactly one
ask. The module reports 26 tests, 26 passed.

Claude-Session: https://claude.ai/code/session_01ELVY5UTnoFX4drhGBHRVXK
(cherry picked from commit 7cce24e103a18a6891a0b0fe70e2179d99945154)

GitOrigin-RevId: 66ca03042d6642d5e9520592753e1da4126e64c6
ide.show.plugin.suggestions.on.open is the switch a user sets to say "do not offer me
plugins". The Markdown banner ignored it, so a user who set it to false and restarted still
met the offer over a README.

The platform reads the key before the project-open balloon
(PluginsAdvertiserStartupActivity.kt:50) and not before an editor banner, so every other
pluginSuggestionProvider ignores it. The divergence is deliberate, and the reason is an
asymmetry of costs. Honouring the switch too widely costs a user one suggestion they might
have wanted. Ignoring it shows a plugin offer to a user who asked to be shown none, and that
is what QA filed. The second mistake is the worse one, so the doubt is spent on the side of
the user's answer.

FigmaAdvertiserRegistry.isSuggestionAllowed is where both switches are read, so the provider
and FigmaLinkDocumentListener cannot answer differently. It reads the platform's key with the
one-argument Registry.is, which throws for a key that is not registered, and that is deliberate:
the two-argument form would make this module own a default for a key it does not own, and would
answer with that default before LoadingState.COMPONENTS_LOADED rather than with what the user
set. The key is declared at registry.properties:2239 and both callers need a running editor, so
the throw is unreachable.

The key's own description in registry.properties:2240 reads "Whether to show Suggested plugins
notifications on project open", which is the argument against this change. Reverting it is one
predicate and two call sites.

The place this really belongs is PluginAdvertiserEditorNotificationProvider, where one read
would answer for every provider and nobody would diverge. That is a Platform change and out of
scope for a bug fix.

MarkdownFigmaAdvertiserBannerTest gains two cases, one per caller. The module reports 28 tests,
28 passed.

Claude-Session: https://claude.ai/code/session_01ELVY5UTnoFX4drhGBHRVXK
(cherry picked from commit c71e6e9875f7490cf9c54f2a7ad0dace43bb574e)

GitOrigin-RevId: fe898cf81a38b0e9857bbb746d75923baf650b29
(cherry picked from commit 4b868d7474119afb81000d92cd8ac447a4613e29)

GitOrigin-RevId: a92de8059dea190b9cd5a8e2a09d9374e9b40da8
(cherry picked from commit f249ccd84ca7db65280ce31644e9e1db8ef6b0ac)

GitOrigin-RevId: d92f22ebce03183c62ee7088c1d779bc811cb8a4
- Extract tooling libraries into modules
- Extract plugin descriptor module instead of using core module as both the content and descriptor

(cherry picked from commit 2edb04e444b424febb1099decdb44daf8848d909)
IJ-MR-222180
(cherry picked from commit 44f2dfa84bde686959e0704e777f640886349d41)

GitOrigin-RevId: 1dfe5ce6ce2e9aedb93c1a7cc6affb232468624c
* remove terminology referring to rebased as an "IDE".

this is something that's bothered me for a while. calling rebased an IDE is misleading because it deliberately does not include many of the features required for a tool to be considered an IDE

* disable "Invalidate Build System IDE caches and Re-sync" action which is not relevant for Rebased

---------

Co-authored-by: detachhead <detachhead@users.noreply.github.com>
(cherry picked from commit e5efeec)
)

* Revert "fix restarting when using the appimage (#241)"

This reverts commit 541afff.

* fix restarting rebased from the appimage using `IDEA_RESTART_VIA_EXIT_CODE` instead.

i think this is a better fix even though it requires me to write bash code instead of kotlin code because not only does it reduce the amount of changes required to the platform but i think it's also slightly faster because it doesn't need to re-mount the appimage's filesystem on launch

---------

Co-authored-by: detachhead <detachhead@users.noreply.github.com>
(cherry picked from commit a2a8868)
i know there are plenty of other ones i missed too, but to minimize upstream conflicts i'm only touching the ones i personally notice since there's a good chance a lot of them aren't actually reachable in rebased

Co-authored-by: detachhead <detachhead@users.noreply.github.com>
(cherry picked from commit d5f15c9)
# Conflicts:
#	.github/actions/setup-kotlin/action.yml
#	.github/workflows/jewel-checks.yml
#	BUILD.bazel
#	intellij.idea.community.main.tests.iml
#	plugins/compose/intellij.compose.ide.plugin.resources/BUILD.bazel
#	plugins/compose/intellij.compose.ide.plugin.resources/intellij.compose.ide.plugin.resources.tests.iml
#	plugins/kotlin/compiler-reference-index/tests.k2/BUILD.bazel
@DetachHead DetachHead added the release branch this PR is for publishing releases based on an upstream release branch - not to be merged label Sep 16, 2026
@DetachHead DetachHead closed this Sep 16, 2026
@DetachHead DetachHead reopened this Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release branch this PR is for publishing releases based on an upstream release branch - not to be merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.