From 5f99c893b385ee22bdcc1cd29b4ded783db47895 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 23 May 2025 13:02:02 -0400 Subject: [PATCH] Remove handling of the legacy `.flutter-plugins` file in `PluginHandler.kt`. (#169317) As of https://github.com/flutter/flutter/pull/169283 it's impossible for the `.flutter-plugins` file to exist outside of unit tests. --- .../src/main/kotlin/plugins/PluginHandler.kt | 78 ------------ .../test/kotlin/plugins/PluginHandlerTest.kt | 114 ------------------ 2 files changed, 192 deletions(-) diff --git a/packages/flutter_tools/gradle/src/main/kotlin/plugins/PluginHandler.kt b/packages/flutter_tools/gradle/src/main/kotlin/plugins/PluginHandler.kt index 23cbcc5468a..72ac88b0a2d 100644 --- a/packages/flutter_tools/gradle/src/main/kotlin/plugins/PluginHandler.kt +++ b/packages/flutter_tools/gradle/src/main/kotlin/plugins/PluginHandler.kt @@ -14,12 +14,9 @@ import com.flutter.gradle.FlutterPluginUtils.getAndroidExtension import com.flutter.gradle.FlutterPluginUtils.getCompileSdkFromProject import com.flutter.gradle.FlutterPluginUtils.supportsBuildMode import com.flutter.gradle.NativePluginLoaderReflectionBridge -import org.gradle.api.GradleException import org.gradle.api.Project import org.jetbrains.kotlin.gradle.plugin.extraProperties import java.io.File -import java.io.FileNotFoundException -import java.nio.charset.StandardCharsets /** * Handles interactions with the flutter plugins (not Gradle plugins) used by the Flutter project, @@ -75,82 +72,7 @@ class PluginHandler( return pluginDependencies!! } - // TODO(54566, 48918): Can remove once the issues are resolved. - // This means all references to `.flutter-plugins` are then removed and - // apps only depend exclusively on the `plugins` property in `.flutter-plugins-dependencies`. - - /** - * Workaround to load non-native plugins for developers who may still use an - * old `settings.gradle` which includes all the plugins from the - * `.flutter-plugins` file, even if not made for Android. - * The settings.gradle then: - * 1) tries to add the android plugin implementation, which does not - * exist at all, but is also not included successfully - * (which does not throw an error and therefore isn't a problem), or - * 2) includes the plugin successfully as a valid android plugin - * directory exists, even if the surrounding flutter package does not - * support the android platform (see e.g. apple_maps_flutter: 1.0.1). - * So as it's included successfully it expects to be added as API. - * This is only possible by taking all plugins into account, which - * only appear on the `dependencyGraph` and in the `.flutter-plugins` file. - * So in summary the plugins are currently selected from the `dependencyGraph` - * and filtered then with the [pluginSupportsAndroidPlatform] method instead of - * just using the `plugins.android` list. - */ - private fun configureLegacyPluginEachProjects(engineVersionValue: String) { - try { - // Read the contents of the settings.gradle file. - // Remove block/line comments - var settingsText = - FlutterPluginUtils - .getSettingsGradleFileFromProjectDir( - project.projectDir, - project.logger - ).readText(StandardCharsets.UTF_8) - settingsText = - settingsText - .replace(Regex("""(?s)/\*.*?\*/"""), "") - .replace(Regex("""(?m)//.*$"""), "") - if (!settingsText.contains("'.flutter-plugins'")) { - return - } - } catch (ignored: FileNotFoundException) { - throw GradleException( - "settings.gradle/settings.gradle.kts does not exist: " + - FlutterPluginUtils - .getSettingsGradleFileFromProjectDir( - project.projectDir, - project.logger - ).absolutePath - ) - } - // TODO(matanlurey): https://github.com/flutter/flutter/issues/48918. - project.logger.quiet( - legacyFlutterPluginsWarning - ) - val deps: List> = getPluginDependencies() - val pluginsNameSet = HashSet() - getPluginList().mapTo(pluginsNameSet) { plugin -> plugin["name"] as String } - deps.filterNot { plugin -> pluginsNameSet.contains(plugin["name"]) } - deps.forEach { plugin: Map -> - val pluginProject = project.rootProject.findProject(":${plugin["name"]}") - if (pluginProject == null) { - // Plugin was not included in `settings.gradle`, but is listed in `.flutter-plugins`. - project.logger.error( - "Plugin project :${plugin["name"]} listed, but not found. Please fix your settings.gradle/settings.gradle.kts." - ) - } else if (pluginSupportsAndroidPlatform(project)) { - // Plugin has a functioning `android` folder and is included successfully, although it's not supported. - // It must be configured nonetheless, to not throw an "Unresolved reference" exception. - configurePluginProject(project, plugin, engineVersionValue) - } else { - // Plugin has no or an empty `android` folder. No action required. - } - } - } - internal fun configurePlugins(engineVersionValue: String) { - configureLegacyPluginEachProjects(engineVersionValue) val pluginList: List> = getPluginList() pluginList.forEach { plugin: Map -> configurePluginProject( diff --git a/packages/flutter_tools/gradle/src/test/kotlin/plugins/PluginHandlerTest.kt b/packages/flutter_tools/gradle/src/test/kotlin/plugins/PluginHandlerTest.kt index 29d40d1573b..4655045de6c 100644 --- a/packages/flutter_tools/gradle/src/test/kotlin/plugins/PluginHandlerTest.kt +++ b/packages/flutter_tools/gradle/src/test/kotlin/plugins/PluginHandlerTest.kt @@ -326,118 +326,4 @@ class PluginHandlerTest { ) } } - - @Test - fun `configurePlugins works for old flutter-plugins file`( - @TempDir tempDir: Path - ) { - val project = mockk() - - // configuration for configureLegacyPluginEachProjects - val projectDir = tempDir.resolve("my-plugin") - projectDir.toFile().mkdirs() - every { project.projectDir } returns projectDir.toFile() - val settingsGradle = File(projectDir.parent.toFile(), "settings.gradle") - settingsGradle.createNewFile() - settingsGradle.writeText("def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')") - val mockLogger = mockk() - every { project.logger } returns mockLogger - every { mockLogger.quiet(any()) } returns Unit - - val pluginProject = mockk() - val pluginDependencyProject = mockk() - val mockBuildType = mockk() - every { pluginProject.hasProperty("local-engine-repo") } returns false - every { pluginProject.hasProperty("android") } returns true - every { mockBuildType.name } returns "debug" - every { mockBuildType.isDebuggable } returns true - every { project.rootProject.findProject(":${cameraDependency["name"]}") } returns pluginProject - every { project.rootProject.findProject(":${flutterPluginAndroidLifecycleDependency["name"]}") } returns pluginDependencyProject - every { pluginProject.extensions.create(any(), any>()) } returns mockk() - val captureActionSlot = slot>() - val capturePluginActionSlot = mutableListOf>() - every { project.afterEvaluate(any>()) } returns Unit - every { pluginProject.afterEvaluate(any>()) } returns Unit - - val mockProjectBuildTypes = - mockk>() - val mockPluginProjectBuildTypes = - mockk>() - every { project.extensions.findByType(BaseExtension::class.java)!!.buildTypes } returns mockProjectBuildTypes - every { pluginProject.extensions.findByType(BaseExtension::class.java)!!.buildTypes } returns mockPluginProjectBuildTypes - every { mockPluginProjectBuildTypes.addAll(any()) } returns true - every { pluginProject.configurations.named(any()) } returns mockk() - every { pluginProject.dependencies.add(any(), any()) } returns mockk() - - every { - project.extensions - .findByType(BaseExtension::class.java)!! - .buildTypes - .iterator() - } returns - mutableListOf( - mockBuildType - ).iterator() andThen - mutableListOf( // can't return the same iterator as it is stateful - mockBuildType - ).iterator() andThen - mutableListOf( // and again - mockBuildType - ).iterator() - every { project.dependencies.add(any(), any()) } returns mockk() - every { project.extensions.findByType(BaseExtension::class.java)!!.compileSdkVersion } returns "android-35" - every { pluginProject.extensions.findByType(BaseExtension::class.java)!!.compileSdkVersion } returns "android-35" - - val pluginHandler = PluginHandler(project) - mockkObject(NativePluginLoaderReflectionBridge) - // mock return of NativePluginLoaderReflectionBridge.getPlugins - val pluginWithDependencies: MutableMap = cameraDependency.toMutableMap() - pluginWithDependencies["dependencies"] = - listOf(flutterPluginAndroidLifecycleDependency["name"]) - every { NativePluginLoaderReflectionBridge.getPlugins(any(), any()) } returns - listOf( - pluginWithDependencies - ) - // mock method calls that are invoked by the args to NativePluginLoaderReflectionBridge.getPlugins - every { project.extraProperties } returns mockk() - every { project.extensions.findByType(FlutterExtension::class.java) } returns FlutterExtension() - every { project.file(any()) } returns mockk() - - val dependencyGraph = - listOf>( - mapOf( - "name" to cameraDependency["name"], - "dependencies" to listOf(flutterPluginAndroidLifecycleDependency["name"]) - ), - mapOf( - "name" to flutterPluginAndroidLifecycleDependency["name"], - "dependencies" to listOf() - ) - ) - - every { NativePluginLoaderReflectionBridge.getDependenciesMetadata(any(), any()) } returns - mapOf("dependencyGraph" to dependencyGraph) - - pluginHandler.configurePlugins( - engineVersionValue = EXAMPLE_ENGINE_VERSION - ) - - verify { project.afterEvaluate(capture(captureActionSlot)) } - verify { pluginProject.afterEvaluate(capture(capturePluginActionSlot)) } - captureActionSlot.captured.execute(project) - capturePluginActionSlot[0].execute(pluginProject) - capturePluginActionSlot[1].execute(pluginProject) - verify { pluginProject.extensions.create("flutter", FlutterExtension::class.java) } - verify { - pluginProject.dependencies.add( - "debugApi", - "io.flutter:flutter_embedding_debug:$EXAMPLE_ENGINE_VERSION" - ) - } - verify { project.dependencies.add("debugApi", pluginProject) } - verify { mockPluginProjectBuildTypes.addAll(project.extensions.findByType(BaseExtension::class.java)!!.buildTypes) } - - verify { pluginProject.dependencies.add("implementation", pluginDependencyProject) } - verify { mockLogger.quiet(PluginHandler.legacyFlutterPluginsWarning) } - } }