Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 0 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

### Fixed

- Silent failure when opening Flutter projects without `.idea` directory in IntelliJ IDEA, by removing `FlutterProjectOpenProcessor` and
migrating configuration logic to `FlutterInitializer`. (#8846)
- Gutter buttons not running tests with non-ASCII characters in their names. (#7985)
- Freeze from JX Browser close. (#8864)
- Crash in split debugger mode in IntelliJ 2025.3+. (#8831)
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
107 changes: 107 additions & 0 deletions src/io/flutter/project/FlutterProjectOpenProcessor.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright 2025 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
package io.flutter.project

import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.projectImport.ProjectOpenProcessor
import icons.FlutterIcons
import io.flutter.FlutterBundle
import io.flutter.FlutterUtils
import io.flutter.pub.PubRoot
import io.flutter.utils.FlutterModuleUtils
import java.util.*
import javax.swing.Icon

/**
* Originally `FlutterProjectOpenProcessor.java`.
*
* This processor handles opening Flutter projects when they are selected directly (e.g. via "Open" in the IDE).
* It delegates the actual opening to the platform's default processor (e.g. Gradle or Maven processor if applicable,
* or the generic project opener) and then ensures that any modules in the project are correctly configured as Flutter modules.
*
* Converted to Kotlin to support `openProjectAsync` which is a suspend function.
*/
open class FlutterProjectOpenProcessor : ProjectOpenProcessor() {
override val name: String
get() = FlutterBundle.message("flutter.module.name")

override fun getIcon(file: VirtualFile): Icon? {
return FlutterIcons.Flutter
}

override fun canOpenProject(file: VirtualFile): Boolean {
if (FlutterUtils.isAndroidStudio()) {
return false
}
val root = PubRoot.forDirectory(file)
return root != null && root.declaresFlutter()
}

/**
* Replaces the deprecated `doOpenProject`.
*
* This method is `suspend` and must be used instead of `doOpenProject` to avoid `IllegalStateException` in newer IDE versions.
*
* It performs the following steps:
* 1. Finds a delegate processor (e.g. Gradle) to open the project.
* 2. Opens the project asynchronously.
* 3. Once opened, checks if the project contains Flutter modules that are not yet configured as such (e.g. missing module type).
* 4. Configures these modules as Flutter modules within a write action.
Comment thread
helin24 marked this conversation as resolved.
*/
override suspend fun openProjectAsync(
virtualFile: VirtualFile,
projectToClose: Project?,
forceOpenInNewFrame: Boolean,
): Project? {
// Delegate opening to the platform open processor.
val importProvider = getDelegateImportProvider(virtualFile) ?: return null
val project = importProvider.openProjectAsync(virtualFile, projectToClose, forceOpenInNewFrame)
if (project == null || project.isDisposed) return project

// Convert any modules that use Flutter but don't have IntelliJ Flutter metadata.
convertToFlutterProject(project)

return project
}

/**
* Deprecated method, kept to satisfy the compiler/interface.
*
* We return `null` to indicate that this processor does not support the synchronous opening method
* and that `openProjectAsync` should be used instead.
*/
override fun doOpenProject(
virtualFile: VirtualFile,
projectToClose: Project?,
forceOpenInNewFrame: Boolean,
): Project? {
return null
}

protected open fun getDelegateImportProvider(file: VirtualFile): ProjectOpenProcessor? {
return EXTENSION_POINT_NAME.extensionList.stream().filter { processor: ProjectOpenProcessor ->
processor.canOpenProject(file) && !Objects.equals(
processor.name,
name
)
}.findFirst().orElse(null)
Comment thread
helin24 marked this conversation as resolved.
}
}

/**
* Sets up a project that doesn't have any Flutter modules.
*
*
* (It probably wasn't created with "flutter create" and probably didn't have any IntelliJ configuration before.)
*/
private fun convertToFlutterProject(project: Project) {
for (module in FlutterModuleUtils.getModules(project)) {
if (FlutterModuleUtils.declaresFlutter(module) && !FlutterModuleUtils.isFlutterModule(module)) {
FlutterModuleUtils.setFlutterModuleAndReload(module, project)
}
}
Comment thread
helin24 marked this conversation as resolved.
}
Loading