diff --git a/CHANGELOG.md b/CHANGELOG.md index 70e550cce..8f30b06d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ ### Fixed +- Silent failure when opening Flutter projects without `.idea` directory in IntelliJ IDEA, by removing `FlutterProjectOpenProcessor` and migrating configuration logic to `FlutterInitializer`. (#8845) + ## 90.0.0 ### Added diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 0e49834ac..5c943d83d 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -335,8 +335,6 @@ - - diff --git a/src/io/flutter/FlutterInitializer.java b/src/io/flutter/FlutterInitializer.java index 4c0b928a5..05b15087b 100644 --- a/src/io/flutter/FlutterInitializer.java +++ b/src/io/flutter/FlutterInitializer.java @@ -67,8 +67,6 @@ * 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; @@ -97,6 +95,18 @@ 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; diff --git a/src/io/flutter/project/FlutterProjectOpenProcessor.kt b/src/io/flutter/project/FlutterProjectOpenProcessor.kt deleted file mode 100644 index edadecba9..000000000 --- a/src/io/flutter/project/FlutterProjectOpenProcessor.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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. - */ - 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) - } -} - -/** - * 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) - } - } -} \ No newline at end of file