Skip to content
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
dc2db7f
fix: Non-ASCII test names being escaped when creating run configurati…
chika3742 Mar 23, 2026
66bcb11
Fix reported freeze (#8864)
helin24 Mar 23, 2026
f98a22a
[build] inline dev-build upload in `deploy.sh` (#8868)
pq Mar 25, 2026
dd0088d
Update sunsetted Flutter SDK versions (#8874)
helin24 Mar 31, 2026
76d8e58
Add reflection utility to fix split debugger error (#8878)
helin24 Apr 1, 2026
b0d959e
Add missing changelog entries and update version (#8880)
helin24 Apr 1, 2026
e5c96f8
Revert "Fix IntelliJ IDEA project open hang by removing FlutterProjec…
helin24 Apr 2, 2026
c57eba9
Use PR numbers in changelog, not issue numbers (#8881)
helin24 Apr 2, 2026
2352bc0
Update Dart plugin version (#8886)
helin24 Apr 2, 2026
27965c3
[fix] target device selector updates (#8891)
pq Apr 8, 2026
cb14614
[ai] add `.aiconfig` (#8894)
pq Apr 9, 2026
e965bb8
Fix IDEA project open hang (#8903)
helin24 Apr 16, 2026
a105e50
Fix losing focus in full screen mode (#8906)
helin24 Apr 16, 2026
662daed
feat: Add file chooser support for widget preview initialization. (#8…
nopjar Apr 16, 2026
5e47de6
[ai] add Claude config (#8912)
pq Apr 17, 2026
c471478
[docs] stop specifying a JDK version (#8911)
pq Apr 17, 2026
70da7a0
[infra] add parameterized `runTarget` to allow running against custom…
pq Apr 17, 2026
6d04cb3
[friction] add auto-baseline updating (#8917)
pq Apr 20, 2026
f47490f
[infra] include Android Studio in release printing (#8915)
cj-radcliff Apr 21, 2026
afc33b5
remove stale link (#8920)
pq Apr 23, 2026
5ba28ee
Bump actions/upload-artifact from 6 to 7 (#8841)
dependabot[bot] Apr 24, 2026
44c3709
[maintenance] migrate deps to `libs.versions.toml` (#8923)
pq Apr 24, 2026
a339482
[maintenance] add gradle deps to dependabot tracking (#8924)
pq Apr 24, 2026
50e466b
Bump gradle-wrapper from 9.3.0 to 9.4.1 (#8926)
dependabot[bot] Apr 24, 2026
336680f
Bump org.jetbrains.changelog from 2.2.0 to 2.5.0 (#8930)
dependabot[bot] Apr 24, 2026
335dd2b
Bump org.junit.platform:junit-platform-launcher from 1.11.4 to 6.0.3 …
dependabot[bot] Apr 24, 2026
57a24ca
Bump com.google.guava:guava from 32.0.1-android to 33.6.0-android (#8…
dependabot[bot] Apr 24, 2026
f2bdbff
Bump org.junit.jupiter:junit-jupiter from 5.11.4 to 6.0.3 (#8927)
dependabot[bot] Apr 24, 2026
739933c
[docs] changelog update for 92.0.0 (#8931)
pq Apr 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .aiconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Gemini Code Assist Configuration
version: 1.0
project:
context:
instruction_files:
- .gemini/styleguide.md

generation_rules:
- "Strictly adhere to the IntelliJ Platform Threading Model: No I/O on the EDT."
- "All generated AnAction classes must be stateless."
- "Apply [MUST-FIX], [CONCERN], and [NIT] severity logic to any code suggestions that violate plugin SDK best practices or style guidelines."
- "Use io.flutter.logging.PluginLogger for all logging; avoid System.out."
- "Always include the standard Chromium Authors copyright header in new files."
- "Adhere to the Zero-Formatting Policy: Do not comment on indentation, spacing, or brace placement."
# Ensure local agents read styleguide files automatically.
- "At the start of the session, read and adhere to the guidelines in all files listed in project.context.instruction_files."

languages:
- java
- kotlin
- dart
8 changes: 6 additions & 2 deletions .gemini/styleguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ enforce standard modern Java/Kotlin coding conventions, but strictly police the
- `[NIT]`: Idiomatic improvements or minor naming suggestions.
- **Focus:** Prioritize logic, performance on the UI thread, and architectural consistency.
- **No Empty Praise:** Do not leave "Looks good" or "Nice change" comments. If there are no issues, leave no comments.
- **Copyright Headers:** Ensure all new files have a proper copyright header (e.g., `Copyright 2026 The Chromium Authors`). Flag any missing
headers as `[MUST-FIX]`.

## 2. IntelliJ Platform Best Practices

Expand All @@ -30,8 +32,10 @@ enforce standard modern Java/Kotlin coding conventions, but strictly police the
as recommended by the modern SDK.
- **Backward Compatibility:** Avoid using `@ApiStatus.Internal` or `@ApiStatus.ScheduledForRemoval` APIs unless strictly necessary.
- **Logging:**
- Reject any use of `System.out.println` or `System.err.println` for logging in `src/` code (integration tests may use them for milestone logging).
- Enforce the use of the IntelliJ SDK's built-in logger (`com.intellij.openapi.diagnostic.Logger`) or our own (`io.flutter.logging.PluginLogger`).
- Reject any use of `System.out.println` or `System.err.println` for logging in `src/` code (integration tests may use them for
milestone logging).
- Enforce the use of the IntelliJ SDK's built-in logger (`com.intellij.openapi.diagnostic.Logger`) or our own (
`io.flutter.logging.PluginLogger`).
- **Actions:**
- Classes extending `AnAction` must be completely stateless. Flag any `AnAction` class that defines mutable instance variables (fields),
as the platform instantiates a single instance of the action for the lifetime of the IDE.
Expand Down
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ Mohamed El Sayed <devblooming@tutanota.com>
Edwin Ludik <edwin.ludik@gmail.com>
Japnit Singh <truejswalia@gmail.com>
Dmitry Kandalov <dmitry.kandalov@gmail.com>
Kazuya Chikamatsu <kazu.chika.shima@gmail.com>
15 changes: 12 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@

### Changed

- Updated gradle plugin version to re-enable running `./gradlew verifyPlugin` locally. (#8847)

### Removed

### Fixed

- Silent failure when opening Flutter projects without `.idea` directory in IntelliJ IDEA, by removing `FlutterProjectOpenProcessor` and migrating configuration logic to `FlutterInitializer`. (#8845)
## 91.0.0

### Changed

- Gradle plugin version to re-enable running `./gradlew verifyPlugin` locally. (#8847)

### Fixed

- Gutter buttons not running tests with non-ASCII characters in their names. (#8838)
- Freeze from JX Browser close. (#8864)
- Crash in split debugger mode in IntelliJ 2025.3+. (#8878)
- Passing additional arguments from the Flutter test template. (#8836)

## 90.0.0

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#

ideaVersion=2025.2.3.9
dartPluginVersion= 503.0.0
dartPluginVersion= 504.0.0
# Also update the versions for verify checks in tool/github.sh.
sinceBuild=251
untilBuild=261.*
Expand Down
2 changes: 2 additions & 0 deletions resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@
<!-- See https://github.com/flutter/flutter-intellij/issues/8029 -->
<projectService serviceImplementation="io.flutter.view.InspectorView" overrides="false"/>

<projectOpenProcessor id="flutter" implementation="io.flutter.project.FlutterProjectOpenProcessor" order="first"/>

<editorNotificationProvider implementation="io.flutter.editor.FlutterPubspecNotificationProvider"/>
<editorNotificationProvider implementation="io.flutter.inspections.SdkConfigurationNotificationProvider"/>
<editorNotificationProvider implementation="io.flutter.editor.NativeEditorNotificationProvider"/>
Expand Down
14 changes: 2 additions & 12 deletions src/io/flutter/FlutterInitializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
* Runs actions after the project has started up and the index is up to date.
*
* @see ProjectOpenActivity for actions that run earlier.
* @see io.flutter.project.FlutterProjectOpenProcessor for additional actions that
* may run when a project is being imported.
*/
public class FlutterInitializer extends FlutterProjectActivity {
private boolean toolWindowsInitialized = false;
Expand Down Expand Up @@ -97,18 +99,6 @@ public void executeProjectStartup(@NotNull Project project) {
// Start a DevTools server
DevToolsService.getInstance(project);

// Ensure Flutter project configuration is applied for projects that may have been
// opened without a .idea directory. Previously this was handled by FlutterProjectOpenProcessor,
// but that processor silently failed when no delegate processor could open the project.
// Instead, we let the platform open the project normally and apply our configuration here.
// See https://github.com/flutter/flutter-intellij/issues/8661 (Android Studio equivalent)
for (Module module : FlutterModuleUtils.getModules(project)) {
if (FlutterModuleUtils.declaresFlutter(module) && !FlutterModuleUtils.isFlutterModule(module)) {
log().info("Fixing Flutter module configuration for " + module.getName());
FlutterModuleUtils.setFlutterModuleAndReload(module, project);
}
}

// If the project declares a Flutter dependency, do some extra initialization.
boolean hasFlutterModule = false;

Expand Down
52 changes: 28 additions & 24 deletions src/io/flutter/actions/DeviceSelectorAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
package io.flutter.actions;

import com.intellij.icons.AllIcons;
import com.intellij.ide.ActivityTracker;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnAction;
Expand Down Expand Up @@ -46,6 +45,7 @@
import io.flutter.run.FlutterDevice;
import io.flutter.run.daemon.DeviceService;
import io.flutter.sdk.AndroidEmulatorManager;
import io.flutter.utils.AsyncUtils;
import io.flutter.utils.FlutterModuleUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -381,14 +381,19 @@ public void projectClosing(@NotNull Project project) {
update(project, presentation);
}

updateComponent(project, presentation);
}

private void updateComponent(@NotNull Project project, @NotNull Presentation presentation) {
final DeviceService deviceService = DeviceService.getInstance(project);
final FlutterDevice selectedDevice = deviceService.getSelectedDevice();
final Collection<FlutterDevice> devices = deviceService.getConnectedDevices();

final String text;
Icon icon = DEFAULT_DEVICE_ICON;
Icon icon;

if (devices.isEmpty()) {
icon = DEFAULT_DEVICE_ICON;
final boolean isLoading = deviceService.getStatus() == DeviceService.State.LOADING;
if (isLoading) {
text = FlutterBundle.message("devicelist.loading");
Expand All @@ -398,6 +403,7 @@ public void projectClosing(@NotNull Project project) {
}
}
else if (selectedDevice == null) {
icon = DEFAULT_DEVICE_ICON;
text = FlutterBundle.message("devicelist.noDeviceSelected");
}
else {
Expand All @@ -412,25 +418,27 @@ else if (selectedDevice == null) {
// Update the custom component if it exists
final JButton customComponent = presentation.getClientProperty(CUSTOM_COMPONENT_KEY);
if (customComponent != null) {
final @Nullable JBLabel iconLabel = (JBLabel)customComponent.getClientProperty(ICON_LABEL_KEY);
final @Nullable JBLabel textLabel = (JBLabel)customComponent.getClientProperty(TEXT_LABEL_KEY);
AsyncUtils.invokeLater(() -> {
final @Nullable JBLabel iconLabel = (JBLabel)customComponent.getClientProperty(ICON_LABEL_KEY);
final @Nullable JBLabel textLabel = (JBLabel)customComponent.getClientProperty(TEXT_LABEL_KEY);

if (iconLabel != null) {
iconLabel.setIcon(icon);
}
if (textLabel != null) {
textLabel.setText(text);
// Update the foreground color to adapt to theme changes.
textLabel.setForeground(getToolbarForegroundColor());
customComponent.invalidate();
Container parent = customComponent.getParent();
while (parent != null) {
parent.invalidate();
parent = parent.getParent();
if (iconLabel != null) {
iconLabel.setIcon(icon);
}
customComponent.revalidate();
customComponent.repaint();
}
if (textLabel != null) {
textLabel.setText(text);
// Update the foreground color to adapt to theme changes.
textLabel.setForeground(getToolbarForegroundColor());
customComponent.invalidate();
Container parent = customComponent.getParent();
while (parent != null) {
parent.invalidate();
parent = parent.getParent();
}
customComponent.revalidate();
customComponent.repaint();
}
});
}
}

Expand All @@ -447,6 +455,7 @@ private void update(@NotNull Project project, @NotNull Presentation presentation
}
updateActions(project, presentation);
updateVisibility(project, presentation);
updateComponent(project, presentation);
}

private static void updateVisibility(final Project project, final @NotNull Presentation presentation) {
Expand Down Expand Up @@ -531,11 +540,6 @@ private void updateActions(@NotNull Project project, @NotNull Presentation prese
// Atomically replace the action list
LOG.debug("[" + projectName + "] Replacing device selector actions");
this.actions = newActions;

var tracker = ActivityTracker.getInstance();
if (tracker != null) {
tracker.inc();
}
}

private static class SelectDeviceAction extends AnAction {
Expand Down
33 changes: 17 additions & 16 deletions src/io/flutter/jxbrowser/EmbeddedBrowserEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
*/
package io.flutter.jxbrowser;

import com.intellij.openapi.application.ApplicationListener;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import io.flutter.utils.OpenApiUtils;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.engine.EngineOptions;
import com.teamdev.jxbrowser.engine.PasswordStore;
Expand All @@ -22,7 +23,7 @@
import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;
import static com.teamdev.jxbrowser.engine.RenderingMode.OFF_SCREEN;

public class EmbeddedBrowserEngine {
public class EmbeddedBrowserEngine implements Disposable {
private static final @NotNull Logger LOG = PluginLogger.createLogger(EmbeddedBrowserEngine.class);
private final Engine engine;

Expand Down Expand Up @@ -60,22 +61,22 @@ public EmbeddedBrowserEngine() {
}
engine = temp;

ApplicationManager.getApplication().addApplicationListener(new ApplicationListener() {
@Override
public boolean canExitApplication() {
try {
if (engine != null && !engine.isClosed()) {
engine.close();
}
}

@Override
public void dispose() {
OpenApiUtils.safeExecuteOnPooledThread(() -> {
try {
if (engine != null && !engine.isClosed()) {
engine.close();
}
catch (Exception ex) {
if (FlutterSettings.getInstance().isFilePathLoggingEnabled()) {
LOG.info(ex);
} else {
LOG.info("Exception when closing JX Browser engine: " + ex.getMessage());
}
}
catch (Exception ex) {
if (FlutterSettings.getInstance().isFilePathLoggingEnabled()) {
LOG.info(ex);
} else {
LOG.info("Exception when closing JX Browser engine: " + ex.getMessage());
}
return true;
}
});
}
Expand Down
14 changes: 13 additions & 1 deletion src/io/flutter/jxbrowser/EmbeddedJxBrowser.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import io.flutter.settings.FlutterSettings;
import io.flutter.utils.AsyncUtils;
import io.flutter.utils.JxBrowserUtils;
import io.flutter.utils.OpenApiUtils;
import io.flutter.utils.ZoomLevelSelector;
import io.flutter.view.EmbeddedBrowser;
import io.flutter.view.EmbeddedTab;
Expand Down Expand Up @@ -98,7 +99,18 @@ public void loadUrl(String url) {

@Override
public void close() {
this.browser.close();
OpenApiUtils.safeExecuteOnPooledThread(() -> {
try {
this.browser.close();
}
catch (Exception ex) {
if (FlutterSettings.getInstance().isFilePathLoggingEnabled()) {
LOG.info(ex);
} else {
LOG.info("Exception when closing JX Browser instance: " + ex.getMessage());
}
}
});
}

@Override
Expand Down
Loading
Loading